Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,61 @@
4. Найденная в соответствии с условием задачи категория должна выводиться в изначальном наименовании, приведенном в файле с входными данными. Если таких категорий несколько, то на вывод они все подаются в алфавитном порядке.

## Автор решения

Корчагин Илья Вадимович
## Описание реализации
На основе json файла были созданы классы POJO: Response, Order, Item, и Category. При помощи библиотеки Jackson считывается
json из файла и преобразуется в экземпляры этих классов. Для работы с json был создан класс JsonConverter в пакете utils.
В этом классе метод _convertJsonToResponse_ преобразует json файл в объект класса Response. Метод _convertCategoriesToJson_
преобразует список категорий в формат json.

В классе ReportGenerator находится функционал для генерации отчета по популярным категориям. Метод _getPopularCategory_
принимает JSON-файл и возвращает список категорий с максимальным количеством упоминаний. Для работы со списками
используется Stream API, т.к. он позволяет сократить код и упростить работу с коллекциями.

Часть кода в методе _getPopularCategory_, отвечающая за подсчет количества упоминаний категорий.

```java
Response response = JsonConverter.convertJsonToResponse(json);
Map<String, Integer> categoriesCount = new HashMap<>();

response.getOrders().stream()
// Отбираем только заказы сделанные в декабре
.filter(order -> checkNewYearHolidays(order.getOrderedAt()))
.forEach(order -> {
order.getItems().forEach(item -> {
categoriesCount.put(item.getCategory().getName(),
// Суммируем количество упоминаний по категориям
categoriesCount.getOrDefault(item.getCategory().getName(), 0) + 1);
});
});
```

Часть кода в методе _getPopularCategory_, отвечающая за определение самых популярных категорий. Сначала определяется
максимальное число упоминания категории, а затем выбираются все названия категорий, число упоминания которых равно
максимальному. Полученный список сортируется в алфавитном порядке.

```java
// Получаем максимальное количество упоминаний
long maxCount = categoriesCount.values().stream().max(Integer::compareTo).orElse(0);

// Возвращаем список категорий с максимальным количеством упоминаний
return categoriesCount.entrySet().stream()
.filter(entry -> entry.getValue() == maxCount) // Фильтруем все элементы категории с максимальным количеством упоминаний
.map(Map.Entry::getKey)
.sorted() // Сортируем по алфавиту
.collect(Collectors.toList());
```


В методе _getPopularCategory_ используются приватные методы _parseDate_ для преобразования даты из текста в объект класса
_LocalDateTime_. Метод _checkNewYearHolidays_ проверяет является ли дата предновогодней (1 - 31 декабря). В этот метод
можно было бы передавать номер месяца и проверять принадлежность даты к этому месяцу, чтобы не хардкодить декабрь.

Метод _generateReport_ преобразует список категорий в строку формата json.

## Инструкция по сборке и запуску решения
Для сборки приложения необходимо в командной строке использовать команду javac, чтобы скомпилировать проект. Затем запустить скомпилированный класс App при помощи команды java и в качестве аргумента передать путь к json файлу.

Можно использовать maven плагин jar для создания jar файла. Созданный файл запустить при помощи команды java -jar [название файла].jar [путь к json файлу] аргументом является путь к json файлу.

Или запустить загруженный файл croc.jar при помощи команды java -jar [путь к файлу croc.jar] [путь к файлу json]
Binary file added croc.jar
Binary file not shown.
86 changes: 86 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru</groupId>
<artifactId>croc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Croc</name>
<description>Croc</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0-rc1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>ru.croc.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs</classpathPrefix>
<mainClass>
ru.croc.App
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
13 changes: 13 additions & 0 deletions src/main/java/ru/croc/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.croc;

import ru.croc.utils.ReportGenerator;

import java.io.File;

public class App {

public static void main(String[] args) {
System.out.println(ReportGenerator.generateReport(
ReportGenerator.getPopularCategory(new File(args[0]))));
}
}
24 changes: 24 additions & 0 deletions src/main/java/ru/croc/models/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ru.croc.models;

public class Category{

private String id;

private String name;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}

public void setId(String id){
this.id = id;
}

public String getId(){
return id;
}
}
34 changes: 34 additions & 0 deletions src/main/java/ru/croc/models/Item.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ru.croc.models;

public class Item {

private String id;

private String name;

private Category category;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}

public void setId(String id){
this.id = id;
}

public String getId(){
return id;
}

public void setCategory(Category category){
this.category = category;
}

public Category getCategory(){
return category;
}
}
29 changes: 29 additions & 0 deletions src/main/java/ru/croc/models/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.croc.models;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;

public class Order {

@JsonProperty("ordered_at")
private String orderedAt;

private List<Item> items;

public void setOrderedAt(String orderedAt){
this.orderedAt = orderedAt;
}

public String getOrderedAt(){
return orderedAt;
}

public void setItems(List<Item> items){
this.items = items;
}

public List<Item> getItems(){
return items;
}
}
22 changes: 22 additions & 0 deletions src/main/java/ru/croc/models/Response.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ru.croc.models;

import java.util.List;

public class Response{
private List<Order> orders;

public Response() {
}

public Response(List<Order> orders) {
this.orders = orders;
}

public void setOrders(List<Order> orders){
this.orders = orders;
}

public List<Order> getOrders(){
return orders;
}
}
33 changes: 33 additions & 0 deletions src/main/java/ru/croc/utils/JsonConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.croc.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import ru.croc.models.Order;
import ru.croc.models.Response;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class JsonConverter {
private static final ObjectMapper mapper = new ObjectMapper();

public static Response convertJsonToResponse(File json) {
Response response = null;
try {
// Корневой элемент JSON'а это массив заказов, поэтому преобразуем его в список
response = new Response(mapper.readValue(json, new TypeReference<List<Order>>() {}));
} catch (IOException e) {
throw new RuntimeException(e);
}
return response;
}

public static String convertCategoriesToJson(List<String> categories) {
return "{categories: " + categories + "}";
}

public static ObjectMapper getObjectMapper() {
return mapper;
}
}
70 changes: 70 additions & 0 deletions src/main/java/ru/croc/utils/ReportGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ru.croc.utils;

import ru.croc.models.Response;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ReportGenerator {
/**
* Метод принимает JSON-файл и возвращает список категорий с максимальным количеством упоминаний
* @param json файл в формате JSON
* @return список категорий
*/
public static List<String> getPopularCategory(File json) {
if (json == null) {
throw new IllegalArgumentException("JSON файл не существует");
}

Response response = JsonConverter.convertJsonToResponse(json);
Map<String, Integer> categoriesCount = new HashMap<>();

// Считаем количество упоминаний категорий
response.getOrders().stream()
.filter(order -> checkNewYearHolidays(order.getOrderedAt()))
.forEach(order -> {
order.getItems().forEach(item -> {
categoriesCount.put(item.getCategory().getName(),
// Суммируем количество упоминаний по категориям
categoriesCount.getOrDefault(item.getCategory().getName(), 0) + 1);
});
});

// Получаем максимальное количество упоминаний
long maxCount = categoriesCount.values().stream().max(Integer::compareTo).orElse(0);

// Возвращаем список категорий с максимальным количеством упоминаний
return categoriesCount.entrySet().stream()
.filter(entry -> entry.getValue() == maxCount) // Фильтруем все элементы категории с максимальным количеством упоминаний
.map(Map.Entry::getKey)
.sorted() // Сортируем по алфавиту
.collect(Collectors.toList());
}

public static String generateReport(List<String> categories) {
return JsonConverter.convertCategoriesToJson(categories);
}

private static LocalDateTime parseDate(String date) {
return LocalDateTime.parse(date);
}

/**
* Проверяет является ли дата предновогодней (1 - 31 декабря)
* @param date дата в формате "yyyy-MM-dd"
* @return true - является, false - не является
*/
private static boolean checkNewYearHolidays(String date) {
try {
LocalDateTime orderDate = parseDate(date);
return orderDate.getMonthValue() == 12;
} catch (DateTimeParseException e) {
return false;
}
}
}
Binary file added src/main/resources/lib/byte-buddy-1.14.9.jar
Binary file not shown.
Binary file not shown.
Binary file added src/main/resources/lib/jackson-core-2.17.0.jar
Binary file not shown.
Binary file not shown.