more insights fixes

pull/6727/head
Thibault Duplessis 2020-05-29 20:32:11 -06:00
parent f3ef586de0
commit f764deb946
3 changed files with 33 additions and 14 deletions

View File

@ -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(

View File

@ -82,17 +82,19 @@ final private class Indexer(
logger.warn(e.getMessage, e)
} map (_.toOption)
}
val query = gameQuery(user) ++ $doc(Game.BSONFields.createdAt $gte from)
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

View File

@ -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 }
}