forked from lichess-org/lila
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DataForm.scala
110 lines (98 loc) · 3.89 KB
/
DataForm.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package lila.gameSearch
import chess.{ Mode }
import com.github.nscala_time.time.Imports._
import org.joda.time.DateTime
import play.api.data._
import play.api.data.Forms._
import lila.common.Form._
import lila.search.Range
private[gameSearch] final class DataForm {
val search = Form(mapping(
"players" -> mapping(
"a" -> optional(nonEmptyText),
"b" -> optional(nonEmptyText),
"winner" -> optional(nonEmptyText)
)(SearchPlayer.apply)(SearchPlayer.unapply),
"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)),
"ratingMin" -> optional(numberIn(Query.averageRatings)),
"ratingMax" -> optional(numberIn(Query.averageRatings)),
"hasAi" -> optional(numberIn(Query.hasAis)),
"aiLevelMin" -> optional(numberIn(Query.aiLevels)),
"aiLevelMax" -> optional(numberIn(Query.aiLevels)),
"durationMin" -> optional(numberIn(Query.durations)),
"durationMax" -> optional(numberIn(Query.durations)),
"dateMin" -> optional(stringIn(Query.dates)),
"dateMax" -> optional(stringIn(Query.dates)),
"status" -> optional(numberIn(Query.statuses)),
"analysed" -> optional(numberIn(Query.analyseds :: Nil)),
"sort" -> mapping(
"field" -> stringIn(Sorting.fields),
"order" -> stringIn(Sorting.orders)
)(SearchSort.apply)(SearchSort.unapply)
)(SearchData.apply)(SearchData.unapply)) fill SearchData()
}
private[gameSearch] case class SearchData(
players: SearchPlayer = SearchPlayer(),
variant: Option[Int] = None,
mode: Option[Int] = None,
opening: Option[String] = None,
turnsMin: Option[Int] = None,
turnsMax: Option[Int] = None,
ratingMin: Option[Int] = None,
ratingMax: Option[Int] = None,
hasAi: Option[Int] = None,
aiLevelMin: Option[Int] = None,
aiLevelMax: Option[Int] = None,
durationMin: Option[Int] = None,
durationMax: Option[Int] = None,
dateMin: Option[String] = None,
dateMax: Option[String] = None,
status: Option[Int] = None,
analysed: Option[Int] = None,
sort: SearchSort = SearchSort()) {
lazy val query = Query(
user1 = players.cleanA,
user2 = players.cleanB,
winner = players.cleanWinner,
variant = variant,
rated = mode flatMap Mode.apply map (_.rated),
opening = opening map (_.trim.toLowerCase),
turns = Range(turnsMin, turnsMax),
averageRating = Range(ratingMin, ratingMax),
hasAi = hasAi map (_ == 1),
aiLevel = Range(aiLevelMin, aiLevelMax),
duration = Range(durationMin, durationMax),
date = Range(dateMin flatMap toDate, dateMax flatMap toDate),
status = status,
analysed = analysed map (_ == 1),
sorting = Sorting(sort.field, sort.order))
def nonEmptyQuery = query.nonEmpty option query
private val DateDelta = """^(\d+)(\w)$""".r
private def toDate(delta: String): Option[DateTime] = delta match {
case DateDelta(n, "h") => parseIntOption(n) map (DateTime.now - _.hours)
case DateDelta(n, "d") => parseIntOption(n) map (DateTime.now - _.days)
case DateDelta(n, "w") => parseIntOption(n) map (DateTime.now - _.weeks)
case DateDelta(n, "m") => parseIntOption(n) map (DateTime.now - _.months)
case DateDelta(n, "y") => parseIntOption(n) map (DateTime.now - _.years)
case _ => None
}
}
private[gameSearch] case class SearchPlayer(
a: Option[String] = None,
b: Option[String] = None,
winner: Option[String] = None) {
def cleanA = clean(a)
def cleanB = clean(b)
def cleanWinner = clean(winner) |> { w =>
w filter List(cleanA, cleanB).flatten.contains
}
private def clean(s: Option[String]) =
s map (_.trim.toLowerCase) filter (_.nonEmpty)
}
private[gameSearch] case class SearchSort(
field: String = Sorting.default.field,
order: String = Sorting.default.order)