Skip to content

Commit

Permalink
resolve branch conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
schlawg committed Dec 16, 2024
2 parents 8872b50 + 099d2e1 commit 916b6e9
Show file tree
Hide file tree
Showing 16 changed files with 167 additions and 72 deletions.
77 changes: 77 additions & 0 deletions bin/mongodb/recap-notif.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const year = 2024;
const dry = false;

let count = 0;

const hasPuzzles = userId => db.user_perf.count({ _id: userId, 'puzzle.nb': { $gt: 0 } });

function sendToUser(user) {
if (!user.enabled) {
print('------------- ' + user._id + ' is closed');
return;
}
const exists = db.notify.countDocuments({ notifies: user._id, 'content.type': 'recap', }, { limit: 1 });
if (exists) {
print('------------- ' + user._id + ' already sent');
return;
}
if (user.seenAt < new Date('2024-01-01')) {
print('------------- ' + user._id + ' not seen in 2024');
return;
}
if (!user.count?.game && !hasPuzzles(user._id)) {
print('------------- ' + user._id + ' no games or puzzles');
return;
}
if (!dry) db.notify.insertOne({
_id: Math.random().toString(36).substring(2, 10),
notifies: user._id,
content: {
type: 'recap',
year: NumberInt(year),
},
read: false,
createdAt: new Date(),
});
count++;
print(count + ' ' + user._id);
}

function sendToUserId(userId) {
const user = db.user4.findOne({ _id: userId });
if (!user) {
print('------------- ' + userId + ' not found');
return;
}
sendToUser(user);
}

function sendToRoleOwners() {
db.user4.find({ enabled: true, roles: { $exists: 1, $ne: [] } }).forEach(user => {
roles = user.roles.filter(r => r != 'ROLE_COACH' && r != 'ROLE_TEACHER' && r != 'ROLE_VERIFIED' && r != 'ROLE_BETA');
if (roles.length) {
sendTo(user);
}
});
}

function sendToTeamMembers(teamId) {
db.team_member.find({ team: teamId }, { user: 1, _id: 0 }).forEach(member => {
sendToUserId(member.user);
});
}

function sendToRandomOnlinePlayers() {
db.user4.find({ enabled: true, 'count.game': { $gt: 10 }, seenAt: { $gt: new Date(Date.now() - 1000 * 60 * 2) } }).sort({ seenAt: -1 }).limit(5_000).forEach(sendToUser);
}

function sendToRandomOfflinePlayers() {
db.user4.find({
enabled: true, 'count.game': { $gt: 10 }, seenAt: {
$gt: new Date(Date.now() - 1000 * 60 * 60 * 24),
$lt: new Date(Date.now() - 1000 * 60 * 60)
}
}).limit(25_000).forEach(sendToUser);
}

sendToRandomOfflinePlayers();
2 changes: 1 addition & 1 deletion modules/core/src/main/perm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ enum Permission(val key: String, val alsoGrants: List[Permission], val name: Str
case StudyAdmin extends Permission("STUDY_ADMIN", List(Relay), "Study/Broadcast admin")
case ApiHog extends Permission("API_HOG", "API hog")
case ApiChallengeAdmin extends Permission("API_CHALLENGE_ADMIN", "API Challenge admin")
case LichessTeam extends Permission("LICHESS_TEAM", Nil, "Lichess team")
case LichessTeam extends Permission("LICHESS_TEAM", List(Beta), "Lichess team")
case BotEditor extends Permission("BOT_EDITOR", "Bot editor")
case TimeoutMod
extends Permission(
Expand Down
1 change: 0 additions & 1 deletion modules/memo/src/main/ParallelMongoQueue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ final class ParallelMongoQueue[A: BSONHandler](
/* Read the oldest <parallelism()> entries from the queue
* start new ones, expire old ones
*/
// LilaScheduler(s"ParallelQueue($name).poll", _.Every(1 second), _.AtMost(5 seconds), _.Delay(33 seconds)):
private val startAfter = if mode.isProd then 33.seconds else 3.seconds
LilaScheduler(s"ParallelQueue($name).poll", _.Every(1 second), _.AtMost(5 seconds), _.Delay(startAfter)):

Expand Down
4 changes: 1 addition & 3 deletions modules/recap/src/main/Env.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package lila.recap

import com.softwaremill.macwire.*
import com.softwaremill.tagging.*

import lila.core.config.CollName
import lila.db.dsl.{ *, given }
Expand All @@ -21,7 +20,7 @@ final class Env(
"recapParallelism",
default = 8,
text = "Number of yearly recaps to build in parallel".some
).taggedWith[Parallelism]
)

private val colls = RecapColls(db(CollName("recap_report")), db(CollName("recap_queue")))

Expand All @@ -41,5 +40,4 @@ final class Env(

lazy val api = wire[RecapApi]

trait Parallelism
final private class RecapColls(val recap: Coll, val queue: Coll)
6 changes: 2 additions & 4 deletions modules/recap/src/main/RecapBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ private final class RecapBuilder(
nbs = NbWin(total = nb, win = wins - fixes),
votes = PuzzleVotes(nb = votes, themes = themes)
)
.monSuccess(_.recap.puzzles)

private def makeGameRecap(scan: GameScan): RecapGames =
RecapGames(
Expand All @@ -68,10 +69,7 @@ private final class RecapBuilder(
timePlaying = scan.secondsPlaying.seconds,
sources = scan.sources,
opponents = scan.opponents.toList.sortBy(-_._2).take(5).map(Recap.Counted.apply),
perfs = scan.perfs.toList
.sortBy(-_._2)
.map:
case (key, games) => Recap.Perf(key, games)
perfs = scan.perfs.toList.sortBy(-_._2).map(Recap.Perf.apply)
)

private def runGameScan(userId: UserId): Fu[GameScan] =
Expand Down
2 changes: 1 addition & 1 deletion modules/relay/src/main/RelayDelay.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ final private class RelayDelay(colls: RelayColls)(using Executor):
Option(v) match
case Some(GamesSeenBy(games, seenBy)) if !seenBy(round.id) =>
lila.mon.relay.dedup.increment()
logger.info(s"Relay dedup cache hit ${round.id} ${round.name} ${url.toString}")
logger.debug(s"Relay dedup cache hit ${round.id} ${round.name} ${url.toString}")
GamesSeenBy(games, seenBy + round.id)
case _ =>
GamesSeenBy(doFetch(), Set(round.id))
Expand Down
12 changes: 5 additions & 7 deletions modules/relay/src/main/RelayPgnStream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ final class RelayPgnStream(
)(using Executor):

def exportFullTourAs(tour: RelayTour, me: Option[User]): Source[PgnStr, ?] = Source.futureSource:
roundRepo
.idsByTourOrdered(tour.id)
.flatMap: ids =>
studyRepo.byOrderedIds(StudyId.from[List, RelayRoundId](ids)).map { studies =>
val visible = studies.filter(_.canView(me.map(_.id)))
Source(visible).flatMapConcat { studyPgnDump.chaptersOf(_, flags) }.throttle(16, 1.second)
}
for
ids <- roundRepo.idsByTourOrdered(tour.id)
studies <- studyRepo.byOrderedIds(StudyId.from[List, RelayRoundId](ids))
visible = studies.filter(_.canView(me.map(_.id)))
yield Source(visible).flatMapConcat { studyPgnDump.chaptersOf(_, flags) }.throttle(16, 1.second)

private val flags = PgnDump.WithFlags(
comments = false,
Expand Down
1 change: 1 addition & 0 deletions modules/shutup/src/main/Dictionary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ uebok
""")

def es = dict("""
bolud[oa]
cabr[oó]na?
cag[oó]n
ching(ue|a)
Expand Down
2 changes: 1 addition & 1 deletion public/flair/list.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Create list.txt from img/*.webp

pushd "$(dirname "$0")"
ls img/*.webp | sed 's/.webp//g' | sed 's/img\///g' >list.txt
ls img/*.webp | grep -v 'symbols.cancel' | sed 's/.webp//g' | sed 's/img\///g' >list.txt
popd

echo "Done creating flair/list.txt."
1 change: 0 additions & 1 deletion public/flair/list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3058,7 +3058,6 @@ symbols.blue-heart
symbols.bright-button
symbols.broken-heart
symbols.brown-heart
symbols.cancel
symbols.cancer
symbols.capricorn
symbols.chequered-flag
Expand Down
6 changes: 2 additions & 4 deletions ui/analyse/css/study/relay/_video-player.scss
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@
color: #222e;
background-color: #dddd;
}
&:hover:not(:has(.video-player-close:hover)) {
.play-button {
opacity: 1;
}
&:hover:not(:has(.video-player-close:hover)) .play-button {
opacity: 1;
}
}
8 changes: 7 additions & 1 deletion ui/recap/css/_recap.scss
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ body {
.recap {
&__logo,
.lpv {
width: 384px;
width: 45vh;
max-width: 61vw;
max-height: 50vh;
}
Expand Down Expand Up @@ -218,6 +218,11 @@ body {
}
}
}
@media (min-width: at-least($xx-small)) {
.logo {
display: none;
}
}
}

.recap small {
Expand Down Expand Up @@ -267,6 +272,7 @@ body {
font-size: 0.8em;
opacity: 0.8;
min-width: 12ch;
padding-left: 1em;
}
}
.recap__slide--opponents {
Expand Down
1 change: 1 addition & 0 deletions ui/recap/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface Sources {
simul: number;
swiss: number;
pool: number;
lobby: number;
ai: number;
arena: number;
}
Expand Down
13 changes: 9 additions & 4 deletions ui/recap/src/slides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ export const timeSpentPlaying = (r: Recap): VNode => {
};

export const nbMoves = (r: Recap): VNode => {
return slideTag('moves')([
return slideTag(
'moves',
6000,
)([
h('div.recap--massive', [h('strong', animateNumber(r.games.moves)), 'moves played']),
h('div', [
h('p', ["That's ", h('strong', showGrams(r.games.moves * pieceGrams)), ' of wood pushed!']),
Expand Down Expand Up @@ -120,8 +123,9 @@ export const firstMoves = (r: Recap, firstMove: Counted<string>): VNode => {
]);
};

export const openingColor = (os: ByColor<Counted<Opening>>, color: Color): VNode => {
export const openingColor = (os: ByColor<Counted<Opening>>, color: Color): VNode | undefined => {
const o = os[color];
if (!o.count) return;
return slideTag('openings')([
h('div.lpv.lpv--todo.lpv--moves-bottom.is2d', {
hook: onInsert(el => loadOpeningLpv(el, color, o.value)),
Expand Down Expand Up @@ -191,7 +195,8 @@ export const sources = (r: Recap): VNode => {
['arena', 'Arena tournaments'],
['swiss', 'Swiss tournaments'],
['simul', 'Simuls'],
['pool', 'Lobby pairing'],
['pool', 'Pool pairing'],
['lobby', 'Lobby custom games'],
];
const best: [string, number][] = all.map(([k, n]) => [n, r.games.sources[k] || 0]);
best.sort((a, b) => b[1] - a[1]);
Expand Down Expand Up @@ -253,7 +258,7 @@ export const thanks = (): VNode =>
slideTag('thanks')([
h('div.recap--massive', 'Thank you for playing on Lichess!'),
h('img.recap__logo', { attrs: { src: site.asset.url('logo/lichess-white.svg') } }),
h('div', "May your pieces find their way to your opponents' kings."),
h('div', "We're glad you're here. Have a great 2025!"),
]);

const renderPerf = (perf: RecapPerf): VNode => {
Expand Down
81 changes: 46 additions & 35 deletions ui/recap/src/swiper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export const makeSwiper =
? parseInt(window.location.hash.slice(1))
: undefined;
const autoplay = !defined(urlSlide);
let lpvTimer: number | undefined;
const options: SwiperOptions = {
modules: [
mod.Pagination,
Expand Down Expand Up @@ -54,46 +53,58 @@ export const makeSwiper =
: undefined,
on: {
autoplayTimeLeft(swiper, time, progress) {
if (swiper.isEnd) progressDiv.remove();
if (swiper.isEnd) progressDiv.style.display = 'none';
else progressDiv.style.display = 'flex';
progressCircle.style.setProperty('--progress', (1 - progress).toString());
progressContent.textContent = `${Math.ceil(time / 1000)}s`;
},
slideChange() {
slideChange(swiper) {
setTimeout(() => {
element
.querySelectorAll('.swiper-slide-active .animated-number')
.forEach((counter: HTMLElement) => {
animateNumber(counter, {});
});
element
.querySelectorAll('.swiper-slide-active .animated-time')
.forEach((counter: HTMLElement) => {
animateNumber(counter, { duration: 1000, render: formatDuration });
});
element
.querySelectorAll('.swiper-slide-active .animated-pulse')
.forEach((counter: HTMLElement) => {
counter.classList.remove('animated-pulse');
setTimeout(() => {
counter.classList.add('animated-pulse');
}, 100);
});
element.querySelectorAll('.swiper-slide-active .lpv').forEach((el: HTMLElement) => {
const lpv = get(el, 'lpv')!;
lpv.goTo('first');
clearTimeout(lpvTimer);
const next = () => {
if (!lpv.canGoTo('next')) return;
lpvTimer = setTimeout(() => {
lpv.goTo('next');
next();
}, 500);
};
next();
});
const slide = element.querySelector('.swiper-slide-active');
if (slide) {
if (swiper.isEnd) swiper.autoplay?.stop();
onSlideChange(slide as HTMLElement);
if (swiper.autoplay?.paused) swiper.autoplay?.resume();
}
}, 200);
},
},
};
new Swiper(element, options);
const swiper = ((window as any).s = new Swiper(element, options));
$(element).on('click', () => {
if (swiper.autoplay && !swiper.isEnd) {
if (swiper.autoplay.paused) swiper.autoplay.resume();
else swiper.autoplay.pause();
}
});
};

let lpvTimer: number | undefined;

function onSlideChange(slide: HTMLElement) {
slide.querySelectorAll('.animated-number').forEach((counter: HTMLElement) => {
animateNumber(counter, {});
});
slide.querySelectorAll('.animated-time').forEach((counter: HTMLElement) => {
animateNumber(counter, { duration: 1000, render: formatDuration });
});
slide.querySelectorAll('.animated-pulse').forEach((counter: HTMLElement) => {
counter.classList.remove('animated-pulse');
setTimeout(() => {
counter.classList.add('animated-pulse');
}, 100);
});
slide.querySelectorAll('.lpv').forEach((el: HTMLElement) => {
const lpv = get(el, 'lpv')!;
lpv.goTo('first');
clearTimeout(lpvTimer);
const next = () => {
if (!lpv.canGoTo('next')) return;
lpvTimer = setTimeout(() => {
lpv.goTo('next');
next();
}, 500);
};
next();
});
}
Loading

0 comments on commit 916b6e9

Please sign in to comment.