lila/modules/study/src/main/StudyApi.scala

141 lines
4.5 KiB
Scala
Raw Normal View History

2016-02-26 05:08:11 -07:00
package lila.study
2016-02-27 04:30:38 -07:00
import akka.actor.ActorRef
2016-02-26 05:08:11 -07:00
2016-04-16 07:26:01 -06:00
import chess.format.{ Forsyth, FEN }
2016-02-26 05:08:11 -07:00
import lila.hub.actorApi.map.Tell
2016-02-27 04:30:38 -07:00
import lila.hub.Sequencer
2016-04-20 22:42:49 -06:00
import lila.user.{ User, UserRepo }
2016-02-26 05:08:11 -07:00
final class StudyApi(
repo: StudyRepo,
2016-02-27 04:30:38 -07:00
sequencers: ActorRef,
2016-02-26 05:08:11 -07:00
socketHub: akka.actor.ActorRef) {
def byId = repo byId _
2016-02-27 04:30:38 -07:00
2016-04-16 07:26:01 -06:00
def create(user: User): Fu[Study] = {
val study = Study.make(
2016-04-20 02:51:08 -06:00
user = user.light,
2016-04-16 07:26:01 -06:00
setup = Chapter.Setup(
gameId = none,
variant = chess.variant.Standard,
orientation = chess.White))
repo insert study inject study
}
2016-02-27 04:30:38 -07:00
def locationByRef(ref: Location.Ref): Fu[Option[Location]] =
byId(ref.studyId) map (_ flatMap (_ location ref.chapterId))
def locationById(id: Location.Ref.ID): Fu[Option[Location]] =
(Location.Ref parseId id) ?? locationByRef
2016-04-20 22:42:49 -06:00
def setMemberPosition(userId: User.ID, ref: Location.Ref, path: Path) = sequenceLocation(ref) { location =>
(location.study canWrite userId) ?? {
repo.setMemberPosition(userId, ref, path) >>-
sendTo(ref.studyId, Socket.MemberPosition(userId, Position.Ref(ref.chapterId, path)))
}
}
2016-02-27 04:30:38 -07:00
2016-04-18 04:51:48 -06:00
def addNode(ref: Location.Ref, path: Path, node: Node) = sequenceLocation(ref) { location =>
(location.study canWrite node.by) ?? {
val newChapter = location.chapter.updateRoot { root =>
root.withChildren(_.addNodeAt(node, path))
}
repo.setChapter(location withChapter newChapter) >>
repo.setMemberPosition(node.by, ref, path + node) >>-
sendTo(ref.studyId, Socket.AddNode(Position.Ref(ref.chapterId, path), node))
2016-04-18 04:51:48 -06:00
}
2016-02-28 17:28:35 -07:00
}
def deleteNodeAt(userId: User.ID, ref: Location.Ref, path: Path) = sequenceLocation(ref) { location =>
(location.study canWrite userId) ?? {
val newChapter = location.chapter.updateRoot { root =>
root.withChildren(_.deleteNodeAt(path))
}
repo.setChapter(location withChapter newChapter) >>-
sendTo(ref.studyId, Socket.DelNode(Position.Ref(ref.chapterId, path)))
}
}
def promoteNodeAt(userId: User.ID, ref: Location.Ref, path: Path) = sequenceLocation(ref) { location =>
(location.study canWrite userId) ?? {
val newChapter = location.chapter.updateRoot { root =>
root.withChildren(_.promoteNodeAt(path))
}
repo.setChapter(location withChapter newChapter)
}
}
2016-04-20 04:19:34 -06:00
def setRole(studyId: Study.ID, byUserId: User.ID, userId: User.ID, roleStr: String) = sequenceStudy(studyId) { study =>
2016-04-20 22:42:49 -06:00
val role = StudyMember.Role.byId.getOrElse(roleStr, StudyMember.Role.Read)
repo.setRole(study, userId, role) >>- reloadMembers(study)
2016-04-20 04:19:34 -06:00
}
2016-04-20 22:42:49 -06:00
def invite(studyId: Study.ID, byUserId: User.ID, username: String) = sequenceStudy(studyId) { study =>
UserRepo.named(username).flatMap {
_.filterNot(study.members.contains) ?? { user =>
repo.addMember(study, StudyMember.make(study, user))
}
} >>- reloadMembers(study)
}
def kick(studyId: Study.ID, byUserId: User.ID, userId: User.ID) = sequenceStudy(studyId) { study =>
study.members.contains(userId) ?? {
repo.removeMember(study, userId)
} >>- reloadMembers(study)
}
2016-04-21 20:53:16 -06:00
def setShapes(studyId: Study.ID, userId: User.ID, shapes: List[Shape]) = sequenceStudy(studyId) { study =>
(study canWrite userId) ?? {
repo.setShapes(study, userId, shapes)
2016-04-21 21:05:43 -06:00
} >>- reloadMemberShapes(study, userId)
2016-04-21 20:53:16 -06:00
}
2016-04-20 22:42:49 -06:00
private def reloadMembers(study: Study) =
repo.membersById(study.id).foreach {
_ foreach { members =>
sendTo(study.id, Socket.ReloadMembers(members))
}
}
2016-04-21 21:05:43 -06:00
private def reloadMemberShapes(study: Study, userId: User.ID) =
repo.memberShapes(study.id, userId).foreach { shapes =>
sendTo(study.id, Socket.ReloadMemberShapes(userId, shapes))
}
2016-02-27 04:30:38 -07:00
private def sequenceRef(refId: Location.Ref.ID)(f: Location.Ref => Funit): Funit =
Location.Ref.parseId(refId) ?? { ref =>
sequence(ref.studyId) {
f(ref)
}
}
2016-04-18 04:51:48 -06:00
private def sequenceLocation(ref: Location.Ref)(f: Location => Funit): Funit =
locationByRef(ref) flatMap {
_ ?? { location =>
sequence(ref.studyId) {
f(location)
}
}
}
2016-04-20 04:19:34 -06:00
private def sequenceStudy(studyId: String)(f: Study => Funit): Funit =
byId(studyId) flatMap {
_ ?? { study =>
sequence(studyId)(f(study))
}
}
2016-02-27 04:30:38 -07:00
private def sequence(studyId: String)(f: => Funit): Funit = {
val promise = scala.concurrent.Promise[Unit]
val work = Sequencer.work(f, promise.some)
sequencers ! Tell(studyId, work)
promise.future
}
2016-04-20 01:04:38 -06:00
private def sendTo(studyId: String, msg: Any) {
socketHub ! Tell(studyId, msg)
}
2016-02-26 05:08:11 -07:00
}