game filter multiple choices wip

pull/83/head
Thibault Duplessis 2013-07-26 14:53:04 +02:00
parent a73e5c9cb6
commit c3543ac9d0
11 changed files with 86 additions and 64 deletions

View File

@ -1,12 +1,11 @@
package controllers
import play.api.data.Form
import play.api.mvc.{ Result, Call }
import lila.app._
import lila.game.GameRepo
import lila.user.UserRepo
import lila.user.{ Context, BodyContext }
import play.api.data.Form
import play.api.mvc.{ Result, Call }
import views._
object Setup extends LilaController with TheftPrevention {
@ -69,7 +68,9 @@ object Setup extends LilaController with TheftPrevention {
}
def filterForm = Open { implicit ctx
env.forms.filterFilled map { html.setup.filter(_) }
env.forms.filterFilled map {
case (form, filter) html.setup.filter(form, filter)
}
}
def filter = OpenBody { implicit ctx

View File

@ -29,8 +29,4 @@ trait SetupHelper extends scalaz.Booleans { self: I18nHelper ⇒
}
}
}
def eloDiffChoices(elo: Int)(implicit ctx: Context) = FilterConfig.eloDiffs map { diff
diff -> "%d - %d (±%d)".format(elo - diff, elo + diff, diff)
}
}

View File

@ -1,24 +1,24 @@
@(form: Form[_])(implicit ctx: Context)
@(form: Form[_], filter: lila.setup.FilterConfig)(implicit ctx: Context)
@helper.form(action = routes.Setup.filter(), 'novalidate -> "novalidate") {
<table>
<tbody>
<tr>
<td>@trans.variant()</td>
<td>@setup.filterRadios(form, "variant", translatedVariantChoices)</td>
<td>@setup.filterCheckboxes(form, "variant", filter.variant.map(_.id.toString), translatedVariantChoices)</td>
</tr>
<tr>
<td>@trans.timeControl()</td>
<td>@setup.filterRadios(form, "speed", translatedSpeedChoices)</td>
<td>@setup.filterCheckboxes(form, "speed", filter.speed.map(_.id.toString), translatedSpeedChoices)</td>
</tr>
<tr>
<td>@trans.mode()</td>
<td>@setup.filterRadios(form, "mode", translatedModeChoices)</td>
<td>@setup.filterCheckboxes(form, "mode", filter.mode.map(_.id.toString), translatedModeChoices)</td>
</tr>
@ctx.me.map { me =>
<tr>
<td>@trans.eloRange()</td>
<td>@setup.filterRadios(form, "eloDiff", eloDiffChoices(me.elo))</td>
<td>@helper.inputText(form("eloRange"))</td>
</tr>
}
</tbody>

View File

@ -0,0 +1,10 @@
@(form: Form[_], key: String, index: Int, value: String, checks: List[String], text: Html)
<label>
<input
type="checkbox"
name="@{form(key).name}[@index]"
value="@value"
@(if(checks contains value) "checked" else "") />
@text
</label>

View File

@ -0,0 +1,7 @@
@(form: Form[_], key: String, checks: List[String], options: Seq[(Any,String)])(implicit ctx: Context)
@options.zipWithIndex.map {
case ((value, text), index) => {
@setup.filterCheckbox(form, key, index, value.toString, checks, Html(text))
}
}

View File

@ -26,6 +26,11 @@ trait PimpedJson {
def arr(key: String): Option[JsArray] =
(js \ key).asOpt[JsArray]
def ints(key: String): Option[List[Int]] =
(js \ key).asOpt[JsArray] map { arr
arr.value.toList map { v v.asOpt[Int] } flatten
}
def get[A: Reads](key: String): Option[A] =
(js \ key).asOpt[A]
}

View File

@ -4,62 +4,62 @@ import play.api.libs.json._
import chess.{ Variant, Mode, Speed }
import lila.common.PimpedJson._
import lila.common.EloRange
case class FilterConfig(
variant: Option[Variant],
mode: Option[Mode],
speed: Option[Speed],
eloDiff: Option[Int]) {
variant: List[Variant],
mode: List[Mode],
speed: List[Speed],
eloRange: EloRange) {
def encode = RawFilterConfig(
v = ~variant.map(_.id),
m = mode.map(_.id) | -1,
s = ~speed.map(_.id),
e = ~eloDiff
v = variant.map(_.id),
m = mode.map(_.id),
s = speed.map(_.id),
e = eloRange.toString
)
def >> = (
variant map (_.id),
mode map (_.id),
speed map (_.id),
eloDiff
eloRange.toString
).some
def render = Json.obj(
"variant" -> variant.map(_.toString),
"mode" -> mode.map(_.toString),
"speed" -> speed.map(_.id),
"eloDiff" -> eloDiff
"eloRange" -> eloRange.toString
)
}
object FilterConfig {
val variants = List(Variant.Standard, Variant.Chess960)
val modes = Mode.all
val speeds = Speed.all
val default = FilterConfig(
variant = none,
mode = none,
speed = none,
eloDiff = none)
variant = variants,
mode = modes,
speed = speeds,
eloRange = EloRange.default)
val variants = 0 :: Config.variants
val modes = -1 :: Mode.all.map(_.id)
val speeds = 0 :: Config.speeds
val eloDiffs = 100 :: 200 :: 300 :: 500 :: Nil
def <<(v: Option[Int], m: Option[Int], s: Option[Int], e: Option[Int]) = new FilterConfig(
variant = v flatMap Variant.apply,
mode = m flatMap Mode.apply,
speed = s flatMap Speed.apply,
eloDiff = e filter (0!=)
def <<(v: List[Int], m: List[Int], s: List[Int], e: String) = new FilterConfig(
variant = v map Variant.apply flatten,
mode = m map Mode.apply flatten,
speed = s map Speed.apply flatten,
eloRange = EloRange orDefault e
)
def fromDB(obj: JsObject): Option[FilterConfig] = for {
filter obj obj "filter"
variant filter int "v"
mode filter int "m"
speed filter int "s"
eloDiff filter int "e"
config RawFilterConfig(variant, mode, speed, eloDiff).decode
variant filter ints "v"
mode filter ints "m"
speed filter ints "s"
eloRange filter str "e"
config RawFilterConfig(variant, mode, speed, eloRange).decode
} yield config
import lila.db.Tube
@ -79,13 +79,13 @@ object FilterConfig {
)
}
private[setup] case class RawFilterConfig(v: Int, m: Int, s: Int, e: Int) {
private[setup] case class RawFilterConfig(v: List[Int], m: List[Int], s: List[Int], e: String) {
def decode = FilterConfig(
variant = Variant(v),
mode = Mode(m),
speed = Speed(s),
eloDiff = e.some filter (0!=)
variant = v map Variant.apply flatten,
mode = m map Mode.apply flatten,
speed = s map Speed.apply flatten,
eloRange = EloRange orDefault e
).some
}

View File

@ -1,28 +1,27 @@
package lila.setup
import play.api.data._
import play.api.data.Forms._
import chess.Variant
import lila.common.EloRange
import lila.db.api._
import lila.lobby.Color
import lila.user.Context
import play.api.data._
import play.api.data.Forms._
import tube.{ userConfigTube, anonConfigTube }
private[setup] final class FormFactory {
import Mappings._
def filterFilled(implicit ctx: Context): Fu[Form[FilterConfig]] =
filterConfig map filter(ctx).fill
def filterFilled(implicit ctx: Context): Fu[(Form[FilterConfig], FilterConfig)] =
filterConfig map { f filter(ctx).fill(f) -> f }
def filter(ctx: Context) = Form(
mapping(
"variant" -> optional(variant),
"mode" -> mode(true),
"speed" -> optional(speed),
"eloDiff" -> optional(eloDiff)
"variant" -> list(variant),
"mode" -> list(rawMode(true)),
"speed" -> list(speed),
"eloRange" -> nonEmptyText
)(FilterConfig.<<)(_.>>)
)
@ -30,7 +29,7 @@ private[setup] final class FormFactory {
def aiFilled(fen: Option[String])(implicit ctx: Context): Fu[Form[AiConfig]] =
aiConfig map { config
ai(ctx) fill fen.fold(config) { f
ai(ctx) fill fen.fold(config) { f
config.copy(fen = f.some, variant = Variant.FromPosition)
}
}
@ -51,7 +50,7 @@ private[setup] final class FormFactory {
def friendFilled(fen: Option[String])(implicit ctx: Context): Fu[Form[FriendConfig]] =
friendConfig map { config
friend(ctx) fill fen.fold(config) { f
friend(ctx) fill fen.fold(config) { f
config.copy(fen = f.some, variant = Variant.FromPosition)
}
}
@ -90,6 +89,6 @@ private[setup] final class FormFactory {
def hookConfig(implicit ctx: Context): Fu[HookConfig] = savedConfig map (_.hook)
def savedConfig(implicit ctx: Context): Fu[UserConfig] =
def savedConfig(implicit ctx: Context): Fu[UserConfig] =
ctx.me.fold(AnonConfigRepo config ctx.req)(UserConfigRepo.config)
}

View File

@ -13,14 +13,14 @@ object Mappings {
val variantWithFen = number.verifying(Config.variantsWithFen contains _)
val time = number.verifying(HookConfig.times contains _)
val increment = number.verifying(HookConfig.increments contains _)
def mode(isAuth: Boolean) = optional(number
def mode(isAuth: Boolean) = optional(rawMode(isAuth))
def rawMode(isAuth: Boolean) = number
.verifying(HookConfig.modes contains _)
.verifying(m m == Mode.Casual.id || isAuth))
.verifying(m m == Mode.Casual.id || isAuth)
val eloRange = optional(nonEmptyText.verifying(EloRange valid _))
val color = nonEmptyText.verifying(Color.names contains _)
val level = number.verifying(AiConfig.levels contains _)
val speed = number.verifying(Config.speeds contains _)
val eloDiff = number.verifying(FilterConfig.eloDiffs contains _)
def fen(strict: Boolean) = optional {
nonEmptyText verifying { source ~(Forsyth <<< source).map(_.situation playable strict) }

View File

@ -2033,7 +2033,7 @@ var storage = {
$div.fadeOut(500);
}
return false;
});
}).click();
$bot.on("click", "tr", function() {
location.href = $(this).find('a.watch').attr("href");

6
todo
View File

@ -57,4 +57,8 @@ customize sound notifications http://imgur.com/70WVyb5
opera issue http://en.lichess.org/forum/lichess-feedback/new-game-wont-show-on-games-list-opera#1
embedded games links http://2ls.ru/chessonline/
filter ranges http://en.lichess.org/forum/lichess-feedback/my-proposed-changes-with-filter-window#1
takeback en passant http://fr.lichess.org/forum/general-chess-discussion/bug-with-take-back-and-en-passant#2
deploy
------
db.config.update({filter:{$exists:1}},{$unset:{filter:1}},{multi:1})
db.config_anon.update({filter:{$exists:1}},{$unset:{filter:1}},{multi:1})