complete search form backbone
parent
d30d5340a2
commit
c8a90693a8
|
@ -9,28 +9,46 @@ final class DataForm {
|
|||
|
||||
val search = Form(mapping(
|
||||
"usernames" -> optional(nonEmptyText),
|
||||
"variant" -> optional(numberIn(Query.variants)),
|
||||
"mode" -> optional(numberIn(Query.modes)),
|
||||
"opening" -> optional(stringIn(Query.openings)),
|
||||
"turnsMin" -> optional(numberIn(Query.turns)),
|
||||
"turnsMax" -> optional(numberIn(Query.turns))
|
||||
"variant" -> numberIn(Query.variants),
|
||||
"mode" -> numberIn(Query.modes),
|
||||
"opening" -> stringIn(Query.openings),
|
||||
"turnsMin" -> numberIn(Query.turns),
|
||||
"turnsMax" -> numberIn(Query.turns),
|
||||
"eloMin" -> numberIn(Query.averageElos),
|
||||
"eloMax" -> numberIn(Query.averageElos),
|
||||
"hasAi" -> numberIn(Query.hasAis),
|
||||
"aiLevel" -> numberIn(Query.aiLevels),
|
||||
"durationMin" -> numberIn(Query.durations),
|
||||
"durationMax" -> numberIn(Query.durations),
|
||||
"dateMin" -> stringIn(Query.dates),
|
||||
"dateMax" -> stringIn(Query.dates),
|
||||
"status" -> numberIn(Query.statuses)
|
||||
)(SearchData.apply)(SearchData.unapply))
|
||||
|
||||
private def numberIn(choices: List[(Int, String)]) =
|
||||
number.verifying(hasKey(choices, _))
|
||||
private def numberIn(choices: Seq[(Int, String)]) =
|
||||
optional(number.verifying(hasKey(choices, _)))
|
||||
|
||||
private def stringIn(choices: List[(String, String)]) =
|
||||
nonEmptyText.verifying(hasKey(choices, _))
|
||||
private def stringIn(choices: Seq[(String, String)]) =
|
||||
optional(text.verifying(hasKey(choices, _)))
|
||||
|
||||
private def hasKey[A](choices: List[(A, _)], key: A) =
|
||||
private def hasKey[A](choices: Seq[(A, _)], key: A) =
|
||||
choices map (_._1) contains key
|
||||
}
|
||||
|
||||
case class SearchData(
|
||||
usernames: Option[String] = None,
|
||||
usernames: Option[String],
|
||||
variant: Option[Int],
|
||||
mode: Option[Int],
|
||||
opening: Option[String],
|
||||
turnsMin: Option[Int],
|
||||
turnsMax: Option[Int]
|
||||
turnsMax: Option[Int],
|
||||
eloMin: Option[Int],
|
||||
eloMax: Option[Int],
|
||||
hasAi: Option[Int],
|
||||
aiLevel: Option[Int],
|
||||
durationMin: Option[Int],
|
||||
durationMax: Option[Int],
|
||||
dateMin: Option[String],
|
||||
dateMax: Option[String],
|
||||
status: Option[Int]
|
||||
)
|
||||
|
|
|
@ -2,16 +2,18 @@ package lila
|
|||
package search
|
||||
|
||||
import Game.fields
|
||||
import chess.{ Variant, Mode, EcoDb }
|
||||
import chess.{ Variant, Mode, Status, EcoDb }
|
||||
|
||||
import org.elasticsearch.index.query._, FilterBuilders._, QueryBuilders._
|
||||
|
||||
case class Query(
|
||||
usernames: List[String] = Nil,
|
||||
variant: Option[Int] = None,
|
||||
status: Option[Int] = None,
|
||||
turns: Range[Int] = Range.none,
|
||||
averageElo: Range[Int] = Range.none,
|
||||
ai: Range[Int] = Range.none,
|
||||
hasAi: Option[Boolean] = None,
|
||||
aiLevel: Range[Int] = Range.none,
|
||||
rated: Option[Boolean] = None,
|
||||
opening: Option[String] = None,
|
||||
date: Range[String] = Range.none,
|
||||
|
@ -33,10 +35,17 @@ case class Query(
|
|||
duration filters fields.duration,
|
||||
date filters fields.date,
|
||||
averageElo filters fields.date,
|
||||
ai filters fields.ai,
|
||||
hasAi.toList map { a ⇒
|
||||
a.fold(
|
||||
rangeFilter(fields.ai) gt 0,
|
||||
termFilter(fields.ai, null)
|
||||
)
|
||||
},
|
||||
aiLevel filters fields.ai,
|
||||
toFilter(variant, fields.variant),
|
||||
toFilter(rated, fields.rated),
|
||||
toFilter(opening, fields.opening)
|
||||
toFilter(opening, fields.opening),
|
||||
toFilter(status, fields.status)
|
||||
).flatten
|
||||
|
||||
def toFilter(query: Option[_], name: String) =
|
||||
|
@ -48,7 +57,9 @@ case class Query(
|
|||
|
||||
object Query {
|
||||
|
||||
val durations = List(0, 1, 2, 3, 5, 10, 15, 20, 30)
|
||||
val durations = List(0, 1, 2, 3, 5, 10, 15, 20, 30) map { d ⇒
|
||||
d -> (d + " minutes")
|
||||
}
|
||||
|
||||
val variants = Variant.all map { v ⇒ v.id -> v.name }
|
||||
|
||||
|
@ -62,6 +73,26 @@ object Query {
|
|||
(1 to 5) ++ (10 to 45 by 5) ++ (50 to 90 by 10) ++ (100 to 300 by 25)
|
||||
}.toList map { t ⇒ t -> (t + " turns") }
|
||||
|
||||
val averageElos = (800 to 2300 by 100).toList map { e ⇒ e -> (e + " ELO") }
|
||||
|
||||
val hasAis = List(
|
||||
0 -> "Human opponent",
|
||||
1 -> "Computer opponent")
|
||||
|
||||
val aiLevels = (1 to 8) map { l ⇒ l -> ("Stockfish level " + l) }
|
||||
|
||||
val dates = List("0d" -> "Today") ++ {
|
||||
(1 to 6) map { d ⇒ (d + "d") -> (d + " days ago") }
|
||||
} ++ {
|
||||
(1 to 3) map { w ⇒ (w + "w") -> (w + " weeks ago") }
|
||||
} ++ {
|
||||
(1 to 6) map { m ⇒ (m + "m") -> (m + " months ago") }
|
||||
} ++ {
|
||||
(1 to 3) map { y ⇒ (y + "y") -> (y + " years ago") }
|
||||
}
|
||||
|
||||
val statuses = Status.finishedNotCheated map { s ⇒ s.id -> s.name }
|
||||
|
||||
def test = Query(
|
||||
usernames = List("thibault"),
|
||||
duration = Range(60.some, 150.some),
|
||||
|
@ -77,7 +108,8 @@ object Query {
|
|||
turns = Range(20.some, 100.some),
|
||||
averageElo = Range(1100.some, 2000.some),
|
||||
opening = "A00".some,
|
||||
ai = Range.none,
|
||||
hasAi = true.some,
|
||||
aiLevel = Range.none,
|
||||
date = Range("2011-01-01".some, none),
|
||||
sorting = Sorting(fields.date, "desc")
|
||||
)
|
||||
|
|
|
@ -11,7 +11,7 @@ menu = game.sideMenu(listMenu, "search").some) {
|
|||
<table>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="@form("usernames").id">Users</label>
|
||||
<label for="@form("usernames").id">Players</label>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
|
@ -38,6 +38,14 @@ menu = game.sideMenu(listMenu, "search").some) {
|
|||
@select(form("mode"), Query.modes, "Casual or Rated")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="@form("status").id">Result</label>
|
||||
</th>
|
||||
<td>
|
||||
@select(form("status"), Query.statuses, "Any result")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="@form("opening").id">@trans.opening()</label>
|
||||
|
@ -55,6 +63,49 @@ menu = game.sideMenu(listMenu, "search").some) {
|
|||
To @select(form("turnsMax"), Query.turns, "Any number of turns")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label>Players ELO</label>
|
||||
</th>
|
||||
<td>
|
||||
From @select(form("eloMin"), Query.averageElos, "Any ELO")
|
||||
To @select(form("eloMax"), Query.averageElos, "Any ELO")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="@form("hasAi").id">Opponent</label>
|
||||
</th>
|
||||
<td>
|
||||
@select(form("hasAi"), Query.hasAis, "Human or Computer")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="@form("aiLevel").id">Stockfish level</label>
|
||||
</th>
|
||||
<td>
|
||||
@select(form("aiLevel"), Query.aiLevels, "Any Stockfish level")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label>Duration</label>
|
||||
</th>
|
||||
<td>
|
||||
From @select(form("durationMin"), Query.durations, "Any duration")
|
||||
To @select(form("durationMax"), Query.durations, "Any duration")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label>Date</label>
|
||||
</th>
|
||||
<td>
|
||||
From @select(form("dateMin"), Query.dates, "Any date")
|
||||
To @select(form("dateMax"), Query.dates, "Any date")
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 56b2604f722084c739af8cfc821798d6d631fcbb
|
||||
Subproject commit 6fc609570941db4840e7de7c810bb2fa957b4153
|
1
todo
1
todo
|
@ -37,3 +37,4 @@ complete search engine using https://github.com/bsadeh/scalastic
|
|||
localize elo chart dates
|
||||
recognize tor IPs http://en.lichess.org/forum/staff/cheater-101#9 https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=37.59.32.99
|
||||
weird UI clock bug (+30 minutes) http://en.lichess.org/forum/lichess-feedback/game-timer-is-30-minutes-incorrectly#4
|
||||
add more system messages to the game chat http://en.lichess.org/forum/lichess-feedback/feedback-about-chat-rooms#2
|
||||
|
|
Loading…
Reference in New Issue