Changed data structure for weather params and aggregating
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
package parse
|
||||
|
||||
import cats.implicits.{catsSyntaxOptionId, toFoldableOps}
|
||||
import io.circe.generic.semiauto.deriveEncoder
|
||||
import io.circe.syntax.EncoderOps
|
||||
import io.circe.{Encoder, Json}
|
||||
import parse.Parser.parseLine
|
||||
|
||||
object Aggregate {
|
||||
|
||||
case class UserQuery(
|
||||
cities: List[String],
|
||||
field: String,
|
||||
key: AggregateKey
|
||||
)
|
||||
|
||||
sealed trait AggregateKey
|
||||
object AggregateKey {
|
||||
case object Min extends AggregateKey
|
||||
case object Max extends AggregateKey
|
||||
case object Avg extends AggregateKey
|
||||
case object Sum extends AggregateKey
|
||||
case object List extends AggregateKey
|
||||
case object Distinct extends AggregateKey
|
||||
|
||||
def fromString(str: String): Option[AggregateKey] = str match {
|
||||
case "min" => Some(AggregateKey.Min)
|
||||
case "max" => Some(AggregateKey.Max)
|
||||
case "avg" => Some(AggregateKey.Avg)
|
||||
case "sum" => Some(AggregateKey.Sum)
|
||||
case "list" => Some(AggregateKey.List)
|
||||
case "distinct" => Some(AggregateKey.Distinct)
|
||||
case _ => None
|
||||
}
|
||||
|
||||
def getKeys: List[String] = {
|
||||
val runtimeMirror = scala.reflect.runtime.currentMirror
|
||||
val classSymbol = runtimeMirror.classSymbol(classOf[AggregateKey])
|
||||
|
||||
// Get all case classes that extend the AggregateKey trait
|
||||
val keys = classSymbol.knownDirectSubclasses.map(_.name.toString).toList
|
||||
|
||||
keys
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait AggregateValue
|
||||
case class DoubleValue(value: Double) extends AggregateValue
|
||||
case class ListOptionValue(list: List[Option[Double]]) extends AggregateValue
|
||||
case class StringListList(list: List[List[String]]) extends AggregateValue
|
||||
case class DistinctStringList(list: List[String]) extends AggregateValue
|
||||
object AggregateValue {
|
||||
def getKeys: List[String] = {
|
||||
val runtimeMirror = scala.reflect.runtime.currentMirror
|
||||
val classSymbol = runtimeMirror.classSymbol(classOf[AggregateValue])
|
||||
|
||||
// Get all case classes that extend the AggregateValue trait
|
||||
val keys = classSymbol.knownDirectSubclasses.map(_.name.toString).toList
|
||||
|
||||
keys
|
||||
}
|
||||
}
|
||||
|
||||
object AggregateValueImplicits {
|
||||
implicit val aggregateValueEncoder: Encoder[AggregateValue] = Encoder.instance {
|
||||
case doubleValue: DoubleValue => doubleValue.asJson
|
||||
case listOptionValue: ListOptionValue => listOptionValue.asJson
|
||||
case stringListList: StringListList => stringListList.asJson
|
||||
case distinctStringList: DistinctStringList => distinctStringList.asJson
|
||||
}
|
||||
|
||||
implicit val doubleValueEncoder: Encoder[DoubleValue] = Encoder.instance {
|
||||
case DoubleValue(value) if !value.isNaN => Json.fromDouble(value).get
|
||||
case _ => Json.Null
|
||||
}
|
||||
implicit val listOptionValueEncoder: Encoder[ListOptionValue] = deriveEncoder[ListOptionValue]
|
||||
implicit val stringListListEncoder: Encoder[StringListList] = deriveEncoder[StringListList]
|
||||
implicit val distinctStringListEncoder: Encoder[DistinctStringList] = deriveEncoder[DistinctStringList]
|
||||
}
|
||||
|
||||
def extractDoubleFieldValues(field: String, weatherData: List[WeatherData]): List[Option[Double]] =
|
||||
field match {
|
||||
case "tempMax" => weatherData.map(_.tempMax)
|
||||
case "tempMin" => weatherData.map(_.tempMin)
|
||||
case "tempAvg" => weatherData.map(_.tempAvg)
|
||||
case "precipitation" => weatherData.map(_.precipitation)
|
||||
case "windAvg" => weatherData.map(_.windAvg)
|
||||
case "windMax" => weatherData.map(_.windMax)
|
||||
case "visibilityMin" => weatherData.map(_.visibilityMin)
|
||||
case "visibilityAvg" => weatherData.map(_.visibilityAvg)
|
||||
case "snowAvg" => weatherData.map(_.snowAvg)
|
||||
case "atmPressire" => weatherData.map(_.atmPressure)
|
||||
case "dewPoint" => weatherData.map(_.dewPoint)
|
||||
case "humidity" => weatherData.map(_.humidity)
|
||||
case "sunDuration" => weatherData.map(_.sunDuration)
|
||||
// case "phenomena" => weatherData.map(_..phenomena)
|
||||
case _ => List.empty
|
||||
}
|
||||
|
||||
def aggregateDoubleValues(
|
||||
AggKey: AggregateKey,
|
||||
values: List[Option[Double]]
|
||||
): Option[AggregateValue] = {
|
||||
val flatValues = values.flatten
|
||||
AggKey match {
|
||||
case AggregateKey.Min => flatValues.minimumOption.map(DoubleValue)
|
||||
case AggregateKey.Max => flatValues.maximumOption.map(DoubleValue)
|
||||
case AggregateKey.Avg => flatValues.reduceOption(_ + _).map(sum => DoubleValue(sum / flatValues.length))
|
||||
case AggregateKey.Sum => flatValues.sum.some.map(DoubleValue)
|
||||
case AggregateKey.List => ListOptionValue(values).some
|
||||
case AggregateKey.Distinct => None
|
||||
}
|
||||
}
|
||||
|
||||
def aggregatePhenomenaValues(
|
||||
aggregationType: AggregateKey,
|
||||
values: List[List[String]]
|
||||
): Option[AggregateValue] =
|
||||
aggregationType match {
|
||||
case AggregateKey.List => StringListList(values).some
|
||||
case AggregateKey.Distinct => DistinctStringList(values.flatten.distinct).some
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user