more insights fixes
parent
f3ef586de0
commit
f764deb946
|
@ -148,7 +148,10 @@ final private class AggregationPipeline(store: Storage)(implicit ec: scala.concu
|
|||
def matchMoves(extraMatcher: Bdoc = $empty) =
|
||||
combineDocs(extraMatcher :: question.filters.collect {
|
||||
case f if f.dimension.isInMove => f.matcher
|
||||
}).some.filterNot(_.isEmpty) map Match
|
||||
} ::: (dimension match {
|
||||
case D.TimeVariance => List($doc(F.moves("v") $exists true))
|
||||
case _ => Nil
|
||||
})).some.filterNot(_.isEmpty) map Match
|
||||
def projectForMove =
|
||||
Project(BSONDocument({
|
||||
metric.dbKey :: dimension.dbKey :: filters.collect {
|
||||
|
@ -188,7 +191,7 @@ final private class AggregationPipeline(store: Storage)(implicit ec: scala.concu
|
|||
List(
|
||||
projectForMove,
|
||||
unwindMoves,
|
||||
matchMoves($doc(F.moves("o") -> $doc("$exists" -> true))),
|
||||
matchMoves($doc(F.moves("o") $exists true)),
|
||||
sampleMoves
|
||||
) :::
|
||||
group(dimension, GroupFunction("$push", $doc("$cond" -> $arr("$" + F.moves("o"), 1, 0)))) :::
|
||||
|
@ -267,7 +270,7 @@ final private class AggregationPipeline(store: Storage)(implicit ec: scala.concu
|
|||
List(
|
||||
projectForMove,
|
||||
unwindMoves,
|
||||
matchMoves(),
|
||||
matchMoves($doc(F.moves("v") $exists true)),
|
||||
sampleMoves
|
||||
) :::
|
||||
group(
|
||||
|
|
|
@ -83,16 +83,18 @@ final private class Indexer(
|
|||
} map (_.toOption)
|
||||
}
|
||||
val query = gameQuery(user) ++ $doc(Game.BSONFields.createdAt $gte from)
|
||||
val bulkInsert = 50
|
||||
val perSecond = 800
|
||||
gameRepo
|
||||
.sortedCursor(query, Query.sortChronological)
|
||||
.documentSource()
|
||||
.take(maxGames)
|
||||
.mapAsync(16)(toEntry)
|
||||
.via(LilaStream.collect)
|
||||
.throttle(800, 1 second)
|
||||
.zipWithIndex
|
||||
.map { case (e, i) => e.copy(number = fromNumber + i.toInt) }
|
||||
.grouped(50)
|
||||
.grouped(bulkInsert)
|
||||
.throttle(perSecond / bulkInsert, 1 second)
|
||||
.map(storage.bulkInsert)
|
||||
.toMat(Sink.ignore)(Keep.right)
|
||||
.run
|
||||
|
|
|
@ -101,8 +101,12 @@ final private class PovToEntry(
|
|||
case (e, i) if (i % 2) == pivot => e
|
||||
}
|
||||
}
|
||||
val blurs = {
|
||||
val bools = from.pov.player.blurs.booleans
|
||||
bools ++ Array.fill(movetimes.size - bools.size)(false)
|
||||
}
|
||||
val timeCvs = slidingMoveTimesCvs(movetimes)
|
||||
movetimes.zip(roles).zip(boards).zip(from.pov.player.blurs.booleans).zip(timeCvs).zipWithIndex.map {
|
||||
movetimes.zip(roles).zip(boards).zip(blurs).zip(timeCvs).zipWithIndex.map {
|
||||
case movetime ~ role ~ board ~ blur ~ timeCv ~ i =>
|
||||
val ply = i * 2 + from.pov.color.fold(1, 2)
|
||||
val prevInfo = prevInfos lift i
|
||||
|
@ -133,18 +137,28 @@ final private class PovToEntry(
|
|||
opportunism = opportunism,
|
||||
luck = luck,
|
||||
blur = blur,
|
||||
timeCv = timeCv.some
|
||||
timeCv = timeCv
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private def slidingMoveTimesCvs(movetimes: Seq[Centis]): Iterator[Float] =
|
||||
movetimes.iterator
|
||||
.sliding(14)
|
||||
.map(a => a.toList.sorted.drop(1).dropRight(1))
|
||||
.flatMap(a => coefVariation(a.map(_.centis + 10)))
|
||||
private def slidingMoveTimesCvs(movetimes: Seq[Centis]): Seq[Option[Float]] = {
|
||||
val sliding = 13 // should be odd
|
||||
val nb = movetimes.size
|
||||
if (nb < sliding) Vector.fill(nb)(none[Float])
|
||||
else {
|
||||
val sides = Vector.fill(sliding / 2)(none[Float])
|
||||
val cvs = movetimes
|
||||
.sliding(sliding)
|
||||
.map { a =>
|
||||
// drop outliers
|
||||
coefVariation(a.map(_.centis + 10).toSeq.sorted.drop(1).dropRight(1))
|
||||
}
|
||||
sides ++ cvs ++ sides
|
||||
}
|
||||
}
|
||||
|
||||
private def coefVariation(a: List[Int]): Option[Float] = {
|
||||
private def coefVariation(a: Seq[Int]): Option[Float] = {
|
||||
val s = Stats(a)
|
||||
s.stdDev.map { _ / s.mean }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue