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 =>
|
2016-04-20 02:03:42 -06:00
|
|
|
(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
|
|
|
}
|
|
|
|
|
2016-04-20 02:03:42 -06: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)))
|
2016-04-19 22:33:59 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-20 02:03:42 -06:00
|
|
|
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-19 22:33:59 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|