From b8567d6e542406635a9fbccd61905c50a26cb013 Mon Sep 17 00:00:00 2001 From: Aknv Date: Thu, 26 Feb 2026 17:19:46 +0300 Subject: [PATCH 1/2] Implement timetable logic and add unit tests --- java-gym-master.iml | 1 + src/ru/yandex/practicum/gym/Coach.java | 43 +++--- src/ru/yandex/practicum/gym/TimeOfDay.java | 27 ++-- src/ru/yandex/practicum/gym/Timetable.java | 125 ++++++++++++++++- .../yandex/practicum/gym/TimetableTest.java | 129 +++++++++++++++--- 5 files changed, 265 insertions(+), 60 deletions(-) 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..8f884b4 100644 --- a/src/ru/yandex/practicum/gym/Timetable.java +++ b/src/ru/yandex/practicum/gym/Timetable.java @@ -4,17 +4,128 @@ public class Timetable { - private /* как это хранить??? */ timetable; + + private Map> dayCache; + + + private Map>> byDayAndTime; + + public Timetable() { + dayCache = new HashMap<>(); + byDayAndTime = 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(); + + if (day == null || time == null) { + return; + } + + + 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> timeMap = byDayAndTime.get(day); + + List sessionsAtTime = timeMap.get(time); + if (sessionsAtTime == null) { + sessionsAtTime = new ArrayList<>(); + timeMap.put(time, sessionsAtTime); + } + sessionsAtTime.add(trainingSession); + } + + + public List getTrainingSessionsForDay(DayOfWeek dayOfWeek) { + if (dayOfWeek == null) { + return new ArrayList<>(); + } + return dayCache.get(dayOfWeek); + } + + + public List getTrainingSessionsForDayAndTime(DayOfWeek dayOfWeek, TimeOfDay timeOfDay) { + if (dayOfWeek == null || timeOfDay == null) { + return new ArrayList<>(); + } + + Map> timeMap = byDayAndTime.get(dayOfWeek); + List list = timeMap.get(timeOfDay); + + if (list == null) { + return new ArrayList<>(); + } + return list; } - public /* непонятно, что возвращать */ getTrainingSessionsForDay(DayOfWeek dayOfWeek) { - //как реализовать, тоже непонятно, но сложность должна быть О(1) + public List getCountByCoaches() { + Map counters = new HashMap<>(); + + for (DayOfWeek day : DayOfWeek.values()) { + List list = dayCache.get(day); + + for (TrainingSession session : list) { + Coach coach = session.getCoach(); + + Integer count = counters.get(coach); + if (count == null) { + counters.put(coach, 1); + } else { + counters.put(coach, count + 1); + } + } + } + + List result = new ArrayList<>(); + for (Coach coach : counters.keySet()) { + result.add(new CounterOfTrainings(coach, counters.get(coach))); + } + + Collections.sort(result, new Comparator() { + @Override + public int compare(CounterOfTrainings a, CounterOfTrainings b) { + return b.getCount() - a.getCount(); + } + }); + + return result; } - public /* непонятно, что возвращать */ getTrainingSessionsForDayAndTime(DayOfWeek dayOfWeek, TimeOfDay timeOfDay) { - //как реализовать, тоже непонятно, но сложность должна быть О(1) + 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 From f82f763f2301431f03be1f77b5e9e47457801299 Mon Sep 17 00:00:00 2001 From: Aknv Date: Fri, 27 Feb 2026 12:23:40 +0300 Subject: [PATCH 2/2] Fix coaches counter --- src/ru/yandex/practicum/gym/Timetable.java | 55 +++++++++++----------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/ru/yandex/practicum/gym/Timetable.java b/src/ru/yandex/practicum/gym/Timetable.java index 8f884b4..0229af3 100644 --- a/src/ru/yandex/practicum/gym/Timetable.java +++ b/src/ru/yandex/practicum/gym/Timetable.java @@ -4,15 +4,19 @@ public class 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<>()); @@ -27,16 +31,17 @@ public void addNewTrainingSession(TrainingSession trainingSession) { DayOfWeek day = trainingSession.getDayOfWeek(); TimeOfDay time = trainingSession.getTimeOfDay(); + Coach coach = trainingSession.getCoach(); - if (day == null || time == null) { + 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) { @@ -44,7 +49,7 @@ public int compare(TrainingSession a, TrainingSession b) { } }); - + // Добавление в map день->время->список Map> timeMap = byDayAndTime.get(day); List sessionsAtTime = timeMap.get(time); @@ -53,6 +58,14 @@ public int compare(TrainingSession a, TrainingSession b) { 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); + } } @@ -70,37 +83,23 @@ public List getTrainingSessionsForDayAndTime(DayOfWeek dayOfWee } Map> timeMap = byDayAndTime.get(dayOfWeek); - List list = timeMap.get(timeOfDay); + List result = timeMap.get(timeOfDay); - if (list == null) { + if (result == null) { return new ArrayList<>(); } - return list; + return result; } + // Теперь без перебора всех тренировок: берём готовую статистику public List getCountByCoaches() { - Map counters = new HashMap<>(); - - for (DayOfWeek day : DayOfWeek.values()) { - List list = dayCache.get(day); - - for (TrainingSession session : list) { - Coach coach = session.getCoach(); - - Integer count = counters.get(coach); - if (count == null) { - counters.put(coach, 1); - } else { - counters.put(coach, count + 1); - } - } - } - List result = new ArrayList<>(); - for (Coach coach : counters.keySet()) { - result.add(new CounterOfTrainings(coach, counters.get(coach))); + + 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) {