@lycoristech/azurdata 0.0.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.
Files changed (274) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +123 -0
  3. package/data/.gitkeep +0 -0
  4. package/data/id-map.json +3530 -0
  5. package/data/ship-list.json +4478 -0
  6. package/data/ships.json +143282 -0
  7. package/data/version.json +5 -0
  8. package/dist/cjs/client/AzurData.js +69 -0
  9. package/dist/cjs/client/fetcher.js +121 -0
  10. package/dist/cjs/client/index.js +7 -0
  11. package/dist/cjs/client/ships.js +80 -0
  12. package/dist/cjs/config.js +14 -0
  13. package/dist/cjs/index.js +6 -0
  14. package/dist/cjs/ingest/files.js +134 -0
  15. package/dist/cjs/ingest/index.js +18 -0
  16. package/dist/cjs/ingest/upstream.js +12 -0
  17. package/dist/cjs/normalize/construction.js +186 -0
  18. package/dist/cjs/normalize/identity.js +131 -0
  19. package/dist/cjs/normalize/index.js +25 -0
  20. package/dist/cjs/normalize/misc.js +31 -0
  21. package/dist/cjs/normalize/retrofit.js +21 -0
  22. package/dist/cjs/normalize/ship.js +406 -0
  23. package/dist/cjs/normalize/skills.js +194 -0
  24. package/dist/cjs/normalize/skins.js +141 -0
  25. package/dist/cjs/normalize/slots.js +35 -0
  26. package/dist/cjs/normalize/stats.js +182 -0
  27. package/dist/cjs/output/index.js +20 -0
  28. package/dist/cjs/output/writeIdMap.js +52 -0
  29. package/dist/cjs/output/writeShipList.js +31 -0
  30. package/dist/cjs/output/writeShips.js +33 -0
  31. package/dist/cjs/output/writeVersion.js +23 -0
  32. package/dist/cjs/package.json +1 -0
  33. package/dist/cjs/schema/output/index.js +17 -0
  34. package/dist/cjs/schema/output/ship.js +169 -0
  35. package/dist/cjs/schema/raw/attributeInfoByType.js +11 -0
  36. package/dist/cjs/schema/raw/equipDataByType.js +12 -0
  37. package/dist/cjs/schema/raw/fleetTechGroup.js +10 -0
  38. package/dist/cjs/schema/raw/fleetTechShipClass.js +15 -0
  39. package/dist/cjs/schema/raw/fleetTechShipTemplate.js +20 -0
  40. package/dist/cjs/schema/raw/index.js +38 -0
  41. package/dist/cjs/schema/raw/shipDataBlueprint.js +11 -0
  42. package/dist/cjs/schema/raw/shipDataBreakout.js +17 -0
  43. package/dist/cjs/schema/raw/shipDataByStar.js +10 -0
  44. package/dist/cjs/schema/raw/shipDataByType.js +13 -0
  45. package/dist/cjs/schema/raw/shipDataCreateExchange.js +10 -0
  46. package/dist/cjs/schema/raw/shipDataGroup.js +22 -0
  47. package/dist/cjs/schema/raw/shipDataStatistics.js +24 -0
  48. package/dist/cjs/schema/raw/shipDataStrengthen.js +12 -0
  49. package/dist/cjs/schema/raw/shipDataTemplate.js +26 -0
  50. package/dist/cjs/schema/raw/shipDataTrans.js +13 -0
  51. package/dist/cjs/schema/raw/shipSkinTemplate.js +23 -0
  52. package/dist/cjs/schema/raw/shipSkinWords.js +11 -0
  53. package/dist/cjs/schema/raw/shopTemplate.js +14 -0
  54. package/dist/cjs/schema/raw/skillDataDisplay.js +11 -0
  55. package/dist/cjs/schema/raw/skillDataTemplate.js +17 -0
  56. package/dist/cjs/schema/raw/transformDataTemplate.js +18 -0
  57. package/dist/cjs/schema/raw/voiceActorCn.js +11 -0
  58. package/dist/cjs/translate/enums.js +131 -0
  59. package/dist/cjs/translate/index.js +19 -0
  60. package/dist/cjs/translate/lookups.js +63 -0
  61. package/dist/cjs/translate/strings.js +98 -0
  62. package/dist/client/AzurData.d.ts +25 -0
  63. package/dist/client/AzurData.d.ts.map +1 -0
  64. package/dist/client/AzurData.js +63 -0
  65. package/dist/client/AzurData.js.map +1 -0
  66. package/dist/client/fetcher.d.ts +25 -0
  67. package/dist/client/fetcher.d.ts.map +1 -0
  68. package/dist/client/fetcher.js +116 -0
  69. package/dist/client/fetcher.js.map +1 -0
  70. package/dist/client/index.d.ts +4 -0
  71. package/dist/client/index.d.ts.map +1 -0
  72. package/dist/client/index.js +3 -0
  73. package/dist/client/index.js.map +1 -0
  74. package/dist/client/ships.d.ts +20 -0
  75. package/dist/client/ships.d.ts.map +1 -0
  76. package/dist/client/ships.js +74 -0
  77. package/dist/client/ships.js.map +1 -0
  78. package/dist/config.d.ts +5 -0
  79. package/dist/config.d.ts.map +1 -0
  80. package/dist/config.js +12 -0
  81. package/dist/config.js.map +1 -0
  82. package/dist/index.d.ts +3 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +2 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/ingest/files.d.ts +25 -0
  87. package/dist/ingest/files.d.ts.map +1 -0
  88. package/dist/ingest/files.js +108 -0
  89. package/dist/ingest/files.js.map +1 -0
  90. package/dist/ingest/index.d.ts +3 -0
  91. package/dist/ingest/index.d.ts.map +1 -0
  92. package/dist/ingest/index.js +3 -0
  93. package/dist/ingest/index.js.map +1 -0
  94. package/dist/ingest/upstream.d.ts +4 -0
  95. package/dist/ingest/upstream.d.ts.map +1 -0
  96. package/dist/ingest/upstream.js +6 -0
  97. package/dist/ingest/upstream.js.map +1 -0
  98. package/dist/normalize/construction.d.ts +30 -0
  99. package/dist/normalize/construction.d.ts.map +1 -0
  100. package/dist/normalize/construction.js +184 -0
  101. package/dist/normalize/construction.js.map +1 -0
  102. package/dist/normalize/identity.d.ts +47 -0
  103. package/dist/normalize/identity.d.ts.map +1 -0
  104. package/dist/normalize/identity.js +129 -0
  105. package/dist/normalize/identity.js.map +1 -0
  106. package/dist/normalize/index.d.ts +10 -0
  107. package/dist/normalize/index.d.ts.map +1 -0
  108. package/dist/normalize/index.js +10 -0
  109. package/dist/normalize/index.js.map +1 -0
  110. package/dist/normalize/misc.d.ts +15 -0
  111. package/dist/normalize/misc.d.ts.map +1 -0
  112. package/dist/normalize/misc.js +29 -0
  113. package/dist/normalize/misc.js.map +1 -0
  114. package/dist/normalize/retrofit.d.ts +14 -0
  115. package/dist/normalize/retrofit.d.ts.map +1 -0
  116. package/dist/normalize/retrofit.js +19 -0
  117. package/dist/normalize/retrofit.js.map +1 -0
  118. package/dist/normalize/ship.d.ts +67 -0
  119. package/dist/normalize/ship.d.ts.map +1 -0
  120. package/dist/normalize/ship.js +369 -0
  121. package/dist/normalize/ship.js.map +1 -0
  122. package/dist/normalize/skills.d.ts +20 -0
  123. package/dist/normalize/skills.d.ts.map +1 -0
  124. package/dist/normalize/skills.js +192 -0
  125. package/dist/normalize/skills.js.map +1 -0
  126. package/dist/normalize/skins.d.ts +14 -0
  127. package/dist/normalize/skins.d.ts.map +1 -0
  128. package/dist/normalize/skins.js +139 -0
  129. package/dist/normalize/skins.js.map +1 -0
  130. package/dist/normalize/slots.d.ts +14 -0
  131. package/dist/normalize/slots.d.ts.map +1 -0
  132. package/dist/normalize/slots.js +33 -0
  133. package/dist/normalize/slots.js.map +1 -0
  134. package/dist/normalize/stats.d.ts +19 -0
  135. package/dist/normalize/stats.d.ts.map +1 -0
  136. package/dist/normalize/stats.js +180 -0
  137. package/dist/normalize/stats.js.map +1 -0
  138. package/dist/output/index.d.ts +5 -0
  139. package/dist/output/index.d.ts.map +1 -0
  140. package/dist/output/index.js +5 -0
  141. package/dist/output/index.js.map +1 -0
  142. package/dist/output/writeIdMap.d.ts +16 -0
  143. package/dist/output/writeIdMap.d.ts.map +1 -0
  144. package/dist/output/writeIdMap.js +47 -0
  145. package/dist/output/writeIdMap.js.map +1 -0
  146. package/dist/output/writeShipList.d.ts +9 -0
  147. package/dist/output/writeShipList.d.ts.map +1 -0
  148. package/dist/output/writeShipList.js +26 -0
  149. package/dist/output/writeShipList.js.map +1 -0
  150. package/dist/output/writeShips.d.ts +15 -0
  151. package/dist/output/writeShips.d.ts.map +1 -0
  152. package/dist/output/writeShips.js +28 -0
  153. package/dist/output/writeShips.js.map +1 -0
  154. package/dist/output/writeVersion.d.ts +11 -0
  155. package/dist/output/writeVersion.d.ts.map +1 -0
  156. package/dist/output/writeVersion.js +18 -0
  157. package/dist/output/writeVersion.js.map +1 -0
  158. package/dist/schema/output/index.d.ts +2 -0
  159. package/dist/schema/output/index.d.ts.map +1 -0
  160. package/dist/schema/output/index.js +2 -0
  161. package/dist/schema/output/index.js.map +1 -0
  162. package/dist/schema/output/ship.d.ts +977 -0
  163. package/dist/schema/output/ship.d.ts.map +1 -0
  164. package/dist/schema/output/ship.js +167 -0
  165. package/dist/schema/output/ship.js.map +1 -0
  166. package/dist/schema/raw/attributeInfoByType.d.ts +25 -0
  167. package/dist/schema/raw/attributeInfoByType.d.ts.map +1 -0
  168. package/dist/schema/raw/attributeInfoByType.js +9 -0
  169. package/dist/schema/raw/attributeInfoByType.js.map +1 -0
  170. package/dist/schema/raw/equipDataByType.d.ts +31 -0
  171. package/dist/schema/raw/equipDataByType.d.ts.map +1 -0
  172. package/dist/schema/raw/equipDataByType.js +10 -0
  173. package/dist/schema/raw/equipDataByType.js.map +1 -0
  174. package/dist/schema/raw/fleetTechGroup.d.ts +19 -0
  175. package/dist/schema/raw/fleetTechGroup.d.ts.map +1 -0
  176. package/dist/schema/raw/fleetTechGroup.js +8 -0
  177. package/dist/schema/raw/fleetTechGroup.js.map +1 -0
  178. package/dist/schema/raw/fleetTechShipClass.d.ts +49 -0
  179. package/dist/schema/raw/fleetTechShipClass.d.ts.map +1 -0
  180. package/dist/schema/raw/fleetTechShipClass.js +13 -0
  181. package/dist/schema/raw/fleetTechShipClass.js.map +1 -0
  182. package/dist/schema/raw/fleetTechShipTemplate.d.ts +79 -0
  183. package/dist/schema/raw/fleetTechShipTemplate.d.ts.map +1 -0
  184. package/dist/schema/raw/fleetTechShipTemplate.js +18 -0
  185. package/dist/schema/raw/fleetTechShipTemplate.js.map +1 -0
  186. package/dist/schema/raw/index.d.ts +23 -0
  187. package/dist/schema/raw/index.d.ts.map +1 -0
  188. package/dist/schema/raw/index.js +23 -0
  189. package/dist/schema/raw/index.js.map +1 -0
  190. package/dist/schema/raw/shipDataBlueprint.d.ts +25 -0
  191. package/dist/schema/raw/shipDataBlueprint.d.ts.map +1 -0
  192. package/dist/schema/raw/shipDataBlueprint.js +9 -0
  193. package/dist/schema/raw/shipDataBlueprint.js.map +1 -0
  194. package/dist/schema/raw/shipDataBreakout.d.ts +61 -0
  195. package/dist/schema/raw/shipDataBreakout.d.ts.map +1 -0
  196. package/dist/schema/raw/shipDataBreakout.js +15 -0
  197. package/dist/schema/raw/shipDataBreakout.js.map +1 -0
  198. package/dist/schema/raw/shipDataByStar.d.ts +19 -0
  199. package/dist/schema/raw/shipDataByStar.d.ts.map +1 -0
  200. package/dist/schema/raw/shipDataByStar.js +8 -0
  201. package/dist/schema/raw/shipDataByStar.js.map +1 -0
  202. package/dist/schema/raw/shipDataByType.d.ts +37 -0
  203. package/dist/schema/raw/shipDataByType.d.ts.map +1 -0
  204. package/dist/schema/raw/shipDataByType.js +11 -0
  205. package/dist/schema/raw/shipDataByType.js.map +1 -0
  206. package/dist/schema/raw/shipDataCreateExchange.d.ts +19 -0
  207. package/dist/schema/raw/shipDataCreateExchange.d.ts.map +1 -0
  208. package/dist/schema/raw/shipDataCreateExchange.js +8 -0
  209. package/dist/schema/raw/shipDataCreateExchange.js.map +1 -0
  210. package/dist/schema/raw/shipDataGroup.d.ts +79 -0
  211. package/dist/schema/raw/shipDataGroup.d.ts.map +1 -0
  212. package/dist/schema/raw/shipDataGroup.js +20 -0
  213. package/dist/schema/raw/shipDataGroup.js.map +1 -0
  214. package/dist/schema/raw/shipDataStatistics.d.ts +103 -0
  215. package/dist/schema/raw/shipDataStatistics.d.ts.map +1 -0
  216. package/dist/schema/raw/shipDataStatistics.js +22 -0
  217. package/dist/schema/raw/shipDataStatistics.js.map +1 -0
  218. package/dist/schema/raw/shipDataStrengthen.d.ts +31 -0
  219. package/dist/schema/raw/shipDataStrengthen.d.ts.map +1 -0
  220. package/dist/schema/raw/shipDataStrengthen.js +10 -0
  221. package/dist/schema/raw/shipDataStrengthen.js.map +1 -0
  222. package/dist/schema/raw/shipDataTemplate.d.ts +115 -0
  223. package/dist/schema/raw/shipDataTemplate.d.ts.map +1 -0
  224. package/dist/schema/raw/shipDataTemplate.js +24 -0
  225. package/dist/schema/raw/shipDataTemplate.js.map +1 -0
  226. package/dist/schema/raw/shipDataTrans.d.ts +37 -0
  227. package/dist/schema/raw/shipDataTrans.d.ts.map +1 -0
  228. package/dist/schema/raw/shipDataTrans.js +11 -0
  229. package/dist/schema/raw/shipDataTrans.js.map +1 -0
  230. package/dist/schema/raw/shipSkinTemplate.d.ts +97 -0
  231. package/dist/schema/raw/shipSkinTemplate.d.ts.map +1 -0
  232. package/dist/schema/raw/shipSkinTemplate.js +21 -0
  233. package/dist/schema/raw/shipSkinTemplate.js.map +1 -0
  234. package/dist/schema/raw/shipSkinWords.d.ts +25 -0
  235. package/dist/schema/raw/shipSkinWords.d.ts.map +1 -0
  236. package/dist/schema/raw/shipSkinWords.js +9 -0
  237. package/dist/schema/raw/shipSkinWords.js.map +1 -0
  238. package/dist/schema/raw/shopTemplate.d.ts +43 -0
  239. package/dist/schema/raw/shopTemplate.d.ts.map +1 -0
  240. package/dist/schema/raw/shopTemplate.js +12 -0
  241. package/dist/schema/raw/shopTemplate.js.map +1 -0
  242. package/dist/schema/raw/skillDataDisplay.d.ts +25 -0
  243. package/dist/schema/raw/skillDataDisplay.d.ts.map +1 -0
  244. package/dist/schema/raw/skillDataDisplay.js +9 -0
  245. package/dist/schema/raw/skillDataDisplay.js.map +1 -0
  246. package/dist/schema/raw/skillDataTemplate.d.ts +61 -0
  247. package/dist/schema/raw/skillDataTemplate.d.ts.map +1 -0
  248. package/dist/schema/raw/skillDataTemplate.js +15 -0
  249. package/dist/schema/raw/skillDataTemplate.js.map +1 -0
  250. package/dist/schema/raw/transformDataTemplate.d.ts +67 -0
  251. package/dist/schema/raw/transformDataTemplate.d.ts.map +1 -0
  252. package/dist/schema/raw/transformDataTemplate.js +16 -0
  253. package/dist/schema/raw/transformDataTemplate.js.map +1 -0
  254. package/dist/schema/raw/voiceActorCn.d.ts +25 -0
  255. package/dist/schema/raw/voiceActorCn.d.ts.map +1 -0
  256. package/dist/schema/raw/voiceActorCn.js +9 -0
  257. package/dist/schema/raw/voiceActorCn.js.map +1 -0
  258. package/dist/translate/enums.d.ts +34 -0
  259. package/dist/translate/enums.d.ts.map +1 -0
  260. package/dist/translate/enums.js +126 -0
  261. package/dist/translate/enums.js.map +1 -0
  262. package/dist/translate/index.d.ts +4 -0
  263. package/dist/translate/index.d.ts.map +1 -0
  264. package/dist/translate/index.js +4 -0
  265. package/dist/translate/index.js.map +1 -0
  266. package/dist/translate/lookups.d.ts +37 -0
  267. package/dist/translate/lookups.d.ts.map +1 -0
  268. package/dist/translate/lookups.js +61 -0
  269. package/dist/translate/lookups.js.map +1 -0
  270. package/dist/translate/strings.d.ts +40 -0
  271. package/dist/translate/strings.d.ts.map +1 -0
  272. package/dist/translate/strings.js +92 -0
  273. package/dist/translate/strings.js.map +1 -0
  274. package/package.json +37 -0
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeSkills = normalizeSkills;
4
+ const enums_js_1 = require("../translate/enums.js");
5
+ const strings_js_1 = require("../translate/strings.js");
6
+ // ---------------------------------------------------------------------------
7
+ // Internal helpers
8
+ // ---------------------------------------------------------------------------
9
+ /**
10
+ * Strip trailing Roman numeral suffix (Ⅰ–Ⅴ or ASCII I/II/III/IV/V) from a skill
11
+ * name, returning just the "root" portion for comparison purposes.
12
+ *
13
+ * Examples:
14
+ * "All Out Assault Ⅰ" → "All Out Assault"
15
+ * "All Out Assault Ⅱ" → "All Out Assault"
16
+ * "Smokescreen: Light Cruisers" → "Smokescreen: Light Cruisers"
17
+ * "Burn Order" → "Burn Order"
18
+ */
19
+ function rootSkillName(name) {
20
+ // Trim Unicode Roman numerals (Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ) and ASCII (I–X variants)
21
+ // at end of string, optionally preceded by a colon/period and more text.
22
+ return name
23
+ .replace(/\s+[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩiIvVxX]+(?:[:.][^\s]*)*\s*$/, "")
24
+ .trim();
25
+ }
26
+ /**
27
+ * Normalize a `skill_id` value (number | number[] | undefined) to a number[].
28
+ */
29
+ function normalizeSkillIdList(raw) {
30
+ if (raw === undefined)
31
+ return [];
32
+ if (Array.isArray(raw))
33
+ return raw;
34
+ return [raw];
35
+ }
36
+ /**
37
+ * Build the description string for a skill.
38
+ */
39
+ function buildDescription(skillTemplate, idStr) {
40
+ const row = skillTemplate[idStr];
41
+ if (row === undefined)
42
+ return "";
43
+ const rawDesc = row.desc;
44
+ if (rawDesc === undefined || rawDesc === "")
45
+ return "";
46
+ const substitutions = (0, strings_js_1.extractMaxLevelSubstitutions)(row.desc_add, row.max_level ?? 10);
47
+ return (0, strings_js_1.substitutePlaceholders)(rawDesc, substitutions);
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // Main
51
+ // ---------------------------------------------------------------------------
52
+ function normalizeSkills(inputs) {
53
+ const { rowIds, en, groupType } = inputs;
54
+ const { template, breakout, skillDataTemplate, skillDataDisplay, trans, transformDataTemplate, } = en;
55
+ // -------------------------------------------------------------------------
56
+ // 1. Resolve the LB3 row ID (the row whose key ends with "4", or last entry).
57
+ // -------------------------------------------------------------------------
58
+ const lb3RowId = rowIds.find((id) => id.endsWith("4")) ?? rowIds[rowIds.length - 1] ?? groupType;
59
+ // -------------------------------------------------------------------------
60
+ // 2. Get the base skill ID list from the LB3 row.
61
+ // -------------------------------------------------------------------------
62
+ const lb3Template = template[lb3RowId];
63
+ const baseSkillIds = lb3Template?.buff_list_display ?? [];
64
+ // -------------------------------------------------------------------------
65
+ // 3. Apply retrofit skill upgrades (if any).
66
+ //
67
+ // TODO: The retrofit skill-upgrade/replace logic is a best-effort
68
+ // approximation. AzurAPI's historical output was inconsistent here; some
69
+ // versions replaced the base skill, others appended. The implementation
70
+ // below attempts a root-name match and replaces when found, otherwise
71
+ // appends. If this causes issues, simplify to just using `baseSkillIds`
72
+ // directly.
73
+ // -------------------------------------------------------------------------
74
+ let finalSkillIds = [...baseSkillIds];
75
+ if (trans !== undefined && transformDataTemplate !== undefined) {
76
+ const transRow = trans[groupType];
77
+ if (transRow !== undefined) {
78
+ // Collect all retrofit skill IDs: from trans.skill_id + each transform node's skill_id
79
+ const retrofitSkillIds = new Set();
80
+ // From the top-level trans row
81
+ const topSkillIds = normalizeSkillIdList(transRow.skill_id);
82
+ for (const sid of topSkillIds) {
83
+ if (sid !== 0)
84
+ retrofitSkillIds.add(sid);
85
+ }
86
+ // From each transform_data_template node referenced in transform_list
87
+ const seenTransformIds = new Set();
88
+ for (const outerList of transRow.transform_list) {
89
+ for (const pair of outerList) {
90
+ const transformId = pair[1];
91
+ if (transformId === undefined || seenTransformIds.has(transformId))
92
+ continue;
93
+ seenTransformIds.add(transformId);
94
+ const tRow = transformDataTemplate[String(transformId)];
95
+ if (tRow === undefined)
96
+ continue;
97
+ const tSkillIds = normalizeSkillIdList(tRow.skill_id);
98
+ for (const sid of tSkillIds) {
99
+ if (sid !== 0)
100
+ retrofitSkillIds.add(sid);
101
+ }
102
+ }
103
+ }
104
+ // Merge retrofit skills: replace base skill if root names match, else append
105
+ for (const retrofitId of retrofitSkillIds) {
106
+ const retrofitRow = skillDataTemplate[String(retrofitId)];
107
+ if (retrofitRow === undefined)
108
+ continue;
109
+ const retrofitName = retrofitRow.name;
110
+ if (retrofitName === undefined)
111
+ continue;
112
+ const retrofitRoot = rootSkillName(retrofitName);
113
+ // Try to find a base skill with the same root name
114
+ let replaced = false;
115
+ for (let i = 0; i < finalSkillIds.length; i++) {
116
+ const baseId = finalSkillIds[i];
117
+ if (baseId === undefined)
118
+ continue;
119
+ const baseRow = skillDataTemplate[String(baseId)];
120
+ if (baseRow === undefined)
121
+ continue;
122
+ const baseName = baseRow.name;
123
+ if (baseName === undefined)
124
+ continue;
125
+ const baseRoot = rootSkillName(baseName);
126
+ if (baseRoot === retrofitRoot && baseRoot.length > 0) {
127
+ finalSkillIds[i] = retrofitId;
128
+ replaced = true;
129
+ break;
130
+ }
131
+ }
132
+ if (!replaced) {
133
+ // No matching base skill — append if not already present
134
+ if (!finalSkillIds.includes(retrofitId)) {
135
+ finalSkillIds.push(retrofitId);
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ // -------------------------------------------------------------------------
142
+ // 4. Build skill objects.
143
+ // -------------------------------------------------------------------------
144
+ const skills = [];
145
+ for (const skillId of finalSkillIds) {
146
+ const idStr = String(skillId);
147
+ const skillRow = skillDataTemplate[idStr];
148
+ const displayRow = skillDataDisplay[idStr];
149
+ // Resolve name: prefer skill_data_template, fallback to skill_data_display
150
+ let nameEn = skillRow?.name ?? displayRow?.name;
151
+ if (nameEn === undefined || nameEn.trim() === "") {
152
+ // No name at all — skip this skill
153
+ console.warn(`normalizeSkills: skill ID ${skillId} has no name in skill_data_template or skill_data_display — skipping (group_type ${groupType})`);
154
+ continue;
155
+ }
156
+ nameEn = nameEn.trim();
157
+ const type = skillRow?.type ?? 0;
158
+ const color = (0, enums_js_1.skillColor)(type);
159
+ const description = buildDescription(skillDataTemplate, idStr);
160
+ skills.push({
161
+ color,
162
+ names: { en: nameEn },
163
+ description,
164
+ });
165
+ }
166
+ // -------------------------------------------------------------------------
167
+ // 5. Build limit breaks.
168
+ //
169
+ // rowIds[0..2] correspond to LB1/LB2/LB3 source rows.
170
+ // The terminal row (index 3, ending in "4") has breakout_view: "None" → skip.
171
+ // -------------------------------------------------------------------------
172
+ // We want the first THREE non-terminal rows: rowIds[0], [1], [2]
173
+ const limitBreaks = [];
174
+ for (let i = 0; i < 3; i++) {
175
+ const rowId = rowIds[i];
176
+ if (rowId === undefined) {
177
+ // Fewer than 3 rows — some ships (e.g. META 4-star ships) may have fewer LB stages
178
+ continue;
179
+ }
180
+ const breakoutRow = breakout[rowId];
181
+ if (breakoutRow === undefined) {
182
+ // Row missing from breakout table — skip
183
+ continue;
184
+ }
185
+ const bonuses = (0, strings_js_1.splitLimitBreakBonuses)(breakoutRow.breakout_view);
186
+ limitBreaks.push(bonuses);
187
+ }
188
+ // If all three limit-break arrays are empty/absent, omit the field
189
+ const hasLimitBreaks = limitBreaks.length > 0 && limitBreaks.some((lb) => lb.length > 0);
190
+ return {
191
+ skills,
192
+ limitBreaks: hasLimitBreaks ? limitBreaks : undefined,
193
+ };
194
+ }
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeSkins = normalizeSkins;
4
+ const config_js_1 = require("../config.js");
5
+ // ---------------------------------------------------------------------------
6
+ // Internal helpers
7
+ // ---------------------------------------------------------------------------
8
+ const DEFAULT_BASE_URL = config_js_1.PAINTINGS_URL;
9
+ /**
10
+ * Returns true if l2d_animations is non-empty
11
+ * (Array with length > 0, or object with at least one key).
12
+ */
13
+ function hasLive2d(l2dAnimations) {
14
+ if (l2dAnimations === undefined || l2dAnimations === null)
15
+ return false;
16
+ if (Array.isArray(l2dAnimations))
17
+ return l2dAnimations.length > 0;
18
+ if (typeof l2dAnimations === "object") {
19
+ return Object.keys(l2dAnimations).length > 0;
20
+ }
21
+ return false;
22
+ }
23
+ /**
24
+ * Returns true if the shop entry's `time` value represents "always"
25
+ * (i.e. the string "always").
26
+ */
27
+ function isAlwaysAvailable(time) {
28
+ return time === "always";
29
+ }
30
+ /**
31
+ * Build the variant images map for a skin painting.
32
+ *
33
+ * Variant mapping:
34
+ * {name}.webp → "default" (base file — the EN version, may be censored)
35
+ * {name}_rw.webp → "censored_nobg" (EN character layer without background)
36
+ * {name}_n.webp → "uncensored" (JP/original version)
37
+ * {name}_n_rw.webp → "uncensored_nobg" (JP character without background)
38
+ * {name}_bj.webp → "background" (background layer only)
39
+ *
40
+ * "censored" is an alias for "default" since the base file IS the EN version.
41
+ */
42
+ function buildVariantImages(painting, baseUrl, available) {
43
+ const lower = painting.toLowerCase();
44
+ const has = (suffix) => {
45
+ const key = suffix === "" ? lower : `${lower}${suffix}`;
46
+ return available ? available.has(key) : true;
47
+ };
48
+ const url = (suffix) => `${baseUrl}/${painting}${suffix}.webp`;
49
+ const images = {};
50
+ if (has(""))
51
+ images.default = url("");
52
+ if (has(""))
53
+ images.censored = url(""); // alias for default
54
+ if (has("_rw"))
55
+ images.censored_nobg = url("_rw");
56
+ if (has("_n"))
57
+ images.uncensored = url("_n");
58
+ if (has("_n_rw"))
59
+ images.uncensored_nobg = url("_n_rw");
60
+ if (has("_bj"))
61
+ images.background = url("_bj");
62
+ return Object.keys(images).length > 0 ? images : undefined;
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Main
66
+ // ---------------------------------------------------------------------------
67
+ function normalizeSkins(inputs) {
68
+ const { groupType, skinTemplate, shopTemplate, thumbnailBaseUrl, availablePaintings } = inputs;
69
+ const base = thumbnailBaseUrl ?? DEFAULT_BASE_URL;
70
+ const groupTypeNum = Number(groupType);
71
+ // Filter skin rows belonging to this ship group, then sort by skin ID ascending
72
+ const skinEntries = Object.entries(skinTemplate)
73
+ .filter(([, row]) => row !== undefined && row.ship_group === groupTypeNum)
74
+ .sort(([a], [b]) => {
75
+ const diff = Number(a) - Number(b);
76
+ return diff;
77
+ });
78
+ if (skinEntries.length === 0) {
79
+ return { skins: [] };
80
+ }
81
+ const skins = [];
82
+ for (const [skinId, row] of skinEntries) {
83
+ if (row === undefined)
84
+ continue;
85
+ // name: row.name if non-empty, else row.desc if non-empty, else "(unnamed)"
86
+ const name = row.name.trim().length > 0
87
+ ? row.name.trim()
88
+ : (row.desc?.trim().length ?? 0) > 0
89
+ ? (row.desc?.trim() ?? "(unnamed)")
90
+ : "(unnamed)";
91
+ // image URL
92
+ const image = `${base}/${row.painting}.webp`;
93
+ // shop info
94
+ const shopId = row.shop_id;
95
+ let cost;
96
+ let isAlways = false;
97
+ let hasValidShop = false;
98
+ if (shopId !== undefined && shopId !== 0) {
99
+ const shopEntry = shopTemplate[String(shopId)];
100
+ if (shopEntry !== undefined) {
101
+ const isShopGenre = shopEntry.genre === "skin_shop" || shopEntry.effect_args !== undefined;
102
+ const resourceNum = shopEntry.resource_num;
103
+ if (isShopGenre && resourceNum !== undefined && resourceNum > 0) {
104
+ cost = resourceNum;
105
+ }
106
+ isAlways = isAlwaysAvailable(shopEntry.time);
107
+ hasValidShop = true;
108
+ }
109
+ }
110
+ // obtainedFrom heuristic
111
+ let obtainedFrom;
112
+ if (row.skin_type === -1) {
113
+ obtainedFrom = "Default";
114
+ }
115
+ else if (hasValidShop && isAlways) {
116
+ obtainedFrom = "Skin Shop";
117
+ }
118
+ else if (shopId !== undefined && shopId !== 0) {
119
+ obtainedFrom = "Limited (Event)";
120
+ }
121
+ else if (row.skin_type === 7 ||
122
+ name.toLowerCase().includes("pledge")) {
123
+ obtainedFrom = "Wedding";
124
+ }
125
+ else {
126
+ obtainedFrom = "Special";
127
+ }
128
+ // live2dModel
129
+ const live2dModel = hasLive2d(row.l2d_animations) ? true : undefined;
130
+ const info = {
131
+ ...(cost !== undefined ? { cost } : {}),
132
+ obtainedFrom,
133
+ ...(live2dModel !== undefined ? { live2dModel } : {}),
134
+ enClient: "Yes",
135
+ };
136
+ // Build variant images object
137
+ const images = buildVariantImages(row.painting, base, availablePaintings);
138
+ skins.push({ name, image, images, info });
139
+ }
140
+ return { skins };
141
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeSlots = normalizeSlots;
4
+ // ---------------------------------------------------------------------------
5
+ // Main
6
+ // ---------------------------------------------------------------------------
7
+ function normalizeSlots(inputs) {
8
+ const { lb0RowId, lb3RowId, template, statistics, lookups } = inputs;
9
+ const tmplLb0 = template[lb0RowId];
10
+ const tmplLb3 = template[lb3RowId];
11
+ // If either template row is missing, return empty — orchestrator decides what to do.
12
+ if (tmplLb0 === undefined || tmplLb3 === undefined) {
13
+ return [];
14
+ }
15
+ const statsLb0 = statistics[lb0RowId];
16
+ const statsLb3 = statistics[lb3RowId];
17
+ const proficiencyLb0 = statsLb0?.equipment_proficiency ?? [];
18
+ const proficiencyLb3 = statsLb3?.equipment_proficiency ?? [];
19
+ // Equipment slot arrays: equip_1, equip_2, equip_3 (ignore 4th augment slot)
20
+ const equipSlots = [
21
+ tmplLb0.equip_1,
22
+ tmplLb0.equip_2,
23
+ tmplLb0.equip_3,
24
+ ];
25
+ const slots = [];
26
+ for (let i = 0; i < 3; i++) {
27
+ const equipArr = equipSlots[i];
28
+ const equipTypeId = equipArr?.[0];
29
+ const type = equipTypeId !== undefined ? lookups.equipTypeName(equipTypeId) : "Unknown";
30
+ const minEfficiency = proficiencyLb0[i] ?? 0;
31
+ const maxEfficiency = proficiencyLb3[i] ?? 0;
32
+ slots.push({ type, minEfficiency, maxEfficiency });
33
+ }
34
+ return slots;
35
+ }
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeStats = normalizeStats;
4
+ const enums_js_1 = require("../translate/enums.js");
5
+ // ---------------------------------------------------------------------------
6
+ // Internal helpers
7
+ // ---------------------------------------------------------------------------
8
+ /**
9
+ * Build a strengthen bonus array (12 elements) from the `durability` field.
10
+ *
11
+ * Strengthen durability mapping (0-indexed):
12
+ * [0] → firepower (attrs index 1)
13
+ * [1] → torpedo (attrs index 2)
14
+ * [2] → (unused / always 0)
15
+ * [3] → aviation (attrs index 4)
16
+ * [4] → reload (attrs index 5)
17
+ */
18
+ function buildStrengthenBonus(durability) {
19
+ const bonus = new Array(12).fill(0);
20
+ bonus[1] = durability[0] ?? 0; // firepower
21
+ bonus[2] = durability[1] ?? 0; // torpedo
22
+ bonus[4] = durability[3] ?? 0; // aviation
23
+ bonus[5] = durability[4] ?? 0; // reload
24
+ return bonus;
25
+ }
26
+ /**
27
+ * Compute a single stat value at the given level.
28
+ * Formula: base + floor(growth * (level - 1) / 1000) + floor(growthExtra * max(level - 100, 0) / 1000) + strengthenBonus
29
+ */
30
+ function computeStat(base, growth, growthExtra, level, strengthenBonus) {
31
+ const fromGrowth = Math.floor((growth * (level - 1)) / 1000);
32
+ const fromExtra = level > 100 ? Math.floor((growthExtra * (level - 100)) / 1000) : 0;
33
+ return base + fromGrowth + fromExtra + strengthenBonus;
34
+ }
35
+ /**
36
+ * Build a StatBlock for a given level from the statistics arrays.
37
+ */
38
+ function buildStatBlock(attrs, attrsGrowth, attrsGrowthExtra, level, strengthenBonus) {
39
+ const partial = {};
40
+ for (let i = 0; i < 12; i++) {
41
+ const field = enums_js_1.STAT_INDEX_TO_FIELD[i];
42
+ if (field === undefined)
43
+ continue;
44
+ const stat = computeStat(attrs[i] ?? 0, attrsGrowth[i] ?? 0, attrsGrowthExtra[i] ?? 0, level, strengthenBonus[i] ?? 0);
45
+ partial[field] = stat;
46
+ }
47
+ // Ensure all required StatBlock fields are present (default 0)
48
+ const block = {
49
+ health: partial.health ?? 0,
50
+ firepower: partial.firepower ?? 0,
51
+ torpedo: partial.torpedo ?? 0,
52
+ evasion: partial.evasion ?? 0,
53
+ antiwar: partial.antiwar ?? 0,
54
+ aviation: partial.aviation ?? 0,
55
+ reload: partial.reload ?? 0,
56
+ speed: partial.speed ?? 0,
57
+ luck: partial.luck ?? 0,
58
+ accuracy: partial.accuracy ?? 0,
59
+ };
60
+ return block;
61
+ }
62
+ /**
63
+ * Retrofit raw stat name → StatBlock field mapping.
64
+ */
65
+ const RETROFIT_RAW_NAME_MAP = {
66
+ durability: "health",
67
+ cannon: "firepower",
68
+ torpedo: "torpedo",
69
+ antiaircraft: "antiwar",
70
+ air: "aviation",
71
+ reload: "reload",
72
+ hit: "accuracy",
73
+ dodge: "evasion",
74
+ speed: "speed",
75
+ };
76
+ /**
77
+ * Compute retrofit stat deltas by walking the transform_list.
78
+ * Returns a partial StatBlock delta (only fields with non-zero deltas).
79
+ */
80
+ function computeRetrofitDeltas(groupType, trans, transformDataTemplate) {
81
+ const transRow = trans[groupType];
82
+ if (transRow === undefined)
83
+ return {};
84
+ const deltas = {};
85
+ const seenTransformIds = new Set();
86
+ for (const outerList of transRow.transform_list) {
87
+ for (const pair of outerList) {
88
+ const transformId = pair[1];
89
+ if (transformId === undefined || seenTransformIds.has(transformId))
90
+ continue;
91
+ seenTransformIds.add(transformId);
92
+ const tRow = transformDataTemplate[String(transformId)];
93
+ if (tRow === undefined)
94
+ continue;
95
+ for (const effectEntry of tRow.effect) {
96
+ for (const [rawStatName, delta] of Object.entries(effectEntry)) {
97
+ const field = RETROFIT_RAW_NAME_MAP[rawStatName];
98
+ if (field === undefined)
99
+ continue;
100
+ const current = deltas[field] ?? 0;
101
+ deltas[field] = current + delta;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ return deltas;
107
+ }
108
+ /**
109
+ * Apply retrofit deltas to a StatBlock, returning a new StatBlock.
110
+ */
111
+ function applyRetrofitDeltas(base, deltas) {
112
+ return {
113
+ health: base.health + (deltas.health ?? 0),
114
+ firepower: base.firepower + (deltas.firepower ?? 0),
115
+ torpedo: base.torpedo + (deltas.torpedo ?? 0),
116
+ evasion: base.evasion + (deltas.evasion ?? 0),
117
+ antiwar: base.antiwar + (deltas.antiwar ?? 0),
118
+ aviation: base.aviation + (deltas.aviation ?? 0),
119
+ reload: base.reload + (deltas.reload ?? 0),
120
+ speed: base.speed + (deltas.speed ?? 0),
121
+ luck: base.luck + (deltas.luck ?? 0),
122
+ accuracy: base.accuracy + (deltas.accuracy ?? 0),
123
+ };
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Main
127
+ // ---------------------------------------------------------------------------
128
+ function normalizeStats(inputs) {
129
+ const { lb3RowId, en, groupType, strengthenId } = inputs;
130
+ const { statistics, strengthen, trans, transformDataTemplate } = en;
131
+ // ------------------------------------------------------------------
132
+ // Get the LB3 statistics row
133
+ // ------------------------------------------------------------------
134
+ const statsRow = statistics[lb3RowId];
135
+ if (statsRow === undefined) {
136
+ throw new Error(`normalizeStats: missing statistics row "${lb3RowId}" for group_type "${groupType}"`);
137
+ }
138
+ const attrs = statsRow.attrs;
139
+ const attrsGrowth = statsRow.attrs_growth;
140
+ const attrsGrowthExtra = statsRow.attrs_growth_extra ?? new Array(12).fill(0);
141
+ // ------------------------------------------------------------------
142
+ // Strengthen bonus
143
+ // ------------------------------------------------------------------
144
+ const strengthenRow = strengthen[strengthenId];
145
+ const durability = strengthenRow?.durability ?? [];
146
+ const strengthenBonus = buildStrengthenBonus(durability);
147
+ // ------------------------------------------------------------------
148
+ // Compute stat blocks at level 100 and 120
149
+ // ------------------------------------------------------------------
150
+ const level100 = buildStatBlock(attrs, attrsGrowth, attrsGrowthExtra, 100, strengthenBonus);
151
+ const level120 = buildStatBlock(attrs, attrsGrowth, attrsGrowthExtra, 120, strengthenBonus);
152
+ // ------------------------------------------------------------------
153
+ // Retrofit deltas
154
+ // ------------------------------------------------------------------
155
+ const hasRetrofit = groupType in trans;
156
+ let level100Retrofit;
157
+ let level120Retrofit;
158
+ if (hasRetrofit) {
159
+ const deltas = computeRetrofitDeltas(groupType, trans, transformDataTemplate);
160
+ level100Retrofit = applyRetrofitDeltas(level100, deltas);
161
+ level120Retrofit = applyRetrofitDeltas(level120, deltas);
162
+ }
163
+ // ------------------------------------------------------------------
164
+ // Enhance value
165
+ // ------------------------------------------------------------------
166
+ const enhanceValue = {
167
+ firepower: durability[0] ?? 0,
168
+ torpedo: durability[1] ?? 0,
169
+ aviation: durability[3] ?? 0,
170
+ reload: durability[4] ?? 0,
171
+ };
172
+ // ------------------------------------------------------------------
173
+ // Assemble output
174
+ // ------------------------------------------------------------------
175
+ const stats = {
176
+ level100,
177
+ level120,
178
+ ...(level100Retrofit !== undefined ? { level100Retrofit } : {}),
179
+ ...(level120Retrofit !== undefined ? { level120Retrofit } : {}),
180
+ };
181
+ return { stats, enhanceValue };
182
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./writeShips.js"), exports);
18
+ __exportStar(require("./writeShipList.js"), exports);
19
+ __exportStar(require("./writeIdMap.js"), exports);
20
+ __exportStar(require("./writeVersion.js"), exports);
@@ -0,0 +1,52 @@
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.writeIdMap = writeIdMap;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ // ---------------------------------------------------------------------------
10
+ // writeIdMap
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Write a name/alias → canonical id map to disk.
14
+ *
15
+ * Shape: Record<string, string>
16
+ *
17
+ * For each ship: emits names.en → id, names.cn → id, names.jp → id, names.code → id
18
+ * For each groupRow: emits padded code → group_type string (legacy AzurAPI lookup)
19
+ *
20
+ * Last-writer-wins for duplicate names.
21
+ */
22
+ function writeIdMap(ships, groupRows, outputPath = "data/id-map.json") {
23
+ const map = {};
24
+ // Collect all EN names first so we don't let names.code overwrite a real ship name
25
+ const enNames = new Set();
26
+ for (const ship of ships) {
27
+ if (ship.names.en !== undefined)
28
+ enNames.add(ship.names.en);
29
+ }
30
+ // Per-ship name entries (first-writer-wins for code names to avoid collisions)
31
+ for (const ship of ships) {
32
+ const { id, names } = ship;
33
+ if (names.en !== undefined)
34
+ map[names.en] = id;
35
+ if (names.cn !== undefined && !(names.cn in map))
36
+ map[names.cn] = id;
37
+ if (names.jp !== undefined && !(names.jp in map))
38
+ map[names.jp] = id;
39
+ if (names.code !== undefined && !(names.code in map) && !enNames.has(names.code)) {
40
+ map[names.code] = id;
41
+ }
42
+ }
43
+ // Legacy 3-digit code → group_type mapping from groupRows
44
+ for (const row of groupRows) {
45
+ const paddedCode = String(row.code).padStart(3, "0");
46
+ map[paddedCode] = String(row.group_type);
47
+ }
48
+ const json = JSON.stringify(map, null, 2);
49
+ const dir = path_1.default.dirname(path_1.default.resolve(outputPath));
50
+ fs_1.default.mkdirSync(dir, { recursive: true });
51
+ fs_1.default.writeFileSync(outputPath, json, "utf-8");
52
+ }
@@ -0,0 +1,31 @@
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.writeShipList = writeShipList;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ // ---------------------------------------------------------------------------
10
+ // writeShipList
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Write a minimal ship list to disk.
14
+ * Shape: Array<{ id: string; name: string; hullType: string; rarity: string }>
15
+ *
16
+ * `name` is resolved in priority order: names.en → names.code → id
17
+ */
18
+ function writeShipList(ships, outputPath = "data/ship-list.json") {
19
+ const list = ships.map((ship) => ({
20
+ id: ship.id,
21
+ name: ship.names.en ?? ship.names.code ?? ship.id,
22
+ hullType: ship.hullType,
23
+ rarity: ship.rarity,
24
+ }));
25
+ // Sort by id numerically for deterministic output
26
+ list.sort((a, b) => Number(a.id) - Number(b.id));
27
+ const json = JSON.stringify(list, null, 2);
28
+ const dir = path_1.default.dirname(path_1.default.resolve(outputPath));
29
+ fs_1.default.mkdirSync(dir, { recursive: true });
30
+ fs_1.default.writeFileSync(outputPath, json, "utf-8");
31
+ }