diff --git a/src/main/java/no/halvorteigen/powerassetoptimizer/controller/AssetController.java b/src/main/java/no/halvorteigen/powerassetoptimizer/controller/AssetController.java index 4437f63..e3e4359 100644 --- a/src/main/java/no/halvorteigen/powerassetoptimizer/controller/AssetController.java +++ b/src/main/java/no/halvorteigen/powerassetoptimizer/controller/AssetController.java @@ -7,9 +7,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -/** - * NOTE: The asset registers through this API - */ @RestController @RequestMapping("api/v1/asset") public class AssetController { diff --git a/src/main/java/no/halvorteigen/powerassetoptimizer/controller/PowerOptimizationController.java b/src/main/java/no/halvorteigen/powerassetoptimizer/controller/PowerOptimizationController.java index 8e10cf6..0944671 100644 --- a/src/main/java/no/halvorteigen/powerassetoptimizer/controller/PowerOptimizationController.java +++ b/src/main/java/no/halvorteigen/powerassetoptimizer/controller/PowerOptimizationController.java @@ -12,9 +12,6 @@ import java.util.Map; import java.util.Optional; -/** - * NOTE: The asset polls its optimized power usage through this API - */ @RestController @RequestMapping("api/v1/optimize") public class PowerOptimizationController { @@ -27,7 +24,6 @@ public PowerOptimizationController(AssetRepository assetRepository, PowerOptimiz this.powerOptimizationService = powerOptimizationService; } - // NOTE: Assuming that returning a Map instead of a list is ok. Can easily be converted to a list if needed. @GetMapping("/{assetName}") public ResponseEntity> optimizeAssetPower(@PathVariable String assetName) { Optional assetOpt = assetRepository.findByName(assetName); diff --git a/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationService.java b/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationService.java index 156f45d..b190b6f 100644 --- a/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationService.java +++ b/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationService.java @@ -18,6 +18,7 @@ @Service public class PowerOptimizationService { + public static final int HOURS_PER_DAY = 24; private final PowerPriceService powerPriceService; private final Clock clock; @@ -72,11 +73,6 @@ public Map optimizePowerUsage(AssetEntity asset) { GoalType.MINIMIZE ).getPoint(); - for (int i = 0; i < solution.length; i++) { - System.out.println("power = " + solution[i] + ", price = " + prices[i] + ", cost = " + solution[i] * prices[i]); - } - System.out.println("Total cost = " + objectiveFunction.value(solution)); - return IntStream.range(0, solution.length) .boxed() .collect(Collectors.toMap(index -> index, index -> solution[index])); diff --git a/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerPriceService.java b/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerPriceService.java index 4fd3519..2e6fcad 100644 --- a/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerPriceService.java +++ b/src/main/java/no/halvorteigen/powerassetoptimizer/service/PowerPriceService.java @@ -4,6 +4,7 @@ import no.halvorteigen.powerassetoptimizer.enums.PriceArea; import no.halvorteigen.powerassetoptimizer.mappers.MapPowerPriceDtoToPowerPrice; import no.halvorteigen.powerassetoptimizer.model.PowerPrice; +import no.halvorteigen.powerassetoptimizer.utils.DateUtils; import no.halvorteigen.powerassetoptimizer.utils.NumberUtils; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -14,7 +15,6 @@ @Service public class PowerPriceService { - // NOTE: May want to have this url as a configuration property public static final String BASE_URL = "https://www.hvakosterstrommen.no/api/v1/prices/"; private final RestTemplate restTemplate; @@ -34,7 +34,10 @@ public List getPowerPrices(int year, int month, int day, PriceArea p } private static String getUrl(int year, int month, int day, PriceArea priceArea) { - // NOTE: Assuming year, month and day are valid + boolean isValidDate = DateUtils.isValidDate(year, month, day); + if (!isValidDate) { + throw new IllegalArgumentException("Invalid day, month or year."); + } String monthFormatted = NumberUtils.fillLeadingZeros(month, 2); String dayFormatted = NumberUtils.fillLeadingZeros(day, 2); return BASE_URL + year + "/" + monthFormatted + "-" + dayFormatted + "_" + priceArea.name() + ".json"; diff --git a/src/main/java/no/halvorteigen/powerassetoptimizer/utils/DateUtils.java b/src/main/java/no/halvorteigen/powerassetoptimizer/utils/DateUtils.java new file mode 100644 index 0000000..51326bc --- /dev/null +++ b/src/main/java/no/halvorteigen/powerassetoptimizer/utils/DateUtils.java @@ -0,0 +1,19 @@ +package no.halvorteigen.powerassetoptimizer.utils; + +import java.time.DateTimeException; +import java.time.YearMonth; + +public class DateUtils { + + private DateUtils() { + // Hide default constructor + } + + public static boolean isValidDate(int year, int month, int day) { + try { + return YearMonth.of(year, month).isValidDay(day); + } catch (DateTimeException exception) { + return false; + } + } +} diff --git a/src/test/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationServiceTest.java b/src/test/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationServiceTest.java index 075050d..4992f9f 100644 --- a/src/test/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationServiceTest.java +++ b/src/test/java/no/halvorteigen/powerassetoptimizer/service/PowerOptimizationServiceTest.java @@ -22,9 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -/** - * NOTE: The tests do not use realistic numbers, just random numbers that cause the desired behavior - */ @ExtendWith(MockitoExtension.class) class PowerOptimizationServiceTest { @@ -58,10 +55,10 @@ void should_optimize_power() { .limit(24) .toArray(PowerPriceDto[]::new); Mockito.when(restTemplate.getForObject( - ArgumentMatchers.anyString(), - ArgumentMatchers.eq(PowerPriceDto[].class) - )) - .thenReturn(powerPriceDtos); + ArgumentMatchers.anyString(), + ArgumentMatchers.eq(PowerPriceDto[].class) + )) + .thenReturn(powerPriceDtos); PowerOptimizationService powerOptimizationService = new PowerOptimizationService( powerPriceService, @@ -108,10 +105,10 @@ void should_throw_exception_when_infeasible_optimization_problem() { .limit(24) .toArray(PowerPriceDto[]::new); Mockito.when(restTemplate.getForObject( - ArgumentMatchers.anyString(), - ArgumentMatchers.eq(PowerPriceDto[].class) - )) - .thenReturn(powerPriceDtos); + ArgumentMatchers.anyString(), + ArgumentMatchers.eq(PowerPriceDto[].class) + )) + .thenReturn(powerPriceDtos); PowerOptimizationService powerOptimizationService = new PowerOptimizationService( powerPriceService,