tournaments wip

This commit is contained in:
Thibault Duplessis 2012-09-08 20:18:38 +02:00
parent 3b2176d903
commit 8c4a16e6e0
17 changed files with 184 additions and 9 deletions

View file

@ -0,0 +1,30 @@
package controllers
import lila._
import views._
import http.Context
import play.api.mvc.Result
object Tournament extends LilaController {
val repo = env.tournament.repo
val forms = env.tournament.forms
val home = Open { implicit ctx
IOk(repo.created map { tournaments
html.tournament.home(tournaments)
})
}
def show(id: String) = Open { implicit ctx
Ok(id)
}
def form = Auth { implicit ctx
me
Ok(html.tournament.form(forms.create))
}
def create = TODO
}

View file

@ -97,6 +97,10 @@ final class CoreEnv private (application: Application, val settings: Settings) {
flood = security.flood,
indexGame = search.indexGame)
lazy val tournament = new lila.tournament.TournamentEnv(
settings = settings,
mongodb = mongodb.apply _)
lazy val analyse = new lila.analyse.AnalyseEnv(
settings = settings,
gameRepo = game.gameRepo,

View file

@ -40,6 +40,8 @@ final class Settings(config: Config) {
val RoundCollectionRoom = getString("round.collection.room")
val RoundCollectionWatcherRoom = getString("round.collection.watcher_room")
val TournamentCollectionTournament = getString("tournament.collection.tournament")
val AnalyseCachedNbTtl = millis("analyse.cached.nb.ttl")
val UserPaginatorMaxPerPage = getInt("user.paginator.max_per_page")

View file

@ -174,9 +174,9 @@ class GameRepo(collection: MongoCollection)
def recentGames(limit: Int): IO[List[DbGame]] = io {
find(Query.started ++ Query.turnsGt(1))
.sort(DBObject("createdAt" -> -1))
.sort(Query.sortCreated)
.limit(limit)
.toList.map(_.decode).flatten sortBy (_.id)
.toList.map(_.decode).flatten
}
def games(ids: List[String]): IO[List[DbGame]] = io {

View file

@ -162,7 +162,8 @@ final class I18nKeys(translator: Translator) {
val bookmarkThisGame = new Key("bookmarkThisGame")
val toggleBackground = new Key("toggleBackground")
val advancedSearch = new Key("advancedSearch")
val tournament = new Key("tournament")
val freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents = new Key("freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents")
def keys = List(playWithAFriend, inviteAFriendToPlayWithYou, playWithTheMachine, challengeTheArtificialIntelligence, toInviteSomeoneToPlayGiveThisUrl, gameOver, waitingForOpponent, waiting, yourTurn, aiNameLevelAiLevel, level, toggleTheChat, toggleSound, chat, resign, checkmate, stalemate, white, black, createAGame, noGameAvailableRightNowCreateOne, whiteIsVictorious, blackIsVictorious, playWithTheSameOpponentAgain, newOpponent, playWithAnotherOpponent, yourOpponentWantsToPlayANewGameWithYou, joinTheGame, whitePlays, blackPlays, theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim, makeYourOpponentResign, forceResignation, talkInChat, theFirstPersonToComeOnThisUrlWillPlayWithYou, whiteCreatesTheGame, blackCreatesTheGame, whiteJoinsTheGame, blackJoinsTheGame, whiteResigned, blackResigned, whiteLeftTheGame, blackLeftTheGame, shareThisUrlToLetSpectatorsSeeTheGame, youAreViewingThisGameAsASpectator, replayAndAnalyse, viewGameStats, flipBoard, threefoldRepetition, claimADraw, offerDraw, draw, nbConnectedPlayers, talkAboutChessAndDiscussLichessFeaturesInTheForum, seeTheGamesBeingPlayedInRealTime, gamesBeingPlayedRightNow, viewAllNbGames, viewNbCheckmates, nbBookmarks, nbPopularGames, nbAnalysedGames, bookmarkedByNbPlayers, viewInFullSize, logOut, signIn, signUp, people, games, forum, chessPlayers, minutesPerSide, variant, timeControl, start, username, password, haveAnAccount, allYouNeedIsAUsernameAndAPassword, learnMoreAboutLichess, rank, gamesPlayed, declineInvitation, cancel, timeOut, drawOfferSent, drawOfferDeclined, drawOfferAccepted, drawOfferCanceled, yourOpponentOffersADraw, accept, decline, playingRightNow, abortGame, gameAborted, standard, unlimited, mode, casual, rated, thisGameIsRated, rematch, rematchOfferSent, rematchOfferAccepted, rematchOfferCanceled, rematchOfferDeclined, cancelRematchOffer, viewRematch, play, inbox, chatRoom, spectatorRoom, composeMessage, sentMessages, incrementInSeconds, freeOnlineChess, spectators, nbWins, nbLosses, nbDraws, exportGames, color, eloRange, giveNbSeconds, searchAPlayer, whoIsOnline, allPlayers, namedPlayers, premoveEnabledClickAnywhereToCancel, thisPlayerUsesChessComputerAssistance, opening, takeback, proposeATakeback, takebackPropositionSent, takebackPropositionDeclined, takebackPropositionAccepted, takebackPropositionCanceled, yourOpponentProposesATakeback, bookmarkThisGame, toggleBackground, advancedSearch, freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents)
def keys = List(playWithAFriend, inviteAFriendToPlayWithYou, playWithTheMachine, challengeTheArtificialIntelligence, toInviteSomeoneToPlayGiveThisUrl, gameOver, waitingForOpponent, waiting, yourTurn, aiNameLevelAiLevel, level, toggleTheChat, toggleSound, chat, resign, checkmate, stalemate, white, black, createAGame, noGameAvailableRightNowCreateOne, whiteIsVictorious, blackIsVictorious, playWithTheSameOpponentAgain, newOpponent, playWithAnotherOpponent, yourOpponentWantsToPlayANewGameWithYou, joinTheGame, whitePlays, blackPlays, theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim, makeYourOpponentResign, forceResignation, talkInChat, theFirstPersonToComeOnThisUrlWillPlayWithYou, whiteCreatesTheGame, blackCreatesTheGame, whiteJoinsTheGame, blackJoinsTheGame, whiteResigned, blackResigned, whiteLeftTheGame, blackLeftTheGame, shareThisUrlToLetSpectatorsSeeTheGame, youAreViewingThisGameAsASpectator, replayAndAnalyse, viewGameStats, flipBoard, threefoldRepetition, claimADraw, offerDraw, draw, nbConnectedPlayers, talkAboutChessAndDiscussLichessFeaturesInTheForum, seeTheGamesBeingPlayedInRealTime, gamesBeingPlayedRightNow, viewAllNbGames, viewNbCheckmates, nbBookmarks, nbPopularGames, nbAnalysedGames, bookmarkedByNbPlayers, viewInFullSize, logOut, signIn, signUp, people, games, forum, chessPlayers, minutesPerSide, variant, timeControl, start, username, password, haveAnAccount, allYouNeedIsAUsernameAndAPassword, learnMoreAboutLichess, rank, gamesPlayed, declineInvitation, cancel, timeOut, drawOfferSent, drawOfferDeclined, drawOfferAccepted, drawOfferCanceled, yourOpponentOffersADraw, accept, decline, playingRightNow, abortGame, gameAborted, standard, unlimited, mode, casual, rated, thisGameIsRated, rematch, rematchOfferSent, rematchOfferAccepted, rematchOfferCanceled, rematchOfferDeclined, cancelRematchOffer, viewRematch, play, inbox, chatRoom, spectatorRoom, composeMessage, sentMessages, incrementInSeconds, freeOnlineChess, spectators, nbWins, nbLosses, nbDraws, exportGames, color, eloRange, giveNbSeconds, searchAPlayer, whoIsOnline, allPlayers, namedPlayers, premoveEnabledClickAnywhereToCancel, thisPlayerUsesChessComputerAssistance, opening, takeback, proposeATakeback, takebackPropositionSent, takebackPropositionDeclined, takebackPropositionAccepted, takebackPropositionCanceled, yourOpponentProposesATakeback, bookmarkThisGame, toggleBackground, advancedSearch, tournament, freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents)
}

View file

@ -0,0 +1,16 @@
package lila
package tournament
import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints._
final class DataForm {
val create = Form(mapping(
"maxUsers" -> number.verifying(min(3), max(8))
)(TournamentSetup.apply)(TournamentSetup.unapply))
}
case class TournamentSetup(
maxUsers: Int)

View file

@ -0,0 +1,26 @@
package lila
package tournament
sealed abstract class Status(val id: Int) extends Ordered[Status] {
def compare(other: Status) = id compare other.id
def name = toString
def is(s: Status): Boolean = this == s
def is(f: Status.type Status): Boolean = is(f(Status))
}
object Status {
case object Created extends Status(10)
case object Started extends Status(20)
case object Aborted extends Status(25) // from this point the game is finished
case object Finished extends Status(30)
val all = List(Created, Started, Aborted, Finished)
val byId = all map { v (v.id, v) } toMap
def apply(id: Int): Option[Status] = byId get id
}

View file

@ -6,8 +6,15 @@ import org.scala_tools.time.Imports._
import com.novus.salat.annotations.Key
case class Tournament(
@Key("_id") id: String,
createdAt: DateTime,
createdBy: String) {
@Key("_id") id: String,
createdBy: String,
maxUsers: Int,
createdAt: DateTime = DateTime.now,
status: Status = Status.Created,
users: List[String]) {
}
object Tournament {
}

View file

@ -0,0 +1,20 @@
package lila
package tournament
import game.{ GameRepo, DbGame }
import core.Settings
import com.traackr.scalastic.elasticsearch
import com.mongodb.casbah.MongoCollection
final class TournamentEnv(
settings: Settings,
mongodb: String MongoCollection) {
import settings._
lazy val forms = new DataForm
lazy val repo = new TournamentRepo(
collection = mongodb(TournamentCollectionTournament))
}

View file

@ -0,0 +1,27 @@
package lila
package tournament
import com.novus.salat._
import com.novus.salat.dao._
import com.mongodb.casbah.MongoCollection
import com.mongodb.casbah.query.Imports._
import scalaz.effects._
import org.joda.time.DateTime
import org.scala_tools.time.Imports._
class TournamentRepo(collection: MongoCollection)
extends SalatDAO[Tournament, String](collection) {
def byId(id: String): IO[Option[Tournament]] = io {
findOneById(id)
}
def created: IO[List[Tournament]] = io {
find(DBObject("status" -> Status.Created))
.sort(DBObject("createdAt" -> -1))
.toList
}
private def idSelector(id: String): DBObject = DBObject("_id" -> id)
private def idSelector(tournament: Tournament): DBObject = idSelector(tournament.id)
}

View file

@ -13,12 +13,13 @@ final class SiteMenu(trans: I18nKeys) {
val play = new Elem("play", routes.Lobby.home, trans.play)
val game = new Elem("game", routes.Game.realtime, trans.games)
val tournament = new Elem("tournament", routes.Tournament.home, trans.tournament)
val user = new Elem("user", routes.User.list(page = 1), trans.people)
val forum = new Elem("forum", routes.ForumCateg.index, trans.forum)
val message = new Elem("message", routes.Message.inbox(page = 1), trans.inbox)
private val authenticated = List(play, game, user, forum, message)
private val anonymous = List(play, game, user, forum)
private val authenticated = List(play, game, tournament, user, forum, message)
private val anonymous = List(play, game, tournament, user, forum)
def all(me: Option[User]) = me.isDefined.fold(authenticated, anonymous)
}

View file

@ -0,0 +1,8 @@
@(form: Form[_])(implicit ctx: Context)
@tournament.layout(
title = "New tournament") {
<h1>New tournament</h1>
<form action="@routes.Tournament.create" method="POST">
</form>
}

View file

@ -0,0 +1,13 @@
@(tournaments: List[lila.tournament.Tournament])(implicit ctx: Context)
@tournament.layout(
title = "Tournaments") {
<div class="content_box tournament_box">
<h1 class="lichess_title">Tournaments</h1>
<div class="body">
list of tournaments
</div>
<a href="@routes.Tournament.form()" class="action button">Create a new tournament</a>
</div>
}

View file

@ -0,0 +1,12 @@
@(title: String)(body: Html)(implicit ctx: Context)
@moreCss = {
@cssTag("tournament.css")
}
@base.layout(
title = title,
moreCss = moreCss,
active = siteMenu.tournament.some) {
<div id="tournament">@body</div>
}

View file

@ -138,4 +138,5 @@ yourOpponentProposesATakeback=Your opponent proposes a takeback
bookmarkThisGame=Bookmark this game
toggleBackground=Toggle background color
advancedSearch=Advanced Search
tournament=Tournament
freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents=Free online Chess game. Play Chess now in a clean interface. No registration, no ads, no plugin required. Play Chess with computer, friends or random opponents.

View file

@ -138,4 +138,5 @@ yourOpponentProposesATakeback=Votre adversaire propose l'annulation du coup
bookmarkThisGame=Mettre cette partie en favoris
toggleBackground=Changer la couleur d'arrière plan
advancedSearch=Recherche avancée
tournament=Tournoi
freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrationNoAdsNoPluginRequiredPlayChessWithComputerFriendsOrRandomOpponents=Jeu d'échecs gratuit en ligne. Jouez aux échecs immédiatement avec une interface simple. Pas d'inscription obligatoire, pas de pub, pas de plugin. Jouez aux échecs contre l'ordinateur, des amis ou des adversaires en ligne.

View file

@ -38,8 +38,14 @@ GET /$gameId<[\w\-]{8}>/$color<white|black>/table controllers.Round.tableWatc
GET /$fullId<[\w\-]{12}>/table controllers.Round.tablePlayer(fullId: String)
GET /$gameId<[\w\-]{8}>/players controllers.Round.players(gameId: String)
# Tournament
GET /tournament controllers.Tournament.home
GET /tournament/$id<[\w\-]{8}> controllers.Tournament.show(id: String)
GET /tournament/new controllers.Tournament.form
POST /tournament/new controllers.Tournament.create
# Analyse
GET /analyse/$gameId<[\w\-]{8}> controllers.Analyse.replay(gameId: String, color: String = "white")
GET /analyse/$gameId<[\w\-]{8}> controllers.Analyse.replay(gameId: String, color: String = "white")
GET /analyse/$gameId<[\w\-]{8}>/$color<white|black> controllers.Analyse.replay(gameId: String, color: String)
POST /analyse/$gameId<[\w\-]{8}>/$color<white|black>/computer controllers.Analyse.computer(gameId: String, color: String)
GET /$gameId<[\w\-]{8}>/stats controllers.Analyse.stats(gameId: String)