@@ -214,4 +214,186 @@ class OpenMeteo(
214214 )
215215 )
216216
217+ private inline fun <reified T > separate (iterable : Iterable <Any >? ) =
218+ iterable?.filterIsInstance<T >()?.ifEmpty { null }
219+
220+ class AnyResponse (
221+ override val latitude : Float ,
222+ override val longitude : Float ,
223+ val elevation : Float? = null ,
224+ @SerialName(" utc_offset_seconds" )
225+ override val utcOffsetSeconds : Int ,
226+ @SerialName(" timezone" )
227+ override val timeZone : TimeZone ,
228+ @SerialName(" timezone_abbreviation" )
229+ override val timeZoneAbbreviation : String ,
230+ @SerialName(" hourly_units" )
231+ override val hourlyUnits : Map <out QueryHourly .Options , Unit > = emptyMap(),
232+ @SerialName(" hourly" )
233+ override val hourlyValues : Map <out QueryHourly .Options , Array <Double ?>> = emptyMap(),
234+ @SerialName(" daily_units" )
235+ override val dailyUnits : Map <out QueryDaily .Options , Unit > = emptyMap(),
236+ @SerialName(" daily" )
237+ override val dailyValues : Map <out QueryDaily .Options , Array <Double ?>> = emptyMap(),
238+ ) : ResponseCoordinates,
239+ ResponseHourly ,
240+ ResponseDaily
241+
242+ operator fun invoke (
243+ hourly : Iterable <QueryHourly .Options >? = null,
244+ daily : Iterable <QueryDaily .Options >? = null,
245+ timeZone : TimeZone ? = null,
246+ startDate : Date ? = null,
247+ endDate : Date ? = null,
248+ pastDays : Int? = null,
249+ forecastDays : Int? = null,
250+ domains : AirQualityDomains ? = null,
251+ currentWeather : Boolean? = null,
252+ temperatureUnit : TemperatureUnit ? = null,
253+ windSpeedUnit : WindSpeedUnit ? = null,
254+ precipitationUnit : PrecipitationUnit ? = null,
255+ latitude : Float = this.latitude,
256+ longitude : Float = this.longitude,
257+ ) = runCatching {
258+
259+ val airQualityHourly = separate<AirQualityHourly >(hourly)
260+ val airQualityResponse = airQualityHourly?.let {
261+ airQuality(
262+ airQualityHourly, domains, timeZone, startDate, endDate,
263+ pastDays, latitude, longitude
264+ ).getOrThrow()
265+ }
266+
267+ val ecmwfHourly = separate<EcmwfHourly >(hourly)
268+ val ecmwfResponse = ecmwfHourly?.let {
269+ ecmwf(
270+ ecmwfHourly, temperatureUnit, windSpeedUnit, precipitationUnit,
271+ timeZone, startDate, endDate, pastDays, latitude, longitude
272+ ).getOrThrow()
273+ }
274+
275+ val forecastHourly = separate<ForecastHourly >(hourly)
276+ val forecastDaily = separate<ForecastDaily >(daily)
277+ // if both are null return null, else return hourly *or* daily
278+ val forecastResponse = (forecastHourly ? : forecastDaily)?.let {
279+ forecast(
280+ forecastHourly, forecastDaily, currentWeather,
281+ temperatureUnit, windSpeedUnit, precipitationUnit, timeZone,
282+ startDate, endDate, pastDays, latitude, longitude
283+ ).getOrThrow()
284+ }
285+
286+ val gfsHourly = separate<GfsHourly >(hourly)
287+ val gfsDaily = separate<GfsDaily >(daily)
288+ val gfsResponse = (gfsHourly ? : gfsDaily)?.let {
289+ gfs(
290+ gfsHourly, gfsDaily, currentWeather, temperatureUnit,
291+ windSpeedUnit, precipitationUnit, timeZone, startDate, endDate,
292+ pastDays, forecastDays, latitude, longitude
293+ ).getOrThrow()
294+ }
295+
296+ val historicalHourly = separate<HistoricalHourly >(hourly)
297+ val historicalDaily = separate<HistoricalDaily >(daily)
298+ val historicalResponse = (historicalHourly ? : historicalDaily)?.let {
299+ historical(
300+ historicalHourly, historicalDaily, temperatureUnit,
301+ windSpeedUnit, precipitationUnit, timeZone, startDate, endDate,
302+ latitude, longitude
303+ ).getOrThrow()
304+ }
305+
306+ val marineHourly = separate<MarineHourly >(hourly)
307+ val marineDaily = separate<MarineDaily >(daily)
308+ val marineResponse = (marineHourly ? : marineDaily)?.let {
309+ marine(
310+ marineHourly, marineDaily, timeZone, startDate, endDate,
311+ latitude, longitude
312+ ).getOrThrow()
313+ }
314+
315+ val hourlyResponses: List <ResponseHourly > = listOfNotNull(
316+ airQualityResponse,
317+ ecmwfResponse,
318+ forecastResponse,
319+ gfsResponse,
320+ historicalResponse,
321+ marineResponse,
322+ )
323+
324+ val dailyResponses: List <ResponseDaily > = listOfNotNull(
325+ forecastResponse,
326+ gfsResponse,
327+ historicalResponse,
328+ marineResponse,
329+ )
330+
331+ val responses = (hourlyResponses + dailyResponses)
332+ // we don't want duplicates
333+ .toSet().toList()
334+
335+ if (responses.isEmpty())
336+ throw Error (" No request was performed! No valid option" )
337+
338+ val elevation = forecastResponse?.elevation
339+ ? : gfsResponse?.elevation
340+
341+ val utcOffsetSeconds = hourlyResponses[0 ].utcOffsetSeconds
342+ val timeZone0 = hourlyResponses[0 ].timeZone
343+ val timeZoneAbbreviation = hourlyResponses[0 ].timeZoneAbbreviation
344+
345+ val hourlyUnits = hourlyResponses
346+ .map { it.hourlyUnits }
347+ .reduce { acc, map -> acc + map }
348+
349+ val hourlyValues = hourlyResponses
350+ .map { it.hourlyValues }
351+ .reduce { acc, map -> acc + map }
352+
353+ val dailyUnits = dailyResponses
354+ .map { it.dailyUnits }
355+ .reduce { acc, map -> acc + map }
356+
357+ val dailyValues = dailyResponses
358+ .map { it.dailyValues }
359+ .reduce { acc, map -> acc + map }
360+
361+
362+ AnyResponse (
363+ latitude,
364+ longitude,
365+ elevation,
366+ utcOffsetSeconds,
367+ timeZone0,
368+ timeZoneAbbreviation,
369+ hourlyUnits,
370+ hourlyValues,
371+ dailyUnits,
372+ dailyValues,
373+ )
374+
375+ }
376+
377+ operator fun invoke (
378+ vararg options : Query .Options ,
379+ timeZone : TimeZone ? = null,
380+ startDate : Date ? = null,
381+ endDate : Date ? = null,
382+ pastDays : Int? = null,
383+ forecastDays : Int? = null,
384+ domains : AirQualityDomains ? = null,
385+ currentWeather : Boolean? = null,
386+ temperatureUnit : TemperatureUnit ? = null,
387+ windSpeedUnit : WindSpeedUnit ? = null,
388+ precipitationUnit : PrecipitationUnit ? = null,
389+ latitude : Float = this.latitude,
390+ longitude : Float = this.longitude,
391+ ) = invoke(
392+ options.filterIsInstance<QueryHourly .Options >(),
393+ options.filterIsInstance<QueryDaily .Options >(),
394+ timeZone, startDate, endDate, pastDays, forecastDays, domains,
395+ currentWeather, temperatureUnit, windSpeedUnit, precipitationUnit,
396+ latitude, longitude,
397+ )
398+
217399}
0 commit comments