lila/app/controllers/Practice.scala

158 lines
4.7 KiB
Scala

package controllers
import play.api.libs.json._
import scala.annotation.nowarn
import lila.api.Context
import lila.app._
import lila.practice.JsonView._
import lila.practice.{ PracticeSection, PracticeStudy, UserStudy }
import lila.study.Study.WithChapter
import lila.study.{ Chapter, Study => StudyModel }
import lila.tree.Node.partitionTreeJsonWriter
import views._
final class Practice(
env: Env,
userAnalysisC: => UserAnalysis
) extends LilaController(env) {
private val api = env.practice.api
def index =
Open { implicit ctx =>
pageHit
api.get(ctx.me) flatMap { up =>
NoCache(Ok(html.practice.index(up))).fuccess
}
}
def show(
@nowarn("cat=unused") sectionId: String,
@nowarn("cat=unused") studySlug: String,
studyId: String
) =
Open { implicit ctx =>
OptionFuResult(api.getStudyWithFirstOngoingChapter(ctx.me, studyId))(showUserPractice)
}
def showChapter(
@nowarn("cat=unused") sectionId: String,
@nowarn("cat=unused") studySlug: String,
studyId: String,
chapterId: String
) =
Open { implicit ctx =>
OptionFuResult(api.getStudyWithChapter(ctx.me, studyId, chapterId))(showUserPractice)
}
def showSection(sectionId: String) =
redirectTo(sectionId)(_.studies.headOption)
def showStudySlug(sectionId: String, studySlug: String) =
redirectTo(sectionId)(_.studies.find(_.slug == studySlug))
private def redirectTo(sectionId: String)(select: PracticeSection => Option[PracticeStudy]) =
Open { implicit ctx =>
api.structure.get.flatMap { struct =>
struct.sections.find(_.id == sectionId).fold(notFound) { section =>
select(section) ?? { study =>
Redirect(routes.Practice.show(section.id, study.slug, study.id.value)).fuccess
}
}
}
}
private def showUserPractice(us: lila.practice.UserStudy)(implicit ctx: Context) =
analysisJson(us) map { case (analysisJson, studyJson) =>
NoCache(
EnableSharedArrayBuffer(
Ok(
html.practice.show(
us,
lila.practice.JsonView.JsData(
study = studyJson,
analysis = analysisJson,
practice = lila.practice.JsonView(us)
)
)
)
)
)
}
def chapter(studyId: String, chapterId: String) =
Open { implicit ctx =>
OptionFuResult(api.getStudyWithChapter(ctx.me, studyId, chapterId)) { us =>
analysisJson(us) map { case (analysisJson, studyJson) =>
Ok(
Json.obj(
"study" -> studyJson,
"analysis" -> analysisJson
)
) as JSON
}
} map NoCache
}
private def analysisJson(us: UserStudy)(implicit ctx: Context): Fu[(JsObject, JsObject)] =
us match {
case UserStudy(_, _, chapters, WithChapter(study, chapter), _) =>
env.study.jsonView(study, chapters, chapter, ctx.me) map { studyJson =>
val initialFen = chapter.root.fen.some
val pov = userAnalysisC.makePov(initialFen, chapter.setup.variant)
val baseData = env.round.jsonView
.userAnalysisJson(
pov,
ctx.pref,
initialFen,
chapter.setup.orientation,
owner = false,
me = ctx.me
)
val analysis = baseData ++ Json.obj(
"treeParts" -> partitionTreeJsonWriter.writes {
lila.study.TreeBuilder(chapter.root, chapter.setup.variant)
},
"practiceGoal" -> lila.practice.PracticeGoal(chapter)
)
(analysis, studyJson)
}
}
def complete(chapterId: String, nbMoves: Int) =
Auth { implicit ctx => me =>
api.progress.setNbMoves(me, chapterId, lila.practice.PracticeProgress.NbMoves(nbMoves))
}
def reset =
AuthBody { _ => me =>
api.progress.reset(me) inject Redirect(routes.Practice.index())
}
def config =
Auth { implicit ctx => _ =>
for {
struct <- api.structure.get
form <- api.config.form
} yield Ok(html.practice.config(struct, form))
}
def configSave =
SecureBody(_.PracticeConfig) { implicit ctx => me =>
implicit val req = ctx.body
api.config.form.flatMap { form =>
FormFuResult(form) { err =>
api.structure.get map { html.practice.config(_, err) }
} { text =>
~api.config.set(text).toOption >>-
api.structure.clear() >>
env.mod.logApi.practiceConfig(me.id) inject Redirect(routes.Practice.config())
}
}
}
implicit private def makeStudyId(id: String): StudyModel.Id = StudyModel.Id(id)
implicit private def makeChapterId(id: String): Chapter.Id = Chapter.Id(id)
}