diff --git a/java-gym-master.iml b/java-gym-master.iml index e5d2daf..5dfd50f 100644 --- a/java-gym-master.iml +++ b/java-gym-master.iml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/src/ru/yandex/practicum/gym/Coach.java b/src/ru/yandex/practicum/gym/Coach.java index dce0d7c..026bf00 100644 --- a/src/ru/yandex/practicum/gym/Coach.java +++ b/src/ru/yandex/practicum/gym/Coach.java @@ -4,12 +4,12 @@ public class Coach { - //фамилия - private String surname; - //имя - private String name; - //отчество - private String middleName; + // фамилия + private final String surname; + // имя + private final String name; + // отчество + private final String middleName; public Coach(String surname, String name, String middleName) { this.surname = surname; @@ -17,19 +17,6 @@ public Coach(String surname, String name, String middleName) { this.middleName = middleName; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Coach coach = (Coach) o; - return Objects.equals(surname, coach.surname) && Objects.equals(name, coach.name) && Objects.equals(middleName, coach.middleName); - } - - @Override - public int hashCode() { - return Objects.hash(surname, name, middleName); - } - public String getSurname() { return surname; } @@ -41,4 +28,20 @@ public String getName() { public String getMiddleName() { return middleName; } -} + + // Нужно для корректной работы HashMap в getCountByCoaches() + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Coach coach = (Coach) o; + return Objects.equals(surname, coach.surname) + && Objects.equals(name, coach.name) + && Objects.equals(middleName, coach.middleName); + } + + @Override + public int hashCode() { + return Objects.hash(surname, name, middleName); + } +} \ No newline at end of file diff --git a/src/ru/yandex/practicum/gym/TimeOfDay.java b/src/ru/yandex/practicum/gym/TimeOfDay.java index c567fec..d0669f9 100644 --- a/src/ru/yandex/practicum/gym/TimeOfDay.java +++ b/src/ru/yandex/practicum/gym/TimeOfDay.java @@ -4,16 +4,25 @@ public class TimeOfDay implements Comparable { - //часы (от 0 до 23) - private int hours; - //минуты (от 0 до 59) - private int minutes; + // часы (от 0 до 23) + private final int hours; + // минуты (от 0 до 59) + private final int minutes; public TimeOfDay(int hours, int minutes) { + this.hours = hours; this.minutes = minutes; } + public int getHours() { + return hours; + } + + public int getMinutes() { + return minutes; + } + @Override public int compareTo(TimeOfDay o) { if (hours != o.hours) return hours - o.hours; @@ -32,12 +41,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(hours, minutes); } - - public int getHours() { - return hours; - } - - public int getMinutes() { - return minutes; - } -} +} \ No newline at end of file diff --git a/src/ru/yandex/practicum/gym/Timetable.java b/src/ru/yandex/practicum/gym/Timetable.java index 48a1e2a..0229af3 100644 --- a/src/ru/yandex/practicum/gym/Timetable.java +++ b/src/ru/yandex/practicum/gym/Timetable.java @@ -4,17 +4,127 @@ public class Timetable { - private /* как это хранить??? */ timetable; + // O(1) получить отсортированный список занятий за день + private Map> dayCache; + + // O(1) получить занятия по дню и времени + private Map>> byDayAndTime; + + // сразу считаем тренировки тренеров при добавлении + private Map coachesCounter; + + public Timetable() { + dayCache = new HashMap<>(); + byDayAndTime = new HashMap<>(); + coachesCounter = new HashMap<>(); + + for (DayOfWeek day : DayOfWeek.values()) { + dayCache.put(day, new ArrayList<>()); + byDayAndTime.put(day, new HashMap<>()); + } + } public void addNewTrainingSession(TrainingSession trainingSession) { - //сохраняем занятие в расписании + if (trainingSession == null) { + return; + } + + DayOfWeek day = trainingSession.getDayOfWeek(); + TimeOfDay time = trainingSession.getTimeOfDay(); + Coach coach = trainingSession.getCoach(); + + if (day == null || time == null || coach == null) { + return; + } + + // 1) Добавление в список дня + List dayList = dayCache.get(day); + dayList.add(trainingSession); + + // сортируем по времени начала (разрешено делать при добавлении) + Collections.sort(dayList, new Comparator() { + @Override + public int compare(TrainingSession a, TrainingSession b) { + return a.getTimeOfDay().compareTo(b.getTimeOfDay()); + } + }); + + // Добавление в map день->время->список + Map> timeMap = byDayAndTime.get(day); + + List sessionsAtTime = timeMap.get(time); + if (sessionsAtTime == null) { + sessionsAtTime = new ArrayList<>(); + timeMap.put(time, sessionsAtTime); + } + sessionsAtTime.add(trainingSession); + + // Сразу обновляем статистику по тренерам + Integer count = coachesCounter.get(coach); + if (count == null) { + coachesCounter.put(coach, 1); + } else { + coachesCounter.put(coach, count + 1); + } + } + + + public List getTrainingSessionsForDay(DayOfWeek dayOfWeek) { + if (dayOfWeek == null) { + return new ArrayList<>(); + } + return dayCache.get(dayOfWeek); } - public /* непонятно, что возвращать */ getTrainingSessionsForDay(DayOfWeek dayOfWeek) { - //как реализовать, тоже непонятно, но сложность должна быть О(1) + + public List getTrainingSessionsForDayAndTime(DayOfWeek dayOfWeek, TimeOfDay timeOfDay) { + if (dayOfWeek == null || timeOfDay == null) { + return new ArrayList<>(); + } + + Map> timeMap = byDayAndTime.get(dayOfWeek); + List result = timeMap.get(timeOfDay); + + if (result == null) { + return new ArrayList<>(); + } + return result; } - public /* непонятно, что возвращать */ getTrainingSessionsForDayAndTime(DayOfWeek dayOfWeek, TimeOfDay timeOfDay) { - //как реализовать, тоже непонятно, но сложность должна быть О(1) + // Теперь без перебора всех тренировок: берём готовую статистику + public List getCountByCoaches() { + List result = new ArrayList<>(); + + for (Coach coach : coachesCounter.keySet()) { + result.add(new CounterOfTrainings(coach, coachesCounter.get(coach))); + } + + // сортировка по убыванию количества + Collections.sort(result, new Comparator() { + @Override + public int compare(CounterOfTrainings a, CounterOfTrainings b) { + return b.getCount() - a.getCount(); + } + }); + + return result; + } + + public static class CounterOfTrainings { + private Coach coach; + private int count; + + public CounterOfTrainings(Coach coach, int count) { + this.coach = coach; + this.count = count; + } + + public Coach getCoach() { + return coach; + } + + public int getCount() { + return count; + } } -} +} \ No newline at end of file diff --git a/test/ru/yandex/practicum/gym/TimetableTest.java b/test/ru/yandex/practicum/gym/TimetableTest.java index e6c5e39..fd90f48 100644 --- a/test/ru/yandex/practicum/gym/TimetableTest.java +++ b/test/ru/yandex/practicum/gym/TimetableTest.java @@ -1,9 +1,10 @@ package ru.yandex.practicum.gym; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.*; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; public class TimetableTest { @@ -13,13 +14,20 @@ void testGetTrainingSessionsForDaySingleSession() { Group group = new Group("Акробатика для детей", Age.CHILD, 60); Coach coach = new Coach("Васильев", "Николай", "Сергеевич"); - TrainingSession singleTrainingSession = new TrainingSession(group, coach, - DayOfWeek.MONDAY, new TimeOfDay(13, 0)); + TrainingSession singleTrainingSession = new TrainingSession( + group, coach, DayOfWeek.MONDAY, new TimeOfDay(13, 0) + ); timetable.addNewTrainingSession(singleTrainingSession); - //Проверить, что за понедельник вернулось одно занятие - //Проверить, что за вторник не вернулось занятий + // Проверить, что за понедельник вернулось одно занятие + List mondaySessions = timetable.getTrainingSessionsForDay(DayOfWeek.MONDAY); + assertEquals(1, mondaySessions.size()); + assertSame(singleTrainingSession, mondaySessions.get(0)); + + // Проверить, что за вторник не вернулось занятий + List tuesdaySessions = timetable.getTrainingSessionsForDay(DayOfWeek.TUESDAY); + assertTrue(tuesdaySessions.isEmpty()); } @Test @@ -29,26 +37,40 @@ void testGetTrainingSessionsForDayMultipleSessions() { Coach coach = new Coach("Васильев", "Николай", "Сергеевич"); Group groupAdult = new Group("Акробатика для взрослых", Age.ADULT, 90); - TrainingSession thursdayAdultTrainingSession = new TrainingSession(groupAdult, coach, - DayOfWeek.THURSDAY, new TimeOfDay(20, 0)); - + TrainingSession thursdayAdultTrainingSession = new TrainingSession( + groupAdult, coach, DayOfWeek.THURSDAY, new TimeOfDay(20, 0) + ); timetable.addNewTrainingSession(thursdayAdultTrainingSession); Group groupChild = new Group("Акробатика для детей", Age.CHILD, 60); - TrainingSession mondayChildTrainingSession = new TrainingSession(groupChild, coach, - DayOfWeek.MONDAY, new TimeOfDay(13, 0)); - TrainingSession thursdayChildTrainingSession = new TrainingSession(groupChild, coach, - DayOfWeek.THURSDAY, new TimeOfDay(13, 0)); - TrainingSession saturdayChildTrainingSession = new TrainingSession(groupChild, coach, - DayOfWeek.SATURDAY, new TimeOfDay(10, 0)); + TrainingSession mondayChildTrainingSession = new TrainingSession( + groupChild, coach, DayOfWeek.MONDAY, new TimeOfDay(13, 0) + ); + TrainingSession thursdayChildTrainingSession = new TrainingSession( + groupChild, coach, DayOfWeek.THURSDAY, new TimeOfDay(13, 0) + ); + TrainingSession saturdayChildTrainingSession = new TrainingSession( + groupChild, coach, DayOfWeek.SATURDAY, new TimeOfDay(10, 0) + ); timetable.addNewTrainingSession(mondayChildTrainingSession); timetable.addNewTrainingSession(thursdayChildTrainingSession); timetable.addNewTrainingSession(saturdayChildTrainingSession); // Проверить, что за понедельник вернулось одно занятие + List mondaySessions = timetable.getTrainingSessionsForDay(DayOfWeek.MONDAY); + assertEquals(1, mondaySessions.size()); + assertSame(mondayChildTrainingSession, mondaySessions.get(0)); + // Проверить, что за четверг вернулось два занятия в правильном порядке: сначала в 13:00, потом в 20:00 + List thursdaySessions = timetable.getTrainingSessionsForDay(DayOfWeek.THURSDAY); + assertEquals(2, thursdaySessions.size()); + assertSame(thursdayChildTrainingSession, thursdaySessions.get(0)); // 13:00 + assertSame(thursdayAdultTrainingSession, thursdaySessions.get(1)); // 20:00 + // Проверить, что за вторник не вернулось занятий + List tuesdaySessions = timetable.getTrainingSessionsForDay(DayOfWeek.TUESDAY); + assertTrue(tuesdaySessions.isEmpty()); } @Test @@ -57,13 +79,80 @@ void testGetTrainingSessionsForDayAndTime() { Group group = new Group("Акробатика для детей", Age.CHILD, 60); Coach coach = new Coach("Васильев", "Николай", "Сергеевич"); - TrainingSession singleTrainingSession = new TrainingSession(group, coach, - DayOfWeek.MONDAY, new TimeOfDay(13, 0)); + TrainingSession singleTrainingSession = new TrainingSession( + group, coach, DayOfWeek.MONDAY, new TimeOfDay(13, 0) + ); timetable.addNewTrainingSession(singleTrainingSession); - //Проверить, что за понедельник в 13:00 вернулось одно занятие - //Проверить, что за понедельник в 14:00 не вернулось занятий + // Проверить, что за понедельник в 13:00 вернулось одно занятие + List at13 = timetable.getTrainingSessionsForDayAndTime( + DayOfWeek.MONDAY, new TimeOfDay(13, 0) + ); + assertEquals(1, at13.size()); + assertSame(singleTrainingSession, at13.get(0)); + + // Проверить, что за понедельник в 14:00 не вернулось занятий + List at14 = timetable.getTrainingSessionsForDayAndTime( + DayOfWeek.MONDAY, new TimeOfDay(14, 0) + ); + assertTrue(at14.isEmpty()); + } + + // -------------------- 3+ теста для getCountByCoaches() -------------------- + + @Test + void testGetCountByCoaches_emptyTimetable_returnsEmptyList() { + Timetable timetable = new Timetable(); + + List result = timetable.getCountByCoaches(); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + void testGetCountByCoaches_singleCoach_multipleTrainings_correctCount() { + Timetable timetable = new Timetable(); + + Coach coach = new Coach("Иванов", "Иван", "Иванович"); + Group group = new Group("Группа", Age.ADULT, 60); + + timetable.addNewTrainingSession(new TrainingSession(group, coach, DayOfWeek.MONDAY, new TimeOfDay(10, 0))); + timetable.addNewTrainingSession(new TrainingSession(group, coach, DayOfWeek.TUESDAY, new TimeOfDay(10, 0))); + timetable.addNewTrainingSession(new TrainingSession(group, coach, DayOfWeek.WEDNESDAY, new TimeOfDay(10, 0))); + + List result = timetable.getCountByCoaches(); + + assertEquals(1, result.size()); + assertEquals(coach, result.get(0).getCoach()); + assertEquals(3, result.get(0).getCount()); } -} + @Test + void testGetCountByCoaches_twoCoaches_sortedByCountDesc() { + Timetable timetable = new Timetable(); + + Coach coachMore = new Coach("Петров", "Пётр", "Петрович"); + Coach coachLess = new Coach("Сидоров", "Сидор", "Сидорович"); + Group group = new Group("Группа", Age.ADULT, 60); + + // coachMore = 3 занятия + timetable.addNewTrainingSession(new TrainingSession(group, coachMore, DayOfWeek.MONDAY, new TimeOfDay(10, 0))); + timetable.addNewTrainingSession(new TrainingSession(group, coachMore, DayOfWeek.TUESDAY, new TimeOfDay(10, 0))); + timetable.addNewTrainingSession(new TrainingSession(group, coachMore, DayOfWeek.WEDNESDAY, new TimeOfDay(10, 0))); + + // coachLess = 1 занятие + timetable.addNewTrainingSession(new TrainingSession(group, coachLess, DayOfWeek.THURSDAY, new TimeOfDay(10, 0))); + + List result = timetable.getCountByCoaches(); + + assertEquals(2, result.size()); + + assertEquals(coachMore, result.get(0).getCoach()); + assertEquals(3, result.get(0).getCount()); + + assertEquals(coachLess, result.get(1).getCoach()); + assertEquals(1, result.get(1).getCount()); + } +} \ No newline at end of file