lila/modules/insight/src/main/AggregationClusters.scala

54 lines
1.9 KiB
Scala
Raw Normal View History

package lila.insight
2019-11-29 19:16:11 -07:00
import reactivemongo.api.bson._
import lila.db.dsl._
object AggregationClusters {
def apply[X](question: Question[X], aggDocs: List[Bdoc]): List[Cluster[X]] =
postSort(question) {
if (Metric isStacked question.metric) stacked(question, aggDocs)
else single(question, aggDocs)
}
private def single[X](question: Question[X], aggDocs: List[Bdoc]): List[Cluster[X]] =
2020-05-27 12:41:50 -06:00
for {
doc <- aggDocs
x <- getId[X](doc)(question.dimension.bson)
value <- doc.double("v")
nb <- doc.int("nb")
ids <- doc.getAsOpt[List[String]]("ids")
} yield Cluster(x, Insight.Single(Point(value)), nb, ids)
private def getId[X](doc: Bdoc)(reader: BSONReader[X]): Option[X] =
doc.get("_id") flatMap reader.readOpt
2015-11-27 20:42:56 -07:00
private case class StackEntry(metric: BSONValue, v: BSONNumberLike)
2019-12-13 07:30:20 -07:00
implicit private val StackEntryBSONReader = Macros.reader[StackEntry]
private def stacked[X](question: Question[X], aggDocs: List[Bdoc]): List[Cluster[X]] =
2020-05-27 21:08:37 -06:00
for {
doc <- aggDocs
metricValues = Metric valuesOf question.metric
x <- getId[X](doc)(question.dimension.bson)
stack <- doc.getAsOpt[List[StackEntry]]("stack")
2020-09-21 01:28:28 -06:00
points = metricValues.map { case Metric.MetricValue(id, name) =>
name -> Point(stack.find(_.metric == id).??(_.v.toDouble.get))
2020-05-27 21:08:37 -06:00
}
total = stack.map(_.v.toInt.get).sum
percents =
if (total == 0) points
else
2020-09-21 01:28:28 -06:00
points.map { case (n, p) =>
n -> Point(100 * p.y / total)
2020-05-27 21:08:37 -06:00
}
ids <- doc.getAsOpt[List[String]]("ids")
} yield Cluster(x, Insight.Stacked(percents), total, ids)
2020-05-05 22:11:15 -06:00
private def postSort[X](q: Question[X])(clusters: List[Cluster[X]]): List[Cluster[X]] =
q.dimension match {
case Dimension.Opening => clusters
case _ => clusters.sortLike(Dimension.valuesOf(q.dimension), _.x)
}
}