maidraw 0.3.1 → 0.4.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/assets/themes/cn/2024Landscape/manifest.json +9 -0
- package/assets/themes/cn/2024Portrait/manifest.json +18 -0
- package/assets/themes/jp/buddiesLandscape/manifest.json +9 -0
- package/assets/themes/jp/buddiesPlusLandscape/manifest.json +9 -0
- package/assets/themes/jp/buddiesPlusPortrait/manifest.json +18 -0
- package/assets/themes/jp/buddiesPortrait/manifest.json +18 -0
- package/assets/themes/jp/finaleLandscape/manifest.json +9 -0
- package/assets/themes/jp/finalePortrait/manifest.json +18 -0
- package/assets/themes/jp/prismLandscape/manifest.json +9 -0
- package/assets/themes/jp/prismPlusLandscape/manifest.json +9 -0
- package/assets/themes/jp/prismPlusPortrait/manifest.json +18 -0
- package/assets/themes/jp/prismPortrait/manifest.json +18 -0
- package/dist/mai/best50/index.d.ts +6 -1
- package/dist/mai/best50/index.js +489 -538
- package/dist/mai/best50/index.js.map +1 -1
- package/dist/mai/best50/lib/divingFish/index.d.ts +5 -7
- package/dist/mai/best50/lib/divingFish/index.js +5 -43
- package/dist/mai/best50/lib/divingFish/index.js.map +1 -1
- package/dist/mai/best50/lib/index.d.ts +16 -1
- package/dist/mai/best50/lib/index.js +83 -2
- package/dist/mai/best50/lib/index.js.map +1 -1
- package/dist/mai/best50/lib/kamaiTachi/index.d.ts +5 -8
- package/dist/mai/best50/lib/kamaiTachi/index.js +81 -75
- package/dist/mai/best50/lib/kamaiTachi/index.js.map +1 -1
- package/dist/mai/best50/lib/lxns/index.d.ts +5 -9
- package/dist/mai/best50/lib/lxns/index.js +13 -57
- package/dist/mai/best50/lib/lxns/index.js.map +1 -1
- package/dist/mai/best50/type.d.ts +145 -0
- package/dist/mai/best50/type.js +3 -0
- package/dist/mai/best50/type.js.map +1 -0
- package/dist/type.d.ts +0 -106
- package/package.json +3 -1
package/dist/mai/best50/index.js
CHANGED
|
@@ -118,6 +118,12 @@ class Best50 {
|
|
|
118
118
|
else
|
|
119
119
|
return false;
|
|
120
120
|
}
|
|
121
|
+
function isUndefined(p) {
|
|
122
|
+
return typeof p == "undefined";
|
|
123
|
+
}
|
|
124
|
+
function isBoolean(p) {
|
|
125
|
+
return typeof p == "boolean";
|
|
126
|
+
}
|
|
121
127
|
if (isString(payload.displayName) &&
|
|
122
128
|
isString(payload.name) &&
|
|
123
129
|
isNumber(payload.width) &&
|
|
@@ -210,6 +216,28 @@ class Best50 {
|
|
|
210
216
|
else
|
|
211
217
|
return false;
|
|
212
218
|
}
|
|
219
|
+
case "text": {
|
|
220
|
+
if (isNumber(element.size) &&
|
|
221
|
+
isString(element.content) &&
|
|
222
|
+
(isUndefined(element.width) ||
|
|
223
|
+
isNumber(element.width)) &&
|
|
224
|
+
(isUndefined(element.height) ||
|
|
225
|
+
isNumber(element.height)) &&
|
|
226
|
+
(isUndefined(element.linebreak) ||
|
|
227
|
+
isBoolean(element.linebreak)) &&
|
|
228
|
+
(isUndefined(element.align) ||
|
|
229
|
+
isOneOf(element.align, "left", "center", "right")) &&
|
|
230
|
+
(isUndefined(element.color) ||
|
|
231
|
+
isString(element.color)) &&
|
|
232
|
+
(isUndefined(element.borderColor) ||
|
|
233
|
+
isString(element.borderColor)) &&
|
|
234
|
+
(isUndefined(element.font) ||
|
|
235
|
+
isString(element.font))) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
213
241
|
default:
|
|
214
242
|
return false;
|
|
215
243
|
}
|
|
@@ -221,12 +249,10 @@ class Best50 {
|
|
|
221
249
|
return false;
|
|
222
250
|
}
|
|
223
251
|
static primaryTheme = null;
|
|
224
|
-
static primaryThemePath = null;
|
|
225
252
|
static loadTheme(path) {
|
|
226
253
|
const theme = this.getTheme(path);
|
|
227
254
|
if (theme) {
|
|
228
|
-
this.primaryTheme = theme
|
|
229
|
-
this.primaryThemePath = theme.path;
|
|
255
|
+
this.primaryTheme = theme;
|
|
230
256
|
return true;
|
|
231
257
|
}
|
|
232
258
|
else
|
|
@@ -248,580 +274,505 @@ class Best50 {
|
|
|
248
274
|
}
|
|
249
275
|
static getThemeFile(path, themePath) {
|
|
250
276
|
if (typeof path == "string" &&
|
|
251
|
-
fs_1.default.existsSync(upath_1.default.join(themePath ?? this.
|
|
252
|
-
return fs_1.default.readFileSync(upath_1.default.join(themePath ?? this.
|
|
277
|
+
fs_1.default.existsSync(upath_1.default.join(themePath ?? this.primaryTheme?.path, path)))
|
|
278
|
+
return fs_1.default.readFileSync(upath_1.default.join(themePath ?? this.primaryTheme?.path, path));
|
|
253
279
|
else
|
|
254
280
|
return Buffer.from([]);
|
|
255
281
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
cur = cur.substring(0, cur.length - 1);
|
|
267
|
-
}
|
|
268
|
-
return cur.trim() + "...";
|
|
269
|
-
}
|
|
282
|
+
/* Begin Draw Tools*/
|
|
283
|
+
static findMaxFitString(ctx, original, maxWidth, lineBreakSuffix = "...") {
|
|
284
|
+
const metrics = ctx.measureText(original);
|
|
285
|
+
if (metrics.width <= maxWidth)
|
|
286
|
+
return original;
|
|
287
|
+
for (let i = 1; i < original.length; ++i) {
|
|
288
|
+
let cur = original.slice(0, original.length - i);
|
|
289
|
+
if (ctx.measureText(cur + lineBreakSuffix).width <= maxWidth) {
|
|
290
|
+
while (cur[cur.length - 1] == " ") {
|
|
291
|
+
cur = cur.substring(0, cur.length - 1);
|
|
270
292
|
}
|
|
271
|
-
return
|
|
293
|
+
return cur.trim() + lineBreakSuffix;
|
|
272
294
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
295
|
+
}
|
|
296
|
+
return original;
|
|
297
|
+
}
|
|
298
|
+
static drawText(ctx, str, x, y, fontSize,
|
|
299
|
+
/**
|
|
300
|
+
* Line width of the text stroke.
|
|
301
|
+
*/
|
|
302
|
+
linewidth,
|
|
303
|
+
/**
|
|
304
|
+
* Max width of the text block.
|
|
305
|
+
*/
|
|
306
|
+
maxWidth, textAlign = "left", mainColor = "white", borderColor = "black", font = `"standard-font-title-latin", "standard-font-title-jp"`, lineBreakSuffix = "...") {
|
|
307
|
+
ctx.font = `${fontSize}px ${font}`;
|
|
308
|
+
str = this.findMaxFitString(ctx, str, maxWidth, lineBreakSuffix);
|
|
309
|
+
if (linewidth > 0) {
|
|
310
|
+
ctx.strokeStyle = borderColor;
|
|
311
|
+
ctx.lineWidth = linewidth;
|
|
312
|
+
ctx.lineCap = "round";
|
|
313
|
+
ctx.lineJoin = "round";
|
|
314
|
+
ctx.textAlign = textAlign;
|
|
315
|
+
ctx.strokeText(str, x, y);
|
|
316
|
+
}
|
|
317
|
+
ctx.fillStyle = mainColor;
|
|
318
|
+
ctx.font = `${fontSize}px ${font}`;
|
|
319
|
+
ctx.textAlign = textAlign;
|
|
320
|
+
ctx.fillText(str, x, y);
|
|
321
|
+
if (linewidth > 0) {
|
|
322
|
+
ctx.strokeStyle = mainColor;
|
|
323
|
+
ctx.lineWidth = linewidth / 8;
|
|
324
|
+
ctx.lineCap = "round";
|
|
325
|
+
ctx.lineJoin = "round";
|
|
284
326
|
ctx.font = `${fontSize}px ${font}`;
|
|
285
327
|
ctx.textAlign = textAlign;
|
|
286
|
-
ctx.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
328
|
+
ctx.strokeText(str, x, y);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
static async drawImageModule(ctx, theme, element) {
|
|
332
|
+
const img = new canvas_1.Image();
|
|
333
|
+
img.src = this.getThemeFile(element.path, theme.path);
|
|
334
|
+
ctx.drawImage(img, element.x, element.y, element.width, element.height);
|
|
335
|
+
}
|
|
336
|
+
static async drawScoreGridModule(ctx, theme, element, score, index, x, y) {
|
|
337
|
+
let curColor = "#FFFFFF";
|
|
338
|
+
switch (score.chart.difficulty) {
|
|
339
|
+
case type_1.EDifficulty.BASIC:
|
|
340
|
+
curColor = element.scoreBubble.color.basic;
|
|
341
|
+
break;
|
|
342
|
+
case type_1.EDifficulty.ADVANCED:
|
|
343
|
+
curColor = element.scoreBubble.color.advanced;
|
|
344
|
+
break;
|
|
345
|
+
case type_1.EDifficulty.EXPERT:
|
|
346
|
+
curColor = element.scoreBubble.color.expert;
|
|
347
|
+
break;
|
|
348
|
+
case type_1.EDifficulty.MASTER:
|
|
349
|
+
curColor = element.scoreBubble.color.master;
|
|
350
|
+
break;
|
|
351
|
+
case type_1.EDifficulty.REMASTER:
|
|
352
|
+
curColor = element.scoreBubble.color.remaster;
|
|
353
|
+
break;
|
|
354
|
+
case type_1.EDifficulty.UTAGE:
|
|
355
|
+
curColor = element.scoreBubble.color.utage;
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
/** Begin Card Draw */
|
|
359
|
+
ctx.save();
|
|
360
|
+
ctx.fillStyle = new color_1.default(curColor).lighten(0.4).hexa();
|
|
361
|
+
ctx.beginPath();
|
|
362
|
+
ctx.roundRect(x, y, element.scoreBubble.width, element.scoreBubble.height, (element.scoreBubble.height * 0.806) / 7);
|
|
363
|
+
ctx.strokeStyle = new color_1.default(curColor).darken(0.3).hexa();
|
|
364
|
+
ctx.lineWidth = element.scoreBubble.margin / 4;
|
|
365
|
+
ctx.stroke();
|
|
366
|
+
ctx.fill();
|
|
367
|
+
ctx.beginPath();
|
|
368
|
+
ctx.roundRect(x, y, element.scoreBubble.width, element.scoreBubble.height, (element.scoreBubble.height * 0.806) / 7);
|
|
369
|
+
ctx.clip();
|
|
370
|
+
/** Begin Main Content Draw */
|
|
371
|
+
{
|
|
372
|
+
ctx.save();
|
|
373
|
+
ctx.beginPath();
|
|
374
|
+
ctx.roundRect(x, y, element.scoreBubble.width, element.scoreBubble.height * 0.742, (element.scoreBubble.height * 0.806) / 7);
|
|
375
|
+
ctx.clip();
|
|
376
|
+
ctx.fillStyle = curColor;
|
|
377
|
+
ctx.fill();
|
|
378
|
+
const jacketSize = Math.min(element.scoreBubble.width, element.scoreBubble.height * 0.742);
|
|
379
|
+
const jacketMaskGrad = ctx.createLinearGradient(x + jacketSize / 2, y + jacketSize / 2, x + jacketSize, y + jacketSize / 2);
|
|
380
|
+
jacketMaskGrad.addColorStop(0, new color_1.default(curColor).alpha(0).hexa());
|
|
381
|
+
jacketMaskGrad.addColorStop(0.25, new color_1.default(curColor).alpha(0.2).hexa());
|
|
382
|
+
jacketMaskGrad.addColorStop(1, new color_1.default(curColor).alpha(1).hexa());
|
|
383
|
+
const jacketMaskGradDark = ctx.createLinearGradient(x + jacketSize / 2, y + jacketSize / 2, x + jacketSize, y + jacketSize / 2);
|
|
384
|
+
jacketMaskGradDark.addColorStop(0, new color_1.default(curColor).darken(0.3).alpha(0).hexa());
|
|
385
|
+
jacketMaskGradDark.addColorStop(0.25, new color_1.default(curColor).darken(0.3).alpha(0.2).hexa());
|
|
386
|
+
jacketMaskGradDark.addColorStop(1, new color_1.default(curColor).darken(0.3).alpha(1).hexa());
|
|
387
|
+
/** Begin Jacket Draw*/
|
|
388
|
+
let jacket = await chart_1.Chart.Database.fecthJacket(score.chart.id);
|
|
389
|
+
if (!jacket)
|
|
390
|
+
jacket = await chart_1.Chart.Database.fecthJacket(0);
|
|
391
|
+
if (jacket) {
|
|
392
|
+
const img = new canvas_1.Image();
|
|
393
|
+
img.src = jacket;
|
|
394
|
+
ctx.drawImage(img, x, y, jacketSize, jacketSize);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
ctx.fillStyle = "#b6ffab";
|
|
398
|
+
ctx.fillRect(x, y, jacketSize, jacketSize);
|
|
399
|
+
}
|
|
400
|
+
/** End Jacket Draw*/
|
|
401
|
+
/** Begin Jacket Gradient Mask Draw*/ {
|
|
402
|
+
ctx.fillStyle = jacketMaskGrad;
|
|
403
|
+
ctx.fillRect(x + jacketSize / 2, y, (jacketSize * 3) / 4, jacketSize);
|
|
404
|
+
} /** End Jacket Gradient Mask Draw*/
|
|
405
|
+
ctx.beginPath();
|
|
406
|
+
ctx.roundRect(x + element.scoreBubble.margin, y + element.scoreBubble.margin, element.scoreBubble.width - element.scoreBubble.margin * 2, element.scoreBubble.height * 0.806 -
|
|
407
|
+
element.scoreBubble.margin * 2, (element.scoreBubble.height * 0.806 -
|
|
408
|
+
element.scoreBubble.margin * 2) /
|
|
409
|
+
7);
|
|
410
|
+
/** Begin Title Draw */ {
|
|
411
|
+
this.drawText(ctx, score.chart.name, x + (jacketSize * 7) / 8, y +
|
|
412
|
+
element.scoreBubble.margin +
|
|
413
|
+
element.scoreBubble.height * 0.806 * 0.144, element.scoreBubble.height * 0.806 * 0.144, element.scoreBubble.height * 0.806 * 0.04, element.scoreBubble.width -
|
|
414
|
+
(jacketSize * 7) / 8 -
|
|
415
|
+
element.scoreBubble.margin, "left", "white", jacketMaskGradDark);
|
|
416
|
+
} /** End Title Draw */
|
|
417
|
+
/** Begin Separation Line Draw */ {
|
|
418
|
+
ctx.beginPath();
|
|
419
|
+
ctx.roundRect(x + (jacketSize * 13) / 16, y +
|
|
420
|
+
element.scoreBubble.margin +
|
|
421
|
+
element.scoreBubble.height * 0.806 * (0.144 + 0.072), element.scoreBubble.width -
|
|
422
|
+
(jacketSize * 13) / 16 -
|
|
423
|
+
element.scoreBubble.margin * 2, element.scoreBubble.height * 0.806 * 0.02, element.scoreBubble.height * 0.806 * 0.16);
|
|
424
|
+
ctx.fillStyle = jacketMaskGradDark;
|
|
425
|
+
ctx.fill();
|
|
426
|
+
} /** End Separation Line Draw */
|
|
427
|
+
/** Begin Achievement Rate Draw */
|
|
428
|
+
this.drawText(ctx, `${score.achievement.toFixed(4)}%`, x -
|
|
429
|
+
element.scoreBubble.margin -
|
|
430
|
+
element.scoreBubble.height * 0.806 * 0.02 +
|
|
431
|
+
element.scoreBubble.width, y +
|
|
432
|
+
element.scoreBubble.margin +
|
|
433
|
+
element.scoreBubble.height *
|
|
434
|
+
0.806 *
|
|
435
|
+
(0.144 + 0.144 + 0.208 - 0.04), element.scoreBubble.height * 0.806 * 0.208, element.scoreBubble.height * 0.806 * 0.04, Infinity, "right", "white", new color_1.default(curColor).darken(0.3).hexa());
|
|
436
|
+
/** End Achievement Rate Draw */
|
|
437
|
+
/** Begin Achievement Rank Draw */
|
|
438
|
+
{
|
|
439
|
+
let rankImg;
|
|
440
|
+
switch (score.achievementRank) {
|
|
441
|
+
case type_1.EAchievementTypes.D:
|
|
442
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.d, theme.path);
|
|
443
|
+
break;
|
|
444
|
+
case type_1.EAchievementTypes.C:
|
|
445
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.c, theme.path);
|
|
446
|
+
break;
|
|
447
|
+
case type_1.EAchievementTypes.B:
|
|
448
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.b, theme.path);
|
|
449
|
+
break;
|
|
450
|
+
case type_1.EAchievementTypes.BB:
|
|
451
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.bb, theme.path);
|
|
452
|
+
break;
|
|
453
|
+
case type_1.EAchievementTypes.BBB:
|
|
454
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.bbb, theme.path);
|
|
455
|
+
break;
|
|
456
|
+
case type_1.EAchievementTypes.A:
|
|
457
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.a, theme.path);
|
|
458
|
+
break;
|
|
459
|
+
case type_1.EAchievementTypes.AA:
|
|
460
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.aa, theme.path);
|
|
461
|
+
break;
|
|
462
|
+
case type_1.EAchievementTypes.AAA:
|
|
463
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.aaa, theme.path);
|
|
464
|
+
break;
|
|
465
|
+
case type_1.EAchievementTypes.S:
|
|
466
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.s, theme.path);
|
|
467
|
+
break;
|
|
468
|
+
case type_1.EAchievementTypes.SP:
|
|
469
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.sp, theme.path);
|
|
470
|
+
break;
|
|
471
|
+
case type_1.EAchievementTypes.SS:
|
|
472
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.ss, theme.path);
|
|
473
|
+
break;
|
|
474
|
+
case type_1.EAchievementTypes.SSP:
|
|
475
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.ssp, theme.path);
|
|
476
|
+
break;
|
|
477
|
+
case type_1.EAchievementTypes.SSS:
|
|
478
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.sss, theme.path);
|
|
479
|
+
break;
|
|
480
|
+
default:
|
|
481
|
+
rankImg = this.getThemeFile(theme.manifest.sprites.achievement.sssp, theme.path);
|
|
482
|
+
}
|
|
483
|
+
const img = new canvas_1.Image();
|
|
484
|
+
img.src = rankImg;
|
|
485
|
+
ctx.drawImage(img, x + jacketSize, y +
|
|
486
|
+
element.scoreBubble.margin +
|
|
487
|
+
element.scoreBubble.height *
|
|
488
|
+
0.806 *
|
|
489
|
+
(0.144 + 0.144 + 0.208 + 0.02), element.scoreBubble.height * 0.806 * 0.3 * 2.133, element.scoreBubble.height * 0.806 * 0.3);
|
|
490
|
+
}
|
|
491
|
+
/** End Achievement Rank Draw */
|
|
492
|
+
/** Begin Milestone Draw */
|
|
493
|
+
{
|
|
494
|
+
let comboImg, syncImg;
|
|
495
|
+
switch (score.combo) {
|
|
496
|
+
case type_1.EComboTypes.NONE:
|
|
497
|
+
comboImg = this.getThemeFile(theme.manifest.sprites.milestone.none, theme.path);
|
|
498
|
+
break;
|
|
499
|
+
case type_1.EComboTypes.FULL_COMBO:
|
|
500
|
+
comboImg = this.getThemeFile(theme.manifest.sprites.milestone.fc, theme.path);
|
|
501
|
+
break;
|
|
502
|
+
case type_1.EComboTypes.FULL_COMBO_PLUS:
|
|
503
|
+
comboImg = this.getThemeFile(theme.manifest.sprites.milestone.fcp, theme.path);
|
|
504
|
+
break;
|
|
505
|
+
case type_1.EComboTypes.ALL_PERFECT:
|
|
506
|
+
comboImg = this.getThemeFile(theme.manifest.sprites.milestone.ap, theme.path);
|
|
507
|
+
break;
|
|
508
|
+
case type_1.EComboTypes.ALL_PERFECT_PLUS:
|
|
509
|
+
comboImg = this.getThemeFile(theme.manifest.sprites.milestone.app, theme.path);
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
switch (score.sync) {
|
|
513
|
+
case type_1.ESyncTypes.NONE:
|
|
514
|
+
syncImg = this.getThemeFile(theme.manifest.sprites.milestone.none, theme.path);
|
|
515
|
+
break;
|
|
516
|
+
case type_1.ESyncTypes.SYNC_PLAY:
|
|
517
|
+
syncImg = this.getThemeFile(theme.manifest.sprites.milestone.sync, theme.path);
|
|
518
|
+
break;
|
|
519
|
+
case type_1.ESyncTypes.FULL_SYNC:
|
|
520
|
+
syncImg = this.getThemeFile(theme.manifest.sprites.milestone.fs, theme.path);
|
|
521
|
+
break;
|
|
522
|
+
case type_1.ESyncTypes.FULL_SYNC_PLUS:
|
|
523
|
+
syncImg = this.getThemeFile(theme.manifest.sprites.milestone.fsp, theme.path);
|
|
524
|
+
break;
|
|
525
|
+
case type_1.ESyncTypes.FULL_SYNC_DX:
|
|
526
|
+
syncImg = this.getThemeFile(theme.manifest.sprites.milestone.fdx, theme.path);
|
|
527
|
+
break;
|
|
528
|
+
case type_1.ESyncTypes.FULL_SYNC_DX_PLUS:
|
|
529
|
+
syncImg = this.getThemeFile(theme.manifest.sprites.milestone.fdxp, theme.path);
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
const combo = new canvas_1.Image();
|
|
533
|
+
combo.src = comboImg;
|
|
534
|
+
ctx.drawImage(combo, x +
|
|
535
|
+
(jacketSize * 7) / 8 +
|
|
536
|
+
element.scoreBubble.height *
|
|
537
|
+
0.806 *
|
|
538
|
+
(0.32 * 2.133 + 0.06), y +
|
|
539
|
+
element.scoreBubble.margin +
|
|
540
|
+
element.scoreBubble.height *
|
|
541
|
+
0.806 *
|
|
542
|
+
(0.144 + 0.144 + 0.208 + 0.01), element.scoreBubble.height * 0.806 * 0.32, element.scoreBubble.height * 0.806 * 0.32);
|
|
543
|
+
const sync = new canvas_1.Image();
|
|
544
|
+
sync.src = syncImg;
|
|
545
|
+
ctx.drawImage(sync, x +
|
|
546
|
+
(jacketSize * 7) / 8 +
|
|
547
|
+
element.scoreBubble.height *
|
|
548
|
+
0.806 *
|
|
549
|
+
(0.32 * 2.133 + 0.04 + 0.32), y +
|
|
550
|
+
element.scoreBubble.margin +
|
|
551
|
+
element.scoreBubble.height *
|
|
552
|
+
0.806 *
|
|
553
|
+
(0.144 + 0.144 + 0.208 + 0.01), element.scoreBubble.height * 0.806 * 0.32, element.scoreBubble.height * 0.806 * 0.32);
|
|
554
|
+
}
|
|
555
|
+
/** End Milestone Draw */
|
|
556
|
+
/** Begin Chart Mode Draw */
|
|
557
|
+
{
|
|
558
|
+
const mode = new canvas_1.Image();
|
|
559
|
+
const chartModeBadgeImg = this.getThemeFile(score.chart.id > 10000
|
|
560
|
+
? theme.manifest.sprites.mode.dx
|
|
561
|
+
: theme.manifest.sprites.mode.standard, theme.path);
|
|
562
|
+
const { width, height } = await (0, sharp_1.default)(chartModeBadgeImg).metadata();
|
|
563
|
+
const aspectRatio = (width ?? 0) / (height ?? 1) || 3;
|
|
564
|
+
mode.src = chartModeBadgeImg;
|
|
565
|
+
const drawHeight = (jacketSize * 6) / 8;
|
|
566
|
+
ctx.drawImage(mode, x + ((jacketSize * 7) / 8 - drawHeight) / 2, y +
|
|
567
|
+
element.scoreBubble.margin +
|
|
568
|
+
element.scoreBubble.height * 0.806 * 0.02, drawHeight, drawHeight / aspectRatio);
|
|
569
|
+
}
|
|
570
|
+
/** End Chart Mode Draw */
|
|
571
|
+
/** Begin Bests Index Draw */
|
|
572
|
+
{
|
|
573
|
+
this.drawText(ctx, `#${index + 1}`, x + element.scoreBubble.margin * 2, y + jacketSize - element.scoreBubble.margin * 2, element.scoreBubble.height * 0.806 * 0.128, element.scoreBubble.height * 0.806 * 0.04, Infinity, "left", "white", new color_1.default(curColor).darken(0.3).hexa());
|
|
574
|
+
}
|
|
575
|
+
/** End Bests Index Draw */
|
|
576
|
+
ctx.restore();
|
|
577
|
+
}
|
|
578
|
+
/** End Main Content Draw */
|
|
579
|
+
/** Begin Difficulty & DX Rating Draw */
|
|
580
|
+
{
|
|
581
|
+
this.drawText(ctx, `${score.chart.level.toFixed(1)} ↑${score.dxRating.toFixed(0)}`, x + element.scoreBubble.margin * 2, y + element.scoreBubble.height * (0.806 + (1 - 0.806) / 2), element.scoreBubble.height * 0.806 * 0.128, element.scoreBubble.height * 0.806 * 0.04, Infinity, "left", "white", new color_1.default(curColor).darken(0.3).hexa());
|
|
582
|
+
if (score.chart.maxDxScore) {
|
|
583
|
+
this.drawText(ctx, `${score.dxScore}/${score.chart.maxDxScore}`, x +
|
|
584
|
+
element.scoreBubble.width -
|
|
585
|
+
element.scoreBubble.margin * 2, y + element.scoreBubble.height * (0.806 + (1 - 0.806) / 2), element.scoreBubble.height * 0.806 * 0.128, element.scoreBubble.height * 0.806 * 0.04, Infinity, "right", "white", new color_1.default(curColor).darken(0.3).hexa());
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
/** End Difficulty & DX Rating Draw */
|
|
589
|
+
ctx.restore();
|
|
590
|
+
/** End Card Draw */
|
|
591
|
+
}
|
|
592
|
+
static async drawProfileModule(ctx, theme, element, username, rating, profilePicture) {
|
|
593
|
+
const nameplate = new canvas_1.Image();
|
|
594
|
+
nameplate.src = this.getThemeFile(theme.manifest.sprites.profile.nameplate, theme.path);
|
|
595
|
+
ctx.drawImage(nameplate, element.x, element.y, element.height * 6.207, element.height);
|
|
596
|
+
/* Begin Profile Picture Draw */
|
|
597
|
+
{
|
|
598
|
+
ctx.save();
|
|
599
|
+
ctx.beginPath();
|
|
600
|
+
ctx.roundRect(element.x + element.height * 0.064, element.y + element.height * 0.064, element.height * 0.872, element.height * 0.872, (element.height * 0.872) / 16);
|
|
601
|
+
ctx.clip();
|
|
602
|
+
ctx.fillStyle = "white";
|
|
603
|
+
ctx.fill();
|
|
604
|
+
const icon = new canvas_1.Image();
|
|
605
|
+
const pfp = profilePicture ||
|
|
606
|
+
this.getThemeFile(theme.manifest.sprites.profile.icon, theme.path);
|
|
607
|
+
const { dominant } = await (0, sharp_1.default)(pfp).stats();
|
|
608
|
+
icon.src = pfp;
|
|
609
|
+
const cropSize = Math.min(icon.width, icon.height);
|
|
610
|
+
ctx.drawImage(icon, (icon.width - cropSize) / 2, (icon.height - cropSize) / 2, cropSize, cropSize, element.x + element.height * 0.064, element.y + element.height * 0.064, element.height * 0.872, element.height * 0.872);
|
|
611
|
+
if (profilePicture) {
|
|
612
|
+
ctx.beginPath();
|
|
613
|
+
ctx.roundRect(element.x + element.height * 0.064, element.y + element.height * 0.064, element.height * 0.872, element.height * 0.872, (element.height * 0.872) / 16);
|
|
614
|
+
ctx.strokeStyle = color_1.default.rgb(dominant).darken(0.3).hex();
|
|
615
|
+
ctx.lineWidth = element.height / 30;
|
|
616
|
+
ctx.stroke();
|
|
617
|
+
}
|
|
618
|
+
ctx.restore();
|
|
619
|
+
}
|
|
620
|
+
/* End Profile Picture Draw */
|
|
621
|
+
/* Begin DX Rating Draw */
|
|
622
|
+
{
|
|
623
|
+
const dxRating = new canvas_1.Image();
|
|
624
|
+
let dxRatingImg;
|
|
625
|
+
switch (true) {
|
|
626
|
+
case rating > 15000: {
|
|
627
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.rainbow, theme.path);
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
case rating > 14500: {
|
|
631
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.platinum, theme.path);
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
case rating > 14000: {
|
|
635
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.gold, theme.path);
|
|
636
|
+
break;
|
|
637
|
+
}
|
|
638
|
+
case rating > 13000: {
|
|
639
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.silver, theme.path);
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
case rating > 12000: {
|
|
643
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.bronze, theme.path);
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
case rating > 10000: {
|
|
647
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.purple, theme.path);
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
650
|
+
case rating > 8000: {
|
|
651
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.red, theme.path);
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
case rating > 6000: {
|
|
655
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.yellow, theme.path);
|
|
656
|
+
break;
|
|
657
|
+
}
|
|
658
|
+
case rating > 4000: {
|
|
659
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.green, theme.path);
|
|
660
|
+
break;
|
|
661
|
+
}
|
|
662
|
+
case rating > 2000: {
|
|
663
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.blue, theme.path);
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
default: {
|
|
667
|
+
dxRatingImg = this.getThemeFile(theme.manifest.sprites.dxRating.white, theme.path);
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
dxRating.src = dxRatingImg;
|
|
672
|
+
ctx.drawImage(dxRating, element.x + element.height, element.y + element.height * 0.064, (element.height / 3) * 5.108, element.height / 3);
|
|
673
|
+
}
|
|
674
|
+
/* End DX Rating Draw */
|
|
675
|
+
/* Begin Username Draw */
|
|
676
|
+
{
|
|
677
|
+
ctx.beginPath();
|
|
678
|
+
ctx.roundRect(element.x + element.height * (1 + 1 / 32), element.y + element.height * (0.064 + 0.333 + 1 / 32), ((element.height / 3) * 5.108 * 6) / 5, (element.height * 7) / 24, element.height / 20);
|
|
679
|
+
ctx.fillStyle = "white";
|
|
680
|
+
ctx.strokeStyle = color_1.default.rgb(180, 180, 180).hex();
|
|
681
|
+
ctx.lineWidth = element.height / 32;
|
|
682
|
+
ctx.stroke();
|
|
683
|
+
ctx.fill();
|
|
684
|
+
const ratingImgBuffer = await this.getRatingNumber(rating, theme);
|
|
685
|
+
if (ratingImgBuffer) {
|
|
686
|
+
const { width, height } = await (0, sharp_1.default)(ratingImgBuffer).metadata();
|
|
687
|
+
if (width && height) {
|
|
688
|
+
const aspectRatio = width / height;
|
|
689
|
+
const image = new canvas_1.Image();
|
|
690
|
+
image.src = ratingImgBuffer;
|
|
691
|
+
const drawHeight = (element.height * 7) / 32;
|
|
692
|
+
ctx.drawImage(image, element.x + element.height * 1.785, element.y + element.height * 0.12, drawHeight * aspectRatio * 0.8, drawHeight);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
this.drawText(ctx, HalfFullWidthConvert.toFullWidth(username), element.x + element.height * (1 + 1 / 16), element.y + element.height * (0.064 + 0.333 + 1 / 4), (element.height * 1) / 6, 0, ((element.height / 3) * 5.108 * 6) / 5, "left", "black", "black", "standard-font-username");
|
|
696
|
+
}
|
|
697
|
+
/* End Username Draw*/
|
|
698
|
+
}
|
|
699
|
+
static async drawTextModule(ctx, theme, element) {
|
|
700
|
+
let infiniteWideLines = element.content.split("\n");
|
|
701
|
+
let lines = [];
|
|
702
|
+
if (element.linebreak) {
|
|
703
|
+
for (let originalContent of infiniteWideLines) {
|
|
704
|
+
while (originalContent.length) {
|
|
705
|
+
const line = this.findMaxFitString(ctx, originalContent, element.width || Infinity, "");
|
|
706
|
+
originalContent = originalContent.replace(line, "").trim();
|
|
707
|
+
lines.push(line.trim());
|
|
708
|
+
}
|
|
295
709
|
}
|
|
296
710
|
}
|
|
711
|
+
else {
|
|
712
|
+
for (const originalContent of infiniteWideLines) {
|
|
713
|
+
lines.push(this.findMaxFitString(ctx, originalContent, element.width || Infinity));
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
for (let i = 0; i < lines.length; ++i) {
|
|
717
|
+
const line = lines[i];
|
|
718
|
+
this.drawText(ctx, line, element.x, element.y + i * element.size * 1.3, element.size, element.size / 6, element.width || Infinity, element.align, element.color || "#FFFFFF", element.borderColor
|
|
719
|
+
? element.borderColor
|
|
720
|
+
: color_1.default.rgb(element.color || "#FFFFFF")
|
|
721
|
+
.darken(0.3)
|
|
722
|
+
.hex(), element.font, element.linebreak ? "" : "...");
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/* End Draw Tools*/
|
|
726
|
+
static async draw(name, rating, newScores, oldScores, options) {
|
|
297
727
|
await chart_1.Chart.Database.cacheJackets([
|
|
298
728
|
...newScores.map((v) => v.chart.id),
|
|
299
729
|
...oldScores.map((v) => v.chart.id),
|
|
300
730
|
]);
|
|
301
|
-
let currentTheme = this.primaryTheme
|
|
731
|
+
let currentTheme = this.primaryTheme;
|
|
302
732
|
if (options?.theme) {
|
|
303
733
|
const theme = this.getTheme(options.theme);
|
|
304
734
|
if (theme) {
|
|
305
|
-
currentTheme = theme
|
|
306
|
-
currentThemePath = theme.path;
|
|
735
|
+
currentTheme = theme;
|
|
307
736
|
}
|
|
308
737
|
}
|
|
309
|
-
if (currentTheme
|
|
310
|
-
const canvas = new canvas_1.Canvas(currentTheme.width * (options?.scale ?? 1), currentTheme.height * (options?.scale ?? 1));
|
|
738
|
+
if (currentTheme) {
|
|
739
|
+
const canvas = new canvas_1.Canvas(currentTheme.manifest.width * (options?.scale ?? 1), currentTheme.manifest.height * (options?.scale ?? 1));
|
|
311
740
|
const ctx = canvas.getContext("2d");
|
|
312
741
|
if (options?.scale)
|
|
313
742
|
ctx.scale(options.scale, options.scale);
|
|
314
743
|
ctx.imageSmoothingEnabled = true;
|
|
315
|
-
for (const element of currentTheme.elements) {
|
|
744
|
+
for (const element of currentTheme.manifest.elements) {
|
|
316
745
|
switch (element.type) {
|
|
317
746
|
case "image": {
|
|
318
|
-
|
|
319
|
-
img.src = this.getThemeFile(element.path, currentThemePath);
|
|
320
|
-
ctx.drawImage(img, element.x, element.y, element.width, element.height);
|
|
747
|
+
await this.drawImageModule(ctx, currentTheme, element);
|
|
321
748
|
break;
|
|
322
749
|
}
|
|
323
750
|
case "score-grid": {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
cury +=
|
|
751
|
+
for (let y = element.y, index = element.index, i = 0; i < element.verticalSize; ++i,
|
|
752
|
+
y +=
|
|
327
753
|
element.scoreBubble.height +
|
|
328
754
|
element.scoreBubble.gap) {
|
|
329
|
-
for (let
|
|
330
|
-
++
|
|
331
|
-
|
|
755
|
+
for (let x = element.x, j = 0; j < element.horizontalSize; ++j,
|
|
756
|
+
++index,
|
|
757
|
+
x +=
|
|
332
758
|
element.scoreBubble.width +
|
|
333
759
|
element.scoreBubble.gap) {
|
|
334
760
|
let curScore;
|
|
335
761
|
if (element.region == "new")
|
|
336
|
-
curScore = newScores[
|
|
762
|
+
curScore = newScores[index];
|
|
337
763
|
else
|
|
338
|
-
curScore = oldScores[
|
|
339
|
-
|
|
340
|
-
let curColor = "#FFFFFF";
|
|
341
|
-
switch (curScore.chart.difficulty) {
|
|
342
|
-
case type_1.EDifficulty.BASIC:
|
|
343
|
-
curColor =
|
|
344
|
-
element.scoreBubble.color.basic;
|
|
345
|
-
break;
|
|
346
|
-
case type_1.EDifficulty.ADVANCED:
|
|
347
|
-
curColor =
|
|
348
|
-
element.scoreBubble.color
|
|
349
|
-
.advanced;
|
|
350
|
-
break;
|
|
351
|
-
case type_1.EDifficulty.EXPERT:
|
|
352
|
-
curColor =
|
|
353
|
-
element.scoreBubble.color
|
|
354
|
-
.expert;
|
|
355
|
-
break;
|
|
356
|
-
case type_1.EDifficulty.MASTER:
|
|
357
|
-
curColor =
|
|
358
|
-
element.scoreBubble.color
|
|
359
|
-
.master;
|
|
360
|
-
break;
|
|
361
|
-
case type_1.EDifficulty.REMASTER:
|
|
362
|
-
curColor =
|
|
363
|
-
element.scoreBubble.color
|
|
364
|
-
.remaster;
|
|
365
|
-
break;
|
|
366
|
-
case type_1.EDifficulty.UTAGE:
|
|
367
|
-
curColor =
|
|
368
|
-
element.scoreBubble.color.utage;
|
|
369
|
-
break;
|
|
370
|
-
}
|
|
371
|
-
/** Begin Card Draw */
|
|
372
|
-
ctx.save();
|
|
373
|
-
ctx.fillStyle = new color_1.default(curColor)
|
|
374
|
-
.lighten(0.4)
|
|
375
|
-
.hexa();
|
|
376
|
-
ctx.beginPath();
|
|
377
|
-
ctx.roundRect(curx, cury, element.scoreBubble.width, element.scoreBubble.height, (element.scoreBubble.height * 0.806) / 7);
|
|
378
|
-
ctx.strokeStyle = new color_1.default(curColor)
|
|
379
|
-
.darken(0.3)
|
|
380
|
-
.hexa();
|
|
381
|
-
ctx.lineWidth =
|
|
382
|
-
element.scoreBubble.margin / 4;
|
|
383
|
-
ctx.stroke();
|
|
384
|
-
ctx.fill();
|
|
385
|
-
ctx.beginPath();
|
|
386
|
-
ctx.roundRect(curx, cury, element.scoreBubble.width, element.scoreBubble.height, (element.scoreBubble.height * 0.806) / 7);
|
|
387
|
-
ctx.clip();
|
|
388
|
-
/** Begin Main Content Draw */
|
|
389
|
-
ctx.save();
|
|
390
|
-
ctx.beginPath();
|
|
391
|
-
ctx.roundRect(curx, cury, element.scoreBubble.width, element.scoreBubble.height * 0.742, (element.scoreBubble.height * 0.806) / 7);
|
|
392
|
-
ctx.clip();
|
|
393
|
-
ctx.fillStyle = curColor;
|
|
394
|
-
ctx.fill();
|
|
395
|
-
const jacketSize = Math.min(element.scoreBubble.width, element.scoreBubble.height * 0.742);
|
|
396
|
-
const jacketMaskGrad = ctx.createLinearGradient(curx + jacketSize / 2, cury + jacketSize / 2, curx + jacketSize, cury + jacketSize / 2);
|
|
397
|
-
jacketMaskGrad.addColorStop(0, new color_1.default(curColor).alpha(0).hexa());
|
|
398
|
-
jacketMaskGrad.addColorStop(0.25, new color_1.default(curColor).alpha(0.2).hexa());
|
|
399
|
-
jacketMaskGrad.addColorStop(1, new color_1.default(curColor).alpha(1).hexa());
|
|
400
|
-
const jacketMaskGradDark = ctx.createLinearGradient(curx + jacketSize / 2, cury + jacketSize / 2, curx + jacketSize, cury + jacketSize / 2);
|
|
401
|
-
jacketMaskGradDark.addColorStop(0, new color_1.default(curColor)
|
|
402
|
-
.darken(0.3)
|
|
403
|
-
.alpha(0)
|
|
404
|
-
.hexa());
|
|
405
|
-
jacketMaskGradDark.addColorStop(0.25, new color_1.default(curColor)
|
|
406
|
-
.darken(0.3)
|
|
407
|
-
.alpha(0.2)
|
|
408
|
-
.hexa());
|
|
409
|
-
jacketMaskGradDark.addColorStop(1, new color_1.default(curColor)
|
|
410
|
-
.darken(0.3)
|
|
411
|
-
.alpha(1)
|
|
412
|
-
.hexa());
|
|
413
|
-
/** Begin Jacket Draw*/
|
|
414
|
-
let jacket = await chart_1.Chart.Database.fecthJacket(curScore.chart.id);
|
|
415
|
-
if (!jacket)
|
|
416
|
-
jacket =
|
|
417
|
-
await chart_1.Chart.Database.fecthJacket(0);
|
|
418
|
-
if (jacket) {
|
|
419
|
-
const img = new canvas_1.Image();
|
|
420
|
-
img.src = jacket;
|
|
421
|
-
ctx.drawImage(img, curx, cury, jacketSize, jacketSize);
|
|
422
|
-
}
|
|
423
|
-
else {
|
|
424
|
-
ctx.fillStyle = "#b6ffab";
|
|
425
|
-
ctx.fillRect(curx, cury, jacketSize, jacketSize);
|
|
426
|
-
}
|
|
427
|
-
/** End Jacket Draw*/
|
|
428
|
-
/** Begin Jacket Gradient Mask Draw*/ {
|
|
429
|
-
ctx.fillStyle = jacketMaskGrad;
|
|
430
|
-
ctx.fillRect(curx + jacketSize / 2, cury, (jacketSize * 3) / 4, jacketSize);
|
|
431
|
-
} /** End Jacket Gradient Mask Draw*/
|
|
432
|
-
ctx.beginPath();
|
|
433
|
-
ctx.roundRect(curx + element.scoreBubble.margin, cury + element.scoreBubble.margin, element.scoreBubble.width -
|
|
434
|
-
element.scoreBubble.margin * 2, element.scoreBubble.height * 0.806 -
|
|
435
|
-
element.scoreBubble.margin * 2, (element.scoreBubble.height * 0.806 -
|
|
436
|
-
element.scoreBubble.margin * 2) /
|
|
437
|
-
7);
|
|
438
|
-
/** Begin Title Draw */ {
|
|
439
|
-
drawText(ctx, curScore.chart.name, curx + (jacketSize * 7) / 8, cury +
|
|
440
|
-
element.scoreBubble.margin +
|
|
441
|
-
element.scoreBubble.height *
|
|
442
|
-
0.806 *
|
|
443
|
-
0.144, element.scoreBubble.height *
|
|
444
|
-
0.806 *
|
|
445
|
-
0.144, element.scoreBubble.height *
|
|
446
|
-
0.806 *
|
|
447
|
-
0.04, element.scoreBubble.width -
|
|
448
|
-
(jacketSize * 7) / 8 -
|
|
449
|
-
element.scoreBubble.margin, "left", "white", jacketMaskGradDark);
|
|
450
|
-
} /** End Title Draw */
|
|
451
|
-
/** Begin Separation Line Draw */ {
|
|
452
|
-
ctx.beginPath();
|
|
453
|
-
ctx.roundRect(curx + (jacketSize * 13) / 16, cury +
|
|
454
|
-
element.scoreBubble.margin +
|
|
455
|
-
element.scoreBubble.height *
|
|
456
|
-
0.806 *
|
|
457
|
-
(0.144 + 0.072), element.scoreBubble.width -
|
|
458
|
-
(jacketSize * 13) / 16 -
|
|
459
|
-
element.scoreBubble.margin * 2, element.scoreBubble.height *
|
|
460
|
-
0.806 *
|
|
461
|
-
0.02, element.scoreBubble.height *
|
|
462
|
-
0.806 *
|
|
463
|
-
0.16);
|
|
464
|
-
ctx.fillStyle = jacketMaskGradDark;
|
|
465
|
-
ctx.fill();
|
|
466
|
-
} /** End Separation Line Draw */
|
|
467
|
-
/** Begin Achievement Rate Draw */
|
|
468
|
-
drawText(ctx, `${curScore.achievement.toFixed(4)}%`, curx -
|
|
469
|
-
element.scoreBubble.margin -
|
|
470
|
-
element.scoreBubble.height *
|
|
471
|
-
0.806 *
|
|
472
|
-
0.02 +
|
|
473
|
-
element.scoreBubble.width, cury +
|
|
474
|
-
element.scoreBubble.margin +
|
|
475
|
-
element.scoreBubble.height *
|
|
476
|
-
0.806 *
|
|
477
|
-
(0.144 + 0.144 + 0.208 - 0.04), element.scoreBubble.height *
|
|
478
|
-
0.806 *
|
|
479
|
-
0.208, element.scoreBubble.height *
|
|
480
|
-
0.806 *
|
|
481
|
-
0.04, Infinity, "right", "white", new color_1.default(curColor).darken(0.3).hexa());
|
|
482
|
-
/** End Achievement Rate Draw */
|
|
483
|
-
/** Begin Achievement Rank Draw */
|
|
484
|
-
{
|
|
485
|
-
let rankImg;
|
|
486
|
-
switch (curScore.achievementRank) {
|
|
487
|
-
case type_1.EAchievementTypes.D:
|
|
488
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
489
|
-
.achievement.d, currentThemePath);
|
|
490
|
-
break;
|
|
491
|
-
case type_1.EAchievementTypes.C:
|
|
492
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
493
|
-
.achievement.c, currentThemePath);
|
|
494
|
-
break;
|
|
495
|
-
case type_1.EAchievementTypes.B:
|
|
496
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
497
|
-
.achievement.b, currentThemePath);
|
|
498
|
-
break;
|
|
499
|
-
case type_1.EAchievementTypes.BB:
|
|
500
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
501
|
-
.achievement.bb, currentThemePath);
|
|
502
|
-
break;
|
|
503
|
-
case type_1.EAchievementTypes.BBB:
|
|
504
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
505
|
-
.achievement.bbb, currentThemePath);
|
|
506
|
-
break;
|
|
507
|
-
case type_1.EAchievementTypes.A:
|
|
508
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
509
|
-
.achievement.a, currentThemePath);
|
|
510
|
-
break;
|
|
511
|
-
case type_1.EAchievementTypes.AA:
|
|
512
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
513
|
-
.achievement.aa, currentThemePath);
|
|
514
|
-
break;
|
|
515
|
-
case type_1.EAchievementTypes.AAA:
|
|
516
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
517
|
-
.achievement.aaa, currentThemePath);
|
|
518
|
-
break;
|
|
519
|
-
case type_1.EAchievementTypes.S:
|
|
520
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
521
|
-
.achievement.s, currentThemePath);
|
|
522
|
-
break;
|
|
523
|
-
case type_1.EAchievementTypes.SP:
|
|
524
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
525
|
-
.achievement.sp, currentThemePath);
|
|
526
|
-
break;
|
|
527
|
-
case type_1.EAchievementTypes.SS:
|
|
528
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
529
|
-
.achievement.ss, currentThemePath);
|
|
530
|
-
break;
|
|
531
|
-
case type_1.EAchievementTypes.SSP:
|
|
532
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
533
|
-
.achievement.ssp, currentThemePath);
|
|
534
|
-
break;
|
|
535
|
-
case type_1.EAchievementTypes.SSS:
|
|
536
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
537
|
-
.achievement.sss, currentThemePath);
|
|
538
|
-
break;
|
|
539
|
-
default:
|
|
540
|
-
rankImg = this.getThemeFile(currentTheme.sprites
|
|
541
|
-
.achievement.sssp, currentThemePath);
|
|
542
|
-
}
|
|
543
|
-
const img = new canvas_1.Image();
|
|
544
|
-
img.src = rankImg;
|
|
545
|
-
ctx.drawImage(img, curx + jacketSize, cury +
|
|
546
|
-
element.scoreBubble.margin +
|
|
547
|
-
element.scoreBubble.height *
|
|
548
|
-
0.806 *
|
|
549
|
-
(0.144 +
|
|
550
|
-
0.144 +
|
|
551
|
-
0.208 +
|
|
552
|
-
0.02), element.scoreBubble.height *
|
|
553
|
-
0.806 *
|
|
554
|
-
0.3 *
|
|
555
|
-
2.133, element.scoreBubble.height *
|
|
556
|
-
0.806 *
|
|
557
|
-
0.3);
|
|
558
|
-
}
|
|
559
|
-
/** End Achievement Rank Draw */
|
|
560
|
-
/** Begin Milestone Draw */
|
|
561
|
-
{
|
|
562
|
-
let comboImg, syncImg;
|
|
563
|
-
switch (curScore.combo) {
|
|
564
|
-
case type_1.EComboTypes.NONE:
|
|
565
|
-
comboImg = this.getThemeFile(currentTheme.sprites
|
|
566
|
-
.milestone.none, currentThemePath);
|
|
567
|
-
break;
|
|
568
|
-
case type_1.EComboTypes.FULL_COMBO:
|
|
569
|
-
comboImg = this.getThemeFile(currentTheme.sprites
|
|
570
|
-
.milestone.fc, currentThemePath);
|
|
571
|
-
break;
|
|
572
|
-
case type_1.EComboTypes.FULL_COMBO_PLUS:
|
|
573
|
-
comboImg = this.getThemeFile(currentTheme.sprites
|
|
574
|
-
.milestone.fcp, currentThemePath);
|
|
575
|
-
break;
|
|
576
|
-
case type_1.EComboTypes.ALL_PERFECT:
|
|
577
|
-
comboImg = this.getThemeFile(currentTheme.sprites
|
|
578
|
-
.milestone.ap, currentThemePath);
|
|
579
|
-
break;
|
|
580
|
-
case type_1.EComboTypes.ALL_PERFECT_PLUS:
|
|
581
|
-
comboImg = this.getThemeFile(currentTheme.sprites
|
|
582
|
-
.milestone.app, currentThemePath);
|
|
583
|
-
break;
|
|
584
|
-
}
|
|
585
|
-
switch (curScore.sync) {
|
|
586
|
-
case type_1.ESyncTypes.NONE:
|
|
587
|
-
syncImg = this.getThemeFile(currentTheme.sprites
|
|
588
|
-
.milestone.none, currentThemePath);
|
|
589
|
-
break;
|
|
590
|
-
case type_1.ESyncTypes.SYNC_PLAY:
|
|
591
|
-
syncImg = this.getThemeFile(currentTheme.sprites
|
|
592
|
-
.milestone.sync, currentThemePath);
|
|
593
|
-
break;
|
|
594
|
-
case type_1.ESyncTypes.FULL_SYNC:
|
|
595
|
-
syncImg = this.getThemeFile(currentTheme.sprites
|
|
596
|
-
.milestone.fs, currentThemePath);
|
|
597
|
-
break;
|
|
598
|
-
case type_1.ESyncTypes.FULL_SYNC_PLUS:
|
|
599
|
-
syncImg = this.getThemeFile(currentTheme.sprites
|
|
600
|
-
.milestone.fsp, currentThemePath);
|
|
601
|
-
break;
|
|
602
|
-
case type_1.ESyncTypes.FULL_SYNC_DX:
|
|
603
|
-
syncImg = this.getThemeFile(currentTheme.sprites
|
|
604
|
-
.milestone.fdx, currentThemePath);
|
|
605
|
-
break;
|
|
606
|
-
case type_1.ESyncTypes.FULL_SYNC_DX_PLUS:
|
|
607
|
-
syncImg = this.getThemeFile(currentTheme.sprites
|
|
608
|
-
.milestone.fdxp, currentThemePath);
|
|
609
|
-
break;
|
|
610
|
-
}
|
|
611
|
-
const combo = new canvas_1.Image();
|
|
612
|
-
combo.src = comboImg;
|
|
613
|
-
ctx.drawImage(combo, curx +
|
|
614
|
-
(jacketSize * 7) / 8 +
|
|
615
|
-
element.scoreBubble.height *
|
|
616
|
-
0.806 *
|
|
617
|
-
(0.32 * 2.133 + 0.06), cury +
|
|
618
|
-
element.scoreBubble.margin +
|
|
619
|
-
element.scoreBubble.height *
|
|
620
|
-
0.806 *
|
|
621
|
-
(0.144 +
|
|
622
|
-
0.144 +
|
|
623
|
-
0.208 +
|
|
624
|
-
0.01), element.scoreBubble.height *
|
|
625
|
-
0.806 *
|
|
626
|
-
0.32, element.scoreBubble.height *
|
|
627
|
-
0.806 *
|
|
628
|
-
0.32);
|
|
629
|
-
const sync = new canvas_1.Image();
|
|
630
|
-
sync.src = syncImg;
|
|
631
|
-
ctx.drawImage(sync, curx +
|
|
632
|
-
(jacketSize * 7) / 8 +
|
|
633
|
-
element.scoreBubble.height *
|
|
634
|
-
0.806 *
|
|
635
|
-
(0.32 * 2.133 +
|
|
636
|
-
0.04 +
|
|
637
|
-
0.32), cury +
|
|
638
|
-
element.scoreBubble.margin +
|
|
639
|
-
element.scoreBubble.height *
|
|
640
|
-
0.806 *
|
|
641
|
-
(0.144 +
|
|
642
|
-
0.144 +
|
|
643
|
-
0.208 +
|
|
644
|
-
0.01), element.scoreBubble.height *
|
|
645
|
-
0.806 *
|
|
646
|
-
0.32, element.scoreBubble.height *
|
|
647
|
-
0.806 *
|
|
648
|
-
0.32);
|
|
649
|
-
}
|
|
650
|
-
/** End Milestone Draw */
|
|
651
|
-
/** Begin Chart Mode Draw */
|
|
652
|
-
{
|
|
653
|
-
const mode = new canvas_1.Image();
|
|
654
|
-
const chartModeBadgeImg = this.getThemeFile(curScore.chart.id > 10000
|
|
655
|
-
? currentTheme.sprites.mode
|
|
656
|
-
.dx
|
|
657
|
-
: currentTheme.sprites.mode
|
|
658
|
-
.standard, currentThemePath);
|
|
659
|
-
const { width, height } = await (0, sharp_1.default)(chartModeBadgeImg).metadata();
|
|
660
|
-
const aspectRatio = (width ?? 0) / (height ?? 1) || 3;
|
|
661
|
-
mode.src = chartModeBadgeImg;
|
|
662
|
-
const drawHeight = (jacketSize * 6) / 8;
|
|
663
|
-
ctx.drawImage(mode, curx +
|
|
664
|
-
((jacketSize * 7) / 8 -
|
|
665
|
-
drawHeight) /
|
|
666
|
-
2, cury +
|
|
667
|
-
element.scoreBubble.margin +
|
|
668
|
-
element.scoreBubble.height *
|
|
669
|
-
0.806 *
|
|
670
|
-
0.02, drawHeight, drawHeight / aspectRatio);
|
|
671
|
-
}
|
|
672
|
-
/** End Chart Mode Draw */
|
|
673
|
-
/** Begin Bests Index Draw */ {
|
|
674
|
-
drawText(ctx, `#${curindex + 1}`, curx +
|
|
675
|
-
element.scoreBubble.margin * 2, cury +
|
|
676
|
-
jacketSize -
|
|
677
|
-
element.scoreBubble.margin * 2, element.scoreBubble.height *
|
|
678
|
-
0.806 *
|
|
679
|
-
0.128, element.scoreBubble.height *
|
|
680
|
-
0.806 *
|
|
681
|
-
0.04, Infinity, "left", "white", new color_1.default(curColor)
|
|
682
|
-
.darken(0.3)
|
|
683
|
-
.hexa());
|
|
684
|
-
} /** End Bests Index Draw */
|
|
685
|
-
ctx.restore();
|
|
686
|
-
/** End Main Content Draw */
|
|
687
|
-
/** Begin Difficulty & DX Rating Draw */ {
|
|
688
|
-
drawText(ctx, `${curScore.chart.level.toFixed(1)} ↑${curScore.dxRating.toFixed(0)}`, curx +
|
|
689
|
-
element.scoreBubble.margin * 2, cury +
|
|
690
|
-
element.scoreBubble.height *
|
|
691
|
-
(0.806 + (1 - 0.806) / 2), element.scoreBubble.height *
|
|
692
|
-
0.806 *
|
|
693
|
-
0.128, element.scoreBubble.height *
|
|
694
|
-
0.806 *
|
|
695
|
-
0.04, Infinity, "left", "white", new color_1.default(curColor)
|
|
696
|
-
.darken(0.3)
|
|
697
|
-
.hexa());
|
|
698
|
-
if (curScore.chart.maxDxScore) {
|
|
699
|
-
drawText(ctx, `${curScore.dxScore}/${curScore.chart.maxDxScore}`, curx +
|
|
700
|
-
element.scoreBubble.width -
|
|
701
|
-
element.scoreBubble.margin *
|
|
702
|
-
2, cury +
|
|
703
|
-
element.scoreBubble.height *
|
|
704
|
-
(0.806 +
|
|
705
|
-
(1 - 0.806) / 2), element.scoreBubble.height *
|
|
706
|
-
0.806 *
|
|
707
|
-
0.128, element.scoreBubble.height *
|
|
708
|
-
0.806 *
|
|
709
|
-
0.04, Infinity, "right", "white", new color_1.default(curColor)
|
|
710
|
-
.darken(0.3)
|
|
711
|
-
.hexa());
|
|
712
|
-
}
|
|
713
|
-
} /** End Difficulty & DX Rating Draw */
|
|
714
|
-
ctx.restore();
|
|
715
|
-
}
|
|
764
|
+
curScore = oldScores[index];
|
|
765
|
+
await this.drawScoreGridModule(ctx, currentTheme, element, curScore, index, x, y);
|
|
716
766
|
}
|
|
717
767
|
}
|
|
718
768
|
break;
|
|
719
769
|
}
|
|
720
770
|
case "profile": {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
ctx.beginPath();
|
|
727
|
-
ctx.roundRect(element.x + element.height * 0.064, element.y + element.height * 0.064, element.height * 0.872, element.height * 0.872, (element.height * 0.872) / 16);
|
|
728
|
-
ctx.clip();
|
|
729
|
-
ctx.fillStyle = "white";
|
|
730
|
-
ctx.fill();
|
|
731
|
-
const profilePicture = options?.profilePicture ||
|
|
732
|
-
this.getThemeFile(currentTheme.sprites.profile.icon, currentThemePath);
|
|
733
|
-
const icon = new canvas_1.Image();
|
|
734
|
-
const { dominant } = await (0, sharp_1.default)(profilePicture).stats();
|
|
735
|
-
icon.src = profilePicture;
|
|
736
|
-
const cropSize = Math.min(icon.width, icon.height);
|
|
737
|
-
ctx.drawImage(icon, (icon.width - cropSize) / 2, (icon.height - cropSize) / 2, cropSize, cropSize, element.x + element.height * 0.064, element.y + element.height * 0.064, element.height * 0.872, element.height * 0.872);
|
|
738
|
-
if (options?.profilePicture) {
|
|
739
|
-
ctx.beginPath();
|
|
740
|
-
ctx.roundRect(element.x + element.height * 0.064, element.y + element.height * 0.064, element.height * 0.872, element.height * 0.872, (element.height * 0.872) / 16);
|
|
741
|
-
ctx.strokeStyle = color_1.default.rgb(dominant)
|
|
742
|
-
.darken(0.3)
|
|
743
|
-
.hex();
|
|
744
|
-
ctx.lineWidth = element.height / 30;
|
|
745
|
-
ctx.stroke();
|
|
746
|
-
}
|
|
747
|
-
ctx.restore();
|
|
748
|
-
/* End Profile Picture Draw */
|
|
749
|
-
const dxRating = new canvas_1.Image();
|
|
750
|
-
let dxRatingImg;
|
|
751
|
-
switch (true) {
|
|
752
|
-
case rating > 15000: {
|
|
753
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.rainbow, currentThemePath);
|
|
754
|
-
break;
|
|
755
|
-
}
|
|
756
|
-
case rating > 14500: {
|
|
757
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.platinum, currentThemePath);
|
|
758
|
-
break;
|
|
759
|
-
}
|
|
760
|
-
case rating > 14000: {
|
|
761
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.gold, currentThemePath);
|
|
762
|
-
break;
|
|
763
|
-
}
|
|
764
|
-
case rating > 13000: {
|
|
765
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.silver, currentThemePath);
|
|
766
|
-
break;
|
|
767
|
-
}
|
|
768
|
-
case rating > 12000: {
|
|
769
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.bronze, currentThemePath);
|
|
770
|
-
break;
|
|
771
|
-
}
|
|
772
|
-
case rating > 10000: {
|
|
773
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.purple, currentThemePath);
|
|
774
|
-
break;
|
|
775
|
-
}
|
|
776
|
-
case rating > 8000: {
|
|
777
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.red, currentThemePath);
|
|
778
|
-
break;
|
|
779
|
-
}
|
|
780
|
-
case rating > 6000: {
|
|
781
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.yellow, currentThemePath);
|
|
782
|
-
break;
|
|
783
|
-
}
|
|
784
|
-
case rating > 4000: {
|
|
785
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.green, currentThemePath);
|
|
786
|
-
break;
|
|
787
|
-
}
|
|
788
|
-
case rating > 2000: {
|
|
789
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.blue, currentThemePath);
|
|
790
|
-
break;
|
|
791
|
-
}
|
|
792
|
-
default: {
|
|
793
|
-
dxRatingImg = this.getThemeFile(currentTheme.sprites.dxRating.white, currentThemePath);
|
|
794
|
-
break;
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
dxRating.src = dxRatingImg;
|
|
798
|
-
ctx.drawImage(dxRating, element.x + element.height, element.y + element.height * 0.064, (element.height / 3) * 5.108, element.height / 3);
|
|
799
|
-
/* Start Username Draw */
|
|
800
|
-
ctx.beginPath();
|
|
801
|
-
ctx.roundRect(element.x + element.height * (1 + 1 / 32), element.y +
|
|
802
|
-
element.height * (0.064 + 0.333 + 1 / 32), ((element.height / 3) * 5.108 * 6) / 5, (element.height * 7) / 24, element.height / 20);
|
|
803
|
-
ctx.fillStyle = "white";
|
|
804
|
-
ctx.strokeStyle = color_1.default.rgb(180, 180, 180).hex();
|
|
805
|
-
ctx.lineWidth = element.height / 32;
|
|
806
|
-
ctx.stroke();
|
|
807
|
-
ctx.fill();
|
|
808
|
-
const ratingImgBuffer = await this.getRatingNumber(rating, {
|
|
809
|
-
manifest: currentTheme,
|
|
810
|
-
path: currentThemePath,
|
|
811
|
-
});
|
|
812
|
-
if (ratingImgBuffer) {
|
|
813
|
-
const { width, height } = await (0, sharp_1.default)(ratingImgBuffer).metadata();
|
|
814
|
-
if (width && height) {
|
|
815
|
-
const aspectRatio = width / height;
|
|
816
|
-
const image = new canvas_1.Image();
|
|
817
|
-
image.src = ratingImgBuffer;
|
|
818
|
-
const drawHeight = (element.height * 7) / 32;
|
|
819
|
-
ctx.drawImage(image, element.x + element.height * 1.785, element.y + element.height * 0.12, drawHeight * aspectRatio * 0.8, drawHeight);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
drawText(ctx, HalfFullWidthConvert.toFullWidth(name), element.x + element.height * (1 + 1 / 16), element.y +
|
|
823
|
-
element.height * (0.064 + 0.333 + 1 / 4), (element.height * 1) / 6, 0, ((element.height / 3) * 5.108 * 6) / 5, "left", "black", "black", "standard-font-username");
|
|
824
|
-
/* End Username Draw*/
|
|
771
|
+
await this.drawProfileModule(ctx, currentTheme, element, name, rating, options?.profilePicture);
|
|
772
|
+
break;
|
|
773
|
+
}
|
|
774
|
+
case "text": {
|
|
775
|
+
await this.drawTextModule(ctx, currentTheme, element);
|
|
825
776
|
break;
|
|
826
777
|
}
|
|
827
778
|
}
|