From c8a90693a8fb80ff322e2d94e3b8476dea219db4 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Wed, 5 Sep 2012 00:59:21 +0200 Subject: [PATCH] complete search form backbone --- app/search/DataForm.scala | 42 +++++++++++++++++-------- app/search/Query.scala | 44 ++++++++++++++++++++++---- app/views/search/form.scala.html | 53 +++++++++++++++++++++++++++++++- scalachess | 2 +- todo | 1 + 5 files changed, 122 insertions(+), 20 deletions(-) diff --git a/app/search/DataForm.scala b/app/search/DataForm.scala index aa0581897f..d154fa0dc9 100644 --- a/app/search/DataForm.scala +++ b/app/search/DataForm.scala @@ -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] ) diff --git a/app/search/Query.scala b/app/search/Query.scala index 090b3e7c69..6bde637900 100644 --- a/app/search/Query.scala +++ b/app/search/Query.scala @@ -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") ) diff --git a/app/views/search/form.scala.html b/app/views/search/form.scala.html index a83276c85e..52c2a0bd84 100644 --- a/app/views/search/form.scala.html +++ b/app/views/search/form.scala.html @@ -11,7 +11,7 @@ menu = game.sideMenu(listMenu, "search").some) { + + + + + + + + + + + + + + + + + + + + + + + +
- +
+ + + @select(form("status"), Query.statuses, "Any result") +
@@ -55,6 +63,49 @@ menu = game.sideMenu(listMenu, "search").some) { To @select(form("turnsMax"), Query.turns, "Any number of turns")
+ + + From @select(form("eloMin"), Query.averageElos, "Any ELO") + To @select(form("eloMax"), Query.averageElos, "Any ELO") +
+ + + @select(form("hasAi"), Query.hasAis, "Human or Computer") +
+ + + @select(form("aiLevel"), Query.aiLevels, "Any Stockfish level") +
+ + + From @select(form("durationMin"), Query.durations, "Any duration") + To @select(form("durationMax"), Query.durations, "Any duration") +
+ + + From @select(form("dateMin"), Query.dates, "Any date") + To @select(form("dateMax"), Query.dates, "Any date") +
diff --git a/scalachess b/scalachess index 56b2604f72..6fc6095709 160000 --- a/scalachess +++ b/scalachess @@ -1 +1 @@ -Subproject commit 56b2604f722084c739af8cfc821798d6d631fcbb +Subproject commit 6fc609570941db4840e7de7c810bb2fa957b4153 diff --git a/todo b/todo index 6f72f0b992..21db98b001 100644 --- a/todo +++ b/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