diff --git a/.gitignore b/.gitignore
index 6eef95a..265b8b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ build/
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
+.idea
*.iws
*.iml
*.ipr
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 14746e7..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 72be7ed..e87b105 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -12,6 +12,7 @@ repositories {
dependencies {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
+ testImplementation("org.jfree:jfreechart:1.5.3")
}
tasks.test {
diff --git a/src/main/java/ru/urfu/Main.java b/src/main/java/ru/urfu/Main.java
index 5845f6d..b5a9126 100644
--- a/src/main/java/ru/urfu/Main.java
+++ b/src/main/java/ru/urfu/Main.java
@@ -1,17 +1,18 @@
-package ru.urfu;
+package main.java.ru.urfu;
+
+// import main.java.ru.urfu.console.Communicator;
+
+import main.java.ru.urfu.presentation.controller.Controller;
+import main.java.ru.urfu.presentation.view.ConsoleView;
+import main.java.ru.urfu.resolver.Resolver;
-//TIP To Run code, press or
-// click the icon in the gutter.
public class Main {
public static void main(String[] args) {
- //TIP Press with your caret at the highlighted text
- // to see how GIGA IDE suggests fixing it.
- System.out.printf("Hello and welcome!");
+ // Communicator.runChampionship();
+ var console = new ConsoleView();
+ var resolver = new Resolver();
- for (int i = 1; i <= 5; i++) {
- //TIP Press to start debugging your code. We have set one breakpoint
- // for you, but you can always add more by pressing .
- System.out.println("i = " + i);
- }
+ var controller = new Controller(console, resolver);
+ controller.start();
}
}
\ No newline at end of file
diff --git a/src/main/java/ru/urfu/console/Communicator.java b/src/main/java/ru/urfu/console/Communicator.java
new file mode 100644
index 0000000..1674a44
--- /dev/null
+++ b/src/main/java/ru/urfu/console/Communicator.java
@@ -0,0 +1,14 @@
+package main.java.ru.urfu.console;
+
+
+import main.java.ru.urfu.parser.CsvParser;
+import main.java.ru.urfu.resolver.Resolver;
+import main.java.ru.urfu.mapper.Mapper;
+import main.java.ru.urfu.drawer.Drawer;
+
+import java.util.Scanner;
+
+public class Communicator {
+ public static void runChampionship() {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/urfu/drawer/Drawer.java b/src/main/java/ru/urfu/drawer/Drawer.java
new file mode 100644
index 0000000..d83de4b
--- /dev/null
+++ b/src/main/java/ru/urfu/drawer/Drawer.java
@@ -0,0 +1,43 @@
+package main.java.ru.urfu.drawer;
+
+import main.java.ru.urfu.model.Position;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartFrame;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
+import org.jfree.chart.plot.PiePlot;
+import org.jfree.chart.plot.Plot;
+import org.jfree.data.general.DefaultPieDataset;
+
+import java.awt.*;
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.util.Map;
+import java.util.Scanner;
+
+public class Drawer {
+ public void drawDiagramPlayersByPosition(Map positionsCount) {
+ DefaultPieDataset dataset = new DefaultPieDataset<>();
+
+ positionsCount.forEach((pos, count) ->
+ dataset.setValue(pos.getTitleRu(), count)
+ );
+
+ JFreeChart chart = ChartFactory.createPieChart("Распределение по позициям", dataset, true, true, false);
+
+ PiePlot plot = (PiePlot) chart.getPlot();
+ plot.setLabelGenerator(new StandardPieSectionLabelGenerator(
+ "{0}: {1} ({2})",
+ new DecimalFormat("0"),
+ new DecimalFormat("0.00%")
+ ));
+
+ plot.setSimpleLabels(true);
+ plot.setLabelBackgroundPaint(Color.WHITE);
+
+ ChartFrame frame = new ChartFrame("Распределение по позициям", chart);
+ frame.pack();
+ frame.setAlwaysOnTop(true);
+ frame.setVisible(true);
+ }
+}
diff --git a/src/main/java/ru/urfu/mapper/Mapper.java b/src/main/java/ru/urfu/mapper/Mapper.java
new file mode 100644
index 0000000..d50a29e
--- /dev/null
+++ b/src/main/java/ru/urfu/mapper/Mapper.java
@@ -0,0 +1,23 @@
+package main.java.ru.urfu.mapper;
+
+import main.java.ru.urfu.model.Player;
+import main.java.ru.urfu.model.Position;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class Mapper {
+
+ private List players = new ArrayList<>();
+
+ public void setPlayers(List players) {
+ this.players = players;
+ }
+
+ public Map getPlayersByPosition() {
+ return players.stream()
+ .collect(Collectors.groupingBy(Player::position, Collectors.counting()));
+ }
+}
diff --git a/src/main/java/ru/urfu/model/Player.java b/src/main/java/ru/urfu/model/Player.java
new file mode 100644
index 0000000..efd9d45
--- /dev/null
+++ b/src/main/java/ru/urfu/model/Player.java
@@ -0,0 +1,16 @@
+package main.java.ru.urfu.model;
+
+public record Player(
+ String name,
+ String team,
+ String city,
+ Position position,
+ String nationality,
+ String agency,
+ int transferCost,
+ int goals,
+ int assists,
+ int yellowCards,
+ int redCards
+) {
+}
\ No newline at end of file
diff --git a/src/main/java/ru/urfu/model/Position.java b/src/main/java/ru/urfu/model/Position.java
new file mode 100644
index 0000000..682483d
--- /dev/null
+++ b/src/main/java/ru/urfu/model/Position.java
@@ -0,0 +1,19 @@
+package main.java.ru.urfu.model;
+
+public enum Position {
+ GOALKEEPER("Вратарь"),
+ DEFENDER("Защитник"),
+ MIDFIELD("Полузащитик"),
+ FORWARD("Нападающий");
+
+ private final String titleRu;
+
+ Position(String title){
+ this.titleRu = title;
+ }
+
+ public String getTitleRu(){
+ return this.titleRu;
+ }
+
+}
diff --git a/src/main/java/ru/urfu/parser/CsvParser.java b/src/main/java/ru/urfu/parser/CsvParser.java
new file mode 100644
index 0000000..658a801
--- /dev/null
+++ b/src/main/java/ru/urfu/parser/CsvParser.java
@@ -0,0 +1,47 @@
+package main.java.ru.urfu.parser;
+
+import main.java.ru.urfu.model.Position;
+import main.java.ru.urfu.model.Player;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+public class CsvParser {
+ public static ArrayList parserCsvToList(String pathString) {
+ var path = Paths.get(pathString);
+ var scan = getScanner(path);
+ var playersList = new ArrayList();
+
+ scan.nextLine();
+ while (scan.hasNextLine()) {
+ playersList.add(parseRowToPlayer(scan.nextLine()));
+ }
+ return playersList;
+ }
+
+ private static Scanner getScanner(Path path) {
+ try {
+ return new Scanner(path);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Player parseRowToPlayer(String row) {
+ var cells = row.split(";");
+ return new Player(cells[0],
+ cells[1],
+ cells[2],
+ Position.valueOf(cells[3]),
+ cells[4],
+ cells[5],
+ Integer.parseInt(cells[6]),
+ Integer.parseInt(cells[7]),
+ Integer.parseInt(cells[8]),
+ Integer.parseInt(cells[9]),
+ Integer.parseInt(cells[10]));
+ }
+}
diff --git a/src/main/java/ru/urfu/presentation/controller/Controller.java b/src/main/java/ru/urfu/presentation/controller/Controller.java
new file mode 100644
index 0000000..4d01dea
--- /dev/null
+++ b/src/main/java/ru/urfu/presentation/controller/Controller.java
@@ -0,0 +1,83 @@
+package main.java.ru.urfu.presentation.controller;
+
+import main.java.ru.urfu.drawer.Drawer;
+import main.java.ru.urfu.mapper.Mapper;
+import main.java.ru.urfu.model.Player;
+import main.java.ru.urfu.parser.CsvParser;
+import main.java.ru.urfu.presentation.view.ConsoleView;
+import main.java.ru.urfu.resolver.Resolver;
+
+import java.util.List;
+import java.util.Scanner;
+
+public class Controller {
+ private final ConsoleView view;
+ private final Scanner scanner;
+ private final Resolver resolver;
+ private final Mapper mapper;
+ private final Drawer drawer;
+
+
+ public Controller(ConsoleView view, Resolver resolver) {
+ this.view = view;
+ this.resolver = resolver;
+ scanner = new Scanner(System.in);
+ drawer = new Drawer();
+ mapper = new Mapper();
+ }
+
+ public void start() {
+ view.showWelcome();
+ mainCycle:
+ while (true) {
+ view.showEnterCommand();
+
+ switch (scanner.nextLine()) {
+ case "F" -> onEnterFile();
+ case "1" -> onTask1Request();
+ case "2" -> onTask2Request();
+ case "3" -> onTask3Request();
+ case "4" -> onTask4Request();
+ case "G" -> onChartRequest();
+ default -> {
+ break mainCycle;
+ }
+ }
+ }
+ }
+
+ private void onEnterFile() {
+ view.showFilePath();
+ try {
+ List players = CsvParser.parserCsvToList(scanner.nextLine());
+ resolver.setPlayers(players);
+ mapper.setPlayers(players);
+ } catch (Exception e) {
+ this.onFileError();
+ }
+ }
+
+ private void onFileError() {
+ view.showFileError();
+ }
+
+ private void onTask1Request() {
+ view.showCountWithoutAgency(resolver.getCountWithoutAgency());
+ }
+
+ private void onTask2Request() {
+ view.showMaxDefenderGoalsCount(resolver.getMaxDefenderGoalsCount());
+ }
+
+ private void onTask3Request() {
+ view.showTheExpensiveGermanPlayerPosition(resolver.getTheExpensiveGermanPlayerPosition());
+ }
+
+ private void onTask4Request() {
+ view.showTheRudestTeam(resolver.getTheRudestTeam());
+ }
+
+ private void onChartRequest() {
+ drawer.drawDiagramPlayersByPosition(mapper.getPlayersByPosition());
+ }
+}
diff --git a/src/main/java/ru/urfu/presentation/view/ConsoleView.java b/src/main/java/ru/urfu/presentation/view/ConsoleView.java
new file mode 100644
index 0000000..55bbdc1
--- /dev/null
+++ b/src/main/java/ru/urfu/presentation/view/ConsoleView.java
@@ -0,0 +1,43 @@
+package main.java.ru.urfu.presentation.view;
+
+public class ConsoleView {
+ public void showWelcome() {
+ System.out.println("""
+ Конанды:
+ F - выбрать файл для анализа
+ 1 - решение задачи 1
+ 2 - решение задачи 2
+ 3 - решение задачи 3
+ 4 - решение задачи 4
+ G - показать график
+ Любая иная клавиша - завершить работу""");
+ }
+
+ public void showEnterCommand() {
+ System.out.print("Введите команду: ");
+ }
+
+ public void showFilePath() {
+ System.out.print("Полный путь до .csv файла: ");
+ }
+
+ public void showFileError() {
+ System.out.println("Неправильный путь до файла");
+ }
+
+ public void showCountWithoutAgency(int count) {
+ System.out.printf("Количество игроков без агентсва: %d\n", count);
+ }
+
+ public void showMaxDefenderGoalsCount(int count) {
+ System.out.printf("Максимальное количество голов у защитника: %d\n", count);
+ }
+
+ public void showTheExpensiveGermanPlayerPosition(String position) {
+ System.out.printf("Название позиции самого дорогого немецкого игрока: %s\n", position);
+ }
+
+ public void showTheRudestTeam(String team) {
+ System.out.printf("Команда с наибольшим средним числом удалений на одного игрока: %s\n", team);
+ }
+}
diff --git a/src/main/java/ru/urfu/resolver/IResolver.java b/src/main/java/ru/urfu/resolver/IResolver.java
index c806b3a..2ae0bc2 100644
--- a/src/main/java/ru/urfu/resolver/IResolver.java
+++ b/src/main/java/ru/urfu/resolver/IResolver.java
@@ -1,4 +1,4 @@
-package ru.urfu.resolver;
+package main.java.ru.urfu.resolver;
public interface IResolver {
// Выведите количество игроков, интересы которых не представляет агентство.
diff --git a/src/main/java/ru/urfu/resolver/Resolver.java b/src/main/java/ru/urfu/resolver/Resolver.java
new file mode 100644
index 0000000..df8b856
--- /dev/null
+++ b/src/main/java/ru/urfu/resolver/Resolver.java
@@ -0,0 +1,55 @@
+package main.java.ru.urfu.resolver;
+
+import main.java.ru.urfu.model.Player;
+import main.java.ru.urfu.model.Position;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class Resolver implements IResolver {
+
+ private List players = new ArrayList<>();
+
+ public void setPlayers(List players) {
+ this.players = players;
+ }
+
+ @Override
+ public int getCountWithoutAgency() {
+ return (int) players.stream()
+ .filter(p -> p.agency().isEmpty())
+ .count();
+ }
+
+ @Override
+ public int getMaxDefenderGoalsCount() {
+ return players.stream()
+ .filter(p -> p.position().equals(Position.DEFENDER))
+ .mapToInt(Player::goals)
+ .max()
+ .orElse(0);
+ }
+
+ @Override
+ public String getTheExpensiveGermanPlayerPosition() {
+ return players.stream()
+ .filter(p -> p.nationality().equals("Germany"))
+ .max(Comparator.comparing(Player::transferCost))
+ .map(Player::position)
+ .map(Position::getTitleRu)
+ .orElse("Нет немецких игроков");
+ }
+
+ @Override
+ public String getTheRudestTeam() {
+ return players.stream()
+ .collect(Collectors.groupingBy(Player::team, Collectors.averagingDouble(Player::redCards)))
+ .entrySet().stream()
+ .max(Map.Entry.comparingByValue())
+ .map(Map.Entry::getKey)
+ .orElse("Команд не найдено");
+ }
+}
diff --git a/src/test/java/ru/urfu/MapperTest.java b/src/test/java/ru/urfu/MapperTest.java
new file mode 100644
index 0000000..f622786
--- /dev/null
+++ b/src/test/java/ru/urfu/MapperTest.java
@@ -0,0 +1,64 @@
+package test.java.ru.urfu;
+
+import main.java.ru.urfu.mapper.Mapper;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import main.java.ru.urfu.model.Player;
+import main.java.ru.urfu.model.Position;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class MapperTest {
+ @Test
+ void testGetPlayersByPositionAll() {
+ List players = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "Nat 1", "Agency 1", 100, 0, 0, 0, 0),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Nat 1", "Agency 1", 100, 0, 0, 0, 0),
+ new Player("Player 3", "Team B", "City B", Position.GOALKEEPER, "Nat 2", "Agency 2", 100, 0, 0, 0, 0),
+ new Player("Player 4", "Team B", "City B", Position.MIDFIELD, "Nat 2", "Agency 2", 100, 0, 0, 0, 0),
+ new Player("Player 5", "Team C", "City C", Position.FORWARD, "Nat 3", "Agency 3", 100, 0, 0, 0, 0)
+ );
+
+ Mapper mapper = new Mapper();
+ mapper.setPlayers(players);
+ Map playersByPosition = mapper.getPlayersByPosition();
+
+ assertEquals(2L, playersByPosition.get(Position.GOALKEEPER));
+ assertEquals(1L, playersByPosition.get(Position.DEFENDER));
+ assertEquals(1L, playersByPosition.get(Position.MIDFIELD));
+ assertEquals(1L, playersByPosition.get(Position.FORWARD));
+ }
+
+ @Test
+ void testGetPlayersByPositionPart() {
+ List players = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "Nat 1", "Agency 1", 100, 0, 0, 0, 0),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Nat 1", "Agency 1", 100, 0, 0, 0, 0),
+ new Player("Player 3", "Team B", "City B", Position.GOALKEEPER, "Nat 2", "Agency 2", 100, 0, 0, 0, 0),
+ new Player("Player 4", "Team B", "City B", Position.MIDFIELD, "Nat 2", "Agency 2", 100, 0, 0, 0, 0)
+ );
+
+ Mapper mapper = new Mapper();
+ mapper.setPlayers(players);
+ Map playersByPosition = mapper.getPlayersByPosition();
+
+ assertEquals(2L, playersByPosition.get(Position.GOALKEEPER));
+ assertEquals(1L, playersByPosition.get(Position.DEFENDER));
+ assertEquals(1L, playersByPosition.get(Position.MIDFIELD));
+ }
+
+ @Test
+ void testGetPlayersByPositionZero() {
+ List players = Collections.emptyList();
+
+ Mapper mapper = new Mapper();
+ mapper.setPlayers(players);
+ Map playersByPosition = mapper.getPlayersByPosition();
+
+ assertEquals(0, playersByPosition.size());
+ }
+}
diff --git a/src/test/java/ru/urfu/ResolverTest.java b/src/test/java/ru/urfu/ResolverTest.java
new file mode 100644
index 0000000..118a032
--- /dev/null
+++ b/src/test/java/ru/urfu/ResolverTest.java
@@ -0,0 +1,92 @@
+package test.java.ru.urfu;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import main.java.ru.urfu.resolver.Resolver;
+import main.java.ru.urfu.model.Player;
+import main.java.ru.urfu.model.Position;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ResolverTest {
+
+ @Test
+ void getCountWithoutAgencyTest() {
+ List players = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "Nat 1", "Agency 1", 100, 0, 0, 0, 0),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Nat 1", "", 100, 0, 0, 0, 0),
+ new Player("Player 3", "Team B", "City B", Position.GOALKEEPER, "Nat 2", "", 100, 0, 0, 0, 0)
+ );
+ Resolver resolver = new Resolver();
+ resolver.setPlayers(players);
+ assertEquals(2, resolver.getCountWithoutAgency());
+
+ List emptyPlayers = Collections.emptyList();
+ Resolver resolverEmpty = new Resolver();
+ resolverEmpty.setPlayers(emptyPlayers);
+ assertEquals(0, resolverEmpty.getCountWithoutAgency());
+ }
+
+ @Test
+ void getMaxDefenderGoalsCountTest() {
+ List players = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "Nat 1", "Agency 1", 100, 20, 0, 0, 0),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Nat 1", "Agency 1", 100, 1, 0, 0, 0),
+ new Player("Player 3", "Team B", "City B", Position.FORWARD, "Nat 2", "Agency 2", 100, 69, 0, 0, 0),
+ new Player("Player 4", "Team B", "City B", Position.DEFENDER, "Nat 2", "Agency 2", 100, 23, 0, 0, 0),
+ new Player("Player 5", "Team C", "City C", Position.DEFENDER, "Nat 3", "Agency 3", 100, 45, 0, 0, 0)
+ );
+ Resolver resolver = new Resolver();
+ resolver.setPlayers(players);
+ assertEquals(45, resolver.getMaxDefenderGoalsCount());
+
+ List emptyPlayers = Collections.emptyList();
+ Resolver resolverEmpty = new Resolver();
+ resolverEmpty.setPlayers(emptyPlayers);
+ assertEquals(0, resolverEmpty.getMaxDefenderGoalsCount());
+ }
+
+ @Test
+ void getTheExpensiveGermanPlayerPositionTest() {
+ List players = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "Germany", "Agency 1", 15, 20, 0, 0, 0),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Germany", "Agency 1", 0, 1, 0, 0, 0),
+ new Player("Player 3", "Team B", "City B", Position.FORWARD, "France", "Agency 2", 100, 69, 0, 0, 0),
+ new Player("Player 4", "Team B", "City B", Position.DEFENDER, "Germany", "Agency 2", 20, 23, 0, 0, 0),
+ new Player("Player 5", "Team C", "City C", Position.DEFENDER, "Russian", "Agency 3", 500000, 45, 0, 0, 0)
+ );
+ Resolver resolver = new Resolver();
+ resolver.setPlayers(players);
+ assertEquals("Защитник", resolver.getTheExpensiveGermanPlayerPosition());
+
+ List noGermanPlayers = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "France", "Agency 1", 15, 20, 0, 0, 0),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Russian", "Agency 1", 0, 1, 0, 0, 0)
+ );
+ Resolver resolverNoGerman = new Resolver();
+ resolverNoGerman.setPlayers(noGermanPlayers);
+ assertEquals("Нет немецких игроков", resolverNoGerman.getTheExpensiveGermanPlayerPosition());
+ }
+
+ @Test
+ void getTheRudestTeamTest() {
+ List players = List.of(
+ new Player("Player 1", "Team A", "City A", Position.GOALKEEPER, "Nat 1", "Agency 1", 100, 20, 0, 0, 2),
+ new Player("Player 2", "Team A", "City A", Position.DEFENDER, "Nat 1", "Agency 1", 100, 1, 0, 0, 0),
+ new Player("Player 3", "Team B", "City B", Position.FORWARD, "Nat 2", "Agency 2", 100, 69, 0, 0, 1),
+ new Player("Player 4", "Team B", "City B", Position.DEFENDER, "Nat 2", "Agency 2", 100, 23, 0, 0, 6),
+ new Player("Player 5", "Team C", "City C", Position.DEFENDER, "Nat 3", "Agency 3", 100, 45, 0, 0, 3)
+ );
+ Resolver resolver = new Resolver();
+ resolver.setPlayers(players);
+ assertEquals("Team B", resolver.getTheRudestTeam());
+
+ List emptyPlayers = Collections.emptyList();
+ Resolver resolverEmpty = new Resolver();
+ resolverEmpty.setPlayers(emptyPlayers);
+ assertEquals("Команд не найдено", resolverEmpty.getTheRudestTeam());
+ }
+}