Skip to content

Commit

Permalink
Merge branch 'master' into round-training-1
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar authored Dec 25, 2024
2 parents 45184ed + 132db2f commit 890ff80
Show file tree
Hide file tree
Showing 192 changed files with 2,587 additions and 846 deletions.
4 changes: 2 additions & 2 deletions app/controllers/Streamer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ final class Streamer(env: Env, apiC: => Api) extends LilaController(env):
.update(sws.streamer, data, isGranted(_.Streamers))
.flatMap:
case Some(change) =>
if change.decline then logApi.streamerDecline(s.user.id)
if change.decline then logApi.streamerDecline(s.user.id, change.reason)
change.list.foreach { logApi.streamerList(s.user.id, _) }
change.tier.foreach { logApi.streamerTier(s.user.id, _) }
if data.approval.flatMap(_.quick).isDefined
if data.approval.quick.isDefined
then
env.streamer.pager.nextRequestId.map: nextId =>
Redirect:
Expand Down
2 changes: 1 addition & 1 deletion conf/base.conf
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ push {
subscription = push_subscription
}
web {
vapid_public_key = "BGr5CL0QlEYa7qW7HLqe7DFkCeTsYMLsi1Db+5Vwt1QBIs6+WxN8066AjtP8S9u+w+CbleE8xWY+qQaNEMs7sAs="
vapid_public_key = "BGr5CL0QlEYa7qW7HLqe7DFkCeTsYMLsi1Db-5Vwt1QBIs6-WxN8066AjtP8S9u-w-CbleE8xWY-qQaNEMs7sAs"
url = "http://push.lichess.ovh:9054"
}
firebase {
Expand Down
26 changes: 15 additions & 11 deletions modules/analyse/src/main/AccuracyPercent.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package lila.analyse

import chess.{ ByColor, Color }
import chess.eval.WinPercent
import chess.eval.Eval.{ Cp, Mate }
import scalalib.Maths
import scalalib.model.Percent

import lila.core.data.Percent
import lila.core.game.SideAndStart
import lila.tree.{ Analysis, Eval, WinPercent }
import lila.tree.{ Analysis, Eval }

// Quality of a move, based on previous and next WinPercent
opaque type AccuracyPercent = Double
Expand Down Expand Up @@ -55,15 +57,17 @@ for x in xs:
def fromEvalsAndPov(pov: SideAndStart, evals: List[Eval]): List[AccuracyPercent] =
val subjectiveEvals = pov.color.fold(evals, evals.map(_.invert))
val alignedEvals =
if pov.color == pov.startColor then Eval.initial :: subjectiveEvals else subjectiveEvals
if pov.color == pov.startColor
then lila.tree.evals.initial :: subjectiveEvals
else subjectiveEvals
alignedEvals
.grouped(2)
.collect { case List(e1, e2) =>
for
before <- WinPercent.fromEval(e1)
after <- WinPercent.fromEval(e2)
yield AccuracyPercent.fromWinPercents(before, after)
}
.collect:
case List(e1, e2) =>
for
before <- e1.score.map(WinPercent.fromScore)
after <- e2.score.map(WinPercent.fromScore)
yield AccuracyPercent.fromWinPercents(before, after)
.flatten
.toList

Expand All @@ -74,8 +78,8 @@ for x in xs:
gameAccuracy(startColor, analysis.infos.map(_.eval).flatMap(_.forceAsCp))

// a mean of volatility-weighted mean and harmonic mean
def gameAccuracy(startColor: Color, cps: List[Eval.Cp]): Option[ByColor[AccuracyPercent]] =
val allWinPercents = (Eval.Cp.initial :: cps).map(WinPercent.fromCentiPawns)
def gameAccuracy(startColor: Color, cps: List[Cp]): Option[ByColor[AccuracyPercent]] =
val allWinPercents = (Cp.initial :: cps).map(WinPercent.fromCentiPawns)
val windowSize = (cps.size / 10).atLeast(2).atMost(8)
val allWinPercentValues = WinPercent.raw(allWinPercents)
val windows =
Expand Down
2 changes: 1 addition & 1 deletion modules/analyse/src/main/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package lila.analyse

export lila.core.lilaism.Lilaism.{ *, given }
export lila.common.extensions.*
export lila.tree.{ Advice, Analysis, Info, WinPercent }
export lila.tree.{ Advice, Analysis, Info }
3 changes: 1 addition & 2 deletions modules/analyse/src/test/AccuracyPercentTest.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package lila.analyse

import chess.{ ByColor, Color }
import chess.eval.Eval.Cp
import scalalib.Maths.isCloseTo

import lila.tree.Eval.Cp

class AccuracyPercentTest extends munit.FunSuite:

import AccuracyPercent.*
Expand Down
4 changes: 2 additions & 2 deletions modules/common/src/main/mon.scala
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ object mon:
timer("relay.fetch.time").withTags(relay(official, id, slug))
def syncTime(official: Boolean, id: RelayTourId, slug: String) =
timer("relay.sync.time").withTags(relay(official, id, slug))
def httpGet(host: String, proxy: Option[String]) =
future("relay.http.get", tags("host" -> host, "proxy" -> proxy.getOrElse("none")))
def httpGet(code: Int, host: String, proxy: Option[String]) = timer("relay.http.get").withTags:
tags("code" -> code, "host" -> host, "proxy" -> proxy.getOrElse("none"))
val dedup = counter("relay.fetch.dedup").withoutTags()
def etag(hit: "hit" | "miss" | "first") = counter("relay.fetch.etag").withTag("hit", hit)

Expand Down
9 changes: 0 additions & 9 deletions modules/core/src/main/data.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ object data:

trait OpaqueInstant[A](using A =:= Instant) extends TotalWrapper[A, Instant]

trait Percent[A]:
def value(a: A): Double
def apply(a: Double): A
object Percent:
def of[A](w: TotalWrapper[A, Double]): Percent[A] = new:
def apply(a: Double): A = w(a)
def value(a: A): Double = w.value(a)
def toInt[A](a: A)(using p: Percent[A]): Int = Math.round(p.value(a)).toInt // round to closest

opaque type RichText = String
object RichText extends OpaqueString[RichText]

Expand Down
3 changes: 1 addition & 2 deletions modules/db/src/main/Handlers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package lila.db
import chess.variant.Variant
import reactivemongo.api.bson.*
import reactivemongo.api.bson.exceptions.TypeDoesNotMatchException

import scala.util.{ Failure, NotGiven, Success, Try }
import scalalib.model.Percent

import lila.common.Iso.{ *, given }
import lila.core.data.Percent
import lila.core.net.IpAddress
import lila.core.game.Blurs

Expand Down
3 changes: 2 additions & 1 deletion modules/evalCache/src/main/BSONHandlers.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package lila.evalCache

import chess.format.{ BinaryFen, Uci }
import chess.eval.*
import reactivemongo.api.bson.*

import scala.util.{ Success, Try }

import lila.db.dsl.{ *, given }
import lila.tree.{ CloudEval, Moves, Pv, Score }
import lila.tree.{ CloudEval, Moves, Pv }

private object BSONHandlers:

Expand Down
2 changes: 1 addition & 1 deletion modules/fishnet/src/main/AnalysisBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,5 @@ final private class AnalysisBuilder(evalCache: IFishnetEvalCache)(using Executor
variation = variation.map(uci => SanStr(uci.uci)) // temporary, for UciToSan
)
if info.ply.isOdd then info.invert else info
case ((_, _), index) => Info(startedAtPly + index + 1, Eval.empty, Nil)
case ((_, _), index) => Info(startedAtPly + index + 1, lila.tree.evals.empty, Nil)
}
2 changes: 1 addition & 1 deletion modules/fishnet/src/main/JsonApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package lila.fishnet

import chess.format.{ Fen, Uci }
import chess.variant.Variant
import chess.eval.Eval.{ Cp, Mate }
import play.api.libs.json.*

import lila.common.Json.{ *, given }
import lila.core.chess.Depth
import lila.core.net.IpAddress
import lila.fishnet.Work as W
import lila.tree.Eval.{ Cp, Mate }

object JsonApi:

Expand Down
3 changes: 2 additions & 1 deletion modules/fishnet/src/test/UciToSanTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package lila.fishnet

import chess.format.pgn.{ Reader, SanStr }
import chess.{ Ply, Replay }
import chess.eval.*
import chess.eval.Eval.*

import scala.language.implicitConversions

import lila.analyse.{ Analysis, Info }
import lila.tree.Eval
import lila.tree.Eval.*

final class UciToSanTest extends munit.FunSuite:

Expand Down
3 changes: 2 additions & 1 deletion modules/insight/src/main/BSONHandlers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package lila.insight

import chess.{ Color, Role }
import chess.IntRating
import chess.eval.WinPercent
import chess.rating.IntRatingDiff
import reactivemongo.api.bson.*

import lila.analyse.{ AccuracyPercent, WinPercent }
import lila.analyse.AccuracyPercent
import lila.common.SimpleOpening
import lila.db.BSON
import lila.db.dsl.{ *, given }
Expand Down
3 changes: 2 additions & 1 deletion modules/insight/src/main/InsightDimension.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package lila.insight

import chess.Role
import chess.eval.WinPercent
import play.api.libs.json.*
import reactivemongo.api.bson.*

import lila.analyse.{ AccuracyPercent, WinPercent }
import lila.analyse.AccuracyPercent
import lila.common.Json.given
import lila.common.{ LilaOpeningFamily, SimpleOpening }
import lila.core.i18n.Translate
Expand Down
5 changes: 3 additions & 2 deletions modules/insight/src/main/PovToEntry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package lila.insight
import chess.format.pgn.SanStr
import chess.opening.OpeningDb
import chess.{ Centis, Clock, Ply, Role, Situation, Stats }
import chess.eval.WinPercent

import lila.analyse.{ AccuracyCP, AccuracyPercent, Advice, Analysis, WinPercent }
import lila.analyse.{ AccuracyCP, AccuracyPercent, Advice, Analysis }
import lila.common.SimpleOpening
import lila.game.Blurs.booleans

Expand Down Expand Up @@ -137,7 +138,7 @@ final private class PovToEntry(
role = role,
eval = prevInfo.flatMap(_.eval.forceAsCp).map(_.ceiled.centipawns),
cpl = cpDiffs.lift(i).flatten,
winPercent = prevInfo.map(_.eval).flatMap(WinPercent.fromEval),
winPercent = prevInfo.map(_.eval).flatMap(_.score).map(WinPercent.fromScore),
accuracyPercent = accuracyPercent,
material = situation.board.materialImbalance * from.pov.color.fold(1, -1),
awareness = awareness,
Expand Down
3 changes: 2 additions & 1 deletion modules/insight/src/main/TutorRange.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package lila.insight

import chess.IntRating
import chess.rating.IntRatingDiff
import chess.eval.WinPercent

import lila.analyse.{ AccuracyPercent, WinPercent }
import lila.analyse.AccuracyPercent

enum RelativeStrength(val id: Int, val name: String):
case MuchWeaker extends RelativeStrength(10, "Much weaker")
Expand Down
5 changes: 3 additions & 2 deletions modules/insight/src/main/model.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package lila.insight

import scalalib.model.Percent
import chess.format.pgn.SanStr
import chess.{ Centis, Clock, Ply, Role }
import chess.eval.WinPercent

import lila.analyse.{ AccuracyPercent, WinPercent }
import lila.analyse.AccuracyPercent
import lila.common.{ LilaOpeningFamily, SimpleOpening }
import lila.core.data.Percent

case class InsightUser(
count: Int, // nb insight entries
Expand Down
4 changes: 2 additions & 2 deletions modules/mod/src/main/ModlogApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ final class ModlogApi(repo: ModlogRepo, userRepo: UserRepo, ircApi: IrcApi, pres
Modlog.isolate
)

def streamerDecline(streamerId: UserId)(using MyId) = add:
Modlog(streamerId.some, Modlog.streamerDecline)
def streamerDecline(streamerId: UserId, reason: Option[String])(using MyId) = add:
Modlog(streamerId.some, Modlog.streamerDecline, reason)

def streamerList(streamerId: UserId, v: Boolean)(using MyId) = add:
Modlog(streamerId.some, if v then Modlog.streamerList else Modlog.streamerUnlist)
Expand Down
2 changes: 0 additions & 2 deletions modules/opening/src/main/ui/OpeningBits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import ScalatagsTemplate.{ *, given }
final class OpeningBits(helpers: Helpers):
import helpers.{ *, given }

def beta = span(cls := "opening__beta")("BETA")

def pageModule(page: Option[OpeningPage])(using Context) =
PageModule(
"opening",
Expand Down
5 changes: 2 additions & 3 deletions modules/opening/src/main/ui/OpeningUi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class OpeningUi(helpers: Helpers, bits: OpeningBits, wiki: WikiUi):
searchAndConfig(page.query.config, "", ""),
resultsList(Nil),
boxTop(
h1("Chess openings", bits.beta),
h1("Chess openings"),
div(cls := "box__top__actions")(
a(href := routes.Opening.tree)("Name tree"),
a(href := s"${routes.UserAnalysis.index}#explorer")("Explorer")
Expand Down Expand Up @@ -96,8 +96,7 @@ final class OpeningUi(helpers: Helpers, bits: OpeningBits, wiki: WikiUi):
a(href := openingKeyUrl(k))(cls := className)(name)
}
)
),
beta
)
)
),
div(cls := "opening__intro")(
Expand Down
9 changes: 5 additions & 4 deletions modules/relay/src/main/RelayFetch.scala
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ final private class RelayFetch(
private val createdGames =
cacheApi.notLoadingSync[LccGameKey, GameJson](256, "relay.fetch.createdLccGames"):
_.expireAfter[LccGameKey, GameJson](
create = (key, _) => (if key.startsWith("started ") then 40.seconds else 3.minutes),
create = (key, _) => (if key.startsWith("started ") then 30.seconds else 3.minutes),
update = (_, _, current) => current,
read = (_, _, current) => current
).build()
Expand All @@ -249,21 +249,22 @@ final private class RelayFetch(
cacheApi.notLoadingSync[LccGameKey, GameJson](256, "relay.fetch.tailLccGames"):
_.expireAfterWrite(1 minutes).build()

// index starts at 1
def apply(lcc: RelayRound.Sync.Lcc, index: Int, roundTags: Tags, started: Boolean)(
fetch: () => Fu[GameJson]
): Fu[GameJson] =
val key = s"${started.so("started ")}${lcc.id} ${lcc.round} $index"
finishedGames
.getIfPresent(key)
.orElse(createdGames.getIfPresent(key))
.orElse((index >= lccCache.tailAt).so(tailGames.getIfPresent(key)))
.orElse((index > lccCache.tailAt).so(tailGames.getIfPresent(key)))
.match
case Some(game) => fuccess(game)
case None =>
fetch().addEffect: game =>
if game.moves.isEmpty then createdGames.put(key, game)
else if game.mergeRoundTags(roundTags).outcome.isDefined then finishedGames.put(key, game)
else if index >= lccCache.tailAt then tailGames.put(key, game)
else if index > lccCache.tailAt then tailGames.put(key, game)

// used to return the last successful result when a source fails
// games are stripped of their moves, only tags are kept.
Expand Down Expand Up @@ -342,7 +343,7 @@ final private class RelayFetch(
private def fetchJsonWithEtag[A: Reads](initialCapacity: Int): URL => CanProxy ?=> Fu[A] =
import RelayFormat.Etag
val cache = cacheApi.notLoadingSync[URL, (Etag, A)](initialCapacity, "relay.fetch.jsonWithEtag"):
_.expireAfterWrite(5 minutes).build()
_.expireAfterWrite(10 minutes).build()
url =>
CanProxy ?=>
cache
Expand Down
12 changes: 6 additions & 6 deletions modules/relay/src/main/RelayFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,17 @@ final private class RelayFormatApi(
if res.status == 304 then none -> newEtag.orElse(etag)
else (res.body: String).some -> newEtag

private def httpGetResponse(req: StandaloneWSRequest)(using CanProxy): Future[StandaloneWSResponse] =
private def httpGetResponse(req: StandaloneWSRequest)(using CanProxy): Fu[StandaloneWSResponse] =
Future
.fromTry(lila.common.url.parse(req.url))
.flatMap: url =>
req
.get()
.monValue: res =>
_.relay.httpGet(res.status, url.host.toString, req.proxyServer.map(_.host))
.flatMap: res =>
if res.status == 200 || res.status == 304 then fuccess(res)
else if res.status == 404 then fufail(NotFound(url))
else fufail(s"[${res.status}] ${req.url}")
.monSuccess(_.relay.httpGet(url.host.toString, req.proxyServer.map(_.host)))
else fufail(Status(res.status, url))

private def responseHeaderCharset(res: StandaloneWSResponse): Option[java.nio.charset.Charset] =
import play.shaded.ahc.org.asynchttpclient.util.HttpUtils
Expand Down Expand Up @@ -152,5 +152,5 @@ private object RelayFormat:
opaque type CanProxy = Boolean
object CanProxy extends YesNo[CanProxy]

case class NotFound(url: URL) extends LilaException:
override val message = s"404: $url"
case class Status(code: Int, url: URL) extends LilaException:
override val message = s"$code: $url"
8 changes: 5 additions & 3 deletions modules/streamer/src/main/Streamer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ object Streamer:
ignored = user.marks.troll,
tier = 0,
chatEnabled = true,
lastGrantedAt = none
lastGrantedAt = none,
reason = none
),
picture = none,
name = Name(user.realNameOrUsername),
Expand All @@ -80,7 +81,8 @@ object Streamer:
ignored: Boolean, // further requests are ignored
tier: Int, // homepage featuring tier
chatEnabled: Boolean, // embed chat inside lichess
lastGrantedAt: Option[Instant]
lastGrantedAt: Option[Instant],
reason: Option[String]
)

case class Twitch(userId: String) derives Eq:
Expand Down Expand Up @@ -127,7 +129,7 @@ object Streamer:
.map(_.fullUrl)
.orElse(streamer.youTube.ifTrue(s.youTube).map(_.fullUrl))

case class ModChange(list: Option[Boolean], tier: Option[Int], decline: Boolean)
case class ModChange(list: Option[Boolean], tier: Option[Int], decline: Boolean, reason: Option[String])

val maxTier = 10

Expand Down
Loading

0 comments on commit 890ff80

Please sign in to comment.