From 1d24a437b20dc1296ef1b2e52a603bdb88a3d065 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 19 Sep 2025 12:21:31 +0200 Subject: [PATCH 01/40] feat: ignore project files --- .gitignore | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 07b8a75..fd200ba 100644 --- a/.gitignore +++ b/.gitignore @@ -127,7 +127,8 @@ http-client.private.env.json __MACOSX/ .AppleDouble .LSOverride -Icon[ ] +Icon[ +] # Thumbnails ._* @@ -150,3 +151,9 @@ Temporary Items ### Custom rules target +assignment/.classpath +assignment/.project +assignment/.settings/org.eclipse.core.resources.prefs +assignment/.settings/org.eclipse.jdt.apt.core.prefs +assignment/.settings/org.eclipse.jdt.core.prefs +assignment/.settings/org.eclipse.m2e.core.prefs From d8582f3a391cb94841bc36d27d4db3f79f49a031 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 19 Sep 2025 12:51:02 +0200 Subject: [PATCH 02/40] ignore .idea directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fd200ba..738d334 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ cmake-build-*/ # IntelliJ out/ +.idea # mpeltonen/sbt-idea plugin .idea_modules/ From 5b15d4273a7ff9dd4e0f807afa55ca1726212fe1 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:29:12 +0200 Subject: [PATCH 03/40] feat: apdata tests --- .../AppointmentDataTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/AppointmentDataTest.java diff --git a/assignment/src/test/java/appointmentplanner/AppointmentDataTest.java b/assignment/src/test/java/appointmentplanner/AppointmentDataTest.java new file mode 100644 index 0000000..585dcb3 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/AppointmentDataTest.java @@ -0,0 +1,33 @@ +package appointmentplanner; + +import static org.assertj.core.api.Assertions.assertThat; + +import appointmentplanner.api.AppointmentData; +import java.time.Duration; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +public class AppointmentDataTest { + + @ParameterizedTest + @CsvSource({ "56", "-5", "30" }) + void getDurationTest(long duration) { + Duration dur = Duration.ofHours(duration); + + AppointmentData instnace = new AppointmentDataImpl(dur, "smth"); + + assertThat(instnace.duration()).isEqualTo(dur); + } + + @ParameterizedTest + @CsvSource({ "one", "two", "three" }) + void getDescriptionTest(String desc) { + String descString = desc; + + AppointmentData instance = new AppointmentDataImpl( + Duration.ofDays(5), + desc); + + assertThat(instance.description()).isEqualTo(descString); + } +} From 23cee8c83d42b737701d2ba5147d83412702a305 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:29:25 +0200 Subject: [PATCH 04/40] impl: app data --- .../AppointmentDataImpl.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/AppointmentDataImpl.java diff --git a/assignment/src/main/java/appointmentplanner/AppointmentDataImpl.java b/assignment/src/main/java/appointmentplanner/AppointmentDataImpl.java new file mode 100644 index 0000000..ccd5bab --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/AppointmentDataImpl.java @@ -0,0 +1,26 @@ +package appointmentplanner; + +import appointmentplanner.api.AppointmentData; +import java.time.Duration; + +public class AppointmentDataImpl implements AppointmentData { + + private Duration duration; + private String description; + + public AppointmentDataImpl(Duration duration, String description) { + this.duration = duration; + this.description = description; + } + + @Override + public Duration duration() { + return this.duration; + } + + @Override + public String description() { + return this.description; + } + +} From 48f22efbf8836be9a3f345cf84fd038d0e3f39d1 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:29:45 +0200 Subject: [PATCH 05/40] test: ap req --- .../AppointmentRequestImplTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/AppointmentRequestImplTest.java diff --git a/assignment/src/test/java/appointmentplanner/AppointmentRequestImplTest.java b/assignment/src/test/java/appointmentplanner/AppointmentRequestImplTest.java new file mode 100644 index 0000000..73c8670 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/AppointmentRequestImplTest.java @@ -0,0 +1,41 @@ +package appointmentplanner; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; +import java.time.LocalTime; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import appointmentplanner.api.AppointmentData; +import appointmentplanner.api.AppointmentRequest; + +public class AppointmentRequestImplTest { + + private static Stream provideAppointmentRequestArgumnets() { + return Stream.of( + Arguments.of(TestData.AR1, TestData.T09_00, TestData.DATA1), + Arguments.of(TestData.AR2, TestData.T09_30, TestData.DATA2), + Arguments.of(TestData.AR3, TestData.T10_30, TestData.DATA3), + Arguments.of(TestData.AR4, TestData.T10_45, TestData.DATA4), + Arguments.of(TestData.AR5, TestData.T11_10, TestData.DATA5), + Arguments.of(TestData.AR6, TestData.T14_30, TestData.DATA6), + Arguments.of(TestData.AR7, TestData.T16_00, TestData.DATA7)); + } + + @ParameterizedTest + @MethodSource("provideAppointmentRequestArgumnets") + void apReqStartTime_shouldReturnCorrectTimeSetInConstructor(AppointmentRequest testetReq, LocalTime expectedTime) { + assertThat(testetReq.startTime()).isEqualTo(expectedTime); + } + + @ParameterizedTest + @MethodSource("provideAppointmentRequestArgumnets") + void apReqAppData_shouldReturnCorrectAppDataSetInConstructor(AppointmentRequest testReq, LocalTime expectedTime, + AppointmentData data) { + assertThat(testReq.appointmentData()).isEqualTo(data); + } +} From 6256321fc505d80febb94cb77f9d1ad6757eafdb Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:29:59 +0200 Subject: [PATCH 06/40] impl: ap req --- .../AppointmentRequestImpl.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/AppointmentRequestImpl.java diff --git a/assignment/src/main/java/appointmentplanner/AppointmentRequestImpl.java b/assignment/src/main/java/appointmentplanner/AppointmentRequestImpl.java new file mode 100644 index 0000000..ce6d2e5 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/AppointmentRequestImpl.java @@ -0,0 +1,41 @@ +package appointmentplanner; + +import java.time.LocalTime; + +import appointmentplanner.api.AppointmentData; +import appointmentplanner.api.AppointmentRequest; +import appointmentplanner.api.TimePreference; + +public class AppointmentRequestImpl implements AppointmentRequest { + + private AppointmentData data; + private LocalTime startTime; + private TimePreference timePreference; + + public AppointmentRequestImpl(AppointmentData data, LocalTime startTime, TimePreference timePreference) { + this.data = data; + this.startTime = startTime; + this.timePreference = timePreference; + } + + public AppointmentRequestImpl(AppointmentData data, LocalTime startTime) { + this.data = data; + this.startTime = startTime; + } + + @Override + public LocalTime startTime() { + return this.startTime; + } + + @Override + public AppointmentData appointmentData() { + return this.data; + } + + @Override + public TimePreference timePreference() { + return this.timePreference; + } + +} From 388e3b09deade5daf23ca599b6f7b1d154b31baf Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:30:17 +0200 Subject: [PATCH 07/40] feat: test data and utils --- .../java/appointmentplanner/TestData.java | 108 ++++++++++++++++++ .../java/appointmentplanner/TestUtils.java | 10 ++ 2 files changed, 118 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/TestData.java create mode 100644 assignment/src/test/java/appointmentplanner/TestUtils.java diff --git a/assignment/src/test/java/appointmentplanner/TestData.java b/assignment/src/test/java/appointmentplanner/TestData.java new file mode 100644 index 0000000..59b3607 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/TestData.java @@ -0,0 +1,108 @@ +package appointmentplanner; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZoneId; + +import appointmentplanner.api.AbstractAPFactory; +import appointmentplanner.api.AppointmentData; +import appointmentplanner.api.AppointmentRequest; +import appointmentplanner.api.LocalDay; +import appointmentplanner.api.LocalDayPlan; +import appointmentplanner.api.TimePreference; +import net.bytebuddy.asm.Advice.Local; + +public interface TestData { + + static final AbstractAPFactory FAC = ServiceFinder.getFactory(); + static final LocalDay TODAY = new LocalDay(); + + static final LocalTime T08_30 = LocalTime.of(8, 30); + static final LocalTime T09_00 = LocalTime.of(9, 0); + static final LocalTime T09_30 = LocalTime.of(9, 30); + static final LocalTime T10_00 = LocalTime.of(10, 0); + static final LocalTime T10_30 = LocalTime.of(10, 30); + static final LocalTime T10_45 = LocalTime.of(10, 45); + static final LocalTime T11_10 = LocalTime.of(11, 10); + static final LocalTime T14_30 = LocalTime.of(14, 30); + static final LocalTime T15_00 = LocalTime.of(15, 0); + static final LocalTime T15_15 = LocalTime.of(15, 15); + static final LocalTime T15_45 = LocalTime.of(15, 45); + static final LocalTime T16_00 = LocalTime.of(16, 00); + static final LocalTime T17_30 = LocalTime.of(17, 30); + static final LocalTime WORKINGDAY_START = T08_30; + static final LocalTime WORKINGDAY_END = T17_30; + + static final Duration D15 = Duration.ofMinutes(15); + static final Duration D30 = Duration.ofMinutes(30); + static final Duration D80 = Duration.ofMinutes(80); + static final Duration D90 = Duration.ofMinutes(90); + static final Duration D200 = Duration.ofMinutes(200); + + static final AppointmentData DATA1 = FAC.createAppointmentData("app1 30 min @9:00", D30); + static final AppointmentData DATA2 = FAC.createAppointmentData("app2 30 min @9:30", D30); + static final AppointmentData DATA3 = FAC.createAppointmentData("app3 15 min @10:30", D15); + static final AppointmentData DATA4 = FAC.createAppointmentData("app4 15 min @10:45", D15); + static final AppointmentData DATA5 = FAC.createAppointmentData("app5 200 min @11:10", D200); + static final AppointmentData DATA6 = FAC.createAppointmentData("app6 30 min @14:30", D30); + static final AppointmentData DATA7 = FAC.createAppointmentData("app7 90 min @16:00", D90); + + static final AppointmentRequest AR1 = FAC.createAppointmentRequest(DATA1, T09_00, TimePreference.UNSPECIFIED); + static final AppointmentRequest AR2 = FAC.createAppointmentRequest(DATA2, T09_30); + static final AppointmentRequest AR3 = FAC.createAppointmentRequest(DATA3, T10_30); + static final AppointmentRequest AR4 = FAC.createAppointmentRequest(DATA4, T10_45); + static final AppointmentRequest AR5 = FAC.createAppointmentRequest(DATA5, T11_10); + static final AppointmentRequest AR6 = FAC.createAppointmentRequest(DATA6, T14_30); + static final AppointmentRequest AR7 = FAC.createAppointmentRequest(DATA7, T16_00, TimePreference.EARLIEST); + + static LocalDayPlan standardDay() { + LocalDayPlan td = emptyWorkingDay(); + addApps(td, AR1, AR2, AR3, AR4, AR5, AR6, AR7); + return td; + } + + static LocalDayPlan emptyWorkingDay() { + return emptyWorkingDay(WORKINGDAY_START); + } + + static LocalDayPlan emptyWorkingDay(LocalTime startTime) { + return FAC.createLocalDayPlan(TODAY, startTime, WORKINGDAY_END); + } + + static LocalDayPlan addApps(LocalDayPlan dp, AppointmentRequest... app) { + + for (AppointmentRequest ar : app) { + dp.addAppointment(ar.appointmentData(), ar.startTime(), ar.timePreference()); + } + return dp; + } + + static LocalDayPlan dayPlanFactory(String startTime, String endTime) { + return FAC.createLocalDayPlan(TODAY, LocalTime.parse(startTime), LocalTime.parse(endTime)); + } + + static LocalDayPlan dayPlanFactory(LocalDay day, String startTime, String endTime) { + return FAC.createLocalDayPlan(day, LocalTime.parse(startTime), LocalTime.parse(endTime)); + } + + static final AppointmentData APD1 = appointmentDataFactory(30, "Some app1"); + static final AppointmentData APD2 = appointmentDataFactory(30, "Some app2"); + static final AppointmentData APD3 = appointmentDataFactory(15, "Some app3"); + static final AppointmentData APD4 = appointmentDataFactory(15, "Some app4"); + static final AppointmentData APD5 = appointmentDataFactory(200, "Some app5"); + static final AppointmentData APD6 = appointmentDataFactory(30, "Some app6"); + static final AppointmentData APD7 = appointmentDataFactory(90, "Some app7"); + + static final Instant T13_10 = TODAY.at(13, 10); + + static AppointmentData appointmentDataFactory(int duration, String someApp) { + return FAC.createAppointmentData(someApp, Duration.ofMinutes(duration)); + } + + static LocalDayPlan createStandardDay(LocalDate at) { + LocalDay ld = new LocalDay(ZoneId.systemDefault(), at); + return FAC.createLocalDayPlan(ld, ld.at(8, 30), ld.at(17, 30)); + } +} diff --git a/assignment/src/test/java/appointmentplanner/TestUtils.java b/assignment/src/test/java/appointmentplanner/TestUtils.java new file mode 100644 index 0000000..0a45a12 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/TestUtils.java @@ -0,0 +1,10 @@ +package appointmentplanner; + +import java.time.Duration; + +public class TestUtils { + + public static Duration makeDuration(String durationString) { + return Duration.ofHours(Long.parseLong(durationString)); + } +} From 6fa9235188e3b5a8a31e9751ebd87fc24402338c Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:30:23 +0200 Subject: [PATCH 08/40] test: ap factory --- .../AppointmentFactoryTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/AppointmentFactoryTest.java diff --git a/assignment/src/test/java/appointmentplanner/AppointmentFactoryTest.java b/assignment/src/test/java/appointmentplanner/AppointmentFactoryTest.java new file mode 100644 index 0000000..c801d14 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/AppointmentFactoryTest.java @@ -0,0 +1,76 @@ +package appointmentplanner; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalTime; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import appointmentplanner.api.AppointmentData; +import appointmentplanner.api.LocalDay; +import appointmentplanner.api.LocalDayPlan; +import appointmentplanner.api.TimePreference; + +public class AppointmentFactoryTest { + + private static APFactory factory = new APFactory(); + + static Stream localDayPlanProvider() { + return Stream.of( + Arguments.of(TestData.TODAY, Instant.parse("2025-10-13T08:00:00Z"), Instant.parse("2025-10-13T12:00:00Z")), + Arguments.of(TestData.TODAY, Instant.parse("2025-10-14T09:00:00Z"), Instant.parse("2025-10-14T11:00:00Z")), + Arguments.of(TestData.TODAY, Instant.parse("2025-10-15T10:00:00Z"), Instant.parse("2025-10-15T14:00:00Z"))); + } + + // @ParameterizedTest + // @MethodSource("localDayPlanProvider") + void testCreateLocalDayPlan_shouldCreateSccessfully(LocalDay localDay, Instant start, Instant end) { + LocalDayPlan plan = factory.createLocalDayPlan(localDay, start, end); + + assertThat(plan.day()).isEqualTo(localDay); + assertThat(plan.startOfDay()).isEqualTo(start); + assertThat(plan.endOfDay()).isEqualTo(end); + } + + static Stream appointmentDataProvider() { + return Stream.of( + Arguments.of("Meeting with team", TestData.D30), + Arguments.of("Doctor's appointment", TestData.D15), + Arguments.of("Project discussion", TestData.D90)); + } + + @ParameterizedTest + @MethodSource("appointmentDataProvider") + void testCreateAppintmentData_shouldCreateSuccessfully(String description, Duration duration) { + var appData = factory.createAppointmentData(description, duration); + + assertThat(appData.description()).isEqualTo(description); + assertThat(appData.duration()).isEqualTo(duration); + } + + static Stream appointmentRequestProvider() { + return Stream.of( + Arguments.of(factory.createAppointmentData("Meeting with team", TestData.D30), TestData.T09_00, + TimePreference.UNSPECIFIED), + Arguments.of(factory.createAppointmentData("Doctor's appointment", TestData.D15), TestData.T10_30, + TimePreference.EARLIEST), + Arguments.of(factory.createAppointmentData("Project discussion", TestData.D90), TestData.T16_00, + TimePreference.LATEST)); + } + + @ParameterizedTest + @MethodSource("appointmentRequestProvider") + void testCreateAppointmentRequest_shouldCreateSuccessfully(AppointmentData appData, + LocalTime prefStart, TimePreference timePref) { + var appRequest = factory.createAppointmentRequest(appData, prefStart, timePref); + + assertThat(appRequest.appointmentData()).isEqualTo(appData); + assertThat(appRequest.startTime()).isEqualTo(prefStart); + assertThat(appRequest.timePreference()).isEqualTo(timePref); + } + +} From 43ac0c2431b94f91eec11d07ac8af2cc78c8899c Mon Sep 17 00:00:00 2001 From: = Date: Tue, 14 Oct 2025 11:30:28 +0200 Subject: [PATCH 09/40] impl: ap factory --- .../java/appointmentplanner/APFactory.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/APFactory.java b/assignment/src/main/java/appointmentplanner/APFactory.java index aacf881..5dd1f71 100644 --- a/assignment/src/main/java/appointmentplanner/APFactory.java +++ b/assignment/src/main/java/appointmentplanner/APFactory.java @@ -20,27 +20,26 @@ import java.time.LocalTime; */ public class APFactory implements AbstractAPFactory { - /** - * Creates a factory. - */ - public APFactory() { - } + /** + * Creates a factory. + */ + public APFactory() { + } - @Override - public LocalDayPlan createLocalDayPlan(LocalDay day, Instant start, Instant end) { - //TODO Return an instance of your class that implements LocalDayPlan - return null; - } + @Override + public LocalDayPlan createLocalDayPlan(LocalDay day, Instant start, Instant end) { + // TODO Return an instance of your class that implements LocalDayPlan + return null; + } - @Override - public AppointmentData createAppointmentData(String description, Duration duration) { - //TODO Return an instance of your class that implements AppointmentData - return null; - } + @Override + public AppointmentData createAppointmentData(String description, Duration duration) { + return new AppointmentDataImpl(duration, description); + } - @Override - public AppointmentRequest createAppointmentRequest(AppointmentData appData, LocalTime prefStart, TimePreference fallBack) { - //TODO Return an instance of your class that implements AppointmentRequest - return null; - } + @Override + public AppointmentRequest createAppointmentRequest(AppointmentData appData, LocalTime prefStart, + TimePreference fallBack) { + return new AppointmentRequestImpl(appData, prefStart, fallBack); + } } From c567314f69ba4105a390b9ce311c68c72924b3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Tue, 14 Oct 2025 12:32:33 +0200 Subject: [PATCH 10/40] test: localDP constructor and getters --- .../appointmentplanner/LocalDayPlanImpl.java | 109 ++++++++++++++++++ .../appointmentplanner/LocalDayPlanTest.java | 42 +++++++ 2 files changed, 151 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java create mode 100644 assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java diff --git a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java new file mode 100644 index 0000000..4604dac --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java @@ -0,0 +1,109 @@ +package appointmentplanner; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalTime; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import appointmentplanner.api.Appointment; +import appointmentplanner.api.AppointmentData; +import appointmentplanner.api.AppointmentRequest; +import appointmentplanner.api.LocalDay; +import appointmentplanner.api.LocalDayPlan; +import appointmentplanner.api.TimePreference; +import appointmentplanner.api.TimeSlot; + +public class LocalDayPlanImpl implements LocalDayPlan { + + public LocalDayPlanImpl(LocalDay day, Instant startOfDay, Instant endOfDay) { + throw new UnsupportedOperationException("Unimplemented constructor 'LocalDayPlanImpl'"); + } + + @Override + public LocalDay day() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'day'"); + } + + @Override + public Instant startOfDay() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'startOfDay'"); + } + + @Override + public Instant endOfDay() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'endOfDay'"); + } + + @Override + public Optional addAppointment(AppointmentData appointmentData, LocalTime start, + TimePreference fallback) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'addAppointment'"); + } + + @Override + public Optional addAppointment(AppointmentData appointmentData, LocalTime startTime) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'addAppointment'"); + } + + @Override + public Optional addAppointment(AppointmentData appointmentData, TimePreference preference) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'addAppointment'"); + } + + @Override + public AppointmentRequest removeAppointment(Appointment appointment) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'removeAppointment'"); + } + + @Override + public List removeAppointments(Predicate filter) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'removeAppointments'"); + } + + @Override + public List appointments() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'appointments'"); + } + + @Override + public List findMatchingFreeSlotsOfDuration(Duration duration, List plans) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'findMatchingFreeSlotsOfDuration'"); + } + + @Override + public List findGapsFitting(Duration duration) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'findGapsFitting'"); + } + + @Override + public List findAppointments(Predicate filter) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'findAppointments'"); + } + + @Override + public boolean contains(Appointment appointment) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'contains'"); + } + + @Override + public int nrOfAppointments() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'nrOfAppointments'"); + } + +} diff --git a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java new file mode 100644 index 0000000..ad87913 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java @@ -0,0 +1,42 @@ +package appointmentplanner; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Instant; +import java.time.LocalTime; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import appointmentplanner.api.LocalDay; +import appointmentplanner.api.LocalDayPlan; + +public class LocalDayPlanTest { + + private static Stream provideLocalDPDataset() { + return Stream.of( + Arguments.of(new LocalDay(), Instant.parse("2023-01-01T08:30:00Z"), Instant.parse("2023-01-01T17:30:00Z")), + Arguments.of(new LocalDay(), Instant.parse("2023-06-15T09:00:00Z"), Instant.parse("2023-06-15T18:00:00Z")), + Arguments.of(new LocalDay(), Instant.parse("2024-12-31T07:00:00Z"), Instant.parse("2024-12-31T16:00:00Z"))); + } + + @ParameterizedTest + @MethodSource("provideLocalDPDataset") + void ldPlanInit_shouldBeSuccessful(LocalDay day, Instant start, Instant end) { + LocalDayPlan plan = new LocalDayPlanImpl(day, start, end); + assertThat(plan).isNotNull(); + } + + @ParameterizedTest + @MethodSource("provideLocalDPDataset") + void ldPlanGetters_shouldReturnSetValues(LocalDay day, Instant start, Instant end) { + LocalDayPlan plan = new LocalDayPlanImpl(day, start, end); + + assertThat(plan.day()).isEqualTo(day); + assertThat(plan.startOfDay()).isEqualTo(start); + assertThat(plan.endOfDay()).isEqualTo(end); + } + +} From d10e8b12846e8668e824b42c963a825016570782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:07:16 +0200 Subject: [PATCH 11/40] extra: notes --- Excalidraw/LinkedListSchema.excalidraw.md | 144 ++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 Excalidraw/LinkedListSchema.excalidraw.md diff --git a/Excalidraw/LinkedListSchema.excalidraw.md b/Excalidraw/LinkedListSchema.excalidraw.md new file mode 100644 index 0000000..505701b --- /dev/null +++ b/Excalidraw/LinkedListSchema.excalidraw.md @@ -0,0 +1,144 @@ +--- + +excalidraw-plugin: parsed +tags: [excalidraw] + +--- +==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: 'Decompress current Excalidraw file'. For more info check in plugin settings under 'Saving' + + +# Excalidraw Data + +## Text Elements +CustomListList ^P7Hc0rRT + +T add(T element) ^ilmdVsfP + +head: Node = default null ^tPykSiIW + +head is null ^Ml0BvnOF + +new node with element ^cOy0ATvK + +head is new node ^2wxZhqIw + +head.next is new node ^B0QMOJrU + +int size() ^l8GER5ik + +recursion (count, element) ^imgFdzPB + +element has next ^2e5NuXLN + + return call(count++) ^ER1bqK84 + +return count ^plS5EIIg + +head is null ^v4SnCGRz + +return 0 ^Vapvn56m + +%% +## Drawing +```compressed-json +N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATLZMzYBXUtiRoIACyhQ4zZAHoFAc0JRJQgEYA6bGwC2CgF7N6hbEcK4OCtptbErHALRY8RMpWdx8Q1TdIEfARcZgRmBShcZQUebQBGADYEmjoghH0EDihmbgBtcDBQMBKIEm4IAAUAdgAJbAAGUgAlABVUkshYRAqoLCgO0sxuZx5q6u1E6viAFh4ADniATkSe + +Oer+UpgRgFYZ5OqVmZ2dgGZqvfmZmc3IChJ1blOG+YSp6rXEhqXzndupBCEZTSbg7OLjHgvHbzMEzGFLeb/azKYLcBr/ZhQUhsADWCAAwmx8GxSBUAMTxBCUymDSCaXDYHHKbFCDjEQnE0kSLHWZhwXCBbK0iAAM0I+HwAGVYKiJIIPMLMdi8QB1B6Sbh8QoCLG4hDSmCy9Dy8r/FnAjjhXJoeL/Nj87BqbY2hro7UQZnCOAASWI1tQeQAuv8ReR + +Mr7uBwhBL/oQ2VgKrgGsKWWzLcx/VGY+6wghiNxEtCGmDqjNbe7GCx2FwbTxEv9K6xOAA5ThibjxBpfaqnebzMax5gAEXSfXzaBFBDC/00wjZAFFgplsv6g/8hHBiLgxx3ql9EvE9vsTm7OhAiBwcZHo/h/sTGXnuJP8NP3X1MAMJPihJiDAAZQhMQAzEU0oVp+gqb9f30YCoFg4URU4KBJUIIxxFQOZtB4eI90SeY8OWPtqkRd1EOyAAxXB9HFZ + +1UD+N9+gAQSIZQa3QYIRQGBsmCgcwCGYoE2Oge1hT0bJcDjJgIzQLNb3dEkgTjAhwI/SCfygf9ALgrThVwIQNOacJUPQrEhAQO9JNqQFgU/VB4iwnZCgAX02YpSnKCRxX0YgADVmBFSphW6dDoAg/5hjQZwPjiBZriWBpiPieI+yWf5aNGPdtCLRJ4uPU4ZnOf57mIR4bVLbQywRL55lOBECouf5JGskE0B4eiz2RI1T1KJU9Q5ElyWpKkkBnBkm + +VTdkiQG7lyA4PkBSyLjSPFKUZRCk18wxXVVXVTUtuVfU1oqDaU2EC0rQ7O0HSdDtXX+T0N19Vdg1IsMEGk1BZNjeMIvQXB4lO1liHTTMbwxBBHxdJYe0hLtUorJgmzY4juKrFs23QpIGgKpYeFOHYNndQCR2CHcJyncz3VnIHFwyRbnvXTdt0huy9y7Q8rmePsLMva9szPe88XHVBn1fM931siBWlQXBiGIAAKaX0mXKAAEpQIoFTJel2WFaVpdF + +vVkMkJQtDNW6yAyKgSjqPwWj2tKCWBNYioOKWs9K149xnaEjS4FEpCJMtUgPq++TSEUjhlIgiQdblxXUGVw3dP0thDNYM20FMymBcs5rbPstrnNconhegSoYBxFDvRVIL4BCiXhV+5wkiWSYPh7A95guSFTjSkY4WSYs6w+U4FhymYGj791itK3hMIuBEksn+JTimLUzyaoEWt4B3IE69CLYgXq8X6rl0ApYaaVGxkHrZM/elm+bBXd0oxQlA0jW + +PolTRzbaEDVCVDUrV9p6k/utH+m13TmkkCDS68lrqwFukfB6Po/T5BemeUMVF3rCzDmeOMxAEwSFwDwQGaYLoyTBjmCGwslgExeNhVGSNbrww9ojasrYODtjQD8GYKw9w7DYe5Yco4WaixzqUamC4DYrgwYzLcZNWb7kPPw3KNx3QXivFQ/mpRBbiIpv8RuEgmqyzQK2IhqAAC8qAiGTmjFAT6N4NZawqKY4g5i2CWJsXYvS+BHGyQQibYy5tjYU + +SojRUERimIsSEm7YUns+L4B9r0ES/wxJREkiHPB1CzwKX8NHVSJiQgeNQBYhA1jbEIHsf4pxEoU4GSMpnVA2ceYICstvAuDli6FDcpADy6AAD6Ox3oAGlmgAFlCDkAAIrNCHIkAA8gADXxEYHyuAhx1x6CQ0g2IqDhRGIkA82gYR7DBAlVeeE94QHSnjOIXxTidk7HWXsDQkhFV2mgBopycIE1xqsOsJwzj1ndFvGy3BMI7FmPEbCiRzjzASnCJE + +HAUSH1AafKa58ICXyGsKekt8JoPxmryfkL8EIrXAcdSBip/6ALnhvHq/8qVyhpWaM6sDKF2SugyG6LoUEsjQQzV6ODQ65Pcj9RMpxyHAy5X0ro9dNTahcjQlmyxiK9n2KvZh1YOzT3YWjDgXCeF2XeUsZYSxJ76pESTBASiJEzjnMQWmKthVng3IotVbMDwnkLOanm2i6lyQFmwB8wsHXujgGwOMOR8jajAAUToJQLbJvjZgzoiak3OB+YsC4hw6 + +w8CBScNetwShQphXChFSL5hpu1OmyA+BQhQEJPoaiMg8yVGjUKHRwamUCigAAIUIXGZQfNe2QCyMQIdbIR1jq2v2xiey2AUHcXO90k7F37NXbs/ZwogizgoAYl8CAeklD6WUMuEz8ANAHfQDgizyLbIbmFd0zccoTH7PMH4KwkrFg+e6dKhZfk5SebCbCaxyxnlnsA01ExzVLFxslBqYL86ahuQfNEGKCRYsGlfEaVMxp30mpyR+pKFpChDJSo6r + +KFRYfpTBxlOoDosuNGy6BHK4E2h5Y6JB/L7qCqevIkV4Ycm6P6ZKkhMwZWcaDeDFmeEp5w2EZARsuqbSnGtSpjh6NuGYxwgIyEyGCGiNJkesWUinUuvpnGpN8r+llwQEYAA4pUTAzhMCaFqJKFUmBBl/n0EOfQ2BJSYCvKWhVOy/pLqoPGpydaFHM2FjhFRJxEX8JuVotdIaw1PkMQxIp6B3GoEAkGlxMdCslOK8wUrYTkIhNakfK2NtIloBuU7W + +Jrtqmvy06QL2/EOvcjSe6DJQcpKifHRAfJSl8CuOKbLKrNX3R6UaRnEypAzJtI6RCm03SSgqrPaXCojmXNuY815nzfmAtBZC2Ft8iqd3LqbrsH4WENM5VmO895Ux+6RSeZMPCYxsZXB7CDz5QCCw7AqgePGNUyzLDhITTeqHWpwe7mvBYuNqh/oJiitFmG/4HWJRfIa18COEqdUT6AT8yWLQpR/ajrHaME71PRvazO8Qse/kzs8MCZOQdKPaXlvH + +TUCq9IJtAa5hO4KyxKohv0IC4B2NJuV8boD3d4MquTSWC3Y07jc1TnAOxXB1Tpk1Yx8Y9injc4mYjw15bPNI51sjY0S/rRAD1iXdwpaLPwxHei4yBvwXo0NQtcvHv+FGmNq542Zs6CmsADQ02ltjyUIDWqYf5SSpa7u4WxjaARJ3DHgPoUE1rZ0N3jbMQtrbWOTtMaZc6n7dOxwqLuDyowM7j6EAr03rvQ+2kltQ0/nx0mj0uB/a8ISIPA8U9LUX + +CnjMTX662TN9nT2+dvXN3Lu3bJ5fxAt8rpKYmaLe78AHrMyevbJcCFl2wIsmADRGKtHoKMp9vQX1nmbnuV4H2LgHkLERIxrciMFjJMDsNDkIjMFjqvCcGDgymCJMHDqvAsLCjcuCjvDwG3C8MRCsE8sgXuFAbjl1FhpTrisNPioRkSjhiSnNDThRstPToaBAtzkygdKziAuzodEwdSiwZALzlyvzpAILjxrRJ2KLo9Ogq7iGG9GKmJmUBJn9IkMr + +hmA3sfLQmhsWB8JzCbmxMlEfAbkahjJCnMPwkhn7v0iZnahfo6jTM7tHrZvGvZhUM4K0M0H+GwPOJKAAFb6DMAwA+SkCjJnZOZQCMTVAD4RYhQCi7qxbxbuge5KLJbsypYwj9gBqqH6J27h75aSyWgUCfReIVL3DqCJzO5lYFYQB5EFGWLFGSClF0z0FYLBLNJ4xYRY5PJY78Jdjga1bNZ2xRI5EpISDxKox9bJIDboB+wBziRZKyETZTZRwzbla + +VEID5EcCFGoC1H1EqwNJpxNJrYbaaJ5ydIdi7ZgD7ZFCHYSAuFuEeHeG+H+GBHBGhHhFGLq4K4n6HKRTHITAEwwhwwJSFofA/aoAtw4TaBjzXBtTYwTxdiaYQDQagjaCjzFhwj4ypGJBQFoHI6oB/Z9gnDmqFo1TAqFhEHoqcGkEk74YO6UEU7UGTHU7kbdaihUbcE0a/xngnwAJfK8BYac4nTsp+CcoqFcYIJC6iF3TuioLi4Bhu7YIiaqGELEJ + +/RbKCkUIimoDt7BRKqdAXECDqFoAW7wjvLwkGGhIIyGrGqYzXD8KQjHDwk26mZZHmZ0iWZ2FCbupMyJHeqHjQipFAGZbr6aIh7WGRpdou4Bgx6OHx6J5Jr1oJqOGQ4omXDonQiYlGZJp4lnKEkLD4wnCFhl4lAV5NrV5qC17hmqGYhN7Dqt5oDt5JzZBd534P5P4v4D6ihD7+g/JrCuhiGQhTDJbHKgqj7KDj4dgzBYQFRpZ+mlhgjwpL5niTqr6 + +1m76clRCb7RY75B4TpsgH474fG7r/D7rLoX6nqXE34VA8AUCYAABakgAAjt6AcndpFqFKpF8aCdCBOclHsIWoeAeAVPCaIfZDCM8AiLVM8gsDcoiTaEBvBvhC8LVJzBmZAOgbZG1GSSPqwX1PSTilSRQeTkDJTjyLQUyXTqtGyYzhydhTtODhwWucxgzlztRXwRxgIdxnyiLvxmLpIbKdIaKuNt9HLomPOMoaDHIbmMLIsMcCcJCPrtpmxHMDoVa + +U8OAV2IWAlIOLavavbhZrYQ0RGZLp6Z6klj6WpcsDsEfIGaucHjluTNkeLMsUViVlUesUQuUZLM5dVq5YUUEtkKbOhJCL0REv0a1tEh+EMexF1gkjxEkpFcJP7OkoHLMYJeHJHIUp5ZVi5asdUdSaUMtnsattwK0kcZaFtjvIXI5Ffr0lcegPMFYPiJgTMksAAKqkCVAig8CVA3qDLNCJDNiShv4PbPmf5HLmpYR9jPAnCwqY43J3KnAQkNALDfB + +9iYnYw/BwEwZwivbTAEGdzHLJSNQ4n8KnKjz5QIaLDQyYGYXfIkG4VkGk40mEX3y4UkXPy06UaMFfwCmcHsG8mcH8lsY85sUamCGTaIISniFCoelvwyGpUEIKEK6Ppqmyoalanq48ALk9QGmmrYSwrjCLA6GagkQGpIwqVlRlh4wHgaZaW25h4ukQCO5WZyJSHxFeleopb/6LzpFBnZah72UM2R4s2RlJop4J7haxnl7J6OHODbV4y7XplrwHUk1 + +JonXdx4znVLxXVLCFlgDFlV4GA14doVm819q9bLmjqm07lTo1mW02WN4blbpH5W0YC7mbnO1RaHnrpn4nnOmX7nHX7uRlwDoNAzITKLIABSpALVQ1kxH+QwIwVwWBiwnYTyzwOE+wIJUBpyQK8IzwOU3Ym1moh4WUSFzyiKxyk8w5pQaFaGN1qAR8XJlJeGBF40dJJGNB71jRb8rJ31QNNF3JdF/1DFYCTFP1wNQpfOHFwuYh3FEhbqsNAlipiNu + +ATmYllZON+MeEXw0K5hDAClBYe9Bh5NdkkB8UFwX6tNTp9Nkirp+lrqMNkACRHNyRSdVwYN1l2554IZft4VmVss2gloH4C2Pl7lZoYETlJSgD/QIDOVbleVg+/l9WvAjWSEfR9sf98VIxFpYx8VUxSVMxwccxdoEcBSSxFR7i0DwD2VaxvlSIqc6cyDJVucZVOJlVZ556Ay548wTm84zQOwhAt24s7xjcH5owOaPYTy2M0136PYIJow41+wfYCU8 + +Ulq4FRdaAX6r2CIVUiwa1qwR1JxrU6GqKxBFJ91+FN8bdRFr1jJ5Kn1FFfdvBx8dKPJQBXJgNzj/BoN09kNc90NrNWCcNy9wlJCEd69LtklRuxY8KIGppB9aAZYylRhmj/YCGzyymZQlhOlDlelMiBl9hnQdmF6FQtQMAmggy8Qzg5Eiy7SbAygQgkoTmEdssQgEdEyERaur50Rj2sRUtbNJlXu7M0w/CUw1dDaAeGRP9N9f9FQMaqAq28sRs0CE + +DFR8zizyzTRSDLRqD4StsGDgxEx540VoxcVRz+Dw2yVRD8NAupD02s26A6zxkSzuxjDzSzD/urDRjdkZxFxnDZce4A62A0gOImAKo+IA6LVqEiQjE95+A2ArQAAmrHQeY9mI2WBCfjbjO8slGPF9vI0kK8DVMsD+QXXhP6jPG48kEkG1GvLVGsCsOairahTif2FlBcJZZcH2LiyY3jrdeYx3cTi3VY0RsRXYx9QwY48wSxS42wW43yWPf3axZPex + +WKSIcgv4zKUZYvQqS7UqfLrgK/ijTJujZFpjbqVrtwPhNvYsDTRaSwijvE5aSk3ZPlFbnMMsFfVYb/VTG6QU6oc/aZSotMKo+8jzfbd/XZSLLpZAELYZVGUmuLdGUngm0mnWG8LS/CrjKM0y+FmywTCeFy4sMSbrfrc2obWWcbfXpE+uYOrbW3qrg2VAF3vQDMJKBwPiE5s0EYO2YhNgMPt8vnscr2DVPmmMLMPlKWmPhPqgG3BpjVJge8iXnjea + +9VYuSvvWzWwuu7bLKoRuju2XD0yNaUMeYen7Rw7VWUPoMoORMQEYJUAOii6I6+iAavA5NDFMN8FnlcOM8AZFD2PnpjhBko1MHsBo7wOCdcIcKB5gZgXhMywCN89hMiXB2k5ZT8MRLy2YyPZioK3hcK2TtYy9Xh29XQcye/FKzwTK1yX9e48yoq14yDf6GDcIZxbPVKQJrxdq5bME3qyvX+BExG1E5o0tfjDCkTYk9DMk7pl7uMG6zCF6zkwzUze6 + +RLvGsU1w4QDwFAPMPQJUDsGwFACKJIIshMviDMtUGwEYJKH+CKJ09qcNRAH00WQlt6cG9hGvPhOG1/ZkTMzkRUIEP24aqgPLHoKyFANQNscnOA5rMsYFyIEjCF2F9kJF025s2/M0ZjBML2OcPsGvAlJZQsMFfswMY5RFUc9gwarg+c0NmeCNilaoQsRlQFwgEF4l6F3OBF1F9kOl/vAw/scVetrfeeMcdtj80XGu+eUHXM9p7p/p4Z8Z6Z+Z5Z9Z + +7Zyi0e09t8QkOAZNT2NcLMPLfIwVMiXMJgbMAVNjGBeBwtYDh0etd0WIdid88dxpjhK6PFK6JbvCRhvyzh9hnhw9Qg4zbSTYyR+K93ZbL3dK1An97Rwq5RcxTD6UN48x74xqxxzxQvTx0vXx6E39M2IJ6a4FVjfqSzPjPsLjPFGDWaYk5O/a5wi6zPthB65k46d635w7n6w/S7YG0MweCG98GG6VYHuKg2tMwLcN3G4UyUGLTGSm6LY4Td+0W910 + +asI9+Fi93d4L5988KcKW3eCWRW+2sQHXt2kJ7WxbQ26Pk213oQNe7e/e4+1O32wOw3doEtYsOcqWBplNdDMy5AKOTO68BcqWNDGCKtV8DrRa3vpb1u47dvh7V/fu07bu450eT7WezfRexeRIDwAgDsM2EIMsn+AT28a+c+6Nf+z8rOZiechpqo0AaIQtXCP2OAeaicDjOB0kJDpVAhTVHVL8IY2NxhUtqY+SX983XiiK1QWD2RvY5K549R640PXR + +4xQj+Pcj0x/AnkhDej2eNKVx3KbxxG/q4mIsoJ1/cJ7icWNCvVJkzT7wHhNJyaklBzFAYlIp6GZz/fdZmpw4YmyUwkAIByI3oSUORBmBOYEA9TVoJUD/AIB6A8QQZJoAfICdwsXTKIifliyloNOZcZwF4X6r0AfIcANtveWWTOAI6QgZwDiG9D4BRkzgZoPZ3eIbdnOetVzi/X57LBh4mTT+qL0jb81o2uTLoMsSbaoBJAoQT6PHT4KrNJYIgsQd + +5UkEdltmgVXZtbBCoHMyuoRCricxwZnNBIqSRKpc0IZjZGudzRYg8w7wGVRB4goBsyQKpvMDiw3C8O0jYa/NA6ThIASALAEQCoBygGAXAIQFICUB63T4i+0SaQ58YXYb4MRGJaTxM6AGYwllHAJ1g+wejN1nWGu6Q5fS8UfsOMDLAE0h+O8PYMiQJqdgCY+mKeAhx+4N07qAPSxoR1Fa2M5+ErLBFDyo5I8mMLOeVgDQY4ysUe2/AXLvz4wY956j + +9UUMfy/qn8SEMyQnqrgc4a5o+nJHGnJW5Y0tqeCTDCEk3p6m50InLIRDl2tzZMv+eTJ3P6x57s0g2wzTgVT2868DfOEvCPOGWl4JlE2cvOMtLUTb4xtuQiRhLkJwgoxEyE5cYIlE0LlDew+vTRIb1bSVsTeJtc3tWRnQrl6yneMuHnwL5F8S+vbTsiMG7JK1oSUwJlgTAKhTtA+BYd3gpizzHJBeqBKqpN2tqx84R8fQ/KnwjbJ8E+zI1FsewnQZ + +9Tyk3f5hUB8CSgdg84b0N6FHRl9n075UIaCWWDJBCwUFZKKd37BKV4htYCcviKngAE14+ZX9jBTsjIdoYBeLUdFELC/ta6xjeuo3X/iT9yC0/dutNAZJNCIeLJL6tD1pRysV+8PJxr0K36ikd+4pPfqUAP5Y8xhOPE/ivRmQ+QL+vAq/oeB7CwpvgtUCTriSK5bDDCMnBrEtSxxLUp4n/H1t/3ybc8+KAzT3GVHc79k9wNwuQncIEEM1jE6AQIFA + +BEAcBUAyXZkuQFi4VEGxTYlsZ1z8p1YdmxXFrHREwZaDOIMVXrLoJdiDYDBdXK5sYJdpNdyGksLsaQGbGtjXmA3LOEN02wuCJuAdGqjn3QB8N4gmge8qMiuBPsFBb6fPKWH2CYEVg+Iw4CCU7CyjcYsHW1tJRTFQY3GCUCqEhWxgJQRmVwDREjiQ5Ydx+A9a0Y9SkQg9iO9oqnI6PI6tD2S7Q2Vp0I9HdD1+SrCAH0N9EDD/RQw/fpx2DHylpcuP + +ZUgrgYHGsuUl/HGslEtT8I4QZwJMWPDWHOt0xp9WfNDATG5iOexw5mhGS/q89Sxlw+KGCG4GTMXa1YiNBoIqCoBUAK4tcQQHwAddwuAAajUm9ccJ0guSQpLtTdj3AKk1sRpK0lWwAq5pLZqoJK5hVDmeg4YtoKq6TjfYtXUoPV2uYmD0qS43SYpJbHKTVJ2QEyRuKKpbjDiLDZwd83Ya8jL2LVY5JoHnDXlagFAecBMh4CSh5g+gSoJoFaANBWgp + +fF8iFCcGbdpRrRBKJcn7A5crgOeFUXZHoSnIXgBUHsgVyHLgcc0fyfNICkLA4xMmZot3rmn+QFoi0IKC0TUPgmA9W6DQ2fqRXn4tCXRbQt0ehIZSejXRgpc6D4zVZsdJSREzHqMNInEMiYK9doNRLRqzCMaJPNQizGOCrAz6TrB1tfyPoKUT6b3M4LVDUS8T7hvrH/sLSEnnC+eOEDzmmUrETZpJMbCAFLxswZpoyEteXhDMTbZpfkeaAFIWk6m1 + +RlMyaeGf1I6nAo144IgWJCKNowjq2ItToHDL6ntSkZewFGaWlakIyBphYYtIkDiJrl4RLeO2knw3YIjWZ0Y2tnuUT68DWRTIm5rGyJAwBlAhuCXtn2m7XF8BzYQgcQMlCkDyBlA6gbQPoHBCvalfUEgB0Ig5ceySGaEFnTbhapbxMlIErCnA4IEx4llDuEnR+A1RTROJTEllCIgcCv03+YaQK1Gl1CnqRHYjPBNI5kUHGi/VCTRy6F/cg5gMVaaj + +3Wkz1NpgY4iTtPGG8DJhf0GOkdP9BE8dStI86cLEK6HAKZ8lQ1JCn/Sk0GeHEnCE8iVEjw3pNY4bip1OERthJyiUSYLwDKSSI2wMwQaDMeHgyZekM5Nm8NTbEyLZ0Ja2Wohy7jNU8E5Gci7I/Y1o4yjMvRHjOhGm9bIl/C3pu01KNtkRl5fPoX2L55TR8LvLssiVQJfZu48KQ4NDHMIB8xyNoQuPsEu5jADRMKPXgsJPbsyWZlZbmQez3Zu0U+h7 + +EIYuW5Hnsoph4hgG2w7Zdse24o9/JKI1my1kg2EfsKBxhBzBoUYNO5FPASBY41gF9OENhBzGUsh6nYODBaiQUoVEOw/cCVhQ6G4dPZBHb2RNL9ng8kJs0lCfNNoqLTMJXo1CbhO5TRy/GwwgJkWKCahiJhK9SMWnI3pqp8aSQQ4JsJLlizWYQBY+i62hTmpShYNNnkp1rlc9f+RMg7AAK4aAtgWUAUFuC0hbQtYW8LJFowO6aYCk0epKbmAofLNB + +RkkgSUD6GWQUCeAcARIDeUYg4QvC5EQZHYowExFHFC8p+j9JEkcCVg7MQGXeHF41zZmc2YgCA2cQxdzBXlRbJZPMkNZBxoVYcbZKnFRUxxpzb2DVxnGuS5x2SDyWQ2yVZVvKmSpbP12CktJtxpVcKWN0in7jDFks9AGUwqZVMamdTBpk0xabEA2mHTGBWnylFvtjw7ybMvQjtm/s7kxyBIDDitntS8I8JXUUfB6nXAh21yS1J8AAmVCx+NCtCXQu + +xRjTbRoPZhYhPIrhy6Mocgei8vYwqs1pfo9VoRLjnbTAmOrMiWGLx4K5a4UiusidLNZnSYxCwUPl+QLm3S8Yz/HYS9JeCFgtFhwvMfxNU4NyYlTcjgaMwrHC8pmUbGSaUDBl/8YZSaV4f0wV4vCNeE5B8fCBMJfBJ4c88vFEvPBLzjeK8r+czLXybzre284Yjwz4YCMhGTRftsfLxjYwgUYnGfGzE0w3yZ28QM6UuQ3lrzt2/83+fvh/lzKgF5+E + +BX0ucWADCs95NxR4q8U+K/FASoJSErVlospRQiScpagJifAchl9aqS3CAzgEsYh4fsl2AQ66jNeb3bXoCWhggSa6x1JMsBN7A2sC6+Md2RPwsYMKYJz1X2din9nTSe6bCqisHOX5cKw5PQ3hT6P4U/KNpUNLVkfzEVJyV6N5GYaPjmGrsTVpPOhF+VUT3TC5hpBDqorLkwk1GB4TFdpSOF30Cx+i76YM1iU4QZRCSklVJOSXkqhZUeHuc8JpVQyB + +59K1WgtVe5ZiPuEa0sBr1jXXB41+EfCLgRpFFkuVlectlCN5WwitV5tDeUiIMotsIFnbbtpiOlXYiKo2ELHOqLhUF4FOquEkbWEmDoqH5mJZnh53VUfzBVj60IvqpZF/y2RAC9WSe2AVZ9QFAyiABsjgB3pwC+gS8XAoTqaMJguuANUkF7CpYCWsKCqPRMYmSMoCyo78UPURSTAUZsq+hMryAI9SR+HUS5b90gmpqp+9Qmfo8qmnNDc1lHdha8ow + +nFqsJjHL5VHIrUxyq1h/firqxBUUTcAuAKMRJSWFww1qU8LtUitM2lyX+5wMYOh2RVEwsVfEsdScMLGTqSxBKv6e92LmfMReVYxdSDLrE4T9Jq4huh5Ra6NigtyYWrPkpQaFL1BjsGJHZLKXMlEklShLQlWmKZJ3JC40wc1wkA+SItrSlbEw06VhTyqXSPcX80va1Bqg95NgNCnnDVBSAXhKADeXIhxh4g+IecJgH8yOrOREAZuOiVLrk8CYWOGE + +DlBBJIz3efpDFdI0WC2bWNc8cAvRrg6qN4UzPbqTiT+xBqcWD4qkfxvyqCbqhHs25V7PTU+yxWTywOSWo4WD0i17yq7StOFIqb8JvyrikIurWabgV4i0FbgGWSNrhG0Kt+W2qtazBiIUBQ8CxKfGpiT6p3VidxurkfNHNAk8ShNkblJF+ehaFAhljbk+dfNncylQYrXVx4N1dK6lUPOSCU1GW3wVbbMFRlgBNt5ImUZH3eR7ir1JOhtDyvLKEyEN + +9ItmTbQ5n8rGRW5PmShoFnH50NXIo1VhpNV8iJA7IciKQGbCF9z+syuOiRsgDNwkoN3IRHuCxwaKEQOOb1Z2AnJrBQM1yOGH+vA4Ic+N1CoTbQv+70LRNjC8TVmpYXPL7tv1N5Xbo+UT1I5/QoQoMNe1bSRhgK7Hlpq+06bkWEKoTjjW7i4R4o32VMcXRRVG5bxyChPcZhHXCwEdjNPRV9N4Go6fS0wH9piUSXBkyVfm5YiFokB9iotQVUiGgzUG + +lc4t5XVLZV1KDJb+sqWi5rOKMF1Kstnk8wUFKK2hTPm3Siqr83ACYIFccAOANKGZhW8ugTUTIBUC3CkBJVDAQgKsQHSwTM15IEUPvoP2DAIAQXF+N6D6D6BpQhOETTaMKDH6RAp+8/dvozXnbJN3dO/XskWhn6MgrWvNYjyP0n7P95+y/QtIYybB39D+jIMAY5zu7XJ9+wAxkGaBlr+c4B+A/oEWQB72OsBj/Y2XP3kQG91k4pVgYgP6A8DSgiyZ + +AAAM4GMgWsLBg5IoNwGqDF+7+TqtNooHGD84EXfuQ25gHKDzbc/QflaDvEJo/+hg3we/1vREDRoIPMfGwDYgJQv23hNMBPmXzcFroK3GAeYCyGiQ+AZFmgB9SYsf0b9Y4P8NKBGA2ABgBfSpgIBmRTihaJ5HjDPJsGxD+gRA0DBkw4SnUR+5kCQFr3dQPQEcYgNKAQAzsHY/hkgBMkKIcHcAmgYINirCO77IVZ4AdESDLikBlA9IeWBbog4bBsjk + +XH5DsC0mGQGmjabFGkYyOyrIuFR3gM8DyNZR1Yjh3g1AYQDoHeInAZHWAdImGR4wEcREcvmiOxHBuI+ig0QBnbZ6o4y+kKcN2EBQBCpkx/4PoAFB4gFdOCQY8NwWNr6mAURmIyzGziOG7AXhVrjkHbbj4IjRCLYwMfen5VsAvERgK0HMP4BLD6A46OkGuO6p0k6kAwIIciw47y9nc0MAYElAvHWjbEJddysxCMRXjtx+42OmcjgB9szo8IG3jixO + +QgAA +``` +%% \ No newline at end of file From 77b859446adf11b25c38d70eb589497b612f67b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:07:31 +0200 Subject: [PATCH 12/40] feat: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 738d334..cfa1d8f 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,4 @@ assignment/.settings/org.eclipse.core.resources.prefs assignment/.settings/org.eclipse.jdt.apt.core.prefs assignment/.settings/org.eclipse.jdt.core.prefs assignment/.settings/org.eclipse.m2e.core.prefs +.obsidian From 9eeaa6ae53c36c3b9258b7d7a517d9e3ae4705ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:08:08 +0200 Subject: [PATCH 13/40] test: linked list node --- .../customlist/CustomListNodeTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/customlist/CustomListNodeTest.java diff --git a/assignment/src/test/java/appointmentplanner/customlist/CustomListNodeTest.java b/assignment/src/test/java/appointmentplanner/customlist/CustomListNodeTest.java new file mode 100644 index 0000000..837fe9b --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/customlist/CustomListNodeTest.java @@ -0,0 +1,41 @@ + +package appointmentplanner.customlist; + +import static org.assertj.core.api.Assertions.*; +import org.junit.jupiter.api.Test; + +public class CustomListNodeTest { + + @Test + void newListNode_shouldCreaeteNotNullNodeObject() { + CustomLinkedListNode node = new CustomLinkedListNode<>(null, "item1"); + assertThat(node).isNotNull(); + } + + @Test + void setNext_shouldSetNextNodeSuccessfully() { + CustomLinkedListNode node1 = new CustomLinkedListNode<>(null, "item1"); + CustomLinkedListNode node2 = new CustomLinkedListNode<>(null, "item2"); + + node1.setNext(node2); + + assertThat(node1.getNext()).isEqualTo(node2); + } + + @Test + void getItem_shouldReturnSetItemSuccessfully() { + CustomLinkedListNode node = new CustomLinkedListNode<>(null, "item1"); + assertThat(node.getItem()).isEqualTo("item1"); + } + + @Test + void getNext_shouldReturnSetNextNodeSuccessfully() { + CustomLinkedListNode node1 = new CustomLinkedListNode<>(null, "item1"); + CustomLinkedListNode node2 = new CustomLinkedListNode<>(null, "item2"); + + node1.setNext(node2); + + assertThat(node1.getNext()).isEqualTo(node2); + } + +} From e1a480610c7ee58d5500eec93f34ee71a7a5ef2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:08:18 +0200 Subject: [PATCH 14/40] impl: custom linked list node --- .../customlist/CustomLinkedListNode.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListNode.java diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListNode.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListNode.java new file mode 100644 index 0000000..1e1c961 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListNode.java @@ -0,0 +1,28 @@ +package appointmentplanner.customlist; + +public class CustomLinkedListNode { + private T item; + private CustomLinkedListNode next; + + public CustomLinkedListNode(CustomLinkedListNode next, T item) { + this.next = next; + this.item = item; + } + + public CustomLinkedListNode(T item) { + this(null, item); + } + + public T getItem() { + return item; + } + + public CustomLinkedListNode getNext() { + return next; + } + + public void setNext(CustomLinkedListNode next) { + this.next = next; + } + +} From c3932eb4404d21c39b84163db5756350aa2a080e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:08:32 +0200 Subject: [PATCH 15/40] test: linked list add and size --- .../customlist/api/CustomLinkedListTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java new file mode 100644 index 0000000..fbbf254 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -0,0 +1,39 @@ +package appointmentplanner.customlist.api; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import appointmentplanner.customlist.CustomLinkedListImpl; + +public class CustomLinkedListTest { + + @Test + void cllAddandCllSize_shouldAddElementSuccessfullyAndCalculateSizeSuccessfully() { + CustomLinkedList list = new CustomLinkedListImpl<>(); + + int counter = 0; + + assertThat(list.size()).isEqualTo(counter); + + for (String word : new String[] { "Ahoj", "jak", "se", "mas", "vole" }) { + counter++; + list.add(word); + assertThat(list.size()).isEqualTo(counter); + } + + } + + @ParameterizedTest + @CsvSource({ + "'Ahoj, jak, to, jde', 'to', true", + "'Ty, jsi, ale, hloupy', 'to', false" + + }) + void cllContains_shouldReturnCorrectResult(String[] data, String toContain, boolean shouldContain) { + + } + +} From 6d829c47b9f4fa8ecce03a0021864b9282a05e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:08:50 +0200 Subject: [PATCH 16/40] feat: custom linked list api definition --- .../customlist/api/CustomLinkedList.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/customlist/api/CustomLinkedList.java diff --git a/assignment/src/main/java/appointmentplanner/customlist/api/CustomLinkedList.java b/assignment/src/main/java/appointmentplanner/customlist/api/CustomLinkedList.java new file mode 100644 index 0000000..6da82e4 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/customlist/api/CustomLinkedList.java @@ -0,0 +1,21 @@ + +package appointmentplanner.customlist.api; + +public interface CustomLinkedList extends Iterable { + + void add(T item); + + void remove(T item); + + void insertAfter(T reference, T item); + + void insertBefore(T reference, T item); + + T getAfter(T reference); + + T getBefore(T reference); + + boolean contains(T item); + + int size(); +} From 21ac9f540508710949f492aaa395407cc0331565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:09:24 +0200 Subject: [PATCH 17/40] impl: custom linked list size and add --- .../customlist/CustomLinkedListImpl.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java new file mode 100644 index 0000000..ef2ed46 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -0,0 +1,84 @@ +package appointmentplanner.customlist; + +import java.util.Iterator; + +import appointmentplanner.customlist.api.CustomLinkedList; + +public class CustomLinkedListImpl implements CustomLinkedList { + + CustomLinkedListNode head = null; + + @Override + public Iterator iterator() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'iterator'"); + } + + @Override + public void add(T item) { + CustomLinkedListNode newNode = new CustomLinkedListNode<>(item); + + CustomLinkedListNode oldHead = head; + + head = newNode; + + if (oldHead != null) { + head.setNext(oldHead); + } + } + + @Override + public void remove(T item) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'remove'"); + } + + @Override + public void insertAfter(T reference, T item) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'insertAfter'"); + } + + @Override + public void insertBefore(T reference, T item) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'insertBefore'"); + } + + @Override + public T getAfter(T reference) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getAfter'"); + } + + @Override + public T getBefore(T reference) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getBefore'"); + } + + @Override + public boolean contains(T item) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'contains'"); + } + + private int recursiveSizeCalc(CustomLinkedListNode node, int count) { + if (node == null) { + return 0; + } + + if (node.getNext() == null) { + return count; + } + + return recursiveSizeCalc(node.getNext(), count + 1); + + } + + @Override + public int size() { + return recursiveSizeCalc(this.head, 1); + } + +} From 999dbb1bd246edc0e715bae88e5e5d14dbe81921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:11:25 +0200 Subject: [PATCH 18/40] cleanup: local day plan test --- .../src/test/java/appointmentplanner/LocalDayPlanTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java index ad87913..89df940 100644 --- a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java +++ b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java @@ -9,6 +9,8 @@ import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.params.provider.ValueSources; import appointmentplanner.api.LocalDay; import appointmentplanner.api.LocalDayPlan; @@ -38,5 +40,4 @@ public class LocalDayPlanTest { assertThat(plan.startOfDay()).isEqualTo(start); assertThat(plan.endOfDay()).isEqualTo(end); } - } From 4f8aa5c88af5b9b76547bdb3e1688d2e4ed77c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:11:40 +0200 Subject: [PATCH 19/40] impl: local day plan --- .../appointmentplanner/LocalDayPlanImpl.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java index 4604dac..e1da13b 100644 --- a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java +++ b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java @@ -17,26 +17,29 @@ import appointmentplanner.api.TimeSlot; public class LocalDayPlanImpl implements LocalDayPlan { - public LocalDayPlanImpl(LocalDay day, Instant startOfDay, Instant endOfDay) { - throw new UnsupportedOperationException("Unimplemented constructor 'LocalDayPlanImpl'"); + public LocalDayPlanImpl(LocalDay day, Instant start, Instant end) { + this.day = day; + this.start = start; + this.end = end; } + private LocalDay day; + private Instant start; + private Instant end; + @Override public LocalDay day() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'day'"); + return day; } @Override public Instant startOfDay() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'startOfDay'"); + return start; } @Override public Instant endOfDay() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'endOfDay'"); + return end; } @Override From 85f0c1d0d423c0883049fa7a0220007dad6f103a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:26:58 +0200 Subject: [PATCH 20/40] feat test: array converter for parametrized tests --- .../StringArrayConverter.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 assignment/src/test/java/appointmentplanner/StringArrayConverter.java diff --git a/assignment/src/test/java/appointmentplanner/StringArrayConverter.java b/assignment/src/test/java/appointmentplanner/StringArrayConverter.java new file mode 100644 index 0000000..15f8036 --- /dev/null +++ b/assignment/src/test/java/appointmentplanner/StringArrayConverter.java @@ -0,0 +1,18 @@ +package appointmentplanner; + +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.SimpleArgumentConverter; + +public class StringArrayConverter extends SimpleArgumentConverter { + + @Override + protected Object convert(Object source, Class targetType) throws ArgumentConversionException { + if (source instanceof String && String[].class.isAssignableFrom(targetType)) { + return ((String) source).split("\\s*,\\s*"); + } else { + throw new IllegalArgumentException("Conversion from " + source.getClass() + " to " + + targetType + " not supported."); + } + } + +} From 1427a96125d672153000873f1a6f15e2d30b9e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:27:20 +0200 Subject: [PATCH 21/40] test: custom linked list contains --- .../customlist/api/CustomLinkedListTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index fbbf254..1e558cd 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -2,10 +2,14 @@ package appointmentplanner.customlist.api; import static org.assertj.core.api.Assertions.*; +import java.util.stream.Stream; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.CsvSource; +import appointmentplanner.StringArrayConverter; import appointmentplanner.customlist.CustomLinkedListImpl; public class CustomLinkedListTest { @@ -32,7 +36,14 @@ public class CustomLinkedListTest { "'Ty, jsi, ale, hloupy', 'to', false" }) - void cllContains_shouldReturnCorrectResult(String[] data, String toContain, boolean shouldContain) { + void cllContains_shouldReturnCorrectResult(@ConvertWith(StringArrayConverter.class) String[] data, String toContain, + boolean shouldContain) { + + CustomLinkedList list = new CustomLinkedListImpl<>(); + + Stream.of(data).forEach(list::add); + + assertThat(list.contains(toContain)).isEqualTo(shouldContain); } From 3a78f9a51d3d66ffd32a1ad1ab2a7ae60fb1790c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 15:27:25 +0200 Subject: [PATCH 22/40] impl: custom linked list --- .../customlist/CustomLinkedListImpl.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java index ef2ed46..1e82fd8 100644 --- a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -27,6 +27,21 @@ public class CustomLinkedListImpl implements CustomLinkedList { } } + private CustomLinkedListNode traverseFind(CustomLinkedListNode currentNode, T item) { + + CustomLinkedListNode nextNode = currentNode.getNext(); + + if (nextNode == null) { + return null; + } + + if (currentNode.getItem().equals(item)) { + return currentNode; + } + + return traverseFind(nextNode, item); + } + @Override public void remove(T item) { // TODO Auto-generated method stub @@ -59,8 +74,7 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public boolean contains(T item) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'contains'"); + return traverseFind(head, item) != null ? true : false; } private int recursiveSizeCalc(CustomLinkedListNode node, int count) { From e0eba95a1da02bf79bb8b5922e8a18aca1911afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 16:18:22 +0200 Subject: [PATCH 23/40] test: linked list remove --- .../customlist/api/CustomLinkedListTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index 1e558cd..26f1629 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -47,4 +47,18 @@ public class CustomLinkedListTest { } + @ParameterizedTest + @CsvSource({ + "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'totalne'" + }) + void cllRemove_shouldRemoveItemSuccessfully(@ConvertWith(StringArrayConverter.class) String[] data, String toRemove) { + CustomLinkedList list = new CustomLinkedListImpl<>(); + + Stream.of(data).forEach(list::add); + + list.remove(toRemove); + + assertThat(list.contains(toRemove)).isFalse(); + } + } From 97dee742299f45caae3fda262daf5e0cf764b48b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Thu, 16 Oct 2025 16:48:53 +0200 Subject: [PATCH 24/40] test: custom linked list get before, after --- .../customlist/api/CustomLinkedListTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index 26f1629..a582191 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -7,7 +7,10 @@ import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.MethodSources; import appointmentplanner.StringArrayConverter; import appointmentplanner.customlist.CustomLinkedListImpl; @@ -61,4 +64,42 @@ public class CustomLinkedListTest { assertThat(list.contains(toRemove)).isFalse(); } + private static enum LlGetPosition { + BEFORE, AFTER + } + + private static String[] someBasicDataSet = new String[] { "O", "MUJ", "BOZE" }; + + private static Stream getAfterBeforeData() { + return Stream.of( + Arguments.of(someBasicDataSet, LlGetPosition.BEFORE, "MUJ", "O"), + Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "MUJ", "BOZE"), + Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "BOZE", null), + Arguments.of(someBasicDataSet, LlGetPosition.BEFORE, "O", null)); + } + + @ParameterizedTest + @MethodSource("getAfterBeforeData") + void cllGetAfter_shouldReturnCorrectResult(String[] data, LlGetPosition position, String reference, + String expectedResult) { + + CustomLinkedList list = new CustomLinkedListImpl<>(); + Stream.of(data).forEach(list::add); + + switch (position) { + case BEFORE: + assertThat(list.getBefore(reference)).isEqualTo(expectedResult); + break; + + case AFTER: + assertThat(list.getAfter(reference)).isEqualTo(expectedResult); + break; + + default: + fail("Incorrect parameters"); + break; + } + + } + } From 2dc0dd706cbf9032215d6850c0ec0e7b9b44a608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Fri, 17 Oct 2025 12:47:55 +0200 Subject: [PATCH 25/40] test fix: cll get before & after - test data set enhacement --- .../appointmentplanner/customlist/api/CustomLinkedListTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index a582191..d88b6bd 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -74,6 +74,7 @@ public class CustomLinkedListTest { return Stream.of( Arguments.of(someBasicDataSet, LlGetPosition.BEFORE, "MUJ", "O"), Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "MUJ", "BOZE"), + Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "O", "MUJ"), Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "BOZE", null), Arguments.of(someBasicDataSet, LlGetPosition.BEFORE, "O", null)); } From 595f2f23447bc0dbdf379faa68f63a19030c64c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Fri, 17 Oct 2025 12:48:27 +0200 Subject: [PATCH 26/40] impl: cll get before & after --- .../customlist/CustomLinkedListImpl.java | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java index 1e82fd8..53a1e3f 100644 --- a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -27,19 +27,57 @@ public class CustomLinkedListImpl implements CustomLinkedList { } } - private CustomLinkedListNode traverseFind(CustomLinkedListNode currentNode, T item) { + private static enum ItemPosition { + AFTER, BEFORE, CURRENT + } + + private CustomLinkedListNode traverseFind(CustomLinkedListNode currentNode, T item, ItemPosition position) { CustomLinkedListNode nextNode = currentNode.getNext(); + switch (position) { + + case CURRENT: + + if (currentNode.getItem().equals(item)) { + return currentNode; + } + + break; + + case AFTER: + + if (nextNode == null) { + return null; + } + + if (nextNode.getItem().equals(item)) { + return currentNode; + } + + break; + + case BEFORE: + + if (nextNode == null) { + return null; + } + + if (currentNode.getItem().equals(item)) { + return nextNode; + } + + break; + + default: + return null; + } + if (nextNode == null) { return null; } - if (currentNode.getItem().equals(item)) { - return currentNode; - } - - return traverseFind(nextNode, item); + return traverseFind(nextNode, item, position); } @Override @@ -62,19 +100,19 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public T getAfter(T reference) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getAfter'"); + CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.AFTER); + return node == null ? null : node.getItem(); } @Override public T getBefore(T reference) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getBefore'"); + CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.BEFORE); + return node == null ? null : node.getItem(); } @Override public boolean contains(T item) { - return traverseFind(head, item) != null ? true : false; + return traverseFind(head, item, ItemPosition.CURRENT) != null ? true : false; } private int recursiveSizeCalc(CustomLinkedListNode node, int count) { From 6d43f605b8328b0edbd3f4f8e8e3130aaad7a157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Fri, 17 Oct 2025 13:01:41 +0200 Subject: [PATCH 27/40] test fix: cll remove - more test scenarios --- .../customlist/api/CustomLinkedListTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index d88b6bd..478676f 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -52,7 +52,9 @@ public class CustomLinkedListTest { @ParameterizedTest @CsvSource({ - "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'totalne'" + "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'totalne'", + "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'Tak'", + "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'uz'", }) void cllRemove_shouldRemoveItemSuccessfully(@ConvertWith(StringArrayConverter.class) String[] data, String toRemove) { CustomLinkedList list = new CustomLinkedListImpl<>(); From 53a09f6538fd1e25d5e08538a68f37f329770051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Fri, 17 Oct 2025 13:01:47 +0200 Subject: [PATCH 28/40] impl: cll remove --- .../customlist/CustomLinkedListImpl.java | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java index 53a1e3f..5e49219 100644 --- a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -45,7 +45,7 @@ public class CustomLinkedListImpl implements CustomLinkedList { break; - case AFTER: + case BEFORE: if (nextNode == null) { return null; @@ -57,7 +57,7 @@ public class CustomLinkedListImpl implements CustomLinkedList { break; - case BEFORE: + case AFTER: if (nextNode == null) { return null; @@ -82,8 +82,27 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public void remove(T item) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'remove'"); + + CustomLinkedListNode nodeToRemove = traverseFind(head, item, ItemPosition.CURRENT); + + if (nodeToRemove == null) { + return; + } + + if (nodeToRemove == head) { + head = head.getNext(); + return; + } + + CustomLinkedListNode beforeNode = traverseFind(head, item, ItemPosition.BEFORE); + + if (nodeToRemove.getNext() == null) { + beforeNode.setNext(null); + return; + } + + beforeNode.setNext(nodeToRemove.getNext()); + } @Override @@ -100,13 +119,19 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public T getAfter(T reference) { - CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.AFTER); + + // head represents the last inserted item thus making enrire list in reverse + // order + CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.BEFORE); return node == null ? null : node.getItem(); } @Override public T getBefore(T reference) { - CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.BEFORE); + + // head represents the last inserted item thus making enrire list in reverse + // order + CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.AFTER); return node == null ? null : node.getItem(); } From 68d51a24aca529fbd80977cf714d26dfb502ad1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Fri, 17 Oct 2025 14:14:04 +0200 Subject: [PATCH 29/40] test enhc: cll remove - test cases - non existing item, list with only one item --- .../appointmentplanner/customlist/api/CustomLinkedListTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index 478676f..9fa839d 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -55,6 +55,8 @@ public class CustomLinkedListTest { "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'totalne'", "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'Tak'", "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'uz'", + "'Tak, jsme, to, cele, totalne, dosrali, ale, co, uz', 'non-existing'", + "'only', 'only'", }) void cllRemove_shouldRemoveItemSuccessfully(@ConvertWith(StringArrayConverter.class) String[] data, String toRemove) { CustomLinkedList list = new CustomLinkedListImpl<>(); From ceadbab59e44ceaafa40de04ac1dc32d27e999f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Fri, 17 Oct 2025 14:20:46 +0200 Subject: [PATCH 30/40] impl fix: cll remove - contains with only item caused exception --- .../customlist/CustomLinkedListImpl.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java index 5e49219..ea46089 100644 --- a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -33,6 +33,10 @@ public class CustomLinkedListImpl implements CustomLinkedList { private CustomLinkedListNode traverseFind(CustomLinkedListNode currentNode, T item, ItemPosition position) { + if (currentNode == null) { + return null; + } + CustomLinkedListNode nextNode = currentNode.getNext(); switch (position) { @@ -83,26 +87,29 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public void remove(T item) { - CustomLinkedListNode nodeToRemove = traverseFind(head, item, ItemPosition.CURRENT); - - if (nodeToRemove == null) { + if (head == null) { return; } - if (nodeToRemove == head) { + if (head.getItem().equals(item)) { head = head.getNext(); return; } CustomLinkedListNode beforeNode = traverseFind(head, item, ItemPosition.BEFORE); - if (nodeToRemove.getNext() == null) { + if (beforeNode == null) { + return; + } + + CustomLinkedListNode nodeToRemove = beforeNode.getNext(); + + if (beforeNode.getNext() == null) { beforeNode.setNext(null); return; } beforeNode.setNext(nodeToRemove.getNext()); - } @Override From b315a8ea4c35fd22926474d3f79bfa243dd80853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 11:43:17 +0200 Subject: [PATCH 31/40] test enhc: cll insert after & before - more test scenarios --- .../customlist/api/CustomLinkedListTest.java | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index 9fa839d..7884b66 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -10,7 +10,6 @@ import org.junit.jupiter.params.converter.ConvertWith; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.MethodSources; import appointmentplanner.StringArrayConverter; import appointmentplanner.customlist.CustomLinkedListImpl; @@ -68,7 +67,7 @@ public class CustomLinkedListTest { assertThat(list.contains(toRemove)).isFalse(); } - private static enum LlGetPosition { + private static enum LlItemPosition { BEFORE, AFTER } @@ -76,16 +75,16 @@ public class CustomLinkedListTest { private static Stream getAfterBeforeData() { return Stream.of( - Arguments.of(someBasicDataSet, LlGetPosition.BEFORE, "MUJ", "O"), - Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "MUJ", "BOZE"), - Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "O", "MUJ"), - Arguments.of(someBasicDataSet, LlGetPosition.AFTER, "BOZE", null), - Arguments.of(someBasicDataSet, LlGetPosition.BEFORE, "O", null)); + Arguments.of(someBasicDataSet, LlItemPosition.BEFORE, "MUJ", "O"), + Arguments.of(someBasicDataSet, LlItemPosition.AFTER, "MUJ", "BOZE"), + Arguments.of(someBasicDataSet, LlItemPosition.AFTER, "O", "MUJ"), + Arguments.of(someBasicDataSet, LlItemPosition.AFTER, "BOZE", null), + Arguments.of(someBasicDataSet, LlItemPosition.BEFORE, "O", null)); } @ParameterizedTest @MethodSource("getAfterBeforeData") - void cllGetAfter_shouldReturnCorrectResult(String[] data, LlGetPosition position, String reference, + void cllGetAfter_shouldReturnCorrectResult(String[] data, LlItemPosition position, String reference, String expectedResult) { CustomLinkedList list = new CustomLinkedListImpl<>(); @@ -107,4 +106,49 @@ public class CustomLinkedListTest { } + private static Stream insertBeforeAfterData() { + return Stream.of( + Arguments.of(someBasicDataSet, "DOPRDELE", "BOZE", LlItemPosition.AFTER), + Arguments.of(new String[] { "Ahoj" }, "vole", "Ahoj", LlItemPosition.AFTER), + Arguments.of(new String[] { "ahoj" }, "More", "ahoj", LlItemPosition.BEFORE), + Arguments.of(new String[] { "A", "tak", "se", "pochcal", "posral", "a", "jeste", "nakonec", "serval" }, + "vyblil", + "posral", LlItemPosition.BEFORE), + Arguments.of(new String[] { "A", "tak", "se", "pochcal", "posral", "a", "jeste", "nakonec", "serval" }, + "vyblil", + "posral", LlItemPosition.AFTER), + Arguments.of(someBasicDataSet, "PREMOCNY", "BOZE", LlItemPosition.BEFORE)); + } + + @ParameterizedTest + @MethodSource("insertBeforeAfterData") + void cllInsertAfterBefore_shouldInsertItemSuccessfully(String[] initData, String toInsert, String reference, + LlItemPosition position) { + + CustomLinkedList list = initPopulaterList(initData); + + switch (position) { + case AFTER: + list.insertAfter(reference, toInsert); + assertThat(list.getAfter(reference)).isEqualTo(toInsert); + break; + + case BEFORE: + list.insertBefore(reference, toInsert); + assertThat(list.getBefore(reference)).isEqualTo(toInsert); + break; + + default: + fail("Incorrect position parameter"); + break; + } + + } + + private CustomLinkedList initPopulaterList(String[] initData) { + CustomLinkedList list = new CustomLinkedListImpl<>(); + Stream.of(initData).forEach(list::add); + return list; + } + } From 3330e31bcfe307becd5735edd13db608487d6879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 11:43:50 +0200 Subject: [PATCH 32/40] impl: cll insert before & after --- .../customlist/CustomLinkedListImpl.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java index ea46089..dc5a189 100644 --- a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -114,20 +114,28 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public void insertAfter(T reference, T item) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'insertAfter'"); + + if (head.getItem().equals(reference)) { + add(item); + return; + } + + CustomLinkedListNode nodeBefore = traverseFind(head, reference, ItemPosition.BEFORE); + CustomLinkedListNode nodeToInsert = new CustomLinkedListNode<>(nodeBefore.getNext(), item); + nodeBefore.setNext(nodeToInsert); } @Override public void insertBefore(T reference, T item) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'insertBefore'"); + CustomLinkedListNode referenceNode = traverseFind(head, reference, ItemPosition.CURRENT); + CustomLinkedListNode nodeToInsert = new CustomLinkedListNode<>(referenceNode.getNext(), item); + referenceNode.setNext(nodeToInsert); } @Override public T getAfter(T reference) { - // head represents the last inserted item thus making enrire list in reverse + // head represents the last inserted item thus making entire list in reverse // order CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.BEFORE); return node == null ? null : node.getItem(); @@ -136,7 +144,7 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public T getBefore(T reference) { - // head represents the last inserted item thus making enrire list in reverse + // head represents the last inserted item thus making entire list in reverse // order CustomLinkedListNode node = traverseFind(head, reference, ItemPosition.AFTER); return node == null ? null : node.getItem(); From aee874063ebb0cb55ba41f33e70222fafb45dba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 11:53:07 +0200 Subject: [PATCH 33/40] test fix: cll - small cosmetic fix --- .../customlist/api/CustomLinkedListTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index 7884b66..e5451ef 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -36,7 +36,6 @@ public class CustomLinkedListTest { @CsvSource({ "'Ahoj, jak, to, jde', 'to', true", "'Ty, jsi, ale, hloupy', 'to', false" - }) void cllContains_shouldReturnCorrectResult(@ConvertWith(StringArrayConverter.class) String[] data, String toContain, boolean shouldContain) { @@ -125,7 +124,7 @@ public class CustomLinkedListTest { void cllInsertAfterBefore_shouldInsertItemSuccessfully(String[] initData, String toInsert, String reference, LlItemPosition position) { - CustomLinkedList list = initPopulaterList(initData); + CustomLinkedList list = initPopulatedList(initData); switch (position) { case AFTER: @@ -145,7 +144,7 @@ public class CustomLinkedListTest { } - private CustomLinkedList initPopulaterList(String[] initData) { + private CustomLinkedList initPopulatedList(String[] initData) { CustomLinkedList list = new CustomLinkedListImpl<>(); Stream.of(initData).forEach(list::add); return list; From 25c09c95d4f5aa5e48be5ef8522bb217d033a926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 12:23:34 +0200 Subject: [PATCH 34/40] test: ldp toString displays date and timezone --- .../test/java/appointmentplanner/LocalDayPlanTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java index 89df940..1dead15 100644 --- a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java +++ b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java @@ -40,4 +40,12 @@ public class LocalDayPlanTest { assertThat(plan.startOfDay()).isEqualTo(start); assertThat(plan.endOfDay()).isEqualTo(end); } + + @ParameterizedTest + @MethodSource("provideLocalDPDataset") + void ldToString_shouldReturnStringContainingLocalDateAndTimeZone(LocalDay day, Instant start, Instant end) { + LocalDayPlan plan = new LocalDayPlanImpl(day, start, end); + + assertThat(plan.toString()).contains(day.zone().toString(), day.date().toString()); + } } From 8fdc0a6d6c7cd940b7e781831557642536b8d9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 12:23:53 +0200 Subject: [PATCH 35/40] impl: ldp toString - date and timezone display --- .../src/main/java/appointmentplanner/LocalDayPlanImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java index e1da13b..c2eedbc 100644 --- a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java +++ b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java @@ -109,4 +109,9 @@ public class LocalDayPlanImpl implements LocalDayPlan { throw new UnsupportedOperationException("Unimplemented method 'nrOfAppointments'"); } + @Override + public String toString() { + return String.format("Day: %s, TimeZone: %s", day.date(), day().zone()); + } + } From a6136413b9282ed2bc1157b1c950d516d1e028ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 15:09:53 +0200 Subject: [PATCH 36/40] test: cll iterator --- .../customlist/api/CustomLinkedListTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java index e5451ef..bb8bf56 100644 --- a/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java +++ b/assignment/src/test/java/appointmentplanner/customlist/api/CustomLinkedListTest.java @@ -144,6 +144,22 @@ public class CustomLinkedListTest { } + @Test + void cllIterate_shouldPerformCorrectIteration() { + + String[] data = new String[] { "Ahoj", "jak", "se", "mas", "?" }; + + CustomLinkedList list = initPopulatedList(data); + + int counter = data.length - 1; + + for (String element : list) { + assertThat(element).isEqualTo(data[counter]); + counter--; + } + + } + private CustomLinkedList initPopulatedList(String[] initData) { CustomLinkedList list = new CustomLinkedListImpl<>(); Stream.of(initData).forEach(list::add); From d29d8b156e7c145402d1ce41e2787afef1e0af6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 15:10:06 +0200 Subject: [PATCH 37/40] impl: cll iterator --- .../customlist/CustomLinkedListImpl.java | 3 +- .../customlist/CustomLinkedListIterator.java | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListIterator.java diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java index dc5a189..5d482a2 100644 --- a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListImpl.java @@ -10,8 +10,7 @@ public class CustomLinkedListImpl implements CustomLinkedList { @Override public Iterator iterator() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'iterator'"); + return new CustomLinkedListIterator(this); } @Override diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListIterator.java b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListIterator.java new file mode 100644 index 0000000..a8d56a7 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomLinkedListIterator.java @@ -0,0 +1,30 @@ +package appointmentplanner.customlist; + +import java.util.Iterator; +import java.util.Iterator; + +public class CustomLinkedListIterator implements Iterator { + + private CustomLinkedListImpl list; + + private CustomLinkedListNode lastNode; + + public CustomLinkedListIterator(CustomLinkedListImpl listToIterate) { + list = listToIterate; + lastNode = list.head; + + } + + @Override + public boolean hasNext() { + return lastNode.getNext() != null; + } + + @Override + public T next() { + T item = lastNode.getItem(); + lastNode = lastNode.getNext(); + return item; + } + +} From e6a56444dbb7bd008865db1eb6f09346f44e8cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 15:10:39 +0200 Subject: [PATCH 38/40] feat: binding custom linked list to Java's default List interface --- .../customlist/CustomListToJavaBinding.java | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/customlist/CustomListToJavaBinding.java diff --git a/assignment/src/main/java/appointmentplanner/customlist/CustomListToJavaBinding.java b/assignment/src/main/java/appointmentplanner/customlist/CustomListToJavaBinding.java new file mode 100644 index 0000000..dc1e941 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/customlist/CustomListToJavaBinding.java @@ -0,0 +1,157 @@ +package appointmentplanner.customlist; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import appointmentplanner.customlist.api.*; + +public class CustomListToJavaBinding implements List { + + private CustomLinkedList list; + + public CustomListToJavaBinding(CustomLinkedList list) { + this.list = list; + } + + @Override + public boolean add(T arg0) { + list.add(arg0); + return true; + } + + @Override + public void add(int arg0, T arg1) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Cannot add to exact index in linked list"); + } + + @Override + public boolean addAll(Collection c) { + c.stream().forEach(list::add); + return true; + } + + @Override + public boolean addAll(int index, Collection c) { + throw new UnsupportedOperationException("Cannot add to exact index in linked list"); + } + + @Override + public void clear() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'clear'"); + } + + @Override + public boolean containsAll(Collection c) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'containsAll'"); + } + + @Override + public T get(int index) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'get'"); + } + + @Override + public int indexOf(Object o) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'indexOf'"); + } + + @Override + public boolean isEmpty() { + return list.size() == 0; + } + + @Override + public Iterator iterator() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'iterator'"); + } + + @Override + public int lastIndexOf(Object o) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'lastIndexOf'"); + } + + @Override + public ListIterator listIterator() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'listIterator'"); + } + + @Override + public ListIterator listIterator(int index) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'listIterator'"); + } + + @Override + public boolean remove(Object o) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'remove'"); + } + + @Override + public T remove(int index) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'remove'"); + } + + @Override + public boolean removeAll(Collection c) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'removeAll'"); + } + + @Override + public boolean retainAll(Collection c) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'retainAll'"); + } + + @Override + public T set(int arg0, T arg1) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'set'"); + } + + @Override + public int size() { + return list.size(); + } + + @Override + public List subList(int fromIndex, int toIndex) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'subList'"); + } + + @Override + public Object[] toArray() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'toArray'"); + } + + @Override + public T[] toArray(T[] arg0) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'toArray'"); + } + + @Override + public boolean contains(Object o) { + try { + T bal = (T) o; + return list.contains(bal); + } catch (Exception e) { + return false; + } + } + +} From 3d4e491ae262023473bb4fd05fcfe1bbbac5fcd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 15:11:38 +0200 Subject: [PATCH 39/40] cleanup: ldp test --- .../src/test/java/appointmentplanner/LocalDayPlanTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java index 1dead15..f93060b 100644 --- a/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java +++ b/assignment/src/test/java/appointmentplanner/LocalDayPlanTest.java @@ -3,14 +3,11 @@ package appointmentplanner; import static org.assertj.core.api.Assertions.assertThat; import java.time.Instant; -import java.time.LocalTime; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.junit.jupiter.params.provider.ValueSources; import appointmentplanner.api.LocalDay; import appointmentplanner.api.LocalDayPlan; From 5da00391ef1769679ddf6c87c68fb58dd00adbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20P=C5=99ib=C3=ADk?= Date: Sat, 18 Oct 2025 15:12:07 +0200 Subject: [PATCH 40/40] feat: appointment list in ldp --- .../appointmentplanner/AppointmentImpl.java | 30 +++++++++++++++++++ .../appointmentplanner/LocalDayPlanImpl.java | 4 +++ 2 files changed, 34 insertions(+) create mode 100644 assignment/src/main/java/appointmentplanner/AppointmentImpl.java diff --git a/assignment/src/main/java/appointmentplanner/AppointmentImpl.java b/assignment/src/main/java/appointmentplanner/AppointmentImpl.java new file mode 100644 index 0000000..2ad57e6 --- /dev/null +++ b/assignment/src/main/java/appointmentplanner/AppointmentImpl.java @@ -0,0 +1,30 @@ +package appointmentplanner; + +import java.time.Instant; + +import appointmentplanner.api.Appointment; +import appointmentplanner.api.AppointmentRequest; + +public class AppointmentImpl implements Appointment { + + private Instant start; + private Instant stop; + + private AppointmentRequest request; + + @Override + public Instant start() { + return start; + } + + @Override + public Instant end() { + return stop; + } + + @Override + public AppointmentRequest request() { + return request; + } + +} diff --git a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java index c2eedbc..9e929cc 100644 --- a/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java +++ b/assignment/src/main/java/appointmentplanner/LocalDayPlanImpl.java @@ -14,9 +14,13 @@ import appointmentplanner.api.LocalDay; import appointmentplanner.api.LocalDayPlan; import appointmentplanner.api.TimePreference; import appointmentplanner.api.TimeSlot; +import appointmentplanner.customlist.CustomLinkedListImpl; +import appointmentplanner.customlist.api.CustomLinkedList; public class LocalDayPlanImpl implements LocalDayPlan { + private CustomLinkedList timeline = new CustomLinkedListImpl<>(); + public LocalDayPlanImpl(LocalDay day, Instant start, Instant end) { this.day = day; this.start = start;