2016-02-26 05:08:11 -07:00
|
|
|
package lila.study
|
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
import chess.format.{ FEN, Uci }
|
2016-04-21 20:53:16 -06:00
|
|
|
import chess.Pos
|
2016-05-10 04:46:04 -06:00
|
|
|
import play.api.libs.json._
|
2020-04-29 08:00:34 -06:00
|
|
|
import scala.util.chaining._
|
2016-02-26 05:08:11 -07:00
|
|
|
|
2019-12-07 17:43:22 -07:00
|
|
|
import lila.common.Json._
|
2019-07-13 12:02:50 -06:00
|
|
|
import lila.socket.Socket.Sri
|
2016-11-26 06:59:27 -07:00
|
|
|
import lila.tree.Node.Shape
|
2016-05-13 06:14:38 -06:00
|
|
|
import lila.user.User
|
2016-02-26 05:08:11 -07:00
|
|
|
|
2016-05-19 12:39:19 -06:00
|
|
|
final class JsonView(
|
2016-05-26 14:01:43 -06:00
|
|
|
studyRepo: StudyRepo,
|
2019-12-03 17:55:45 -07:00
|
|
|
lightUserApi: lila.user.LightUserApi
|
2019-12-13 18:17:43 -07:00
|
|
|
)(implicit ec: scala.concurrent.ExecutionContext) {
|
2016-05-11 03:20:19 -06:00
|
|
|
|
|
|
|
import JsonView._
|
2016-04-20 01:04:38 -06:00
|
|
|
|
2016-05-19 12:39:19 -06:00
|
|
|
def apply(
|
2019-12-13 07:30:20 -07:00
|
|
|
study: Study,
|
|
|
|
chapters: List[Chapter.Metadata],
|
|
|
|
currentChapter: Chapter,
|
|
|
|
me: Option[User]
|
2017-02-14 08:34:07 -07:00
|
|
|
) = {
|
2016-10-12 07:37:40 -06:00
|
|
|
|
|
|
|
def allowed(selection: Settings.UserSelection): Boolean =
|
|
|
|
Settings.UserSelection.allows(selection, study, me.map(_.id))
|
|
|
|
|
2016-12-21 06:44:18 -07:00
|
|
|
me.?? { studyRepo.liked(study, _) } map { liked =>
|
2019-12-13 07:30:20 -07:00
|
|
|
studyWrites.writes(study) ++ Json
|
|
|
|
.obj(
|
|
|
|
"liked" -> liked,
|
2019-07-04 16:10:59 -06:00
|
|
|
"features" -> Json.obj(
|
2019-12-13 07:30:20 -07:00
|
|
|
"cloneable" -> allowed(study.settings.cloneable),
|
|
|
|
"chat" -> allowed(study.settings.chat),
|
|
|
|
"sticky" -> study.settings.sticky,
|
|
|
|
"description" -> study.settings.description
|
|
|
|
),
|
2020-02-21 12:27:22 -07:00
|
|
|
"topics" -> study.topicsOrEmpty,
|
2019-12-13 07:30:20 -07:00
|
|
|
"chapters" -> chapters.map(chapterMetadataWrites.writes),
|
|
|
|
"chapter" -> Json
|
|
|
|
.obj(
|
|
|
|
"id" -> currentChapter.id,
|
|
|
|
"ownerId" -> currentChapter.ownerId,
|
|
|
|
"setup" -> currentChapter.setup,
|
|
|
|
"tags" -> currentChapter.tags,
|
|
|
|
"features" -> Json.obj(
|
|
|
|
"computer" -> allowed(study.settings.computer),
|
|
|
|
"explorer" -> allowed(study.settings.explorer)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add("description", currentChapter.description)
|
|
|
|
.add("serverEval", currentChapter.serverEval)
|
|
|
|
.add("relay", currentChapter.relay)(relayWrites)
|
2020-04-29 08:00:34 -06:00
|
|
|
.pipe(addChapterMode(currentChapter))
|
2019-12-13 07:30:20 -07:00
|
|
|
)
|
|
|
|
.add("description", study.description)
|
2016-12-21 06:44:18 -07:00
|
|
|
}
|
2017-08-10 20:05:03 -06:00
|
|
|
}
|
2016-05-19 12:39:19 -06:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
def chapterConfig(c: Chapter) =
|
|
|
|
Json
|
|
|
|
.obj(
|
|
|
|
"id" -> c.id,
|
|
|
|
"name" -> c.name,
|
|
|
|
"orientation" -> c.setup.orientation
|
|
|
|
)
|
2020-04-29 08:00:34 -06:00
|
|
|
.add("description", c.description) pipe addChapterMode(c)
|
2017-08-15 14:28:16 -06:00
|
|
|
|
2020-05-05 22:11:15 -06:00
|
|
|
def pagerData(s: Study.WithChaptersAndLiked) =
|
|
|
|
Json.obj(
|
|
|
|
"id" -> s.study.id.value,
|
|
|
|
"name" -> s.study.name.value,
|
|
|
|
"liked" -> s.liked,
|
|
|
|
"likes" -> s.study.likes.value,
|
|
|
|
"updatedAt" -> s.study.updatedAt,
|
|
|
|
"owner" -> lightUserApi.sync(s.study.ownerId),
|
|
|
|
"chapters" -> s.chapters.take(4),
|
|
|
|
"members" -> s.study.members.members.values.take(4)
|
|
|
|
)
|
2018-04-16 07:59:58 -06:00
|
|
|
|
2017-08-15 14:28:16 -06:00
|
|
|
private def addChapterMode(c: Chapter)(js: JsObject): JsObject =
|
|
|
|
js.add("practice", c.isPractice)
|
|
|
|
.add("gamebook", c.isGamebook)
|
|
|
|
.add("conceal", c.conceal)
|
2016-05-31 05:16:07 -06:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val memberRoleWrites = Writes[StudyMember.Role] { r =>
|
2016-05-11 03:20:19 -06:00
|
|
|
JsString(r.id)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val memberWrites: Writes[StudyMember] = Writes[StudyMember] { m =>
|
2020-06-06 18:09:18 -06:00
|
|
|
Json.obj("user" -> lightUserApi.syncFallback(m.id), "role" -> m.role)
|
2016-05-11 03:20:19 -06:00
|
|
|
}
|
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val membersWrites: Writes[StudyMembers] = Writes[StudyMembers] { m =>
|
2016-05-11 03:20:19 -06:00
|
|
|
Json toJson m.members
|
|
|
|
}
|
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private val studyWrites = OWrites[Study] { s =>
|
|
|
|
Json
|
|
|
|
.obj(
|
|
|
|
"id" -> s.id,
|
|
|
|
"name" -> s.name,
|
|
|
|
"members" -> s.members,
|
|
|
|
"position" -> s.position,
|
|
|
|
"ownerId" -> s.ownerId,
|
|
|
|
"settings" -> s.settings,
|
|
|
|
"visibility" -> s.visibility,
|
|
|
|
"createdAt" -> s.createdAt,
|
|
|
|
"secondsSinceUpdate" -> (nowSeconds - s.updatedAt.getSeconds).toInt,
|
|
|
|
"from" -> s.from,
|
|
|
|
"likes" -> s.likes
|
|
|
|
)
|
|
|
|
.add("isNew" -> s.isNew)
|
2016-05-11 03:20:19 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object JsonView {
|
|
|
|
|
2016-06-13 05:29:00 -06:00
|
|
|
case class JsData(study: JsObject, analysis: JsObject)
|
2016-04-16 07:26:01 -06:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit val studyIdWrites: Writes[Study.Id] = stringIsoWriter(Study.idIso)
|
2017-01-20 06:14:47 -07:00
|
|
|
implicit val studyNameWrites: Writes[Study.Name] = stringIsoWriter(Study.nameIso)
|
2017-08-19 09:31:28 -06:00
|
|
|
implicit val studyIdNameWrites = OWrites[Study.IdName] { s =>
|
|
|
|
Json.obj("id" -> s._id, "name" -> s.name)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit val chapterIdWrites: Writes[Chapter.Id] = stringIsoWriter(Chapter.idIso)
|
2017-01-20 06:14:47 -07:00
|
|
|
implicit val chapterNameWrites: Writes[Chapter.Name] = stringIsoWriter(Chapter.nameIso)
|
2017-01-20 05:47:52 -07:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private val posReader: Reads[Pos] = Reads[Pos] { v =>
|
2020-09-21 03:31:16 -06:00
|
|
|
(v.asOpt[String] flatMap Pos.fromKey).fold[JsResult[Pos]](JsError(Nil))(JsSuccess(_))
|
2016-04-21 20:53:16 -06:00
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val pathWrites: Writes[Path] = Writes[Path] { p =>
|
2016-04-21 20:53:16 -06:00
|
|
|
JsString(p.toString)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val sriWriter: Writes[Sri] = Writes[Sri] { sri =>
|
2019-07-13 12:02:50 -06:00
|
|
|
JsString(sri.value)
|
2016-04-23 21:01:58 -06:00
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val visibilityWriter: Writes[Study.Visibility] = Writes[Study.Visibility] { v =>
|
2016-04-26 21:12:53 -06:00
|
|
|
JsString(v.key)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val fromWriter: Writes[Study.From] = Writes[Study.From] {
|
|
|
|
case Study.From.Scratch => JsString("scratch")
|
|
|
|
case Study.From.Game(id) => Json.obj("game" -> id)
|
2016-08-31 10:03:37 -06:00
|
|
|
case Study.From.Study(id) => Json.obj("study" -> id)
|
2017-10-04 20:45:54 -06:00
|
|
|
case Study.From.Relay(id) => Json.obj("relay" -> id)
|
2016-05-22 08:50:55 -06:00
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val userSelectionWriter = Writes[Settings.UserSelection] { v =>
|
2016-05-13 06:14:38 -06:00
|
|
|
JsString(v.key)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val settingsWriter: Writes[Settings] = Json.writes[Settings]
|
|
|
|
|
|
|
|
implicit private[study] val shapeReader: Reads[Shape] = Reads[Shape] { js =>
|
|
|
|
js.asOpt[JsObject]
|
|
|
|
.flatMap { o =>
|
|
|
|
for {
|
|
|
|
brush <- o str "brush"
|
|
|
|
orig <- o.get[Pos]("orig")
|
|
|
|
} yield o.get[Pos]("dest") match {
|
|
|
|
case Some(dest) => Shape.Arrow(brush, orig, dest)
|
|
|
|
case _ => Shape.Circle(brush, orig)
|
|
|
|
}
|
2016-04-21 20:53:16 -06:00
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
.fold[JsResult[Shape]](JsError(Nil))(JsSuccess(_))
|
2016-04-16 07:26:01 -06:00
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private val plyWrites = Writes[Chapter.Ply] { p =>
|
2016-05-18 08:15:02 -06:00
|
|
|
JsNumber(p.value)
|
|
|
|
}
|
2016-04-16 07:26:01 -06:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private val variantWrites = OWrites[chess.variant.Variant] { v =>
|
2016-05-22 04:54:20 -06:00
|
|
|
Json.obj("key" -> v.key, "name" -> v.name)
|
|
|
|
}
|
2016-12-21 11:18:38 -07:00
|
|
|
implicit val pgnTagWrites: Writes[chess.format.pgn.Tag] = Writes[chess.format.pgn.Tag] { t =>
|
2016-12-21 17:37:14 -07:00
|
|
|
Json.arr(t.name.toString, t.value)
|
2016-05-17 09:35:04 -06:00
|
|
|
}
|
2017-09-20 11:22:06 -06:00
|
|
|
implicit val pgnTagsWrites = Writes[chess.format.pgn.Tags] { tags =>
|
|
|
|
JsArray(tags.value map pgnTagWrites.writes)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private val chapterSetupWrites = Json.writes[Chapter.Setup]
|
2021-09-15 10:02:34 -06:00
|
|
|
|
|
|
|
implicit val chapterMetadataWrites = OWrites[Chapter.Metadata] { c =>
|
2021-03-20 13:14:14 -06:00
|
|
|
Json
|
|
|
|
.obj("id" -> c._id, "name" -> c.name)
|
|
|
|
.add("ongoing", c.looksOngoing)
|
|
|
|
.add("res" -> c.resultStr)
|
2016-04-24 03:15:18 -06:00
|
|
|
}
|
2016-04-20 01:04:38 -06:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val positionRefWrites: Writes[Position.Ref] = Json.writes[Position.Ref]
|
|
|
|
implicit private val likesWrites: Writes[Study.Likes] = Writes[Study.Likes] { p =>
|
2016-05-26 14:01:43 -06:00
|
|
|
JsNumber(p.value)
|
|
|
|
}
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val likingRefWrites: Writes[Study.Liking] = Json.writes[Study.Liking]
|
2017-10-05 17:22:29 -06:00
|
|
|
|
|
|
|
implicit val relayWrites = OWrites[Chapter.Relay] { r =>
|
2017-10-09 07:36:33 -06:00
|
|
|
Json.obj(
|
2019-12-13 07:30:20 -07:00
|
|
|
"path" -> r.path,
|
2017-10-09 07:36:33 -06:00
|
|
|
"secondsSinceLastMove" -> r.secondsSinceLastMove
|
|
|
|
)
|
2017-10-05 17:22:29 -06:00
|
|
|
}
|
2018-01-21 19:28:45 -07:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val serverEvalWrites: Writes[Chapter.ServerEval] = Json.writes[Chapter.ServerEval]
|
2019-10-23 09:31:31 -06:00
|
|
|
|
2019-12-13 07:30:20 -07:00
|
|
|
implicit private[study] val whoWriter: Writes[actorApi.Who] = Writes[actorApi.Who] { w =>
|
2019-11-08 15:50:39 -07:00
|
|
|
Json.obj("u" -> w.u, "s" -> w.sri)
|
|
|
|
}
|
2020-02-21 12:27:22 -07:00
|
|
|
|
2020-02-21 17:47:45 -07:00
|
|
|
implicit val topicWrites: Writes[StudyTopic] = stringIsoWriter(StudyTopic.topicIso)
|
|
|
|
implicit val topicsWrites: Writes[StudyTopics] = Writes[StudyTopics] { topics =>
|
2020-02-21 12:27:22 -07:00
|
|
|
JsArray(topics.value map topicWrites.writes)
|
|
|
|
}
|
2016-04-18 00:32:34 -06:00
|
|
|
}
|