koishi-plugin-ciyi 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/lib/index.js +233 -86
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# koishi-plugin-ciyi
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
词意 · 每天一个两字词,在群里开猜
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -15,11 +15,11 @@ yarn add koishi-plugin-ciyi
|
|
|
15
15
|
| 指令 | 说明 |
|
|
16
16
|
| --- | --- |
|
|
17
17
|
| `ciyi` | 玩法 |
|
|
18
|
-
| `ciyi.猜 <词>` |
|
|
18
|
+
| `ciyi.猜 <词>` | 开始今日对局并报一个两字词 |
|
|
19
19
|
| `ciyi.裸词 [开/关]` | 切换本频道无前缀续猜 |
|
|
20
|
-
| `ciyi.排行榜` |
|
|
20
|
+
| `ciyi.排行榜` | 累计猜中排行榜 |
|
|
21
21
|
|
|
22
|
-
首次用 `ciyi.猜 <词>`
|
|
22
|
+
首次用 `ciyi.猜 <词>` 开题,之后可直接发送两字词继续猜。裸词设置只对当前频道生效,重启后恢复默认。
|
|
23
23
|
|
|
24
24
|
## 许可证
|
|
25
25
|
|
package/lib/index.js
CHANGED
|
@@ -203,6 +203,25 @@ var SHAPE = {
|
|
|
203
203
|
full: 9999
|
|
204
204
|
};
|
|
205
205
|
var FONT_STACK = '"Roboto Flex", "Roboto", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", system-ui, sans-serif';
|
|
206
|
+
var MONO_STACK = '"Roboto Mono", "JetBrains Mono", "SF Mono", "Cascadia Mono", Consolas, "Noto Sans Mono", monospace';
|
|
207
|
+
var TYPE = {
|
|
208
|
+
displayLarge: { size: 57, line: 64, weight: 400, tracking: -0.25 },
|
|
209
|
+
displayMedium: { size: 45, line: 52, weight: 400, tracking: 0 },
|
|
210
|
+
displaySmall: { size: 36, line: 44, weight: 400, tracking: 0 },
|
|
211
|
+
headlineLarge: { size: 32, line: 40, weight: 400, tracking: 0 },
|
|
212
|
+
headlineMedium: { size: 28, line: 36, weight: 400, tracking: 0 },
|
|
213
|
+
headlineSmall: { size: 24, line: 32, weight: 400, tracking: 0 },
|
|
214
|
+
titleLarge: { size: 22, line: 28, weight: 400, tracking: 0 },
|
|
215
|
+
titleMedium: { size: 16, line: 24, weight: 500, tracking: 0.15 },
|
|
216
|
+
titleSmall: { size: 14, line: 20, weight: 500, tracking: 0.1 },
|
|
217
|
+
bodyLarge: { size: 16, line: 24, weight: 400, tracking: 0.5 },
|
|
218
|
+
bodyMedium: { size: 14, line: 20, weight: 400, tracking: 0.25 },
|
|
219
|
+
bodySmall: { size: 12, line: 16, weight: 400, tracking: 0.4 },
|
|
220
|
+
labelLarge: { size: 14, line: 20, weight: 500, tracking: 0.1 },
|
|
221
|
+
labelMedium: { size: 12, line: 16, weight: 500, tracking: 0.5 },
|
|
222
|
+
labelSmall: { size: 11, line: 16, weight: 500, tracking: 0.5 }
|
|
223
|
+
};
|
|
224
|
+
var EMPHASIZED_WEIGHT = { display: 600, headline: 600, title: 600, label: 600 };
|
|
206
225
|
var MEDAL = {
|
|
207
226
|
gold: lch(58, 52, 85),
|
|
208
227
|
silver: lch(66, 5, 260),
|
|
@@ -247,11 +266,13 @@ var C = {
|
|
|
247
266
|
primary: SCHEME.primary,
|
|
248
267
|
onPrimary: SCHEME.onPrimary,
|
|
249
268
|
primaryContainer: SCHEME.primaryContainer,
|
|
250
|
-
onPrimaryContainer: SCHEME.onPrimaryContainer
|
|
269
|
+
onPrimaryContainer: SCHEME.onPrimaryContainer,
|
|
270
|
+
secondaryContainer: SCHEME.secondaryContainer,
|
|
271
|
+
onSecondaryContainer: SCHEME.onSecondaryContainer
|
|
251
272
|
};
|
|
252
273
|
var FRESH = lch(94, 14, HUE);
|
|
253
274
|
var FONT_SANS = FONT_STACK;
|
|
254
|
-
var FONT_NUM = FONT_STACK
|
|
275
|
+
var FONT_NUM = `${MONO_STACK},${FONT_STACK}`;
|
|
255
276
|
function s(n) {
|
|
256
277
|
return Math.round(n * SCALE);
|
|
257
278
|
}
|
|
@@ -317,7 +338,7 @@ function textRight(ctx, text, x, y, font, color, offsetY = 0) {
|
|
|
317
338
|
}
|
|
318
339
|
__name(textRight, "textRight");
|
|
319
340
|
function fontSizeOf(font) {
|
|
320
|
-
return Number(font.match(/([\d.]+)px/)?.[1] ?? s(
|
|
341
|
+
return Number(font.match(/([\d.]+)px/)?.[1] ?? s(TYPE.bodySmall.size));
|
|
321
342
|
}
|
|
322
343
|
__name(fontSizeOf, "fontSizeOf");
|
|
323
344
|
function textWidth(text, fontSize) {
|
|
@@ -378,9 +399,30 @@ async function toPng(service, innerW, innerH, draw) {
|
|
|
378
399
|
}
|
|
379
400
|
__name(toPng, "toPng");
|
|
380
401
|
var GRID = {
|
|
381
|
-
sm: {
|
|
382
|
-
|
|
383
|
-
|
|
402
|
+
sm: {
|
|
403
|
+
cell: 26,
|
|
404
|
+
gap: 4,
|
|
405
|
+
border: 1,
|
|
406
|
+
font: TYPE.labelLarge.size,
|
|
407
|
+
weight: EMPHASIZED_WEIGHT.label,
|
|
408
|
+
radius: SHAPE.extraSmall
|
|
409
|
+
},
|
|
410
|
+
md: {
|
|
411
|
+
cell: 34,
|
|
412
|
+
gap: 4,
|
|
413
|
+
border: 1,
|
|
414
|
+
font: TYPE.titleLarge.size,
|
|
415
|
+
weight: EMPHASIZED_WEIGHT.title,
|
|
416
|
+
radius: SHAPE.small
|
|
417
|
+
},
|
|
418
|
+
lg: {
|
|
419
|
+
cell: 78,
|
|
420
|
+
gap: 9,
|
|
421
|
+
border: 1.5,
|
|
422
|
+
font: TYPE.displayMedium.size,
|
|
423
|
+
weight: EMPHASIZED_WEIGHT.display,
|
|
424
|
+
radius: SHAPE.large
|
|
425
|
+
}
|
|
384
426
|
};
|
|
385
427
|
function gridWidth(word, size) {
|
|
386
428
|
const g = GRID[size];
|
|
@@ -389,9 +431,9 @@ function gridWidth(word, size) {
|
|
|
389
431
|
return s(g.cell * n + g.gap * (n - 1));
|
|
390
432
|
}
|
|
391
433
|
__name(gridWidth, "gridWidth");
|
|
392
|
-
function drawGridCell(ctx, x, y, size, ch, mode,
|
|
434
|
+
function drawGridCell(ctx, x, y, size, ch, mode, g) {
|
|
393
435
|
const half = size / 2;
|
|
394
|
-
const radius =
|
|
436
|
+
const radius = s(g.radius);
|
|
395
437
|
if (mode === "mk") {
|
|
396
438
|
fillRound(ctx, x, y, size, size, radius, C.surfaceContainerHighest);
|
|
397
439
|
ctx.save();
|
|
@@ -404,20 +446,20 @@ function drawGridCell(ctx, x, y, size, ch, mode, fontSize, borderW) {
|
|
|
404
446
|
size - s(1),
|
|
405
447
|
radius,
|
|
406
448
|
C.outline,
|
|
407
|
-
s(
|
|
449
|
+
s(g.border)
|
|
408
450
|
);
|
|
409
451
|
ctx.restore();
|
|
410
452
|
return;
|
|
411
453
|
}
|
|
412
454
|
fillRound(ctx, x, y, size, size, radius, C.surfaceContainerHigh);
|
|
413
455
|
if (ch) {
|
|
414
|
-
const fs = s(
|
|
456
|
+
const fs = s(g.font);
|
|
415
457
|
textCenter(
|
|
416
458
|
ctx,
|
|
417
459
|
ch,
|
|
418
460
|
x + half,
|
|
419
461
|
y + half,
|
|
420
|
-
|
|
462
|
+
`${g.weight} ${fs}px ${FONT_SANS}`,
|
|
421
463
|
C.onSurface,
|
|
422
464
|
cjkOffset(fs)
|
|
423
465
|
);
|
|
@@ -430,15 +472,15 @@ function drawWordGrid(ctx, x, y, word, size, mask) {
|
|
|
430
472
|
const gap = s(g.gap);
|
|
431
473
|
const chars = Array.from(word || "");
|
|
432
474
|
if (chars.length === 0) {
|
|
433
|
-
textCenter(ctx, "—", x + s(14), y + cell / 2, `${s(
|
|
475
|
+
textCenter(ctx, "—", x + s(14), y + cell / 2, `${s(TYPE.bodySmall.size)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
434
476
|
return s(28);
|
|
435
477
|
}
|
|
436
478
|
let cx = x;
|
|
437
479
|
for (let i = 0; i < chars.length; i++) {
|
|
438
480
|
if (i === mask) {
|
|
439
|
-
drawGridCell(ctx, cx, y, cell, null, "mk", g
|
|
481
|
+
drawGridCell(ctx, cx, y, cell, null, "mk", g);
|
|
440
482
|
} else {
|
|
441
|
-
drawGridCell(ctx, cx, y, cell, chars[i], "on", g
|
|
483
|
+
drawGridCell(ctx, cx, y, cell, chars[i], "on", g);
|
|
442
484
|
}
|
|
443
485
|
cx += cell + gap;
|
|
444
486
|
}
|
|
@@ -447,12 +489,12 @@ function drawWordGrid(ctx, x, y, word, size, mask) {
|
|
|
447
489
|
__name(drawWordGrid, "drawWordGrid");
|
|
448
490
|
function drawSeal(ctx, x, y, size, lines) {
|
|
449
491
|
fillRound(ctx, x, y, size, size, s(SHAPE.extraLarge), C.primary);
|
|
450
|
-
const fs = s(
|
|
492
|
+
const fs = s(TYPE.titleLarge.size);
|
|
451
493
|
const lh = fs * 1.06;
|
|
452
494
|
const total = lh * lines.length;
|
|
453
495
|
let cy = y + size / 2 - total / 2 + lh / 2;
|
|
454
496
|
for (const line of lines) {
|
|
455
|
-
textCenter(ctx, line, x + size / 2, cy,
|
|
497
|
+
textCenter(ctx, line, x + size / 2, cy, `${EMPHASIZED_WEIGHT.title} ${fs}px ${FONT_SANS}`, C.onPrimary);
|
|
456
498
|
cy += lh;
|
|
457
499
|
}
|
|
458
500
|
}
|
|
@@ -465,13 +507,20 @@ function drawHeader(ctx, innerX, innerY, innerW, sub, right) {
|
|
|
465
507
|
const h2 = padTop + sealSize + padBottom;
|
|
466
508
|
drawSeal(ctx, innerX + padX, innerY + padTop, sealSize, ["词", "意"]);
|
|
467
509
|
const brandX = innerX + padX + sealSize + s(15);
|
|
468
|
-
textLeft(
|
|
510
|
+
textLeft(
|
|
511
|
+
ctx,
|
|
512
|
+
"词意",
|
|
513
|
+
brandX,
|
|
514
|
+
innerY + padTop + s(14),
|
|
515
|
+
`${EMPHASIZED_WEIGHT.headline} ${s(TYPE.headlineMedium.size)}px ${FONT_SANS}`,
|
|
516
|
+
C.onSurface
|
|
517
|
+
);
|
|
469
518
|
textLeft(
|
|
470
519
|
ctx,
|
|
471
520
|
"ci yi",
|
|
472
521
|
brandX,
|
|
473
522
|
innerY + padTop + s(36),
|
|
474
|
-
`italic ${s(
|
|
523
|
+
`italic ${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
475
524
|
C.onSurfaceVariant
|
|
476
525
|
);
|
|
477
526
|
const subRight = right ? innerX + innerW - padX - s(150) : innerX + innerW - padX;
|
|
@@ -481,13 +530,27 @@ function drawHeader(ctx, innerX, innerY, innerW, sub, right) {
|
|
|
481
530
|
brandX,
|
|
482
531
|
innerY + padTop + s(58),
|
|
483
532
|
subRight - brandX,
|
|
484
|
-
`${s(
|
|
533
|
+
`${s(TYPE.bodySmall.size)}px ${FONT_SANS}`,
|
|
485
534
|
C.onSurfaceVariant
|
|
486
535
|
);
|
|
487
536
|
if (right) {
|
|
488
537
|
const rx = innerX + innerW - padX;
|
|
489
|
-
textRight(
|
|
490
|
-
|
|
538
|
+
textRight(
|
|
539
|
+
ctx,
|
|
540
|
+
right.big,
|
|
541
|
+
rx,
|
|
542
|
+
innerY + padTop + s(16),
|
|
543
|
+
`${EMPHASIZED_WEIGHT.headline} ${s(TYPE.headlineLarge.size)}px ${FONT_NUM}`,
|
|
544
|
+
C.primary
|
|
545
|
+
);
|
|
546
|
+
textRight(
|
|
547
|
+
ctx,
|
|
548
|
+
right.cap,
|
|
549
|
+
rx,
|
|
550
|
+
innerY + padTop + s(44),
|
|
551
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
552
|
+
C.onSurfaceVariant
|
|
553
|
+
);
|
|
491
554
|
}
|
|
492
555
|
const lineY = innerY + h2;
|
|
493
556
|
ctx.strokeStyle = C.outlineVariant;
|
|
@@ -525,16 +588,16 @@ function drawFooter(ctx, innerX, y, innerW, legendItems, tip) {
|
|
|
525
588
|
for (const { tier, range } of legendItems) {
|
|
526
589
|
fillRound(ctx, lx, cy - s(4.5), s(9), s(9), s(SHAPE.full), tier.color);
|
|
527
590
|
lx += s(9) + s(6);
|
|
528
|
-
textLeft(ctx, tier.name, lx, cy, `${s(
|
|
529
|
-
lx += textWidth(tier.name, s(
|
|
530
|
-
textLeft(ctx, range, lx, cy, `${s(
|
|
531
|
-
lx += textWidth(range, s(
|
|
591
|
+
textLeft(ctx, tier.name, lx, cy, `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
592
|
+
lx += textWidth(tier.name, s(TYPE.labelSmall.size)) + s(4);
|
|
593
|
+
textLeft(ctx, range, lx, cy, `${s(TYPE.labelSmall.size)}px ${FONT_NUM}`, C.onSurfaceVariant);
|
|
594
|
+
lx += textWidth(range, s(TYPE.labelSmall.size)) + s(13);
|
|
532
595
|
}
|
|
533
|
-
const tipFont = `${s(
|
|
596
|
+
const tipFont = `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`;
|
|
534
597
|
const maxTipWidth = legendItems.length ? s(145) : innerW - padX * 2;
|
|
535
598
|
textRight(
|
|
536
599
|
ctx,
|
|
537
|
-
ellipsize(tip, maxTipWidth, s(
|
|
600
|
+
ellipsize(tip, maxTipWidth, s(TYPE.labelSmall.size)),
|
|
538
601
|
innerX + innerW - padX,
|
|
539
602
|
cy,
|
|
540
603
|
tipFont,
|
|
@@ -551,17 +614,24 @@ function drawLegendFull(ctx, x, y, w) {
|
|
|
551
614
|
const cx = x + i % 2 * colW;
|
|
552
615
|
const cy = y + Math.floor(i / 2) * rowH;
|
|
553
616
|
fillRound(ctx, cx, cy - s(4.5), s(9), s(9), s(SHAPE.full), t.color);
|
|
554
|
-
textLeft(ctx, t.name, cx + s(15), cy, `${s(
|
|
555
|
-
textLeft(ctx, tierRange(i), cx + s(52), cy, `${s(
|
|
556
|
-
textLeft(ctx, t.note, cx + s(100), cy, `${s(
|
|
617
|
+
textLeft(ctx, t.name, cx + s(15), cy, `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
618
|
+
textLeft(ctx, tierRange(i), cx + s(52), cy, `${s(TYPE.labelSmall.size)}px ${FONT_NUM}`, C.onSurfaceVariant);
|
|
619
|
+
textLeft(ctx, t.note, cx + s(100), cy, `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
557
620
|
}
|
|
558
621
|
return rowH * Math.ceil(TIERS.length / 2) + s(8);
|
|
559
622
|
}
|
|
560
623
|
__name(drawLegendFull, "drawLegendFull");
|
|
561
624
|
function drawSectionTitle(ctx, x, y, w, title) {
|
|
562
625
|
fillRound(ctx, x, y - s(1), s(3), s(12), s(SHAPE.full), C.primary);
|
|
563
|
-
textLeft(
|
|
564
|
-
|
|
626
|
+
textLeft(
|
|
627
|
+
ctx,
|
|
628
|
+
title,
|
|
629
|
+
x + s(15),
|
|
630
|
+
y + s(5),
|
|
631
|
+
`${EMPHASIZED_WEIGHT.label} ${s(TYPE.labelMedium.size)}px ${FONT_SANS}`,
|
|
632
|
+
C.onSurfaceVariant
|
|
633
|
+
);
|
|
634
|
+
const tw = textWidth(title, s(TYPE.labelMedium.size));
|
|
565
635
|
ctx.strokeStyle = C.outlineVariant;
|
|
566
636
|
ctx.lineWidth = s(1);
|
|
567
637
|
ctx.beginPath();
|
|
@@ -581,7 +651,7 @@ function drawNearBar(ctx, x, y, pct, tier) {
|
|
|
581
651
|
const gap = s(3);
|
|
582
652
|
const fillW = Math.max(barH, barW * pct / 100);
|
|
583
653
|
const top = y - barH / 2;
|
|
584
|
-
fillRound(ctx, x, top, fillW, barH,
|
|
654
|
+
fillRound(ctx, x, top, fillW, barH, s(SHAPE.full), tier.color);
|
|
585
655
|
if (fillW + gap < barW) {
|
|
586
656
|
fillRound(
|
|
587
657
|
ctx,
|
|
@@ -589,11 +659,18 @@ function drawNearBar(ctx, x, y, pct, tier) {
|
|
|
589
659
|
top,
|
|
590
660
|
barW - fillW - gap,
|
|
591
661
|
barH,
|
|
592
|
-
|
|
662
|
+
s(SHAPE.full),
|
|
593
663
|
C.surfaceContainerHighest
|
|
594
664
|
);
|
|
595
665
|
}
|
|
596
|
-
textLeft(
|
|
666
|
+
textLeft(
|
|
667
|
+
ctx,
|
|
668
|
+
tier.name,
|
|
669
|
+
x + barW + s(9),
|
|
670
|
+
y,
|
|
671
|
+
`${EMPHASIZED_WEIGHT.label} ${s(TYPE.labelMedium.size)}px ${FONT_SANS}`,
|
|
672
|
+
tier.color
|
|
673
|
+
);
|
|
597
674
|
}
|
|
598
675
|
__name(drawNearBar, "drawNearBar");
|
|
599
676
|
function measureBoard(opts) {
|
|
@@ -633,10 +710,10 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
633
710
|
const rk0 = nb1 + cols.nb;
|
|
634
711
|
const mt0 = rk0 + cols.rk;
|
|
635
712
|
const noX = bx + s(2);
|
|
636
|
-
const meterBlockW = s(88) + s(9) + textWidth("咫尺", s(
|
|
713
|
+
const meterBlockW = s(88) + s(9) + textWidth("咫尺", s(TYPE.labelMedium.size));
|
|
637
714
|
const mtX = mt0 + Math.max(0, (cols.mt - meterBlockW) / 2);
|
|
638
715
|
const headY = y;
|
|
639
|
-
const fs = s(
|
|
716
|
+
const fs = s(TYPE.labelSmall.size);
|
|
640
717
|
textLeft(ctx, "序", noX, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
641
718
|
textCenter(ctx, "更近 ◀", nb0 + cols.nb / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
642
719
|
textCenter(ctx, "猜测", gw0 + cols.gw / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
@@ -653,7 +730,7 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
653
730
|
`…… 另有 ${row.gapBefore} 词未列`,
|
|
654
731
|
cx + tableW / 2,
|
|
655
732
|
ry + s(10),
|
|
656
|
-
`${s(
|
|
733
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
657
734
|
C.onSurfaceVariant
|
|
658
735
|
);
|
|
659
736
|
ctx.strokeStyle = C.outlineVariant;
|
|
@@ -683,7 +760,7 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
683
760
|
String(ordinal).padStart(2, "0"),
|
|
684
761
|
noX,
|
|
685
762
|
midY,
|
|
686
|
-
`${s(
|
|
763
|
+
`${s(TYPE.labelMedium.size)}px ${FONT_NUM}`,
|
|
687
764
|
C.onSurfaceVariant
|
|
688
765
|
);
|
|
689
766
|
const nbX = nb0 + (cols.nb - gridWidth(history.leftHint, "sm")) / 2;
|
|
@@ -693,12 +770,12 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
693
770
|
const rbX = nb1 + (cols.nb - gridWidth(history.rightHint, "sm")) / 2;
|
|
694
771
|
drawWordGrid(ctx, rbX, midY - s(13), history.rightHint, "sm", 1);
|
|
695
772
|
const rankText = String(history.rank);
|
|
696
|
-
const rankFont =
|
|
697
|
-
const rankWidth = textWidth(rankText, s(
|
|
698
|
-
const hashW = textWidth("#", s(
|
|
773
|
+
const rankFont = `${EMPHASIZED_WEIGHT.title} ${s(TYPE.titleLarge.size)}px ${FONT_NUM}`;
|
|
774
|
+
const rankWidth = textWidth(rankText, s(TYPE.titleLarge.size));
|
|
775
|
+
const hashW = textWidth("#", s(TYPE.labelMedium.size));
|
|
699
776
|
const rankBlock = hashW + s(3) + rankWidth;
|
|
700
777
|
const rankLeft = rk0 + (cols.rk - rankBlock) / 2;
|
|
701
|
-
textLeft(ctx, "#", rankLeft, midY, `${s(
|
|
778
|
+
textLeft(ctx, "#", rankLeft, midY, `${s(TYPE.labelMedium.size)}px ${FONT_NUM}`, C.onSurfaceVariant);
|
|
702
779
|
textLeft(ctx, rankText, rankLeft + hashW + s(3), midY, rankFont, tier.color);
|
|
703
780
|
drawNearBar(ctx, mtX, midY, pct, tier);
|
|
704
781
|
ry += rowH;
|
|
@@ -740,31 +817,59 @@ function renderIntroCard(service, opts) {
|
|
|
740
817
|
y += s(11);
|
|
741
818
|
const p1h = s(104);
|
|
742
819
|
drawPanel(ctx, ix + s(22), y, iw - s(44), p1h);
|
|
743
|
-
textLeft(ctx, "开始", ix + s(38), y + s(24), `${s(
|
|
744
|
-
textLeft(
|
|
820
|
+
textLeft(ctx, "开始", ix + s(38), y + s(24), `${s(TYPE.labelLarge.size)}px ${FONT_SANS}`, C.primary);
|
|
821
|
+
textLeft(
|
|
822
|
+
ctx,
|
|
823
|
+
"ciyi.猜 山水",
|
|
824
|
+
ix + s(96),
|
|
825
|
+
y + s(24),
|
|
826
|
+
`${s(TYPE.labelLarge.size)}px ${FONT_SANS}`,
|
|
827
|
+
C.onSurface
|
|
828
|
+
);
|
|
745
829
|
textLeftFit(
|
|
746
830
|
ctx,
|
|
747
831
|
`开题并报一个两字词${opts.middleware ? ";开题后可直接发词" : ""}`,
|
|
748
832
|
ix + s(230),
|
|
749
833
|
y + s(24),
|
|
750
834
|
iw - s(268),
|
|
751
|
-
`${s(
|
|
835
|
+
`${s(TYPE.bodyMedium.size)}px ${FONT_SANS}`,
|
|
836
|
+
C.onSurface
|
|
837
|
+
);
|
|
838
|
+
textLeft(ctx, "切换", ix + s(38), y + s(52), `${s(TYPE.labelLarge.size)}px ${FONT_SANS}`, C.primary);
|
|
839
|
+
textLeft(
|
|
840
|
+
ctx,
|
|
841
|
+
"ciyi.裸词 开/关",
|
|
842
|
+
ix + s(96),
|
|
843
|
+
y + s(52),
|
|
844
|
+
`${s(TYPE.labelLarge.size)}px ${FONT_SANS}`,
|
|
752
845
|
C.onSurface
|
|
753
846
|
);
|
|
754
|
-
textLeft(ctx, "切换", ix + s(38), y + s(52), `${s(14)}px ${FONT_SANS}`, C.primary);
|
|
755
|
-
textLeft(ctx, "ciyi.裸词 开/关", ix + s(96), y + s(52), `${s(13.5)}px ${FONT_NUM}`, C.onSurface);
|
|
756
847
|
textLeftFit(
|
|
757
848
|
ctx,
|
|
758
849
|
"临时改本频道的续猜方式",
|
|
759
850
|
ix + s(230),
|
|
760
851
|
y + s(52),
|
|
761
852
|
iw - s(268),
|
|
762
|
-
`${s(
|
|
853
|
+
`${s(TYPE.bodyMedium.size)}px ${FONT_SANS}`,
|
|
854
|
+
C.onSurface
|
|
855
|
+
);
|
|
856
|
+
textLeft(ctx, "排行", ix + s(38), y + s(80), `${s(TYPE.labelLarge.size)}px ${FONT_SANS}`, C.primary);
|
|
857
|
+
textLeft(
|
|
858
|
+
ctx,
|
|
859
|
+
"ciyi.排行榜",
|
|
860
|
+
ix + s(96),
|
|
861
|
+
y + s(80),
|
|
862
|
+
`${s(TYPE.labelLarge.size)}px ${FONT_SANS}`,
|
|
863
|
+
C.onSurface
|
|
864
|
+
);
|
|
865
|
+
textLeft(
|
|
866
|
+
ctx,
|
|
867
|
+
"看谁猜中得最多",
|
|
868
|
+
ix + s(230),
|
|
869
|
+
y + s(80),
|
|
870
|
+
`${s(TYPE.bodyMedium.size)}px ${FONT_SANS}`,
|
|
763
871
|
C.onSurface
|
|
764
872
|
);
|
|
765
|
-
textLeft(ctx, "排行", ix + s(38), y + s(80), `${s(14)}px ${FONT_SANS}`, C.primary);
|
|
766
|
-
textLeft(ctx, "ciyi.排行榜", ix + s(96), y + s(80), `${s(13.5)}px ${FONT_NUM}`, C.onSurface);
|
|
767
|
-
textLeft(ctx, "看谁猜中得最多", ix + s(230), y + s(80), `${s(14)}px ${FONT_SANS}`, C.onSurface);
|
|
768
873
|
y += p1h + s(19);
|
|
769
874
|
y += drawSectionTitle(ctx, ix + s(22), y, iw - s(44), "读板");
|
|
770
875
|
y += s(11);
|
|
@@ -788,7 +893,7 @@ function renderIntroCard(service, opts) {
|
|
|
788
893
|
"这一行是说:「企业」与今日答案的意思相近程度,排在第 467 位。",
|
|
789
894
|
ix + s(38),
|
|
790
895
|
y + s(104),
|
|
791
|
-
`${s(
|
|
896
|
+
`${s(TYPE.bodySmall.size)}px ${FONT_SANS}`,
|
|
792
897
|
C.onSurfaceVariant
|
|
793
898
|
);
|
|
794
899
|
textLeft(
|
|
@@ -796,7 +901,7 @@ function renderIntroCard(service, opts) {
|
|
|
796
901
|
"两侧空格各藏一字:左邻更近,右邻更远。",
|
|
797
902
|
ix + s(38),
|
|
798
903
|
y + s(126),
|
|
799
|
-
`${s(
|
|
904
|
+
`${s(TYPE.bodySmall.size)}px ${FONT_SANS}`,
|
|
800
905
|
C.onSurfaceVariant
|
|
801
906
|
);
|
|
802
907
|
textLeft(
|
|
@@ -804,7 +909,7 @@ function renderIntroCard(service, opts) {
|
|
|
804
909
|
"名次越小,离答案越近;#1 就是答案本身。",
|
|
805
910
|
ix + s(38),
|
|
806
911
|
y + s(148),
|
|
807
|
-
`${s(
|
|
912
|
+
`${s(TYPE.bodySmall.size)}px ${FONT_SANS}`,
|
|
808
913
|
C.onSurfaceVariant
|
|
809
914
|
);
|
|
810
915
|
y += sampleH + s(19);
|
|
@@ -827,7 +932,7 @@ function renderIntroCard(service, opts) {
|
|
|
827
932
|
"一日一词,猜中即止,次日零点换题",
|
|
828
933
|
ix + s(22),
|
|
829
934
|
iy + ih - s(30),
|
|
830
|
-
`${s(
|
|
935
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
831
936
|
C.onSurfaceVariant
|
|
832
937
|
);
|
|
833
938
|
});
|
|
@@ -842,37 +947,44 @@ function renderWinCard(service, opts) {
|
|
|
842
947
|
const revealH = s(130);
|
|
843
948
|
drawPanel(ctx, ix + s(22), y, iw - s(44), revealH);
|
|
844
949
|
drawSeal(ctx, ix + iw - s(80), y - s(13), s(42), ["中"]);
|
|
845
|
-
textLeft(ctx, "今日答案", ix + s(38), y + s(24), `${s(
|
|
950
|
+
textLeft(ctx, "今日答案", ix + s(38), y + s(24), `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
846
951
|
drawWordGrid(ctx, ix + s(38), y + s(40), opts.answer, "lg");
|
|
847
952
|
const ax = ix + iw - s(310);
|
|
848
953
|
if (opts.neighbors.length) {
|
|
849
|
-
textLeft(ctx, "意思最近的几个词", ax, y + s(24), `${s(
|
|
954
|
+
textLeft(ctx, "意思最近的几个词", ax, y + s(24), `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
850
955
|
let nx = ax;
|
|
851
956
|
let ny = y + s(48);
|
|
852
|
-
const chipFont = `${s(
|
|
957
|
+
const chipFont = `${s(TYPE.labelLarge.size)}px ${FONT_SANS}`;
|
|
853
958
|
const chipRight = ix + iw - s(38);
|
|
854
959
|
for (const word of opts.neighbors) {
|
|
855
|
-
const fittedWord = ellipsize(word, s(116), s(
|
|
856
|
-
const pw = textWidth(fittedWord, s(
|
|
960
|
+
const fittedWord = ellipsize(word, s(116), s(TYPE.labelLarge.size));
|
|
961
|
+
const pw = textWidth(fittedWord, s(TYPE.labelLarge.size)) + s(20);
|
|
857
962
|
if (nx !== ax && nx + pw > chipRight) {
|
|
858
963
|
nx = ax;
|
|
859
964
|
ny += s(36);
|
|
860
965
|
}
|
|
861
966
|
if (ny + s(14) > y + revealH - s(12)) break;
|
|
862
|
-
fillRound(ctx, nx, ny - s(14), pw, s(28), s(SHAPE.full),
|
|
967
|
+
fillRound(ctx, nx, ny - s(14), pw, s(28), s(SHAPE.full), C.secondaryContainer);
|
|
863
968
|
textCenter(
|
|
864
969
|
ctx,
|
|
865
970
|
fittedWord,
|
|
866
971
|
nx + pw / 2,
|
|
867
972
|
ny,
|
|
868
973
|
chipFont,
|
|
869
|
-
|
|
870
|
-
cjkOffset(s(
|
|
974
|
+
C.onSecondaryContainer,
|
|
975
|
+
cjkOffset(s(TYPE.labelLarge.size))
|
|
871
976
|
);
|
|
872
977
|
nx += pw + s(7);
|
|
873
978
|
}
|
|
874
979
|
} else {
|
|
875
|
-
textLeft(
|
|
980
|
+
textLeft(
|
|
981
|
+
ctx,
|
|
982
|
+
"今日一词,就此收笔。",
|
|
983
|
+
ax,
|
|
984
|
+
y + s(50),
|
|
985
|
+
`${s(TYPE.bodyMedium.size)}px ${FONT_SANS}`,
|
|
986
|
+
C.onSurfaceVariant
|
|
987
|
+
);
|
|
876
988
|
}
|
|
877
989
|
y += revealH + s(14);
|
|
878
990
|
const statW = (iw - s(44) - s(20)) / 3;
|
|
@@ -884,11 +996,32 @@ function renderWinCard(service, opts) {
|
|
|
884
996
|
for (let i = 0; i < 3; i++) {
|
|
885
997
|
const sx = ix + s(22) + i * (statW + s(10));
|
|
886
998
|
drawPanel(ctx, sx, y, statW, s(56));
|
|
887
|
-
textLeft(
|
|
999
|
+
textLeft(
|
|
1000
|
+
ctx,
|
|
1001
|
+
stats[i].n,
|
|
1002
|
+
sx + s(14),
|
|
1003
|
+
y + s(22),
|
|
1004
|
+
`${EMPHASIZED_WEIGHT.headline} ${s(TYPE.headlineSmall.size)}px ${FONT_NUM}`,
|
|
1005
|
+
C.primary
|
|
1006
|
+
);
|
|
888
1007
|
if (stats[i].u) {
|
|
889
|
-
textLeft(
|
|
1008
|
+
textLeft(
|
|
1009
|
+
ctx,
|
|
1010
|
+
stats[i].u,
|
|
1011
|
+
sx + s(14) + textWidth(stats[i].n, s(TYPE.headlineSmall.size)) + s(3),
|
|
1012
|
+
y + s(26),
|
|
1013
|
+
`${s(TYPE.labelMedium.size)}px ${FONT_SANS}`,
|
|
1014
|
+
C.onSurfaceVariant
|
|
1015
|
+
);
|
|
890
1016
|
}
|
|
891
|
-
textLeft(
|
|
1017
|
+
textLeft(
|
|
1018
|
+
ctx,
|
|
1019
|
+
stats[i].c,
|
|
1020
|
+
sx + s(14),
|
|
1021
|
+
y + s(44),
|
|
1022
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
1023
|
+
C.onSurfaceVariant
|
|
1024
|
+
);
|
|
892
1025
|
}
|
|
893
1026
|
const quip = opts.closest === null ? "一击即中,今日无需第二次落笔" : `从 #${opts.closest} 一步跨到 #1`;
|
|
894
1027
|
const footerTip = opts.canStartToday ? "ciyi.猜 山水 · 开启今日新题" : "明日零点换新题 · ciyi.排行榜";
|
|
@@ -900,8 +1033,8 @@ function renderWinCard(service, opts) {
|
|
|
900
1033
|
[],
|
|
901
1034
|
footerTip
|
|
902
1035
|
);
|
|
903
|
-
const footerFont = `${s(
|
|
904
|
-
const footerTipWidth = textWidth(footerTip, s(
|
|
1036
|
+
const footerFont = `${s(TYPE.labelSmall.size)}px ${FONT_SANS}`;
|
|
1037
|
+
const footerTipWidth = textWidth(footerTip, s(TYPE.labelSmall.size));
|
|
905
1038
|
textLeftFit(
|
|
906
1039
|
ctx,
|
|
907
1040
|
`${opts.username} 拿下今日一词 · ${quip}`,
|
|
@@ -941,10 +1074,10 @@ function renderRankCard(service, opts) {
|
|
|
941
1074
|
if (!opts.entries.length) {
|
|
942
1075
|
textCenter(
|
|
943
1076
|
ctx,
|
|
944
|
-
"
|
|
1077
|
+
"排行榜还空着",
|
|
945
1078
|
panelX + panelW / 2,
|
|
946
1079
|
y + s(31),
|
|
947
|
-
`${s(
|
|
1080
|
+
`${s(TYPE.bodyMedium.size)}px ${FONT_SANS}`,
|
|
948
1081
|
C.onSurfaceVariant
|
|
949
1082
|
);
|
|
950
1083
|
textCenter(
|
|
@@ -952,7 +1085,7 @@ function renderRankCard(service, opts) {
|
|
|
952
1085
|
"今日第一个猜中的人,会写在这里。",
|
|
953
1086
|
panelX + panelW / 2,
|
|
954
1087
|
y + s(61),
|
|
955
|
-
`${s(
|
|
1088
|
+
`${s(TYPE.bodyMedium.size)}px ${FONT_SANS}`,
|
|
956
1089
|
C.onSurfaceVariant
|
|
957
1090
|
);
|
|
958
1091
|
} else {
|
|
@@ -974,35 +1107,49 @@ function renderRankCard(service, opts) {
|
|
|
974
1107
|
const px = contentLeft;
|
|
975
1108
|
const py = midY - posSize / 2;
|
|
976
1109
|
const podium = [MEDAL.gold, MEDAL.silver, MEDAL.bronze];
|
|
977
|
-
const pc = i < 3 ? { bg: podium[i], fg:
|
|
1110
|
+
const pc = i < 3 ? { bg: podium[i], fg: C.onPrimary } : { bg: C.surfaceContainerHighest, fg: C.onSurfaceVariant };
|
|
978
1111
|
fillRound(ctx, px, py, posSize, posSize, s(SHAPE.full), pc.bg);
|
|
979
|
-
textCenter(
|
|
1112
|
+
textCenter(
|
|
1113
|
+
ctx,
|
|
1114
|
+
String(i + 1),
|
|
1115
|
+
px + posSize / 2,
|
|
1116
|
+
midY,
|
|
1117
|
+
`${EMPHASIZED_WEIGHT.label} ${s(TYPE.labelLarge.size)}px ${FONT_NUM}`,
|
|
1118
|
+
pc.fg
|
|
1119
|
+
);
|
|
980
1120
|
const name2 = e.username || "无名氏";
|
|
981
1121
|
const nameX = px + posSize + s(14);
|
|
982
|
-
const nameFont = `${s(
|
|
1122
|
+
const nameFont = `${s(TYPE.titleMedium.size)}px ${FONT_SANS}`;
|
|
983
1123
|
const score = String(e.score);
|
|
984
|
-
const unitFont = s(
|
|
1124
|
+
const unitFont = s(TYPE.labelSmall.size);
|
|
985
1125
|
const unitW = textWidth("次", unitFont);
|
|
986
|
-
const scoreFont = s(
|
|
1126
|
+
const scoreFont = s(TYPE.titleLarge.size);
|
|
987
1127
|
const scoreRight = contentRight - unitW - s(8);
|
|
988
1128
|
const scoreLeft = scoreRight - textWidth(score, scoreFont);
|
|
989
|
-
const meWidth = e.me ? textWidth("我", s(
|
|
1129
|
+
const meWidth = e.me ? textWidth("我", s(TYPE.labelSmall.size)) + s(18) : 0;
|
|
990
1130
|
const fittedName = ellipsize(
|
|
991
1131
|
name2,
|
|
992
1132
|
Math.max(0, scoreLeft - s(16) - nameX - meWidth),
|
|
993
|
-
s(
|
|
1133
|
+
s(TYPE.titleMedium.size)
|
|
994
1134
|
);
|
|
995
1135
|
textLeft(ctx, fittedName, nameX, midY, nameFont, C.onSurface);
|
|
996
1136
|
if (e.me) {
|
|
997
|
-
const nw = textWidth(fittedName, s(
|
|
998
|
-
textLeft(
|
|
1137
|
+
const nw = textWidth(fittedName, s(TYPE.titleMedium.size));
|
|
1138
|
+
textLeft(
|
|
1139
|
+
ctx,
|
|
1140
|
+
"我",
|
|
1141
|
+
nameX + nw + s(8),
|
|
1142
|
+
midY,
|
|
1143
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
1144
|
+
C.primary
|
|
1145
|
+
);
|
|
999
1146
|
}
|
|
1000
1147
|
textRight(
|
|
1001
1148
|
ctx,
|
|
1002
1149
|
score,
|
|
1003
1150
|
scoreRight,
|
|
1004
1151
|
midY,
|
|
1005
|
-
|
|
1152
|
+
`${EMPHASIZED_WEIGHT.title} ${scoreFont}px ${FONT_NUM}`,
|
|
1006
1153
|
C.onSurface
|
|
1007
1154
|
);
|
|
1008
1155
|
textRight(ctx, "次", contentRight, midY, `${unitFont}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
@@ -1014,7 +1161,7 @@ function renderRankCard(service, opts) {
|
|
|
1014
1161
|
`…… 另有 ${opts.hidden} 人在榜`,
|
|
1015
1162
|
contentLeft,
|
|
1016
1163
|
ry + s(16),
|
|
1017
|
-
`${s(
|
|
1164
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
1018
1165
|
C.onSurfaceVariant
|
|
1019
1166
|
);
|
|
1020
1167
|
}
|
|
@@ -1032,7 +1179,7 @@ function renderRankCard(service, opts) {
|
|
|
1032
1179
|
"每猜中一日之词,记一次",
|
|
1033
1180
|
panelX,
|
|
1034
1181
|
iy + ih - s(30),
|
|
1035
|
-
`${s(
|
|
1182
|
+
`${s(TYPE.labelSmall.size)}px ${FONT_SANS}`,
|
|
1036
1183
|
C.onSurfaceVariant
|
|
1037
1184
|
);
|
|
1038
1185
|
});
|
|
@@ -1310,7 +1457,7 @@ function apply(ctx, cfg) {
|
|
|
1310
1457
|
__name(middlewareSwitchText, "middlewareSwitchText");
|
|
1311
1458
|
function winText(o) {
|
|
1312
1459
|
return textCard(
|
|
1313
|
-
"猜中了 · 今日已封题",
|
|
1460
|
+
"🏆 猜中了 · 今日已封题",
|
|
1314
1461
|
`答案 ${o.answer}`,
|
|
1315
1462
|
[
|
|
1316
1463
|
`猜测 ${o.attempts} 次`,
|