db.puzzle2_round (user,date) index, and a theme field
the round.user can be dropped after a year to keep the index smallpuzzle
parent
967a664d5d
commit
aa27d11787
|
@ -95,13 +95,11 @@ final class Puzzle(
|
|||
ctx.me match {
|
||||
case Some(me) =>
|
||||
for {
|
||||
isStudent <- env.clas.api.student.isStudent(me.id)
|
||||
(round, perf) <- env.puzzle.finisher(
|
||||
puzzle = puzzle,
|
||||
theme = theme.key,
|
||||
user = me,
|
||||
result = Result(resultInt == 1),
|
||||
isStudent = isStudent
|
||||
result = Result(resultInt == 1)
|
||||
)
|
||||
newUser = me.copy(perfs = me.perfs.copy(puzzle = perf))
|
||||
_ = env.puzzle.session.onComplete(round, theme.key)
|
||||
|
@ -312,13 +310,11 @@ final class Puzzle(
|
|||
).fuccess
|
||||
case Some((puzzle, result)) =>
|
||||
for {
|
||||
isStudent <- env.clas.api.student.isStudent(me.id)
|
||||
(round, perf) <- env.puzzle.finisher(
|
||||
puzzle = puzzle,
|
||||
theme = PuzzleTheme.mix.key,
|
||||
user = me,
|
||||
result = result,
|
||||
isStudent = isStudent
|
||||
result = result
|
||||
)
|
||||
_ = env.puzzle.session.onComplete(round, PuzzleTheme.mix.key)
|
||||
} yield Ok(
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// for puzzle v2
|
||||
|
||||
db.puzzle2_path.createIndex({min: 1, max: -1});
|
||||
|
||||
db.puzzle2_round.createIndex({p: 1}, {partialFilterExpression:{t:{$exists:true}}});
|
||||
db.puzzle2_round.createIndex({u:1,d:-1},{partialFilterExpression:{u:{$exists:1}}});
|
||||
|
||||
db.puzzle2_puzzle.createIndex({day:1}, {partialFilterExpression:{day:{$exists:true}}});
|
||||
|
|
|
@ -3,7 +3,7 @@ package lila.activity
|
|||
import reactivemongo.api.bson._
|
||||
import scala.util.Success
|
||||
|
||||
import lila.common.Iso
|
||||
import lila.common.{ Day, Iso }
|
||||
import lila.db.dsl._
|
||||
import lila.rating.BSONHandlers.perfTypeKeyIso
|
||||
import lila.rating.PerfType
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package lila.clas
|
||||
|
||||
import org.joda.time.{ DateTime, Period }
|
||||
|
||||
import lila.rating.PerfType
|
||||
import lila.game.{ Game, GameRepo }
|
||||
import lila.user.User
|
||||
import lila.db.dsl._
|
||||
import reactivemongo.api._
|
||||
import reactivemongo.api.bson._
|
||||
|
||||
import lila.db.dsl._
|
||||
import lila.game.{ Game, GameRepo }
|
||||
import lila.puzzle.PuzzleRound
|
||||
import lila.rating.PerfType
|
||||
import lila.user.User
|
||||
|
||||
case class ClasProgress(
|
||||
perfType: PerfType,
|
||||
days: Int,
|
||||
|
@ -84,8 +85,8 @@ final class ClasProgressApi(
|
|||
import framework._
|
||||
Match(
|
||||
$doc(
|
||||
"u" $in userIds,
|
||||
"a" $gt (DateTime.now minusDays days)
|
||||
PuzzleRound.BSONFields.user $in userIds,
|
||||
PuzzleRound.BSONFields.date $gt DateTime.now.minusDays(days)
|
||||
)
|
||||
) -> List(
|
||||
GroupField("u")(
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package lila.puzzle
|
||||
|
||||
case class AggregateVote(up: Int, down: Int, nb: Int, ratio: Int) {
|
||||
|
||||
def add(v: Boolean) =
|
||||
copy(
|
||||
up = up + (if (v) 1 else 0),
|
||||
down = down + (if (v) 0 else 1)
|
||||
).computeNbAndRatio
|
||||
|
||||
def change(from: Boolean, to: Boolean) =
|
||||
if (from == to) this
|
||||
else
|
||||
copy(
|
||||
up = up + (if (to) 1 else -1),
|
||||
down = down + (if (to) -1 else 1)
|
||||
).computeNbAndRatio
|
||||
|
||||
def count = up + down
|
||||
|
||||
def sum = up - down
|
||||
|
||||
def computeNbAndRatio =
|
||||
if (up + down > 0)
|
||||
copy(
|
||||
ratio = 100 * (up - down) / (up + down),
|
||||
nb = up + down
|
||||
)
|
||||
else
|
||||
copy(
|
||||
ratio = 1,
|
||||
nb = 0
|
||||
)
|
||||
}
|
||||
|
||||
object AggregateVote {
|
||||
|
||||
val default = AggregateVote(1, 0, 1, 100)
|
||||
val disable = AggregateVote(0, 9000, 9000, -100).computeNbAndRatio
|
||||
|
||||
val minRatio = -50
|
||||
val minVotes = 30
|
||||
|
||||
import reactivemongo.api.bson.Macros
|
||||
implicit val aggregatevoteBSONHandler = Macros.handler[AggregateVote]
|
||||
}
|
|
@ -3,12 +3,12 @@ package lila.puzzle
|
|||
import chess.format.{ FEN, Uci }
|
||||
import reactivemongo.api.bson._
|
||||
import scala.util.Success
|
||||
import scala.util.Try
|
||||
|
||||
import lila.db.BSON
|
||||
import lila.db.dsl._
|
||||
import lila.game.Game
|
||||
import lila.rating.Glicko
|
||||
import scala.util.Try
|
||||
|
||||
private[puzzle] object BsonHandlers {
|
||||
|
||||
|
@ -64,20 +64,18 @@ private[puzzle] object BsonHandlers {
|
|||
import PuzzleRound.BSONFields._
|
||||
def reads(r: BSON.Reader) = PuzzleRound(
|
||||
id = r.get[PuzzleRound.Id](id),
|
||||
date = r.date(date),
|
||||
win = r.bool(win),
|
||||
date = r.date(date),
|
||||
vote = r.intO(vote),
|
||||
themes = r.getsD[PuzzleRound.Theme](themes),
|
||||
weight = r.intO(weight)
|
||||
themes = r.getsD[PuzzleRound.Theme](themes)
|
||||
)
|
||||
def writes(w: BSON.Writer, r: PuzzleRound) =
|
||||
$doc(
|
||||
id -> r.id,
|
||||
date -> r.date,
|
||||
win -> r.win,
|
||||
date -> r.date,
|
||||
vote -> r.vote,
|
||||
themes -> w.listO(r.themes),
|
||||
weight -> r.weight
|
||||
themes -> w.listO(r.themes)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ final class PuzzleActivity(
|
|||
def stream(config: Config): Source[String, _] =
|
||||
Source futureSource {
|
||||
colls.round.map {
|
||||
_.find($doc("_id" $startsWith s"${config.user.id}${PuzzleRound.idSep}"))
|
||||
.sort($sort desc "_id")
|
||||
_.find($doc(PuzzleRound.BSONFields.user -> config.user.id))
|
||||
.sort($sort desc PuzzleRound.BSONFields.date)
|
||||
.batchSize(config.perSecond.value)
|
||||
.cursor[PuzzleRound](ReadPreference.secondaryPreferred)
|
||||
.documentSource()
|
||||
|
@ -46,13 +46,8 @@ final class PuzzleActivity(
|
|||
colls.puzzle {
|
||||
_.primitiveMap[Puzzle.Id, Double](
|
||||
ids = rounds.map(_.id.puzzleId),
|
||||
field = "perf.gl.r",
|
||||
fieldExtractor = obj =>
|
||||
for {
|
||||
perf <- obj.child("perf")
|
||||
gl <- perf.child("gl")
|
||||
rating <- gl.double("r")
|
||||
} yield rating
|
||||
field = s"${Puzzle.BSONFields.glicko}.r",
|
||||
fieldExtractor = _.child("glicko").flatMap(_ double "r")
|
||||
) map { ratings =>
|
||||
rounds flatMap { round =>
|
||||
ratings get round.id.puzzleId map { puzzleRating =>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package lila.puzzle
|
||||
|
||||
import cats.implicits._
|
||||
import org.joda.time.DateTime
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import lila.db.AsyncColl
|
||||
|
@ -33,10 +34,12 @@ final private[puzzle] class PuzzleApi(
|
|||
def find(user: User, puzzleId: Puzzle.Id): Fu[Option[PuzzleRound]] =
|
||||
colls.round(_.byId[PuzzleRound](PuzzleRound.Id(user.id, puzzleId).toString))
|
||||
|
||||
def upsert(r: PuzzleRound, studentUserId: Option[User.ID]): Funit = {
|
||||
val roundDoc = RoundHandler.write(r) ++ studentUserId.?? { userId =>
|
||||
$doc(PuzzleRound.BSONFields.user -> userId)
|
||||
}
|
||||
def upsert(r: PuzzleRound, theme: PuzzleTheme.Key): Funit = {
|
||||
val roundDoc = RoundHandler.write(r) ++
|
||||
$doc(
|
||||
PuzzleRound.BSONFields.user -> r.id.userId,
|
||||
PuzzleRound.BSONFields.theme -> theme.some.filter(_ != PuzzleTheme.mix.key)
|
||||
)
|
||||
colls.round(_.update.one($id(r.id), roundDoc, upsert = true)).void
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,7 @@ final private[puzzle] class PuzzleFinisher(
|
|||
puzzle: Puzzle,
|
||||
theme: PuzzleTheme.Key,
|
||||
user: User,
|
||||
result: Result,
|
||||
isStudent: Boolean
|
||||
result: Result
|
||||
): Fu[(PuzzleRound, Perf)] =
|
||||
api.round.find(user, puzzle.id) flatMap { prevRound =>
|
||||
val now = DateTime.now
|
||||
|
@ -65,7 +64,8 @@ final private[puzzle] class PuzzleFinisher(
|
|||
.some
|
||||
.filter(puzzle.glicko !=)
|
||||
.filter(_.sanityCheck)
|
||||
val round = PuzzleRound(id = PuzzleRound.Id(user.id, puzzle.id), date = now, win = result.win)
|
||||
val round =
|
||||
PuzzleRound(id = PuzzleRound.Id(user.id, puzzle.id), win = result.win, date = DateTime.now)
|
||||
val userPerf =
|
||||
user.perfs.puzzle.addOrReset(_.puzzle.crazyGlicko, s"puzzle ${puzzle.id}")(userRating, now) pipe {
|
||||
p =>
|
||||
|
@ -75,7 +75,7 @@ final private[puzzle] class PuzzleFinisher(
|
|||
}
|
||||
(round, newPuzzleGlicko, userPerf)
|
||||
}
|
||||
api.round.upsert(round, isStudent option user.id) zip
|
||||
api.round.upsert(round, theme) zip
|
||||
colls.puzzle {
|
||||
_.update
|
||||
.one(
|
||||
|
|
|
@ -2,15 +2,15 @@ package lila.puzzle
|
|||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
import lila.common.Day
|
||||
import lila.user.User
|
||||
|
||||
case class PuzzleRound(
|
||||
id: PuzzleRound.Id,
|
||||
date: DateTime,
|
||||
win: Boolean,
|
||||
date: DateTime,
|
||||
vote: Option[Int] = None,
|
||||
themes: List[PuzzleRound.Theme] = Nil,
|
||||
weight: Option[Int] = None
|
||||
themes: List[PuzzleRound.Theme] = Nil
|
||||
) {
|
||||
|
||||
def userId = id.userId
|
||||
|
@ -49,12 +49,13 @@ object PuzzleRound {
|
|||
|
||||
object BSONFields {
|
||||
val id = "_id"
|
||||
val date = "d"
|
||||
val win = "w"
|
||||
val vote = "v"
|
||||
val themes = "t"
|
||||
val puzzle = "p" // only if themes is set!
|
||||
val weight = "e"
|
||||
val user = "u" // student denormalization
|
||||
val user = "u"
|
||||
val date = "d"
|
||||
val theme = "t"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue