Skip to content

Commit 37c60b4

Browse files
committed
tutor badges
1 parent 8bce195 commit 37c60b4

File tree

12 files changed

+74
-57
lines changed

12 files changed

+74
-57
lines changed

modules/tutor/src/main/TutorFullReport.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ case class TutorFullReport(
1212

1313
export config.{ user, id, url }
1414

15-
lazy val nbGames = perfs.toList.map(_.stats.totalNbGames).sum
15+
def stats = perfs.map(_.stats)
16+
17+
lazy val nbGames = stats.totalNbGames
18+
1619
lazy val totalTime: FiniteDuration =
17-
perfs.toList.flatMap(_.estimateTotalTime).foldLeft(0.minutes)(_ + _)
20+
perfs.flatMap(_.estimateTotalTime).foldLeft(0.minutes)(_ + _)
1821

1922
def favouritePerfs: List[TutorPerfReport] = perfs.headOption.so:
2023
_ :: perfs.tailSafe.takeWhile: perf =>
@@ -46,7 +49,7 @@ case class TutorFullReport(
4649
object TutorFullReport:
4750

4851
case class Preview(config: TutorConfig, at: Instant, perfs: List[TutorPerfReport.Preview]):
49-
def nbGames = perfs.map(_.stats.totalNbGames).sum
52+
def stats = perfs.map(_.stats)
5053

5154
object F:
5255
val config = "config"

modules/tutor/src/main/package.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package lila.tutor
33
import chess.IntRating
44

55
import lila.core.perf.UserWithPerfs
6-
import lila.insight.ClockPercent
6+
import lila.insight.{ ClockPercent, InsightPerfStats, MeanRating }
77
export lila.core.lilaism.Lilaism.{ *, given }
88
export lila.common.extensions.*
99

@@ -16,4 +16,9 @@ private given Ordering[GoodPercent] = doubleOrdering
1616

1717
private given Conversion[UserWithPerfs, User] = _.user
1818

19+
extension (stats: List[InsightPerfStats])
20+
def totalNbGames = stats.map(_.totalNbGames).sum
21+
def meanRating = (totalNbGames > 0).option:
22+
MeanRating(stats.map(s => s.rating.value * s.totalNbGames).sum / totalNbGames)
23+
1924
type Angle = "skills" | "opening" | "time" | "phases" | "pieces"

modules/tutor/src/main/ui/TutorBits.scala

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package lila.tutor
22
package ui
33

44
import lila.ui.*
5-
6-
import ScalatagsTemplate.{ *, given }
5+
import lila.ui.ScalatagsTemplate.{ *, given }
76
import lila.rating.PerfType
7+
import lila.insight.MeanRating
88

99
final class TutorBits(helpers: Helpers)(
1010
val openingUrl: chess.opening.Opening => Call
@@ -37,7 +37,20 @@ final class TutorBits(helpers: Helpers)(
3737
frag(print(config.from), "", print(config.to))
3838

3939
def days(config: TutorConfig)(using Translate) =
40-
trans.site.nbDays.plural(config.days, config.days.localize)
40+
trans.site.nbDays.plural(config.days, strong(config.days.localize))
41+
42+
def reportTime(config: TutorConfig)(using Context) =
43+
span(cls := "tutor-badge tutor-badge--time")(
44+
span(cls := "tutor-badge__dates")(dateRange(config)(showDateShort(_))),
45+
span(cls := "tutor-badge__days")(days(config))
46+
)
47+
48+
def reportMeta(nbGames: Int, rating: Option[MeanRating])(using Context) =
49+
val tag = if nbGames == 0 then badTag else span
50+
tag(cls := "tutor-badge tutor-badge--meta")(
51+
span(cls := "tutor-badge__games")(trans.site.nbGames.plural(nbGames, strong(nbGames.localize))),
52+
span(cls := "tutor-badge__rating")(trans.site.rating(), " ", strong(rating.fold("?")(_.toString)))
53+
)
4154

4255
val seeMore = a(cls := "tutor-card__more")("Click to see more...")
4356

modules/tutor/src/main/ui/TutorHomeUi.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ final class TutorHomeUi(helpers: Helpers, bits: TutorBits, q: TutorQueueUi, rps:
4545
bits.mascotSays(q.waitingText(a)),
4646
q.waitingGames(a)
4747
),
48-
div(cls := "box")(rps.list(previews))
48+
rps.list(previews)
4949
)
5050
case None =>
5151
frag(
@@ -59,7 +59,7 @@ final class TutorHomeUi(helpers: Helpers, bits: TutorBits, q: TutorQueueUi, rps:
5959
)
6060
),
6161
rps.newForm(user, form),
62-
div(cls := "box")(rps.list(previews))
62+
rps.list(previews)
6363
)
6464

6565
private def title(user: UserId)(using Context) =

modules/tutor/src/main/ui/TutorReportUi.scala

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,29 @@ final class TutorReportUi(helpers: Helpers, bits: TutorBits, perfUi: TutorPerfUi
99

1010
def apply(full: TutorFullReport)(using Context) =
1111
bits.page(menu = bits.menu(full, none))(cls := "tutor__report tutor-layout"):
12-
val metaTag = if full.perfs.isEmpty then badTag else span
1312
frag(
1413
div(cls := "box")(
1514
boxTop(h1("Lichess Tutor", bits.beta, bits.otherUser(full.user))),
1615
bits.mascotSays(
1716
div(cls := "tutor__report__header")(
18-
span(cls := "tutor__report__dates")(bits.dateRange(full.config)(semanticDate(_))),
19-
metaTag(cls := "tutor__report__meta")(
20-
strong(trans.site.nbGames.plural(full.nbGames, full.nbGames.localize)),
21-
"",
22-
bits.days(full.config)
23-
),
17+
bits.reportTime(full.config),
18+
bits.reportMeta(full.nbGames, full.stats.meanRating),
2419
postForm(
2520
cls := "tutor__report__delete",
2621
action := routes.Tutor.delete(full.user.id, full.config.rangeStr)
2722
):
2823
button(tpe := "submit")(trans.site.delete)
2924
),
30-
full.perfs.nonEmpty.option:
31-
frag(
32-
p(
33-
"Each aspect of your playstyle is compared to other players of similar rating, called \"peers\"."
34-
),
35-
p(
36-
"It should give you some idea about what your strengths are, and where you have room for improvement."
37-
)
25+
if full.perfs.isEmpty then p("Not enough rated games to examine!")
26+
else
27+
p(
28+
"Each aspect of your playstyle is compared to other players of similar rating, called \"peers\".",
29+
br,
30+
"It should give you some idea about what your strengths are, and where you have room for improvement."
3831
)
3932
)
4033
),
41-
tutorConcepts,
34+
full.perfs.nonEmpty.option(tutorConcepts),
4235
div(cls := "tutor__perfs tutor-cards")(
4336
full.perfs.toList.map { perfReportCard(full, _) }
4437
)

modules/tutor/src/main/ui/TutorReportsUi.scala

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import play.api.data.{ Form, Field }
66

77
import lila.ui.*
88
import lila.ui.ScalatagsTemplate.{ *, given }
9+
import lila.insight.MeanRating
910

1011
final class TutorReportsUi(helpers: Helpers, bits: TutorBits):
1112
import helpers.{ *, given }
1213

1314
def newForm(user: UserId, form: Form[?])(using Context) =
1415
postForm(cls := "form3 tutor__report-form", action := routes.Tutor.compute(user.id)):
15-
form3.fieldset("Request a new Tutor report", toggle = form.globalError.pp.isDefined.some)(
16+
form3.fieldset("Request a new Tutor report", toggle = form.globalError.isDefined.some)(
1617
cls := "box-pad"
1718
)(
1819
form3.split(
@@ -24,22 +25,16 @@ final class TutorReportsUi(helpers: Helpers, bits: TutorBits):
2425
)
2526

2627
def list(previews: List[TutorFullReport.Preview])(using Context) =
27-
div(cls := "box tutor__reports-list")(
28-
previews.map(preview)
29-
)
28+
div(cls := "tutor__reports-list")(previews.map(preview))
3029

3130
private def preview(p: TutorFullReport.Preview)(using Context) =
3231
a(
3332
href := p.config.url.root,
3433
cls := List("tutor-preview" -> true, "tutor-preview--empty" -> p.perfs.isEmpty)
3534
)(
36-
span(cls := "tutor-preview__dates")(
37-
span(bits.dateRange(p.config)(showDateShort(_))),
38-
span(
39-
strong(trans.site.nbGames.plural(p.nbGames, p.nbGames.localize)),
40-
"",
41-
bits.days(p.config)
42-
)
35+
span(cls := "tutor-preview__badges")(
36+
bits.reportTime(p.config),
37+
bits.reportMeta(p.stats.totalNbGames, p.stats.meanRating)
4338
),
4439
if p.perfs.isEmpty then badTag(cls := "tutor-preview__empty")("Not enough games!")
4540
else

ui/tutor/css/_badge.scss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.tutor-badge {
2+
@extend %box-radius, %flex-column;
3+
padding: 0.5em 1em;
4+
&--time {
5+
background: $m-brag_bg--mix-20;
6+
}
7+
&--meta {
8+
background: $m-good_bg--mix-20;
9+
&:is(bad) {
10+
background: $m-bad_bg--mix-20;
11+
}
12+
}
13+
}

ui/tutor/css/_home.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,9 @@
2424
list-style-position: inside;
2525
}
2626
}
27+
28+
&__reports-list {
29+
@extend %flex-column;
30+
gap: 0.3em;
31+
}
2732
}

ui/tutor/css/_preview.scss

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
.tutor-preview {
2-
@extend %flex-between-nowrap;
3-
padding: 1em var(---box-padding);
2+
@extend %box-neat, %flex-between-nowrap;
3+
background: $c-bg-box;
4+
padding: 1em 2em;
45
color: $c-font;
56
white-space: nowrap;
67
gap: 2em;
78
overflow: hidden;
89

910
&:hover {
1011
background: $m-primary_bg--mix-10;
12+
color: $c-font-clearer;
1113
}
1214

1315
&--empty {
14-
background: $m-bad_bg--mix-10;
16+
background: $m-bad_bg--mix-05;
1517
&:hover {
16-
background: $m-bad_bg--mix-15;
18+
background: $m-bad_bg--mix-10;
1719
}
1820
}
1921

20-
&__dates {
21-
@extend %flex-column;
22+
&__badges {
23+
@extend %flex-center-nowrap;
24+
gap: 1em;
2225
}
2326
&__perfs {
2427
@extend %flex-center-nowrap;

ui/tutor/css/_report.scss

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,6 @@
44
gap: 1em;
55
margin-bottom: 2em;
66
}
7-
&__dates,
8-
&__meta {
9-
@extend %box-radius;
10-
padding: 0.5em 1em;
11-
}
12-
&__dates {
13-
background: $m-brag_bg--mix-20;
14-
font-weight: bold;
15-
}
16-
&__meta {
17-
background: $m-good_bg--mix-20;
18-
&:is(bad) {
19-
background: $m-bad_bg--mix-20;
20-
}
21-
}
227
&__delete {
238
font-size: 0.9em;
249
button {

0 commit comments

Comments
 (0)