From a52ac0d8ec1813d480d658d50e35f84747c2f952 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 5 Jan 2013 17:00:47 +0100 Subject: [PATCH] chess960 and rated tournaments --- app/setup/SetupHelper.scala | 4 +- app/templating/StringHelper.scala | 2 - app/tournament/DataForm.scala | 15 +++++-- app/tournament/GameJoiner.scala | 7 ++- app/tournament/Tournament.scala | 27 +++++++++--- app/tournament/TournamentApi.scala | 15 +++---- app/views/tournament/createdTable.scala.html | 8 ++++ app/views/tournament/faq.scala.html | 2 +- app/views/tournament/form.scala.html | 16 +++++++ app/views/tournament/homeInner.scala.html | 45 ++++++++++++++------ app/views/tournament/infoBox.scala.html | 11 ++--- public/stylesheets/tournament.css | 3 ++ 12 files changed, 110 insertions(+), 45 deletions(-) diff --git a/app/setup/SetupHelper.scala b/app/setup/SetupHelper.scala index 011c553e8b..7b48a45337 100644 --- a/app/setup/SetupHelper.scala +++ b/app/setup/SetupHelper.scala @@ -15,11 +15,11 @@ trait SetupHelper { self: I18nHelper ⇒ def translatedVariantChoices(implicit ctx: Context) = List( Variant.Standard.id.toString -> trans.standard.str(), - Variant.Chess960.id.toString -> StringHelper.ucFirst(Variant.Chess960.name) + Variant.Chess960.id.toString -> Variant.Chess960.name.capitalize ) def translatedSpeedChoices(implicit ctx: Context) = Speed.all map { s ⇒ - s.id.toString -> (s.toString + " - " + StringHelper.ucFirst(s.name)) + s.id.toString -> (s.toString + " - " + s.name.capitalize) } def eloDiffChoices(elo: Int)(implicit ctx: Context) = FilterConfig.eloDiffs map { diff ⇒ diff --git a/app/templating/StringHelper.scala b/app/templating/StringHelper.scala index df727967dc..24b2c0a6bf 100644 --- a/app/templating/StringHelper.scala +++ b/app/templating/StringHelper.scala @@ -11,8 +11,6 @@ object StringHelper extends StringHelper trait StringHelper { - def ucFirst(str: String) = ~(str lift 0).map(_.toUpper) + (str drop 1) - def slugify(input: String) = { val nowhitespace = input.trim.replace(" ", "-") val normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD) diff --git a/app/tournament/DataForm.scala b/app/tournament/DataForm.scala index 9617671348..814c1d2855 100644 --- a/app/tournament/DataForm.scala +++ b/app/tournament/DataForm.scala @@ -1,6 +1,9 @@ package lila package tournament +import chess.{ Mode, Variant } +import lila.setup.Mappings + import play.api.data._ import play.api.data.Forms._ import play.api.data.validation.Constraints._ @@ -35,7 +38,9 @@ final class DataForm(isDev: Boolean) { "clockTime" -> numberIn(clockTimeChoices), "clockIncrement" -> numberIn(clockIncrementChoices), "minutes" -> numberIn(minuteChoices), - "minPlayers" -> numberIn(minPlayerChoices) + "minPlayers" -> numberIn(minPlayerChoices), + "variant" -> Mappings.variant, + "mode" -> Mappings.mode(true) )(TournamentSetup.apply)(TournamentSetup.unapply) .verifying("Invalid clock", _.validClock) .verifying("Increase tournament duration, or decrease game clock", _.validTiming) @@ -43,14 +48,18 @@ final class DataForm(isDev: Boolean) { clockTime = clockTimeDefault, clockIncrement = clockIncrementDefault, minutes = minuteDefault, - minPlayers = minPlayerDefault) + minPlayers = minPlayerDefault, + variant = Variant.Standard.id, + mode = Mode.Casual.id.some) } private[tournament] case class TournamentSetup( clockTime: Int, clockIncrement: Int, minutes: Int, - minPlayers: Int) { + minPlayers: Int, + variant: Int, + mode: Option[Int]) { def validClock = (clockTime + clockIncrement) > 0 diff --git a/app/tournament/GameJoiner.scala b/app/tournament/GameJoiner.scala index d4e33274c1..5e26d455f0 100644 --- a/app/tournament/GameJoiner.scala +++ b/app/tournament/GameJoiner.scala @@ -22,18 +22,17 @@ final class GameJoiner( def apply(tour: Started)(pairing: Pairing): IO[DbGame] = for { user1 ← getUser(pairing.user1) map (_ err "No such user " + pairing) user2 ← getUser(pairing.user2) map (_ err "No such user " + pairing) - variant = chess.Variant.Standard game = DbGame( game = chess.Game( - board = chess.Board init variant, + board = chess.Board init tour.variant, clock = tour.clock.chessClock.some ), ai = None, whitePlayer = DbPlayer.white withUser user1, blackPlayer = DbPlayer.black withUser user2, creatorColor = chess.Color.White, - mode = chess.Mode.Casual, - variant = variant + mode = tour.mode, + variant = tour.variant ).withTournamentId(tour.id) .withId(pairing.gameId) .start diff --git a/app/tournament/Tournament.scala b/app/tournament/Tournament.scala index aa2bb34720..bb48b3e6e5 100644 --- a/app/tournament/Tournament.scala +++ b/app/tournament/Tournament.scala @@ -8,6 +8,7 @@ import com.mongodb.casbah.query.Imports.DBObject import ornicar.scalalib.Random import scalaz.NonEmptyList +import chess.{ Variant, Mode } import user.User import game.PovRef @@ -16,6 +17,8 @@ case class Data( clock: TournamentClock, minutes: Int, minPlayers: Int, + variant: Variant, + mode: Mode, createdAt: DateTime, createdBy: String) @@ -40,6 +43,10 @@ sealed trait Tournament { def minutes = data.minutes lazy val duration = new Duration(minutes * 60 * 1000) + def variant = data.variant + def mode = data.mode + def rated = mode.rated + def userIds = players map (_.id) def activeUserIds = players filter (_.active) map (_.id) def nbActiveUsers = players count (_.active) @@ -79,6 +86,8 @@ sealed trait StartedOrFinished extends Tournament { clock = data.clock, minutes = data.minutes, minPlayers = data.minPlayers, + variant = data.variant.id, + mode = data.mode.id, createdAt = data.createdAt, createdBy = data.createdBy, startedAt = startedAt.some, @@ -112,6 +121,8 @@ case class Created( status = Status.Created.id, name = data.name, clock = data.clock, + variant = data.variant.id, + mode = data.mode.id, minutes = data.minutes, minPlayers = data.minPlayers, createdAt = data.createdAt, @@ -214,11 +225,13 @@ case class RawTournament( status: Int, startedAt: Option[DateTime] = None, players: List[Player] = Nil, - pairings: List[RawPairing] = Nil) { + pairings: List[RawPairing] = Nil, + variant: Int = Variant.Standard.id, + mode: Int = Mode.Casual.id) { def created: Option[Created] = (status == Status.Created.id) option Created( id = id, - data = Data(name, clock, minutes, minPlayers, createdAt, createdBy), + data = Data(name, clock, minutes, minPlayers, Variant orDefault variant, Mode orDefault mode, createdAt, createdBy), players = players) def started: Option[Started] = for { @@ -226,7 +239,7 @@ case class RawTournament( if status == Status.Started.id } yield Started( id = id, - data = Data(name, clock, minutes, minPlayers, createdAt, createdBy), + data = Data(name, clock, minutes, minPlayers, Variant orDefault variant, Mode orDefault mode, createdAt, createdBy), startedAt = stAt, players = players, pairings = decodePairings) @@ -236,7 +249,7 @@ case class RawTournament( if status == Status.Finished.id } yield Finished( id = id, - data = Data(name, clock, minutes, minPlayers, createdAt, createdBy), + data = Data(name, clock, minutes, minPlayers, Variant orDefault variant, Mode orDefault mode, createdAt, createdBy), startedAt = stAt, players = players, pairings = decodePairings) @@ -258,13 +271,17 @@ object Tournament { createdBy: User, clock: TournamentClock, minutes: Int, - minPlayers: Int): Created = Created( + minPlayers: Int, + variant: Variant, + mode: Mode): Created = Created( id = Random nextString 8, data = Data( name = RandomName(), clock = clock, createdBy = createdBy.id, createdAt = DateTime.now, + variant = variant, + mode = mode, minutes = minutes, minPlayers = minPlayers), players = List(Player(createdBy)) diff --git a/app/tournament/TournamentApi.scala b/app/tournament/TournamentApi.scala index 5a53a42fdd..e2c29423f7 100644 --- a/app/tournament/TournamentApi.scala +++ b/app/tournament/TournamentApi.scala @@ -7,6 +7,7 @@ import scalaz.effects._ import scalaz.{ NonEmptyList, Success, Failure } import play.api.libs.json._ +import chess.{ Mode, Variant } import controllers.routes import game.DbGame import user.User @@ -37,7 +38,9 @@ private[tournament] final class TournamentApi( createdBy = me, clock = TournamentClock(setup.clockTime * 60, setup.clockIncrement), minutes = setup.minutes, - minPlayers = setup.minPlayers) + minPlayers = setup.minPlayers, + mode = Mode orDefault ~setup.mode, + variant = Variant orDefault setup.variant) _ ← repo saveIO created _ ← (withdrawIds map socket.reload).sequence _ ← reloadSiteSocket @@ -47,15 +50,11 @@ private[tournament] final class TournamentApi( def startIfReady(created: Created): Option[IO[Unit]] = created.startIfReady map doStart - def earlyStart(created: Created): Option[IO[Unit]] = + def earlyStart(created: Created): Option[IO[Unit]] = created.readyToEarlyStart option doStart(created.start) - private def doStart(started: Started): IO[Unit] = for { - _ ← repo saveIO started - _ ← socket start started.id - _ ← reloadSiteSocket - _ ← lobbyReload - } yield () + private def doStart(started: Started): IO[Unit] = + (repo saveIO started) >> (socket start started.id) >> reloadSiteSocket >> lobbyReload def wipeEmpty(created: Created): IO[Unit] = (for { _ ← repo removeIO created diff --git a/app/views/tournament/createdTable.scala.html b/app/views/tournament/createdTable.scala.html index 8f9c7d6a91..e84a59f9e4 100644 --- a/app/views/tournament/createdTable.scala.html +++ b/app/views/tournament/createdTable.scala.html @@ -10,6 +10,14 @@ @tours.map { tour => @tournament.linkTo(tour) + + @if(tour.variant.exotic) { + 960 + } + @if(tour.rated) { + rated + } + @tour.clock.show @{tour.minutes}m @tour.playerRatio diff --git a/app/views/tournament/faq.scala.html b/app/views/tournament/faq.scala.html index 55834a7586..3264d5f690 100644 --- a/app/views/tournament/faq.scala.html +++ b/app/views/tournament/faq.scala.html @@ -8,7 +8,7 @@ You will be notified when the tournament starts, so it is safe to play in another tab while waiting. ## Is it rated? -No, tournament games won't impact your ELO. +Some tournaments are rated and will affect your ELO. ## How to win? The players with the more points at the end of the tournament duration wins. diff --git a/app/views/tournament/form.scala.html b/app/views/tournament/form.scala.html index f851dacb63..1e5136860e 100644 --- a/app/views/tournament/form.scala.html +++ b/app/views/tournament/form.scala.html @@ -12,6 +12,22 @@ title = "New tournament") {

@error.message

} + + + + + + + + - - + + @@ -15,8 +15,15 @@ @createds.map { tour => - - + + - - + + @@ -53,8 +60,15 @@ @starteds.map { tour => - - + + - - + + @@ -77,8 +91,15 @@ @finisheds.map { tour => - - + +
+ + + @base.select(form("variant"), translatedVariantChoices) +
+ + + @base.select(form("mode"), translatedModeChoices) +
diff --git a/app/views/tournament/homeInner.scala.html b/app/views/tournament/homeInner.scala.html index c149099f90..38d4c026ff 100644 --- a/app/views/tournament/homeInner.scala.html +++ b/app/views/tournament/homeInner.scala.html @@ -6,8 +6,8 @@
Open tournamentsClockDuration@trans.mode()@trans.timeControl() Players
@linkTo(tour)@tour.clock.show@{tour.minutes}m + @if(tour.variant.exotic) { + 960 + } + @if(tour.rated) { + @trans.rated() + } + @tour.clock.show | @{tour.minutes}m @tour.playerRatio @ctx.me.map { me => @@ -43,8 +50,8 @@
Now PlayingClockDuration@trans.mode()@trans.timeControl() Players Leader
@linkTo(tour)@tour.clock.show@{tour.minutes}m + @if(tour.variant.exotic) { + 960 + } + @if(tour.rated) { + @trans.rated() + } + @tour.clock.show | @{tour.minutes}m @tour.playerRatio @tour.winner.map { player => @userInfosLink(player.username, player.elo.some, withOnline = false) @@ -67,8 +81,8 @@
FinishedClockDuration@trans.mode()@trans.timeControl() Players Winner
@linkTo(tour)@tour.clock.show@{tour.minutes}m + @if(tour.variant.exotic) { + 960 + } + @if(tour.rated) { + @trans.rated() + } + @tour.clock.show | @{tour.minutes}m @tour.playerRatio @tour.winner.map { player => @userInfosLink(player.username, player.elo.some, withOnline = false) diff --git a/app/views/tournament/infoBox.scala.html b/app/views/tournament/infoBox.scala.html index 90ca173647..da021460f0 100644 --- a/app/views/tournament/infoBox.scala.html +++ b/app/views/tournament/infoBox.scala.html @@ -6,15 +6,10 @@
Created by @userIdLink(tour.createdBy.some, withOnline = false)

- @tour.playerRatio players, - @if(false) { - rated - } else { - casual - } + @tour.clock.show, + @variantName(tour.variant).capitalize, + @{ tour.rated.fold(trans.rated(), trans.casual()) }

- @tour.clock.show -
Duration: @tour.minutes minutes @if(tour.isRunning && (tour isActive ctx.me)) {

diff --git a/public/stylesheets/tournament.css b/public/stylesheets/tournament.css index 04737c9ef4..b679ee45c4 100644 --- a/public/stylesheets/tournament.css +++ b/public/stylesheets/tournament.css @@ -42,6 +42,9 @@ #tournament table.slist tbody span.winner { background-position: right -304px; } +#tournament table.slist .small { + font-size: 0.8em; +} #tournament form.inline { display: inline;