Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into local-play
Browse files Browse the repository at this point in the history
  • Loading branch information
schlawg committed Jan 11, 2025
2 parents da881d0 + 10f2df9 commit 1a9a666
Show file tree
Hide file tree
Showing 275 changed files with 650 additions and 1,439 deletions.
2 changes: 1 addition & 1 deletion app/controllers/User.scala
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ final class User(
res <-
if HTTPRequest.isSynchronousHttp(ctx.req) then
for
info <- env.userInfo(u, nbs, withUblog = false)
info <- env.userInfo(u, nbs, withUblog = true)
_ <- env.team.cached.lightCache.preloadMany(info.teamIds)
social <- env.socialInfo(u)
searchForm = (filters.current == GameFilter.Search).option(
Expand Down
2 changes: 1 addition & 1 deletion bin/trans-dump.ts → bin/i18n-file-gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function keyListFrom(name: string): KeyList {
const dbCode = (obj: KeyList) => ` object ${convertObjectName(obj.name)}:\n${obj.code}`;

Promise.all(xmls.map(keyListFrom)).then(objs => {
const code = `// Generated with bin/trans-dump.ts
const code = `// Generated with bin/i18n-file-gen.ts
package lila.core.i18n
opaque type I18nKey = String
Expand Down
2 changes: 1 addition & 1 deletion bin/trans-unused
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def main() -> None:
r = subprocess.run(["sed","-i", "", f"/{unused}.*</d", path], capture_output=True)


r = subprocess.run(["pnpm", "run", "trans-dump"], cwd=LILA_DIR)
r = subprocess.run(["pnpm", "run", "i18n-file-gen"], cwd=LILA_DIR)
sys.exit(r.returncode)


Expand Down
23 changes: 7 additions & 16 deletions modules/common/src/main/Bus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,26 +104,17 @@ final private class EventBus[Event, Channel, Subscriber](
publish: (Subscriber, Event) => Unit
):

private val entries = java.util.concurrent.ConcurrentHashMap[Channel, Set[Subscriber]](initialCapacity)
private val entries = scalalib.ConcurrentMap[Channel, Set[Subscriber]](initialCapacity)
export entries.size

def subscribe(subscriber: Subscriber, channel: Channel): Unit =
entries
.compute(
channel,
(_: Channel, subs: Set[Subscriber]) => Option(subs).fold(Set(subscriber))(_ + subscriber)
)
entries.compute(channel):
_.fold(Set(subscriber))(_ + subscriber).some

def unsubscribe(subscriber: Subscriber, channel: Channel): Unit =
entries
.computeIfPresent(
channel,
(_: Channel, subs: Set[Subscriber]) =>
val newSubs = subs - subscriber
if newSubs.isEmpty then null
else newSubs
)
entries.computeIfPresent(channel): subs =>
val newSubs = subs - subscriber
Option.when(newSubs.nonEmpty)(newSubs)

def publish(event: Event, channel: Channel): Unit =
Option(entries.get(channel)).foreach:
_.foreach(publish(_, event))
entries.get(channel).foreach(_.foreach(publish(_, event)))
1 change: 1 addition & 0 deletions modules/core/src/main/perm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ enum Permission(val key: String, val alsoGrants: List[Permission], val name: Str
GamifyView,
SeeReport,
ModLog,
SeeInsight,
ModMessage,
ModNote,
ViewPrintNoIP,
Expand Down
2 changes: 2 additions & 0 deletions modules/coreI18n/src/main/i18n.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import scalatags.Text.RawFrag
import scala.concurrent.duration.FiniteDuration
export scalalib.newtypes.{ given, * }

val maxLangs = 128

/* play.api.i18n.Lang is composed of language and country.
* Let's make new types for those so we don't mix them.
*/
Expand Down
5 changes: 4 additions & 1 deletion modules/coreI18n/src/main/key.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated with bin/trans-dump.ts
// Generated with bin/i18n-file-gen.ts
package lila.core.i18n

opaque type I18nKey = String
Expand Down Expand Up @@ -2208,8 +2208,11 @@ object I18nKey:
val `opponentLeftCounter`: I18nKey = "opponentLeftCounter"
val `mateInXHalfMoves`: I18nKey = "mateInXHalfMoves"
val `nbBlunders`: I18nKey = "nbBlunders"
val `numberBlunders`: I18nKey = "numberBlunders"
val `nbMistakes`: I18nKey = "nbMistakes"
val `numberMistakes`: I18nKey = "numberMistakes"
val `nbInaccuracies`: I18nKey = "nbInaccuracies"
val `numberInaccuracies`: I18nKey = "numberInaccuracies"
val `nbPlayers`: I18nKey = "nbPlayers"
val `nbGames`: I18nKey = "nbGames"
val `ratingXOverYGames`: I18nKey = "ratingXOverYGames"
Expand Down
1 change: 1 addition & 0 deletions modules/game/src/main/GamesByUsersStream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ private object GameStream:
)
.add("provisional" -> p.provisional))
)
.add("winner" -> g.winnerColor.map(_.name))
.add("initialFen" -> initialFen)
.add("clock" -> g.clock.map: clock =>
Json.obj(
Expand Down
21 changes: 8 additions & 13 deletions modules/memo/src/main/ExpirableCallbackMemo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package lila.memo

import akka.actor.{ Cancellable, Scheduler }

import java.util.concurrent.ConcurrentHashMap
import scala.jdk.CollectionConverters.*

// calls a function when a key expires
Expand All @@ -13,21 +12,17 @@ final class ExpireCallbackMemo[K](
initialCapacity: Int = 4096
)(using Executor):

private val timeouts = ConcurrentHashMap[K, Cancellable](initialCapacity)
private val timeouts = scalalib.ConcurrentMap[K, Cancellable](initialCapacity)

export timeouts.{ contains as get, size as count }
export timeouts.{ contains as get, size as count, keySet }

def put(key: K): Unit = timeouts.compute(
key,
(_, canc) =>
Option(canc).foreach(_.cancel())
scheduler.scheduleOnce(ttl) {
def put(key: K): Unit = timeouts.compute(key): canc =>
canc.foreach(_.cancel())
scheduler
.scheduleOnce(ttl):
remove(key)
callback(key)
}
)
.some

// does not call the expiration callback
def remove(key: K): Unit = Option(timeouts.remove(key)).foreach(_.cancel())

def keySet: Set[K] = timeouts.keySet.asScala.toSet
def remove(key: K): Unit = timeouts.remove(key).foreach(_.cancel())
22 changes: 9 additions & 13 deletions modules/msg/src/main/MsgNotify.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package lila.msg

import akka.actor.Cancellable

import java.util.concurrent.ConcurrentHashMap

import lila.common.String.shorten
import lila.core.notify.{ NotifyApi, NotificationContent }
import lila.db.dsl.{ *, given }
Expand All @@ -17,7 +15,7 @@ final private class MsgNotify(

private val delay = 5 seconds

private val delayed = ConcurrentHashMap[MsgThread.Id, Cancellable](256)
private val delayed = scalalib.ConcurrentMap[MsgThread.Id, Cancellable](256)

def onPost(threadId: MsgThread.Id): Unit = schedule(threadId)

Expand All @@ -39,25 +37,23 @@ final private class MsgNotify(
notifyApi.remove(thread.other(user.id), $doc("content.user" -> user.id)).void
}

private def schedule(threadId: MsgThread.Id): Unit = delayed.compute(
threadId,
(id, canc) =>
Option(canc).foreach(_.cancel())
scheduler.scheduleOnce(delay):
delayed.remove(id)
private def schedule(threadId: MsgThread.Id): Unit = delayed.compute(threadId): canc =>
canc.foreach(_.cancel())
scheduler
.scheduleOnce(delay):
delayed.remove(threadId)
doNotify(threadId)
)
.some

private def cancel(threadId: MsgThread.Id): Boolean =
Option(delayed.remove(threadId)).map(_.cancel()).isDefined
delayed.remove(threadId).map(_.cancel()).isDefined

private def doNotify(threadId: MsgThread.Id): Funit =
colls.thread.byId[MsgThread](threadId.value).flatMapz { thread =>
val msg = thread.lastMsg
(!thread.delBy(thread.other(msg.user))).so(
(!thread.delBy(thread.other(msg.user))).so:
notifyApi.notifyOne(
thread.other(msg.user),
NotificationContent.PrivateMessage(msg.user, text = shorten(msg.text, 40))
)
)
}
20 changes: 9 additions & 11 deletions modules/round/src/main/RoundSocket.scala
Original file line number Diff line number Diff line change
Expand Up @@ -453,19 +453,17 @@ object RoundSocket:
duration: FiniteDuration,
terminate: GameId => Unit
)(using Executor):
import java.util.concurrent.ConcurrentHashMap

private val terminations = ConcurrentHashMap[GameId, Cancellable](65536)
private val terminations = scalalib.ConcurrentMap[GameId, Cancellable](65536)

def schedule(gameId: GameId): Unit =
terminations.compute(
gameId,
(id, canc) =>
Option(canc).foreach(_.cancel())
scheduler.scheduleOnce(duration):
terminations.remove(id)
terminate(id)
)
terminations.compute(gameId): canc =>
canc.foreach(_.cancel())
scheduler
.scheduleOnce(duration):
terminations.remove(gameId)
terminate(gameId)
.some

def cancel(gameId: GameId): Unit =
Option(terminations.remove(gameId)).foreach(_.cancel())
terminations.remove(gameId).foreach(_.cancel())
5 changes: 4 additions & 1 deletion modules/shutup/src/main/Dictionary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ package lila.shutup
private object Dictionary:

def en = dict("""
(burn|die) in hell
(burn|die|rot) in hell
(f++|ph)(u++|e++|a++)c?k(er|r|u|k|t|ing?|ign|en|tard?|face|off?|e?d|)
go to hell
(kill|hang|neck) my ?self
[ck]um(shot|)
[ck]unt(ing|)
Expand Down Expand Up @@ -54,6 +55,7 @@ cunn?ilingu
dic?k(head|face|suc?ker|)
dildo
dogg?ystyle
dogshit
douche(bag|)
downsie?
dumb(ass?|)
Expand Down Expand Up @@ -301,6 +303,7 @@ gaa?ndu?
def fr = dict("""
batard
connard
cr[eé]tin
encul[eé]
fdp
pd
Expand Down
23 changes: 8 additions & 15 deletions modules/tournament/src/main/Duel.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package lila.tournament

import java.util.concurrent.ConcurrentHashMap
import scala.collection.immutable.TreeSet
import chess.IntRating

Expand Down Expand Up @@ -38,9 +37,9 @@ final private class DuelStore:

import Duel.*

private val byTourId = new ConcurrentHashMap[TourId, TreeSet[Duel]](256)
private val byTourId = scalalib.ConcurrentMap[TourId, TreeSet[Duel]](256)

def get(tourId: TourId): Option[TreeSet[Duel]] = Option(byTourId.get(tourId))
export byTourId.get

def bestRated(tourId: TourId, nb: Int): List[Duel] =
get(tourId).so {
Expand All @@ -61,19 +60,13 @@ final private class DuelStore:
averageRating = IntRating((p1.rating.value + p2.rating.value) / 2)
)
do
byTourId.compute(
tour.id,
(_: TourId, v: TreeSet[Duel]) =>
if v == null then TreeSet(tb)(gameIdOrdering)
else v + tb
)
byTourId.compute(tour.id):
_.fold(TreeSet(tb)(gameIdOrdering))(_ + tb).some

def remove(game: Game): Unit =
game.tournamentId.foreach: tourId =>
byTourId.computeIfPresent(
tourId,
(_: TourId, tb: TreeSet[Duel]) =>
val w = tb - emptyGameId(game.id)
if w.isEmpty then null else w
)
byTourId.computeIfPresent(tourId): tb =>
val w = tb - emptyGameId(game.id)
Option.when(w.nonEmpty)(w)

def remove(tour: Tournament): Unit = byTourId.remove(tour.id)
35 changes: 12 additions & 23 deletions modules/tournament/src/main/WaitingUsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package lila.tournament

import chess.Clock.Config as TournamentClock
import scalalib.cache.ExpireSetMemo
import lila.tournament.WaitingUsers.WithNext

private case class WaitingUsers(
hash: Map[UserId, Instant],
Expand Down Expand Up @@ -62,28 +63,23 @@ private case class WaitingUsers(

final private class WaitingUsersApi(using Executor):

private val store = new java.util.concurrent.ConcurrentHashMap[TourId, WaitingUsers.WithNext](64)
private val store = scalalib.ConcurrentMap[TourId, WaitingUsers.WithNext](64)

def hasUser(tourId: TourId, userId: UserId): Boolean =
Option(store.get(tourId)).exists(_.waiting.hasUser(userId))
store.get(tourId).exists(_.waiting.hasUser(userId))

def registerNextPromise(tour: Tournament, promise: Promise[WaitingUsers]) =
updateOrCreate(tour)(_.copy(next = promise.some))

def registerWaitingUsers(tourId: TourId, users: Set[UserId]) =
store.computeIfPresent(
tourId,
(_: TourId, cur: WaitingUsers.WithNext) =>
val newWaiting = cur.waiting.update(users)
cur.next.foreach(_.success(newWaiting))
WaitingUsers.WithNext(newWaiting, none)
)
store.computeIfPresent(tourId): cur =>
val newWaiting = cur.waiting.update(users)
cur.next.foreach(_.success(newWaiting))
WaitingUsers.WithNext(newWaiting, none).some

def registerPairedUsers(tourId: TourId, users: Set[UserId]) =
store.computeIfPresent(
tourId,
(_: TourId, cur: WaitingUsers.WithNext) => cur.copy(waiting = cur.waiting.removePairedUsers(users))
)
store.computeIfPresent(tourId): cur =>
cur.copy(waiting = cur.waiting.removePairedUsers(users)).some

def addApiUser(tour: Tournament, user: User) = updateOrCreate(tour) { w =>
w.copy(waiting = w.waiting.addApiUser(user.id))
Expand All @@ -92,16 +88,9 @@ final private class WaitingUsersApi(using Executor):
def remove(id: TourId) = store.remove(id)

private def updateOrCreate(tour: Tournament)(f: WaitingUsers.WithNext => WaitingUsers.WithNext) =
store.compute(
tour.id,
(_: TourId, cur: WaitingUsers.WithNext) =>
f(
Option(cur) | WaitingUsers.WithNext(
WaitingUsers(Map.empty, None, tour.clock, nowInstant),
none
)
)
)
store.compute(tour.id): cur =>
val users = cur | WaitingUsers.WithNext(WaitingUsers(Map.empty, None, tour.clock, nowInstant), none)
f(users).some

private object WaitingUsers:
case class WithNext(waiting: WaitingUsers, next: Option[Promise[WaitingUsers]])
4 changes: 2 additions & 2 deletions modules/tutor/src/main/TutorNumber.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ trait TutorNumber[V]:
object TutorNumber:

given TutorNumber[GoodPercent] with
val iso = Iso.sameRuntime
val iso = summon[Iso[Double, GoodPercent]]
def grade(a: GoodPercent, b: GoodPercent) = Grade.percent(a, b)
given TutorNumber[AccuracyPercent] with
val iso = Iso.sameRuntime
val iso = summon[Iso[Double, AccuracyPercent]]
def grade(a: AccuracyPercent, b: AccuracyPercent) = Grade.percent(a, b)
given TutorNumber[IntRating] with
val iso = Iso.double[IntRating](d => IntRating(roundToInt(d)), _.value.toDouble)
Expand Down
Loading

0 comments on commit 1a9a666

Please sign in to comment.