Skip to content

Commit

Permalink
Merge pull request #45 from daithihearn/daily-mdian
Browse files Browse the repository at this point in the history
feat: daily median endpoint
  • Loading branch information
daithihearn authored Oct 19, 2023
2 parents 93801b4 + 3308b14 commit 2bc0b77
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.15.0
1.16.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ie.daithi.electricityprices.model

import java.time.LocalDate

data class DailyMedian(
val date: LocalDate,
val median: Double
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package ie.daithi.electricityprices.service

import ie.daithi.electricityprices.exceptions.DataNotAvailableYetException
import ie.daithi.electricityprices.model.DailyPriceInfo
import ie.daithi.electricityprices.model.EsiosPrice
import ie.daithi.electricityprices.model.Price
import ie.daithi.electricityprices.model.ReePrice
import ie.daithi.electricityprices.model.*
import ie.daithi.electricityprices.repos.PriceRepo
import ie.daithi.electricityprices.utils.*
import org.apache.logging.log4j.LogManager
Expand Down Expand Up @@ -62,6 +59,26 @@ class PriceService(
)
}

fun getMedians(prices: List<Price>): List<DailyMedian> {
val medians = mutableListOf<DailyMedian>()
val dates = prices.map { it.dateTime.toLocalDate() }.distinct()
dates.forEach { date ->
val pricesForDay = prices.filter { it.dateTime.toLocalDate() == date }
val median = pricesForDay.map { it.price }.average()
medians.add(DailyMedian(date, median))
}
return medians
}

fun getDailyMedians(date: LocalDate, numberOfDays: Long): List<DailyMedian> {
val xDaysAgo = date.minusDays(numberOfDays).atStartOfDay().minusSeconds(1)
val today = date.plusDays(1).atStartOfDay().minusSeconds(1)

val prices = getPrices(xDaysAgo, today)
if (prices.isEmpty()) throw DataNotAvailableYetException("30 day median data not available for $date")
return getMedians(prices)
}

/*
Calls to the API and update the latest prices
We use the REE API as they have the most up-to-date data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ie.daithi.electricityprices.web.controller

import ie.daithi.electricityprices.exceptions.DataNotAvailableYetException
import ie.daithi.electricityprices.exceptions.UnprocessableEntityException
import ie.daithi.electricityprices.model.DailyMedian
import ie.daithi.electricityprices.model.DailyPriceInfo
import ie.daithi.electricityprices.model.Price
import ie.daithi.electricityprices.service.PriceService
Expand Down Expand Up @@ -131,4 +132,64 @@ class PriceController(
date ?: return priceSerice.getTodayPriceInfo()
return priceSerice.getDailyPriceInfo(LocalDate.parse(date, dateFormatter))
}

@GetMapping("/price/medians")
@ResponseStatus(value = HttpStatus.OK)
@Operation(
summary = "Get 30 day medians",
description = "Return median values for the 30 days before the date provided. " +
"Dates should be given in a string form yyyy-MM-dd"
)
@Parameter(
`in` = ParameterIn.QUERY,
name = "date",
schema = Schema(type = "string", pattern = "\\d{4}-\\d{2}-\\d{2}"),
description = "Address of the transaction origin",
required = false,
example = "2023-08-30"
)
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "Request successful"),
ApiResponse(
responseCode = "404", description = "Data not available", content = [Content(
mediaType = "application/json",
schema = Schema(implementation = DataNotAvailableYetException::class),
examples = [
ExampleObject(
value = "{\n" +
" \"timestamp\": \"2023-09-10T10:03:38.111+00:00\",\n" +
" \"status\": 404,\n" +
" \"error\": \"Not Found\",\n" +
" \"message\": \"No data available for 2024-01-01\",\n" +
" \"path\": \"/api/v1/price/medians?date=2024-01-01\"\n" +
"}"
)
]
)]
),
ApiResponse(
responseCode = "422", description = "Invalid date", content = [Content(
mediaType = "application/json",
schema = Schema(implementation = UnprocessableEntityException::class),
examples = [
ExampleObject(
value = "{\n" +
" \"timestamp\": \"2023-09-10T10:03:38.111+00:00\",\n" +
" \"status\": 422,\n" +
" \"error\": \"Unprocessable Entity\",\n" +
" \"message\": \"\"getDailyPriceInfo.date: The provided date is invalid. It must match yyyy-MM-dd\",\n" +
" \"path\": \"/api/v1/price/medians/incorrect\"\n" +
"}"
)
]
)]
)
]
)
@ResponseBody
fun getThirtyDayMedians(@ValidDateDay @RequestParam(required = false) date: String?): List<DailyMedian> {
val day = date?.let { LocalDate.parse(it, dateFormatter) } ?: LocalDate.now()
return priceSerice.getDailyMedians(day, 30)
}
}

0 comments on commit 2bc0b77

Please sign in to comment.