notify users that their game analysis is complete.

This commit is contained in:
Gordon Martin 2016-06-03 22:05:10 +01:00
parent 95656880eb
commit 5a73edb131
9 changed files with 99 additions and 10 deletions

View file

@ -10,6 +10,7 @@ import lila.hub.actorApi.map.Tell
final class Analyser(
indexer: ActorSelection,
roundSocket: ActorSelection,
notifier: Notifier,
bus: lila.common.Bus) {
def get(id: String): Fu[Option[Analysis]] = AnalysisRepo byId id
@ -21,7 +22,7 @@ final class Analyser(
sendAnalysisProgress(analysis) >>- {
bus.publish(actorApi.AnalysisReady(game, analysis), 'analysisReady)
indexer ! InsertGame(game)
}
} >>- notifier.notifyAnalysisComplete(analysis, game)
}
}
@ -36,6 +37,8 @@ final class Analyser(
pgnMoves = game.pgnMoves,
variant = game.variant,
initialFen = initialFen | FEN(game.variant.initialFen)))
}
}
}

View file

@ -3,6 +3,7 @@ package lila.analyse
import akka.actor._
import akka.pattern.pipe
import com.typesafe.config.Config
import lila.notify.NotifyApi
import scala.util.{ Success, Failure }
import spray.caching.{ LruCache, Cache }
@ -13,7 +14,8 @@ final class Env(
db: lila.db.Env,
system: ActorSystem,
roundSocket: ActorSelection,
indexer: ActorSelection) {
indexer: ActorSelection,
notifyApi: NotifyApi) {
private val CollectionAnalysis = config getString "collection.analysis"
private val NetDomain = config getString "net.domain"
@ -23,12 +25,16 @@ final class Env(
private[analyse] lazy val analysisColl = db(CollectionAnalysis)
lazy val notifier = new Notifier(notifyApi)
lazy val analyser = new Analyser(
indexer = indexer,
roundSocket = roundSocket,
notifier = notifier,
bus = system.lilaBus)
lazy val annotator = new Annotator(NetDomain)
}
object Env {
@ -38,5 +44,6 @@ object Env {
db = lila.db.Env.current,
system = lila.common.PlayApp.system,
roundSocket = lila.hub.Env.current.socket.round,
indexer = lila.hub.Env.current.actor.gameSearch)
indexer = lila.hub.Env.current.actor.gameSearch,
notifyApi = lila.notify.Env.current.api)
}

View file

@ -0,0 +1,34 @@
package lila.analyse
import chess.Color
import lila.analyse.Analysis
import lila.common.LightUser
import lila.game.{Namer, Game}
import lila.notify.Notification.Notifies
import lila.notify.{Notification, AnalysisFinished, NotifyApi}
final class Notifier(notifyApi: NotifyApi) {
def notifyAnalysisComplete(analysis: Analysis, game: Game) = {
val notifies = Notifies(analysis.requestedBy)
val color = requestByColor(analysis, game)
val opponent = AnalysisFinished.OpponentName(opponentName(color, game))
val notifyContent = AnalysisFinished(AnalysisFinished.Id(analysis.id), color, opponent)
val notification = Notification(notifies, notifyContent)
notifyApi.addNotification(notification)
}
private def requestByColor(analysis: Analysis, game: Game) = {
if (game.blackPlayer.userId contains analysis.requestedBy) Color.black
else Color.white
}
implicit val lightUser : LightUser.Getter = lila.user.Env.current.lightUser
private def opponentName(color: Color, game: Game) = {
val player = game.pov(color).player
Namer.playerText(player)
}
}

View file

@ -1,5 +1,6 @@
package lila.notify
import chess.Color
import lila.db.BSON.{ Reader, Writer }
import lila.db.dsl._
import lila.db.{ dsl, BSON }
@ -46,6 +47,15 @@ private object BSONHandlers {
implicit val BlogTitleHandler = stringAnyValHandler[NewBlogPost.Title](_.value, NewBlogPost.Title.apply)
implicit val NewBlogPostHandler = Macros.handler[NewBlogPost]
implicit val ColourHandler = new BSON[Color] {
override def reads(reader: Reader): Color = Color(reader.str("color")) | Color.White
override def writes(writer: Writer, color: Color): dsl.Bdoc = $doc("color" -> color.name)
}
implicit val AnalysisIdHandler = stringAnyValHandler[AnalysisFinished.Id](_.value, AnalysisFinished.Id.apply)
implicit val AnalysisAgainstHandler = stringAnyValHandler[AnalysisFinished.OpponentName](_.value, AnalysisFinished.OpponentName.apply)
implicit val AnalysisFinishedHandler = Macros.handler[AnalysisFinished]
implicit val NotificationContentHandler = new BSON[NotificationContent] {
private def writeNotificationType(notificationContent: NotificationContent) = {
@ -56,6 +66,7 @@ private object BSONHandlers {
case _: QaAnswer => "qaAnswer"
case _: TeamJoined => "teamJoined"
case _: NewBlogPost => "newBlogPost"
case _: AnalysisFinished => "analysisFinished"
}
}
@ -76,6 +87,8 @@ private object BSONHandlers {
case t: TeamJoined => TeamJoinedHandler.write(t) ++ $doc("type" -> writeNotificationType(notificationContent))
case b: NewBlogPost =>
NewBlogPostHandler.write(b) ++ $doc("type" -> writeNotificationType(notificationContent))
case a: AnalysisFinished =>
AnalysisFinishedHandler.write(a) ++ $doc("type" -> writeNotificationType(notificationContent))
}
}
@ -98,12 +111,13 @@ private object BSONHandlers {
}
def reads(reader: Reader): NotificationContent = reader.str("type") match {
case "mention" => readMentionedNotification(reader)
case "invitedStudy" => readInvitedStudyNotification(reader)
case "privateMessage" => PrivateMessageHandler read reader.doc
case "qaAnswer" => QaAnswerHandler read reader.doc
case "teamJoined" => TeamJoinedHandler read reader.doc
case "newBlogPost" => NewBlogPostHandler read reader.doc
case "mention" => readMentionedNotification(reader)
case "invitedStudy" => readInvitedStudyNotification(reader)
case "privateMessage" => PrivateMessageHandler read reader.doc
case "qaAnswer" => QaAnswerHandler read reader.doc
case "teamJoined" => TeamJoinedHandler read reader.doc
case "newBlogPost" => NewBlogPostHandler read reader.doc
case "analysisFinished" => AnalysisFinishedHandler read reader.doc
}
def writes(writer: Writer, n: NotificationContent): dsl.Bdoc = {

View file

@ -35,6 +35,10 @@ final class JSONHandlers(
"id" -> id.value,
"slug" -> slug.value,
"title" -> title.value)
case AnalysisFinished(id, color, against) => Json.obj(
"id" -> id.value,
"color" -> color.name,
"opponentName" -> against.value)
}
}
@ -48,6 +52,7 @@ final class JSONHandlers(
case _: QaAnswer => "qaAnswer"
case _: TeamJoined => "teamJoined"
case _: NewBlogPost => "newBlogPost"
case _: AnalysisFinished => "analysisFinished"
}
Json.obj("content" -> writeBody(body),

View file

@ -1,5 +1,6 @@
package lila.notify
import chess.Color
import lila.common.paginator.Paginator
import lila.notify.MentionedInThread.PostId
import org.joda.time.DateTime
@ -96,3 +97,10 @@ object NewBlogPost {
case class Slug(value: String) extends AnyVal with StringValue
case class Title(value: String) extends AnyVal with StringValue
}
case class AnalysisFinished(id: AnalysisFinished.Id, playedAs: Color, opponentName: AnalysisFinished.OpponentName) extends NotificationContent
object AnalysisFinished {
case class Id(value: String) extends AnyVal with StringValue
case class OpponentName(value: String) extends AnyVal with StringValue
}

View file

@ -63,6 +63,7 @@ final class NotifyApi(
case QaAnswer(_, question, _) => repo.hasRecentQaAnswer(notification.notifies, question)
case _: TeamJoined => fuccess(false)
case _: NewBlogPost => fuccess(false)
case _: AnalysisFinished => fuccess(false)
}
}

View file

@ -181,7 +181,7 @@ object ApplicationBuild extends Build {
libraryDependencies ++= provided(play.api, RM, hasher)
)
lazy val analyse = project("analyse", Seq(common, hub, chess, game, user)).settings(
lazy val analyse = project("analyse", Seq(common, hub, chess, game, user, notifyModule)).settings(
libraryDependencies ++= provided(
play.api, RM, spray.caching)
)

View file

@ -128,6 +128,23 @@ var handlers = {
text: function(n) {
return n.content.title;
}
},
analysisFinished: {
html: function(notification) {
var content = notification.content
var url = "/" + content.id + "/" + content.color
return genericNotification(notification, url, 'A', [
m('span', [
m('strong', 'Analysis complete'),
drawTime(notification)
]),
m('span', 'Analysis of game against « ' + content.opponentName + ' » complete.')
]);
},
text: function(n) {
return 'Analysis of game against « ' + n.content.opponentName + ' » complete.';
}
}
};