rm0193-mapreduce
Thibault Duplessis 2019-11-28 19:34:46 -06:00
parent 5a8f45ff99
commit b7a77cc3f4
48 changed files with 117 additions and 141 deletions

View File

@ -15,16 +15,16 @@ trait RequestGetter {
req.queryString get name flatMap (_.headOption) filter (_.nonEmpty)
protected def getInt(name: String)(implicit ctx: UserContext) =
get(name) flatMap parseIntOption
get(name) flatMap (_.toIntOption)
protected def getInt(name: String, req: RequestHeader): Option[Int] =
req.queryString get name flatMap (_.headOption) flatMap parseIntOption
req.queryString get name flatMap (_.headOption) flatMap (_.toIntOption)
protected def getLong(name: String)(implicit ctx: UserContext) =
get(name) flatMap parseLongOption
get(name) flatMap (_.toLongOption)
protected def getLong(name: String, req: RequestHeader) =
get(name, req) flatMap parseLongOption
get(name, req) flatMap (_.toLongOption)
protected def getBool(name: String)(implicit ctx: UserContext) =
(getInt(name) exists trueish) || (get(name) exists trueish)

View File

@ -32,14 +32,14 @@ trait StringHelper { self: NumberHelper =>
val rendered = s.render
rendered match {
case NumberFirstRegex(number, html) => frag(
strong((~parseIntOption(number)).localize),
strong((~number.toIntOption).localize),
br,
raw(html)
)
case NumberLastRegex(n) if rendered.length > n.length + 1 => frag(
raw(rendered.dropRight(n.length + 1)),
br,
strong((~parseIntOption(n)).localize)
strong((~n.toIntOption).localize)
)
case h => raw(h.replaceIf('\n', "<br>"))
}

View File

@ -110,7 +110,7 @@ lazy val evaluation = module("evaluation", Seq(
)
lazy val common = module("common", Seq()).settings(
libraryDependencies ++= provided(play.api, kamon.core, scalatags, ws, jodaForms) ++ Seq(scaffeine) ++ reactivemongo.bundle
libraryDependencies ++= provided(play.api, kamon.core, scalatags, jodaForms) ++ Seq(scaffeine) ++ reactivemongo.bundle
)
lazy val rating = module("rating", Seq(common, db, memo)).settings(

View File

@ -58,8 +58,8 @@ object Info {
def start(ply: Int) = Info(ply, Eval.initial, Nil)
private def strCp(s: String) = parseIntOption(s) map Cp.apply
private def strMate(s: String) = parseIntOption(s) map Mate.apply
private def strCp(s: String) = s.toIntOption map Cp.apply
private def strMate(s: String) = s.toIntOption map Mate.apply
private def decode(ply: Int, str: String): Option[Info] = str.split(separator) match {
case Array() => Info(ply, Eval.empty).some

View File

@ -77,7 +77,7 @@ sealed trait Context extends lila.user.UserContextWrapper {
def requiresFingerprint = isAuth && !pageData.hasFingerprint
def zoom: Int = {
req.session get "zoom2" flatMap parseIntOption map (_ - 100) filter (0 <=) filter (100 >=)
req.session get "zoom2" flatMap (_.toIntOption) map (_ - 100) filter (0 <=) filter (100 >=)
} | 85
}

View File

@ -56,8 +56,8 @@ object Mobile {
def requestVersion(req: RequestHeader): Option[ApiVersion] = {
(req.headers.get(HeaderNames.ACCEPT), req.path) match {
case (Some(HeaderPattern(v)), _) => parseIntOption(v) map ApiVersion.apply
case (_, PathPattern(v)) => parseIntOption(v) map ApiVersion.apply
case (Some(HeaderPattern(v)), _) => v.toIntOption map ApiVersion.apply
case (_, PathPattern(v)) => v.toIntOption map ApiVersion.apply
case _ => none
}
} filter acceptedVersions.contains

View File

@ -18,16 +18,16 @@ object Youtube {
private def parseSeconds(text: String) = text match {
case HourMinSecRegex(hourS, minS, secS) => for {
hour <- parseIntOption(hourS)
min <- parseIntOption(minS)
sec <- parseIntOption(secS)
hour <- hourS.toIntOption
min <- minS.toIntOption
sec <- secS.toIntOption
} yield 3600 * hour + 60 * min + sec
case MinSecRegex(minS, secS) => for {
min <- parseIntOption(minS)
sec <- parseIntOption(secS)
min <- minS.toIntOption
sec <- secS.toIntOption
} yield 60 * min + sec
case SecRegex(secS) => for {
sec <- parseIntOption(secS)
sec <- secS.toIntOption
} yield sec
case _ => None
}

View File

@ -1,6 +1,7 @@
package lila.common
import scala.concurrent.duration._
import scala.concurrent.{ Future => ScalaFu }
object Future {
@ -19,9 +20,11 @@ object Future {
}
}
def filter[A](list: List[A])(f: A => Fu[Boolean]): Fu[List[A]] = list.map {
element => f(element) dmap (_ option element)
}.sequenceFu.dmap(_.flatten)
def filter[A](list: List[A])(f: A => Fu[Boolean]): Fu[List[A]] = ScalaFu.sequence {
list.map {
element => f(element) dmap (_ option element)
}
}.dmap(_.flatten)
def filterNot[A](list: List[A])(f: A => Fu[Boolean]): Fu[List[A]] =
filter(list)(a => !f(a))

View File

@ -42,8 +42,6 @@ trait Lilaisms
@inline implicit def toPimpedFutureBoolean(f: Fu[Boolean]) = new PimpedFutureBoolean(f)
@inline implicit def toPimpedFutureOption[A](f: Fu[Option[A]]) = new PimpedFutureOption(f)
@inline implicit def toPimpedFutureValid[A](f: Fu[Valid[A]]) = new PimpedFutureValid(f)
@inline implicit def toPimpedIterableFuture[A, M[X] <: IterableOnce[X]](t: M[Fu[A]]) =
new PimpedIterableFuture(t)
@inline implicit def toPimpedJsObject(jo: JsObject) = new PimpedJsObject(jo)
@inline implicit def toPimpedJsValue(jv: JsValue) = new PimpedJsValue(jv)

View File

@ -38,22 +38,6 @@ trait PackageObject extends Lilaisms {
def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x)
}
@deprecated
def parseIntOption(str: String): Option[Int] =
str.toIntOption
@deprecated
def parseFloatOption(str: String): Option[Float] =
Try(java.lang.Float.parseFloat(str)).toOption
@deprecated
def parseLongOption(str: String): Option[Long] =
Try(java.lang.Long.parseLong(str)).toOption
@deprecated
def parseDoubleOption(str: String): Option[Double] =
Try(java.lang.Double.parseDouble(str)).toOption
def intBox(in: Range.Inclusive)(v: Int): Int =
math.max(in.start, math.min(v, in.end))

View File

@ -2,6 +2,7 @@ package lila.base
import LilaTypes._
import ornicar.scalalib.Zero
import scala.collection.BuildFrom
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{ Future, ExecutionContext }
@ -175,10 +176,3 @@ final class PimpedFutureValid[A](private val fua: Fu[Valid[A]]) extends AnyVal {
_.fold[Fu[A]](fufail(_), fuccess(_))
}(ExecutionContext.parasitic)
}
final class PimpedIterableFuture[A, M[X] <: IterableOnce[X]](private val t: M[Fu[A]]) extends AnyVal {
import scala.collection.generic.CanBuildFrom
def sequenceFu(implicit cbf: CanBuildFrom[M[Fu[A]], A, M[A]]): Fu[M[A]] =
Future.sequence(t)
}

View File

@ -30,7 +30,7 @@ trait AdapterLike[A] {
def slice(offset: Int, length: Int) =
AdapterLike.this.slice(offset, length) flatMap { results =>
results.map(f).sequenceFu
scala.concurrent.Future sequence results.map(f)
}
}

View File

@ -60,7 +60,7 @@ final class Paginator[A] private[paginator] (
withCurrentPageResults(currentPageResults map f)
def mapFutureResults[B](f: A => Fu[B]): Fu[Paginator[B]] =
currentPageResults.map(f).sequenceFu map withCurrentPageResults
scala.concurrent.Future.sequence(currentPageResults.map(f)) map withCurrentPageResults
}
object Paginator {

View File

@ -17,8 +17,8 @@ private object BSONHandlers {
implicit val PvsHandler = new BSONHandler[BSONString, NonEmptyList[Pv]] {
private def scoreWrite(s: Score): String = s.value.fold(_.value.toString, m => s"#${m.value}")
private def scoreRead(str: String): Option[Score] =
if (str startsWith "#") parseIntOption(str drop 1) map { m => Score mate Mate(m) }
else parseIntOption(str) map { c => Score cp Cp(c) }
if (str startsWith "#") str.drop(1).toIntOption map { m => Score mate Mate(m) }
else str.toIntOption map { c => Score cp Cp(c) }
private def movesWrite(moves: Moves): String = Uci writeListPiotr moves.value.toList
private def movesRead(str: String): Option[Moves] =
Uci readListPiotr str flatMap (_.toNel) map Moves.apply
@ -45,7 +45,7 @@ private object BSONHandlers {
def read(bs: BSONString): Id = bs.value split ':' match {
case Array(fen) => Id(chess.variant.Standard, SmallFen raw fen)
case Array(variantId, fen) => Id(
parseIntOption(variantId) flatMap chess.variant.Variant.apply err s"Invalid evalcache variant $variantId",
variantId.toIntOption flatMap chess.variant.Variant.apply err s"Invalid evalcache variant $variantId",
SmallFen raw fen
)
case _ => sys error s"Invalid evalcache id ${bs.value}"

View File

@ -29,7 +29,7 @@ final class FishnetRedis(
case Array(gameId, plyS, uci) => for {
move <- Uci(uci)
ply <- parseIntOption(plyS)
ply <- plyS.toIntOption
} Bus.publish(Tell(gameId, FishnetPlay(move, ply)), 'roundMapTell)
case _ =>
}

View File

@ -53,8 +53,8 @@ object JsonApi {
threads: Option[String],
hash: Option[String]
) {
def threadsInt = threads flatMap parseIntOption
def hashInt = hash flatMap parseIntOption
def threadsInt = threads flatMap (_.toIntOption)
def hashInt = hash flatMap (_.toIntOption)
}
case class Acquire(

View File

@ -61,7 +61,7 @@ case class Player(
def withName(name: String) = copy(name = name.some)
def nameSplit: Option[(String, Option[Int])] = name map {
case Player.nameSplitRegex(n, r) => n -> parseIntOption(r)
case Player.nameSplitRegex(n, r) => n -> r.toIntOption
case n => n -> none
}

View File

@ -48,7 +48,7 @@ object History {
private[history] implicit val RatingsMapReader = new BSONDocumentReader[RatingsMap] {
def read(doc: BSONDocument): RatingsMap = doc.stream.flatMap {
case scala.util.Success(BSONElement(k, BSONInteger(v))) => parseIntOption(k) map (_ -> v)
case scala.util.Success(BSONElement(k, BSONInteger(v))) => k.toIntOption map (_ -> v)
case _ => none[(Int, Int)]
}.toList sortBy (_._1)
}

View File

@ -4,7 +4,7 @@ import com.github.benmanes.caffeine.cache._
import ornicar.scalalib.Zero
import java.util.concurrent.TimeUnit
import scala.collection.JavaConverters._
import scala.jdk.CollectionConverters._
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.Promise

View File

@ -2,8 +2,14 @@ package lila.hub
import akka.actor._
import com.typesafe.config.Config
import play.api.Configuration
final class Env(config: Config, system: ActorSystem) {
final class Env(
appConfig: Configuration,
system: ActorSystem
) {
val config = appConfig.get[Config]("hub")
val gameSearch = select("actor.game.search")
val renderer = select("actor.renderer")
@ -23,11 +29,3 @@ final class Env(config: Config, system: ActorSystem) {
private def select(name: String) =
system.actorSelection("/user/" + config.getString(name))
}
object Env {
lazy val current = "hub" boot new Env(
config = lila.common.PlayApp loadConfig "hub",
system = lila.common.PlayApp.system
)
}

View File

@ -4,7 +4,7 @@ import com.github.benmanes.caffeine.cache._
import ornicar.scalalib.Zero
import java.util.concurrent.TimeUnit
import scala.collection.JavaConverters._
import scala.jdk.CollectionConverters._
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.Promise

View File

@ -128,20 +128,20 @@ object Dimension {
}
def valueByKey[X](d: Dimension[X], key: String): Option[X] = d match {
case Period => parseIntOption(key) map lila.insight.Period.apply
case Period => key.toIntOption map lila.insight.Period.apply
case Date => None
case Perf => PerfType.byKey get key
case Phase => parseIntOption(key) flatMap lila.insight.Phase.byId.get
case Result => parseIntOption(key) flatMap lila.insight.Result.byId.get
case Termination => parseIntOption(key) flatMap lila.insight.Termination.byId.get
case Phase => key.toIntOption flatMap lila.insight.Phase.byId.get
case Result => key.toIntOption flatMap lila.insight.Result.byId.get
case Termination => key.toIntOption flatMap lila.insight.Termination.byId.get
case Color => chess.Color(key)
case Opening => EcopeningDB.allByEco get key
case OpponentStrength => parseIntOption(key) flatMap RelativeStrength.byId.get
case OpponentStrength => key.toIntOption flatMap RelativeStrength.byId.get
case PieceRole => chess.Role.all.find(_.name == key)
case MovetimeRange => parseIntOption(key) flatMap lila.insight.MovetimeRange.byId.get
case MyCastling | OpCastling => parseIntOption(key) flatMap lila.insight.Castling.byId.get
case MovetimeRange => key.toIntOption flatMap lila.insight.MovetimeRange.byId.get
case MyCastling | OpCastling => key.toIntOption flatMap lila.insight.Castling.byId.get
case QueenTrade => lila.insight.QueenTrade(key == "true").some
case MaterialRange => parseIntOption(key) flatMap lila.insight.MaterialRange.byId.get
case MaterialRange => key.toIntOption flatMap lila.insight.MaterialRange.byId.get
}
def valueToJson[X](d: Dimension[X])(v: X): play.api.libs.json.JsObject = {

View File

@ -65,7 +65,7 @@ object SettingStore {
case "off" | "no" | "false" | "0" => false.some
case _ => none
})
implicit val intReader = new StringReader[Int](parseIntOption)
implicit val intReader = new StringReader[Int](_.toIntOption)
implicit val stringReader = new StringReader[String](some)
def fromIso[A](iso: lila.common.Iso[String, A]) = new StringReader[A](v => iso.from(v).some)
}

View File

@ -23,14 +23,14 @@ object PracticeGoal {
def apply(chapter: lila.study.Chapter): PracticeGoal =
chapter.tags(_.Termination).map(v => MultiSpaceR.replaceAllIn(v.trim, " ")).flatMap {
case MateR() => Mate.some
case MateInR(movesStr) => parseIntOption(movesStr) map MateIn.apply
case DrawInR(movesStr) => parseIntOption(movesStr) map DrawIn.apply
case EqualInR(movesStr) => parseIntOption(movesStr) map EqualIn.apply
case MateInR(movesStr) => movesStr.toIntOption map MateIn.apply
case DrawInR(movesStr) => movesStr.toIntOption map DrawIn.apply
case EqualInR(movesStr) => movesStr.toIntOption map EqualIn.apply
case EvalInR(cpStr, movesStr) => for {
cp <- parseIntOption(cpStr)
moves <- parseIntOption(movesStr)
cp <- cpStr.toIntOption
moves <- movesStr.toIntOption
} yield EvalIn(cp, moves)
case PromotionR(cpStr) => parseIntOption(cpStr) map Promotion.apply
case PromotionR(cpStr) => cpStr.toIntOption map Promotion.apply
case _ => none
} | Mate // default to mate
}

View File

@ -1,7 +1,7 @@
package lila.push
import akka.actor._
import collection.JavaConverters._
import scala.jdk.CollectionConverters._
import com.google.auth.oauth2.{ GoogleCredentials, ServiceAccountCredentials }
import com.typesafe.config.Config
import play.api.Play

View File

@ -83,7 +83,7 @@ final class Env(
def cli = new lila.common.Cli {
def process = {
case "puzzle" :: "disable" :: id :: Nil => parseIntOption(id) ?? { id =>
case "puzzle" :: "disable" :: id :: Nil => id.toIntOption ?? { id =>
api.puzzle disable id inject "Done"
}
}

View File

@ -23,7 +23,7 @@ case class Puzzle(
// ply after "initial move" when we start solving
def initialPly: Int = {
fen.split(' ').lastOption flatMap parseIntOption map { move =>
fen.split(' ').lastOption flatMap (_.toIntOption) map { move =>
move * 2 - color.fold(0, 1)
}
} | 0

View File

@ -19,7 +19,7 @@ object RatingFactor {
s.split(separator).toList.map(_.trim.split('=')) flatMap {
case Array(ptk, fs) => for {
pt <- PerfType(ptk)
f <- parseDoubleOption(fs)
f <- fs.toDoubleOption
} yield pt -> RatingFactor(f)
case _ => None
} toMap

View File

@ -28,9 +28,9 @@ object RatingRange {
// ^\d{3,4}\-\d{3,4}$
def apply(from: String): Option[RatingRange] = for {
min <- parseIntOption(from takeWhile ('-' !=))
min <- from.takeWhile('-' !=).toIntOption
if acceptable(min)
max <- parseIntOption(from dropWhile ('-' !=) tail)
max <- from.dropWhile('-' !=).tail.toIntOption
if acceptable(max)
if min < max
} yield RatingRange(min, max)

View File

@ -104,7 +104,7 @@ object Relay {
case class Upstream(url: String) extends AnyVal {
def isLocal = url.contains("://127.0.0.1") || url.contains("://localhost")
def withRound = url.split(" ", 2) match {
case Array(u, round) => UpstreamWithRound(u, parseIntOption(round))
case Array(u, round) => UpstreamWithRound(u, round.toIntOption)
case _ => UpstreamWithRound(url, none)
}
}

View File

@ -208,7 +208,7 @@ private object RelayFetch {
val strMoves = moves.map(_ split ' ') map { move =>
chess.format.pgn.Move(
san = ~move.headOption,
secondsLeft = move.lift(1).map(_.takeWhile(_.isDigit)) flatMap parseIntOption
secondsLeft = move.lift(1).map(_.takeWhile(_.isDigit)) flatMap (_.toIntOption)
)
} mkString " "
s"${extraTags}\n\n$strMoves"

View File

@ -208,8 +208,8 @@ object RoundSocket {
case "r/bye" => Bye(Game.FullId(raw.args)).some
case "r/hold" => raw.get(4) {
case Array(fullId, ip, meanS, sdS) => for {
mean <- parseIntOption(meanS)
sd <- parseIntOption(sdS)
mean <- meanS.toIntOption
sd <- sdS.toIntOption
} yield HoldAlert(FullId(fullId), IpAddress(ip), mean, sd)
}
case "r/report" => raw.get(4) {
@ -228,7 +228,7 @@ object RoundSocket {
private def centis(s: String): Option[Centis] =
if (s == "-") none
else parseIntOption(s) map Centis.apply
else s.toIntOption map Centis.apply
private def readColor(s: String) =
if (s == "w") Some(White)

View File

@ -1,6 +1,7 @@
package lila.search
import play.api.libs.json._
import play.api.libs.ws._
sealed trait ESClient {
@ -18,14 +19,12 @@ sealed trait ESClient {
}
final class ESClientHttp(
endpoint: String,
val index: Index,
writeable: Boolean
ws: WSClient,
config: SearchConfig,
val index: Index
) extends ESClient {
import play.api.libs.ws.WS
import play.api.Play.current
def store(id: Id, doc: JsObject) = writeable ?? monitor("store") {
def store(id: Id, doc: JsObject) = config.writeable ?? monitor("store") {
HTTP(s"store/${index.name}/${id.value}", doc)
}
@ -37,10 +36,10 @@ final class ESClientHttp(
HTTP(s"count/${index.name}", query, CountResponse.apply)
}
def deleteById(id: lila.search.Id) = writeable ??
def deleteById(id: lila.search.Id) = config.writeable ??
HTTP(s"delete/id/${index.name}/${id.value}", Json.obj())
def deleteByIds(ids: List[lila.search.Id]) = writeable ??
def deleteByIds(ids: List[lila.search.Id]) = config.writeable ??
HTTP(s"delete/ids/${index.name}", Json.obj("ids" -> ids.map(_.value)))
def putMapping =
@ -55,7 +54,7 @@ final class ESClientHttp(
HTTP(s"refresh/${index.name}", Json.obj())
private[search] def HTTP[D: Writes, R](url: String, data: D, read: String => R): Fu[R] =
WS.url(s"$endpoint/$url").post(Json toJson data) flatMap {
ws.url(s"${config.endpoint}/$url").post(Json toJson data) flatMap {
case res if res.status == 200 => fuccess(read(res.body))
case res => fufail(s"$url ${res.status}")
}

View File

@ -1,28 +1,21 @@
package lila.search
import akka.actor.ActorSystem
import com.typesafe.config.Config
import com.softwaremill.macwire._
import io.methvin.play.autoconfig._
import play.api.Configuration
import play.api.libs.ws._
final class Env(
config: Config,
appConfig: Configuration,
system: ActorSystem,
scheduler: lila.common.Scheduler
ws: WSClient
) {
val config = appConfig.get[SearchConfig]("search")(AutoConfig.loader)
private val Enabled = config getBoolean "enabled"
private val Writeable = config getBoolean "writeable"
private val Endpoint = config getString "endpoint"
def makeHttp(index: Index): ESClientHttp = wire[ESClientHttp]
val makeClient = (index: Index) =>
if (Enabled) new ESClientHttp(Endpoint, index, Writeable)
else new ESClientStub
}
object Env {
lazy val current = "search" boot new Env(
config = lila.common.PlayApp loadConfig "search",
system = lila.common.PlayApp.system,
scheduler = lila.common.PlayApp.scheduler
)
if (config.enabled) makeHttp(index)
else wire[ESClientStub]
}

View File

@ -17,5 +17,5 @@ object SearchResponse {
case class CountResponse(count: Int) extends AnyVal
object CountResponse {
def apply(txt: String): CountResponse = CountResponse(~parseIntOption(txt))
def apply(txt: String): CountResponse = CountResponse(~txt.toIntOption)
}

View File

@ -7,4 +7,10 @@ package object search extends PackageObject {
val format = "YYYY-MM-dd HH:mm:ss"
val formatter: DateTimeFormatter = DateTimeFormat forPattern format
}
case class SearchConfig(
enabled: Boolean,
writeable: Boolean,
endpoint: String
)
}

View File

@ -23,7 +23,7 @@ final class IpIntel(asyncCache: lila.memo.AsyncCache.Builder, contactEmail: Emai
f = ip => {
val url = s"https://check.getipintel.net/check.php?ip=$ip&contact=${contactEmail.value}"
WS.url(url).get().map(_.body).mon(_.security.proxy.request.time).flatMap { str =>
parseFloatOption(str).fold[Fu[Int]](fufail(s"Invalid ratio ${str.take(140)}")) { ratio =>
str.toFloatOption.fold[Fu[Int]](fufail(s"Invalid ratio ${str.take(140)}")) { ratio =>
if (ratio < 0) fufail(s"IpIntel error $ratio on $url")
else fuccess((ratio * 100).toInt)
}

View File

@ -29,6 +29,6 @@ private object LoginToken {
object DateStr {
def toStr(date: DateTime) = date.getMillis.toString
def toDate(str: String) = parseLongOption(str) map { new DateTime(_) }
def toDate(str: String) = str.toLongOption map { new DateTime(_) }
}
}

View File

@ -169,17 +169,17 @@ object RemoteSocket {
}.some
case "disconnect/sris" => DisconnectSris(commas(raw.args) map Sri.apply).some
case "notified/batch" => NotifiedBatch(commas(raw.args)).some
case "lag" => raw.all |> { s => s lift 1 flatMap parseIntOption map Centis.apply map { Lag(s(0), _) } }
case "lag" => raw.all |> { s => s lift 1 flatMap (_.toIntOption) map Centis.apply map { Lag(s(0), _) } }
case "lags" => Lags(commas(raw.args).flatMap {
_ split ':' match {
case Array(user, l) => parseIntOption(l) map { lag => user -> Centis(lag) }
case Array(user, l) => l.toIntOption map { lag => user -> Centis(lag) }
case _ => None
}
}.toMap).some
case "friends/batch" => FriendsBatch(commas(raw.args)).some
case "tell/sri" => raw.get(3)(tellSriMapper)
case "req/response" => raw.get(2) {
case Array(reqId, response) => parseIntOption(reqId) map { ReqResponse(_, response) }
case Array(reqId, response) => reqId.toIntOption map { ReqResponse(_, response) }
}
case "boot" => WsBoot.some
case _ => none

View File

@ -32,9 +32,9 @@ private[study] object CommentParser {
private type ClockAndComment = (Option[Centis], String)
private def readCentis(hours: String, minutes: String, seconds: String): Option[Centis] = for {
h <- parseIntOption(hours)
m <- parseIntOption(minutes)
cs <- parseDoubleOption(seconds) match {
h <- hours.toIntOption
m <- minutes.toIntOption
cs <- seconds.toDoubleOption match {
case Some(s) => Some(Maths.roundAt(s * 100, 0).toInt)
case _ => none
}

View File

@ -14,7 +14,7 @@ private final class PgnFetch {
private val ChessbaseRegex = """chessgames\.com/.*[\?&]gid=(\d+)""".r.unanchored
def fromUrl(url: String): Fu[Option[Pgn]] = url match {
case ChessbaseRegex(id) => parseIntOption(id) ?? downloadChessbase
case ChessbaseRegex(id) => id.toIntOption ?? downloadChessbase
case _ => fuccess(none)
}

View File

@ -117,8 +117,8 @@ object StudyMultiBoard {
wName <- tags(_.White)
bName <- tags(_.Black)
} yield Color.Map(
white = Player(wName, tags(_.WhiteTitle), tags(_.WhiteElo) flatMap parseIntOption),
black = Player(bName, tags(_.BlackTitle), tags(_.BlackElo) flatMap parseIntOption)
white = Player(wName, tags(_.WhiteTitle), tags(_.WhiteElo) flatMap (_.toIntOption)),
black = Player(bName, tags(_.BlackTitle), tags(_.BlackElo) flatMap (_.toIntOption))
)
}
}

View File

@ -106,7 +106,7 @@ object DataForm {
val validVariants = List(Standard, Chess960, KingOfTheHill, ThreeCheck, Antichess, Atomic, Horde, RacingKings, Crazyhouse)
def guessVariant(from: String): Option[Variant] = validVariants.find { v =>
v.key == from || parseIntOption(from).exists(v.id ==)
v.key == from || from.toIntOption.exists(v.id ==)
}
def startingPosition(fen: String, variant: Variant): StartingPosition =

View File

@ -49,8 +49,8 @@ object Title {
private val NewFideProfileUrlRegex = """(?:https?://)ratings\.fide\.com/profile/(\d+)""".r
def apply(url: String): Fu[Option[Title]] = url.trim match {
case FideProfileUrlRegex(id) => parseIntOption(id) ?? fromFideProfile
case NewFideProfileUrlRegex(id) => parseIntOption(id) ?? fromFideProfile
case FideProfileUrlRegex(id) => id.toIntOption ?? fromFideProfile
case NewFideProfileUrlRegex(id) => id.toIntOption ?? fromFideProfile
case _ => fuccess(none)
}

View File

@ -89,7 +89,7 @@ object Sheet {
def youtubeId = `gsx$youtubeid`.toString.trim
def author = `gsx$youtubeauthor`.toString.trim
def title = `gsx$title`.toString.trim
def targets = `gsx$target`.toString.split(';').map(_.trim).toList flatMap parseIntOption
def targets = `gsx$target`.toString.split(';').map(_.trim).toList flatMap (_.toIntOption)
def tags = `gsx$tags`.toString.split(';').map(_.trim.toLowerCase).toList.filter(_.nonEmpty) ::: {
if (targets contains 1) List("beginner")
else if (targets contains 3) List("advanced")
@ -98,6 +98,6 @@ object Sheet {
def lang = `gsx$language`.toString.trim
def ads = `gsx$ads`.toString.trim == "yes"
def include = `gsx$include`.toString.trim == "yes"
def startTime = ~parseIntOption(`gsx$starttimeinseconds`.toString.trim)
def startTime = ~`gsx$starttimeinseconds`.toString.trim.toIntOption
}
}

View File

@ -24,9 +24,9 @@ private[video] final class Youtube(
def updateAll: Funit = fetch flatMap { entries =>
entries.map { entry =>
api.video.setMetadata(entry.id, Metadata(
views = ~parseIntOption(entry.statistics.viewCount),
likes = ~parseIntOption(entry.statistics.likeCount) -
~parseIntOption(entry.statistics.dislikeCount),
views = ~entry.statistics.viewCount.toIntOption,
likes = ~entry.statistics.likeCount.toIntOption -
~entry.statistics.dislikeCount.toIntOption,
description = entry.snippet.description,
duration = Some(entry.contentDetails.seconds),
publishedAt = entry.snippet.publishedAt.flatMap { at =>

View File

@ -1,5 +1,5 @@
import com.typesafe.sbt.SbtScalariform.autoImport.scalariformPreferences
import play.sbt.Play.autoImport._
import play.sbt.PlayImport._
import sbt._, Keys._
import scalariform.formatter.preferences._
@ -27,7 +27,7 @@ object BuildSettings {
.setPreference(DanglingCloseParenthesis, Force)
.setPreference(DoubleIndentConstructorArguments, true)
def defaultDeps = Seq(scalaz, chess, scalalib, jodaTime, macwire) // , specs2, specs2Scalaz)
def defaultDeps = Seq(scalaz, chess, scalalib, jodaTime, ws, macwire, autoconfig) // , specs2, specs2Scalaz)
def compile(deps: ModuleID*): Seq[ModuleID] = deps map (_ % "compile")
def provided(deps: ModuleID*): Seq[ModuleID] = deps map (_ % "provided")

View File

@ -43,6 +43,7 @@ object Dependencies {
val epoll = "io.netty" % "netty-transport-native-epoll" % "4.1.43.Final" classifier "linux-x86_64"
val markdown = "com.vladsch.flexmark" % "flexmark-all" % "0.59.58"
val macwire = "com.softwaremill.macwire" %% "macros" % "2.3.3" % "provided"
val autoconfig = "io.methvin.play" %% "autoconfig-macros" % "0.3.0"
object reactivemongo {
val version = "0.19.1"