lila/modules/game/src/main/Event.scala

251 lines
6.6 KiB
Scala
Raw Normal View History

2013-03-22 11:53:13 -06:00
package lila.game
2012-05-14 14:36:32 -06:00
import lila.common.PimpedJson._
2012-05-14 14:36:32 -06:00
import play.api.libs.json._
2015-06-16 04:09:36 -06:00
import chess.Pos
2013-05-24 11:04:49 -06:00
import chess.Pos.{ piotr, allPiotrs }
import chess.{ PromotableRole, Pos, Color, Situation, Move => ChessMove, Clock => ChessClock, Status }
import lila.chat.{ Line, UserLine, PlayerLine }
2012-05-14 14:36:32 -06:00
sealed trait Event {
def typ: String
def data: JsValue
def only: Option[Color] = None
def owner: Boolean = false
def watcher: Boolean = false
def troll: Boolean = false
2012-05-14 14:36:32 -06:00
}
object Event {
sealed trait Empty extends Event {
def data = JsNull
}
2013-03-30 15:30:47 -06:00
object Start extends Empty {
2012-05-14 14:36:32 -06:00
def typ = "start"
}
2015-04-27 14:36:43 -06:00
case class Move(
orig: Pos,
dest: Pos,
color: Color,
san: String,
fen: String,
check: Boolean,
threefold: Boolean,
promotion: Option[Promotion],
enpassant: Option[Enpassant],
2015-06-15 17:56:27 -06:00
castle: Option[Castling],
2015-06-15 18:09:38 -06:00
state: State,
2015-06-16 04:09:36 -06:00
clock: Option[Event],
possibleMoves: Map[Pos, List[Pos]]) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "move"
2013-04-01 21:43:01 -06:00
def data = Json.obj(
2015-04-28 10:14:14 -06:00
// legacy data
2013-04-01 21:43:01 -06:00
"from" -> orig.key,
"to" -> dest.key,
"color" -> color.name,
2015-04-28 10:14:14 -06:00
// new data
"uci" -> s"${orig.key}${dest.key}",
2015-04-27 14:36:43 -06:00
"san" -> san,
"fen" -> fen,
"check" -> check.option(true),
"threefold" -> threefold.option(true),
"promotion" -> promotion.map(_.data),
"enpassant" -> enpassant.map(_.data),
2015-06-15 17:56:27 -06:00
"castle" -> castle.map(_.data),
"ply" -> state.turns,
"status" -> state.status.map { s =>
Json.obj("id" -> s.id, "name" -> s.name)
},
"wDraw" -> state.whiteOffersDraw.option(true),
2015-06-15 18:09:38 -06:00
"bDraw" -> state.blackOffersDraw.option(true),
2015-06-16 04:09:36 -06:00
"clock" -> clock.map(_.data),
"dests" -> PossibleMoves.json(possibleMoves)
2015-04-27 14:36:43 -06:00
).noNull
2012-05-14 14:36:32 -06:00
}
object Move {
2015-06-16 04:09:36 -06:00
def apply(move: ChessMove, situation: Situation, state: State, clock: Option[Event]): Move = Move(
orig = move.orig,
dest = move.dest,
color = move.piece.color,
san = chess.format.pgn.Dumper(move),
fen = chess.format.Forsyth.exportBoard(situation.board),
check = situation.check,
threefold = situation.threefoldRepetition,
promotion = move.promotion.map { Promotion(_, move.dest) },
enpassant = (move.capture ifTrue move.enpassant).map {
Event.Enpassant(_, !move.color)
},
castle = move.castle.map {
case (king, rook) => Castling(king, rook, move.color)
},
state = state,
clock = clock,
possibleMoves = situation.destinations)
2012-05-14 14:36:32 -06:00
}
case class PossibleMoves(
color: Color,
moves: Map[Pos, List[Pos]]) extends Event {
2014-05-10 04:39:38 -06:00
def typ = "possibleMoves"
2015-06-16 04:09:36 -06:00
def data = PossibleMoves json moves
2012-05-14 14:36:32 -06:00
override def only = Some(color)
}
2015-06-16 04:09:36 -06:00
object PossibleMoves {
def json(moves: Map[Pos, List[Pos]]) =
if (moves.isEmpty) JsNull
else moves.foldLeft(JsObject(Nil)) {
case (res, (o, d)) => res + (o.key, JsString(d map (_.key) mkString))
}
}
2015-01-11 16:56:03 -07:00
case class Enpassant(pos: Pos, color: Color) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "enpassant"
2015-01-11 16:56:03 -07:00
def data = Json.obj(
"key" -> pos.key,
"color" -> color.name)
2012-05-14 14:36:32 -06:00
}
case class Castling(king: (Pos, Pos), rook: (Pos, Pos), color: Color) extends Event {
def typ = "castling"
2013-04-01 21:43:01 -06:00
def data = Json.obj(
"king" -> Json.arr(king._1.key, king._2.key),
"rook" -> Json.arr(rook._1.key, rook._2.key),
"color" -> color.name
)
2012-05-14 14:36:32 -06:00
}
case class RedirectOwner(
color: Color,
2014-08-13 16:14:03 -06:00
id: String,
cookie: Option[JsObject]) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "redirect"
def data = Json.obj(
2014-08-13 16:14:03 -06:00
"id" -> id,
"url" -> s"/$id",
"cookie" -> cookie
).noNull
2012-05-14 14:36:32 -06:00
override def only = Some(color)
override def owner = true
}
case class Promotion(role: PromotableRole, pos: Pos) extends Event {
def typ = "promotion"
2013-04-01 21:43:01 -06:00
def data = Json.obj(
"key" -> pos.key,
"pieceClass" -> role.toString.toLowerCase
)
2012-05-14 14:36:32 -06:00
}
2014-01-31 18:02:32 -07:00
case class PlayerMessage(line: PlayerLine) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "message"
2014-01-31 18:02:32 -07:00
def data = Line toJson line
2012-05-14 14:36:32 -06:00
override def owner = true
2014-01-31 18:02:32 -07:00
override def troll = false
2012-05-14 14:36:32 -06:00
}
2014-01-31 18:02:32 -07:00
case class UserMessage(line: UserLine, w: Boolean) extends Event {
def typ = "message"
2014-01-31 18:02:32 -07:00
def data = Line toJson line
override def troll = line.troll
override def watcher = w
2014-02-19 11:52:22 -07:00
override def owner = !w
}
2015-06-16 03:33:49 -06:00
case class End(winner: Option[Color]) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "end"
2015-06-16 03:33:49 -06:00
def data = winner.map(_.name).fold[JsValue](JsNull)(JsString.apply)
2012-05-14 14:36:32 -06:00
}
2014-10-03 02:10:12 -06:00
case object Reload extends Empty {
def typ = "reload"
}
case object ReloadOwner extends Empty {
def typ = "reload"
override def owner = true
}
2012-05-14 14:36:32 -06:00
case class Premove(color: Color) extends Empty {
def typ = "premove"
override def only = Some(color)
override def owner = true
2012-05-14 14:36:32 -06:00
}
case class Clock(white: Float, black: Float) extends Event {
def typ = "clock"
2013-04-01 21:43:01 -06:00
def data = Json.obj(
"white" -> white,
"black" -> black
)
2012-05-14 14:36:32 -06:00
}
object Clock {
def apply(clock: ChessClock): Clock = Clock(
clock remainingTime Color.White,
clock remainingTime Color.Black)
2015-06-26 04:25:29 -06:00
def tenths(white: Int, black: Int): Clock = Clock(white.toFloat / 10, black.toFloat / 10)
2012-05-14 14:36:32 -06:00
}
2014-11-30 03:22:23 -07:00
case class CorrespondenceClock(white: Float, black: Float) extends Event {
def typ = "cclock"
def data = Json.obj("white" -> white, "black" -> black)
}
object CorrespondenceClock {
def apply(clock: lila.game.CorrespondenceClock): CorrespondenceClock =
CorrespondenceClock(clock.whiteTime, clock.blackTime)
}
2014-07-31 13:06:22 -06:00
case class CheckCount(white: Int, black: Int) extends Event {
def typ = "checkCount"
def data = Json.obj(
"white" -> white,
"black" -> black
)
}
case class State(
color: Color,
turns: Int,
status: Option[Status],
whiteOffersDraw: Boolean,
blackOffersDraw: Boolean) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "state"
2013-04-01 21:43:01 -06:00
def data = Json.obj(
"color" -> color.name,
"turns" -> turns,
"status" -> status.map { s =>
Json.obj(
"id" -> s.id,
"name" -> s.name)
},
"wDraw" -> whiteOffersDraw.option(true),
"bDraw" -> blackOffersDraw.option(true)
).noNull
2012-05-14 14:36:32 -06:00
}
case class TakebackOffers(
white: Boolean,
black: Boolean) extends Event {
def typ = "takebackOffers"
def data = Json.obj(
"white" -> white.option(true),
"black" -> black.option(true)
).noNull
override def owner = true
}
2012-05-14 14:36:32 -06:00
case class Crowd(
white: Boolean,
black: Boolean,
2012-06-10 15:37:11 -06:00
watchers: List[String]) extends Event {
2012-05-14 14:36:32 -06:00
def typ = "crowd"
2013-04-01 21:43:01 -06:00
def data = Json.obj(
"white" -> white,
"black" -> black,
2013-05-10 07:32:45 -06:00
"watchers" -> watchers)
2012-05-14 14:36:32 -06:00
}
}