volleyballsimtypes 0.0.521 → 0.0.523
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/api/index.d.ts +1 -1
- package/dist/cjs/src/data/country-locales.json +12 -0
- package/dist/cjs/src/data/init-models.js +4 -0
- package/dist/cjs/src/data/models/currency-transaction.d.ts +3 -2
- package/dist/cjs/src/data/models/currency-transaction.js +1 -0
- package/dist/cjs/src/data/models/index.d.ts +1 -0
- package/dist/cjs/src/data/models/index.js +1 -0
- package/dist/cjs/src/data/models/user-achievements.d.ts +19 -0
- package/dist/cjs/src/data/models/user-achievements.js +37 -0
- package/dist/cjs/src/service/achievement/achievement-status.d.ts +5 -0
- package/dist/cjs/src/service/achievement/achievement-status.js +13 -0
- package/dist/cjs/src/service/achievement/achievement-type.d.ts +24 -0
- package/dist/cjs/src/service/achievement/achievement-type.js +85 -0
- package/dist/cjs/src/service/achievement/index.d.ts +3 -0
- package/dist/cjs/src/service/achievement/index.js +19 -0
- package/dist/cjs/src/service/achievement/schemas/achievements.z.d.ts +3 -0
- package/dist/cjs/src/service/achievement/schemas/achievements.z.js +9 -0
- package/dist/cjs/src/service/index.d.ts +1 -0
- package/dist/cjs/src/service/index.js +1 -0
- package/dist/cjs/src/service/match/vper.js +23 -3
- package/dist/cjs/src/service/match/vper.test.js +86 -0
- package/dist/cjs/src/service/notification/catalog/en.json +4 -0
- package/dist/cjs/src/service/notification/catalog/es.json +4 -0
- package/dist/cjs/src/service/notification/catalog/fr.json +4 -0
- package/dist/cjs/src/service/notification/catalog/it.json +4 -0
- package/dist/cjs/src/service/notification/catalog/pl.json +4 -0
- package/dist/cjs/src/service/notification/catalog/pt-BR.json +4 -0
- package/dist/cjs/src/service/notification/catalog/tr.json +4 -0
- package/dist/cjs/src/service/notification/notification-type.d.ts +1 -1
- package/dist/cjs/src/service/notification/notification-type.js +2 -1
- package/dist/cjs/src/service/notification/registry.js +9 -0
- package/dist/cjs/src/service/team/base-config.js +8 -4
- package/dist/cjs/src/service/team/default-base-config.js +11 -9
- package/dist/cjs/src/service/team/default-base-config.test.js +52 -0
- package/dist/esm/src/api/index.d.ts +1 -1
- package/dist/esm/src/data/country-locales.json +12 -0
- package/dist/esm/src/data/init-models.js +5 -1
- package/dist/esm/src/data/models/currency-transaction.d.ts +3 -2
- package/dist/esm/src/data/models/currency-transaction.js +1 -0
- package/dist/esm/src/data/models/index.d.ts +1 -0
- package/dist/esm/src/data/models/index.js +1 -0
- package/dist/esm/src/data/models/user-achievements.d.ts +19 -0
- package/dist/esm/src/data/models/user-achievements.js +33 -0
- package/dist/esm/src/service/achievement/achievement-status.d.ts +5 -0
- package/dist/esm/src/service/achievement/achievement-status.js +10 -0
- package/dist/esm/src/service/achievement/achievement-type.d.ts +24 -0
- package/dist/esm/src/service/achievement/achievement-type.js +77 -0
- package/dist/esm/src/service/achievement/index.d.ts +3 -0
- package/dist/esm/src/service/achievement/index.js +3 -0
- package/dist/esm/src/service/achievement/schemas/achievements.z.d.ts +3 -0
- package/dist/esm/src/service/achievement/schemas/achievements.z.js +6 -0
- package/dist/esm/src/service/index.d.ts +1 -0
- package/dist/esm/src/service/index.js +1 -0
- package/dist/esm/src/service/match/vper.js +23 -3
- package/dist/esm/src/service/match/vper.test.js +86 -0
- package/dist/esm/src/service/notification/catalog/en.json +4 -0
- package/dist/esm/src/service/notification/catalog/es.json +4 -0
- package/dist/esm/src/service/notification/catalog/fr.json +4 -0
- package/dist/esm/src/service/notification/catalog/it.json +4 -0
- package/dist/esm/src/service/notification/catalog/pl.json +4 -0
- package/dist/esm/src/service/notification/catalog/pt-BR.json +4 -0
- package/dist/esm/src/service/notification/catalog/tr.json +4 -0
- package/dist/esm/src/service/notification/notification-type.d.ts +1 -1
- package/dist/esm/src/service/notification/notification-type.js +2 -1
- package/dist/esm/src/service/notification/registry.js +9 -0
- package/dist/esm/src/service/team/base-config.js +8 -4
- package/dist/esm/src/service/team/default-base-config.js +11 -9
- package/dist/esm/src/service/team/default-base-config.test.js +53 -1
- package/package.json +1 -1
|
@@ -58,5 +58,9 @@
|
|
|
58
58
|
"title": "Evento encerrado",
|
|
59
59
|
"body": "O evento acabou. Veja a tabela final e suas recompensas.",
|
|
60
60
|
"placed": "O evento acabou. Você terminou em {{position}} de {{entrants}}."
|
|
61
|
+
},
|
|
62
|
+
"regionRelocation": {
|
|
63
|
+
"title": "Seu time está mudando",
|
|
64
|
+
"body": "Seu time foi escolhido para ser movido para a nova região: Kyorin. Nada muda em relação ao time que você gerencia, seus jogadores ou qualquer outra coisa."
|
|
61
65
|
}
|
|
62
66
|
}
|
|
@@ -58,5 +58,9 @@
|
|
|
58
58
|
"title": "Etkinlik bitti",
|
|
59
59
|
"body": "Etkinlik sona erdi. Final tablosuna ve ödüllerine bak.",
|
|
60
60
|
"placed": "Etkinlik sona erdi. {{entrants}} takım arasında {{position}}. oldun."
|
|
61
|
+
},
|
|
62
|
+
"regionRelocation": {
|
|
63
|
+
"title": "Takımın taşınıyor",
|
|
64
|
+
"body": "Takımın yeni bölgeye, Kyorin'e taşınmak üzere seçildi. Yönettiğin takım, oyuncuların ya da başka hiçbir şey açısından hiçbir şey değişmiyor."
|
|
61
65
|
}
|
|
62
66
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const NOTIFICATION_TYPES: readonly ["MATCH_RESULT", "INJURY", "INJURY_RECOVERED", "SEASON_END", "GRANT_RECEIVED", "PROMOTION", "DAILY_LOGIN", "WELCOME", "COMPENSATION", "EVENT_REGISTRATION_OPEN", "EVENT_REGISTRATION_CLOSING", "EVENT_STARTED", "EVENT_FINAL_ROUND", "EVENT_FINISHED"];
|
|
1
|
+
export declare const NOTIFICATION_TYPES: readonly ["MATCH_RESULT", "INJURY", "INJURY_RECOVERED", "SEASON_END", "GRANT_RECEIVED", "PROMOTION", "DAILY_LOGIN", "WELCOME", "COMPENSATION", "EVENT_REGISTRATION_OPEN", "EVENT_REGISTRATION_CLOSING", "EVENT_STARTED", "EVENT_FINAL_ROUND", "EVENT_FINISHED", "REGION_RELOCATION"];
|
|
2
2
|
export type NotificationType = typeof NOTIFICATION_TYPES[number];
|
|
3
3
|
export declare const NOTIFICATION_LOCALES: readonly ["en", "es", "fr", "it", "pl", "pt-BR", "tr"];
|
|
4
4
|
export type NotificationLocale = typeof NOTIFICATION_LOCALES[number];
|
|
@@ -16,7 +16,8 @@ export const NOTIFICATION_TYPES = [
|
|
|
16
16
|
'EVENT_REGISTRATION_CLOSING',
|
|
17
17
|
'EVENT_STARTED',
|
|
18
18
|
'EVENT_FINAL_ROUND',
|
|
19
|
-
'EVENT_FINISHED'
|
|
19
|
+
'EVENT_FINISHED',
|
|
20
|
+
'REGION_RELOCATION'
|
|
20
21
|
];
|
|
21
22
|
// The 7 supported locales. Must stay in sync with the API VALID_LOCALES set and the UI src/locales/*.json.
|
|
22
23
|
export const NOTIFICATION_LOCALES = ['en', 'es', 'fr', 'it', 'pl', 'pt-BR', 'tr'];
|
|
@@ -159,6 +159,15 @@ export const NOTIFICATION_REGISTRY = {
|
|
|
159
159
|
emitsPush: false,
|
|
160
160
|
richRender: 'COMPENSATION',
|
|
161
161
|
catalogKeys: []
|
|
162
|
+
},
|
|
163
|
+
// One-off relocation warning: sent to users whose team is being moved to Kyorin. Informational; opens their team.
|
|
164
|
+
REGION_RELOCATION: {
|
|
165
|
+
emitsPush: true,
|
|
166
|
+
deepLink: teamPath,
|
|
167
|
+
pushTitleKey: 'regionRelocation.title',
|
|
168
|
+
pushBodyKey: 'regionRelocation.body',
|
|
169
|
+
inAppMessageKey: 'regionRelocation.body',
|
|
170
|
+
catalogKeys: ['regionRelocation.title', 'regionRelocation.body']
|
|
162
171
|
}
|
|
163
172
|
};
|
|
164
173
|
// The notification types that emit a mobile push (everything except COMPENSATION). Source of truth = each
|
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
// (and populated from a picked default preset); consumed by the positional engine to place players. A team with no
|
|
5
5
|
// `basePositions` falls back to the default preset for its `rotationSystem`.
|
|
6
6
|
//
|
|
7
|
-
// KEYING: rotation 1..6 and zone 1..6 are the ROTATIONAL (at-the-whistle) slots. The
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// the
|
|
7
|
+
// KEYING: rotation 1..6 and zone 1..6 are the ROTATIONAL (at-the-whistle) slots. The `rotation` key is the MAIN
|
|
8
|
+
// designated setter's (designatedSetters[0]) rotational ZONE, raw 1..6 (`rotation` == that setter's zone; there is
|
|
9
|
+
// NO setter-zone->rotation remap). This is the single convention everywhere: the editor writes it (posOf anchored on
|
|
10
|
+
// the main setter, saved verbatim), the engine reads it (positioning.rotationOf = getMainSetter zone), and the
|
|
11
|
+
// offensive/tempo/blocking prefs key by mainSetter.position. `coords[formation][rotation][zone]` is the standing
|
|
12
|
+
// coordinate for that formation; `receive[rotation][zone]` is the reception-participation flag (absent zone => default
|
|
13
|
+
// to participating). (History: rotationOf once remapped via SETTER_ZONE_TO_ROTATION and defaultReceiveMap once keyed
|
|
14
|
+
// by that index; both were unified to the raw main-setter zone. See VolleyballSim/plans/rotation-key-main-setter.md.)
|
|
11
15
|
export const BASE_FORMATIONS = ['SERVE', 'RECEIVE', 'DEFENCE', 'DEF_L', 'DEF_M', 'DEF_R', 'ATTACK'];
|
|
@@ -195,22 +195,24 @@ const DEFAULT_5_1_RECEIVE = {
|
|
|
195
195
|
5: { 1: true, 2: false, 3: true, 4: false, 5: false, 6: true },
|
|
196
196
|
6: { 1: true, 2: false, 3: false, 4: true, 5: true, 6: false }
|
|
197
197
|
};
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
//
|
|
201
|
-
// slot function is an OUTSIDE_HITTER (either row) or a BACK-ROW MIDDLE_BLOCKER (the libero's slot)
|
|
202
|
-
// opposite and the front-row middle hide. slotFunctionAt maps the opposite slot to SETTER in 4-2/6-2,
|
|
203
|
-
// second setter is excluded too, giving the same 3-passer map for every system.
|
|
198
|
+
// The default serve-receive participation map: the standard 3-passer formation. Keyed by the MAIN setter's rotational
|
|
199
|
+
// ZONE (raw 1..6 = the canonical convention: receive[Z] describes the formation with the setter at zone Z), matching
|
|
200
|
+
// DEFAULT_5_1_RECEIVE, the PRESET_6_2/PRESET_4_2 presets, the tactics editor, and the engine's rotationOf. A rotational
|
|
201
|
+
// slot passes iff its slot function is an OUTSIDE_HITTER (either row) or a BACK-ROW MIDDLE_BLOCKER (the libero's slot);
|
|
202
|
+
// the setter, the opposite and the front-row middle hide. slotFunctionAt maps the opposite slot to SETTER in 4-2/6-2,
|
|
203
|
+
// so the second setter is excluded too, giving the same 3-passer map for every system.
|
|
204
|
+
// (History: this used to key by a rotation INDEX via ROTATION_TO_SETTER_ZONE {1:1,2:6,3:5,4:4,5:3,6:2}, a leftover of
|
|
205
|
+
// the old setter-zone->rotation remap removed from rotationOf; that transposed the non-5-1 default receive maps at
|
|
206
|
+
// rotations 2/3/5/6. Fixed 2026-08-23, see VolleyballSim/plans/rotation-key-main-setter.md + the re-key migration.)
|
|
204
207
|
export function defaultReceiveMap(system) {
|
|
205
208
|
const receive = {};
|
|
206
|
-
for (let
|
|
207
|
-
const setterZone = ROTATION_TO_SETTER_ZONE[rotation];
|
|
209
|
+
for (let setterZone = 1; setterZone <= 6; setterZone++) {
|
|
208
210
|
const perZone = {};
|
|
209
211
|
for (let zone = 1; zone <= 6; zone++) {
|
|
210
212
|
const fn = slotFunctionAt(system, setterZone, zone);
|
|
211
213
|
perZone[String(zone)] = fn === RoleEnum.OUTSIDE_HITTER || (fn === RoleEnum.MIDDLE_BLOCKER && isBackRow(zone));
|
|
212
214
|
}
|
|
213
|
-
receive[String(
|
|
215
|
+
receive[String(setterZone)] = perZone;
|
|
214
216
|
}
|
|
215
217
|
return receive;
|
|
216
218
|
}
|
|
@@ -1,7 +1,59 @@
|
|
|
1
1
|
import { RotationSystemEnum } from './rotation-system';
|
|
2
|
-
import { defaultBaseConfig } from './default-base-config';
|
|
2
|
+
import { defaultBaseConfig, defaultReceiveMap } from './default-base-config';
|
|
3
|
+
import { baseConfigViolations } from './receive-overlap';
|
|
3
4
|
// Back-row rotational zones (right/left/middle back). Front row is {2,3,4}.
|
|
4
5
|
const BACK_ROW = new Set([1, 5, 6]);
|
|
6
|
+
// The editor and the sim BOTH fall back to defaultBaseConfig for a zone a config leaves unset, so the default base
|
|
7
|
+
// MUST itself pass the FIVB overlap / serve-line rules in every rotation. Otherwise a partial config (some zones
|
|
8
|
+
// stored, others defaulted) can render/commit an unset zone onto a neighbour and read "out of rotation even in
|
|
9
|
+
// base" for a formation the sim runs legally (rush6@ tournament report, 2026-08-21).
|
|
10
|
+
// The default receive map must key by the MAIN setter's RAW rotational zone (receive[R] describes the formation with
|
|
11
|
+
// the setter at zone R), the single canonical convention shared by DEFAULT_5_1_RECEIVE, the PRESET_6_2/4_2 presets,
|
|
12
|
+
// the tactics editor, and the engine's rotationOf. It used to key by a rotation INDEX (ROTATION_TO_SETTER_ZONE), which
|
|
13
|
+
// transposed non-5-1 maps at rotations 2/3/5/6 (fixed 2026-08-23; see plans/rotation-key-main-setter.md).
|
|
14
|
+
describe('defaultReceiveMap: raw main-setter-zone convention', () => {
|
|
15
|
+
it('5-1: the computed map equals the hand-authored raw DEFAULT_5_1_RECEIVE', () => {
|
|
16
|
+
// defaultBaseConfig(5-1).receive IS the hand-authored DEFAULT_5_1_RECEIVE. The computed map matching it proves
|
|
17
|
+
// defaultReceiveMap keys by the raw setter zone (receive[R] = setter@R), not the old index.
|
|
18
|
+
expect(defaultReceiveMap(RotationSystemEnum.FIVE_ONE)).toEqual(defaultBaseConfig(RotationSystemEnum.FIVE_ONE).receive);
|
|
19
|
+
});
|
|
20
|
+
it('every system: receive[R] hides the setter at zone R (raw), never at ROTATION_TO_SETTER_ZONE[R]', () => {
|
|
21
|
+
for (const system of Object.values(RotationSystemEnum)) {
|
|
22
|
+
if (system === RotationSystemEnum.SIX_ZERO)
|
|
23
|
+
continue; // 6-0 has no designated setter
|
|
24
|
+
const map = defaultReceiveMap(system);
|
|
25
|
+
for (const z of [2, 3, 5, 6]) { // the rotations where raw and the old index convention diverge
|
|
26
|
+
expect({ system, z, passes: map[String(z)]?.[String(z)] }).toEqual({ system, z, passes: false });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe('defaultBaseConfig base-config legality', () => {
|
|
32
|
+
it('has zero SERVE/RECEIVE overlap violations for every rotation system', () => {
|
|
33
|
+
for (const system of Object.values(RotationSystemEnum)) {
|
|
34
|
+
expect({ system, violations: baseConfigViolations(defaultBaseConfig(system)) }).toEqual({ system, violations: [] });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
// Regression (rush6@ tournament report, 2026-08-21): a partial RECEIVE config (some zones stored, one left unset)
|
|
39
|
+
// reads "out of rotation even in base" ONLY when the editor fills the unset zone from a coarse flat grid (all
|
|
40
|
+
// back-row zones at depth 6.5), which lands on a stored DEEP neighbour. Filling from the sim's per-rotation default
|
|
41
|
+
// (what the editor's coordOf now does, matching what the sim always did) keeps it legal.
|
|
42
|
+
describe('unset RECEIVE zone fallback (editor gap fill)', () => {
|
|
43
|
+
// The reported user's real rotation-2 RECEIVE: zone 3 sits abnormally deep at d 6.5; zone 6 is unset.
|
|
44
|
+
const partialRot2 = {
|
|
45
|
+
1: { d: 6.4, r: 3.15 }, 2: { d: 2.75, r: 1.65 }, 3: { d: 6.5, r: -2.65 }, 4: { d: 2.75, r: -2.75 }, 5: { d: 2.8, r: -3.05 }
|
|
46
|
+
};
|
|
47
|
+
const FLAT_GRID_ZONE6 = { d: 6.5, r: 0 }; // the editor's OLD blank-slate default for a back-row zone
|
|
48
|
+
const SIM_DEFAULT_ZONE6 = defaultBaseConfig(RotationSystemEnum.FIVE_ONE).coords.RECEIVE['2']['6']; // the fix's fallback
|
|
49
|
+
const violationsWithZone6 = (zone6) => baseConfigViolations({ coords: { RECEIVE: { 2: { ...partialRot2, 6: zone6 } } } });
|
|
50
|
+
it('collides (zones 3,6) when the gap is filled from the flat grid - the bug', () => {
|
|
51
|
+
expect(violationsWithZone6(FLAT_GRID_ZONE6).map(v => v.zones)).toEqual([[3, 6]]);
|
|
52
|
+
});
|
|
53
|
+
it('stays legal when the gap is filled from the sim per-rotation default - the fix', () => {
|
|
54
|
+
expect(violationsWithZone6(SIM_DEFAULT_ZONE6)).toEqual([]);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
5
57
|
// The trajectory-set default desired-contact (owner D9, 2026-08-12): a near-net hitting point in each attacker's
|
|
6
58
|
// lane, NOT the old set-to-the-standing-dot location. Front row contacts sit ~0.5 m off the net; back row on the
|
|
7
59
|
// ~1.8 m pipe line; the lateral is the ATTACK-dot's r clamped inside the antenna (|r| <= 4.3).
|