diff --git a/app/views/account/pref.scala.html b/app/views/account/pref.scala.html index e95af0fd5a..a6d2782fe3 100644 --- a/app/views/account/pref.scala.html +++ b/app/views/account/pref.scala.html @@ -24,16 +24,25 @@

Show board highlights (last move and check)

@base.radios(form("highlight"), Seq(0 -> "No", 1 -> "Yes")) +
  • +

    Show board coordinates (A-H, 1-8)

    + @base.radios(form("coords"), Pref.Coords.choices) +
  • Show piece destinations (valid moves and premoves)

    @base.radios(form("destination"), Seq(0 -> "No", 1 -> "Yes"))
  • + + +
    + Chess clock + diff --git a/app/views/base/layout.scala.html b/app/views/base/layout.scala.html index bf95ef07ee..704e74e5f6 100644 --- a/app/views/base/layout.scala.html +++ b/app/views/base/layout.scala.html @@ -47,7 +47,8 @@ openGraph: Map[Symbol, String] = Map.empty)(body: Html)(implicit ctx: Context) ctx.currentPieceSet3d, ctx.pref.highlight ?? "highlight", ctx.blindMode ?? "blind_mode", - if (ctx.is3d) "is3d" else "is2d").mkString(" ")" + if (ctx.is3d) "is3d" else "is2d", + "coords_" + ctx.pref.coords).mkString(" ")" data-piece-set="@ctx.currentPieceSet" data-static-url="@staticUrl("")" data-sound-dir="@staticUrl("sound")" diff --git a/doc/mobile/play.md b/doc/mobile/play.md index ae99fa4416..50ded92676 100644 --- a/doc/mobile/play.md +++ b/doc/mobile/play.md @@ -193,7 +193,7 @@ Each event has a version number `v`, a type `t` and data `d`. "t": "premove", "d": null }, { - "v": 12, // game metadata has changed (could be rematch negociation, for instance) + "v": 12, // game metadata has changed (could be rematch negotiation, for instance) "t": "reloadTable", // fetch the game document for more info "d": null }, { @@ -209,12 +209,12 @@ Each event has a version number `v`, a type `t` and data `d`. {t: 'resign'} ``` -## Rematch negociation +## Rematch negotiation When the opponent proposes or declines a rematch, a `reloadTable` event is sent to the client. You should then fetch the game document to learn about -the rematch negociation state, in `opponent.isOfferingRematch`. +the rematch negotiation state, in `opponent.isOfferingRematch`. ### Propose or accept rematch diff --git a/modules/pref/src/main/DataForm.scala b/modules/pref/src/main/DataForm.scala index 804b54edd1..4e3aedca7d 100644 --- a/modules/pref/src/main/DataForm.scala +++ b/modules/pref/src/main/DataForm.scala @@ -16,6 +16,7 @@ private[pref] final class DataForm(api: PrefApi) { "follow" -> number.verifying(Set(0, 1) contains _), "highlight" -> number.verifying(Set(0, 1) contains _), "destination" -> number.verifying(Set(0, 1) contains _), + "coords" -> number.verifying(Pref.Coords.choices.toMap contains _), "challenge" -> number.verifying(Pref.Challenge.choices.toMap contains _), "premove" -> number.verifying(Set(0, 1) contains _), "animation" -> number.verifying(Set(0, 1, 2, 3) contains _), @@ -31,6 +32,7 @@ private[pref] final class DataForm(api: PrefApi) { follow: Int, highlight: Int, destination: Int, + coords: Int, challenge: Int, premove: Int, animation: Int, @@ -45,6 +47,7 @@ private[pref] final class DataForm(api: PrefApi) { follow = follow == 1, highlight = highlight == 1, destination = destination == 1, + coords = coords, challenge = challenge, premove = premove == 1, animation = animation, @@ -62,6 +65,7 @@ private[pref] final class DataForm(api: PrefApi) { follow = pref.follow.fold(1, 0), highlight = pref.highlight.fold(1, 0), destination = pref.destination.fold(1, 0), + coords = pref.coords, challenge = pref.challenge, premove = pref.premove.fold(1, 0), animation = pref.animation, diff --git a/modules/pref/src/main/Pref.scala b/modules/pref/src/main/Pref.scala index 660e040e20..5225cedc71 100644 --- a/modules/pref/src/main/Pref.scala +++ b/modules/pref/src/main/Pref.scala @@ -25,6 +25,7 @@ case class Pref( follow: Boolean, highlight: Boolean, destination: Boolean, + coords: Int, challenge: Int, coordColor: Int, puzzleDifficulty: Int, @@ -145,6 +146,17 @@ object Pref { SLOW -> "Slow") } + object Coords { + val NONE = 0 + val INSIDE = 1 + val OUTSIDE = 2 + + val choices = Seq( + NONE -> "Nope", + INSIDE -> "Inside the board", + OUTSIDE -> "Outside the board") + } + object Challenge { val NEVER = 1 val RATING = 2 @@ -189,6 +201,7 @@ object Pref { follow = true, highlight = true, destination = true, + coords = Coords.OUTSIDE, challenge = Challenge.RATING, coordColor = Color.RANDOM, puzzleDifficulty = Difficulty.NORMAL, diff --git a/modules/pref/src/main/PrefApi.scala b/modules/pref/src/main/PrefApi.scala index a6b6dde6e5..8bd94a0e44 100644 --- a/modules/pref/src/main/PrefApi.scala +++ b/modules/pref/src/main/PrefApi.scala @@ -39,13 +39,36 @@ final class PrefApi(coll: Coll, cacheTtl: Duration) { follow = r.getD("follow", Pref.default.follow), highlight = r.getD("highlight", Pref.default.highlight), destination = r.getD("destination", Pref.default.destination), + coords = r.getD("coords", Pref.default.coords), challenge = r.getD("challenge", Pref.default.challenge), coordColor = r.getD("coordColor", Pref.default.coordColor), puzzleDifficulty = r.getD("puzzleDifficulty", Pref.default.puzzleDifficulty), tags = r.getD("tags", Pref.default.tags)) - private val writer = Macros.writer[Pref] - def writes(w: BSON.Writer, o: Pref) = writer write o + def writes(w: BSON.Writer, o: Pref) = BSONDocument( + "_id" -> o._id, + "dark" -> o.dark, + "is3d" -> o.is3d, + "theme" -> o.theme, + "pieceSet" -> o.pieceSet, + "theme3d" -> o.theme3d, + "pieceSet3d" -> o.pieceSet3d, + "autoQueen" -> o.autoQueen, + "autoThreefold" -> o.autoThreefold, + "takeback" -> o.takeback, + "clockTenths" -> o.clockTenths, + "clockBar" -> o.clockBar, + "premove" -> o.premove, + "animation" -> o.animation, + "captured" -> o.captured, + "follow" -> o.follow, + "highlight" -> o.highlight, + "destination" -> o.destination, + "coords" -> o.coords, + "challenge" -> o.challenge, + "coordColor" -> o.coordColor, + "puzzleDifficulty" -> o.puzzleDifficulty, + "tags" -> o.tags) } def saveTag(user: User, name: String, value: String) = diff --git a/modules/round/src/main/JsonView.scala b/modules/round/src/main/JsonView.scala index 6045f78851..d9b9d258ea 100644 --- a/modules/round/src/main/JsonView.scala +++ b/modules/round/src/main/JsonView.scala @@ -84,6 +84,7 @@ final class JsonView( "animationDuration" -> animationDuration(pov, pref), "highlight" -> pref.highlight, "destination" -> pref.destination, + "coords" -> pref.coords, "autoQueen" -> pref.autoQueen, "clockTenths" -> pref.clockTenths, "clockBar" -> pref.clockBar, @@ -155,6 +156,7 @@ final class JsonView( "pref" -> Json.obj( "animationDelay" -> animationDuration(pov, pref), "highlight" -> pref.highlight, + "coords" -> pref.coords, "clockTenths" -> pref.clockTenths, "clockBar" -> pref.clockBar, "showCaptured" -> pref.captured diff --git a/public/javascripts/common.js b/public/javascripts/common.js index c1f037da3f..1b00c21a64 100644 --- a/public/javascripts/common.js +++ b/public/javascripts/common.js @@ -9,6 +9,7 @@ function parseFen($elem) { var color = $this.data('color'); var ground = $this.data('chessground'); var config = { + coordinates: false, viewOnly: true, fen: $this.data('fen'), lastMove: lm ? [lm[0] + lm[1], lm[2] + lm[3]] : [], diff --git a/public/stylesheets/board.css b/public/stylesheets/board.css index 2856f58cfe..953e28fec4 100644 --- a/public/stylesheets/board.css +++ b/public/stylesheets/board.css @@ -1106,13 +1106,13 @@ div.control .rematch.disabled { } #claim_draw_zone, div.force_resign_zone, -div.negociation { +div.negotiation { margin-top: 10px; padding-top: 10px; border-top: 1px solid #ddd; } #claim_draw_zone .button, -div.negociation .button, +div.negotiation .button, div.force_resign_zone .button { display: inline-block; } diff --git a/public/stylesheets/chessground.css b/public/stylesheets/chessground.css index a337de3880..9dcd77f68e 100644 --- a/public/stylesheets/chessground.css +++ b/public/stylesheets/chessground.css @@ -41,8 +41,6 @@ body.is3d .cg-board { position: absolute; font-size: 11px; line-height: 11px; - color: #fff; - text-shadow: 0 1px 2px #000; opacity: 0.7; text-transform: uppercase; } @@ -56,6 +54,32 @@ body.is3d .cg-board { right: 1px; top: 1px; } +body.coords_1 .cg-square[data-coord-x]::after { + color: #fff; + text-shadow: 0 1px 2px #000; +} +body.coords_1 .cg-square[data-coord-y]::before { + color: #fff; + text-shadow: 0 1px 2px #000; +} +body.coords_2 .cg-square[data-coord-x]::after { + bottom: -11px; + left: 29px; + color: #bbb; + font-weight: bold; +} +body.coords_2.is3d .cg-square[data-coord-x]::after { + bottom: -22px; +} +body.coords_2 .cg-square[data-coord-y]::before { + right: -8px; + top: 26px; + color: #bbb; + font-weight: bold; +} +body.coords_2.is3d .cg-square[data-coord-y]::before { + top: 24px; +} .cg-square.move-dest { background: radial-gradient(rgba(20, 85, 30, 0.3) 22%, #208530 0, rgba(0, 0, 0, 0.3) 0, rgba(0, 0, 0, 0) 0); cursor: pointer; diff --git a/public/stylesheets/dark.css b/public/stylesheets/dark.css index 0ab91c215c..32df548e27 100644 --- a/public/stylesheets/dark.css +++ b/public/stylesheets/dark.css @@ -125,7 +125,7 @@ body.dark #hooks_list .pool_buttons > a, body.dark #hooks_list .pool_title, body.dark div.training div.box, body.dark div.force_resign_zone, -body.dark div.negociation { +body.dark div.negotiation { border-color: #3d3d3d; } body.dark #crosstable td.last { @@ -163,6 +163,8 @@ body.dark #tv_history a.user_link, body.dark #timeline a.user_link, body.dark #team .forum a.user_link, body.dark span.board_mark, +body.dark.coords_2 .cg-square[data-coord-x]::after, +body.dark.coords_2 .cg-square[data-coord-y]::before, body.dark div.user_show div.content_box_top > span, body.dark span.progress > .zero, body.dark div.undertable_top span.title { diff --git a/ui/round/package.json b/ui/round/package.json index 35dd8caf7e..879e281718 100644 --- a/ui/round/package.json +++ b/ui/round/package.json @@ -30,7 +30,7 @@ "watchify": "^1.0.2" }, "dependencies": { - "chessground": "^1.5.6", + "chessground": "^1.5.7", "lodash-node": "^2.4.1", "mithril": "^0.1.22" } diff --git a/ui/round/src/ground.js b/ui/round/src/ground.js index 37e801bd61..5b33017c9f 100644 --- a/ui/round/src/ground.js +++ b/ui/round/src/ground.js @@ -9,6 +9,7 @@ function makeConfig(data, fen) { turnColor: data.game.player, lastMove: util.str2move(data.game.lastMove), check: data.game.check, + coordinates: data.pref.coords !== 0, highlight: { lastMove: data.pref.highlight, check: data.pref.highlight, diff --git a/ui/round/src/view/table.js b/ui/round/src/view/table.js index 196eb373d0..493b15c90b 100644 --- a/ui/round/src/view/table.js +++ b/ui/round/src/view/table.js @@ -152,13 +152,13 @@ function renderTablePlay(ctrl) { onclick: partial(ctrl.socket.send, 'draw-claim', null) }, ctrl.trans('claimADraw')) ]) : ( - d.player.isOfferingDraw ? m('div.negociation', [ + d.player.isOfferingDraw ? m('div.negotiation', [ ctrl.trans('drawOfferSent') + ' ', m('a', { onclick: partial(ctrl.socket.send, 'draw-no', null) }, ctrl.trans('cancel')) ]) : null, - d.opponent.isOfferingDraw ? m('div.negociation', [ + d.opponent.isOfferingDraw ? m('div.negotiation', [ ctrl.trans('yourOpponentOffersADraw'), m('br'), m('a.button[data-icon=E]', { @@ -170,13 +170,13 @@ function renderTablePlay(ctrl) { }, ctrl.trans('decline')), ]) : null ), - d.player.isProposingTakeback ? m('div.negociation', [ + d.player.isProposingTakeback ? m('div.negotiation', [ ctrl.trans('takebackPropositionSent') + ' ', m('a', { onclick: partial(ctrl.socket.send, 'takeback-no', null) }, ctrl.trans('cancel')) ]) : null, - d.opponent.isProposingTakeback ? m('div.negociation', [ + d.opponent.isProposingTakeback ? m('div.negotiation', [ ctrl.trans('yourOpponentProposesATakeback'), m('br'), m('a.button[data-icon=E]', {