diff --git a/build.gradle.kts b/build.gradle.kts index 72be7ed..933e308 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,10 @@ plugins { id("java") + id("application") +} + +application { + mainClass = "ru.urfu.Main" } group = "ru.urfu" @@ -10,10 +15,21 @@ repositories { } dependencies { + testImplementation("org.jfree:jfreechart:1.5.4") + implementation("org.jfree:jfreechart:1.5.4") testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0") } tasks.test { useJUnitPlatform() -} \ No newline at end of file + testLogging { + events("passed", "skipped", "failed") + } +} + +tasks.named("run") { + standardInput = System.`in` +} diff --git a/src/main/java/ru/urfu/Main.java b/src/main/java/ru/urfu/Main.java index 5845f6d..56a8eb3 100644 --- a/src/main/java/ru/urfu/Main.java +++ b/src/main/java/ru/urfu/Main.java @@ -1,17 +1,11 @@ package ru.urfu; -//TIP To Run code, press or -// click the icon in the gutter. +import ru.urfu.console.*; +import ru.urfu.parser.*; +import ru.urfu.model.*; + 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!"); - - 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); - } + Communicator.runChampionship(); } -} \ 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..ce77b50 --- /dev/null +++ b/src/main/java/ru/urfu/console/Communicator.java @@ -0,0 +1,32 @@ +package ru.urfu.console; + +import ru.urfu.parser.*; +import ru.urfu.resolver.*; +import ru.urfu.graphics.*; + +import java.util.Scanner; + +public class Communicator { + public static void runChampionship() { + var scanner = new Scanner(System.in); + System.out.println("Введите файл для анализа из директории src/main/resources: "); + String fileName = scanner.nextLine(); + + var players = CSVParser.parseCSVToList(fileName); + var resolver = new Resolver(players); + + System.out.println("Количество игроков, интересы которых не представляет агенство:"); + System.out.println(resolver.getCountWithoutAgency()); + + System.out.println("Максимальное число голов, забитых защитником:"); + System.out.println(resolver.getMaxDefenderGoalsCount()); + + System.out.println("Русское название позиции самого дорогого немецкого игрока:"); + System.out.println(resolver.getTheExpensiveGermanPlayerPosition()); + + System.out.println("Команда с наибольшим средним числом красных карточек на одного игрока:"); + System.out.println(resolver.getTheRudestTeam()); + + Graphics.showGraphics(Graphics.makeMapping(players)); + } +} diff --git a/src/main/java/ru/urfu/graphics/Graphics.java b/src/main/java/ru/urfu/graphics/Graphics.java new file mode 100644 index 0000000..f044a67 --- /dev/null +++ b/src/main/java/ru/urfu/graphics/Graphics.java @@ -0,0 +1,72 @@ +package ru.urfu.graphics; + +import ru.urfu.model.*; + +import javax.swing.JPanel; +import javax.swing.JFrame; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartFrame; +import org.jfree.chart.*; +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; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class Graphics { + public static Map makeMapping(List players) { + return players + .stream() + .collect(Collectors.groupingBy(Player::position, Collectors.counting())); + } + + static String posToStr(Position pos) { + switch (pos) { + case (Position.GOALKEEPER): + return "Вратарь"; + case (Position.DEFENDER): + return "Защитник"; + case (Position.MIDFIELD): + return "Полузащитник"; + default: + return "Нападающий"; + } + } + + public static void showGraphics(Map positionsCount) { + DefaultPieDataset dataset = new DefaultPieDataset<>(); + + positionsCount.forEach((pos, cnt) -> + dataset.setValue(posToStr(pos), cnt) + ); + + JFreeChart chart = ChartFactory.createPieChart("Распределение по позициям", dataset, true, true, false); + + ChartPanel chartPanel = new ChartPanel(chart); + JFrame frame = new JFrame(); + + PiePlot plot = (PiePlot) chart.getPlot(); + plot.setLabelGenerator(new StandardPieSectionLabelGenerator( + "{0}: {1} ({2})", + new DecimalFormat("0"), + new DecimalFormat("0.00%") + )); + + + frame.setSize(800, 600); + frame.setContentPane(chartPanel); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} 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..fbd6c2d --- /dev/null +++ b/src/main/java/ru/urfu/model/Player.java @@ -0,0 +1,14 @@ +package ru.urfu.model; + +public record Player( + String name, + String team, + String city, + Position position, + String nationality, + String agency, + int cost, + int goals, + int yCards, + int rCards +) {} 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..0df3c0e --- /dev/null +++ b/src/main/java/ru/urfu/model/Position.java @@ -0,0 +1,8 @@ +package ru.urfu.model; + +public enum Position { + GOALKEEPER, + DEFENDER, + MIDFIELD, + FORWARD +} 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..42c98f6 --- /dev/null +++ b/src/main/java/ru/urfu/parser/CSVParser.java @@ -0,0 +1,48 @@ +package ru.urfu.parser; + +import ru.urfu.model.*; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Scanner; +import java.io.*; + +public class CSVParser { + public static ArrayList parseCSVToList(String filename) { + var list = new ArrayList(); + var scanner = getScanner(Paths.get(System.getProperty("user.dir") + "/src/main/resources/" + filename)); + + scanner.nextLine(); + while (scanner.hasNextLine()) { + list.add(parsePlayerRow(scanner.nextLine())); + } + + return list; + } + + public static Player parsePlayerRow(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[8]), + Integer.parseInt(cells[10]), + Integer.parseInt(cells[11]) + ); + } + + private static Scanner getScanner(Path path) { + try { + return new Scanner(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} 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..ae9cbd6 --- /dev/null +++ b/src/main/java/ru/urfu/resolver/Resolver.java @@ -0,0 +1,77 @@ +package ru.urfu.resolver; + +import ru.urfu.model.*; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class Resolver implements IResolver { + private final List players; + + public Resolver(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)) + .max(Comparator.comparing(p -> p.goals())) + .map(p -> p.goals()) + .orElse(-1); + } + + @Override + public String getTheExpensiveGermanPlayerPosition() { + return players.stream() + .filter(p -> p.nationality().equals("Germany")) + .max(Comparator.comparing(p -> p.cost())) + .map(p -> { + switch (p.position()) { + case (Position.GOALKEEPER): + return "Вратарь"; + case (Position.DEFENDER): + return "Защитник"; + case (Position.MIDFIELD): + return "Полузащитник"; + default: + return "Нападающий"; + } + }) + .orElse("Ошибка: немецких игроков не найдено"); + } + + @Override + public String getTheRudestTeam() { + var teams = players + .stream() + .collect(Collectors.groupingBy(p -> p.team())); + + var maxEntry = teams + .entrySet() + .stream() + .max(Comparator.comparing(entry -> + entry + .getValue() + .stream() + .mapToDouble(Player::rCards) + .average() + .orElse(0) + )) + .orElse(null); + + if (maxEntry == null) { + return "Ошибка: команд не найдено"; + } + return maxEntry.getKey(); + } +} diff --git a/src/test/java/ru/urfu/graphics/MappingTest.java b/src/test/java/ru/urfu/graphics/MappingTest.java new file mode 100644 index 0000000..c91b8bc --- /dev/null +++ b/src/test/java/ru/urfu/graphics/MappingTest.java @@ -0,0 +1,37 @@ +package ru.urfu.graphics; + +import ru.urfu.graphics.*; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +import ru.urfu.model.*; +import ru.urfu.parser.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class MappingTest { + @Test + void testMakeMapping() { + List players = List.of( + CSVParser.parsePlayerRow("Randall Hilpert;North Carolina dolphins;Tennessee;DEFENDER;Ghana;Bahringer-Larson;54202579;21;2;13;8;0"), + CSVParser.parsePlayerRow("Connie Hegmann;North Carolina dolphins;Tennessee;DEFENDER;Ecuador;Bogisich-Rempel;97729347;2;8;28;4;5"), + CSVParser.parsePlayerRow("Leda Orn III;Nevada whales;South Carolina;MIDFIELD;Ghana;;53608367;19;5;18;2;0"), + CSVParser.parsePlayerRow("Thomas Howell DVM;Mississippi witches;Virginia;FORWARD;Colombia;;32821305;2;27;26;2;7"), + CSVParser.parsePlayerRow("Sherril Jacobs DDS;Massachusetts enchanters;Connecticut;MIDFIELD;Germany;Hauck Inc;39373848;20;16;21;2;1"), + CSVParser.parsePlayerRow("Antonina Reinger DVM;Hawaii oxen;Oklahoma;FORWARD;Ghana;Walker and Sons;99974008;4;27;18;8;4"), + CSVParser.parsePlayerRow("Lourdes Schoen;Minnesota giants;Washington;DEFENDER;Croatia;Graham-Powlowski;87664016;13;29;13;5;2"), + CSVParser.parsePlayerRow("Lilli Pagac;North Carolina dolphins;Tennessee;FORWARD;Qatar;Jakubowski and Sons;44568969;8;16;29;3;5"), + CSVParser.parsePlayerRow("Mitsuko Fadel;Wisconsin prophets;Vermont;FORWARD;Qatar;Price-Hirthe;47975979;4;16;0;0;6") + ); + + Map playersByPosition = Graphics.makeMapping(players); + + assertEquals(3L, playersByPosition.get(Position.DEFENDER)); + assertEquals(2L, playersByPosition.get(Position.MIDFIELD)); + assertEquals(4L, playersByPosition.get(Position.FORWARD)); + } + +} diff --git a/src/test/java/ru/urfu/resolver/ResolverTest.java b/src/test/java/ru/urfu/resolver/ResolverTest.java new file mode 100644 index 0000000..7f52a6b --- /dev/null +++ b/src/test/java/ru/urfu/resolver/ResolverTest.java @@ -0,0 +1,68 @@ +package ru.urfu.resolver; + +import org.junit.jupiter.api.Test; +import ru.urfu.model.*; +import ru.urfu.parser.*; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class ResolverTest { + + @Test + void testGetCountWithoutAgency() { + List players = List.of( + CSVParser.parsePlayerRow("Rory Koss;Utah nemesis;New York;MIDFIELD;Ghana;Jakubowski and Sons;4483194;20;13;11;9;2"), + CSVParser.parsePlayerRow("Carson Bradtke;Florida tigers;Washington;FORWARD;Colombia;;61663205;8;24;28;0;1"), + CSVParser.parsePlayerRow("Micha Koch;New Mexico ogres;Georgia;GOALKEEPER;Croatia;;32216127;15;20;0;7;1") + ); + Resolver resolver = new Resolver(players); + assertEquals(2, resolver.getCountWithoutAgency()); + } + + @Test + void testMaxDefenderGoals() { + List players = List.of( + CSVParser.parsePlayerRow("Rory Koss;Utah nemesis;New York;MIDFIELD;Ghana;Jakubowski and Sons;4483194;20;13;11;9;2"), + CSVParser.parsePlayerRow("Carson Bradtke;Florida tigers;Washington;FORWARD;Colombia;;61663205;8;24;28;0;1"), + CSVParser.parsePlayerRow("Eusebio Beatty IV;New Mexico ogres;Georgia;DEFENDER;Ecuador;D'Amore LLC;17429288;0;10;6;1;4"), + CSVParser.parsePlayerRow("Steven O'Conner DDS;Nevada whales;South Carolina;DEFENDER;Ghana;Bogisich-Rempel;32437027;26;15;16;1;6") + ); + Resolver resolver = new Resolver(players); + assertEquals(15, resolver.getMaxDefenderGoalsCount()); + } + + @Test + void testExpensiveGermanPosition() { + List players = List.of( + CSVParser.parsePlayerRow("Rory Koss;Utah nemesis;New York;MIDFIELD;Ghana;Jakubowski and Sons;4483194;20;13;11;9;2"), + CSVParser.parsePlayerRow("Carson Bradtke;Florida tigers;Washington;FORWARD;Colombia;;61663205;8;24;28;0;1"), + CSVParser.parsePlayerRow("Eusebio Beatty IV;New Mexico ogres;Georgia;DEFENDER;Ecuador;D'Amore LLC;17429288;0;10;6;1;4"), + CSVParser.parsePlayerRow("Steven O'Conner DDS;Nevada whales;South Carolina;DEFENDER;Ghana;Bogisich-Rempel;32437027;26;15;16;1;6"), + CSVParser.parsePlayerRow("Terry Hegmann;Wisconsin prophets;Vermont;DEFENDER;Germany;Graham-Powlowski;7294362;12;11;28;1;8"), + CSVParser.parsePlayerRow("Beckie Lindgren;Nevada whales;South Carolina;MIDFIELD;Germany;Walker and Sons;11576194;25;16;15;0;7") + ); + Resolver resolver = new Resolver(players); + assertEquals("Полузащитник", resolver.getTheExpensiveGermanPlayerPosition()); + } + + @Test + void testRudestTeam() { + List players = List.of( + CSVParser.parsePlayerRow("Iva Streich;Nevada whales;South Carolina;MIDFIELD;Colombia;D'Amore LLC;75012006;22;19;6;3;7"), + CSVParser.parsePlayerRow("Miss Buck Bradtke;Nevada whales;South Carolina;DEFENDER;Brazil;D'Amore LLC;33850831;20;26;18;6;9"), + CSVParser.parsePlayerRow("Everette Kovacek MD;Wisconsin prophets;Vermont;DEFENDER;Palau;Walker and Sons;64396675;27;11;25;0;5"), + CSVParser.parsePlayerRow("Ms. Adolph Hartmann;North Carolina dolphins;Tennessee;FORWARD;Croatia;;52944545;27;10;5;5;8"), + CSVParser.parsePlayerRow("Kenyetta Emard;Mississippi witches;Virginia;GOALKEEPER;Ecuador;D'Amore LLC;94715977;10;24;18;0;7"), + CSVParser.parsePlayerRow("Mrs. Celina Abshire;Massachusetts enchanters;Connecticut;GOALKEEPER;Qatar;D'Amore LLC;41436703;27;4;1;0;0"), + CSVParser.parsePlayerRow("Dr. Royal King;Florida tigers;Washington;GOALKEEPER;Ecuador;Walker and Sons;50056961;21;6;3;5;4"), + CSVParser.parsePlayerRow("Rory Koss;Utah nemesis;New York;MIDFIELD;Ghana;Jakubowski and Sons;4483194;20;13;11;9;2"), + CSVParser.parsePlayerRow("Lorinda Labadie;Utah nemesis;New York;MIDFIELD;Germany;Price-Hirthe;33413181;22;13;21;0;4"), + CSVParser.parsePlayerRow("Ms. Erwin Hoeger;Minnesota giants;Washington;DEFENDER;Qatar;Fadel LLC;71207725;26;28;15;7;1"), + CSVParser.parsePlayerRow("Terry Hegmann;Wisconsin prophets;Vermont;DEFENDER;Germany;Graham-Powlowski;7294362;12;11;28;1;8") + ); + Resolver resolver = new Resolver(players); + assertEquals("Nevada whales", resolver.getTheRudestTeam()); + } +}