diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4942001fac37d57b2a692c8c8577c07a434daffd --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ +.idea/* + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store diff --git a/lances-curve.iml b/lances-curve.iml new file mode 100644 index 0000000000000000000000000000000000000000..d8a1435f58f21281bb23482440d32ccacb14cb61 --- /dev/null +++ b/lances-curve.iml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module-library"> + <library name="JUnit4"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> + </orderEntry> + <orderEntry type="module-library"> + <library name="JUnit5.8.1"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter/5.8.1/junit-jupiter-5.8.1.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.8.1/junit-jupiter-api-5.8.1.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.8.1/junit-platform-commons-1.8.1.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-params/5.8.1/junit-jupiter-params-5.8.1.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-engine/5.8.1/junit-jupiter-engine-5.8.1.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.8.1/junit-platform-engine-1.8.1.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> + </orderEntry> + </component> +</module> \ No newline at end of file diff --git a/src/main/LancesCurve.java b/src/main/LancesCurve.java new file mode 100644 index 0000000000000000000000000000000000000000..4357439cc7306686b7194dbc58be6506d30d8002 --- /dev/null +++ b/src/main/LancesCurve.java @@ -0,0 +1,80 @@ +package main; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class LancesCurve { + private final List<Plan> plans; + + public LancesCurve(List<Plan> plans) { + this.plans = plans; + } + + private List<Instant> getAllOrderedDate() { + return this.plans.stream() + .flatMap(plan -> Stream.of(plan.getStart(), plan.getEnd())) + .distinct() + .sorted() + .collect(Collectors.toList()); + } + + private List<Plan> getValueForEachInterval() { + var result = new ArrayList<Plan>(); + var orderedDateList = this.getAllOrderedDate(); + for (int i = 0; i < orderedDateList.size() - 1; i++) { + var x0 = orderedDateList.get(i); + var x1 = orderedDateList.get(i + 1); + var currentValue = plans.stream() + .filter(plan -> plan.getStart().isBefore(x1) && plan.getEnd().isAfter(x0)) + .mapToInt(Plan::getValue) + .sum(); + + var newPlan = new Plan(currentValue, x0, x1); + result.add(newPlan); + } + return result; + } + + private List<Plan> removeUselessAbscissa(List<Plan> plans) { + for (int i = 0; i < plans.size() - 1; i++) { + var current = plans.get(i); + var next = plans.get(i + 1); + if (current.getValue() == next.getValue()) { + next.setStart(current.getStart()); + plans.remove(i); + } + } + return plans; + } + + public LancesCurve setupCurve() { + var plans = this.getValueForEachInterval(); + var finalPlans = this.removeUselessAbscissa(plans); + return new LancesCurve(finalPlans); + } + + public List<Plan> getPlans() { + return plans; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LancesCurve that = (LancesCurve) o; + + return Objects.equals(plans, that.plans); + } + + @Override + public String toString() { + return "LancesCurve{" + + "plans=" + plans + + '}'; + } +} diff --git a/src/main/Main.java b/src/main/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..3b7512a6a32aad5a301e15219a7e1a0012b4f899 --- /dev/null +++ b/src/main/Main.java @@ -0,0 +1,6 @@ +package main; + +public class Main { + public static void main(String[] args) { + } +} diff --git a/src/main/Plan.java b/src/main/Plan.java new file mode 100644 index 0000000000000000000000000000000000000000..ad8323377f0ce2d83c0823a5d58cbcd9c56db624 --- /dev/null +++ b/src/main/Plan.java @@ -0,0 +1,66 @@ +package main; + +import main.exception.DateOrderException; + +import java.time.Instant; +import java.util.Objects; + +public class Plan { + private int value; + private Instant start; + private Instant end; + + public Plan(int value, Instant start, Instant end) { + this.value = value; + if (start.isAfter(end)) { + throw new DateOrderException("Start date should be before end date"); + } + this.start = start; + this.end = end; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public Instant getStart() { + return start; + } + + public void setStart(Instant start) { + this.start = start; + } + + public Instant getEnd() { + return end; + } + + public void setEnd(Instant end) { + this.end = end; + } + + @Override + public String toString() { + return "Plan{" + + "value=" + value + + ", start=" + start + + ", end=" + end + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Plan plan = (Plan) o; + + if (value != plan.value) return false; + if (!Objects.equals(start, plan.start)) return false; + return Objects.equals(end, plan.end); + } +} diff --git a/src/main/exception/DateOrderException.java b/src/main/exception/DateOrderException.java new file mode 100644 index 0000000000000000000000000000000000000000..60dac5e595223f2603b281cac09cd49f40d88cd0 --- /dev/null +++ b/src/main/exception/DateOrderException.java @@ -0,0 +1,14 @@ +package main.exception; + +public class DateOrderException extends RuntimeException { + public DateOrderException() { + } + + public DateOrderException(String message) { + super(message); + } + + public DateOrderException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/test/LancesCurveTest.java b/src/test/LancesCurveTest.java new file mode 100644 index 0000000000000000000000000000000000000000..31485b84dff1d51dab82e9455dde637a7853df9a --- /dev/null +++ b/src/test/LancesCurveTest.java @@ -0,0 +1,63 @@ +package test; + +import main.LancesCurve; +import main.exception.DateOrderException; +import org.junit.jupiter.api.Test; +import test.data.LancesCurveTestsData; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static test.data.LancesCurveKataData.*; + +class LancesCurveTest { + + @Test + void validKataData_returnCorrectLancesCurve() { + var lancesCurve = new LancesCurve(List.of(exigence1(), exigence2(), exigence3(), exigence4())); + var result = lancesCurve.setupCurve(); + + var expectedCurve = new LancesCurve(List.of( + expectedPlan1(), + expectedPlan2(), + expectedPlan3(), + expectedPlan4(), + expectedPlan5() + )); + + assertEquals(5, result.getPlans().size()); + assertEquals(expectedCurve.getPlans(), result.getPlans()); + assertEquals(expectedCurve, result); + } + + @Test + void wrongPlan_throwsException() { + assertThrows(DateOrderException.class, LancesCurveTestsData::wrongDate); + } + + /*@Test + void getAllOrderedDateTest() { + var plan1 = new Plan(1, midnight(), eightAM()); + var plan2 = new Plan(3, nineAM(), fourPM()); + var plan3 = new Plan(3, midnight(), fourPM()); + var curve = new LancesCurve(List.of(plan1, plan2, plan3)); + + var orderedDate = curve.getAllOrderedDate(); + var expectedList = List.of( + midnight(), + eightAM(), + nineAM(), + fourPM() + ); + + assertEquals(expectedList, orderedDate); + }*/ + + /*@Test + void shouldReturnTheCorrectValueAtEachDate() { + var lancesCurve = new LancesCurve(List.of(exigence1(), exigence2(), exigence3(), exigence4())); + var result = lancesCurve.getValueForEachInterval(); + + assertEquals(6, result.size()); + }*/ +} diff --git a/src/test/data/LancesCurveKataData.java b/src/test/data/LancesCurveKataData.java new file mode 100644 index 0000000000000000000000000000000000000000..c913542d5b1965dd198ab63eed615299fb92daf4 --- /dev/null +++ b/src/test/data/LancesCurveKataData.java @@ -0,0 +1,44 @@ +package test.data; + +import main.Plan; + +import java.time.Instant; + +public class LancesCurveKataData { + + public static Plan exigence1() { + return new Plan(1, Instant.parse("2021-07-05T00:00:00Z"), Instant.parse("2021-07-12T00:00:00Z")); + } + + public static Plan exigence2() { + return new Plan(2, Instant.parse("2021-07-06T20:00:00Z"), Instant.parse("2021-07-07T00:00:00Z")); + } + + public static Plan exigence3() { + return new Plan(1, Instant.parse("2021-07-06T22:00:00Z"), Instant.parse("2021-07-07T02:00:00Z")); + } + + public static Plan exigence4() { + return new Plan(1, Instant.parse("2021-07-07T02:00:00Z"), Instant.parse("2021-07-07T04:00:00Z")); + } + + public static Plan expectedPlan1() { + return new Plan(1, Instant.parse("2021-07-05T00:00:00Z"), Instant.parse("2021-07-06T20:00:00Z")); + } + + public static Plan expectedPlan2() { + return new Plan(3, Instant.parse("2021-07-06T20:00:00Z"), Instant.parse("2021-07-06T22:00:00Z")); + } + + public static Plan expectedPlan3() { + return new Plan(4, Instant.parse("2021-07-06T22:00:00Z"), Instant.parse("2021-07-07T00:00:00Z")); + } + + public static Plan expectedPlan4() { + return new Plan(2, Instant.parse("2021-07-07T00:00:00Z"), Instant.parse("2021-07-07T04:00:00Z")); + } + + public static Plan expectedPlan5() { + return new Plan(1, Instant.parse("2021-07-07T04:00:00Z"), Instant.parse("2021-07-12T00:00:00Z")); + } +} diff --git a/src/test/data/LancesCurveTestsData.java b/src/test/data/LancesCurveTestsData.java new file mode 100644 index 0000000000000000000000000000000000000000..a3f48d7639be12fed4d5284716b5fba07f4f3f8f --- /dev/null +++ b/src/test/data/LancesCurveTestsData.java @@ -0,0 +1,25 @@ +package test.data; + +import main.Plan; +import org.junit.jupiter.api.function.Executable; + +import java.time.Instant; + +public class LancesCurveTestsData { + public static Instant midnight() { + return Instant.parse("2022-05-15T00:00:00.00Z"); + } + public static Instant eightAM() { + return Instant.parse("2022-05-15T08:00:00.00Z"); + } + public static Instant nineAM() { + return Instant.parse("2022-05-15T09:00:00.00Z"); + } + public static Instant fourPM() { + return Instant.parse("2022-05-15T16:00:00.00Z"); + } + + public static Plan wrongDate() { + return new Plan(10, Instant.parse("2022-05-14T15:25:00Z"), Instant.parse("2022-05-14T14:00:00Z")); + } +}