activity: aggregate practice progress
parent
7e14de5f7b
commit
93c121c0c8
|
@ -12,7 +12,8 @@ case class Activity(
|
|||
comps: CompAnalysis,
|
||||
posts: Posts,
|
||||
puzzles: Puzzles,
|
||||
learn: Learn
|
||||
learn: Learn,
|
||||
practice: Practice
|
||||
) {
|
||||
|
||||
def userId = id.userId
|
||||
|
@ -41,6 +42,7 @@ object Activity {
|
|||
posts = PostsZero.zero,
|
||||
comps = CompsZero.zero,
|
||||
puzzles = PuzzlesZero.zero,
|
||||
learn = LearnZero.zero
|
||||
learn = LearnZero.zero,
|
||||
practice = PracticeZero.zero
|
||||
)
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ final class ActivityApi(coll: Coll) {
|
|||
def addLearn(userId: User.ID, stage: String) =
|
||||
update(userId) { a => a.copy(learn = a.learn + Learn.Stage(stage)).some }
|
||||
|
||||
def addPractice(prog: lila.practice.PracticeProgress.OnComplete) =
|
||||
update(prog.userId) { a => a.copy(practice = a.practice + prog.studyId).some }
|
||||
|
||||
private def getOrCreate(userId: User.ID) = get(userId) map { _ | Activity.make(userId) }
|
||||
private def save(activity: Activity) = coll.update($id(activity.id), activity, upsert = true).void
|
||||
private def update(userId: User.ID)(f: Activity => Option[Activity]): Funit =
|
||||
|
|
|
@ -7,6 +7,7 @@ import lila.db.BSON.{ MapDocument, MapValue }
|
|||
import lila.db.dsl._
|
||||
import lila.rating.BSONHandlers.perfTypeKeyIso
|
||||
import lila.rating.PerfType
|
||||
import lila.study.Study
|
||||
|
||||
private object BSONHandlers {
|
||||
|
||||
|
@ -72,6 +73,10 @@ private object BSONHandlers {
|
|||
private implicit val learnMapHandler = MapValue.MapHandler[Learn.Stage, Int]
|
||||
private implicit val learnHandler = isoHandler[Learn, Map[Learn.Stage, Int], Bdoc]((l: Learn) => l.value, Learn.apply _)
|
||||
|
||||
private implicit val studyIdIso = Iso.string[Study.Id](Study.Id.apply, _.value)
|
||||
private implicit val practiceMapHandler = MapValue.MapHandler[Study.Id, Int]
|
||||
private implicit val practiceHandler = isoHandler[Practice, Map[Study.Id, Int], Bdoc]((p: Practice) => p.value, Practice.apply _)
|
||||
|
||||
implicit val activityHandler = new lila.db.BSON[Activity] {
|
||||
|
||||
private val id = "_id"
|
||||
|
@ -80,6 +85,7 @@ private object BSONHandlers {
|
|||
private val posts = "p"
|
||||
private val puzzles = "z"
|
||||
private val learn = "l"
|
||||
private val practice = "r"
|
||||
|
||||
def reads(r: lila.db.BSON.Reader) = Activity(
|
||||
id = r.get[Id](id),
|
||||
|
@ -87,7 +93,8 @@ private object BSONHandlers {
|
|||
comps = r.getD[CompAnalysis](comps),
|
||||
posts = r.getD[Posts](posts),
|
||||
puzzles = r.getD[Puzzles](puzzles),
|
||||
learn = r.getD[Learn](learn)
|
||||
learn = r.getD[Learn](learn),
|
||||
practice = r.getD[Practice](practice)
|
||||
)
|
||||
|
||||
def writes(w: lila.db.BSON.Writer, o: Activity) = BSONDocument(
|
||||
|
@ -96,7 +103,8 @@ private object BSONHandlers {
|
|||
comps -> w.zero(o.comps),
|
||||
posts -> w.zero(o.posts),
|
||||
puzzles -> w.zero(o.puzzles),
|
||||
learn -> w.zero(o.learn)
|
||||
learn -> w.zero(o.learn),
|
||||
practice -> w.zero(o.practice)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,18 @@ final class Env(
|
|||
coll = activityColl
|
||||
)
|
||||
|
||||
system.lilaBus.subscribe(system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
case lila.game.actorApi.FinishGame(game, _, _) if !game.aborted => api addGame game
|
||||
case lila.analyse.actorApi.AnalysisReady(_, analysis) => api addAnalysis analysis
|
||||
case lila.forum.actorApi.CreatePost(post, topic) => api.addForumPost(post, topic)
|
||||
case res: lila.puzzle.Puzzle.UserResult => api addPuzzle res
|
||||
}
|
||||
})), 'finishGame, 'analysisReady, 'forumPost, 'finishPuzzle)
|
||||
system.lilaBus.subscribe(
|
||||
system.actorOf(Props(new Actor {
|
||||
def receive = {
|
||||
case lila.game.actorApi.FinishGame(game, _, _) if !game.aborted => api addGame game
|
||||
case lila.analyse.actorApi.AnalysisReady(_, analysis) => api addAnalysis analysis
|
||||
case lila.forum.actorApi.CreatePost(post, topic) => api.addForumPost(post, topic)
|
||||
case res: lila.puzzle.Puzzle.UserResult => api addPuzzle res
|
||||
case prog: lila.practice.PracticeProgress.OnComplete => api addPractice prog
|
||||
}
|
||||
})),
|
||||
'finishGame, 'analysisReady, 'forumPost, 'finishPuzzle, 'finishPractice
|
||||
)
|
||||
}
|
||||
|
||||
object Env {
|
||||
|
|
|
@ -2,6 +2,7 @@ package lila.activity
|
|||
|
||||
import ornicar.scalalib.Zero
|
||||
import lila.rating.PerfType
|
||||
import lila.study.Study
|
||||
import model._
|
||||
|
||||
object activities {
|
||||
|
@ -44,4 +45,11 @@ object activities {
|
|||
case class Stage(value: String) extends AnyVal
|
||||
}
|
||||
implicit val LearnZero = Zero.instance(Learn(Map.empty))
|
||||
|
||||
case class Practice(value: Map[Study.Id, Int]) {
|
||||
def +(studyId: Study.Id) = copy(
|
||||
value = value + (studyId -> value.get(studyId).fold(1)(1 +))
|
||||
)
|
||||
}
|
||||
implicit val PracticeZero = Zero.instance(Practice(Map.empty))
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ final class Env(
|
|||
coll = db(CollectionProgress),
|
||||
configStore = configStore[PracticeConfig]("practice", logger),
|
||||
asyncCache = asyncCache,
|
||||
studyApi = studyApi
|
||||
studyApi = studyApi,
|
||||
bus = system.lilaBus
|
||||
)
|
||||
|
||||
system.lilaBus.subscribe(system.actorOf(Props(new Actor {
|
||||
|
|
|
@ -10,7 +10,8 @@ final class PracticeApi(
|
|||
coll: Coll,
|
||||
configStore: lila.memo.ConfigStore[PracticeConfig],
|
||||
asyncCache: lila.memo.AsyncCache.Builder,
|
||||
studyApi: lila.study.StudyApi
|
||||
studyApi: lila.study.StudyApi,
|
||||
bus: lila.common.Bus
|
||||
) {
|
||||
|
||||
import BSONHandlers._
|
||||
|
@ -82,10 +83,15 @@ final class PracticeApi(
|
|||
private def save(p: PracticeProgress): Funit =
|
||||
coll.update($id(p.id), p, upsert = true).void
|
||||
|
||||
def setNbMoves(user: User, chapterId: Chapter.Id, score: NbMoves) =
|
||||
def setNbMoves(user: User, chapterId: Chapter.Id, score: NbMoves) = {
|
||||
get(user) flatMap { prog =>
|
||||
save(prog.withNbMoves(chapterId, score))
|
||||
}
|
||||
} >>- studyApi.studyIdOf(chapterId).foreach {
|
||||
_ ?? { studyId =>
|
||||
bus.publish(PracticeProgress.OnComplete(user.id, studyId, chapterId), 'finishPractice)
|
||||
}
|
||||
}
|
||||
|
||||
def reset(user: User) =
|
||||
coll.remove($id(user.id)).void
|
||||
|
|
|
@ -2,6 +2,7 @@ package lila.practice
|
|||
|
||||
import org.joda.time.DateTime
|
||||
|
||||
import lila.user.User
|
||||
import lila.study.{ Study, Chapter }
|
||||
|
||||
case class PracticeProgress(
|
||||
|
@ -43,6 +44,8 @@ object PracticeProgress {
|
|||
case class NbMoves(value: Int) extends AnyVal
|
||||
implicit val nbMovesIso = lila.common.Iso.int[NbMoves](NbMoves.apply, _.value)
|
||||
|
||||
case class OnComplete(userId: User.ID, studyId: Study.Id, chapterId: Chapter.Id)
|
||||
|
||||
type ChapterNbMoves = Map[Chapter.Id, NbMoves]
|
||||
|
||||
def empty(id: Id) = PracticeProgress(
|
||||
|
|
|
@ -14,6 +14,9 @@ final class ChapterRepo(coll: Coll) {
|
|||
|
||||
def byId(id: Chapter.Id): Fu[Option[Chapter]] = coll.byId[Chapter, Chapter.Id](id)
|
||||
|
||||
def studyIdOf(chapterId: Chapter.Id): Fu[Option[Study.Id]] =
|
||||
coll.primitiveOne[Study.Id]($id(chapterId), "studyId")
|
||||
|
||||
// def metadataById(id: Chapter.Id): Fu[Option[Chapter.Metadata]] =
|
||||
// coll.find($id(id), noRootProjection).one[Chapter.Metadata]
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ final class StudyApi(
|
|||
}
|
||||
}
|
||||
|
||||
def studyIdOf = chapterRepo.studyIdOf _
|
||||
|
||||
def create(data: DataForm.Data, user: User): Fu[Option[Study.WithChapter]] = data.as match {
|
||||
case DataForm.AsNewStudy =>
|
||||
studyMaker(data, user) flatMap { res =>
|
||||
|
|
|
@ -193,7 +193,7 @@ object ApplicationBuild extends Build {
|
|||
libraryDependencies ++= provided(play.api, reactivemongo.driver)
|
||||
)
|
||||
|
||||
lazy val activity = project("activity", Seq(common, game, analyse, user, forum, study, pool, puzzle, tournament)).settings(
|
||||
lazy val activity = project("activity", Seq(common, game, analyse, user, forum, study, pool, puzzle, tournament, practice)).settings(
|
||||
libraryDependencies ++= provided(play.api, reactivemongo.driver)
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue