From c070c474c775bbc19459968b5990460b18e14757 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:24:24 +0000 Subject: [PATCH 01/17] Setting up GitHub Classroom Feedback From 3520cb08467744775a75791ba69cd28d40088c4a Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Tue, 16 Sep 2025 13:20:07 +0200 Subject: [PATCH 02/17] =?UTF-8?q?Testar=20h=C3=A4mta=20fr=C3=A5n=20getPris?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 20a692ac..4cf4c62d 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -2,8 +2,22 @@ import com.example.api.ElpriserAPI; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + public class Main { public static void main(String[] args) { - ElpriserAPI elpriserAPI = new ElpriserAPI(); + // skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll + ElpriserAPI api = new ElpriserAPI(); + + // dagens priser + List getPriserCopy = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); + + System.out.println(getPriserCopy.get(4).timeStart().toLocalTime()); + System.out.println(getPriserCopy.getFirst().sekPerKWh()); + + + } } From ddb841c17f9027eba451f4c4587b316dbb0a0dfb Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:02:53 +0200 Subject: [PATCH 03/17] =?UTF-8?q?Forts=C3=A4tter=20testa=20grejer,=20kommi?= =?UTF-8?q?t=20l=C3=A4ngre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 4cf4c62d..df2ee848 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -3,6 +3,7 @@ import com.example.api.ElpriserAPI; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -11,11 +12,19 @@ public static void main(String[] args) { // skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll ElpriserAPI api = new ElpriserAPI(); - // dagens priser - List getPriserCopy = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); + // datum + LocalDate todaysDate = LocalDate.now(); + LocalDate tomorrowsDate = LocalDate.now().plusDays(1); + int day = LocalDate.now().getDayOfMonth(); - System.out.println(getPriserCopy.get(4).timeStart().toLocalTime()); - System.out.println(getPriserCopy.getFirst().sekPerKWh()); +// //Ta in och parsea ett datum via readLine +// System.out.println("Ange ett datum:"); +// LocalDate test = LocalDate.parse(System.console().readLine()); + + List pricesToday = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE4)); + List pricesTomorrow = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE4)); + + System.out.println(pricesToday.get(2).); From f262d62ab1feb73dbeb747d03b3241ae8e0aec3f Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:05:26 +0200 Subject: [PATCH 04/17] =?UTF-8?q?Forts=C3=A4tter=20testa=20grejer,=20kommi?= =?UTF-8?q?t=20l=C3=A4ngre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index df2ee848..6aa00c89 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -24,7 +24,7 @@ public static void main(String[] args) { List pricesToday = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE4)); List pricesTomorrow = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE4)); - System.out.println(pricesToday.get(2).); + System.out.println(pricesToday.get(2).timeEnd()); From 7d3bcf58fc69c042e23e001b7e85cf34297e67a1 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Tue, 16 Sep 2025 23:23:37 +0200 Subject: [PATCH 05/17] =?UTF-8?q?R=C3=A4knar=20ut=20total=20och=20medelv?= =?UTF-8?q?=C3=A4rde?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6aa00c89..517a2ec0 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -21,11 +21,17 @@ public static void main(String[] args) { // System.out.println("Ange ett datum:"); // LocalDate test = LocalDate.parse(System.console().readLine()); - List pricesToday = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE4)); - List pricesTomorrow = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE4)); + List pricesToday = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); + List pricesTomorrow = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); - System.out.println(pricesToday.get(2).timeEnd()); + double totalt = 0; + for(int i = 0; i < pricesToday.size(); i++){ + System.out.println(pricesToday.get(i).sekPerKWh()); + totalt += pricesToday.get(i).sekPerKWh(); + } + System.out.println("Total: " + totalt); + System.out.println("Medelvärde: " + totalt/pricesToday.size()); } From 669c3a3202b5ba6af68fceb90fa84b411c1b1606 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:00:12 +0200 Subject: [PATCH 06/17] Uppdaterat av Maritn --- src/main/java/com/example/Main.java | 23 +++- src/test/java/com/example/MainTest.java | 162 ++++++++++++++---------- 2 files changed, 114 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 517a2ec0..21877038 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -12,14 +12,29 @@ public static void main(String[] args) { // skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll ElpriserAPI api = new ElpriserAPI(); + + //testar args.length + if(args.length > 0){ + System.out.println("args length: " + args.length); + System.out.println("args[2]: " + args[2]); + } else{ + System.out.println("Nothing here."); + } + // datum LocalDate todaysDate = LocalDate.now(); LocalDate tomorrowsDate = LocalDate.now().plusDays(1); + LocalDate chosenDate; int day = LocalDate.now().getDayOfMonth(); -// //Ta in och parsea ett datum via readLine -// System.out.println("Ange ett datum:"); -// LocalDate test = LocalDate.parse(System.console().readLine()); + + + if(todaysDate.isBefore(tomorrowsDate)){ + System.out.println("todays date is before tomorrows date"); + } else { + System.out.println("todays date is not before tomorrows date"); + } + List pricesToday = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); List pricesTomorrow = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); @@ -32,6 +47,8 @@ public static void main(String[] args) { System.out.println("Total: " + totalt); System.out.println("Medelvärde: " + totalt/pricesToday.size()); + String test = System.console().readLine("Skriv något!: "); + System.out.println(test); } diff --git a/src/test/java/com/example/MainTest.java b/src/test/java/com/example/MainTest.java index 6199d951..c61f3589 100644 --- a/src/test/java/com/example/MainTest.java +++ b/src/test/java/com/example/MainTest.java @@ -43,7 +43,8 @@ void getPriser_shouldReturnParsedPrices_whenMockDataIsProvided() { [{"SEK_per_kWh":0.12229,"EUR_per_kWh":0.01112,"EXR":10.997148,"time_start":"2025-09-04T00:00:00+02:00","time_end":"2025-09-04T01:00:00+02:00"},{"SEK_per_kWh":0.09886,"EUR_per_kWh":0.00899,"EXR":10.997148,"time_start":"2025-09-04T01:00:00+02:00","time_end":"2025-09-04T02:00:00+02:00"},{"SEK_per_kWh":0.09095,"EUR_per_kWh":0.00827,"EXR":10.997148,"time_start":"2025-09-04T02:00:00+02:00","time_end":"2025-09-04T03:00:00+02:00"},{"SEK_per_kWh":0.04201,"EUR_per_kWh":0.00382,"EXR":10.997148,"time_start":"2025-09-04T03:00:00+02:00","time_end":"2025-09-04T04:00:00+02:00"},{"SEK_per_kWh":0.04146,"EUR_per_kWh":0.00377,"EXR":10.997148,"time_start":"2025-09-04T04:00:00+02:00","time_end":"2025-09-04T05:00:00+02:00"},{"SEK_per_kWh":0.04465,"EUR_per_kWh":0.00406,"EXR":10.997148,"time_start":"2025-09-04T05:00:00+02:00","time_end":"2025-09-04T06:00:00+02:00"},{"SEK_per_kWh":0.32991,"EUR_per_kWh":0.03,"EXR":10.997148,"time_start":"2025-09-04T06:00:00+02:00","time_end":"2025-09-04T07:00:00+02:00"},{"SEK_per_kWh":0.47123,"EUR_per_kWh":0.04285,"EXR":10.997148,"time_start":"2025-09-04T07:00:00+02:00","time_end":"2025-09-04T08:00:00+02:00"},{"SEK_per_kWh":0.68182,"EUR_per_kWh":0.062,"EXR":10.997148,"time_start":"2025-09-04T08:00:00+02:00","time_end":"2025-09-04T09:00:00+02:00"},{"SEK_per_kWh":0.4125,"EUR_per_kWh":0.03751,"EXR":10.997148,"time_start":"2025-09-04T09:00:00+02:00","time_end":"2025-09-04T10:00:00+02:00"},{"SEK_per_kWh":0.29571,"EUR_per_kWh":0.02689,"EXR":10.997148,"time_start":"2025-09-04T10:00:00+02:00","time_end":"2025-09-04T11:00:00+02:00"},{"SEK_per_kWh":0.06136,"EUR_per_kWh":0.00558,"EXR":10.997148,"time_start":"2025-09-04T11:00:00+02:00","time_end":"2025-09-04T12:00:00+02:00"},{"SEK_per_kWh":0.03662,"EUR_per_kWh":0.00333,"EXR":10.997148,"time_start":"2025-09-04T12:00:00+02:00","time_end":"2025-09-04T13:00:00+02:00"},{"SEK_per_kWh":0.0375,"EUR_per_kWh":0.00341,"EXR":10.997148,"time_start":"2025-09-04T13:00:00+02:00","time_end":"2025-09-04T14:00:00+02:00"},{"SEK_per_kWh":0.26822,"EUR_per_kWh":0.02439,"EXR":10.997148,"time_start":"2025-09-04T14:00:00+02:00","time_end":"2025-09-04T15:00:00+02:00"},{"SEK_per_kWh":0.30429,"EUR_per_kWh":0.02767,"EXR":10.997148,"time_start":"2025-09-04T15:00:00+02:00","time_end":"2025-09-04T16:00:00+02:00"},{"SEK_per_kWh":0.36675,"EUR_per_kWh":0.03335,"EXR":10.997148,"time_start":"2025-09-04T16:00:00+02:00","time_end":"2025-09-04T17:00:00+02:00"},{"SEK_per_kWh":0.58296,"EUR_per_kWh":0.05301,"EXR":10.997148,"time_start":"2025-09-04T17:00:00+02:00","time_end":"2025-09-04T18:00:00+02:00"},{"SEK_per_kWh":0.92145,"EUR_per_kWh":0.08379,"EXR":10.997148,"time_start":"2025-09-04T18:00:00+02:00","time_end":"2025-09-04T19:00:00+02:00"},{"SEK_per_kWh":1.5054,"EUR_per_kWh":0.13689,"EXR":10.997148,"time_start":"2025-09-04T19:00:00+02:00","time_end":"2025-09-04T20:00:00+02:00"},{"SEK_per_kWh":1.00888,"EUR_per_kWh":0.09174,"EXR":10.997148,"time_start":"2025-09-04T20:00:00+02:00","time_end":"2025-09-04T21:00:00+02:00"},{"SEK_per_kWh":0.63179,"EUR_per_kWh":0.05745,"EXR":10.997148,"time_start":"2025-09-04T21:00:00+02:00","time_end":"2025-09-04T22:00:00+02:00"},{"SEK_per_kWh":0.56382,"EUR_per_kWh":0.05127,"EXR":10.997148,"time_start":"2025-09-04T22:00:00+02:00","time_end":"2025-09-04T23:00:00+02:00"},{"SEK_per_kWh":0.52951,"EUR_per_kWh":0.04815,"EXR":10.997148,"time_start":"2025-09-04T23:00:00+02:00","time_end":"2025-09-05T00:00:00+02:00"}]"""; // 2. Set the mock response using the static method. - ElpriserAPI.setMockResponse(fakeJson); + LocalDate today = LocalDate.of(2025, 9, 4); + ElpriserAPI.setMockResponseForDate(today,fakeJson); // 3. Create an instance of the class as a student would. ElpriserAPI api = new ElpriserAPI(false); // Disable caching for predictable tests @@ -109,7 +110,8 @@ void displayMeanPrice_withValidData() { {"SEK_per_kWh":0.30,"EUR_per_kWh":0.03,"EXR":10.0,"time_start":"2025-09-04T02:00:00+02:00","time_end":"2025-09-04T03:00:00+02:00"}, {"SEK_per_kWh":0.40,"EUR_per_kWh":0.04,"EXR":10.0,"time_start":"2025-09-04T03:00:00+02:00","time_end":"2025-09-04T04:00:00+02:00"}]"""; - ElpriserAPI.setMockResponse(mockJson); + LocalDate today = LocalDate.of(2025, 9, 4); + ElpriserAPI.setMockResponseForDate(today,mockJson); Main.main(new String[]{"--zone", "SE3", "--date", "2025-09-04"}); @@ -127,7 +129,8 @@ void displayMinMaxPrices_withValidData() { {"SEK_per_kWh":0.80,"EUR_per_kWh":0.08,"EXR":10.0,"time_start":"2025-09-04T02:00:00+02:00","time_end":"2025-09-04T03:00:00+02:00"}, {"SEK_per_kWh":0.30,"EUR_per_kWh":0.03,"EXR":10.0,"time_start":"2025-09-04T03:00:00+02:00","time_end":"2025-09-04T04:00:00+02:00"}]"""; - ElpriserAPI.setMockResponse(mockJson); + LocalDate today = LocalDate.of(2025, 9, 4); + ElpriserAPI.setMockResponseForDate(today,mockJson); Main.main(new String[]{"--zone", "SE1", "--date", "2025-09-04"}); @@ -144,13 +147,22 @@ void displayMinMaxPrices_withValidData() { @Test void displaySortedPrices_whenRequested() { - String mockJson = """ - [{"SEK_per_kWh":0.30,"EUR_per_kWh":0.03,"EXR":10.0,"time_start":"2025-09-04T00:00:00+02:00","time_end":"2025-09-04T01:00:00+02:00"}, - {"SEK_per_kWh":0.10,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-04T01:00:00+02:00","time_end":"2025-09-04T02:00:00+02:00"}, - {"SEK_per_kWh":0.20,"EUR_per_kWh":0.02,"EXR":10.0,"time_start":"2025-09-04T02:00:00+02:00","time_end":"2025-09-04T03:00:00+02:00"}, - {"SEK_per_kWh":0.10,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-04T03:00:00+02:00","time_end":"2025-09-04T04:00:00+02:00"}]"""; + // This test ensures charging window can span days when next day data exists + LocalDate today = LocalDate.of(2025, 9, 4); + LocalDate tomorrow = today.plusDays(1); - ElpriserAPI.setMockResponse(mockJson); + String mockJsonToday = """ + [{"SEK_per_kWh":0.30,"EUR_per_kWh":0.03,"EXR":10.0,"time_start":"2025-09-04T20:00:00+02:00","time_end":"2025-09-04T21:00:00+02:00"}, + {"SEK_per_kWh":0.10,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-04T21:00:00+02:00","time_end":"2025-09-04T22:00:00+02:00"}, + {"SEK_per_kWh":0.20,"EUR_per_kWh":0.02,"EXR":10.0,"time_start":"2025-09-04T22:00:00+02:00","time_end":"2025-09-04T23:00:00+02:00"}, + {"SEK_per_kWh":0.10,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-04T23:00:00+02:00","time_end":"2025-09-04T00:00:00+02:00"}]"""; + String mockJsonTomorrow = """ + [{"SEK_per_kWh":0.10,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-05T00:00:00+02:00","time_end":"2025-09-05T01:00:00+02:00"}, + {"SEK_per_kWh":0.15,"EUR_per_kWh":0.015,"EXR":10.0,"time_start":"2025-09-05T01:00:00+02:00","time_end":"2025-09-05T02:00:00+02:00"}, + {"SEK_per_kWh":0.15,"EUR_per_kWh":0.015,"EXR":10.0,"time_start":"2025-09-05T02:00:00+02:00","time_end":"2025-09-05T03:00:00+02:00"}]"""; + + ElpriserAPI.setMockResponseForDate(today, mockJsonToday); + ElpriserAPI.setMockResponseForDate(tomorrow, mockJsonTomorrow); Main.main(new String[]{"--zone", "SE2", "--date", "2025-09-04", "--sorted"}); @@ -158,10 +170,13 @@ void displaySortedPrices_whenRequested() { // Expected sorted output (ascending by price) List expectedOrder = List.of( - "01-02 10,00 öre", - "03-04 10,00 öre", - "02-03 20,00 öre", - "00-01 30,00 öre" + "20-21 30,00 öre", + "22-23 20,00 öre", + "01-02 15,00 öre", + "02-03 15,00 öre", + "21-22 10,00 öre", + "23-00 10,00 öre", + "00-01 10,00 öre" ); // Extract actual lines that match the pattern @@ -183,7 +198,9 @@ void findOptimalCharging2Hours() { {"SEK_per_kWh":0.15,"EUR_per_kWh":0.015,"EXR":10.0,"time_start":"2025-09-04T03:00:00+02:00","time_end":"2025-09-04T04:00:00+02:00"}, {"SEK_per_kWh":0.30,"EUR_per_kWh":0.03,"EXR":10.0,"time_start":"2025-09-04T04:00:00+02:00","time_end":"2025-09-04T05:00:00+02:00"}]"""; - ElpriserAPI.setMockResponse(mockJson); + LocalDate today = LocalDate.of(2025, 9, 4); + + ElpriserAPI.setMockResponseForDate(today, mockJson); Main.main(new String[]{"--zone", "SE3", "--date", "2025-09-04", "--charging", "2h"}); @@ -204,7 +221,9 @@ void findOptimalCharging4Hours() { {"SEK_per_kWh":0.20,"EUR_per_kWh":0.02,"EXR":10.0,"time_start":"2025-09-04T04:00:00+02:00","time_end":"2025-09-04T05:00:00+02:00"}, {"SEK_per_kWh":0.30,"EUR_per_kWh":0.03,"EXR":10.0,"time_start":"2025-09-04T05:00:00+02:00","time_end":"2025-09-04T06:00:00+02:00"}]"""; - ElpriserAPI.setMockResponse(mockJson); + LocalDate today = LocalDate.of(2025, 9, 4); + + ElpriserAPI.setMockResponseForDate(today, mockJson); Main.main(new String[]{"--zone", "SE1", "--date", "2025-09-04", "--charging", "4h"}); @@ -223,7 +242,9 @@ void chargingWindowDoesNotUseNextDay_whenNextDayUnavailable() { [{"SEK_per_kWh":0.20,"EUR_per_kWh":0.02,"EXR":10.0,"time_start":"2025-09-04T00:00:00+02:00","time_end":"2025-09-04T01:00:00+02:00"}, {"SEK_per_kWh":0.10,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-04T01:00:00+02:00","time_end":"2025-09-04T02:00:00+02:00"}, {"SEK_per_kWh":0.15,"EUR_per_kWh":0.015,"EXR":10.0,"time_start":"2025-09-04T02:00:00+02:00","time_end":"2025-09-04T03:00:00+02:00"}]"""; - ElpriserAPI.setMockResponse(mockJsonToday); + LocalDate today = LocalDate.of(2025, 9, 4); + ElpriserAPI.setMockResponseForDate(today,mockJsonToday); + Main.main(new String[]{"--zone", "SE3", "--date", "2025-09-04", "--charging", "2h"}); String output = bos.toString(); // Best 2h window should be 01-03 (0.10 + 0.15) @@ -235,7 +256,7 @@ void chargingWindowDoesNotUseNextDay_whenNextDayUnavailable() { void findOptimalCharging8Hours() { // Create mock data with 12 hours to allow for 8-hour window StringBuilder jsonBuilder = new StringBuilder("["); - double[] prices = {0.50, 0.10, 0.05, 0.15, 0.08, 0.12, 0.06, 0.09, 0.25, 0.30, 0.35, 0.40}; + double[] prices = {0.50, 0.10, 0.05, 0.15, 0.08, 0.12, 0.06, 0.09, 0.25, 0.30, 0.35, 0.40, 0.50, 0.10, 0.05, 0.15, 0.08, 0.12, 0.06, 0.09, 0.25, 0.30, 0.35, 0.40}; for (int i = 0; i < prices.length; i++) { if (i > 0) jsonBuilder.append(","); @@ -243,12 +264,20 @@ void findOptimalCharging8Hours() { Locale.US, """ {"SEK_per_kWh":%.2f,"EUR_per_kWh":%.3f,"EXR":10.0,"time_start":"2025-09-04T%02d:00:00+02:00","time_end":"2025-09-04T%02d:00:00+02:00"}""", - prices[i], prices[i] / 10, i, i + 1 + prices[i], prices[i] / 10, i, (i + 1) % 24 )); } jsonBuilder.append("]"); - ElpriserAPI.setMockResponse(jsonBuilder.toString()); + LocalDate today = LocalDate.of(2025, 9, 4); + ElpriserAPI.setMockResponseForDate(today, jsonBuilder.toString()); + + LocalDate tomorrow = today.plusDays(1); + String mockJsonTomorrow = """ + [{"SEK_per_kWh":0.1,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"2025-09-05T00:00:00+02:00","time_end":"2025-09-05T01:00:00+02:00"}, + {"SEK_per_kWh":0.15,"EUR_per_kWh":0.015,"EXR":10.0,"time_start":"2025-09-05T01:00:00+02:00","time_end":"2025-09-05T02:00:00+02:00"}, + {"SEK_per_kWh":0.15,"EUR_per_kWh":0.015,"EXR":10.0,"time_start":"2025-09-05T02:00:00+02:00","time_end":"2025-09-05T03:00:00+02:00"}]"""; + ElpriserAPI.setMockResponseForDate(tomorrow, mockJsonTomorrow); Main.main(new String[]{"--zone", "SE4", "--date", "2025-09-04", "--charging", "8h"}); @@ -359,66 +388,63 @@ void chargingWindowSpansToNextDay_whenCheapestCrossesMidnight() { } @Test - public void testHourlyMinMaxPrices() { - List quarterHourPrices = new ArrayList<>(); - - // Simulate 96 prices: 24 hours, each with 4 quarter-hour prices - for (int i = 0; i < 96; i++) { - quarterHourPrices.add((double) (i % 24)); // repeating hourly pattern - } + void testHourlyMinMaxPrices_with96Entries() { + // --- ARRANGE --- + LocalDate today = LocalDate.of(2025, 9, 4); + StringBuilder jsonBuilder = new StringBuilder("["); - // Expected hourly averages - List hourlyAverages = new ArrayList<>(); - for (int i = 0; i < 24; i++) { - double sum = 0; - for (int j = 0; j < 4; j++) { - sum += quarterHourPrices.get(i * 4 + j); + for (int hour = 0; hour < 24; hour++) { + for (int quarter = 0; quarter < 4; quarter++) { + if (hour > 0 || quarter > 0) { + jsonBuilder.append(","); + } + double price = (hour * 0.1) + (quarter * 0.01) + 0.10; + String time_start = String.format("2025-09-04T%02d:%02d:00+02:00", hour, quarter * 15); + String time_end = String.format("2025-09-04T%02d:%02d:00+02:00", hour, (quarter + 1) * 15); + if (quarter == 3) { // Handle end of hour + time_end = String.format("2025-09-04T%02d:00:00+02:00", (hour + 1) % 24); + } + + jsonBuilder.append(String.format(Locale.US, + """ + {"SEK_per_kWh":%.4f,"EUR_per_kWh":0.01,"EXR":10.0,"time_start":"%s","time_end":"%s"}""", + price, time_start, time_end)); } - hourlyAverages.add(sum / 4.0); } + jsonBuilder.append("]"); + ElpriserAPI.setMockResponseForDate(today, jsonBuilder.toString()); - double expectedMin = Collections.min(hourlyAverages); - double expectedMax = Collections.max(hourlyAverages); + // --- ACT --- + Main.main(new String[]{"--zone", "SE3", "--date", "2025-09-04"}); - // Call your method under test - PriceRange result = PriceCalculator.calculateHourlyMinMax(quarterHourPrices); + // --- ASSERT --- + String output = bos.toString(); + assertThat(output).containsIgnoringCase("lägsta pris"); + assertThat(output).containsIgnoringCase("högsta pris"); + assertThat(output).containsIgnoringCase("medelpris"); - assertThat(result.getMin()).isCloseTo(expectedMin, within(0.001)); - assertThat(result.getMax()).isCloseTo(expectedMax, within(0.001)); + // Expected Min: Hour 0 -> avg(0.10, 0.11, 0.12, 0.13) = 0.115 SEK/kWh = 11,50 öre + // Expected Max: Hour 23 -> avg(2.40, 2.41, 2.42, 2.43) = 2.415 SEK/kWh = 241,50 öre + assertThat(output).contains("00-01"); // Cheapest hour + assertThat(output).contains("23-00"); // Most expensive hour + assertThat(output).contains(formatOre(0.115)); + assertThat(output).contains(formatOre(2.415)); + + // Calculate overall average for the day + double totalSum = 0; + for (int hour = 0; hour < 24; hour++) { + for (int quarter = 0; quarter < 4; quarter++) { + totalSum += (hour * 0.1) + (quarter * 0.01) + 0.10; + } + } + double expectedMean = totalSum / 96; + assertThat(output).contains("Medelpris: " + formatOre(expectedMean) + " öre"); } private String formatOre(double sekPerKWh) { double ore = sekPerKWh * 100.0; - DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.of("sv", "SE")); + DecimalFormatSymbols symbols = new DecimalFormatSymbols(new Locale("sv", "SE")); DecimalFormat df = new DecimalFormat("0.00", symbols); return df.format(ore); } -} -class PriceRange { - private final double min; - private final double max; - - public PriceRange(double min, double max) { - this.min = min; - this.max = max; - } - - public double getMin() { return min; } - public double getMax() { return max; } -} - -class PriceCalculator { - public static PriceRange calculateHourlyMinMax(List quarterHourPrices) { - List hourlyAverages = new ArrayList<>(); - for (int i = 0; i < 24; i++) { - double sum = 0; - for (int j = 0; j < 4; j++) { - sum += quarterHourPrices.get(i * 4 + j); - } - hourlyAverages.add(sum / 4.0); - } - double min = Collections.min(hourlyAverages); - double max = Collections.max(hourlyAverages); - return new PriceRange(min, max); - } } \ No newline at end of file From 0f1de4bb606d07e997be1c1db5337c563774548e Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:49:50 +0200 Subject: [PATCH 07/17] =?UTF-8?q?b=C3=B6rjat=20om=20p=C3=A5=20nytt,=20b?= =?UTF-8?q?=C3=A4ttre=20strukturerat.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 265 +++++++++++++++++++++++++--- 1 file changed, 238 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 21877038..28d097c7 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,55 +1,266 @@ package com.example; - import com.example.api.ElpriserAPI; +import java.text.NumberFormat; import java.time.LocalDate; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Locale; + +import com.example.api.ElpriserAPI.Prisklass; +import com.example.api.ElpriserAPI.Elpris; +import static com.example.api.ElpriserAPI.Prisklass.SE1; + public class Main { public static void main(String[] args) { - // skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll + + //Formatering till svenska decimaler + NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); + //Hur många siffror/decimaler som ska ingå + decimalFormatering.setMaximumFractionDigits(2); + decimalFormatering.setMinimumFractionDigits(2); + decimalFormatering.setMinimumIntegerDigits(2); + + // Skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll ElpriserAPI api = new ElpriserAPI(); + // Variabler + Prisklass zone = SE1; + LocalDate date = LocalDate.now(); + String chargingWindow = "0H"; + + boolean isCliRunning = false; + boolean isSorted = false; + boolean isProgramClosing = false; + + int minIndex; + int maxIndex; + + double meanPrice; + +/* ***************************************************************************************************************************************** */ +/* ************************************************************** KÖR PROGRAM ************************************************************** */ +/* ***************************************************************************************************************************************** */ - //testar args.length - if(args.length > 0){ - System.out.println("args length: " + args.length); - System.out.println("args[2]: " + args[2]); - } else{ - System.out.println("Nothing here."); + System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + System.out.println(""" + ###################################################################### + ###################### APPLIKATION INITIERAD ######################### + ###################################################################### + """); + if (args.length == 0) { + //Interaktivt + drawInterfaceMenu(); } + else { + //CLI + isCliRunning = true; + Prisklass zoneTest = zoneValidation(checkArgsForZone(args), true); + System.out.println(zoneTest); + } + + + + + + + + +/* ***************************************************************************************************************************************** */ +/* ************************************************************** HÄMTA VÄRDEN ************************************************************* */ +/* ***************************************************************************************************************************************** */ - // datum - LocalDate todaysDate = LocalDate.now(); - LocalDate tomorrowsDate = LocalDate.now().plusDays(1); - LocalDate chosenDate; - int day = LocalDate.now().getDayOfMonth(); + // Hämta dagens och morgondagens värden + List firstDay = new ArrayList<>(api.getPriser(date, zone)); + List secondDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); + List bothDays = addLists(firstDay, secondDay); + // Räkna ut min, max- och medelpris + meanPrice = meanPriceCalculation(firstDay); + minIndex = minPriceCalculation(firstDay); + maxIndex = maxPriceCalculation(firstDay); + double minPrice = firstDay.get(minIndex).sekPerKWh() * 100; + double maxPrice = firstDay.get(maxIndex).sekPerKWh() * 100; - if(todaysDate.isBefore(tomorrowsDate)){ - System.out.println("todays date is before tomorrows date"); + System.out.println("\nMedelpris: " + meanPrice); + System.out.println("Lägsta pris: " + decimalFormatering.format(minPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(minIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(minIndex).timeEnd().getHour())); + System.out.println("Högsta pris: " + decimalFormatering.format(maxPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(maxIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(maxIndex).timeEnd().getHour())); + + +// // RADERA : Skriv ut varje timme +// for (Elpris firstDays : firstDay) { +// System.out.println(firstDays); +// } + + //ERROR TEST : Stänger evighetsloop + System.out.println("\nAvslutar applikationen.\n"); + System.exit(0); + } + + +/* ***************************************************************************************************************************************** */ +/* **************************************************************** METODER **************************************************************** */ +/* ***************************************************************************************************************************************** */ + + /* ################## CLI ################## */ + //OK-ish + public static void helpCli() { + System.out.println("\n\n\t################################################## HJÄLP #########################################################\n"); + + System.out.println("\tZONE: --zone SE1/SE2/SE3/SE4 | Vilken zon priserna ska hämtas ifrån."); + System.out.println("\t SE1 = norra Sverige | SE2 = norra mellansverige | SE3 = södra mellansverige | SE4 = södra Sverige\n"); + System.out.println("\tDATE: --date YYYY-MM-DD | Vilket datum priserna ska hämtas ifrån. Om datum inte angivits används dagens datum.\n"); + System.out.println("\tCHARGING:--charging 0H/2H/4H/8H | Ange för att hitta det billigaste laddningsfönstret.\n"); + System.out.println("\tSORTED: --sorted | Sortera listan från lägsta pris till högsta pris."); + + System.out.println("\n\t##################################################################################################################"); + + exitApplication(); + + } + + /* ################## INTERFACE ################## */ + // OK + public static void drawInterfaceMenu() { + System.out.println("************** KATEGORIER **************"); + System.out.println("usage | zone | date | charging | sorted | exit"); + } + //OK + public static String chooseInterfaceCategory(){ + String[] categories = { "usage", "zone", "date", "charging", "sorted", "exit"}; + String category; + + while (true) { + category = System.console().readLine("Välj kategori: "); + for (int i = 0; i < categories.length; i++){ + if (categories[i].equals(category)){ + return category; + } + } + } + } + + /* ################## ZONES ################## */ + //OK + public static String zoneInterfaceInput(){ + System.out.println("Ange zon SE1 | SE2 | SE3 | SE4:"); + return System.console().readLine(); + } + + //OK + public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) { + + while (true) { + try { + return Prisklass.valueOf(methodInput.toUpperCase()); + } + catch (IllegalArgumentException e) { + if (isCliRunning){ + System.out.print("!! zone required: Giltig zon krävs. "); + exitApplication(); + } + else { + System.out.println("!! zone required: Giltig zon krävs."); + methodInput = zoneInterfaceInput(); + } + } + } + } + + public static String checkArgsForZone(String[] argsArray) { + for (int i = 0; i < argsArray.length; i++){ + if (argsArray[i].equals("--zone")){ + return argsArray[i+1]; + } + } + System.out.println("Ingen giltig zon har angetts, ange --zone SE1|SE2|SE3|SE4"); + exitApplication(); + } + + /* ################## OTHER ################## */ + + //OK + public static LocalDate dateValidation(String dateInput) { + try { + return LocalDate.parse(dateInput); + } catch (Exception e) { + System.out.println("!! OGILTIGT DATUM: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Programmet kommer att köras med dagens datum."); + return LocalDate.now(); + } + } + + public static String chargingWindowValidation(String chargingInput) { + if (chargingInput.equalsIgnoreCase("2h") || chargingInput.equalsIgnoreCase("4h") || chargingInput.equalsIgnoreCase("8h")) { + return chargingInput.toUpperCase(); + } else { + System.out.println("!! OGILTIG INMATNING: \"" + chargingInput + "\". Kör programmet utan laddningsfönster."); + return "0H"; + } + + } + + public static List addLists(List firstDay, List secondDay) { + List tempList = new ArrayList<>(); + + + // Kolla om värdena laddats ned + if (!firstDay.isEmpty() && !secondDay.isEmpty()) { + tempList.addAll(firstDay); + tempList.addAll(secondDay); + } else if (!firstDay.isEmpty()) { + tempList.addAll(firstDay); } else { - System.out.println("todays date is not before tomorrows date"); + System.out.println("!! Ingen data kunde hämtas."); } + return tempList; + } + public static double meanPriceCalculation(List list) { + double sum = 0; + int numberCount = list.size(); - List pricesToday = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); - List pricesTomorrow = new ArrayList<>(api.getPriser(LocalDate.now(), ElpriserAPI.Prisklass.SE3)); + for (int i = 0; i < numberCount; i++) { + sum += list.get(i).sekPerKWh(); + } + return sum / numberCount; + } - double totalt = 0; - for(int i = 0; i < pricesToday.size(); i++){ - System.out.println(pricesToday.get(i).sekPerKWh()); - totalt += pricesToday.get(i).sekPerKWh(); + public static int minPriceCalculation(List list) { + double min = list.getFirst().sekPerKWh(); + int minIndex = 0; + for (int i = 0; i < list.size(); i++) { + if (list.get(i).sekPerKWh() < min) { + min = list.get(i).sekPerKWh(); + minIndex = i; + } } - System.out.println("Total: " + totalt); - System.out.println("Medelvärde: " + totalt/pricesToday.size()); - String test = System.console().readLine("Skriv något!: "); - System.out.println(test); + return minIndex; + } + public static int maxPriceCalculation(List list) { + double max = list.getFirst().sekPerKWh(); + int maxIndex = 0; + for (int i = 0; i < list.size(); i++) { + if (list.get(i).sekPerKWh() > max) { + max = list.get(i).sekPerKWh(); + maxIndex = i; + } + } + + return maxIndex; + } + + public static void exitApplication(){ + System.out.println("Stänger applikationen..."); + System.exit(0); } + } + + + + From c2f44ce3a5578c6f0b2c232bc2773694327f17f1 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:21:07 +0200 Subject: [PATCH 08/17] flesta metoder klara --- src/main/java/com/example/Main.java | 240 +++++++++++++++++----------- 1 file changed, 150 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 28d097c7..eac4a8cf 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,6 +1,7 @@ package com.example; import com.example.api.ElpriserAPI; +import java.sql.SQLOutput; import java.text.NumberFormat; import java.time.LocalDate; import java.util.ArrayList; @@ -10,7 +11,7 @@ import com.example.api.ElpriserAPI.Prisklass; import com.example.api.ElpriserAPI.Elpris; import static com.example.api.ElpriserAPI.Prisklass.SE1; - +import static com.example.api.ElpriserAPI.Prisklass.SE3; public class Main { public static void main(String[] args) { @@ -43,50 +44,56 @@ public static void main(String[] args) { /* ************************************************************** KÖR PROGRAM ************************************************************** */ /* ***************************************************************************************************************************************** */ - System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - System.out.println(""" + System.out.println("\n\n\n\n\n" + """ ###################################################################### ###################### APPLIKATION INITIERAD ######################### ###################################################################### """); + + /* ######## INTERAKTIVT ####### */ if (args.length == 0) { - //Interaktivt drawInterfaceMenu(); } + + /* ######## CLI ####### */ else { - //CLI isCliRunning = true; - Prisklass zoneTest = zoneValidation(checkArgsForZone(args), true); - System.out.println(zoneTest); - } - - - - + if (args.length == 1) { + helpCli(); + } + zone = zoneValidation(checkArgsForZone(args), isCliRunning); + date = checkArgsForDate(args); + chargingWindow = checkArgsForCharging(args); + isSorted = checkArgsForSorted(args); + System.out.println(zone); + System.out.println(date); + System.out.println(chargingWindow); + System.out.println(isSorted); + } /* ***************************************************************************************************************************************** */ /* ************************************************************** HÄMTA VÄRDEN ************************************************************* */ /* ***************************************************************************************************************************************** */ - // Hämta dagens och morgondagens värden - List firstDay = new ArrayList<>(api.getPriser(date, zone)); - List secondDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); - List bothDays = addLists(firstDay, secondDay); - - // Räkna ut min, max- och medelpris - meanPrice = meanPriceCalculation(firstDay); - minIndex = minPriceCalculation(firstDay); - maxIndex = maxPriceCalculation(firstDay); - - double minPrice = firstDay.get(minIndex).sekPerKWh() * 100; - double maxPrice = firstDay.get(maxIndex).sekPerKWh() * 100; - - System.out.println("\nMedelpris: " + meanPrice); - System.out.println("Lägsta pris: " + decimalFormatering.format(minPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(minIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(minIndex).timeEnd().getHour())); - System.out.println("Högsta pris: " + decimalFormatering.format(maxPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(maxIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(maxIndex).timeEnd().getHour())); +// // Hämta dagens och morgondagens värden +// List firstDay = new ArrayList<>(api.getPriser(date, zone)); +// List secondDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); +// List bothDays = addLists(firstDay, secondDay); +// +// // Räkna ut min, max- och medelpris +// meanPrice = meanPriceCalculation(firstDay); +// minIndex = minPriceCalculation(firstDay); +// maxIndex = maxPriceCalculation(firstDay); +// +// double minPrice = firstDay.get(minIndex).sekPerKWh() * 100; +// double maxPrice = firstDay.get(maxIndex).sekPerKWh() * 100; +// +// System.out.println("\nMedelpris: " + meanPrice); +// System.out.println("Lägsta pris: " + decimalFormatering.format(minPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(minIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(minIndex).timeEnd().getHour())); +// System.out.println("Högsta pris: " + decimalFormatering.format(maxPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(maxIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(maxIndex).timeEnd().getHour())); // // RADERA : Skriv ut varje timme @@ -95,7 +102,7 @@ public static void main(String[] args) { // } //ERROR TEST : Stänger evighetsloop - System.out.println("\nAvslutar applikationen.\n"); + System.out.println("\nSlutet av koden: Avslutar applikationen.\n"); System.exit(0); } @@ -105,7 +112,7 @@ public static void main(String[] args) { /* ***************************************************************************************************************************************** */ /* ################## CLI ################## */ - //OK-ish + // OK-ish, bygg på public static void helpCli() { System.out.println("\n\n\t################################################## HJÄLP #########################################################\n"); @@ -118,38 +125,96 @@ public static void helpCli() { System.out.println("\n\t##################################################################################################################"); exitApplication(); + } + + // OK + public static String checkArgsForZone(String[] argsArray) { + for (int i = 0; i < argsArray.length; i++){ + if (argsArray[i].equalsIgnoreCase("--zone") && i < argsArray.length-1){ + return argsArray[i+1]; + } + } + System.out.println("zone required : Ingen zone har angetts, ange --zone SE1|SE2|SE3|SE4 vid initiering."); + exitApplication(); + // Return behövs för att compilern ska vara glad, även om det inte körs + return "null"; + } + //OK + public static LocalDate checkArgsForDate(String[] argsArray) { + for (int i = 0; i < argsArray.length; i++){ + if (argsArray[i].equalsIgnoreCase("--date") && i < argsArray.length-1){ + return dateValidation(argsArray[i+1]); + } + } + System.out.println("Inget datum angett, applikationen kommer att köras med dagens datum."); + return LocalDate.now(); + } + + //OK + public static String checkArgsForCharging(String[] argsArray) { + for (int i = 0; i < argsArray.length; i++){ + if (argsArray[i].equalsIgnoreCase("--charging") && i < argsArray.length-1){ + return chargingWindowValidation(argsArray[i+1]); + } + } + System.out.println("!! OGILTIGT LADDNINGSFÖNSTER: Kör programmet utan laddningsfönster."); + return "0H"; + } + + public static boolean checkArgsForSorted(String[] argsArray) { + for (String array : argsArray) { + if (array.equalsIgnoreCase("--sorted")){ + return true; + } + } + return false; } /* ################## INTERFACE ################## */ // OK public static void drawInterfaceMenu() { - System.out.println("************** KATEGORIER **************"); + System.out.println("***************** KATEGORIER *****************"); System.out.println("usage | zone | date | charging | sorted | exit"); + chooseInterfaceCategory(); } - //OK + + // OK public static String chooseInterfaceCategory(){ - String[] categories = { "usage", "zone", "date", "charging", "sorted", "exit"}; - String category; + String[] categories = { "usage", "zone", "date", "charging", "sorted"}; + String categoryInput; while (true) { - category = System.console().readLine("Välj kategori: "); - for (int i = 0; i < categories.length; i++){ - if (categories[i].equals(category)){ - return category; - } + categoryInput = System.console().readLine("Välj kategori: "); + if (categoryInput.equalsIgnoreCase("exit")) { + break; } + else { + for (String category : categories) { + if (category.equalsIgnoreCase(categoryInput)) { + return categoryInput; + } + } + //Sparar ifall jag misslyckades med enhanced for-loopen +// for (int i = 0; i < categories.length; i++){ +// if (categories[i].equalsIgnoreCase(categoryInput)){ +// return categoryInput; +// } + } + } + exitApplication(); + return "null"; } /* ################## ZONES ################## */ - //OK + // OK public static String zoneInterfaceInput(){ - System.out.println("Ange zon SE1 | SE2 | SE3 | SE4:"); + System.out.println("Ange zon: SE1, SE2, SE3 eller SE4:"); return System.console().readLine(); } - //OK + // OK public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) { while (true) { @@ -169,54 +234,7 @@ public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) } } - public static String checkArgsForZone(String[] argsArray) { - for (int i = 0; i < argsArray.length; i++){ - if (argsArray[i].equals("--zone")){ - return argsArray[i+1]; - } - } - System.out.println("Ingen giltig zon har angetts, ange --zone SE1|SE2|SE3|SE4"); - exitApplication(); - } - - /* ################## OTHER ################## */ - - //OK - public static LocalDate dateValidation(String dateInput) { - try { - return LocalDate.parse(dateInput); - } catch (Exception e) { - System.out.println("!! OGILTIGT DATUM: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Programmet kommer att köras med dagens datum."); - return LocalDate.now(); - } - } - - public static String chargingWindowValidation(String chargingInput) { - if (chargingInput.equalsIgnoreCase("2h") || chargingInput.equalsIgnoreCase("4h") || chargingInput.equalsIgnoreCase("8h")) { - return chargingInput.toUpperCase(); - } else { - System.out.println("!! OGILTIG INMATNING: \"" + chargingInput + "\". Kör programmet utan laddningsfönster."); - return "0H"; - } - - } - - public static List addLists(List firstDay, List secondDay) { - List tempList = new ArrayList<>(); - - - // Kolla om värdena laddats ned - if (!firstDay.isEmpty() && !secondDay.isEmpty()) { - tempList.addAll(firstDay); - tempList.addAll(secondDay); - } else if (!firstDay.isEmpty()) { - tempList.addAll(firstDay); - } else { - System.out.println("!! Ingen data kunde hämtas."); - } - return tempList; - } - + /* ################## CALCULATIONS ################## */ public static double meanPriceCalculation(List list) { double sum = 0; int numberCount = list.size(); @@ -254,6 +272,48 @@ public static int maxPriceCalculation(List list) { return maxIndex; } + /* ################## OTHER ################## */ + // OK + public static List addLists(List firstDay, List secondDay) { + // Temporär lista + List twoDayList = new ArrayList<>(); + + // Kolla om värdena laddats ned + if (!firstDay.isEmpty() && !secondDay.isEmpty()) { + twoDayList.addAll(firstDay); + twoDayList.addAll(secondDay); + } + else { + System.out.println("!! Ingen data kunde hämtas."); + } + return twoDayList; + } + + // OK + public static LocalDate dateValidation(String dateInput) { + try { + return LocalDate.parse(dateInput); + } + catch (Exception e) { + System.out.println("!! OGILTIGT DATUM: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Applikationen kommer att köras med dagens datum."); + return LocalDate.now(); + } + } + + // OK + public static String chargingWindowValidation(String chargingInput) { + String[] chargingWindow = {"0H", "2H", "4H", "8H"}; + + for(String hours : chargingWindow){ + if (chargingInput.equalsIgnoreCase(hours)){ + return hours.toUpperCase(); + } + } + System.out.println("!! OGILTIGT LADDNINGSFÖNSTER: \"" + chargingInput + "\". Kör programmet utan laddningsfönster."); + return "0H"; + } + + // OK public static void exitApplication(){ System.out.println("Stänger applikationen..."); System.exit(0); From d01ddd7c60b895e7bf81c8852a3513beeca41608 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:35:20 +0200 Subject: [PATCH 09/17] Listor fungerar --- src/main/java/com/example/Main.java | 38 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index eac4a8cf..4a07756a 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -27,13 +27,17 @@ public static void main(String[] args) { ElpriserAPI api = new ElpriserAPI(); // Variabler - Prisklass zone = SE1; - LocalDate date = LocalDate.now(); - String chargingWindow = "0H"; + Prisklass zone; + LocalDate date; + + List firstDay; + List nextDay; + List bothDays; + + String chargingWindow; boolean isCliRunning = false; - boolean isSorted = false; - boolean isProgramClosing = false; + boolean isSorted; int minIndex; int maxIndex; @@ -67,6 +71,10 @@ public static void main(String[] args) { chargingWindow = checkArgsForCharging(args); isSorted = checkArgsForSorted(args); + firstDay = fetchContents(api.getPriser(date, zone)); + nextDay = fetchContents(api.getPriser(date.plusDays(1), zone)); + bothDays = addDays(firstDay, nextDay); + System.out.println(zone); System.out.println(date); System.out.println(chargingWindow); @@ -82,7 +90,7 @@ public static void main(String[] args) { // List firstDay = new ArrayList<>(api.getPriser(date, zone)); // List secondDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); // List bothDays = addLists(firstDay, secondDay); -// + // // Räkna ut min, max- och medelpris // meanPrice = meanPriceCalculation(firstDay); // minIndex = minPriceCalculation(firstDay); @@ -140,7 +148,7 @@ public static String checkArgsForZone(String[] argsArray) { return "null"; } - //OK + // OK public static LocalDate checkArgsForDate(String[] argsArray) { for (int i = 0; i < argsArray.length; i++){ if (argsArray[i].equalsIgnoreCase("--date") && i < argsArray.length-1){ @@ -151,17 +159,17 @@ public static LocalDate checkArgsForDate(String[] argsArray) { return LocalDate.now(); } - //OK + // OK public static String checkArgsForCharging(String[] argsArray) { for (int i = 0; i < argsArray.length; i++){ if (argsArray[i].equalsIgnoreCase("--charging") && i < argsArray.length-1){ return chargingWindowValidation(argsArray[i+1]); } } - System.out.println("!! OGILTIGT LADDNINGSFÖNSTER: Kör programmet utan laddningsfönster."); return "0H"; } + // OK public static boolean checkArgsForSorted(String[] argsArray) { for (String array : argsArray) { if (array.equalsIgnoreCase("--sorted")){ @@ -274,7 +282,12 @@ public static int maxPriceCalculation(List list) { /* ################## OTHER ################## */ // OK - public static List addLists(List firstDay, List secondDay) { + public static List fetchContents(List priceList) { + return new ArrayList<>(priceList); + } + + // OK + public static List addDays(List firstDay, List secondDay) { // Temporär lista List twoDayList = new ArrayList<>(); @@ -283,9 +296,6 @@ public static List addLists(List firstDay, List secondDa twoDayList.addAll(firstDay); twoDayList.addAll(secondDay); } - else { - System.out.println("!! Ingen data kunde hämtas."); - } return twoDayList; } @@ -319,6 +329,8 @@ public static void exitApplication(){ System.exit(0); } + /* ################## FOR TESTING ################## */ + } From 29c4a89d5b9392295a17ac0639582da44ae3a770 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:57:13 +0200 Subject: [PATCH 10/17] Sortering fungerar --- src/main/java/com/example/Main.java | 91 +++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 4a07756a..240c1e21 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,17 +1,15 @@ package com.example; import com.example.api.ElpriserAPI; -import java.sql.SQLOutput; import java.text.NumberFormat; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import com.example.api.ElpriserAPI.Prisklass; import com.example.api.ElpriserAPI.Elpris; -import static com.example.api.ElpriserAPI.Prisklass.SE1; -import static com.example.api.ElpriserAPI.Prisklass.SE3; public class Main { public static void main(String[] args) { @@ -31,17 +29,17 @@ public static void main(String[] args) { LocalDate date; List firstDay; + List sortedFirstDay; List nextDay; List bothDays; + List sortedBothDays; + List sortedList; String chargingWindow; boolean isCliRunning = false; boolean isSorted; - int minIndex; - int maxIndex; - double meanPrice; /* ***************************************************************************************************************************************** */ @@ -66,19 +64,25 @@ public static void main(String[] args) { helpCli(); } + // Kolla igenom args och sätt variabler zone = zoneValidation(checkArgsForZone(args), isCliRunning); date = checkArgsForDate(args); chargingWindow = checkArgsForCharging(args); isSorted = checkArgsForSorted(args); + // Hämta listor firstDay = fetchContents(api.getPriser(date, zone)); nextDay = fetchContents(api.getPriser(date.plusDays(1), zone)); - bothDays = addDays(firstDay, nextDay); + bothDays = addLists(firstDay, nextDay); + // Sortera listor + + if (isSorted){ + sortedFirstDay = sortFirstDay(firstDay); + sortedBothDays = sortBothDays(bothDays); + } + + - System.out.println(zone); - System.out.println(date); - System.out.println(chargingWindow); - System.out.println(isSorted); } @@ -86,11 +90,6 @@ public static void main(String[] args) { /* ************************************************************** HÄMTA VÄRDEN ************************************************************* */ /* ***************************************************************************************************************************************** */ -// // Hämta dagens och morgondagens värden -// List firstDay = new ArrayList<>(api.getPriser(date, zone)); -// List secondDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); -// List bothDays = addLists(firstDay, secondDay); - // // Räkna ut min, max- och medelpris // meanPrice = meanPriceCalculation(firstDay); // minIndex = minPriceCalculation(firstDay); @@ -103,12 +102,6 @@ public static void main(String[] args) { // System.out.println("Lägsta pris: " + decimalFormatering.format(minPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(minIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(minIndex).timeEnd().getHour())); // System.out.println("Högsta pris: " + decimalFormatering.format(maxPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(maxIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(maxIndex).timeEnd().getHour())); - -// // RADERA : Skriv ut varje timme -// for (Elpris firstDays : firstDay) { -// System.out.println(firstDays); -// } - //ERROR TEST : Stänger evighetsloop System.out.println("\nSlutet av koden: Avslutar applikationen.\n"); System.exit(0); @@ -280,14 +273,14 @@ public static int maxPriceCalculation(List list) { return maxIndex; } - /* ################## OTHER ################## */ + /* ################## LISTS ################## */ // OK public static List fetchContents(List priceList) { return new ArrayList<>(priceList); } // OK - public static List addDays(List firstDay, List secondDay) { + public static List addLists(List firstDay, List secondDay) { // Temporär lista List twoDayList = new ArrayList<>(); @@ -299,6 +292,49 @@ public static List addDays(List firstDay, List secondDay return twoDayList; } + public static List sortFirstDay(List firstDay) { + boolean doneSorting = false; + + while (!doneSorting){ + doneSorting = true; + for(int i = 0; i < firstDay.size()-1; i++ ){ + for (int j = i+1; j < firstDay.size(); j++){ + if (firstDay.get(i).sekPerKWh() > firstDay.get(j).sekPerKWh()){ + doneSorting = false; + Elpris tempFirstDay = firstDay.get(i); + firstDay.set(i, firstDay.get(j)); + firstDay.set(j, tempFirstDay); + } + } + } + } + + return firstDay; + } + + public static List sortBothDays(List bothDays) { + boolean doneSorting = false; + + if (!bothDays.isEmpty()) { + while (!doneSorting) { + doneSorting = true; + for(int i = 0; i < bothDays.size()-1; i++ ){ + for (int j = i+1; j < bothDays.size(); j++){ + if (bothDays.get(i).sekPerKWh() > bothDays.get(j).sekPerKWh()){ + doneSorting = false; + Elpris tempBothDays = bothDays.get(i); + bothDays.set(i, bothDays.get(j)); + bothDays.set(j, tempBothDays); + } + } + } + } + } + return bothDays; + } + + /* ################## OTHER ################## */ + // OK public static LocalDate dateValidation(String dateInput) { try { @@ -329,8 +365,13 @@ public static void exitApplication(){ System.exit(0); } - /* ################## FOR TESTING ################## */ + /* ################## FOR TESTING ################## */ + public static void printLists(List list){ + for (Elpris elpris : list){ + System.out.println(elpris.toString()); + } + } } From 636aadfc40760d721cee1392e1089af8c6fe8d80 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:57:21 +0200 Subject: [PATCH 11/17] Sortering fungerar --- src/main/java/com/example/Anteckningar | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/com/example/Anteckningar diff --git a/src/main/java/com/example/Anteckningar b/src/main/java/com/example/Anteckningar new file mode 100644 index 00000000..211f31e3 --- /dev/null +++ b/src/main/java/com/example/Anteckningar @@ -0,0 +1,15 @@ + ************************************ + ************bra att ha kod********** + ************************************ + + //Ta in och parsea ett datum via readLine + while(true){ + try{ + System.out.println("Enter a date:"); + chosenDate = LocalDate.parse(System.console().readLine()); + break; + } catch(Exception e){ + chosenDate = LocalDate.now(); + System.out.println("-------!!!!!INVALID FORMAT!!!!!!-------\nPlease enter a date in the \"yyyy-mm-dd\" format:"); + } + } From 41d3c1ed847567c8979b22c4d5b2db20b5bb64d1 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:07:14 +0200 Subject: [PATCH 12/17] 12 tester ok, 7 kvar --- src/main/java/com/example/Main.java | 333 ++++++++++++++++------------ 1 file changed, 197 insertions(+), 136 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 240c1e21..6ffae832 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,25 +1,25 @@ +//todo window sorting algo +//todo sorted output format + package com.example; + import com.example.api.ElpriserAPI; +import com.example.api.ElpriserAPI.Prisklass; +import com.example.api.ElpriserAPI.Elpris; +import java.text.DecimalFormat; import java.text.NumberFormat; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Locale; -import com.example.api.ElpriserAPI.Prisklass; -import com.example.api.ElpriserAPI.Elpris; + public class Main { - public static void main(String[] args) { - //Formatering till svenska decimaler - NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); - //Hur många siffror/decimaler som ska ingå - decimalFormatering.setMaximumFractionDigits(2); - decimalFormatering.setMinimumFractionDigits(2); - decimalFormatering.setMinimumIntegerDigits(2); + public static void main(String[] args) { // Skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll ElpriserAPI api = new ElpriserAPI(); @@ -29,15 +29,17 @@ public static void main(String[] args) { LocalDate date; List firstDay; - List sortedFirstDay; List nextDay; List bothDays; List sortedBothDays; - List sortedList; + List sortedFirstDay; + + String[] minMaxMean = new String[3]; String chargingWindow; + String noChargingWindow = "0H"; - boolean isCliRunning = false; + boolean isCliRunning; boolean isSorted; double meanPrice; @@ -61,50 +63,69 @@ public static void main(String[] args) { else { isCliRunning = true; if (args.length == 1) { - helpCli(); + helpCli(args); + return; } - // Kolla igenom args och sätt variabler - zone = zoneValidation(checkArgsForZone(args), isCliRunning); + + // Kolla igenom args och sätt variabler // + + // Validera zoninput + if (zoneValidation(checkArgsForZone(args), true) != null){ + zone = zoneValidation(checkArgsForZone(args), true); + } + else { + return; + } date = checkArgsForDate(args); chargingWindow = checkArgsForCharging(args); isSorted = checkArgsForSorted(args); - // Hämta listor - firstDay = fetchContents(api.getPriser(date, zone)); - nextDay = fetchContents(api.getPriser(date.plusDays(1), zone)); + + // Skapa första dagens lista + if (!api.getPriser(date,zone).isEmpty()){ + firstDay = new ArrayList<>(api.getPriser(date, zone)); + } + else{ + System.out.println("ingen data kunde hämtas, avslutar programmet."); + return; + } + nextDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); bothDays = addLists(firstDay, nextDay); // Sortera listor + sortedFirstDay = sortList(firstDay, noChargingWindow); + sortedBothDays = sortList(bothDays, noChargingWindow); - if (isSorted){ - sortedFirstDay = sortFirstDay(firstDay); - sortedBothDays = sortBothDays(bothDays); + // Min, Max, Mean + minMaxMean = minMaxMeanToArray(minPrice(sortedFirstDay), maxPrice(sortedFirstDay), meanPrice(sortedFirstDay), sortedFirstDay); + for(String s : minMaxMean) { + System.out.print(s); } - + // Print lists + if (isSorted && !sortedBothDays.isEmpty()) { + for(int i = sortedBothDays.size()-1; i >= 0; i--) { + System.out.print(timeFormatter(sortedBothDays.get(i).timeStart().getHour(), sortedBothDays.get(i).timeEnd().getHour()) + " "); + System.out.println(decimalFormatter(sortedBothDays.get(i).sekPerKWh()) + " öre"); + } + } + else if (isSorted && !sortedFirstDay.isEmpty()) { + for(int i = sortedFirstDay.size()-1; i >= 0; i--) { + System.out.print(timeFormatter(sortedFirstDay.get(i).timeStart().getHour(), sortedFirstDay.get(i).timeEnd().getHour()) + " "); + System.out.println(decimalFormatter(sortedFirstDay.get(i).sekPerKWh()) + " öre"); + } + } + else if (!firstDay.isEmpty()) { + printLists(firstDay); + } + else { + System.out.println("No data found.."); + } } - -/* ***************************************************************************************************************************************** */ -/* ************************************************************** HÄMTA VÄRDEN ************************************************************* */ -/* ***************************************************************************************************************************************** */ - -// // Räkna ut min, max- och medelpris -// meanPrice = meanPriceCalculation(firstDay); -// minIndex = minPriceCalculation(firstDay); -// maxIndex = maxPriceCalculation(firstDay); -// -// double minPrice = firstDay.get(minIndex).sekPerKWh() * 100; -// double maxPrice = firstDay.get(maxIndex).sekPerKWh() * 100; -// -// System.out.println("\nMedelpris: " + meanPrice); -// System.out.println("Lägsta pris: " + decimalFormatering.format(minPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(minIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(minIndex).timeEnd().getHour())); -// System.out.println("Högsta pris: " + decimalFormatering.format(maxPrice) + " öre" + " Mellan: " + String.format("%02d", firstDay.get(maxIndex).timeStart().getHour()) + "-" + String.format("%02d", firstDay.get(maxIndex).timeEnd().getHour())); - //ERROR TEST : Stänger evighetsloop System.out.println("\nSlutet av koden: Avslutar applikationen.\n"); - System.exit(0); } @@ -113,19 +134,20 @@ public static void main(String[] args) { /* ***************************************************************************************************************************************** */ /* ################## CLI ################## */ - // OK-ish, bygg på - public static void helpCli() { - System.out.println("\n\n\t################################################## HJÄLP #########################################################\n"); - System.out.println("\tZONE: --zone SE1/SE2/SE3/SE4 | Vilken zon priserna ska hämtas ifrån."); - System.out.println("\t SE1 = norra Sverige | SE2 = norra mellansverige | SE3 = södra mellansverige | SE4 = södra Sverige\n"); - System.out.println("\tDATE: --date YYYY-MM-DD | Vilket datum priserna ska hämtas ifrån. Om datum inte angivits används dagens datum.\n"); - System.out.println("\tCHARGING:--charging 0H/2H/4H/8H | Ange för att hitta det billigaste laddningsfönstret.\n"); - System.out.println("\tSORTED: --sorted | Sortera listan från lägsta pris till högsta pris."); + public static void helpCli(String[] args) { + if(args[0].equalsIgnoreCase("--help")){ - System.out.println("\n\t##################################################################################################################"); + System.out.println("\n\n\t################################################## HJÄLP #########################################################\n"); - exitApplication(); + System.out.println("\tZONE: --zone SE1/SE2/SE3/SE4 | Vilken zon priserna ska hämtas ifrån."); + System.out.println("\t SE1 = norra Sverige | SE2 = norra mellansverige | SE3 = södra mellansverige | SE4 = södra Sverige\n"); + System.out.println("\tDATE: --date YYYY-MM-DD | Vilket datum priserna ska hämtas ifrån. Om datum inte angivits används dagens datum.\n"); + System.out.println("\tCHARGING:--charging 0H/2H/4H/8H | Ange för att hitta det billigaste laddningsfönstret.\n"); + System.out.println("\tSORTED: --sorted | Sortera listan från lägsta pris till högsta pris."); + + System.out.println("\n\t##################################################################################################################"); + } } // OK @@ -135,9 +157,7 @@ public static String checkArgsForZone(String[] argsArray) { return argsArray[i+1]; } } - System.out.println("zone required : Ingen zone har angetts, ange --zone SE1|SE2|SE3|SE4 vid initiering."); - exitApplication(); - // Return behövs för att compilern ska vara glad, även om det inte körs + System.out.println("zone required : Ingen zon har angetts."); return "null"; } @@ -148,7 +168,6 @@ public static LocalDate checkArgsForDate(String[] argsArray) { return dateValidation(argsArray[i+1]); } } - System.out.println("Inget datum angett, applikationen kommer att köras med dagens datum."); return LocalDate.now(); } @@ -177,7 +196,7 @@ public static boolean checkArgsForSorted(String[] argsArray) { public static void drawInterfaceMenu() { System.out.println("***************** KATEGORIER *****************"); System.out.println("usage | zone | date | charging | sorted | exit"); - chooseInterfaceCategory(); + //chooseInterfaceCategory(); } // OK @@ -217,69 +236,85 @@ public static String zoneInterfaceInput(){ // OK public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) { - + String[] enums = {"se1","se2","se3","se4"}; while (true) { - try { - return Prisklass.valueOf(methodInput.toUpperCase()); - } - catch (IllegalArgumentException e) { - if (isCliRunning){ - System.out.print("!! zone required: Giltig zon krävs. "); - exitApplication(); - } - else { - System.out.println("!! zone required: Giltig zon krävs."); - methodInput = zoneInterfaceInput(); + for (String e : enums) { + if (methodInput.equalsIgnoreCase(e)) { + return Prisklass.valueOf(methodInput.toUpperCase()); } } + if (isCliRunning){ + System.out.println("ogiltig zon"); + System.out.print("!! zone required: Ogiltig zon. "); + return null; + } + else { + System.out.println("ogiltig zon"); + System.out.println("!! zone required: Ogiltig zon."); + methodInput = zoneInterfaceInput(); + } } } /* ################## CALCULATIONS ################## */ - public static double meanPriceCalculation(List list) { + // OK Returnerar medelvärdet + public static double meanPrice(List list) { double sum = 0; - int numberCount = list.size(); - for (int i = 0; i < numberCount; i++) { - sum += list.get(i).sekPerKWh(); + // "Error handling" + if (list.isEmpty()){ + return 0; } - return sum / numberCount; - } - public static int minPriceCalculation(List list) { - double min = list.getFirst().sekPerKWh(); - int minIndex = 0; - for (int i = 0; i < list.size(); i++) { - if (list.get(i).sekPerKWh() < min) { - min = list.get(i).sekPerKWh(); - minIndex = i; - } + for (Elpris number : list){ + sum += number.sekPerKWh(); } - return minIndex; + return (sum / list.size()); } - public static int maxPriceCalculation(List list) { - double max = list.getFirst().sekPerKWh(); - int maxIndex = 0; + // OK Returnerar lägsta priset + public static double minPrice(List sortedList) { + List tempList = new ArrayList<>(sortedList); + // "Error handling" + if (sortedList.isEmpty()){ + return 0; + } + return tempList.getFirst().sekPerKWh(); + } - for (int i = 0; i < list.size(); i++) { - if (list.get(i).sekPerKWh() > max) { - max = list.get(i).sekPerKWh(); - maxIndex = i; - } + // OK Returnerar högsta priset + public static double maxPrice(List sortedList) { + List tempList = new ArrayList<>(sortedList); + // "Error handling" + if (sortedList.isEmpty()){ + return 0; } + return tempList.getLast().sekPerKWh(); + } - return maxIndex; + // OK Skriv min, max, mean till array + public static String[] minMaxMeanToArray(double min, double max, double mean, List sortedList) { + String minHours = timeFormatter(sortedList.getFirst().timeStart().getHour(), sortedList.getFirst().timeEnd().getHour()); + String maxHours = timeFormatter(sortedList.getLast().timeStart().getHour(), sortedList.getLast().timeEnd().getHour()); + return new String[]{"lägsta pris: " + minHours + " ", decimalFormatter(min), " öre ", "\nhögsta pris: " + maxHours + " ", decimalFormatter(max), " öre ", "\nmedelpris: ", decimalFormatter(min), " öre\n"}; } - /* ################## LISTS ################## */ - // OK - public static List fetchContents(List priceList) { - return new ArrayList<>(priceList); + // RADERA? + public static LocalDate sendBackDate(Elpris singleHourContent) { + return singleHourContent.timeStart().toLocalDate(); } - // OK + // Beräkna vilken tid som är tidigast + + + /* ################## LISTS ################## */ + // OK Behåller ifall jag glömmer hur jag gör i main. +// public static List fetchContents(List priceList) { +// return new ArrayList<>(priceList); +// } + + // OK Lägger ihop första och andra dagens värden public static List addLists(List firstDay, List secondDay) { // Temporär lista List twoDayList = new ArrayList<>(); @@ -292,58 +327,65 @@ public static List addLists(List firstDay, List secondDa return twoDayList; } - public static List sortFirstDay(List firstDay) { + // OK Sorterar listan + public static List sortList(List unsortedList, String chargingWindow) { + List sortedList = new ArrayList<>(unsortedList); + int sortedListSize = sortedList.size(); boolean doneSorting = false; - while (!doneSorting){ - doneSorting = true; - for(int i = 0; i < firstDay.size()-1; i++ ){ - for (int j = i+1; j < firstDay.size(); j++){ - if (firstDay.get(i).sekPerKWh() > firstDay.get(j).sekPerKWh()){ - doneSorting = false; - Elpris tempFirstDay = firstDay.get(i); - firstDay.set(i, firstDay.get(j)); - firstDay.set(j, tempFirstDay); + if(sortedListSize > 0 && chargingWindow.equalsIgnoreCase("0H")){ + while (!doneSorting){ + doneSorting = true; + for(int i = 0; i < sortedListSize-1; i++ ){ + for (int j = i+1; j < sortedListSize; j++){ + + // Endast för att snygga upp i koden + double iSekPerKwh = sortedList.get(i).sekPerKWh(); + double jSekPerKwh = sortedList.get(j).sekPerKWh(); + // Tidsvariabler för att jämföra vilken som ska komma först i sorterade listan + LocalDateTime firstHour = sortedList.get(i).timeStart().toLocalDateTime(); + LocalDateTime secondHour = sortedList.get(j).timeStart().toLocalDateTime(); + + // Byt plats på elementen om billigare pris hittas + if (iSekPerKwh > jSekPerKwh){ + doneSorting = false; + Elpris tempFirstDay = sortedList.get(i); + sortedList.set(i, sortedList.get(j)); + sortedList.set(j, tempFirstDay); + } + // Om priserna är lika, lägg det tidigaste datumet/tiden först + else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ + doneSorting = false; + Elpris tempFirstDay = sortedList.get(i); + sortedList.set(i, sortedList.get(j)); + sortedList.set(j, tempFirstDay); + } } } } } - - return firstDay; + return sortedList; } - public static List sortBothDays(List bothDays) { - boolean doneSorting = false; + /* ################## OTHER ################## */ - if (!bothDays.isEmpty()) { - while (!doneSorting) { - doneSorting = true; - for(int i = 0; i < bothDays.size()-1; i++ ){ - for (int j = i+1; j < bothDays.size(); j++){ - if (bothDays.get(i).sekPerKWh() > bothDays.get(j).sekPerKWh()){ - doneSorting = false; - Elpris tempBothDays = bothDays.get(i); - bothDays.set(i, bothDays.get(j)); - bothDays.set(j, tempBothDays); - } - } - } + // OK Validerar datuminput + public static LocalDate dateValidation(String dateInput) { + if (!dateInput.isEmpty()){ + try { + return LocalDate.parse(dateInput); + } + catch (Exception e) { + System.out.println("!! invalid date: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Applikationen kommer att köras med dagens datum."); } } - return bothDays; + return LocalDate.now(); } - /* ################## OTHER ################## */ - - // OK - public static LocalDate dateValidation(String dateInput) { - try { - return LocalDate.parse(dateInput); - } - catch (Exception e) { - System.out.println("!! OGILTIGT DATUM: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Applikationen kommer att köras med dagens datum."); - return LocalDate.now(); - } + // OK Formatera start- och sluttid till formatet"00-00" + public static String timeFormatter(int startHour, int endHour) { + NumberFormat integerFormatter = new DecimalFormat("00"); + return String.format(integerFormatter.format(startHour) + "-" + integerFormatter.format(endHour)); } // OK @@ -359,6 +401,22 @@ public static String chargingWindowValidation(String chargingInput) { return "0H"; } + // OK + public static String decimalFormatter(double decimalNumber) { + //Formatering till svenska decimaler + NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); + //Hur många siffror/decimaler som ska ingå + decimalFormatering.setMaximumFractionDigits(2); + decimalFormatering.setMinimumFractionDigits(2); + decimalFormatering.setMinimumIntegerDigits(2); + + if (decimalNumber == 0){ + return "No data."; + } + + return decimalFormatering.format(decimalNumber*100); + } + // OK public static void exitApplication(){ System.out.println("Stänger applikationen..."); @@ -367,11 +425,14 @@ public static void exitApplication(){ /* ################## FOR TESTING ################## */ + // OK public static void printLists(List list){ for (Elpris elpris : list){ System.out.println(elpris.toString()); } } + + } From 5e9f92295a1142811e3060b7f7ad036ad5ed2546 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Tue, 30 Sep 2025 14:11:56 +0200 Subject: [PATCH 13/17] 16 tester ok, 3 kvar --- src/main/java/com/example/Main.java | 186 ++++++++++++++++++++++++---- 1 file changed, 159 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6ffae832..2c7255dd 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,5 +1,6 @@ //todo window sorting algo -//todo sorted output format +//todo ersätt sortList med arrayer + package com.example; @@ -7,6 +8,7 @@ import com.example.api.ElpriserAPI.Prisklass; import com.example.api.ElpriserAPI.Elpris; +import java.sql.SQLOutput; import java.text.DecimalFormat; import java.text.NumberFormat; import java.time.LocalDate; @@ -33,17 +35,20 @@ public static void main(String[] args) { List bothDays; List sortedBothDays; List sortedFirstDay; + int[] firstDaySortedIndex; + int[] bothDaysSortedIndex; + int[] chargingWindowIndex; + String[] minMaxMean = new String[3]; String chargingWindow; - String noChargingWindow = "0H"; + int chargingHours = 0; + boolean isCliRunning; boolean isSorted; - double meanPrice; - /* ***************************************************************************************************************************************** */ /* ************************************************************** KÖR PROGRAM ************************************************************** */ /* ***************************************************************************************************************************************** */ @@ -68,8 +73,7 @@ public static void main(String[] args) { } - // Kolla igenom args och sätt variabler // - + //#### Kolla igenom args och sätt variabler ####// // Validera zoninput if (zoneValidation(checkArgsForZone(args), true) != null){ zone = zoneValidation(checkArgsForZone(args), true); @@ -79,9 +83,10 @@ public static void main(String[] args) { } date = checkArgsForDate(args); chargingWindow = checkArgsForCharging(args); + chargingHours = Integer.parseInt(chargingWindow.substring(0, 1)); isSorted = checkArgsForSorted(args); - + //#### Skapa listor ####// // Skapa första dagens lista if (!api.getPriser(date,zone).isEmpty()){ firstDay = new ArrayList<>(api.getPriser(date, zone)); @@ -90,19 +95,23 @@ public static void main(String[] args) { System.out.println("ingen data kunde hämtas, avslutar programmet."); return; } + // Skapa andra dagens lista nextDay = new ArrayList<>(api.getPriser(date.plusDays(1), zone)); + // Lägg ihop listorna bothDays = addLists(firstDay, nextDay); + // Sortera listor - sortedFirstDay = sortList(firstDay, noChargingWindow); - sortedBothDays = sortList(bothDays, noChargingWindow); + sortedFirstDay = sortList(firstDay); + sortedBothDays = sortList(bothDays); + chargingWindowIndex = chargingWindowSorting(bothDays, chargingHours); - // Min, Max, Mean + //#### Min, Max, Mean ####// minMaxMean = minMaxMeanToArray(minPrice(sortedFirstDay), maxPrice(sortedFirstDay), meanPrice(sortedFirstDay), sortedFirstDay); for(String s : minMaxMean) { System.out.print(s); } - // Print lists + //#### Print lists ####// if (isSorted && !sortedBothDays.isEmpty()) { for(int i = sortedBothDays.size()-1; i >= 0; i--) { System.out.print(timeFormatter(sortedBothDays.get(i).timeStart().getHour(), sortedBothDays.get(i).timeEnd().getHour()) + " "); @@ -122,6 +131,9 @@ else if (!firstDay.isEmpty()) { System.out.println("No data found.."); } + // Skriv ut optimala laddningsfönstret + printCharging(bothDays, chargingHours, chargingWindowIndex[0]); + } //ERROR TEST : Stänger evighetsloop @@ -273,6 +285,15 @@ public static double meanPrice(List list) { return (sum / list.size()); } + public static double meanPriceCharging(List list, int chargingWindow, int index) { + double sum = 0; + for (int i = 0; i < chargingWindow; i++) { + sum += list.get(index + i).sekPerKWh(); + } + sum /= chargingWindow; + return sum; + } + // OK Returnerar lägsta priset public static double minPrice(List sortedList) { List tempList = new ArrayList<>(sortedList); @@ -305,9 +326,6 @@ public static LocalDate sendBackDate(Elpris singleHourContent) { return singleHourContent.timeStart().toLocalDate(); } - // Beräkna vilken tid som är tidigast - - /* ################## LISTS ################## */ // OK Behåller ifall jag glömmer hur jag gör i main. // public static List fetchContents(List priceList) { @@ -324,16 +342,19 @@ public static List addLists(List firstDay, List secondDa twoDayList.addAll(firstDay); twoDayList.addAll(secondDay); } + else{ + twoDayList.addAll(firstDay); + } return twoDayList; } // OK Sorterar listan - public static List sortList(List unsortedList, String chargingWindow) { + public static List sortList(List unsortedList) { List sortedList = new ArrayList<>(unsortedList); int sortedListSize = sortedList.size(); boolean doneSorting = false; - if(sortedListSize > 0 && chargingWindow.equalsIgnoreCase("0H")){ + if(sortedListSize > 0){ while (!doneSorting){ doneSorting = true; for(int i = 0; i < sortedListSize-1; i++ ){ @@ -347,19 +368,19 @@ public static List sortList(List unsortedList, String chargingWi LocalDateTime secondHour = sortedList.get(j).timeStart().toLocalDateTime(); // Byt plats på elementen om billigare pris hittas - if (iSekPerKwh > jSekPerKwh){ - doneSorting = false; - Elpris tempFirstDay = sortedList.get(i); - sortedList.set(i, sortedList.get(j)); - sortedList.set(j, tempFirstDay); - } - // Om priserna är lika, lägg det tidigaste datumet/tiden först - else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ + if (iSekPerKwh > jSekPerKwh || (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour))){ doneSorting = false; Elpris tempFirstDay = sortedList.get(i); sortedList.set(i, sortedList.get(j)); sortedList.set(j, tempFirstDay); } + // RADERA? TESTA FÖRST Om priserna är lika, lägg det tidigaste datumet/tiden först +// else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ +// doneSorting = false; +// Elpris tempFirstDay = sortedList.get(i); +// sortedList.set(i, sortedList.get(j)); +// sortedList.set(j, tempFirstDay); +// } } } } @@ -367,6 +388,95 @@ else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ return sortedList; } +// // RADERA? OK Sorterar listan +// public static List sortedListIndexing(List unsortedList, String chargingWindow) { +// List sortedList = new ArrayList<>(unsortedList); +// int sortedListSize = sortedList.size(); +// boolean doneSorting = false; +// +// if(sortedListSize > 0 && chargingWindow.equalsIgnoreCase("0H")){ +// while (!doneSorting){ +// doneSorting = true; +// for(int i = 0; i < sortedListSize-1; i++ ){ +// for (int j = i+1; j < sortedListSize; j++){ +// +// // Endast för att snygga upp i koden +// double iSekPerKwh = sortedList.get(i).sekPerKWh(); +// double jSekPerKwh = sortedList.get(j).sekPerKWh(); +// // Tidsvariabler för att jämföra vilken som ska komma först i sorterade listan +// LocalDateTime firstHour = sortedList.get(i).timeStart().toLocalDateTime(); +// LocalDateTime secondHour = sortedList.get(j).timeStart().toLocalDateTime(); +// +// // Byt plats på elementen om billigare pris hittas +// if (iSekPerKwh > jSekPerKwh || (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour))){ +// doneSorting = false; +// Elpris tempFirstDay = sortedList.get(i); +// sortedList.set(i, sortedList.get(j)); +// sortedList.set(j, tempFirstDay); +// } +// // RADERA? TESTA FÖRST Om priserna är lika, lägg det tidigaste datumet/tiden först +// else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ +// doneSorting = false; +// Elpris tempFirstDay = sortedList.get(i); +// sortedList.set(i, sortedList.get(j)); +// sortedList.set(j, tempFirstDay); +// } +// } +// } +// } +// } +// return sortedList; +// } + + // RADERA? OK Sorterar listan med sortList, får denna användas? +// public static List sortedListIndexing(List unsortedList, String chargingWindow) { +// return sortList(unsortedList, chargingWindow); +// } + + public static int[] chargingWindowSorting(List unsortedList, int chargingWindow) { + List list = new ArrayList<>(unsortedList); + + int indexSize = (list.size() - chargingWindow)+1; + // Skapar array som sparar startindex för alla charging windows + int[] windowIndexing = new int[indexSize]; + + // Börja med att sätta startindex i ordning (kan ev. tas bort senare) + for (int i = 0; i < indexSize; i++) { + windowIndexing[i] = i; + } + + for(int i = 0; i < indexSize-1; i++ ){ + double iSumSekPerKwh = 0; + // Tidsvariabel för andra laddningsfönstret till att jämföra vilken som ska komma först i sorterade listan + LocalDateTime firstHour = list.get(i).timeStart().toLocalDateTime(); + + // Summera värdena för första laddningsfönstret + for(int j = 0; j < chargingWindow; j++){ + iSumSekPerKwh += list.get(i+j).sekPerKWh(); + } + + // Jämför summorna + for (int k = i+1; k < indexSize-1; k++){ + double jSumSekPerKwh = 0; + // Tidsvariabel för andra laddningsfönstret till att jämföra vilken som ska komma först i sorterade listan + LocalDateTime secondHour = list.get(k).timeStart().toLocalDateTime(); + + // Summera värdena för andra laddningsfönstret + for(int l = 0; l < chargingWindow; l++){ + jSumSekPerKwh += list.get(k+l).sekPerKWh(); + } + + // Byt plats på elementen om billigare fönster hittas eller om priserna är lika, lägg det tidigaste datumet/tiden först + if (iSumSekPerKwh > jSumSekPerKwh || (iSumSekPerKwh == jSumSekPerKwh && firstHour.isBefore(secondHour))){ + windowIndexing[i] = k; + windowIndexing[k] = i; + } + } + } + + return windowIndexing; + } + /* ################## OTHER ################## */ // OK Validerar datuminput @@ -382,13 +492,25 @@ public static LocalDate dateValidation(String dateInput) { return LocalDate.now(); } + public static String integerFormatter(int Number) { + NumberFormat integerFormatter = new DecimalFormat("00"); + return integerFormatter.format(Number); + } + // OK Formatera start- och sluttid till formatet"00-00" public static String timeFormatter(int startHour, int endHour) { NumberFormat integerFormatter = new DecimalFormat("00"); - return String.format(integerFormatter.format(startHour) + "-" + integerFormatter.format(endHour)); + return String.format(integerFormatter(startHour) + "-" + integerFormatter(endHour)); } - // OK + // OK Formatera start-tid till formatet"00:00" + public static String timeFormatter(LocalDateTime timeStart) { + int hour = timeStart.getHour(); + int minute = timeStart.getMinute(); + return integerFormatter(hour) + ":" + integerFormatter(minute); + } + + // OK Ev. ändring: Denna skulle ev. kunna skicka tillbaka int public static String chargingWindowValidation(String chargingInput) { String[] chargingWindow = {"0H", "2H", "4H", "8H"}; @@ -424,7 +546,7 @@ public static void exitApplication(){ } - /* ################## FOR TESTING ################## */ + /* ################## PRINTING ################## */ // OK public static void printLists(List list){ for (Elpris elpris : list){ @@ -432,7 +554,17 @@ public static void printLists(List list){ } } + public static void printCharging(List inputList, int chargingHours, int index){ + List list = new ArrayList<>(inputList); + double meanPrice = meanPriceCharging(list, chargingHours, index); + String startHour = timeFormatter(list.get(index).timeStart().toLocalDateTime()); + System.out.println("\nFör optimalt " + chargingHours + " timmars laddningsfönster:"); + //"Påbörja laddning kl. 01:00" + System.out.println("Påbörja laddning kl. " + startHour); + // "Medelpris för fönster: " + expectedAvgStr + " öre." + System.out.println("Medelpris " + decimalFormatter(meanPrice) + " öre\n"); + } } From 951df8f2e918fea977404bd2b41a98ffb69c3219 Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:31:27 +0200 Subject: [PATCH 14/17] =?UTF-8?q?alla=20tester=20godk=C3=A4nda?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 283 +++++++++++++++------------- 1 file changed, 151 insertions(+), 132 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 2c7255dd..a346f88f 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -8,7 +8,6 @@ import com.example.api.ElpriserAPI.Prisklass; import com.example.api.ElpriserAPI.Elpris; -import java.sql.SQLOutput; import java.text.DecimalFormat; import java.text.NumberFormat; import java.time.LocalDate; @@ -35,16 +34,10 @@ public static void main(String[] args) { List bothDays; List sortedBothDays; List sortedFirstDay; - int[] firstDaySortedIndex; - int[] bothDaysSortedIndex; int[] chargingWindowIndex; - - - String[] minMaxMean = new String[3]; - + String[] minMaxMean; String chargingWindow; - int chargingHours = 0; - + int chargingHours; boolean isCliRunning; boolean isSorted; @@ -72,7 +65,6 @@ public static void main(String[] args) { return; } - //#### Kolla igenom args och sätt variabler ####// // Validera zoninput if (zoneValidation(checkArgsForZone(args), true) != null){ @@ -103,41 +95,57 @@ public static void main(String[] args) { // Sortera listor sortedFirstDay = sortList(firstDay); sortedBothDays = sortList(bothDays); - chargingWindowIndex = chargingWindowSorting(bothDays, chargingHours); - //#### Min, Max, Mean ####// - minMaxMean = minMaxMeanToArray(minPrice(sortedFirstDay), maxPrice(sortedFirstDay), meanPrice(sortedFirstDay), sortedFirstDay); - for(String s : minMaxMean) { - System.out.print(s); + //#### 96 entries list ####// + if (firstDay.size() == 96) { + quarterlyToHourly(firstDay); } - - //#### Print lists ####// - if (isSorted && !sortedBothDays.isEmpty()) { - for(int i = sortedBothDays.size()-1; i >= 0; i--) { - System.out.print(timeFormatter(sortedBothDays.get(i).timeStart().getHour(), sortedBothDays.get(i).timeEnd().getHour()) + " "); - System.out.println(decimalFormatter(sortedBothDays.get(i).sekPerKWh()) + " öre"); + else{ + //#### Min, Max, Mean ####// + minMaxMean = minMaxMeanToArray(minPrice(sortedFirstDay), maxPrice(sortedFirstDay), meanPrice(sortedFirstDay), sortedFirstDay); + System.out.println("\n"); + for(String s : minMaxMean) { + System.out.print(s); } - } - else if (isSorted && !sortedFirstDay.isEmpty()) { - for(int i = sortedFirstDay.size()-1; i >= 0; i--) { - System.out.print(timeFormatter(sortedFirstDay.get(i).timeStart().getHour(), sortedFirstDay.get(i).timeEnd().getHour()) + " "); - System.out.println(decimalFormatter(sortedFirstDay.get(i).sekPerKWh()) + " öre"); + + //#### Optimal charging hours ####// + if(chargingHours > 0) { + chargingWindowIndex = chargingWindowSorting(bothDays, chargingHours); + // Skriv ut optimala laddningsfönstret + printCharging(bothDays, chargingHours, chargingWindowIndex[0]); } - } - else if (!firstDay.isEmpty()) { - printLists(firstDay); - } - else { - System.out.println("No data found.."); - } - // Skriv ut optimala laddningsfönstret - printCharging(bothDays, chargingHours, chargingWindowIndex[0]); + //#### Print lists ####// + if (isSorted && !sortedBothDays.isEmpty()) { + System.out.println("Sorterad lista två dagar:"); + for(int i = sortedBothDays.size()-1; i >= 0; i--) { + // Kan snygga upp detta om jag orkar lägga tid + System.out.print(timeFormatter(sortedBothDays.get(i).timeStart().getHour(), sortedBothDays.get(i).timeEnd().getHour()) + " "); + System.out.println(decimalFormatter(sortedBothDays.get(i).sekPerKWh()) + " öre"); + } + } + else if (isSorted && !sortedFirstDay.isEmpty()) { + System.out.println("Sorterad lista en dag:"); + for(int i = sortedFirstDay.size()-1; i >= 0; i--) { + // Kan snygga upp detta om jag orkar lägga tid + System.out.print(timeFormatter(sortedFirstDay.get(i).timeStart().getHour(), sortedFirstDay.get(i).timeEnd().getHour()) + " "); + System.out.println(decimalFormatter(sortedFirstDay.get(i).sekPerKWh()) + " öre"); + } + } + // RADERA? +// else if (!firstDay.isEmpty()) { +// printLists(firstDay); +// } + else { + System.out.println("No data found.."); + } + } + System.out.println("\n"); } - - //ERROR TEST : Stänger evighetsloop - System.out.println("\nSlutet av koden: Avslutar applikationen.\n"); + //RADERA? +// //ERROR TEST : Stänger evighetsloop +// System.out.println("\nSlutet av koden: Avslutar applikationen.\n"); } @@ -285,13 +293,13 @@ public static double meanPrice(List list) { return (sum / list.size()); } - public static double meanPriceCharging(List list, int chargingWindow, int index) { + public static double meanPriceCharging(List list, int chargingHours, int index) { double sum = 0; - for (int i = 0; i < chargingWindow; i++) { + for (int i = 0; i < chargingHours; i++) { sum += list.get(index + i).sekPerKWh(); + } - sum /= chargingWindow; - return sum; + return sum/chargingHours; } // OK Returnerar lägsta priset @@ -318,19 +326,10 @@ public static double maxPrice(List sortedList) { public static String[] minMaxMeanToArray(double min, double max, double mean, List sortedList) { String minHours = timeFormatter(sortedList.getFirst().timeStart().getHour(), sortedList.getFirst().timeEnd().getHour()); String maxHours = timeFormatter(sortedList.getLast().timeStart().getHour(), sortedList.getLast().timeEnd().getHour()); - return new String[]{"lägsta pris: " + minHours + " ", decimalFormatter(min), " öre ", "\nhögsta pris: " + maxHours + " ", decimalFormatter(max), " öre ", "\nmedelpris: ", decimalFormatter(min), " öre\n"}; - } - - // RADERA? - public static LocalDate sendBackDate(Elpris singleHourContent) { - return singleHourContent.timeStart().toLocalDate(); + return new String[]{"lägsta pris: " + minHours + " ", decimalFormatter(min), " öre ", "\nhögsta pris: " + maxHours + " ", decimalFormatter(max), " öre ", "\nmedelpris: ", decimalFormatter(mean), " öre\n"}; } /* ################## LISTS ################## */ - // OK Behåller ifall jag glömmer hur jag gör i main. -// public static List fetchContents(List priceList) { -// return new ArrayList<>(priceList); -// } // OK Lägger ihop första och andra dagens värden public static List addLists(List firstDay, List secondDay) { @@ -374,13 +373,6 @@ public static List sortList(List unsortedList) { sortedList.set(i, sortedList.get(j)); sortedList.set(j, tempFirstDay); } - // RADERA? TESTA FÖRST Om priserna är lika, lägg det tidigaste datumet/tiden först -// else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ -// doneSorting = false; -// Elpris tempFirstDay = sortedList.get(i); -// sortedList.set(i, sortedList.get(j)); -// sortedList.set(j, tempFirstDay); -// } } } } @@ -388,92 +380,103 @@ public static List sortList(List unsortedList) { return sortedList; } -// // RADERA? OK Sorterar listan -// public static List sortedListIndexing(List unsortedList, String chargingWindow) { -// List sortedList = new ArrayList<>(unsortedList); -// int sortedListSize = sortedList.size(); -// boolean doneSorting = false; -// -// if(sortedListSize > 0 && chargingWindow.equalsIgnoreCase("0H")){ -// while (!doneSorting){ -// doneSorting = true; -// for(int i = 0; i < sortedListSize-1; i++ ){ -// for (int j = i+1; j < sortedListSize; j++){ -// -// // Endast för att snygga upp i koden -// double iSekPerKwh = sortedList.get(i).sekPerKWh(); -// double jSekPerKwh = sortedList.get(j).sekPerKWh(); -// // Tidsvariabler för att jämföra vilken som ska komma först i sorterade listan -// LocalDateTime firstHour = sortedList.get(i).timeStart().toLocalDateTime(); -// LocalDateTime secondHour = sortedList.get(j).timeStart().toLocalDateTime(); -// -// // Byt plats på elementen om billigare pris hittas -// if (iSekPerKwh > jSekPerKwh || (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour))){ -// doneSorting = false; -// Elpris tempFirstDay = sortedList.get(i); -// sortedList.set(i, sortedList.get(j)); -// sortedList.set(j, tempFirstDay); -// } -// // RADERA? TESTA FÖRST Om priserna är lika, lägg det tidigaste datumet/tiden först -// else if (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour)){ -// doneSorting = false; -// Elpris tempFirstDay = sortedList.get(i); -// sortedList.set(i, sortedList.get(j)); -// sortedList.set(j, tempFirstDay); -// } -// } -// } -// } -// } -// return sortedList; -// } + public static void quarterlyToHourly(List quarterlyList) { + System.out.println(quarterlyList.size()); + double cheapestPrice = 0; + double mostExpensivePrice = 0; + double meanPrice = 0; + int cheapestHourStart = 1; + int cheapestHourEnd = 1; + int mostExpensiveHourStart = 2; + int mostExpensiveHourEnd = 2; + + for (int i = 0; i < 96; i = i+4 ) { + double currentPrice; + double sekPerKWh = 0; + + List tempLoopList = quarterlyList.subList(i, i+4); + + // Räkna ut summan av timmens kvartspriser + for (int j = 0; j < tempLoopList.size(); j++){ + sekPerKWh += tempLoopList.get(j).sekPerKWh(); + } + currentPrice = sekPerKWh/4; + + // Om billigare + if (cheapestPrice == 0 || currentPrice < cheapestPrice) { + cheapestPrice = currentPrice; + cheapestHourStart = tempLoopList.getFirst().timeStart().getHour(); + if (cheapestHourStart == 23) { + cheapestHourEnd = 0; + } + else{ + cheapestHourEnd = (cheapestHourStart+1); + } + } - // RADERA? OK Sorterar listan med sortList, får denna användas? -// public static List sortedListIndexing(List unsortedList, String chargingWindow) { -// return sortList(unsortedList, chargingWindow); -// } + // Om dyrare + else if (currentPrice > mostExpensivePrice) { + mostExpensivePrice = currentPrice; + mostExpensiveHourStart = tempLoopList.getFirst().timeStart().getHour(); + if (mostExpensiveHourStart == 23) { + mostExpensiveHourEnd = 0; + } + else{ + mostExpensiveHourEnd = mostExpensiveHourStart+1; + } + } + } + + // Räkna ut medelpriset + for (int i = 0; i < 96; i++){ + meanPrice += quarterlyList.get(i).sekPerKWh(); + } + + meanPrice = meanPrice/96; + + + System.out.println("\n96 entries:"); + System.out.println("Lägsta pris kl " + timeFormatter(cheapestHourStart, cheapestHourEnd) + " " + decimalFormatterCharging(cheapestPrice) + " öre"); + System.out.println("Högsta pris kl " + timeFormatter(mostExpensiveHourStart, mostExpensiveHourEnd) + " " + decimalFormatterCharging(mostExpensivePrice) + " öre"); + System.out.println("Medelpris: " + decimalFormatterCharging(meanPrice) + " öre\n"); + } public static int[] chargingWindowSorting(List unsortedList, int chargingWindow) { List list = new ArrayList<>(unsortedList); - int indexSize = (list.size() - chargingWindow)+1; + // Skapar array som sparar startindex för alla charging windows int[] windowIndexing = new int[indexSize]; - // Börja med att sätta startindex i ordning (kan ev. tas bort senare) - for (int i = 0; i < indexSize; i++) { - windowIndexing[i] = i; + // Börja med att sätta startindex till 0,1,2,3 osv. + for (int m = 0; m < indexSize; m++) { + windowIndexing[m] = m; } - for(int i = 0; i < indexSize-1; i++ ){ - double iSumSekPerKwh = 0; - // Tidsvariabel för andra laddningsfönstret till att jämföra vilken som ska komma först i sorterade listan + for(int i = 0; i <= indexSize-2; i++){ + double firstSum = 0; + double secondSum = 0; + int nextElement = i+1; + // Tidsvariabler för laddningsfönster till att jämföra vilken som ska komma först i sorterade listan LocalDateTime firstHour = list.get(i).timeStart().toLocalDateTime(); + LocalDateTime secondHour = list.get(nextElement).timeStart().toLocalDateTime(); // Summera värdena för första laddningsfönstret for(int j = 0; j < chargingWindow; j++){ - iSumSekPerKwh += list.get(i+j).sekPerKWh(); + firstSum += list.get(i+j).sekPerKWh(); } - // Jämför summorna - for (int k = i+1; k < indexSize-1; k++){ - double jSumSekPerKwh = 0; - // Tidsvariabel för andra laddningsfönstret till att jämföra vilken som ska komma först i sorterade listan - LocalDateTime secondHour = list.get(k).timeStart().toLocalDateTime(); - - // Summera värdena för andra laddningsfönstret - for(int l = 0; l < chargingWindow; l++){ - jSumSekPerKwh += list.get(k+l).sekPerKWh(); - } + // Summera värdena för andra laddningsfönstret + for(int l = 0; l < chargingWindow; l++){ + secondSum += list.get(nextElement+l).sekPerKWh(); + } - // Byt plats på elementen om billigare fönster hittas eller om priserna är lika, lägg det tidigaste datumet/tiden först - if (iSumSekPerKwh > jSumSekPerKwh || (iSumSekPerKwh == jSumSekPerKwh && firstHour.isBefore(secondHour))){ - windowIndexing[i] = k; - windowIndexing[k] = i; - } + // Byt plats på elementen om billigare fönster hittas eller om priserna är lika, lägg det tidigaste datumet/tiden först + if (firstSum > secondSum || (firstSum == secondSum && firstHour.isBefore(secondHour))){ + windowIndexing[i] = nextElement; + windowIndexing[nextElement] = i; } } - return windowIndexing; } @@ -499,7 +502,6 @@ public static String integerFormatter(int Number) { // OK Formatera start- och sluttid till formatet"00-00" public static String timeFormatter(int startHour, int endHour) { - NumberFormat integerFormatter = new DecimalFormat("00"); return String.format(integerFormatter(startHour) + "-" + integerFormatter(endHour)); } @@ -523,7 +525,7 @@ public static String chargingWindowValidation(String chargingInput) { return "0H"; } - // OK + // OK Formaterar till 00,00 public static String decimalFormatter(double decimalNumber) { //Formatering till svenska decimaler NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); @@ -539,6 +541,22 @@ public static String decimalFormatter(double decimalNumber) { return decimalFormatering.format(decimalNumber*100); } + // OK Formaterar till 0,0 + public static String decimalFormatterCharging(double decimalNumber) { + //Formatering till svenska decimaler + NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); + //Hur många siffror/decimaler som ska ingå + decimalFormatering.setMaximumFractionDigits(2); + decimalFormatering.setMinimumFractionDigits(2); + decimalFormatering.setMinimumIntegerDigits(1); + + if (decimalNumber == 0){ + return "No data."; + } + + return decimalFormatering.format(decimalNumber*100); + } + // OK public static void exitApplication(){ System.out.println("Stänger applikationen..."); @@ -557,13 +575,14 @@ public static void printLists(List list){ public static void printCharging(List inputList, int chargingHours, int index){ List list = new ArrayList<>(inputList); double meanPrice = meanPriceCharging(list, chargingHours, index); + String formattedPrice; String startHour = timeFormatter(list.get(index).timeStart().toLocalDateTime()); + formattedPrice = String.format(decimalFormatterCharging(meanPrice)); + System.out.println("\nFör optimalt " + chargingHours + " timmars laddningsfönster:"); - //"Påbörja laddning kl. 01:00" - System.out.println("Påbörja laddning kl. " + startHour); - // "Medelpris för fönster: " + expectedAvgStr + " öre." - System.out.println("Medelpris " + decimalFormatter(meanPrice) + " öre\n"); + System.out.println("Påbörja laddning kl " + startHour); + System.out.println("Medelpris för fönster: " + formattedPrice + " öre\n"); } } From fd35861dd0d7ef404c1a33b0ffc14be4676d759e Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:34:43 +0200 Subject: [PATCH 15/17] =?UTF-8?q?alla=20tester=20godk=C3=A4nda,=20interakt?= =?UTF-8?q?ivt=20implementerat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 383 +++++++++++++++------------- 1 file changed, 204 insertions(+), 179 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index a346f88f..4329eb1a 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,12 +1,9 @@ -//todo window sorting algo -//todo ersätt sortList med arrayer - - package com.example; import com.example.api.ElpriserAPI; import com.example.api.ElpriserAPI.Prisklass; import com.example.api.ElpriserAPI.Elpris; +import com.sun.security.jgss.GSSUtil; import java.text.DecimalFormat; import java.text.NumberFormat; @@ -17,17 +14,15 @@ import java.util.Locale; - public class Main { - public static void main(String[] args) { // Skapa objekt av klasssen ElpriserAPI för att kunna använda dess innehåll ElpriserAPI api = new ElpriserAPI(); // Variabler - Prisklass zone; - LocalDate date; + Prisklass zone = Prisklass.SE1; + LocalDate date = LocalDate.now(); List firstDay; List nextDay; @@ -37,53 +32,96 @@ public static void main(String[] args) { int[] chargingWindowIndex; String[] minMaxMean; String chargingWindow; - int chargingHours; + String categoryInput; + int chargingHours = 0; + boolean isProgramRunning = true; boolean isCliRunning; - boolean isSorted; + boolean isSorted = false; -/* ***************************************************************************************************************************************** */ -/* ************************************************************** KÖR PROGRAM ************************************************************** */ -/* ***************************************************************************************************************************************** */ + /* ***************************************************************************************************************************************** */ + /* ************************************************************** KÖR PROGRAM ************************************************************** */ + /* ***************************************************************************************************************************************** */ System.out.println("\n\n\n\n\n" + """ - ###################################################################### - ###################### APPLIKATION INITIERAD ######################### - ###################################################################### + \t###################################################################### + \t###################### APPLIKATION INITIERAD ######################### + \t###################################################################### """); - /* ######## INTERAKTIVT ####### */ - if (args.length == 0) { - drawInterfaceMenu(); - } + /* ######## Kolla om programmet ska köras som CLI eller interactive ####### */ - /* ######## CLI ####### */ - else { - isCliRunning = true; - if (args.length == 1) { - helpCli(args); - return; + // Om endast 1 eller 0 argument, anta att det är --help eller + // att användaren angett fel och behöver hjälp. + if (args.length == 0 || (args.length == 1 && args[0].equalsIgnoreCase("--help"))) { + helpCli(); + return; + } + else if (args.length == 1 && args[0].equalsIgnoreCase("--interactive")) { + isCliRunning = false; + boolean isMenuRunning = true; + boolean isZoneSet = false; + + while (isMenuRunning) { + drawInterfaceMenu(); + categoryInput = chooseInterfaceCategory(); + switch (categoryInput) { + case "usage": + break; + case "zone": + zone = zoneInterfaceInput(); + isZoneSet = true; + break; + case "date": + date = dateInterfaceInput(); + break; + case "charging": + chargingWindow = chargingInterfaceInput(); + break; + case "sorted": + isSorted = !isSorted; + System.out.println("Sorted satt till " + isSorted); + break; + case "run": + if (isZoneSet){ + isMenuRunning = false; + } + else { + System.out.println("En zon måste anges innan programmet kan köras."); + } + break; + case "exit": + return; + default: + isMenuRunning = false; + isProgramRunning = false; + break; + } } - - //#### Kolla igenom args och sätt variabler ####// + } else { + isCliRunning = true; + //#### SKAPA VARIABLER ####// // Validera zoninput - if (zoneValidation(checkArgsForZone(args), true) != null){ + if (zoneValidation(checkArgsForZone(args), isCliRunning) != null) { zone = zoneValidation(checkArgsForZone(args), true); - } - else { + } else { + //isProgramRunning = false; return; } date = checkArgsForDate(args); chargingWindow = checkArgsForCharging(args); chargingHours = Integer.parseInt(chargingWindow.substring(0, 1)); isSorted = checkArgsForSorted(args); + } + + + /* ######## KÖR PROGRAMMET ####### */ + if (isProgramRunning) { - //#### Skapa listor ####// // Skapa första dagens lista - if (!api.getPriser(date,zone).isEmpty()){ + if (!api.getPriser(date, zone).isEmpty()) { firstDay = new ArrayList<>(api.getPriser(date, zone)); - } - else{ + } else { System.out.println("ingen data kunde hämtas, avslutar programmet."); return; } @@ -92,24 +130,23 @@ public static void main(String[] args) { // Lägg ihop listorna bothDays = addLists(firstDay, nextDay); - // Sortera listor + // Sortera listorna sortedFirstDay = sortList(firstDay); sortedBothDays = sortList(bothDays); //#### 96 entries list ####// if (firstDay.size() == 96) { quarterlyToHourly(firstDay); - } - else{ + } else { //#### Min, Max, Mean ####// minMaxMean = minMaxMeanToArray(minPrice(sortedFirstDay), maxPrice(sortedFirstDay), meanPrice(sortedFirstDay), sortedFirstDay); System.out.println("\n"); - for(String s : minMaxMean) { + for (String s : minMaxMean) { System.out.print(s); } //#### Optimal charging hours ####// - if(chargingHours > 0) { + if (chargingHours > 0) { chargingWindowIndex = chargingWindowSorting(bothDays, chargingHours); // Skriv ut optimala laddningsfönstret printCharging(bothDays, chargingHours, chargingWindowIndex[0]); @@ -118,63 +155,54 @@ public static void main(String[] args) { //#### Print lists ####// if (isSorted && !sortedBothDays.isEmpty()) { System.out.println("Sorterad lista två dagar:"); - for(int i = sortedBothDays.size()-1; i >= 0; i--) { - // Kan snygga upp detta om jag orkar lägga tid + for (int i = sortedBothDays.size() - 1; i >= 0; i--) { + // Kan snygga upp detta om jag orkar lägga tid på det System.out.print(timeFormatter(sortedBothDays.get(i).timeStart().getHour(), sortedBothDays.get(i).timeEnd().getHour()) + " "); System.out.println(decimalFormatter(sortedBothDays.get(i).sekPerKWh()) + " öre"); } - } - else if (isSorted && !sortedFirstDay.isEmpty()) { + } else if (isSorted && !sortedFirstDay.isEmpty()) { System.out.println("Sorterad lista en dag:"); - for(int i = sortedFirstDay.size()-1; i >= 0; i--) { - // Kan snygga upp detta om jag orkar lägga tid + for (int i = sortedFirstDay.size() - 1; i >= 0; i--) { + // Kan snygga upp detta om jag orkar lägga tid på det System.out.print(timeFormatter(sortedFirstDay.get(i).timeStart().getHour(), sortedFirstDay.get(i).timeEnd().getHour()) + " "); System.out.println(decimalFormatter(sortedFirstDay.get(i).sekPerKWh()) + " öre"); } - } - // RADERA? -// else if (!firstDay.isEmpty()) { -// printLists(firstDay); -// } - else { + } else { System.out.println("No data found.."); } } System.out.println("\n"); } - //RADERA? -// //ERROR TEST : Stänger evighetsloop -// System.out.println("\nSlutet av koden: Avslutar applikationen.\n"); + + System.out.println("\nProgrammet avslutas...\n"); } -/* ***************************************************************************************************************************************** */ -/* **************************************************************** METODER **************************************************************** */ -/* ***************************************************************************************************************************************** */ + /* ***************************************************************************************************************************************** */ + /* **************************************************************** METODER **************************************************************** */ + /* ***************************************************************************************************************************************** */ /* ################## CLI ################## */ - public static void helpCli(String[] args) { - if(args[0].equalsIgnoreCase("--help")){ - - System.out.println("\n\n\t################################################## HJÄLP #########################################################\n"); + public static void helpCli() { - System.out.println("\tZONE: --zone SE1/SE2/SE3/SE4 | Vilken zon priserna ska hämtas ifrån."); - System.out.println("\t SE1 = norra Sverige | SE2 = norra mellansverige | SE3 = södra mellansverige | SE4 = södra Sverige\n"); - System.out.println("\tDATE: --date YYYY-MM-DD | Vilket datum priserna ska hämtas ifrån. Om datum inte angivits används dagens datum.\n"); - System.out.println("\tCHARGING:--charging 0H/2H/4H/8H | Ange för att hitta det billigaste laddningsfönstret.\n"); - System.out.println("\tSORTED: --sorted | Sortera listan från lägsta pris till högsta pris."); + System.out.println("\n\n\t################################################## USAGE #########################################################\n"); + System.out.println("\tZONE : --zone SE1/SE2/SE3/SE4 | Vilken zon priserna ska hämtas ifrån."); + System.out.println("\t SE1 = norra Sverige | SE2 = norra mellansverige | SE3 = södra mellansverige | SE4 = södra Sverige\n"); + System.out.println("\tDATE : --date YYYY-MM-DD | Vilket datum priserna ska hämtas ifrån. Om datum inte angivits används dagens datum.\n"); + System.out.println("\tCHARGING : --charging 0H/2H/4H/8H | Ange för att hitta det billigaste laddningsfönstret.\n"); + System.out.println("\tSORTED : --sorted | Sortera listan från lägsta pris till högsta pris.\n"); + System.out.println("\tINTERACTIVE : --interactive | Ange värden via gränssnitt."); - System.out.println("\n\t##################################################################################################################"); - } + System.out.println("\n\t##################################################################################################################"); } // OK public static String checkArgsForZone(String[] argsArray) { - for (int i = 0; i < argsArray.length; i++){ - if (argsArray[i].equalsIgnoreCase("--zone") && i < argsArray.length-1){ - return argsArray[i+1]; + for (int i = 0; i < argsArray.length; i++) { + if (argsArray[i].equalsIgnoreCase("--zone") && i < argsArray.length - 1) { + return argsArray[i + 1]; } } System.out.println("zone required : Ingen zon har angetts."); @@ -183,9 +211,9 @@ public static String checkArgsForZone(String[] argsArray) { // OK public static LocalDate checkArgsForDate(String[] argsArray) { - for (int i = 0; i < argsArray.length; i++){ - if (argsArray[i].equalsIgnoreCase("--date") && i < argsArray.length-1){ - return dateValidation(argsArray[i+1]); + for (int i = 0; i < argsArray.length; i++) { + if (argsArray[i].equalsIgnoreCase("--date") && i < argsArray.length - 1) { + return dateValidation(argsArray[i + 1]); } } return LocalDate.now(); @@ -193,9 +221,9 @@ public static LocalDate checkArgsForDate(String[] argsArray) { // OK public static String checkArgsForCharging(String[] argsArray) { - for (int i = 0; i < argsArray.length; i++){ - if (argsArray[i].equalsIgnoreCase("--charging") && i < argsArray.length-1){ - return chargingWindowValidation(argsArray[i+1]); + for (int i = 0; i < argsArray.length; i++) { + if (argsArray[i].equalsIgnoreCase("--charging") && i < argsArray.length - 1) { + return chargingWindowValidation(argsArray[i + 1]); } } return "0H"; @@ -204,7 +232,7 @@ public static String checkArgsForCharging(String[] argsArray) { // OK public static boolean checkArgsForSorted(String[] argsArray) { for (String array : argsArray) { - if (array.equalsIgnoreCase("--sorted")){ + if (array.equalsIgnoreCase("--sorted")) { return true; } } @@ -214,64 +242,73 @@ public static boolean checkArgsForSorted(String[] argsArray) { /* ################## INTERFACE ################## */ // OK public static void drawInterfaceMenu() { - System.out.println("***************** KATEGORIER *****************"); - System.out.println("usage | zone | date | charging | sorted | exit"); - //chooseInterfaceCategory(); + System.out.println("\n***************** KATEGORIER *****************"); + System.out.println(" | zone | date | charging | sorted | run | exit |"); } // OK - public static String chooseInterfaceCategory(){ - String[] categories = { "usage", "zone", "date", "charging", "sorted"}; + public static String chooseInterfaceCategory() { + String[] categories = {"usage", "zone", "date", "charging", "sorted", "run"}; String categoryInput; while (true) { categoryInput = System.console().readLine("Välj kategori: "); if (categoryInput.equalsIgnoreCase("exit")) { break; - } - else { + } else { for (String category : categories) { if (category.equalsIgnoreCase(categoryInput)) { return categoryInput; } } - //Sparar ifall jag misslyckades med enhanced for-loopen -// for (int i = 0; i < categories.length; i++){ -// if (categories[i].equalsIgnoreCase(categoryInput)){ -// return categoryInput; -// } - } + } } - exitApplication(); return "null"; } - /* ################## ZONES ################## */ // OK - public static String zoneInterfaceInput(){ - System.out.println("Ange zon: SE1, SE2, SE3 eller SE4:"); - return System.console().readLine(); + public static Prisklass zoneInterfaceInput() { + Prisklass zone = zoneValidation(System.console().readLine("Ange en zon enligt formatet \"SE1\", \"SE2\", \"SE3\" eller \"SE4\": "), false); + System.out.println("Zon satt till: " + zone); + return zone; + } + + // OK + public static LocalDate dateInterfaceInput() { + LocalDate date = dateValidation(System.console().readLine("Ange ett datum enligt formatet \"YYYY-MM-DD\": ")); + System.out.println("Datum satt till: " + date); + return date; + } + + // OK + public static String chargingInterfaceInput() { + String charging = chargingWindowValidation(System.console().readLine("Ange ett laddningsfönster enligt formatet \"0H\", \"2H\",\"4H\", \"8H\": ")); + System.out.println("Laddfönster satt till: " + charging); + return charging; } + /* ################## ZONES ################## */ // OK public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) { - String[] enums = {"se1","se2","se3","se4"}; + String[] enums = {"se1", "se2", "se3", "se4"}; while (true) { - for (String e : enums) { - if (methodInput.equalsIgnoreCase(e)) { - return Prisklass.valueOf(methodInput.toUpperCase()); + if (methodInput != null) { + for (String e : enums) { + if (methodInput.equalsIgnoreCase(e)) { + return Prisklass.valueOf(methodInput.toUpperCase()); + } } } - if (isCliRunning){ + + if (isCliRunning) { System.out.println("ogiltig zon"); System.out.print("!! zone required: Ogiltig zon. "); return null; - } - else { + } else { System.out.println("ogiltig zon"); System.out.println("!! zone required: Ogiltig zon."); - methodInput = zoneInterfaceInput(); + zoneInterfaceInput(); } } } @@ -282,11 +319,11 @@ public static double meanPrice(List list) { double sum = 0; // "Error handling" - if (list.isEmpty()){ + if (list.isEmpty()) { return 0; } - for (Elpris number : list){ + for (Elpris number : list) { sum += number.sekPerKWh(); } @@ -299,14 +336,14 @@ public static double meanPriceCharging(List list, int chargingHours, int sum += list.get(index + i).sekPerKWh(); } - return sum/chargingHours; + return sum / chargingHours; } // OK Returnerar lägsta priset public static double minPrice(List sortedList) { - List tempList = new ArrayList<>(sortedList); + List tempList = new ArrayList<>(sortedList); // "Error handling" - if (sortedList.isEmpty()){ + if (sortedList.isEmpty()) { return 0; } return tempList.getFirst().sekPerKWh(); @@ -314,9 +351,9 @@ public static double minPrice(List sortedList) { // OK Returnerar högsta priset public static double maxPrice(List sortedList) { - List tempList = new ArrayList<>(sortedList); + List tempList = new ArrayList<>(sortedList); // "Error handling" - if (sortedList.isEmpty()){ + if (sortedList.isEmpty()) { return 0; } return tempList.getLast().sekPerKWh(); @@ -326,7 +363,7 @@ public static double maxPrice(List sortedList) { public static String[] minMaxMeanToArray(double min, double max, double mean, List sortedList) { String minHours = timeFormatter(sortedList.getFirst().timeStart().getHour(), sortedList.getFirst().timeEnd().getHour()); String maxHours = timeFormatter(sortedList.getLast().timeStart().getHour(), sortedList.getLast().timeEnd().getHour()); - return new String[]{"lägsta pris: " + minHours + " ", decimalFormatter(min), " öre ", "\nhögsta pris: " + maxHours + " ", decimalFormatter(max), " öre ", "\nmedelpris: ", decimalFormatter(mean), " öre\n"}; + return new String[]{"lägsta pris: " + minHours + " ", decimalFormatter(min), " öre", "\nhögsta pris: " + maxHours + " ", decimalFormatter(max), " öre", "\nmedelpris: ", decimalFormatter(mean), " öre\n"}; } /* ################## LISTS ################## */ @@ -340,8 +377,7 @@ public static List addLists(List firstDay, List secondDa if (!firstDay.isEmpty() && !secondDay.isEmpty()) { twoDayList.addAll(firstDay); twoDayList.addAll(secondDay); - } - else{ + } else { twoDayList.addAll(firstDay); } return twoDayList; @@ -353,35 +389,34 @@ public static List sortList(List unsortedList) { int sortedListSize = sortedList.size(); boolean doneSorting = false; - if(sortedListSize > 0){ - while (!doneSorting){ - doneSorting = true; - for(int i = 0; i < sortedListSize-1; i++ ){ - for (int j = i+1; j < sortedListSize; j++){ - - // Endast för att snygga upp i koden - double iSekPerKwh = sortedList.get(i).sekPerKWh(); - double jSekPerKwh = sortedList.get(j).sekPerKWh(); - // Tidsvariabler för att jämföra vilken som ska komma först i sorterade listan - LocalDateTime firstHour = sortedList.get(i).timeStart().toLocalDateTime(); - LocalDateTime secondHour = sortedList.get(j).timeStart().toLocalDateTime(); - - // Byt plats på elementen om billigare pris hittas - if (iSekPerKwh > jSekPerKwh || (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour))){ - doneSorting = false; - Elpris tempFirstDay = sortedList.get(i); - sortedList.set(i, sortedList.get(j)); - sortedList.set(j, tempFirstDay); - } + if (sortedListSize > 0) { + while (!doneSorting) { + doneSorting = true; + for (int i = 0; i < sortedListSize - 1; i++) { + for (int j = i + 1; j < sortedListSize; j++) { + + // Endast för att snygga upp i koden + double iSekPerKwh = sortedList.get(i).sekPerKWh(); + double jSekPerKwh = sortedList.get(j).sekPerKWh(); + // Tidsvariabler för att jämföra vilken som ska komma först i sorterade listan + LocalDateTime firstHour = sortedList.get(i).timeStart().toLocalDateTime(); + LocalDateTime secondHour = sortedList.get(j).timeStart().toLocalDateTime(); + + // Byt plats på elementen om billigare pris hittas + if (iSekPerKwh > jSekPerKwh || (iSekPerKwh == jSekPerKwh && firstHour.isBefore(secondHour))) { + doneSorting = false; + Elpris tempFirstDay = sortedList.get(i); + sortedList.set(i, sortedList.get(j)); + sortedList.set(j, tempFirstDay); } } } } + } return sortedList; } public static void quarterlyToHourly(List quarterlyList) { - System.out.println(quarterlyList.size()); double cheapestPrice = 0; double mostExpensivePrice = 0; double meanPrice = 0; @@ -390,17 +425,17 @@ public static void quarterlyToHourly(List quarterlyList) { int mostExpensiveHourStart = 2; int mostExpensiveHourEnd = 2; - for (int i = 0; i < 96; i = i+4 ) { + for (int i = 0; i < 96; i = i + 4) { double currentPrice; double sekPerKWh = 0; - List tempLoopList = quarterlyList.subList(i, i+4); + List tempLoopList = quarterlyList.subList(i, i + 4); // Räkna ut summan av timmens kvartspriser - for (int j = 0; j < tempLoopList.size(); j++){ + for (int j = 0; j < tempLoopList.size(); j++) { sekPerKWh += tempLoopList.get(j).sekPerKWh(); } - currentPrice = sekPerKWh/4; + currentPrice = sekPerKWh / 4; // Om billigare if (cheapestPrice == 0 || currentPrice < cheapestPrice) { @@ -408,9 +443,8 @@ public static void quarterlyToHourly(List quarterlyList) { cheapestHourStart = tempLoopList.getFirst().timeStart().getHour(); if (cheapestHourStart == 23) { cheapestHourEnd = 0; - } - else{ - cheapestHourEnd = (cheapestHourStart+1); + } else { + cheapestHourEnd = (cheapestHourStart + 1); } } @@ -420,20 +454,18 @@ else if (currentPrice > mostExpensivePrice) { mostExpensiveHourStart = tempLoopList.getFirst().timeStart().getHour(); if (mostExpensiveHourStart == 23) { mostExpensiveHourEnd = 0; - } - else{ - mostExpensiveHourEnd = mostExpensiveHourStart+1; + } else { + mostExpensiveHourEnd = mostExpensiveHourStart + 1; } } } // Räkna ut medelpriset - for (int i = 0; i < 96; i++){ + for (int i = 0; i < 96; i++) { meanPrice += quarterlyList.get(i).sekPerKWh(); } - meanPrice = meanPrice/96; - + meanPrice = meanPrice / 96; System.out.println("\n96 entries:"); System.out.println("Lägsta pris kl " + timeFormatter(cheapestHourStart, cheapestHourEnd) + " " + decimalFormatterCharging(cheapestPrice) + " öre"); @@ -443,7 +475,7 @@ else if (currentPrice > mostExpensivePrice) { public static int[] chargingWindowSorting(List unsortedList, int chargingWindow) { List list = new ArrayList<>(unsortedList); - int indexSize = (list.size() - chargingWindow)+1; + int indexSize = (list.size() - chargingWindow) + 1; // Skapar array som sparar startindex för alla charging windows int[] windowIndexing = new int[indexSize]; @@ -453,26 +485,26 @@ public static int[] chargingWindowSorting(List unsortedList, int chargin windowIndexing[m] = m; } - for(int i = 0; i <= indexSize-2; i++){ + for (int i = 0; i <= indexSize - 2; i++) { double firstSum = 0; double secondSum = 0; - int nextElement = i+1; + int nextElement = i + 1; // Tidsvariabler för laddningsfönster till att jämföra vilken som ska komma först i sorterade listan LocalDateTime firstHour = list.get(i).timeStart().toLocalDateTime(); LocalDateTime secondHour = list.get(nextElement).timeStart().toLocalDateTime(); // Summera värdena för första laddningsfönstret - for(int j = 0; j < chargingWindow; j++){ - firstSum += list.get(i+j).sekPerKWh(); + for (int j = 0; j < chargingWindow; j++) { + firstSum += list.get(i + j).sekPerKWh(); } // Summera värdena för andra laddningsfönstret - for(int l = 0; l < chargingWindow; l++){ - secondSum += list.get(nextElement+l).sekPerKWh(); + for (int l = 0; l < chargingWindow; l++) { + secondSum += list.get(nextElement + l).sekPerKWh(); } // Byt plats på elementen om billigare fönster hittas eller om priserna är lika, lägg det tidigaste datumet/tiden först - if (firstSum > secondSum || (firstSum == secondSum && firstHour.isBefore(secondHour))){ + if (firstSum > secondSum || (firstSum == secondSum && firstHour.isBefore(secondHour))) { windowIndexing[i] = nextElement; windowIndexing[nextElement] = i; } @@ -484,12 +516,11 @@ public static int[] chargingWindowSorting(List unsortedList, int chargin // OK Validerar datuminput public static LocalDate dateValidation(String dateInput) { - if (!dateInput.isEmpty()){ + if (!dateInput.isEmpty()) { try { return LocalDate.parse(dateInput); - } - catch (Exception e) { - System.out.println("!! invalid date: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Applikationen kommer att köras med dagens datum."); + } catch (Exception e) { + System.out.println("!! invalid date: \"" + dateInput + "\" inte enligt formatet \"YYYY-MM-DD\": Applikationen kommer att köras med dagens datum."); } } return LocalDate.now(); @@ -516,10 +547,10 @@ public static String timeFormatter(LocalDateTime timeStart) { public static String chargingWindowValidation(String chargingInput) { String[] chargingWindow = {"0H", "2H", "4H", "8H"}; - for(String hours : chargingWindow){ - if (chargingInput.equalsIgnoreCase(hours)){ - return hours.toUpperCase(); - } + for (String hours : chargingWindow) { + if (chargingInput.equalsIgnoreCase(hours)) { + return hours.toUpperCase(); + } } System.out.println("!! OGILTIGT LADDNINGSFÖNSTER: \"" + chargingInput + "\". Kör programmet utan laddningsfönster."); return "0H"; @@ -534,11 +565,11 @@ public static String decimalFormatter(double decimalNumber) { decimalFormatering.setMinimumFractionDigits(2); decimalFormatering.setMinimumIntegerDigits(2); - if (decimalNumber == 0){ + if (decimalNumber == 0) { return "No data."; } - return decimalFormatering.format(decimalNumber*100); + return decimalFormatering.format(decimalNumber * 100); } // OK Formaterar till 0,0 @@ -550,29 +581,23 @@ public static String decimalFormatterCharging(double decimalNumber) { decimalFormatering.setMinimumFractionDigits(2); decimalFormatering.setMinimumIntegerDigits(1); - if (decimalNumber == 0){ + if (decimalNumber == 0) { return "No data."; } - return decimalFormatering.format(decimalNumber*100); - } - - // OK - public static void exitApplication(){ - System.out.println("Stänger applikationen..."); - System.exit(0); + return decimalFormatering.format(decimalNumber * 100); } /* ################## PRINTING ################## */ // OK - public static void printLists(List list){ - for (Elpris elpris : list){ + public static void printLists(List list) { + for (Elpris elpris : list) { System.out.println(elpris.toString()); } } - public static void printCharging(List inputList, int chargingHours, int index){ + public static void printCharging(List inputList, int chargingHours, int index) { List list = new ArrayList<>(inputList); double meanPrice = meanPriceCharging(list, chargingHours, index); String formattedPrice; @@ -582,7 +607,7 @@ public static void printCharging(List inputList, int chargingHours, int System.out.println("\nFör optimalt " + chargingHours + " timmars laddningsfönster:"); System.out.println("Påbörja laddning kl " + startHour); - System.out.println("Medelpris för fönster: " + formattedPrice + " öre\n"); + System.out.println("Medelpris för fönster: " + formattedPrice + " öre\n"); } } From 445d3e18fb99be84fc2df0bfc6d640ff2864170c Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:37:24 +0200 Subject: [PATCH 16/17] =?UTF-8?q?alla=20tester=20godk=C3=A4nda,=20interakt?= =?UTF-8?q?ivt=20implementerat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 44 +++++++++-------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 4329eb1a..9c7a4278 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -3,7 +3,6 @@ import com.example.api.ElpriserAPI; import com.example.api.ElpriserAPI.Prisklass; import com.example.api.ElpriserAPI.Elpris; -import com.sun.security.jgss.GSSUtil; import java.text.DecimalFormat; import java.text.NumberFormat; @@ -198,7 +197,6 @@ public static void helpCli() { System.out.println("\n\t##################################################################################################################"); } - // OK public static String checkArgsForZone(String[] argsArray) { for (int i = 0; i < argsArray.length; i++) { if (argsArray[i].equalsIgnoreCase("--zone") && i < argsArray.length - 1) { @@ -209,7 +207,6 @@ public static String checkArgsForZone(String[] argsArray) { return "null"; } - // OK public static LocalDate checkArgsForDate(String[] argsArray) { for (int i = 0; i < argsArray.length; i++) { if (argsArray[i].equalsIgnoreCase("--date") && i < argsArray.length - 1) { @@ -219,7 +216,6 @@ public static LocalDate checkArgsForDate(String[] argsArray) { return LocalDate.now(); } - // OK public static String checkArgsForCharging(String[] argsArray) { for (int i = 0; i < argsArray.length; i++) { if (argsArray[i].equalsIgnoreCase("--charging") && i < argsArray.length - 1) { @@ -229,7 +225,6 @@ public static String checkArgsForCharging(String[] argsArray) { return "0H"; } - // OK public static boolean checkArgsForSorted(String[] argsArray) { for (String array : argsArray) { if (array.equalsIgnoreCase("--sorted")) { @@ -240,13 +235,12 @@ public static boolean checkArgsForSorted(String[] argsArray) { } /* ################## INTERFACE ################## */ - // OK + public static void drawInterfaceMenu() { System.out.println("\n***************** KATEGORIER *****************"); System.out.println(" | zone | date | charging | sorted | run | exit |"); } - // OK public static String chooseInterfaceCategory() { String[] categories = {"usage", "zone", "date", "charging", "sorted", "run"}; String categoryInput; @@ -267,21 +261,18 @@ public static String chooseInterfaceCategory() { return "null"; } - // OK public static Prisklass zoneInterfaceInput() { Prisklass zone = zoneValidation(System.console().readLine("Ange en zon enligt formatet \"SE1\", \"SE2\", \"SE3\" eller \"SE4\": "), false); System.out.println("Zon satt till: " + zone); return zone; } - // OK public static LocalDate dateInterfaceInput() { LocalDate date = dateValidation(System.console().readLine("Ange ett datum enligt formatet \"YYYY-MM-DD\": ")); System.out.println("Datum satt till: " + date); return date; } - // OK public static String chargingInterfaceInput() { String charging = chargingWindowValidation(System.console().readLine("Ange ett laddningsfönster enligt formatet \"0H\", \"2H\",\"4H\", \"8H\": ")); System.out.println("Laddfönster satt till: " + charging); @@ -289,7 +280,7 @@ public static String chargingInterfaceInput() { } /* ################## ZONES ################## */ - // OK + public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) { String[] enums = {"se1", "se2", "se3", "se4"}; while (true) { @@ -314,7 +305,7 @@ public static Prisklass zoneValidation(String methodInput, Boolean isCliRunning) } /* ################## CALCULATIONS ################## */ - // OK Returnerar medelvärdet + // Returnerar medelvärdet public static double meanPrice(List list) { double sum = 0; @@ -339,7 +330,7 @@ public static double meanPriceCharging(List list, int chargingHours, int return sum / chargingHours; } - // OK Returnerar lägsta priset + // Returnerar lägsta priset public static double minPrice(List sortedList) { List tempList = new ArrayList<>(sortedList); // "Error handling" @@ -349,7 +340,7 @@ public static double minPrice(List sortedList) { return tempList.getFirst().sekPerKWh(); } - // OK Returnerar högsta priset + // Returnerar högsta priset public static double maxPrice(List sortedList) { List tempList = new ArrayList<>(sortedList); // "Error handling" @@ -359,7 +350,7 @@ public static double maxPrice(List sortedList) { return tempList.getLast().sekPerKWh(); } - // OK Skriv min, max, mean till array + // Skriv min, max, mean till array public static String[] minMaxMeanToArray(double min, double max, double mean, List sortedList) { String minHours = timeFormatter(sortedList.getFirst().timeStart().getHour(), sortedList.getFirst().timeEnd().getHour()); String maxHours = timeFormatter(sortedList.getLast().timeStart().getHour(), sortedList.getLast().timeEnd().getHour()); @@ -368,7 +359,7 @@ public static String[] minMaxMeanToArray(double min, double max, double mean, Li /* ################## LISTS ################## */ - // OK Lägger ihop första och andra dagens värden + // Lägger ihop första och andra dagens värden public static List addLists(List firstDay, List secondDay) { // Temporär lista List twoDayList = new ArrayList<>(); @@ -383,7 +374,7 @@ public static List addLists(List firstDay, List secondDa return twoDayList; } - // OK Sorterar listan + // Sorterar listan public static List sortList(List unsortedList) { List sortedList = new ArrayList<>(unsortedList); int sortedListSize = sortedList.size(); @@ -514,7 +505,7 @@ public static int[] chargingWindowSorting(List unsortedList, int chargin /* ################## OTHER ################## */ - // OK Validerar datuminput + // Validerar datuminput public static LocalDate dateValidation(String dateInput) { if (!dateInput.isEmpty()) { try { @@ -531,19 +522,19 @@ public static String integerFormatter(int Number) { return integerFormatter.format(Number); } - // OK Formatera start- och sluttid till formatet"00-00" + // Formatera start- och sluttid till formatet"00-00" public static String timeFormatter(int startHour, int endHour) { return String.format(integerFormatter(startHour) + "-" + integerFormatter(endHour)); } - // OK Formatera start-tid till formatet"00:00" + // Formatera start-tid till formatet"00:00" public static String timeFormatter(LocalDateTime timeStart) { int hour = timeStart.getHour(); int minute = timeStart.getMinute(); return integerFormatter(hour) + ":" + integerFormatter(minute); } - // OK Ev. ändring: Denna skulle ev. kunna skicka tillbaka int + // Ev. ändring: Denna skulle ev. kunna skicka tillbaka int public static String chargingWindowValidation(String chargingInput) { String[] chargingWindow = {"0H", "2H", "4H", "8H"}; @@ -556,7 +547,7 @@ public static String chargingWindowValidation(String chargingInput) { return "0H"; } - // OK Formaterar till 00,00 + // Formaterar till 00,00 public static String decimalFormatter(double decimalNumber) { //Formatering till svenska decimaler NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); @@ -572,7 +563,7 @@ public static String decimalFormatter(double decimalNumber) { return decimalFormatering.format(decimalNumber * 100); } - // OK Formaterar till 0,0 + // Formaterar till 0,0 public static String decimalFormatterCharging(double decimalNumber) { //Formatering till svenska decimaler NumberFormat decimalFormatering = NumberFormat.getNumberInstance(Locale.of("sv", "SE")); @@ -588,14 +579,7 @@ public static String decimalFormatterCharging(double decimalNumber) { return decimalFormatering.format(decimalNumber * 100); } - /* ################## PRINTING ################## */ - // OK - public static void printLists(List list) { - for (Elpris elpris : list) { - System.out.println(elpris.toString()); - } - } public static void printCharging(List inputList, int chargingHours, int index) { List list = new ArrayList<>(inputList); From 989eee77dde4fe95a2997141d6348c6cd921d4be Mon Sep 17 00:00:00 2001 From: Dennis Selden <111012436+DenSel@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:40:53 +0200 Subject: [PATCH 17/17] =?UTF-8?q?alla=20tester=20godk=C3=A4nda,=20interakt?= =?UTF-8?q?ivt=20implementerat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/Main.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 9c7a4278..7f9d5ca5 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -35,7 +35,7 @@ public static void main(String[] args) { int chargingHours = 0; boolean isProgramRunning = true; - boolean isCliRunning; + boolean isCliRunning = false; boolean isSorted = false; /* ***************************************************************************************************************************************** */ @@ -57,7 +57,6 @@ public static void main(String[] args) { return; } else if (args.length == 1 && args[0].equalsIgnoreCase("--interactive")) { - isCliRunning = false; boolean isMenuRunning = true; boolean isZoneSet = false; @@ -580,7 +579,6 @@ public static String decimalFormatterCharging(double decimalNumber) { } /* ################## PRINTING ################## */ - public static void printCharging(List inputList, int chargingHours, int index) { List list = new ArrayList<>(inputList); double meanPrice = meanPriceCharging(list, chargingHours, index);