@jjlmoya/utils-games-development 1.63.0 → 1.65.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 (181) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -1
  3. package/src/entries.ts +7 -1
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/seo_parity.test.ts +2 -2
  7. package/src/tests/seo_translation_completeness.test.ts +69 -0
  8. package/src/tests/tool_validation.test.ts +2 -2
  9. package/src/tests/translation_copy.test.ts +21 -18
  10. package/src/tool/audioLoopPointFinder/i18n/de.ts +13 -0
  11. package/src/tool/audioLoopPointFinder/i18n/fr.ts +26 -0
  12. package/src/tool/audioLoopPointFinder/i18n/id.ts +4 -0
  13. package/src/tool/audioLoopPointFinder/i18n/it.ts +3 -0
  14. package/src/tool/audioLoopPointFinder/i18n/nl.ts +4 -0
  15. package/src/tool/audioLoopPointFinder/i18n/pl.ts +4 -0
  16. package/src/tool/audioLoopPointFinder/i18n/pt.ts +3 -0
  17. package/src/tool/audioLoopPointFinder/i18n/ru.ts +4 -0
  18. package/src/tool/audioLoopPointFinder/i18n/sv.ts +4 -0
  19. package/src/tool/audioLoopPointFinder/i18n/tr.ts +4 -0
  20. package/src/tool/audioLoopPointFinder/i18n/zh.ts +4 -0
  21. package/src/tool/damageFormulaLab/bibliography.astro +24 -0
  22. package/src/tool/damageFormulaLab/bibliography.ts +10 -0
  23. package/src/tool/damageFormulaLab/component.astro +178 -0
  24. package/src/tool/damageFormulaLab/controller.ts +235 -0
  25. package/src/tool/damageFormulaLab/damage-formula-lab.css +644 -0
  26. package/src/tool/damageFormulaLab/dom-views.ts +193 -0
  27. package/src/tool/damageFormulaLab/entry.ts +28 -0
  28. package/src/tool/damageFormulaLab/evaluator.ts +84 -0
  29. package/src/tool/damageFormulaLab/expression.ts +191 -0
  30. package/src/tool/damageFormulaLab/i18n/de.ts +194 -0
  31. package/src/tool/damageFormulaLab/i18n/en.ts +231 -0
  32. package/src/tool/damageFormulaLab/i18n/es.ts +181 -0
  33. package/src/tool/damageFormulaLab/i18n/fr.ts +194 -0
  34. package/src/tool/damageFormulaLab/i18n/id.ts +194 -0
  35. package/src/tool/damageFormulaLab/i18n/it.ts +182 -0
  36. package/src/tool/damageFormulaLab/i18n/ja.ts +183 -0
  37. package/src/tool/damageFormulaLab/i18n/ko.ts +182 -0
  38. package/src/tool/damageFormulaLab/i18n/nl.ts +182 -0
  39. package/src/tool/damageFormulaLab/i18n/pl.ts +182 -0
  40. package/src/tool/damageFormulaLab/i18n/pt.ts +182 -0
  41. package/src/tool/damageFormulaLab/i18n/ru.ts +183 -0
  42. package/src/tool/damageFormulaLab/i18n/sv.ts +183 -0
  43. package/src/tool/damageFormulaLab/i18n/tr.ts +183 -0
  44. package/src/tool/damageFormulaLab/i18n/zh.ts +183 -0
  45. package/src/tool/damageFormulaLab/index.ts +11 -0
  46. package/src/tool/damageFormulaLab/logic.test.ts +138 -0
  47. package/src/tool/damageFormulaLab/logic.ts +138 -0
  48. package/src/tool/damageFormulaLab/model.ts +151 -0
  49. package/src/tool/damageFormulaLab/seo.astro +13 -0
  50. package/src/tool/damageFormulaLab/storage.ts +62 -0
  51. package/src/tool/damageFormulaLab/transfers.ts +89 -0
  52. package/src/tool/damageFormulaLab/ui.ts +62 -0
  53. package/src/tool/gameDeltaTimeFixedTimestepLab/bibliography.astro +22 -0
  54. package/src/tool/gameDeltaTimeFixedTimestepLab/bibliography.ts +10 -0
  55. package/src/tool/gameDeltaTimeFixedTimestepLab/component.astro +51 -0
  56. package/src/tool/gameDeltaTimeFixedTimestepLab/controller.ts +79 -0
  57. package/src/tool/gameDeltaTimeFixedTimestepLab/dom-views.ts +88 -0
  58. package/src/tool/gameDeltaTimeFixedTimestepLab/entry.ts +27 -0
  59. package/src/tool/gameDeltaTimeFixedTimestepLab/evaluator.ts +21 -0
  60. package/src/tool/gameDeltaTimeFixedTimestepLab/game-delta-time-fixed-timestep-lab.css +491 -0
  61. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/de.ts +56 -0
  62. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/en.ts +180 -0
  63. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/es.ts +56 -0
  64. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/fr.ts +46 -0
  65. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/id.ts +46 -0
  66. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/it.ts +46 -0
  67. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/ja.ts +46 -0
  68. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/ko.ts +46 -0
  69. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/nl.ts +46 -0
  70. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/pl.ts +46 -0
  71. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/pt.ts +46 -0
  72. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/ru.ts +46 -0
  73. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/sv.ts +46 -0
  74. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/tr.ts +46 -0
  75. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/zh.ts +46 -0
  76. package/src/tool/gameDeltaTimeFixedTimestepLab/index.ts +11 -0
  77. package/src/tool/gameDeltaTimeFixedTimestepLab/logic.test.ts +35 -0
  78. package/src/tool/gameDeltaTimeFixedTimestepLab/logic.ts +140 -0
  79. package/src/tool/gameDeltaTimeFixedTimestepLab/seo.astro +15 -0
  80. package/src/tool/gameDeltaTimeFixedTimestepLab/seo_contract.test.ts +25 -0
  81. package/src/tool/gameDeltaTimeFixedTimestepLab/storage.ts +23 -0
  82. package/src/tool/gameDeltaTimeFixedTimestepLab/ui.ts +54 -0
  83. package/src/tool/gameUIAccessibilityTester/i18n/de.ts +13 -0
  84. package/src/tool/gameUIAccessibilityTester/i18n/fr.ts +13 -0
  85. package/src/tool/gameUIAccessibilityTester/i18n/id.ts +13 -0
  86. package/src/tool/gameUIAccessibilityTester/i18n/it.ts +1 -0
  87. package/src/tool/gameUIAccessibilityTester/i18n/nl.ts +5 -0
  88. package/src/tool/gameUIAccessibilityTester/i18n/pl.ts +5 -0
  89. package/src/tool/gameUIAccessibilityTester/i18n/pt.ts +2 -0
  90. package/src/tool/gameUIAccessibilityTester/i18n/ru.ts +1 -0
  91. package/src/tool/gameUIAccessibilityTester/i18n/sv.ts +1 -0
  92. package/src/tool/gameUIAccessibilityTester/i18n/tr.ts +2 -0
  93. package/src/tool/gameUIAccessibilityTester/i18n/zh.ts +1 -0
  94. package/src/tool/hitboxHurtboxAnimator/i18n/de.ts +14 -0
  95. package/src/tool/hitboxHurtboxAnimator/i18n/fr.ts +13 -0
  96. package/src/tool/hitboxHurtboxAnimator/i18n/id.ts +13 -0
  97. package/src/tool/hitboxHurtboxAnimator/i18n/it.ts +1 -0
  98. package/src/tool/hitboxHurtboxAnimator/i18n/nl.ts +1 -0
  99. package/src/tool/hitboxHurtboxAnimator/i18n/pl.ts +2 -0
  100. package/src/tool/hitboxHurtboxAnimator/i18n/pt.ts +2 -0
  101. package/src/tool/hitboxHurtboxAnimator/i18n/ru.ts +2 -0
  102. package/src/tool/hitboxHurtboxAnimator/i18n/sv.ts +1 -0
  103. package/src/tool/hitboxHurtboxAnimator/i18n/tr.ts +2 -0
  104. package/src/tool/itchioGameTester/i18n/de.ts +13 -0
  105. package/src/tool/itchioGameTester/i18n/es.ts +2 -2
  106. package/src/tool/itchioGameTester/i18n/fr.ts +26 -0
  107. package/src/tool/itchioGameTester/i18n/id.ts +3 -0
  108. package/src/tool/itchioGameTester/i18n/it.ts +3 -0
  109. package/src/tool/itchioGameTester/i18n/ja.ts +3 -0
  110. package/src/tool/itchioGameTester/i18n/ko.ts +3 -0
  111. package/src/tool/itchioGameTester/i18n/nl.ts +3 -0
  112. package/src/tool/itchioGameTester/i18n/pl.ts +3 -0
  113. package/src/tool/itchioGameTester/i18n/pt.ts +3 -0
  114. package/src/tool/itchioGameTester/i18n/ru.ts +3 -0
  115. package/src/tool/itchioGameTester/i18n/sv.ts +3 -0
  116. package/src/tool/itchioGameTester/i18n/tr.ts +3 -0
  117. package/src/tool/itchioGameTester/i18n/zh.ts +3 -0
  118. package/src/tool/localizationSanitizer/i18n/de.ts +13 -0
  119. package/src/tool/localizationSanitizer/i18n/es.ts +26 -0
  120. package/src/tool/localizationSanitizer/i18n/fr.ts +4 -0
  121. package/src/tool/localizationSanitizer/i18n/id.ts +4 -0
  122. package/src/tool/localizationSanitizer/i18n/it.ts +4 -0
  123. package/src/tool/localizationSanitizer/i18n/ja.ts +4 -0
  124. package/src/tool/localizationSanitizer/i18n/ko.ts +4 -0
  125. package/src/tool/localizationSanitizer/i18n/nl.ts +5 -0
  126. package/src/tool/localizationSanitizer/i18n/pl.ts +5 -0
  127. package/src/tool/localizationSanitizer/i18n/pt.ts +5 -0
  128. package/src/tool/localizationSanitizer/i18n/ru.ts +5 -0
  129. package/src/tool/localizationSanitizer/i18n/sv.ts +5 -0
  130. package/src/tool/localizationSanitizer/i18n/tr.ts +5 -0
  131. package/src/tool/localizationSanitizer/i18n/zh.ts +6 -0
  132. package/src/tool/pixelArtPaletteSwapper/i18n/ja.ts +13 -0
  133. package/src/tool/pixelArtPaletteSwapper/i18n/ko.ts +13 -0
  134. package/src/tool/pixelArtPaletteSwapper/i18n/zh.ts +18 -0
  135. package/src/tool/retroSfxGenerator/i18n/de.ts +13 -0
  136. package/src/tool/retroSfxGenerator/i18n/fr.ts +13 -0
  137. package/src/tool/retroSfxGenerator/i18n/id.ts +13 -0
  138. package/src/tool/retroSfxGenerator/i18n/it.ts +1 -0
  139. package/src/tool/retroSfxGenerator/i18n/nl.ts +1 -0
  140. package/src/tool/retroSfxGenerator/i18n/pl.ts +1 -0
  141. package/src/tool/retroSfxGenerator/i18n/pt.ts +1 -0
  142. package/src/tool/retroSfxGenerator/i18n/ru.ts +1 -0
  143. package/src/tool/retroSfxGenerator/i18n/sv.ts +2 -0
  144. package/src/tool/retroSfxGenerator/i18n/tr.ts +1 -0
  145. package/src/tool/retroSfxGenerator/i18n/zh.ts +1 -0
  146. package/src/tool/spriteSheetPacker/i18n/de.ts +13 -0
  147. package/src/tool/spriteSheetPacker/i18n/es.ts +2 -2
  148. package/src/tool/spriteSheetPacker/i18n/fr.ts +26 -0
  149. package/src/tool/spriteSheetPacker/i18n/id.ts +4 -0
  150. package/src/tool/spriteSheetPacker/i18n/it.ts +4 -0
  151. package/src/tool/spriteSheetPacker/i18n/ja.ts +3 -0
  152. package/src/tool/spriteSheetPacker/i18n/ko.ts +3 -0
  153. package/src/tool/spriteSheetPacker/i18n/nl.ts +4 -0
  154. package/src/tool/spriteSheetPacker/i18n/pl.ts +4 -0
  155. package/src/tool/spriteSheetPacker/i18n/pt.ts +4 -0
  156. package/src/tool/spriteSheetPacker/i18n/ru.ts +4 -0
  157. package/src/tool/spriteSheetPacker/i18n/sv.ts +4 -0
  158. package/src/tool/spriteSheetPacker/i18n/tr.ts +4 -0
  159. package/src/tool/spriteSheetPacker/i18n/zh.ts +4 -0
  160. package/src/tool/steamBbcodeTranslator/i18n/de.ts +22 -0
  161. package/src/tool/steamBbcodeTranslator/i18n/es.ts +23 -1
  162. package/src/tool/steamBbcodeTranslator/i18n/fr.ts +6 -1
  163. package/src/tool/steamBbcodeTranslator/i18n/id.ts +7 -1
  164. package/src/tool/steamBbcodeTranslator/i18n/it.ts +6 -1
  165. package/src/tool/steamBbcodeTranslator/i18n/ja.ts +5 -1
  166. package/src/tool/steamBbcodeTranslator/i18n/ko.ts +5 -1
  167. package/src/tool/steamBbcodeTranslator/i18n/nl.ts +7 -1
  168. package/src/tool/steamBbcodeTranslator/i18n/pl.ts +7 -1
  169. package/src/tool/steamBbcodeTranslator/i18n/pt.ts +7 -1
  170. package/src/tool/steamBbcodeTranslator/i18n/ru.ts +7 -1
  171. package/src/tool/steamBbcodeTranslator/i18n/sv.ts +7 -1
  172. package/src/tool/steamBbcodeTranslator/i18n/tr.ts +7 -1
  173. package/src/tool/steamBbcodeTranslator/i18n/zh.ts +5 -1
  174. package/src/tool/steamCapsuleGenerator/i18n/de.ts +2 -2
  175. package/src/tool/steamCapsuleGenerator/i18n/es.ts +2 -2
  176. package/src/tool/steamCapsuleGenerator/i18n/fr.ts +2 -2
  177. package/src/tool/steamCapsuleGenerator/i18n/pl.ts +13 -0
  178. package/src/tool/steamCapsuleGenerator/i18n/ru.ts +26 -0
  179. package/src/tool/steamCapsuleGenerator/i18n/sv.ts +1 -0
  180. package/src/tool/steamCapsuleGenerator/i18n/tr.ts +1 -0
  181. package/src/tools.ts +4 -0
@@ -0,0 +1,235 @@
1
+ import { renderLab } from "./dom-views";
2
+ import {
3
+ configFromHash,
4
+ defaultConfig,
5
+ formulaPresets,
6
+ parseConfig,
7
+ scenarios,
8
+ } from "./model";
9
+ import type { LabConfig } from "./model";
10
+ import { loadPreferences, savePreferences } from "./storage";
11
+ import {
12
+ copyShareLink,
13
+ exportChartPng,
14
+ exportCsv,
15
+ exportJson,
16
+ } from "./transfers";
17
+ import type { DamageFormulaLabUI } from "./ui";
18
+
19
+ type Update = (config: LabConfig) => void;
20
+ type GetConfig = () => LabConfig;
21
+
22
+ function input(root: HTMLElement, name: string): HTMLInputElement | null {
23
+ return root.querySelector<HTMLInputElement>(`[name="${name}"]`);
24
+ }
25
+
26
+ function numberValue(
27
+ root: HTMLElement,
28
+ name: string,
29
+ fallback: number,
30
+ ): number {
31
+ const value = Number(input(root, name)?.value);
32
+ return Number.isFinite(value) ? value : fallback;
33
+ }
34
+
35
+ function setActive(root: HTMLElement, selector: string, value: string): void {
36
+ root.querySelectorAll<HTMLElement>(selector).forEach((item) => {
37
+ const candidate = item.dataset.rounding ?? item.dataset.order;
38
+ item.dataset.active = String(candidate === value);
39
+ });
40
+ }
41
+
42
+ function writeInputs(root: HTMLElement, config: LabConfig): void {
43
+ const values: Record<string, number | string> = {
44
+ formulaA: config.formulaA,
45
+ formulaB: config.formulaB,
46
+ ...config.variables,
47
+ health: config.settings.health,
48
+ attacksPerSecond: config.settings.attacksPerSecond,
49
+ };
50
+ Object.entries(values).forEach(([name, value]) => {
51
+ const field = input(root, name);
52
+ if (field) field.value = String(value);
53
+ });
54
+ setActive(root, "[data-rounding]", config.settings.rounding);
55
+ setActive(root, "[data-order]", config.settings.modifierOrder);
56
+ }
57
+
58
+ function readVariables(
59
+ root: HTMLElement,
60
+ current: LabConfig,
61
+ ): Record<string, number> {
62
+ return Object.fromEntries(
63
+ Object.keys(current.variables).map((name) => [
64
+ name,
65
+ numberValue(
66
+ root,
67
+ name,
68
+ current.variables[name as keyof typeof current.variables],
69
+ ),
70
+ ]),
71
+ );
72
+ }
73
+
74
+ function readConfig(root: HTMLElement, current: LabConfig): LabConfig {
75
+ return parseConfig({
76
+ ...current,
77
+ formulaA: input(root, "formulaA")?.value,
78
+ formulaB: input(root, "formulaB")?.value,
79
+ variables: readVariables(root, current),
80
+ settings: {
81
+ ...current.settings,
82
+ health: numberValue(root, "health", current.settings.health),
83
+ attacksPerSecond: numberValue(
84
+ root,
85
+ "attacksPerSecond",
86
+ current.settings.attacksPerSecond,
87
+ ),
88
+ },
89
+ });
90
+ }
91
+
92
+ function save(config: LabConfig): void {
93
+ savePreferences({
94
+ formulaA: config.formulaA,
95
+ formulaB: config.formulaB,
96
+ rounding: config.settings.rounding,
97
+ modifierOrder: config.settings.modifierOrder,
98
+ });
99
+ }
100
+
101
+ function initialConfig(): LabConfig {
102
+ const preferences = loadPreferences();
103
+ return (
104
+ configFromHash(location.hash) ?? {
105
+ ...structuredClone(defaultConfig),
106
+ formulaA: preferences.formulaA,
107
+ formulaB: preferences.formulaB,
108
+ settings: {
109
+ ...defaultConfig.settings,
110
+ rounding: preferences.rounding,
111
+ modifierOrder: preferences.modifierOrder,
112
+ },
113
+ }
114
+ );
115
+ }
116
+
117
+ function applyScenario(config: LabConfig, name: string): LabConfig {
118
+ const scenario = scenarios[name];
119
+ if (!scenario) return config;
120
+ const { health, ...variables } = scenario;
121
+ return {
122
+ ...config,
123
+ variables: { ...config.variables, ...variables },
124
+ settings: { ...config.settings, health },
125
+ };
126
+ }
127
+
128
+ function bindModes(root: HTMLElement, get: GetConfig, update: Update): void {
129
+ root
130
+ .querySelectorAll<HTMLButtonElement>("[data-rounding]")
131
+ .forEach((button) =>
132
+ button.addEventListener("click", () => {
133
+ const config = get();
134
+ update({
135
+ ...config,
136
+ settings: {
137
+ ...config.settings,
138
+ rounding: button.dataset
139
+ .rounding as LabConfig["settings"]["rounding"],
140
+ },
141
+ });
142
+ }),
143
+ );
144
+ root.querySelectorAll<HTMLButtonElement>("[data-order]").forEach((button) =>
145
+ button.addEventListener("click", () => {
146
+ const config = get();
147
+ update({
148
+ ...config,
149
+ settings: {
150
+ ...config.settings,
151
+ modifierOrder: button.dataset
152
+ .order as LabConfig["settings"]["modifierOrder"],
153
+ },
154
+ });
155
+ }),
156
+ );
157
+ }
158
+
159
+ function bindPresets(root: HTMLElement, get: GetConfig, update: Update): void {
160
+ root.querySelectorAll<HTMLButtonElement>("[data-preset]").forEach((button) =>
161
+ button.addEventListener("click", () => {
162
+ const formula =
163
+ formulaPresets[button.dataset.preset as keyof typeof formulaPresets];
164
+ update({ ...get(), formulaB: formula });
165
+ }),
166
+ );
167
+ root
168
+ .querySelectorAll<HTMLButtonElement>("[data-scenario]")
169
+ .forEach((button) =>
170
+ button.addEventListener("click", () => {
171
+ update(applyScenario(get(), button.dataset.scenario ?? ""));
172
+ }),
173
+ );
174
+ }
175
+
176
+ function bindImport(
177
+ root: HTMLElement,
178
+ update: Update,
179
+ ui: DamageFormulaLabUI,
180
+ ): void {
181
+ const picker = root.querySelector<HTMLInputElement>("[data-import]");
182
+ picker?.addEventListener("change", async () => {
183
+ try {
184
+ const file = picker.files?.[0];
185
+ if (file) update(parseConfig(JSON.parse(await file.text())));
186
+ } catch {
187
+ const status = root.querySelector<HTMLElement>("[data-status]");
188
+ if (status) status.textContent = ui.importError;
189
+ }
190
+ });
191
+ }
192
+
193
+ function bindExports(
194
+ root: HTMLElement,
195
+ get: GetConfig,
196
+ update: Update,
197
+ ui: DamageFormulaLabUI,
198
+ ): void {
199
+ root
200
+ .querySelector("[data-reset]")
201
+ ?.addEventListener("click", () => update(structuredClone(defaultConfig)));
202
+ root
203
+ .querySelector("[data-json]")
204
+ ?.addEventListener("click", () => exportJson(get()));
205
+ root
206
+ .querySelector("[data-csv]")
207
+ ?.addEventListener("click", () => exportCsv(get()));
208
+ root
209
+ .querySelector("[data-png]")
210
+ ?.addEventListener("click", () => exportChartPng(root));
211
+ root.querySelector("[data-share]")?.addEventListener("click", async () => {
212
+ await copyShareLink(get());
213
+ const status = root.querySelector<HTMLElement>("[data-status]");
214
+ if (status) status.textContent = ui.copiedStatus;
215
+ });
216
+ bindImport(root, update, ui);
217
+ }
218
+
219
+ export function mountDamageFormulaLab(
220
+ root: HTMLElement,
221
+ ui: DamageFormulaLabUI,
222
+ ): void {
223
+ let config = initialConfig();
224
+ const update: Update = (next) => {
225
+ config = next;
226
+ writeInputs(root, config);
227
+ save(config);
228
+ renderLab(root, config, ui);
229
+ };
230
+ root.addEventListener("input", () => update(readConfig(root, config)));
231
+ bindModes(root, () => config, update);
232
+ bindPresets(root, () => config, update);
233
+ bindExports(root, () => config, update, ui);
234
+ update(config);
235
+ }