diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..ae5474d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..e5d6295 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index ee9d69b..7b2cd64 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,19 @@ 4. Найденный в соответствии с условием задачи месяц должен выводиться на английском языке в нижнем регистре. Если месяцев несколько, то на вывод они все подаются на английском языке в нижнем регистре в порядке их следования в течение года. ## Автор решения +Разнодумова Виктория Алексеевна ## Описание реализации +1. Проект содержит 3 класса (Main - для запуска приложения, Report - для генерации отчетов и работы с ними, Order - для хранения и парсинга заказов) и 2 перечисления (OrderStatuses - для хранения состояний заказов, Months - для обработки месяцев). +2. В начале работы программа считывает содержимое файла format.json и преобразует его в массив JSON, который передается в статический метод parseOrders() класса Order, который хранит данные каждого заказа после парсинга. Метод parseOrders() принимает массив JSON, и для каждого его объекта преобразует поля в удобный для работы формат. Поле status хранится в виде перечислений OrderStatuses. Метод возвращает список типа Order. +3. Создаём новый отчёт - объект класса Report для поиска месяца с наибольшими тратами. Для формирования отчёта используется функция generateMaxTotalMonthReport(), возвращающая строку в формате JSON. +4. Внутри функции создаётся словарь totalForMonths, который будет хранить месяц и сумму заказов. Затем начинаем итерироваться по всем заказам из нашего списка заказов и выполняем проверку на статус. Если он соответствует COMPLETED, то для него получаем месяц. Далее проверяем, был ли месяц уже добавлен в наш словарь. Если да, то для суммарного значения переменной double totalForMonth берём уже записанное в словарь значение, в противном случае присваиваем переменной 0.0. В результате обновляем наш словарь: добавляем в него пару ключу - текущий месяц, значение - старое значение totalForMonth из словаря плюс поле total текущего объекта Order, которое получаем с помощью гетэра. +5. Далее выполняется поиск максимального значения суммы total. Проходимся по всем значениям из словаря totalForMonths и сравниваем их с максимальным maxTotal, который проинициализирован значением Double.MIN_VALUE. Таким образом получаем максимальное значение. +6. Создаём список всех месяцев maxTotalForMonths, для которых сумма оказалась равна найденному maxTotal. Если найдено несколько месяцев, то необходимо обеспечить вывод в порядке их следования в течение года. Для этого проходим по значениям перечисления Months и проверяем, была ли в указанный месяц максимальная сумма. Если да, то преобразуем значение из Months в строку и добавляем в список. +7. В конце создаём объект JSON и добавляем в него найденные значения. Таким образом, функция generateMaxTotalMonthReport() возвращает строку в формате JSON, которая в классе Main выводится на экран. +## Инструкция по сборке и запуску решения +Для запуска необходим maven-сборщик с официального сайта. +1. В командной строке необходимо прописать команду для копирования репозитория: git clone https://github.com/victoriaraznodumova/school2024-test-task1.git +2. В корневой директории проекта нужно прописать команду для сборки проекта: mvn clean package +3. Команда для запуска приложения: mvn exec:java -## Инструкция по сборке и запуску решения diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..44b4d09 --- /dev/null +++ b/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + org.example + test-task1 + 1.0-SNAPSHOT + + + 19 + 19 + UTF-8 + + + + + + + org.json + json + 20240303 + + + + \ No newline at end of file diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java new file mode 100644 index 0000000..c401435 --- /dev/null +++ b/src/main/java/org/example/Main.java @@ -0,0 +1,24 @@ +package org.example; + +import org.json.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +public class Main { + public static void main(String[] args) { + try { + String jsonString = new String(Files.readAllBytes(Paths.get("format.json"))); + JSONArray jsonArray = new JSONArray(jsonString); + List orders = Order.parseOrders(jsonArray); + Report maxMonthReport = new Report(orders); + System.out.println(maxMonthReport.generateMaxTotalMonthReport()); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (JSONException e) { + throw new RuntimeException(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/example/Months.java b/src/main/java/org/example/Months.java new file mode 100644 index 0000000..24c340d --- /dev/null +++ b/src/main/java/org/example/Months.java @@ -0,0 +1,16 @@ +package org.example; + +public enum Months { + JANUARY, + FEBRUARY, + MARCH, + APRIL, + MAY, + JUNE, + JULY, + AUGUST, + SEPTEMBER, + OCTOBER, + NOVEMBER, + DECEMBER; +} \ No newline at end of file diff --git a/src/main/java/org/example/Order.java b/src/main/java/org/example/Order.java new file mode 100644 index 0000000..30bf79a --- /dev/null +++ b/src/main/java/org/example/Order.java @@ -0,0 +1,50 @@ +package org.example; + +import org.json.*; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +public class Order { + private String userId; + private LocalDate orderedAt; + private OrderStatuses status; + private double total; + + public Order(String userId, LocalDate orderedAt, OrderStatuses status, double total) { + this.userId = userId; + this.orderedAt = orderedAt; + this.status = status; + this.total = total; + } + public String getUserId() { + return userId; + } + public OrderStatuses getStatus(){ + return status; + } + public LocalDate getOrderedAt() { + return orderedAt; + } + public double getTotal() { + return total; + } + + public static List parseOrders(JSONArray jsonArray) { + List orders = new ArrayList<>(); + for (int i = 0; i < jsonArray.length(); i++) { + try { + JSONObject jsonObject = jsonArray.getJSONObject(i); + String userId = jsonObject.getString("user_id"); + LocalDate orderedAt = LocalDate.parse(jsonObject.getString("ordered_at").substring(0, 10)); + OrderStatuses status = OrderStatuses.valueOf(jsonObject.getString("status")); + double total = jsonObject.getDouble("total"); + orders.add(new Order(userId, orderedAt, status, total)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return orders; + } +} \ No newline at end of file diff --git a/src/main/java/org/example/OrderStatuses.java b/src/main/java/org/example/OrderStatuses.java new file mode 100644 index 0000000..0a49f0c --- /dev/null +++ b/src/main/java/org/example/OrderStatuses.java @@ -0,0 +1,8 @@ +package org.example; + +public enum OrderStatuses { + COMPLETED, + CANCELED, + CREATED, + DELIVERY; +} \ No newline at end of file diff --git a/src/main/java/org/example/Report.java b/src/main/java/org/example/Report.java new file mode 100644 index 0000000..5b1ed17 --- /dev/null +++ b/src/main/java/org/example/Report.java @@ -0,0 +1,43 @@ +package org.example; + +import org.json.JSONObject; + +import java.time.Month; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Report { + List orders; + public Report( List orders){ + this.orders = orders; + } + + public String generateMaxTotalMonthReport() { + Map totalForMonths = new HashMap<>(); + for (Order order : orders) { + if (order.getStatus() == OrderStatuses.COMPLETED) { + Month month = order.getOrderedAt().getMonth(); + double totalForMonth = totalForMonths.getOrDefault(month.name().toLowerCase(), 0.0); + totalForMonths.put(month.name().toLowerCase(), totalForMonth + order.getTotal()); + } + } + double maxTotal = Double.MIN_VALUE; + for (double total : totalForMonths.values()) { + maxTotal = Math.max(maxTotal, total); + } + + List maxTotalForMonths = new ArrayList<>(); + for (Months month: Months.values()){ + String monthString = month.toString().toLowerCase(); + if (totalForMonths.containsKey(monthString) && totalForMonths.get(monthString) == maxTotal){ + maxTotalForMonths.add(monthString); + } + } + + JSONObject reportJson = new JSONObject(); + reportJson.put("months", maxTotalForMonths); + return reportJson.toString(); + } +} \ No newline at end of file