Progress on round setup

This commit is contained in:
Thibault Duplessis 2012-05-16 01:02:32 +02:00
parent ba38cee499
commit 701e4fc78a
17 changed files with 160 additions and 40 deletions

View file

@ -83,6 +83,8 @@ trait LilaController
def IOk[A](op: IO[A])(implicit writer: Writeable[A], ctype: ContentTypeOf[A]) = def IOk[A](op: IO[A])(implicit writer: Writeable[A], ctype: ContentTypeOf[A]) =
Ok(op.unsafePerformIO) Ok(op.unsafePerformIO)
def IORedirect(op: IO[Call]) = Redirect(op.unsafePerformIO)
// I like Unit requests. // I like Unit requests.
implicit def wUnit: Writeable[Unit] = implicit def wUnit: Writeable[Unit] =
Writeable[Unit](_ Codec toUTF8 "ok") Writeable[Unit](_ Codec toUTF8 "ok")

View file

@ -0,0 +1,9 @@
package controllers
import lila._
import views._
object Round extends LilaController {
def player(playerId: String) = TODO
}

View file

@ -7,6 +7,7 @@ import setup._
object Setup extends LilaController { object Setup extends LilaController {
def forms = env.setup.formFactory def forms = env.setup.formFactory
def processor = env.setup.processor
val aiForm = Open { implicit ctx val aiForm = Open { implicit ctx
IOk(forms.aiFilled map { html.setup.ai(_) }) IOk(forms.aiFilled map { html.setup.ai(_) })
@ -16,7 +17,11 @@ object Setup extends LilaController {
implicit val req = ctx.body implicit val req = ctx.body
forms.ai.bindFromRequest.fold( forms.ai.bindFromRequest.fold(
_ Redirect(routes.Lobby.home), _ Redirect(routes.Lobby.home),
_ Redirect(routes.Lobby.home) config IORedirect(
processor ai config map { pov
routes.Round.player(pov.playerId)
}
)
) )
} }

View file

@ -2,7 +2,7 @@ package lila
package core package core
import com.mongodb.casbah.MongoConnection import com.mongodb.casbah.MongoConnection
import com.mongodb.{ Mongo, MongoOptions, ServerAddress MongoServer } import com.mongodb.{ DBRef, Mongo, MongoOptions, ServerAddress MongoServer }
import akka.actor._ import akka.actor._
@ -11,7 +11,7 @@ import play.api.Application
import ui._ import ui._
final class CoreEnv private(application: Application, settings: Settings) { final class CoreEnv private (application: Application, settings: Settings) {
implicit val app = application implicit val app = application
import settings._ import settings._
@ -22,7 +22,8 @@ final class CoreEnv private(application: Application, settings: Settings) {
lazy val user = new lila.user.UserEnv( lazy val user = new lila.user.UserEnv(
settings = settings, settings = settings,
mongodb = mongodb.apply _) mongodb = mongodb.apply _,
dbRef = namespace id new DBRef(mongodb.underlying, namespace, id))
lazy val lobby = new lila.lobby.LobbyEnv( lazy val lobby = new lila.lobby.LobbyEnv(
app = app, app = app,
@ -37,7 +38,8 @@ final class CoreEnv private(application: Application, settings: Settings) {
lazy val setup = new lila.setup.SetupEnv( lazy val setup = new lila.setup.SetupEnv(
settings = settings, settings = settings,
mongodb = mongodb.apply _) mongodb = mongodb.apply _,
gameRepo = game.gameRepo)
lazy val timeline = new lila.timeline.TimelineEnv( lazy val timeline = new lila.timeline.TimelineEnv(
settings = settings, settings = settings,
@ -101,7 +103,7 @@ final class CoreEnv private(application: Application, settings: Settings) {
object CoreEnv { object CoreEnv {
def apply(app: Application) = new CoreEnv( def apply(app: Application) = new CoreEnv(
app, app,
new Settings(app.configuration.underlying) new Settings(app.configuration.underlying)
) )
} }

View file

@ -2,6 +2,7 @@ package lila
package game package game
import round.{ Event, Progress } import round.{ Event, Progress }
import user.User
import chess.{ History ChessHistory, Board, Move, Pos, Game, Clock, Status, Color, Piece, Variant } import chess.{ History ChessHistory, Board, Move, Pos, Game, Clock, Status, Color, Piece, Variant }
import Color._ import Color._
import chess.format.{ PgnReader, Fen } import chess.format.{ PgnReader, Fen }
@ -259,4 +260,30 @@ object DbGame {
val fullIdSize = 12 val fullIdSize = 12
def takeGameId(fullId: String) = fullId take gameIdSize def takeGameId(fullId: String) = fullId take gameIdSize
def apply(
game: Game,
whitePlayer: DbPlayer,
blackPlayer: DbPlayer,
ai: Option[(Color, Int)],
creatorColor: Color,
isRated: Boolean,
variant: Variant,
createdAt: DateTime): DbGame = DbGame(
id = IdGenerator.game,
whitePlayer = whitePlayer,
blackPlayer = blackPlayer,
pgn = "",
status = Status.Created,
turns = game.turns,
clock = game.clock,
lastMove = None,
check = None,
creatorColor = creatorColor,
positionHashes = "",
castles = "KQkq",
isRated = isRated,
variant = variant,
lastMoveTime = None,
createdAt = createdAt.some)
} }

View file

@ -2,6 +2,7 @@ package lila
package game package game
import chess._ import chess._
import user.User
import com.mongodb.DBRef import com.mongodb.DBRef
@ -27,6 +28,10 @@ case class DbPlayer(
} }
} mkString " " } mkString " "
def withUser(user: User)(dbRef: User => DBRef): DbPlayer = copy(
user = dbRef(user).some,
elo = user.elo.some)
def isAi = aiLevel.isDefined def isAi = aiLevel.isDefined
def isHuman = !isAi def isHuman = !isAi
@ -50,3 +55,22 @@ case class DbPlayer(
def removeTakebackProposition = copy(isProposingTakeback = false) def removeTakebackProposition = copy(isProposingTakeback = false)
} }
object DbPlayer {
def apply(
color: Color,
aiLevel: Option[Int]): DbPlayer = DbPlayer(
id = IdGenerator.player,
color = color,
ps = "",
aiLevel = aiLevel,
isWinner = None,
elo = None,
isOfferingDraw = false,
lastDrawOffer = None,
isProposingTakeback = false,
user = None,
moveTimes = "",
blurs = 0)
}

View file

@ -0,0 +1,11 @@
package lila
package game
import ornicar.scalalib.OrnicarRandom
object IdGenerator {
def game = OrnicarRandom nextAsciiString DbGame.gameIdSize
def player = OrnicarRandom nextAsciiString DbGame.playerIdSize
}

View file

@ -7,6 +7,8 @@ case class Pov(game: DbGame, color: Color) {
def player = game player color def player = game player color
def playerId = player.id
def opponent = game player !color def opponent = game player !color
def isPlayerFullId(fullId: Option[String]): Boolean = def isPlayerFullId(fullId: Option[String]): Boolean =

View file

@ -1,12 +1,29 @@
package lila package lila
package setup package setup
import chess.Variant import chess.{ Game, Board, Variant, Color ChessColor }
import elo.EloRange import elo.EloRange
import game.{ DbGame, DbPlayer }
import org.joda.time.DateTime
case class AiConfig(variant: Variant, level: Int, color: Color) extends Config { case class AiConfig(variant: Variant, level: Int, color: Color) extends Config {
def >> = (variant.id, level, color.name).some def >> = (variant.id, level, color.name).some
def game = DbGame(
game = Game(board = Board(pieces = variant.pieces)),
ai = Some(!creatorColor -> level),
whitePlayer = DbPlayer(
color = ChessColor.White,
aiLevel = creatorColor.black option level),
blackPlayer = DbPlayer(
color = ChessColor.Black,
aiLevel = creatorColor.white option level),
creatorColor = creatorColor,
isRated = false,
variant = variant,
createdAt = DateTime.now)
} }
object AiConfig extends BaseConfig { object AiConfig extends BaseConfig {
@ -17,8 +34,8 @@ object AiConfig extends BaseConfig {
color = Color(c) err "Invalid color " + c) color = Color(c) err "Invalid color " + c)
val default = AiConfig( val default = AiConfig(
variant = variantDefault, variant = variantDefault,
level = 1, level = 1,
color = Color.default) color = Color.default)
val levelChoices = (1 to 8).toList map { l l.toString -> l.toString } val levelChoices = (1 to 8).toList map { l l.toString -> l.toString }

View file

@ -3,6 +3,7 @@ package setup
import chess.{ Variant, Mode } import chess.{ Variant, Mode }
import elo.EloRange import elo.EloRange
import game.{ GameRepo, DbGame, Pov }
trait Config { trait Config {
@ -11,6 +12,12 @@ trait Config {
// Creator player color // Creator player color
val color: Color val color: Color
lazy val creatorColor = color.resolve
def game: DbGame
def pov = Pov(game, creatorColor)
} }
trait HumanConfig extends Config with EloRange { trait HumanConfig extends Config with EloRange {

View file

@ -2,17 +2,21 @@ package lila
package setup package setup
import http.Context import http.Context
import game.{ GameRepo, Pov }
import chess.{ Game, Board }
import scalaz.effects._ import scalaz.effects._
final class Processor( final class Processor(
configRepo: UserConfigRepo) { configRepo: UserConfigRepo,
gameRepo: GameRepo) {
def ai(config: AiConfig)(implicit ctx: Context): IO[Unit] = for { def ai(config: AiConfig)(implicit ctx: Context): IO[Pov] = for {
_ ctx.me.fold( _ ctx.me.fold(
user configRepo.update(user, ((c: UserConfig) c withAi config)), user configRepo.update(user, ((c: UserConfig) c withAi config)),
io() io()
) )
color = config.color.resolve pov = config.pov
} yield () _ gameRepo insert pov.game
} yield pov
} }

View file

@ -4,10 +4,12 @@ package setup
import com.mongodb.casbah.MongoCollection import com.mongodb.casbah.MongoCollection
import core.Settings import core.Settings
import game.GameRepo
final class SetupEnv( final class SetupEnv(
settings: Settings, settings: Settings,
mongodb: String MongoCollection) { mongodb: String MongoCollection,
gameRepo: GameRepo) {
import settings._ import settings._
@ -17,5 +19,6 @@ final class SetupEnv(
configRepo = configRepo) configRepo = configRepo)
lazy val processor = new Processor( lazy val processor = new Processor(
configRepo = configRepo) configRepo = configRepo,
gameRepo = gameRepo)
} }

View file

@ -9,8 +9,8 @@ import play.api.libs.concurrent._
// Keep uptodate with framework/src/play/src/main/scala/play/api/libs/iteratee/Iteratee.scala PushEnumerator (l.1020) // Keep uptodate with framework/src/play/src/main/scala/play/api/libs/iteratee/Iteratee.scala PushEnumerator (l.1020)
final class LilaEnumerator[E]( final class LilaEnumerator[E](
in: List[E], in: List[E],
onStart: => Unit = () => (), onStart: () => Unit = () => (),
onComplete: => Unit = () => (), onComplete: () => Unit = () => (),
onError: (String, Input[E]) => Unit = (_: String, _: Input[E]) => ()) onError: (String, Input[E]) => Unit = (_: String, _: Input[E]) => ())
extends Enumerator[E] with Enumerator.Pushee[E] { extends Enumerator[E] with Enumerator.Pushee[E] {
@ -18,7 +18,7 @@ extends Enumerator[E] with Enumerator.Pushee[E] {
var promise: Promise[Iteratee[E, _]] with Redeemable[Iteratee[E, _]] = _ var promise: Promise[Iteratee[E, _]] with Redeemable[Iteratee[E, _]] = _
def apply[A](it: Iteratee[E, A]): Promise[Iteratee[E, A]] = { def apply[A](it: Iteratee[E, A]): Promise[Iteratee[E, A]] = {
onStart onStart()
iteratee = it.asInstanceOf[Iteratee[E, _]] iteratee = it.asInstanceOf[Iteratee[E, _]]
in foreach push in foreach push
val newPromise = new STMPromise[Iteratee[E, A]]() val newPromise = new STMPromise[Iteratee[E, A]]()
@ -36,31 +36,29 @@ extends Enumerator[E] with Enumerator.Pushee[E] {
def push(item: E): Boolean = { def push(item: E): Boolean = {
if (iteratee != null) { if (iteratee != null) {
iteratee = iteratee.pureFlatFold[E, Any]( iteratee = iteratee.pureFlatFold[E, Any] {
// DONE case Step.Done(a, in) => {
(a, in) => { onComplete()
onComplete
Done(a, in) Done(a, in)
}, }
// CONTINUE case Step.Cont(k) => {
k => {
val next = k(Input.El(item)) val next = k(Input.El(item))
next.pureFlatFold( next.pureFlatFold {
(a, in) => { case Step.Done(a, in) => {
onComplete onComplete()
next next
}, }
_ => next, case _ => next
(_, _) => next) }
}, }
// ERROR case Step.Error(e, in) => {
(e, in) => {
onError(e, in) onError(e, in)
Error(e, in) Error(e, in)
}) }
}
true true
} else { } else {
false false

View file

@ -4,7 +4,6 @@ package socket
import play.api.libs.concurrent._ import play.api.libs.concurrent._
import play.api.libs.json._ import play.api.libs.json._
import play.api.libs.iteratee._ import play.api.libs.iteratee._
import scala.util.Random
object Util { object Util {

View file

@ -2,18 +2,23 @@ package lila
package user package user
import com.mongodb.casbah.MongoCollection import com.mongodb.casbah.MongoCollection
import com.mongodb.casbah.Imports.ObjectId
import com.mongodb.DBRef
import core.Settings import core.Settings
final class UserEnv( final class UserEnv(
settings: Settings, settings: Settings,
mongodb: String MongoCollection) { mongodb: String MongoCollection,
dbRef: String ObjectId DBRef) {
import settings._ import settings._
lazy val historyRepo = new HistoryRepo(mongodb(MongoCollectionHistory)) lazy val historyRepo = new HistoryRepo(mongodb(MongoCollectionHistory))
lazy val userRepo = new UserRepo(mongodb(MongoCollectionUser)) lazy val userRepo = new UserRepo(
collection = mongodb(MongoCollectionUser),
dbRef = user dbRef(MongoCollectionUser)(user.id))
lazy val eloUpdater = new EloUpdater( lazy val eloUpdater = new EloUpdater(
userRepo = userRepo, userRepo = userRepo,

View file

@ -3,13 +3,15 @@ package user
import com.novus.salat._ import com.novus.salat._
import com.novus.salat.dao._ import com.novus.salat.dao._
import com.mongodb.DBRef
import com.mongodb.casbah.MongoCollection import com.mongodb.casbah.MongoCollection
import com.mongodb.casbah.Imports._ import com.mongodb.casbah.Imports._
import scalaz.effects._ import scalaz.effects._
import com.roundeights.hasher.Implicits._ import com.roundeights.hasher.Implicits._
class UserRepo(collection: MongoCollection) class UserRepo(
extends SalatDAO[User, ObjectId](collection) { collection: MongoCollection,
val dbRef: User => DBRef) extends SalatDAO[User, ObjectId](collection) {
def user(userId: String): IO[Option[User]] = user(new ObjectId(userId)) def user(userId: String): IO[Option[User]] = user(new ObjectId(userId))

View file

@ -1,6 +1,9 @@
# Game # Game
GET /games controllers.Game.list GET /games controllers.Game.list
# Round
GET /playerId controllers.Round.player(playerId: String)
# Setting # Setting
POST /setting/color controllers.Setting.color POST /setting/color controllers.Setting.color
POST /setting/sound controllers.Setting.sound POST /setting/sound controllers.Setting.sound