|
| 1 | +package io.github.tobyhs.weatherweight.data |
| 2 | + |
| 3 | +import io.github.tobyhs.weatherweight.api.tomorrow.TomorrowService |
| 4 | +import io.github.tobyhs.weatherweight.data.model.DailyForecast |
| 5 | +import io.github.tobyhs.weatherweight.data.model.ForecastResultSet |
| 6 | +import io.github.tobyhs.weatherweight.data.model.HourlyForecast |
| 7 | + |
| 8 | +import kotlinx.coroutines.CoroutineDispatcher |
| 9 | +import kotlinx.coroutines.withContext |
| 10 | + |
| 11 | +import java.time.Clock |
| 12 | +import java.time.ZonedDateTime |
| 13 | + |
| 14 | +import kotlin.math.roundToInt |
| 15 | + |
| 16 | +/** |
| 17 | + * Implementation of [WeatherCoroutinesRepository] that uses tomorrow.io' APIs |
| 18 | + */ |
| 19 | +class TomorrowRepository( |
| 20 | + private val tomorrowService: TomorrowService, |
| 21 | + private val clock: Clock, |
| 22 | + private val ioDispatcher: CoroutineDispatcher, |
| 23 | +) : WeatherCoroutinesRepository { |
| 24 | + override suspend fun getForecast(location: String): ForecastResultSet = withContext(ioDispatcher) { |
| 25 | + val forecast = tomorrowService.getForecast(location) |
| 26 | + ForecastResultSet( |
| 27 | + location = forecast.location.name, |
| 28 | + publicationTime = ZonedDateTime.now(clock), |
| 29 | + dailyForecasts = convertDailyForecasts(forecast.timelines.daily), |
| 30 | + hourlyForecasts = convertHourlyForecasts(forecast.timelines.hourly), |
| 31 | + ) |
| 32 | + } |
| 33 | + |
| 34 | + private fun convertDailyForecasts( |
| 35 | + dailyForecasts: List<io.github.tobyhs.weatherweight.api.tomorrow.forecast.DailyForecast> |
| 36 | + ): List<DailyForecast> = dailyForecasts.map { dailyForecast -> |
| 37 | + val descriptionMin = convertWeatherCode(dailyForecast.values.weatherCodeMin) |
| 38 | + val descriptionMax = convertWeatherCode(dailyForecast.values.weatherCodeMax) |
| 39 | + val description = if (descriptionMin == descriptionMax) { |
| 40 | + descriptionMin |
| 41 | + } else { |
| 42 | + "$descriptionMin / $descriptionMax" |
| 43 | + } |
| 44 | + DailyForecast( |
| 45 | + date = dailyForecast.time.toLocalDate(), |
| 46 | + low = dailyForecast.values.temperatureMin.roundToInt(), |
| 47 | + high = dailyForecast.values.temperatureMax.roundToInt(), |
| 48 | + text = description, |
| 49 | + precipitationProbability = dailyForecast.values.precipitationProbabilityMax, |
| 50 | + ) |
| 51 | + } |
| 52 | + |
| 53 | + private fun convertHourlyForecasts( |
| 54 | + hourlyForecasts: List<io.github.tobyhs.weatherweight.api.tomorrow.forecast.HourlyForecast> |
| 55 | + ): List<HourlyForecast> = hourlyForecasts.map { hourlyForecast -> |
| 56 | + HourlyForecast( |
| 57 | + dateTime = hourlyForecast.time, |
| 58 | + text = convertWeatherCode(hourlyForecast.values.weatherCode), |
| 59 | + temperature = hourlyForecast.values.temperature.roundToInt(), |
| 60 | + precipitationProbability = hourlyForecast.values.precipitationProbability, |
| 61 | + ) |
| 62 | + } |
| 63 | + |
| 64 | + private fun convertWeatherCode(weatherCode: Int): String { |
| 65 | + return TOMORROW_WEATHER_CODES.getOrDefault(weatherCode, "Unknown") |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +// From https://docs.tomorrow.io/reference/data-layers-weather-codes |
| 70 | +private val TOMORROW_WEATHER_CODES = mapOf( |
| 71 | + 0 to "Unknown", |
| 72 | + 1000 to "Clear, Sunny", |
| 73 | + 1100 to "Mostly Clear", |
| 74 | + 1101 to "Partly Cloudy", |
| 75 | + 1102 to "Mostly Cloudy", |
| 76 | + 1001 to "Cloudy", |
| 77 | + 2000 to "Fog", |
| 78 | + 2100 to "Light Fog", |
| 79 | + 4000 to "Drizzle", |
| 80 | + 4001 to "Rain", |
| 81 | + 4200 to "Light Rain", |
| 82 | + 4201 to "Heavy Rain", |
| 83 | + 5000 to "Snow", |
| 84 | + 5001 to "Flurries", |
| 85 | + 5100 to "Light Snow", |
| 86 | + 5101 to "Heavy Snow", |
| 87 | + 6000 to "Freezing Drizzle", |
| 88 | + 6001 to "Freezing Rain", |
| 89 | + 6200 to "Light Freezing Rain", |
| 90 | + 6201 to "Heavy Freezing Rain", |
| 91 | + 7000 to "Ice Pellets", |
| 92 | + 7101 to "Heavy Ice Pellets", |
| 93 | + 7102 to "Light Ice Pellets", |
| 94 | + 8000 to "Thunderstorm", |
| 95 | +) |
0 commit comments