maidraw 0.9.4 → 0.10.0

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.
Files changed (167) hide show
  1. package/assets/themes/chunithm/best/luminousLandscape/new/manifest.json +58 -32
  2. package/assets/themes/chunithm/best/luminousLandscape/recents/manifest.json +57 -31
  3. package/assets/themes/chunithm/best/luminousPlusLandscape/new/manifest.json +57 -31
  4. package/assets/themes/chunithm/best/luminousPlusLandscape/recents/manifest.json +57 -31
  5. package/assets/themes/chunithm/best/verseLandscape/new/manifest.json +57 -31
  6. package/assets/themes/chunithm/best/verseLandscape/recents/manifest.json +57 -31
  7. package/assets/themes/chunithm/chart/jp/verse/manifest.json +73 -71
  8. package/assets/themes/maimai/best50/cn/2024Landscape/manifest.json +90 -54
  9. package/assets/themes/maimai/best50/cn/2024Portrait/manifest.json +89 -53
  10. package/assets/themes/maimai/best50/cn/2025Landscape/manifest.json +90 -54
  11. package/assets/themes/maimai/best50/cn/2025Portrait/manifest.json +89 -53
  12. package/assets/themes/maimai/best50/common/prism/plus/background.png +0 -0
  13. package/assets/themes/maimai/best50/jp/buddiesLandscape/manifest.json +89 -53
  14. package/assets/themes/maimai/best50/jp/buddiesPlusLandscape/manifest.json +89 -53
  15. package/assets/themes/maimai/best50/jp/buddiesPlusPortrait/manifest.json +89 -53
  16. package/assets/themes/maimai/best50/jp/buddiesPortrait/manifest.json +89 -53
  17. package/assets/themes/maimai/best50/jp/finaleLandscape/manifest.json +89 -53
  18. package/assets/themes/maimai/best50/jp/finalePortrait/manifest.json +89 -53
  19. package/assets/themes/maimai/best50/jp/prismLandscape/manifest.json +90 -54
  20. package/assets/themes/maimai/best50/jp/prismPlusLandscape/manifest.json +90 -54
  21. package/assets/themes/maimai/best50/jp/prismPlusPortrait/manifest.json +92 -55
  22. package/assets/themes/maimai/best50/jp/prismPortrait/manifest.json +89 -53
  23. package/assets/themes/maimai/best50/salt/2026landscape/manifest.json +89 -53
  24. package/assets/themes/maimai/chart/jp/prism/manifest.json +100 -96
  25. package/assets/themes/ongeki/jp/brightMemoryLandscape/classic/manifest.json +101 -30
  26. package/assets/themes/ongeki/jp/brightMemoryLandscape/refresh/manifest.json +78 -30
  27. package/assets/themes/ongeki/jp/refreshLandscape/classic/manifest.json +101 -2
  28. package/assets/themes/ongeki/jp/refreshLandscape/refresh/manifest.json +78 -30
  29. package/dist/chu/index.d.ts +14 -4
  30. package/dist/chu/index.js +16 -4
  31. package/dist/chu/index.js.map +1 -1
  32. package/dist/chu/lib/{index.d.ts → adapter/index.d.ts} +1 -1
  33. package/dist/chu/lib/{index.js → adapter/index.js} +1 -1
  34. package/dist/chu/lib/adapter/index.js.map +1 -0
  35. package/dist/chu/lib/{kamaiTachi → adapter/kamaiTachi}/index.d.ts +1 -1
  36. package/dist/chu/lib/{kamaiTachi → adapter/kamaiTachi}/index.js +10 -10
  37. package/dist/chu/lib/adapter/kamaiTachi/index.js.map +1 -0
  38. package/dist/chu/lib/{lxns → adapter/lxns}/index.d.ts +1 -1
  39. package/dist/chu/lib/{lxns → adapter/lxns}/index.js +4 -4
  40. package/dist/chu/lib/adapter/lxns/index.js.map +1 -0
  41. package/dist/chu/{chart → lib}/database.d.ts +3 -3
  42. package/dist/chu/{chart → lib}/database.js +2 -2
  43. package/dist/chu/lib/database.js.map +1 -0
  44. package/dist/chu/lib/util.d.ts +149 -0
  45. package/dist/chu/lib/util.js +270 -0
  46. package/dist/chu/lib/util.js.map +1 -0
  47. package/dist/chu/painter/best50/index.d.ts +120 -0
  48. package/dist/chu/painter/best50/index.js +158 -0
  49. package/dist/chu/painter/best50/index.js.map +1 -0
  50. package/dist/chu/painter/chart/index.d.ts +170 -0
  51. package/dist/chu/painter/chart/index.js +116 -0
  52. package/dist/chu/painter/chart/index.js.map +1 -0
  53. package/dist/chu/painter/index.d.ts +194 -0
  54. package/dist/chu/painter/index.js +1105 -0
  55. package/dist/chu/painter/index.js.map +1 -0
  56. package/dist/geki/index.d.ts +10 -4
  57. package/dist/geki/index.js +12 -4
  58. package/dist/geki/index.js.map +1 -1
  59. package/dist/geki/lib/adapter/index.js.map +1 -0
  60. package/dist/geki/lib/adapter/kamaiTachi/index.js.map +1 -0
  61. package/dist/geki/{chart → lib}/database.d.ts +1 -1
  62. package/dist/geki/{chart → lib}/database.js +2 -2
  63. package/dist/geki/lib/database.js.map +1 -0
  64. package/dist/geki/painter/best50/index.d.ts +122 -0
  65. package/dist/geki/painter/best50/index.js +197 -0
  66. package/dist/geki/painter/best50/index.js.map +1 -0
  67. package/dist/geki/painter/index.d.ts +88 -0
  68. package/dist/geki/painter/index.js +448 -0
  69. package/dist/geki/painter/index.js.map +1 -0
  70. package/dist/lib/cache.d.ts +1 -0
  71. package/dist/lib/cache.js +6 -1
  72. package/dist/lib/cache.js.map +1 -1
  73. package/dist/lib/painter.d.ts +100 -0
  74. package/dist/lib/painter.js +216 -0
  75. package/dist/lib/painter.js.map +1 -0
  76. package/dist/lib/util.d.ts +6 -282
  77. package/dist/lib/util.js +50 -540
  78. package/dist/lib/util.js.map +1 -1
  79. package/dist/mai/index.d.ts +22 -6
  80. package/dist/mai/index.js +24 -6
  81. package/dist/mai/index.js.map +1 -1
  82. package/dist/mai/lib/{divingFish → adapter/divingFish}/index.d.ts +6 -6
  83. package/dist/mai/lib/{divingFish → adapter/divingFish}/index.js +29 -30
  84. package/dist/mai/lib/adapter/divingFish/index.js.map +1 -0
  85. package/dist/mai/lib/{index.d.ts → adapter/index.d.ts} +11 -11
  86. package/dist/mai/lib/{index.js → adapter/index.js} +2 -2
  87. package/dist/{geki/bests/lib → mai/lib/adapter}/index.js.map +1 -1
  88. package/dist/mai/lib/{kamaiTachi → adapter/kamaiTachi}/index.d.ts +84 -42
  89. package/dist/mai/lib/{kamaiTachi → adapter/kamaiTachi}/index.js +70 -62
  90. package/dist/mai/lib/adapter/kamaiTachi/index.js.map +1 -0
  91. package/dist/mai/lib/{lxns → adapter/lxns}/index.d.ts +12 -12
  92. package/dist/mai/lib/{lxns → adapter/lxns}/index.js +29 -30
  93. package/dist/mai/lib/adapter/lxns/index.js.map +1 -0
  94. package/dist/mai/lib/{maishift → adapter/maishift}/index.d.ts +4 -4
  95. package/dist/mai/lib/{maishift → adapter/maishift}/index.js +20 -20
  96. package/dist/mai/lib/adapter/maishift/index.js.map +1 -0
  97. package/dist/mai/{chart → lib}/database.d.ts +3 -3
  98. package/dist/mai/{chart → lib}/database.js +2 -2
  99. package/dist/mai/lib/database.js.map +1 -0
  100. package/dist/mai/lib/util.d.ts +134 -0
  101. package/dist/mai/lib/util.js +264 -0
  102. package/dist/mai/lib/util.js.map +1 -0
  103. package/dist/mai/painter/best50/index.d.ts +140 -0
  104. package/dist/mai/painter/best50/index.js +176 -0
  105. package/dist/mai/painter/best50/index.js.map +1 -0
  106. package/dist/mai/painter/chart/index.d.ts +195 -0
  107. package/dist/mai/painter/chart/index.js +115 -0
  108. package/dist/mai/painter/chart/index.js.map +1 -0
  109. package/dist/mai/painter/index.d.ts +237 -0
  110. package/dist/mai/painter/index.js +1431 -0
  111. package/dist/mai/painter/index.js.map +1 -0
  112. package/dist/mai/painter/level50/index.d.ts +28 -0
  113. package/dist/mai/painter/level50/index.js +129 -0
  114. package/dist/mai/painter/level50/index.js.map +1 -0
  115. package/dist/mai/type.d.ts +110 -0
  116. package/dist/mai/type.js +73 -1
  117. package/dist/mai/type.js.map +1 -1
  118. package/package.json +56 -55
  119. package/dist/chu/bests/best50.d.ts +0 -37
  120. package/dist/chu/bests/best50.js +0 -742
  121. package/dist/chu/bests/best50.js.map +0 -1
  122. package/dist/chu/bests/index.d.ts +0 -1
  123. package/dist/chu/bests/index.js +0 -6
  124. package/dist/chu/bests/index.js.map +0 -1
  125. package/dist/chu/bests/type.d.ts +0 -122
  126. package/dist/chu/bests/type.js +0 -3
  127. package/dist/chu/bests/type.js.map +0 -1
  128. package/dist/chu/chart/database.js.map +0 -1
  129. package/dist/chu/chart/index.d.ts +0 -212
  130. package/dist/chu/chart/index.js +0 -1064
  131. package/dist/chu/chart/index.js.map +0 -1
  132. package/dist/chu/lib/index.js.map +0 -1
  133. package/dist/chu/lib/kamaiTachi/index.js.map +0 -1
  134. package/dist/chu/lib/lxns/index.js.map +0 -1
  135. package/dist/geki/bests/best50.d.ts +0 -35
  136. package/dist/geki/bests/best50.js +0 -821
  137. package/dist/geki/bests/best50.js.map +0 -1
  138. package/dist/geki/bests/index.d.ts +0 -1
  139. package/dist/geki/bests/index.js +0 -6
  140. package/dist/geki/bests/index.js.map +0 -1
  141. package/dist/geki/bests/lib/kamaiTachi/index.js.map +0 -1
  142. package/dist/geki/bests/type.d.ts +0 -122
  143. package/dist/geki/bests/type.js +0 -3
  144. package/dist/geki/bests/type.js.map +0 -1
  145. package/dist/geki/chart/database.js.map +0 -1
  146. package/dist/geki/chart/index.d.ts +0 -4
  147. package/dist/geki/chart/index.js +0 -32
  148. package/dist/geki/chart/index.js.map +0 -1
  149. package/dist/mai/best50/index.d.ts +0 -271
  150. package/dist/mai/best50/index.js +0 -915
  151. package/dist/mai/best50/index.js.map +0 -1
  152. package/dist/mai/chart/database.js.map +0 -1
  153. package/dist/mai/chart/index.d.ts +0 -238
  154. package/dist/mai/chart/index.js +0 -1281
  155. package/dist/mai/chart/index.js.map +0 -1
  156. package/dist/mai/level50/index.d.ts +0 -28
  157. package/dist/mai/level50/index.js +0 -774
  158. package/dist/mai/level50/index.js.map +0 -1
  159. package/dist/mai/lib/divingFish/index.js.map +0 -1
  160. package/dist/mai/lib/index.js.map +0 -1
  161. package/dist/mai/lib/kamaiTachi/index.js.map +0 -1
  162. package/dist/mai/lib/lxns/index.js.map +0 -1
  163. package/dist/mai/lib/maishift/index.js.map +0 -1
  164. /package/dist/geki/{bests/lib → lib/adapter}/index.d.ts +0 -0
  165. /package/dist/geki/{bests/lib → lib/adapter}/index.js +0 -0
  166. /package/dist/geki/{bests/lib → lib/adapter}/kamaiTachi/index.d.ts +0 -0
  167. /package/dist/geki/{bests/lib → lib/adapter}/kamaiTachi/index.js +0 -0
@@ -0,0 +1,1105 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ChunithmPainterModule = exports.ChunithmPainter = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const sharp_1 = __importDefault(require("sharp"));
9
+ const color_1 = __importDefault(require("color"));
10
+ const v4_1 = require("zod/v4");
11
+ const canvas_1 = require("canvas");
12
+ const database_1 = require("../lib/database");
13
+ const util_1 = require("../lib/util");
14
+ const type_1 = require("../type");
15
+ const util_2 = require("../../lib/util");
16
+ const painter_1 = require("../../lib/painter");
17
+ class ChunithmPainter extends painter_1.Painter {
18
+ constructor({ theme: { schema, searchPaths, defaultTheme }, }) {
19
+ super({ theme: { schema, searchPaths, defaultTheme } });
20
+ }
21
+ }
22
+ exports.ChunithmPainter = ChunithmPainter;
23
+ var ChunithmPainterModule;
24
+ (function (ChunithmPainterModule) {
25
+ let Profile;
26
+ (function (Profile) {
27
+ Profile.schema = painter_1.ThemeManager.Element.extend({
28
+ type: v4_1.z.literal("profile"),
29
+ height: v4_1.z.number().min(1),
30
+ sprites: v4_1.z.object({
31
+ ratingNumberMap: v4_1.z.string(),
32
+ profile: v4_1.z.object({
33
+ nameplate: v4_1.z.string(),
34
+ icon: v4_1.z.string(),
35
+ }),
36
+ }),
37
+ });
38
+ async function draw(ctx, theme, element, username, rating, profilePicture) {
39
+ const nameplate = new canvas_1.Image();
40
+ nameplate.src = theme.getFile(element.sprites.profile.nameplate);
41
+ ctx.drawImage(nameplate, element.x, element.y, element.height * 2.526, element.height);
42
+ /* Begin Profile Picture Draw */
43
+ {
44
+ ctx.save();
45
+ ctx.beginPath();
46
+ ctx.roundRect(element.x + element.height * 2.0, element.y + element.height * 0.3, element.height * 0.45, element.height * 0.45, 0);
47
+ ctx.clip();
48
+ ctx.fillStyle = "white";
49
+ ctx.fill();
50
+ const icon = new canvas_1.Image();
51
+ try {
52
+ (0, sharp_1.default)(profilePicture);
53
+ }
54
+ catch {
55
+ // Unknown profile picture binary
56
+ profilePicture = undefined;
57
+ }
58
+ const pfp = profilePicture ||
59
+ theme.getFile(element.sprites.profile.icon);
60
+ const { dominant } = await (0, sharp_1.default)(pfp).stats();
61
+ icon.src = await (0, sharp_1.default)(pfp).png().toBuffer();
62
+ const cropSize = Math.min(icon.width, icon.height);
63
+ ctx.drawImage(icon, (icon.width - cropSize) / 2, (icon.height - cropSize) / 2, cropSize, cropSize, element.x + element.height * 2.0, element.y + element.height * 0.3, element.height * 0.45, element.height * 0.45);
64
+ if (profilePicture) {
65
+ ctx.beginPath();
66
+ ctx.roundRect(element.x + element.height * 2.0, element.y + element.height * 0.3, element.height * 0.45, element.height * 0.45, 0);
67
+ ctx.strokeStyle = color_1.default.rgb(dominant).darken(0.3).hex();
68
+ ctx.lineWidth = element.height / 128;
69
+ ctx.stroke();
70
+ }
71
+ ctx.restore();
72
+ }
73
+ /* End Profile Picture Draw */
74
+ /* Begin Username Draw */
75
+ {
76
+ ctx.beginPath();
77
+ ctx.roundRect(element.x + element.height * (21 / 32), element.y + element.height * (11 / 32), element.height * (85 / 64), element.height * (13 / 32), 0);
78
+ ctx.fillStyle = "rgba(255, 255, 255, 0.45)";
79
+ ctx.fill();
80
+ // const ratingImgBuffer = await this.getRatingNumber(rating, theme);
81
+ // if (ratingImgBuffer) {
82
+ // const { width, height } =
83
+ // await sharp(ratingImgBuffer).metadata();
84
+ // if (width && height) {
85
+ // const aspectRatio = width / height;
86
+ // const image = new Image();
87
+ // image.src = ratingImgBuffer;
88
+ // const drawHeight = (element.height * 7) / 32;
89
+ // ctx.drawImage(
90
+ // image,
91
+ // element.x + element.height * 2.0,
92
+ // element.y + element.height * 0.3,
93
+ // drawHeight * aspectRatio * 0.8,
94
+ // drawHeight
95
+ // );
96
+ // }
97
+ // }
98
+ util_2.Util.drawText(ctx, "Lv.", element.x + element.height * (43 / 64), element.y + element.height * (0.3 + 1 / 4), (element.height * 1) / 16, 0, ((element.height / 3) * 5.108 * 3.1) / 5, "left", "black", "black", "standard-font-username");
99
+ util_2.Util.drawText(ctx, "99", element.x + element.height * (49 / 64), element.y + element.height * (0.3 + 1 / 4), (element.height * 1) / 11, 0, ((element.height / 3) * 5.108 * 3.1) / 5, "left", "black", "black", "standard-font-username");
100
+ util_2.Util.drawText(ctx, util_2.Util.HalfFullWidthConvert.toFullWidth(username), element.x + element.height * (56 / 64), element.y + element.height * (0.3 + 1 / 4), (element.height * 1) / 8, 0, element.height * (65 / 64), "left", "black", "black", "standard-font-username");
101
+ util_2.Util.drawText(ctx, "RATING", element.x + element.height * (43 / 64), element.y + element.height * (47 / 64), (element.height * 7) / 88, 0, ((element.height / 3) * 5.108 * 3.1) / 5, "left", "black", "black", "standard-font-username");
102
+ util_2.Util.drawText(ctx, util_2.Util.truncate(rating, 2), element.x + element.height * (67 / 64), element.y + element.height * (47 / 64), (element.height * 5) / 44, 0, ((element.height / 3) * 5.108 * 3.1) / 5, "left", "black", "black", "standard-font-username");
103
+ }
104
+ /* End Username Draw*/
105
+ }
106
+ Profile.draw = draw;
107
+ })(Profile = ChunithmPainterModule.Profile || (ChunithmPainterModule.Profile = {}));
108
+ let Best50;
109
+ (function (Best50) {
110
+ let ScoreGrid;
111
+ (function (ScoreGrid) {
112
+ ScoreGrid.schema = painter_1.ThemeManager.Element.extend({
113
+ type: v4_1.z.literal("score-grid"),
114
+ horizontalSize: v4_1.z.number().min(1),
115
+ verticalSize: v4_1.z.number().min(1),
116
+ region: v4_1.z.enum(["new", "old"]),
117
+ index: v4_1.z.number().min(0),
118
+ scoreBubble: v4_1.z.object({
119
+ width: v4_1.z.number().min(1),
120
+ height: v4_1.z.number().min(1),
121
+ margin: v4_1.z.number().min(0),
122
+ gap: v4_1.z.number().min(0),
123
+ color: v4_1.z.object({
124
+ basic: util_2.Util.z.color(),
125
+ advanced: util_2.Util.z.color(),
126
+ expert: util_2.Util.z.color(),
127
+ master: util_2.Util.z.color(),
128
+ ultima: util_2.Util.z.color(),
129
+ worldsEnd: util_2.Util.z.color(),
130
+ }),
131
+ }),
132
+ sprites: v4_1.z.object({
133
+ achievement: v4_1.z.object({
134
+ d: v4_1.z.string(),
135
+ c: v4_1.z.string(),
136
+ b: v4_1.z.string(),
137
+ bb: v4_1.z.string(),
138
+ bbb: v4_1.z.string(),
139
+ a: v4_1.z.string(),
140
+ aa: v4_1.z.string(),
141
+ aaa: v4_1.z.string(),
142
+ s: v4_1.z.string(),
143
+ sp: v4_1.z.string(),
144
+ ss: v4_1.z.string(),
145
+ ssp: v4_1.z.string(),
146
+ sss: v4_1.z.string(),
147
+ sssp: v4_1.z.string(),
148
+ }),
149
+ milestone: v4_1.z.object({
150
+ aj: v4_1.z.string(),
151
+ ajc: v4_1.z.string(),
152
+ fc: v4_1.z.string(),
153
+ none: v4_1.z.string(),
154
+ }),
155
+ }),
156
+ });
157
+ async function draw(ctx, theme, element, score, index, x, y) {
158
+ let curColor = "#FFFFFF";
159
+ switch (score.chart.difficulty) {
160
+ case type_1.EDifficulty.BASIC:
161
+ curColor = element.scoreBubble.color.basic;
162
+ break;
163
+ case type_1.EDifficulty.ADVANCED:
164
+ curColor = element.scoreBubble.color.advanced;
165
+ break;
166
+ case type_1.EDifficulty.EXPERT:
167
+ curColor = element.scoreBubble.color.expert;
168
+ break;
169
+ case type_1.EDifficulty.MASTER:
170
+ curColor = element.scoreBubble.color.master;
171
+ break;
172
+ case type_1.EDifficulty.ULTIMA:
173
+ curColor = element.scoreBubble.color.ultima;
174
+ break;
175
+ case type_1.EDifficulty.WORLDS_END:
176
+ curColor = element.scoreBubble.color.worldsEnd;
177
+ break;
178
+ }
179
+ /** Begin Card Draw */
180
+ ctx.save();
181
+ ctx.fillStyle = new color_1.default(curColor).lighten(0.4).hexa();
182
+ ctx.beginPath();
183
+ ctx.roundRect(x, y, element.scoreBubble.width, element.scoreBubble.height, (element.scoreBubble.height * 0.806) / 7);
184
+ ctx.strokeStyle = new color_1.default(curColor).darken(0.3).hexa();
185
+ ctx.lineWidth = element.scoreBubble.margin / 4;
186
+ ctx.stroke();
187
+ ctx.fill();
188
+ ctx.beginPath();
189
+ ctx.roundRect(x, y, element.scoreBubble.width, element.scoreBubble.height, (element.scoreBubble.height * 0.806) / 7);
190
+ ctx.clip();
191
+ /** Begin Main Content Draw */
192
+ {
193
+ ctx.save();
194
+ ctx.beginPath();
195
+ ctx.roundRect(x, y, element.scoreBubble.width, element.scoreBubble.height * 0.742, (element.scoreBubble.height * 0.806) / 7);
196
+ ctx.clip();
197
+ ctx.fillStyle = curColor;
198
+ ctx.fill();
199
+ const jacketSize = Math.min(element.scoreBubble.width, element.scoreBubble.height * 0.742);
200
+ const jacketMaskGrad = ctx.createLinearGradient(x + jacketSize / 2, y + jacketSize / 2, x + jacketSize, y + jacketSize / 2);
201
+ jacketMaskGrad.addColorStop(0, new color_1.default(curColor).alpha(0).hexa());
202
+ jacketMaskGrad.addColorStop(0.25, new color_1.default(curColor).alpha(0.2).hexa());
203
+ jacketMaskGrad.addColorStop(1, new color_1.default(curColor).alpha(1).hexa());
204
+ const jacketMaskGradDark = ctx.createLinearGradient(x + jacketSize / 2, y + jacketSize / 2, x + jacketSize, y + jacketSize / 2);
205
+ jacketMaskGradDark.addColorStop(0, new color_1.default(curColor).darken(0.3).alpha(0).hexa());
206
+ jacketMaskGradDark.addColorStop(0.25, new color_1.default(curColor).darken(0.3).alpha(0.2).hexa());
207
+ jacketMaskGradDark.addColorStop(1, new color_1.default(curColor).darken(0.3).alpha(1).hexa());
208
+ /** Begin Jacket Draw*/
209
+ let jacket = await database_1.Database.fetchJacket(score.chart.id);
210
+ if (!jacket)
211
+ jacket = await database_1.Database.fetchJacket(-1);
212
+ if (jacket) {
213
+ const img = new canvas_1.Image();
214
+ img.src = jacket;
215
+ ctx.drawImage(img, x, y, jacketSize, jacketSize);
216
+ }
217
+ else {
218
+ ctx.fillStyle = "#b6ffab";
219
+ ctx.fillRect(x, y, jacketSize, jacketSize);
220
+ }
221
+ /** End Jacket Draw*/
222
+ /** Begin Jacket Gradient Mask Draw*/ {
223
+ ctx.fillStyle = jacketMaskGrad;
224
+ ctx.fillRect(x + jacketSize / 2, y, (jacketSize * 3) / 4, jacketSize);
225
+ } /** End Jacket Gradient Mask Draw*/
226
+ ctx.beginPath();
227
+ ctx.roundRect(x + element.scoreBubble.margin, y + element.scoreBubble.margin, element.scoreBubble.width -
228
+ element.scoreBubble.margin * 2, element.scoreBubble.height * 0.806 -
229
+ element.scoreBubble.margin * 2, (element.scoreBubble.height * 0.806 -
230
+ element.scoreBubble.margin * 2) /
231
+ 7);
232
+ /** Begin Title Draw */ {
233
+ util_2.Util.drawText(ctx, score.chart.name, x + (jacketSize * 7) / 8, y +
234
+ element.scoreBubble.margin +
235
+ element.scoreBubble.height * 0.806 * 0.144, element.scoreBubble.height * 0.806 * 0.144, element.scoreBubble.height * 0.806 * 0.04, element.scoreBubble.width -
236
+ (jacketSize * 7) / 8 -
237
+ element.scoreBubble.margin, "left", "white", jacketMaskGradDark);
238
+ } /** End Title Draw */
239
+ /** Begin Separation Line Draw */ {
240
+ ctx.beginPath();
241
+ ctx.roundRect(x + (jacketSize * 13) / 16, y +
242
+ element.scoreBubble.margin +
243
+ element.scoreBubble.height *
244
+ 0.806 *
245
+ (0.144 + 0.072), element.scoreBubble.width -
246
+ (jacketSize * 13) / 16 -
247
+ element.scoreBubble.margin * 2, element.scoreBubble.height * 0.806 * 0.02, element.scoreBubble.height * 0.806 * 0.16);
248
+ ctx.fillStyle = jacketMaskGradDark;
249
+ ctx.fill();
250
+ } /** End Separation Line Draw */
251
+ /** Begin Achievement Rate Draw */
252
+ util_2.Util.drawText(ctx, util_2.Util.truncate(score.score, 0), x -
253
+ element.scoreBubble.margin -
254
+ element.scoreBubble.height * 0.806 * 0.02 +
255
+ element.scoreBubble.width, y +
256
+ element.scoreBubble.margin +
257
+ element.scoreBubble.height *
258
+ 0.806 *
259
+ (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());
260
+ /** End Achievement Rate Draw */
261
+ /** Begin Achievement Rank Draw */
262
+ {
263
+ let rankImg;
264
+ switch (score.rank) {
265
+ case type_1.EAchievementTypes.D:
266
+ rankImg = theme.getFile(element.sprites.achievement.d);
267
+ break;
268
+ case type_1.EAchievementTypes.C:
269
+ rankImg = theme.getFile(element.sprites.achievement.c);
270
+ break;
271
+ case type_1.EAchievementTypes.B:
272
+ rankImg = theme.getFile(element.sprites.achievement.b);
273
+ break;
274
+ case type_1.EAchievementTypes.BB:
275
+ rankImg = theme.getFile(element.sprites.achievement.bb);
276
+ break;
277
+ case type_1.EAchievementTypes.BBB:
278
+ rankImg = theme.getFile(element.sprites.achievement.bbb);
279
+ break;
280
+ case type_1.EAchievementTypes.A:
281
+ rankImg = theme.getFile(element.sprites.achievement.a);
282
+ break;
283
+ case type_1.EAchievementTypes.AA:
284
+ rankImg = theme.getFile(element.sprites.achievement.aa);
285
+ break;
286
+ case type_1.EAchievementTypes.AAA:
287
+ rankImg = theme.getFile(element.sprites.achievement.aaa);
288
+ break;
289
+ case type_1.EAchievementTypes.S:
290
+ rankImg = theme.getFile(element.sprites.achievement.s);
291
+ break;
292
+ case type_1.EAchievementTypes.SP:
293
+ rankImg = theme.getFile(element.sprites.achievement.sp);
294
+ break;
295
+ case type_1.EAchievementTypes.SS:
296
+ rankImg = theme.getFile(element.sprites.achievement.ss);
297
+ break;
298
+ case type_1.EAchievementTypes.SSP:
299
+ rankImg = theme.getFile(element.sprites.achievement.ssp);
300
+ break;
301
+ case type_1.EAchievementTypes.SSS:
302
+ rankImg = theme.getFile(element.sprites.achievement.sss);
303
+ break;
304
+ default:
305
+ rankImg = theme.getFile(element.sprites.achievement.sssp);
306
+ }
307
+ const img = new canvas_1.Image();
308
+ img.src = rankImg;
309
+ ctx.drawImage(img, x + jacketSize * (13 / 16), y +
310
+ element.scoreBubble.margin +
311
+ element.scoreBubble.height *
312
+ 0.806 *
313
+ (0.144 + 0.144 - 0.01), element.scoreBubble.height * 0.806 * 0.2 * 3, element.scoreBubble.height * 0.806 * 0.2);
314
+ }
315
+ /** End Achievement Rank Draw */
316
+ /** Begin Milestone Draw */
317
+ {
318
+ let comboImg;
319
+ switch (score.combo) {
320
+ case type_1.EComboTypes.NONE:
321
+ comboImg = theme.getFile(element.sprites.milestone.none);
322
+ break;
323
+ case type_1.EComboTypes.FULL_COMBO:
324
+ comboImg = theme.getFile(element.sprites.milestone.fc);
325
+ break;
326
+ case type_1.EComboTypes.ALL_JUSTICE:
327
+ comboImg = theme.getFile(element.sprites.milestone.aj);
328
+ break;
329
+ case type_1.EComboTypes.ALL_JUSTICE_CRITICAL:
330
+ comboImg = theme.getFile(element.sprites.milestone.ajc);
331
+ break;
332
+ }
333
+ ctx.fillStyle = "#e8eaec";
334
+ ctx.roundRect(x -
335
+ element.scoreBubble.height * 0.806 * 0.32 * 3 -
336
+ element.scoreBubble.margin -
337
+ element.scoreBubble.height * 0.806 * 0.02 +
338
+ element.scoreBubble.width, y +
339
+ element.scoreBubble.margin +
340
+ element.scoreBubble.height *
341
+ 0.806 *
342
+ (0.144 + 0.144 + 0.208 + 0.1), element.scoreBubble.height * 0.806 * 0.32 * 3, (element.scoreBubble.height * 0.806 * 0.32 * 3) /
343
+ 6.7, (element.scoreBubble.height * 0.806 * 0.32 * 3) / 56);
344
+ ctx.fill();
345
+ const combo = new canvas_1.Image();
346
+ combo.src = comboImg;
347
+ ctx.drawImage(combo, x -
348
+ element.scoreBubble.height * 0.806 * 0.32 * 3 -
349
+ element.scoreBubble.margin -
350
+ element.scoreBubble.height * 0.806 * 0.02 +
351
+ element.scoreBubble.width, y +
352
+ element.scoreBubble.margin +
353
+ element.scoreBubble.height *
354
+ 0.806 *
355
+ (0.144 + 0.144 + 0.208 + 0.1), element.scoreBubble.height * 0.806 * 0.32 * 3, (element.scoreBubble.height * 0.806 * 0.32 * 3) /
356
+ 6.7);
357
+ }
358
+ /** End Milestone Draw */
359
+ /** Begin Bests Index Draw */
360
+ {
361
+ util_2.Util.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());
362
+ }
363
+ /** End Bests Index Draw */
364
+ ctx.restore();
365
+ }
366
+ /** End Main Content Draw */
367
+ /** Begin Difficulty & Rating Draw */
368
+ {
369
+ util_2.Util.drawText(ctx, `lv. ${util_2.Util.truncate(score.chart.level, 1)}`, x + element.scoreBubble.margin * 2, y +
370
+ element.scoreBubble.height *
371
+ (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());
372
+ util_2.Util.drawText(ctx, `+${util_2.Util.truncate(score.rating, 2)}`, x +
373
+ element.scoreBubble.width -
374
+ element.scoreBubble.margin * 2, y +
375
+ element.scoreBubble.height *
376
+ (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());
377
+ }
378
+ /** End Difficulty & Rating Draw */
379
+ ctx.restore();
380
+ /** End Card Draw */
381
+ }
382
+ ScoreGrid.draw = draw;
383
+ })(ScoreGrid = Best50.ScoreGrid || (Best50.ScoreGrid = {}));
384
+ })(Best50 = ChunithmPainterModule.Best50 || (ChunithmPainterModule.Best50 = {}));
385
+ let Chart;
386
+ (function (Chart) {
387
+ const JPN_LATEST = 230;
388
+ const INT_LATEST = 140;
389
+ const CHN_LATEST = 120;
390
+ const CHUNITHM_VERSIONS = [
391
+ 240, 230, 225, 220, 215, 210, 205, 200, 150, 145, 140, 135, 130,
392
+ 125, 120, 115, 110, 105, 100,
393
+ ];
394
+ const CHUNITHM_INT_VERSIONS = [
395
+ 140, 135, 130, 125, 120, 115, 110, 105, 100,
396
+ ];
397
+ const ZHONGERJIEZOU_VERSIONS = [120, 110, 100];
398
+ function findVersion(v, region) {
399
+ const target = (() => {
400
+ switch (region) {
401
+ case "INT":
402
+ return CHUNITHM_INT_VERSIONS;
403
+ case "CHN":
404
+ return ZHONGERJIEZOU_VERSIONS;
405
+ case "JPN":
406
+ default:
407
+ return CHUNITHM_VERSIONS;
408
+ }
409
+ })();
410
+ for (const version of target) {
411
+ if (v >= version)
412
+ return version;
413
+ }
414
+ return null;
415
+ }
416
+ let ChartGrid;
417
+ (function (ChartGrid) {
418
+ ChartGrid.schema = painter_1.ThemeManager.Element.extend({
419
+ type: v4_1.z.literal("chart-grid"),
420
+ width: v4_1.z.number().min(1),
421
+ height: v4_1.z.number().min(1),
422
+ margin: v4_1.z.number().min(0),
423
+ gap: v4_1.z.number().min(0),
424
+ bubble: v4_1.z.object({
425
+ margin: v4_1.z.number().min(0),
426
+ color: v4_1.z.object({
427
+ basic: util_2.Util.z.color(),
428
+ advanced: util_2.Util.z.color(),
429
+ expert: util_2.Util.z.color(),
430
+ master: util_2.Util.z.color(),
431
+ ultima: util_2.Util.z.color(),
432
+ worldsEnd: util_2.Util.z.color(),
433
+ }),
434
+ }),
435
+ color: v4_1.z.object({
436
+ card: util_2.Util.z.color(),
437
+ }),
438
+ sprites: v4_1.z.object({
439
+ achievement: v4_1.z.object({
440
+ d: v4_1.z.string(),
441
+ c: v4_1.z.string(),
442
+ b: v4_1.z.string(),
443
+ bb: v4_1.z.string(),
444
+ bbb: v4_1.z.string(),
445
+ a: v4_1.z.string(),
446
+ aa: v4_1.z.string(),
447
+ aaa: v4_1.z.string(),
448
+ s: v4_1.z.string(),
449
+ sp: v4_1.z.string(),
450
+ ss: v4_1.z.string(),
451
+ ssp: v4_1.z.string(),
452
+ sss: v4_1.z.string(),
453
+ sssp: v4_1.z.string(),
454
+ }),
455
+ milestone: v4_1.z.object({
456
+ aj: v4_1.z.string(),
457
+ ajc: v4_1.z.string(),
458
+ fc: v4_1.z.string(),
459
+ none: v4_1.z.string(),
460
+ }),
461
+ versions: v4_1.z.object({
462
+ JPN: v4_1.z.object({
463
+ "100": v4_1.z.string(),
464
+ "105": v4_1.z.string(),
465
+ "110": v4_1.z.string(),
466
+ "115": v4_1.z.string(),
467
+ "120": v4_1.z.string(),
468
+ "125": v4_1.z.string(),
469
+ "130": v4_1.z.string(),
470
+ "135": v4_1.z.string(),
471
+ "140": v4_1.z.string(),
472
+ "145": v4_1.z.string(),
473
+ "150": v4_1.z.string(),
474
+ "155": v4_1.z.string(),
475
+ "200": v4_1.z.string(),
476
+ "205": v4_1.z.string(),
477
+ "210": v4_1.z.string(),
478
+ "215": v4_1.z.string(),
479
+ "220": v4_1.z.string(),
480
+ "225": v4_1.z.string(),
481
+ "230": v4_1.z.string(),
482
+ "240": v4_1.z.string(),
483
+ }),
484
+ INT: v4_1.z.object({
485
+ "100": v4_1.z.string(),
486
+ "105": v4_1.z.string(),
487
+ "110": v4_1.z.string(),
488
+ "115": v4_1.z.string(),
489
+ "120": v4_1.z.string(),
490
+ "125": v4_1.z.string(),
491
+ "130": v4_1.z.string(),
492
+ "135": v4_1.z.string(),
493
+ "140": v4_1.z.string(),
494
+ }),
495
+ CHN: v4_1.z.object({
496
+ "100": v4_1.z.string(),
497
+ "110": v4_1.z.string(),
498
+ "120": v4_1.z.string(),
499
+ "130": v4_1.z.string(),
500
+ }),
501
+ }),
502
+ }),
503
+ });
504
+ async function draw(ctx, theme, element, chartId, scores, region = "JPN") {
505
+ /* Begin Background Draw */
506
+ ctx.roundRect(element.x, element.y, element.width, element.height, Math.min(theme.content.width, theme.content.height) *
507
+ (3 / 128));
508
+ ctx.fillStyle = element.color.card;
509
+ ctx.strokeStyle = new color_1.default(element.color.card)
510
+ .darken(0.6)
511
+ .hex();
512
+ ctx.lineWidth =
513
+ Math.min(theme.content.width, theme.content.height) *
514
+ (3 / 512);
515
+ ctx.stroke();
516
+ ctx.fill();
517
+ /* End Background Draw */
518
+ const difficulties = [];
519
+ for (let i = type_1.EDifficulty.BASIC; i <= type_1.EDifficulty.ULTIMA; ++i) {
520
+ const chart = database_1.Database.getLocalChart(chartId, i);
521
+ if (chart)
522
+ difficulties.push(chart);
523
+ }
524
+ const cardWidth = element.width - element.margin * 2;
525
+ const cardHeight = (element.height - element.margin * 2 - element.gap * 3) / 4;
526
+ for (let y = element.y + element.margin, i = 0; i < difficulties.length; ++i, y += cardHeight + element.gap) {
527
+ const chart = difficulties[i];
528
+ if (chart)
529
+ if (difficulties.length > 4 && i == 0) {
530
+ await drawChartGridCard(ctx, theme, element, chart, i, element.x + element.margin, y, (cardWidth - element.margin) / 2, cardHeight, true, region, scores[i]);
531
+ i++;
532
+ const chartA = difficulties[i];
533
+ if (chartA)
534
+ await drawChartGridCard(ctx, theme, element, chartA, i, element.x +
535
+ element.margin +
536
+ (cardWidth + element.margin) / 2, y, (cardWidth - element.margin) / 2, cardHeight, true, region, scores[i]);
537
+ }
538
+ else {
539
+ await drawChartGridCard(ctx, theme, element, chart, i, element.x + element.margin, y, cardWidth, cardHeight, false, region, scores[i]);
540
+ }
541
+ }
542
+ }
543
+ ChartGrid.draw = draw;
544
+ async function drawChartGridCard(ctx, theme, element, chart, difficulty, x, y, width, height, isShort, targetRegion = "JPN", score) {
545
+ let curColor = "#FFFFFF";
546
+ switch (difficulty) {
547
+ case type_1.EDifficulty.BASIC:
548
+ curColor = element.bubble.color.basic;
549
+ break;
550
+ case type_1.EDifficulty.ADVANCED:
551
+ curColor = element.bubble.color.advanced;
552
+ break;
553
+ case type_1.EDifficulty.EXPERT:
554
+ curColor = element.bubble.color.expert;
555
+ break;
556
+ case type_1.EDifficulty.MASTER:
557
+ curColor = element.bubble.color.master;
558
+ break;
559
+ case type_1.EDifficulty.ULTIMA:
560
+ curColor = element.bubble.color.ultima;
561
+ break;
562
+ case type_1.EDifficulty.WORLDS_END:
563
+ curColor = element.bubble.color.worldsEnd;
564
+ break;
565
+ }
566
+ /** Begin Card Draw */
567
+ ctx.save();
568
+ ctx.fillStyle = new color_1.default(curColor).lighten(0.4).hexa();
569
+ ctx.beginPath();
570
+ ctx.roundRect(x, y, width, height, (height * 0.806) / 7);
571
+ ctx.strokeStyle = new color_1.default(curColor).darken(0.3).hexa();
572
+ ctx.lineWidth = element.bubble.margin / 4;
573
+ ctx.stroke();
574
+ ctx.fill();
575
+ ctx.beginPath();
576
+ ctx.roundRect(x, y, width, height, (height * 0.806) / 7);
577
+ ctx.clip();
578
+ /** Begin Main Content Draw */
579
+ {
580
+ ctx.save();
581
+ ctx.beginPath();
582
+ ctx.rect(x, y, width, height);
583
+ ctx.clip();
584
+ ctx.fillStyle = curColor;
585
+ ctx.fill();
586
+ const titleSize = height * (47 / 256);
587
+ /** Begin Difficulty Text & Separation Line Draw */
588
+ {
589
+ let difficultiy = "";
590
+ switch (chart.difficulty) {
591
+ case type_1.EDifficulty.BASIC:
592
+ difficultiy = "BASIC";
593
+ break;
594
+ case type_1.EDifficulty.ADVANCED:
595
+ difficultiy = "ADVANCED";
596
+ break;
597
+ case type_1.EDifficulty.EXPERT:
598
+ difficultiy = "EXPERT";
599
+ break;
600
+ case type_1.EDifficulty.MASTER:
601
+ difficultiy = "MASTER";
602
+ break;
603
+ case type_1.EDifficulty.ULTIMA:
604
+ difficultiy = "ULTIMA";
605
+ break;
606
+ case type_1.EDifficulty.WORLDS_END:
607
+ difficultiy = "WORLD'S END";
608
+ break;
609
+ }
610
+ const levelTextSize = titleSize * (5 / 8);
611
+ util_2.Util.drawText(ctx, difficultiy, x + element.bubble.margin, y +
612
+ element.bubble.margin +
613
+ titleSize -
614
+ element.bubble.margin * (1 / 4), titleSize, height * 0.806 * 0.04, Infinity, "left", "white", new color_1.default(curColor).darken(0.3).hexa());
615
+ const difficultyTextWidth = util_2.Util.measureText(ctx, difficultiy, titleSize, Infinity).width;
616
+ util_2.Util.drawText(ctx, `Lv. ${util_2.Util.truncate(chart.events
617
+ .filter((v) => v.version.region == targetRegion)
618
+ .reverse()
619
+ .find((v) => v.type == "existence")?.data
620
+ .level || 0, 1)}${score ? ` +${util_2.Util.truncate(score.rating, 1)}` : ""}`, x + element.bubble.margin * 2 + difficultyTextWidth, y +
621
+ element.bubble.margin +
622
+ titleSize -
623
+ element.bubble.margin * (1 / 4), levelTextSize, height * 0.806 * 0.04, Infinity, "left", "white", new color_1.default(curColor).darken(0.3).hexa());
624
+ ctx.beginPath();
625
+ ctx.roundRect(x + element.bubble.margin, y +
626
+ element.bubble.margin +
627
+ titleSize +
628
+ element.bubble.margin * (1 / 4), height * 2 - element.bubble.margin * 2, height * 0.806 * 0.02, height * 0.806 * 0.16);
629
+ ctx.fillStyle = new color_1.default(curColor).darken(0.3).hex();
630
+ ctx.fill();
631
+ }
632
+ /** End Difficulty Text & Separation Line Draw */
633
+ /** Begin Achievement Rate Draw */
634
+ {
635
+ const scoreSize = height * 0.806 * 0.208;
636
+ util_2.Util.drawText(ctx, score ? util_2.Util.truncate(score.score, 0) : "NO RECORD", x +
637
+ height * 2 -
638
+ element.bubble.margin -
639
+ height * 0.806 * 0.02, y +
640
+ element.bubble.margin +
641
+ titleSize +
642
+ element.bubble.margin * (5 / 8) +
643
+ scoreSize, scoreSize, height * 0.806 * 0.04, Infinity, "right", "white", new color_1.default(curColor).darken(0.3).hexa());
644
+ }
645
+ /** End Achievement Rate Draw */
646
+ /** Begin Achievement Rank Draw */
647
+ {
648
+ if (score) {
649
+ let rankImg;
650
+ switch (score.rank) {
651
+ case type_1.EAchievementTypes.D:
652
+ rankImg = theme.getFile(element.sprites.achievement.d);
653
+ break;
654
+ case type_1.EAchievementTypes.C:
655
+ rankImg = theme.getFile(element.sprites.achievement.c);
656
+ break;
657
+ case type_1.EAchievementTypes.B:
658
+ rankImg = theme.getFile(element.sprites.achievement.b);
659
+ break;
660
+ case type_1.EAchievementTypes.BB:
661
+ rankImg = theme.getFile(element.sprites.achievement.bb);
662
+ break;
663
+ case type_1.EAchievementTypes.BBB:
664
+ rankImg = theme.getFile(element.sprites.achievement.bbb);
665
+ break;
666
+ case type_1.EAchievementTypes.A:
667
+ rankImg = theme.getFile(element.sprites.achievement.a);
668
+ break;
669
+ case type_1.EAchievementTypes.AA:
670
+ rankImg = theme.getFile(element.sprites.achievement.aa);
671
+ break;
672
+ case type_1.EAchievementTypes.AAA:
673
+ rankImg = theme.getFile(element.sprites.achievement.aaa);
674
+ break;
675
+ case type_1.EAchievementTypes.S:
676
+ rankImg = theme.getFile(element.sprites.achievement.s);
677
+ break;
678
+ case type_1.EAchievementTypes.SP:
679
+ rankImg = theme.getFile(element.sprites.achievement.sp);
680
+ break;
681
+ case type_1.EAchievementTypes.SS:
682
+ rankImg = theme.getFile(element.sprites.achievement.ss);
683
+ break;
684
+ case type_1.EAchievementTypes.SSP:
685
+ rankImg = theme.getFile(element.sprites.achievement.ssp);
686
+ break;
687
+ case type_1.EAchievementTypes.SSS:
688
+ rankImg = theme.getFile(element.sprites.achievement.sss);
689
+ break;
690
+ default:
691
+ rankImg = theme.getFile(element.sprites.achievement.sssp);
692
+ }
693
+ const blockHeight = height * 0.806 * 0.3 * 0.85, blockWidth = blockHeight * (540 / 180);
694
+ const img = new canvas_1.Image();
695
+ img.src = rankImg;
696
+ ctx.drawImage(img, x + element.bubble.margin * (1 / 2), y +
697
+ element.bubble.margin +
698
+ titleSize +
699
+ element.bubble.margin * (1 / 2), blockWidth, blockHeight);
700
+ }
701
+ }
702
+ /** End Achievement Rank Draw */
703
+ /** Begin Milestone Draw */
704
+ {
705
+ const blockWidth = height * 0.806 * 0.32 * 3, blockHeight = (blockWidth * 40) / 268;
706
+ const curX = x -
707
+ blockWidth +
708
+ height * 2 -
709
+ element.bubble.margin, curY = y + element.bubble.margin * 2 + titleSize * 2;
710
+ ctx.fillStyle = "#e8eaec";
711
+ ctx.roundRect(curX, curY, blockWidth, blockHeight, blockWidth / 56);
712
+ ctx.fill();
713
+ if (score) {
714
+ let comboImg;
715
+ switch (score.combo) {
716
+ case type_1.EComboTypes.NONE:
717
+ comboImg = theme.getFile(element.sprites.milestone.none);
718
+ break;
719
+ case type_1.EComboTypes.FULL_COMBO:
720
+ comboImg = theme.getFile(element.sprites.milestone.fc);
721
+ break;
722
+ case type_1.EComboTypes.ALL_JUSTICE:
723
+ comboImg = theme.getFile(element.sprites.milestone.aj);
724
+ break;
725
+ case type_1.EComboTypes.ALL_JUSTICE_CRITICAL:
726
+ comboImg = theme.getFile(element.sprites.milestone.ajc);
727
+ break;
728
+ }
729
+ const combo = new canvas_1.Image();
730
+ combo.src = comboImg;
731
+ ctx.drawImage(combo, curX, curY, blockWidth, blockHeight);
732
+ }
733
+ }
734
+ /** End Milestone Draw */
735
+ /** Begin Version Draw */
736
+ {
737
+ const version = {
738
+ region: "JPN",
739
+ version: undefined,
740
+ };
741
+ const VER = chart.difficulty == type_1.EDifficulty.ULTIMA
742
+ ? chart.events.find((v) => v.type == "existence" &&
743
+ v.version.region == targetRegion)?.version
744
+ : chart.addVersion;
745
+ version.version = VER;
746
+ version.region = targetRegion;
747
+ const versionImageHeight = (height - element.bubble.margin * 2) *
748
+ (isShort ? 9 / 16 : 1 / 2);
749
+ const versionImageWidth = (versionImageHeight / 160) * 201;
750
+ const curx = x + width - element.bubble.margin, cury = y + element.bubble.margin;
751
+ if (version.version) {
752
+ const rawVersion = findVersion(util_1.ChunithmUtil.getNumberVersion(version.version), targetRegion);
753
+ if (rawVersion) {
754
+ const versionImage = theme.getFile(element.sprites.versions[version.region][rawVersion]);
755
+ try {
756
+ (0, sharp_1.default)(versionImage);
757
+ if (versionImage) {
758
+ const versionImg = new canvas_1.Image();
759
+ versionImg.src = versionImage;
760
+ ctx.drawImage(versionImg, curx - versionImageWidth, cury, versionImageWidth, versionImageHeight);
761
+ }
762
+ }
763
+ catch { }
764
+ }
765
+ }
766
+ /** End Version Draw */
767
+ /** Begin Note Count Draw */
768
+ const noteCountTexts = Object.entries(chart.meta.notes).map(([k, v]) => `${util_2.Util.capitalize(k)}: ${v}`);
769
+ const noteCountTextSize = (height - element.bubble.margin * 4) /
770
+ noteCountTexts.length;
771
+ let noteCountLength = 0;
772
+ noteCountTexts.forEach((v, i) => {
773
+ util_2.Util.drawText(ctx, v, x +
774
+ element.bubble.margin * (3 / 2) +
775
+ height * 2, y +
776
+ element.bubble.margin +
777
+ noteCountTextSize +
778
+ (noteCountTextSize +
779
+ (element.bubble.margin * 2) /
780
+ (noteCountTexts.length - 1)) *
781
+ i, noteCountTextSize, height * 0.806 * 0.04, Infinity, "left", "white", new color_1.default(curColor).darken(0.3).hexa());
782
+ const length = util_2.Util.measureText(ctx, v, noteCountTextSize, Infinity).width;
783
+ if (length > noteCountLength)
784
+ noteCountLength = length;
785
+ });
786
+ /** End Note Count Draw */
787
+ /** Begin Internal Level Trend Draw */
788
+ if (!isShort) {
789
+ const CURRENT_VER = (() => {
790
+ switch (targetRegion) {
791
+ case "INT":
792
+ return INT_LATEST;
793
+ case "CHN":
794
+ return CHN_LATEST;
795
+ case "JPN":
796
+ default:
797
+ return JPN_LATEST;
798
+ }
799
+ })();
800
+ const maxWidth = width -
801
+ height * 2 -
802
+ element.bubble.margin * 4 -
803
+ noteCountLength -
804
+ versionImageWidth;
805
+ const maxFitTrendCount = Math.trunc(maxWidth / versionImageWidth);
806
+ const trendEvents = chart.events.filter((v) => v.type == "existence" &&
807
+ v.version.region == targetRegion);
808
+ let actualEvents = lodash_1.default.uniqWith(trendEvents, (a, b) => {
809
+ return lodash_1.default.isEqual(a.data.level, b.data.level);
810
+ });
811
+ if (actualEvents.length == maxFitTrendCount) {
812
+ }
813
+ else if (actualEvents.length > maxFitTrendCount) {
814
+ while (actualEvents.length > maxFitTrendCount)
815
+ actualEvents.shift();
816
+ actualEvents.shift();
817
+ actualEvents.shift();
818
+ actualEvents.unshift(trendEvents[0]);
819
+ actualEvents.push(trendEvents[trendEvents.length - 1]);
820
+ }
821
+ else if (trendEvents.length > maxFitTrendCount) {
822
+ actualEvents = lodash_1.default.filter(actualEvents, (v) => !(lodash_1.default.isEqual(v.version.gameVersion, trendEvents[0].version
823
+ .gameVersion) ||
824
+ lodash_1.default.isEqual(v.version.gameVersion, trendEvents[trendEvents.length - 1].version.gameVersion)));
825
+ for (let i = trendEvents.length - 2; i > 0 &&
826
+ actualEvents.length < maxFitTrendCount - 2; --i) {
827
+ const event = trendEvents[i];
828
+ if (event)
829
+ actualEvents.push(event);
830
+ actualEvents = lodash_1.default.uniqWith(actualEvents, (a, b) => {
831
+ return (lodash_1.default.isEqual(a.version.gameVersion.major, b.version.gameVersion.major) &&
832
+ lodash_1.default.isEqual(a.version.gameVersion.minor, b.version.gameVersion.minor));
833
+ });
834
+ }
835
+ actualEvents.unshift(trendEvents[0]);
836
+ actualEvents.push(trendEvents[trendEvents.length - 1]);
837
+ actualEvents = lodash_1.default.uniqWith(actualEvents, (a, b) => {
838
+ return (lodash_1.default.isEqual(a.version.gameVersion.major, b.version.gameVersion.major) &&
839
+ lodash_1.default.isEqual(a.version.gameVersion.minor, b.version.gameVersion.minor));
840
+ });
841
+ actualEvents = lodash_1.default.sortBy(actualEvents, (v) => util_1.ChunithmUtil.getNumberVersion(v.version));
842
+ if (trendEvents.length > 1) {
843
+ if (actualEvents.length >= maxFitTrendCount)
844
+ actualEvents.pop();
845
+ actualEvents.push(trendEvents[trendEvents.length - 1]);
846
+ }
847
+ const removalEvent = chart.events.find((v) => v.type == "removal" &&
848
+ v.version.region == targetRegion);
849
+ if (removalEvent) {
850
+ actualEvents.pop();
851
+ actualEvents.push(removalEvent);
852
+ }
853
+ }
854
+ else {
855
+ actualEvents = [...trendEvents];
856
+ }
857
+ if (util_1.ChunithmUtil.getNumberVersion(actualEvents[actualEvents.length - 1]
858
+ .version) < CURRENT_VER) {
859
+ while (actualEvents.length >= maxFitTrendCount)
860
+ actualEvents.pop();
861
+ actualEvents.push({
862
+ type: "removal",
863
+ version: util_1.ChunithmUtil.Version.toEventVersion(util_1.ChunithmUtil.Version.getNextVersion(trendEvents[trendEvents.length - 1].version)),
864
+ });
865
+ }
866
+ actualEvents = lodash_1.default.uniqWith(actualEvents, (a, b) => {
867
+ return (lodash_1.default.isEqual(a.version.gameVersion.major, b.version.gameVersion.major) &&
868
+ lodash_1.default.isEqual(a.version.gameVersion.minor, b.version.gameVersion.minor) &&
869
+ lodash_1.default.isEqual(a.type, b.type));
870
+ });
871
+ let positionAdjustment = 0;
872
+ let addGap = (maxWidth -
873
+ actualEvents.length * versionImageWidth) /
874
+ (actualEvents.length - 1);
875
+ if (addGap > maxWidth / 5) {
876
+ addGap = maxWidth / 5;
877
+ positionAdjustment =
878
+ (maxWidth -
879
+ (addGap * (actualEvents.length - 1) +
880
+ versionImageWidth *
881
+ actualEvents.length)) /
882
+ 2;
883
+ }
884
+ for (let i = 0, curx = x +
885
+ positionAdjustment +
886
+ height * 2 +
887
+ element.bubble.margin * (5 / 2) +
888
+ noteCountLength, cury = y +
889
+ element.bubble.margin +
890
+ versionImageHeight * (1 / 2); i < actualEvents.length; ++i) {
891
+ const event = actualEvents[i];
892
+ const rawVersion = findVersion(util_1.ChunithmUtil.getNumberVersion(event.version), targetRegion);
893
+ if (rawVersion) {
894
+ const versionImage = theme.getFile(element.sprites.versions[targetRegion][rawVersion]);
895
+ try {
896
+ (0, sharp_1.default)(versionImage);
897
+ if (versionImage) {
898
+ const versionImg = new canvas_1.Image();
899
+ versionImg.src = versionImage;
900
+ ctx.drawImage(versionImg, curx, cury, versionImageWidth, versionImageHeight);
901
+ if (event.type == "existence") {
902
+ let symbol = "";
903
+ if (i != 0) {
904
+ const lastEvent = actualEvents[i - 1];
905
+ if (lastEvent.type ==
906
+ "existence") {
907
+ if (lastEvent.data
908
+ .level <
909
+ event.data.level)
910
+ symbol = "↑";
911
+ else if (lastEvent.data
912
+ .level >
913
+ event.data.level)
914
+ symbol = "↓";
915
+ else if (lastEvent.data
916
+ .level ==
917
+ event.data.level)
918
+ symbol = "→";
919
+ }
920
+ }
921
+ util_2.Util.drawText(ctx, `${symbol}${util_2.Util.truncate(event.data.level, 1)}`, curx +
922
+ versionImageWidth / 2, cury +
923
+ versionImageHeight +
924
+ noteCountTextSize, noteCountTextSize, height * 0.806 * 0.04, Infinity, "center", "white", new color_1.default(curColor)
925
+ .darken(0.3)
926
+ .hexa());
927
+ }
928
+ else if (event.type == "removal") {
929
+ util_2.Util.drawText(ctx, `❌`, curx +
930
+ versionImageWidth / 2, cury +
931
+ versionImageHeight +
932
+ noteCountTextSize, noteCountTextSize, height * 0.806 * 0.04, Infinity, "center", "white", new color_1.default(curColor)
933
+ .darken(0.3)
934
+ .hexa());
935
+ }
936
+ curx += versionImageWidth + addGap;
937
+ }
938
+ }
939
+ catch { }
940
+ }
941
+ }
942
+ }
943
+ }
944
+ /** End Internal Level Trend Draw */
945
+ ctx.restore();
946
+ }
947
+ /** End Main Content Draw */
948
+ ctx.fillStyle = new color_1.default(curColor).lighten(0.4).hexa();
949
+ ctx.beginPath();
950
+ ctx.roundRect(x, y + height * 0.742, height * 2, height * (1 - 0.742), [0, (height * 0.806) / 7, 0, (height * 0.806) / 7]);
951
+ ctx.fill();
952
+ /** Begin Difficulty & DX Rating Draw */
953
+ {
954
+ ctx.save();
955
+ ctx.clip();
956
+ util_2.Util.drawText(ctx, chart.designer || "-", x + element.bubble.margin, y + height * (0.806 + (1 - 0.806) / 2), height * 0.806 * 0.128, height * 0.806 * 0.04, Infinity, "left", "white", new color_1.default(curColor).darken(0.3).hexa());
957
+ ctx.restore();
958
+ // Util.drawText(
959
+ // ctx,
960
+ // `${score ? `${score.dxScore}/` : "MAX DX SCR: "}${chart.meta.maxDXScore}`,
961
+ // x + height * 2 - element.bubble.margin,
962
+ // y + height - element.bubble.margin * 3.1,
963
+ // height * 0.806 * 0.128,
964
+ // height * 0.806 * 0.04,
965
+ // Infinity,
966
+ // "right",
967
+ // "white",
968
+ // new Color(curColor).darken(0.3).hexa()
969
+ // );
970
+ }
971
+ /** End Difficulty & DX Rating Draw */
972
+ ctx.restore();
973
+ /** End Card Draw */
974
+ }
975
+ })(ChartGrid = Chart.ChartGrid || (Chart.ChartGrid = {}));
976
+ let DetailInfo;
977
+ (function (DetailInfo) {
978
+ DetailInfo.schema = painter_1.ThemeManager.Element.extend({
979
+ type: v4_1.z.literal("detail-info"),
980
+ width: v4_1.z.number().min(1),
981
+ height: v4_1.z.number().min(1),
982
+ margin: v4_1.z.number().min(0),
983
+ color: v4_1.z.object({
984
+ card: util_2.Util.z.color(),
985
+ }),
986
+ });
987
+ async function draw(ctx, theme, element, chartId) {
988
+ const jacketMargin = element.margin;
989
+ const textMargin = element.margin;
990
+ const chart = database_1.Database.getLocalChart(chartId, type_1.EDifficulty.BASIC);
991
+ const jacket = await database_1.Database.fetchJacket(chartId);
992
+ /* Begin Background Draw */
993
+ ctx.beginPath();
994
+ ctx.roundRect(element.x, element.y, element.width, element.height, Math.min(theme.content.width, theme.content.height) *
995
+ (3 / 128));
996
+ ctx.fillStyle = element.color.card;
997
+ ctx.strokeStyle = new color_1.default(element.color.card)
998
+ .darken(0.6)
999
+ .hex();
1000
+ ctx.lineWidth =
1001
+ Math.min(theme.content.width, theme.content.height) *
1002
+ (3 / 512);
1003
+ ctx.stroke();
1004
+ ctx.fill();
1005
+ /* End Background Draw */
1006
+ /* Begin jacket draw */
1007
+ if (jacket) {
1008
+ const jacketImage = new canvas_1.Image();
1009
+ const roundRadius = Math.min(theme.content.width, theme.content.height) *
1010
+ (3 / 128);
1011
+ jacketImage.src = jacket;
1012
+ ctx.beginPath();
1013
+ ctx.roundRect(element.x + jacketMargin, element.y + jacketMargin, element.width - jacketMargin * 2, element.width - jacketMargin * 2, [roundRadius, roundRadius, 0, 0]);
1014
+ ctx.save();
1015
+ ctx.clip();
1016
+ ctx.drawImage(jacketImage, element.x + jacketMargin, element.y + jacketMargin, element.width - jacketMargin * 2, element.width - jacketMargin * 2);
1017
+ ctx.restore();
1018
+ }
1019
+ /* End jacket draw */
1020
+ /* Begin Detail Draw */
1021
+ if (chart) {
1022
+ const textSizeTitle = element.width * (1 / 16);
1023
+ const textSizeSecondary = element.width * (1 / 24);
1024
+ const { actualBoundingBoxAscent: ascent, actualBoundingBoxDescent: decent, } = util_2.Util.measureText(ctx, chart.name, textSizeTitle, Infinity);
1025
+ const titleActualHeight = Math.abs(ascent - decent);
1026
+ const textLineWidth = element.width * (7 / 512);
1027
+ const textColor = new color_1.default(element.color.card)
1028
+ .darken(0.5)
1029
+ .hex();
1030
+ const textTitleMaxWidth = element.width - textMargin * 2;
1031
+ const titleMetrics = util_2.Util.measureText(ctx, chart.name, textSizeTitle, textTitleMaxWidth);
1032
+ util_2.Util.drawText(ctx, chart.name, element.x + textMargin, element.y +
1033
+ jacketMargin +
1034
+ textMargin * (1 / 2) +
1035
+ (element.width - jacketMargin * 2) +
1036
+ textSizeTitle, textSizeTitle, textLineWidth, textTitleMaxWidth, "left", "white", textColor);
1037
+ util_2.Util.drawText(ctx, chart.artist, element.x + textMargin, element.y +
1038
+ jacketMargin +
1039
+ textMargin * (1 / 2) +
1040
+ (element.width - jacketMargin * 2) +
1041
+ textSizeTitle * 2, textSizeSecondary, textLineWidth, element.width - textMargin * 2, "left", "white", textColor);
1042
+ function getBpmRange(bpms) {
1043
+ const uniqueBpms = lodash_1.default.uniq(bpms);
1044
+ if (uniqueBpms.length <= 0)
1045
+ return "0";
1046
+ else if (uniqueBpms.length == 1)
1047
+ return `${uniqueBpms[0]}`;
1048
+ else {
1049
+ const minBpm = Math.min(...uniqueBpms);
1050
+ const maxBpm = Math.max(...uniqueBpms);
1051
+ return `${minBpm}-${maxBpm}`;
1052
+ }
1053
+ }
1054
+ util_2.Util.drawText(ctx, `#${chart.id} BPM: ${getBpmRange(chart.bpms)}`, element.x + textMargin, element.y +
1055
+ jacketMargin +
1056
+ textMargin * (1 / 2) +
1057
+ (element.width - jacketMargin * 2) +
1058
+ textSizeTitle * 3, textSizeSecondary, textLineWidth, element.width - textMargin * 2, "left", "white", textColor);
1059
+ const EVENT_JPN = chart.events
1060
+ .filter((v) => v.version.region == "JPN" &&
1061
+ util_1.ChunithmUtil.getNumberVersion(v.version) >=
1062
+ JPN_LATEST)
1063
+ .map((v) => v.type);
1064
+ const EVENT_INT = chart.events
1065
+ .filter((v) => v.version.region == "INT" &&
1066
+ util_1.ChunithmUtil.getNumberVersion(v.version) >=
1067
+ INT_LATEST)
1068
+ .map((v) => v.type);
1069
+ const EVENT_CHN = chart.events
1070
+ .filter((v) => v.version.region == "CHN" &&
1071
+ util_1.ChunithmUtil.getNumberVersion(v.version) >=
1072
+ CHN_LATEST)
1073
+ .map((v) => v.type);
1074
+ const EXIST_JPN = EVENT_JPN.includes("existence") &&
1075
+ !EVENT_JPN.includes("removal")
1076
+ ? "🇯🇵"
1077
+ : "";
1078
+ const EXIST_INT = EVENT_INT.includes("existence") &&
1079
+ !EVENT_INT.includes("removal")
1080
+ ? "🌏"
1081
+ : "";
1082
+ const EXIST_CHN = EVENT_CHN.includes("existence") &&
1083
+ !EVENT_CHN.includes("removal")
1084
+ ? "🇨🇳"
1085
+ : "";
1086
+ const title = [];
1087
+ if (EXIST_JPN)
1088
+ title.push(EXIST_JPN);
1089
+ if (EXIST_INT)
1090
+ title.push(EXIST_INT);
1091
+ if (EXIST_CHN)
1092
+ title.push(EXIST_CHN);
1093
+ await util_2.Util.drawEmojiOrGlyph(ctx, title.join(" "), element.x + element.width - textMargin, element.y +
1094
+ jacketMargin +
1095
+ textMargin * (1 / 2) +
1096
+ (element.width - jacketMargin * 2) +
1097
+ textSizeTitle * 3, textSizeSecondary * (9 / 8), element.width - textMargin * 2, "right", "white", textColor);
1098
+ }
1099
+ /* End Detail Draw */
1100
+ }
1101
+ DetailInfo.draw = draw;
1102
+ })(DetailInfo = Chart.DetailInfo || (Chart.DetailInfo = {}));
1103
+ })(Chart = ChunithmPainterModule.Chart || (ChunithmPainterModule.Chart = {}));
1104
+ })(ChunithmPainterModule || (exports.ChunithmPainterModule = ChunithmPainterModule = {}));
1105
+ //# sourceMappingURL=index.js.map