|
2 | 2 |
|
3 | 3 | import com.example.api.ElpriserAPI; |
4 | 4 |
|
| 5 | +import java.text.NumberFormat; |
| 6 | +import java.time.DateTimeException; |
| 7 | +import java.time.LocalDate; |
| 8 | +import java.time.format.DateTimeFormatter; |
| 9 | +import java.util.*; |
| 10 | + |
| 11 | + |
5 | 12 | public class Main { |
| 13 | + static DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH"); |
| 14 | + static NumberFormat numberFormat = NumberFormat.getNumberInstance(); |
6 | 15 | public static void main(String[] args) { |
7 | | - ElpriserAPI elpriserAPI = new ElpriserAPI(); |
| 16 | + |
| 17 | + ElpriserAPI elpriserApi = new ElpriserAPI(); |
| 18 | + Locale.setDefault(Locale.of("sv", "SE")); |
| 19 | + System.out.println("Välkommen till Elpris-kollen!"); |
| 20 | + String zoneOf = null; |
| 21 | + String dateOf = null; |
| 22 | + String chargingInput = null; |
| 23 | + boolean isSorted = false; |
| 24 | + |
| 25 | + List<String> validZones = new ArrayList<>(); |
| 26 | + validZones.add("SE1"); |
| 27 | + validZones.add("SE2"); |
| 28 | + validZones.add("SE3"); |
| 29 | + validZones.add("SE4"); |
| 30 | + |
| 31 | + List<String> validHours = new ArrayList<>(); |
| 32 | + validHours.add("2h"); |
| 33 | + validHours.add("4h"); |
| 34 | + validHours.add("8h"); |
| 35 | + |
| 36 | + |
| 37 | + if (args.length == 0) { helpMe(); |
| 38 | + } |
| 39 | + |
| 40 | + for (int i = 0; i < args.length; i++) { |
| 41 | + switch (args[i]) { |
| 42 | + case "--zone" -> { if (i + 1 < args.length) { |
| 43 | + zoneOf = args[++i]; |
| 44 | + } |
| 45 | + } |
| 46 | + case "--date" -> { if (i + 1 < args.length) { |
| 47 | + dateOf = args[++i]; |
| 48 | + } |
| 49 | + } |
| 50 | + case "--charging" -> { if (i + 1 < args.length) { |
| 51 | + chargingInput = args[++i]; |
| 52 | + } |
| 53 | + } |
| 54 | + case "--sorted" -> |
| 55 | + isSorted = true; |
| 56 | + |
| 57 | + case "--help" -> { helpMe(); return;} |
| 58 | + |
| 59 | + } |
| 60 | + |
| 61 | + } |
| 62 | + LocalDate dagensDatum; |
| 63 | + |
| 64 | + if (dateOf != null) |
| 65 | + try { |
| 66 | + dagensDatum = LocalDate.parse(dateOf); |
| 67 | + } catch (DateTimeException e) { |
| 68 | + System.out.println("Ogiltigt datum: " + dateOf); |
| 69 | + helpMe(); |
| 70 | + return; |
| 71 | + } |
| 72 | + else { |
| 73 | + dagensDatum = LocalDate.now(); |
| 74 | + } |
| 75 | + LocalDate tomorrow = dagensDatum.plusDays(1); |
| 76 | + ElpriserAPI.Prisklass zon; |
| 77 | + |
| 78 | + |
| 79 | + if (zoneOf == null || !validZones.contains(zoneOf.toUpperCase())) { |
| 80 | + System.out.println("Ogiltig zon: " + zoneOf); |
| 81 | + helpMe(); |
| 82 | + return; |
| 83 | + } |
| 84 | + zon = ElpriserAPI.Prisklass.valueOf(zoneOf.toUpperCase()); |
| 85 | + List<ElpriserAPI.Elpris> priserIdag = elpriserApi.getPriser(dagensDatum, zon); |
| 86 | + if(priserIdag.isEmpty()) { |
| 87 | + System.out.println("Inga priser hittade för idag"); |
| 88 | + return; |
| 89 | + } else { |
| 90 | + System.out.println("Dagens priser:"); |
| 91 | + } |
| 92 | + List<ElpriserAPI.Elpris> priserImorgon = elpriserApi.getPriser(tomorrow, zon); |
| 93 | + if(priserImorgon.isEmpty()){ |
| 94 | + System.out.println("Inga priser för imorgon hittades"); |
| 95 | + } else { |
| 96 | + System.out.println("Morgondagens priser:"); |
| 97 | + } |
| 98 | + |
| 99 | + numberFormat.setMaximumFractionDigits(2); |
| 100 | + numberFormat.setMinimumFractionDigits(2); |
| 101 | + |
| 102 | + List<ElpriserAPI.Elpris> kombineradeListor = combinedLists(priserIdag,priserImorgon); |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + int timmar =0; |
| 107 | + if (chargingInput != null) { |
| 108 | + if (!validHours.contains(chargingInput.toLowerCase())) { |
| 109 | + System.out.println("Ogiltig charging: " + chargingInput); |
| 110 | + helpMe(); |
| 111 | + return; |
| 112 | + } |
| 113 | + try { |
| 114 | + timmar = Integer.parseInt(chargingInput.toLowerCase().replace("h","")); |
| 115 | + } catch (NumberFormatException e) { |
| 116 | + helpMe(); |
| 117 | + return; |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + if (timmar > 0) { |
| 122 | + chargingWindow(kombineradeListor, timmar); |
| 123 | + return; |
| 124 | + } |
| 125 | + if (isSorted) { |
| 126 | + List<ElpriserAPI.Elpris> sorteradePriser = isSortedCombined(priserIdag, priserImorgon); |
| 127 | + printPriser(sorteradePriser); |
| 128 | + } else { |
| 129 | + printPriser(kombineradeListor); |
| 130 | + } |
| 131 | + |
| 132 | + |
| 133 | + |
| 134 | + priceMinMax(kombineradeListor); |
| 135 | + medelPris(kombineradeListor); |
| 136 | + calculateHourlyAverages(priserIdag); |
| 137 | + |
| 138 | + } |
| 139 | + |
| 140 | + public static List<ElpriserAPI.Elpris> combinedLists(List<ElpriserAPI.Elpris> priserIdag, List<ElpriserAPI.Elpris> priserImorgon) { |
| 141 | + List<ElpriserAPI.Elpris> kombineradeLaddpriser = new ArrayList<>(); |
| 142 | + if (priserIdag != null) kombineradeLaddpriser.addAll(priserIdag); |
| 143 | + if (priserImorgon != null) kombineradeLaddpriser.addAll(priserImorgon); |
| 144 | + |
| 145 | + return kombineradeLaddpriser; |
| 146 | + } |
| 147 | + |
| 148 | + public static void chargingWindow (List<ElpriserAPI.Elpris> elpriserLadda, int timmar) { |
| 149 | + |
| 150 | + DateTimeFormatter minuteFormatter = DateTimeFormatter.ofPattern("HH:mm"); |
| 151 | + |
| 152 | + |
| 153 | + if (elpriserLadda == null) { |
| 154 | + System.out.println("Inga eller för få timmar för att beräkna laddningsfönster."); |
| 155 | + return; |
| 156 | + } |
| 157 | + |
| 158 | + double minSumma = Double.MAX_VALUE; |
| 159 | + int startIndex = -1; |
| 160 | + |
| 161 | + for (int i = 0; i <= elpriserLadda.size() - timmar; i++) { |
| 162 | + double summa = 0.0; |
| 163 | + for (int j = 0; j < timmar; j++) { |
| 164 | + summa += elpriserLadda.get(i+j).sekPerKWh(); |
| 165 | + } |
| 166 | + if (summa< minSumma) { |
| 167 | + minSumma = summa; |
| 168 | + startIndex = i; |
| 169 | + } |
| 170 | + |
| 171 | + } |
| 172 | + if (startIndex != -1) { |
| 173 | + ElpriserAPI.Elpris start = elpriserLadda.get(startIndex); |
| 174 | + ElpriserAPI.Elpris slut = elpriserLadda.get(startIndex + timmar -1); |
| 175 | + |
| 176 | + String startTid = start.timeStart().format(minuteFormatter); |
| 177 | + String slutTid = slut.timeEnd().format(minuteFormatter); |
| 178 | + double snittPris = (minSumma/timmar) * 100; |
| 179 | + |
| 180 | + |
| 181 | + System.out.printf("Billigaste laddningsfönster för %dh är kl %s-%s\nMedelpris för fönster: %.2f öre\n Påbörja laddning %s", timmar, startTid, slutTid, snittPris, startTid); |
| 182 | + } |
| 183 | + } |
| 184 | + //Processar prislistan som får 96 priser |
| 185 | + public static void calculateHourlyAverages (List<ElpriserAPI.Elpris> elpriser96) { |
| 186 | + if (elpriser96.size() > 48) { |
| 187 | + //i är 0; så länge i är mindre än storleken på listan; öka i med 4 |
| 188 | + for (int i = 0; i < elpriser96.size(); i += 4) { |
| 189 | + //I varje loop, stoppa de fyra värdena i en sublist |
| 190 | + List<ElpriserAPI.Elpris> listaPerTimme = elpriser96.subList(i, i + 4); |
| 191 | + |
| 192 | + double sum = listaPerTimme.stream().mapToDouble(ElpriserAPI.Elpris::sekPerKWh).sum(); |
| 193 | + double medelPris = sum / 4.0; |
| 194 | + |
| 195 | + int timme = i / 4; |
| 196 | + int timme2 = timme + 1; |
| 197 | + |
| 198 | + String timDel = String.format("%02d-%02d", timme, timme2); |
| 199 | + double medelprisToOre = medelPris * 100; |
| 200 | + |
| 201 | + |
| 202 | + System.out.printf("%s Medelpris: %.2f öre\n", timDel, medelprisToOre); |
| 203 | + } |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + static void printPriser (List<ElpriserAPI.Elpris> priser) { |
| 208 | + priser.forEach(elpriser -> System.out.printf(""" |
| 209 | + %s-%s %.2f öre |
| 210 | + """,elpriser.timeStart().format(timeFormatter), elpriser.timeEnd().format(timeFormatter), elpriser.sekPerKWh()*100)); |
| 211 | + } |
| 212 | + |
| 213 | + public static List<ElpriserAPI.Elpris> isSortedCombined (List<ElpriserAPI.Elpris> priserIdag, List<ElpriserAPI.Elpris> priserImorgon) { |
| 214 | + List<ElpriserAPI.Elpris> sammansattaPriser = new ArrayList<>(); |
| 215 | + sammansattaPriser.addAll(priserIdag); |
| 216 | + sammansattaPriser.addAll(priserImorgon); |
| 217 | + sammansattaPriser.sort(Comparator.comparing(ElpriserAPI.Elpris::sekPerKWh).reversed().thenComparing(ElpriserAPI.Elpris::timeStart)); |
| 218 | + |
| 219 | + return sammansattaPriser; |
| 220 | + } |
| 221 | + |
| 222 | + private static void medelPris(List<ElpriserAPI.Elpris> prisLista) { |
| 223 | + double summa = 0.0; |
| 224 | + if (prisLista == null) { |
| 225 | + System.out.println("Ingen data tillgänglig för medelpris"); |
| 226 | + return; |
| 227 | + } |
| 228 | + for (ElpriserAPI.Elpris elpriser : prisLista) { |
| 229 | + summa += elpriser.sekPerKWh(); |
| 230 | + } |
| 231 | + double medelPrisOfDay = summa/ prisLista.size() *100; |
| 232 | + System.out.printf("Medelpris: %.2f öre \n", medelPrisOfDay); |
| 233 | + } |
| 234 | + |
| 235 | + public static void priceMinMax (List<ElpriserAPI.Elpris> prisLista) { |
| 236 | + //todo: bryt ut max till en egen metod |
| 237 | + double minPris = Double.MAX_VALUE; |
| 238 | + double maxPris = Double.MIN_VALUE; |
| 239 | + String minTid = null; |
| 240 | + String minTidSlut = null; |
| 241 | + String maxTid = null; |
| 242 | + String maxTidSlut = null; |
| 243 | + if (prisLista.isEmpty()) { |
| 244 | + System.out.println("Ingen data finns att visa"); |
| 245 | + return; |
| 246 | + } |
| 247 | + |
| 248 | + for (ElpriserAPI.Elpris elpriser : prisLista) { |
| 249 | + double worthOf = elpriser.sekPerKWh() *100; |
| 250 | + |
| 251 | + if (minPris > worthOf ) { |
| 252 | + minPris = worthOf; |
| 253 | + minTid = elpriser.timeStart().format(timeFormatter); |
| 254 | + minTidSlut = elpriser.timeEnd().format(timeFormatter); |
| 255 | + } |
| 256 | + if (maxPris < worthOf) { |
| 257 | + maxPris = worthOf; |
| 258 | + maxTid = elpriser.timeStart().format(timeFormatter); |
| 259 | + maxTidSlut = elpriser.timeEnd().format(timeFormatter); |
| 260 | + } |
| 261 | + } |
| 262 | + System.out.printf("Lägsta pris för dagen: %.2f öre/KWh Kl: %s - %s \n", minPris, minTid, minTidSlut); |
| 263 | + System.out.printf("Högsta pris för dagen: %.2f öre/KWh Kl: %s - %s \n", maxPris, maxTid, maxTidSlut); |
| 264 | + |
| 265 | + } |
| 266 | + |
| 267 | + // metod för --help att skickas till if-sats |
| 268 | + public static void helpMe() { |
| 269 | + System.out.println(""" |
| 270 | + Hjälpcenter |
| 271 | + ______________________ |
| 272 | +
|
| 273 | + Usage / Användning: |
| 274 | + java -cp target/classes com.example.Main [alternativ] |
| 275 | +
|
| 276 | + Alternativ: |
| 277 | + --zone SE1|SE2|SE3|SE4 (obligatoriskt) Välj giltig elpris-zon |
| 278 | + --date YYYY-MM-DD (valfritt) Välj datum, t.ex. 2025-09-21 |
| 279 | + --charging 2h|4h|8h (valfritt) Hitta billigaste laddningsfönster |
| 280 | + --sorted (valfritt) Sortera priser fallande |
| 281 | + --help (valfritt) Visa denna hjälptext |
| 282 | +
|
| 283 | + Exempel: |
| 284 | + java Main --zone SE3 -- date 2025-09-21 --charging 4h |
| 285 | + """); |
8 | 286 | } |
9 | 287 | } |
| 288 | + |
| 289 | +// java -cp target/classes com.example.Main --zone SE2 --date 2025-09-04 --sorted |
| 290 | + |
| 291 | + |
| 292 | + |
0 commit comments