volleyballsimtypes 0.0.477 → 0.0.479

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 (63) hide show
  1. package/dist/cjs/src/service/index.d.ts +1 -0
  2. package/dist/cjs/src/service/index.js +1 -0
  3. package/dist/cjs/src/service/notification/catalog/en.json +41 -0
  4. package/dist/cjs/src/service/notification/catalog/es.json +41 -0
  5. package/dist/cjs/src/service/notification/catalog/fr.json +41 -0
  6. package/dist/cjs/src/service/notification/catalog/index.d.ts +3 -0
  7. package/dist/cjs/src/service/notification/catalog/index.js +22 -0
  8. package/dist/cjs/src/service/notification/catalog/it.json +41 -0
  9. package/dist/cjs/src/service/notification/catalog/pl.json +41 -0
  10. package/dist/cjs/src/service/notification/catalog/pt-BR.json +41 -0
  11. package/dist/cjs/src/service/notification/catalog/tr.json +41 -0
  12. package/dist/cjs/src/service/notification/index.d.ts +5 -0
  13. package/dist/cjs/src/service/notification/index.js +23 -0
  14. package/dist/cjs/src/service/notification/notification-type.d.ts +6 -0
  15. package/dist/cjs/src/service/notification/notification-type.js +30 -0
  16. package/dist/cjs/src/service/notification/notification.test.d.ts +1 -0
  17. package/dist/cjs/src/service/notification/notification.test.js +128 -0
  18. package/dist/cjs/src/service/notification/payloads.d.ts +34 -0
  19. package/dist/cjs/src/service/notification/payloads.js +5 -0
  20. package/dist/cjs/src/service/notification/registry.d.ts +13 -0
  21. package/dist/cjs/src/service/notification/registry.js +112 -0
  22. package/dist/cjs/src/service/notification/render.d.ts +10 -0
  23. package/dist/cjs/src/service/notification/render.js +64 -0
  24. package/dist/cjs/src/service/team/pinch-condition.d.ts +7 -0
  25. package/dist/cjs/src/service/team/pinch-condition.js +10 -1
  26. package/dist/cjs/src/service/team/schemas/designated-sub.z.d.ts +22 -1
  27. package/dist/cjs/src/service/team/schemas/designated-sub.z.js +5 -3
  28. package/dist/cjs/src/service/team/schemas/designated-sub.z.test.js +10 -0
  29. package/dist/cjs/src/service/team/schemas/libero-sub.z.d.ts +9 -0
  30. package/dist/cjs/src/service/team/schemas/tactics.z.d.ts +18 -0
  31. package/dist/cjs/src/service/team/schemas/team.z.d.ts +18 -0
  32. package/dist/esm/src/service/index.d.ts +1 -0
  33. package/dist/esm/src/service/index.js +1 -0
  34. package/dist/esm/src/service/notification/catalog/en.json +41 -0
  35. package/dist/esm/src/service/notification/catalog/es.json +41 -0
  36. package/dist/esm/src/service/notification/catalog/fr.json +41 -0
  37. package/dist/esm/src/service/notification/catalog/index.d.ts +3 -0
  38. package/dist/esm/src/service/notification/catalog/index.js +16 -0
  39. package/dist/esm/src/service/notification/catalog/it.json +41 -0
  40. package/dist/esm/src/service/notification/catalog/pl.json +41 -0
  41. package/dist/esm/src/service/notification/catalog/pt-BR.json +41 -0
  42. package/dist/esm/src/service/notification/catalog/tr.json +41 -0
  43. package/dist/esm/src/service/notification/index.d.ts +5 -0
  44. package/dist/esm/src/service/notification/index.js +5 -0
  45. package/dist/esm/src/service/notification/notification-type.d.ts +6 -0
  46. package/dist/esm/src/service/notification/notification-type.js +26 -0
  47. package/dist/esm/src/service/notification/notification.test.d.ts +1 -0
  48. package/dist/esm/src/service/notification/notification.test.js +126 -0
  49. package/dist/esm/src/service/notification/payloads.d.ts +34 -0
  50. package/dist/esm/src/service/notification/payloads.js +4 -0
  51. package/dist/esm/src/service/notification/registry.d.ts +13 -0
  52. package/dist/esm/src/service/notification/registry.js +109 -0
  53. package/dist/esm/src/service/notification/render.d.ts +10 -0
  54. package/dist/esm/src/service/notification/render.js +58 -0
  55. package/dist/esm/src/service/team/pinch-condition.d.ts +7 -0
  56. package/dist/esm/src/service/team/pinch-condition.js +9 -0
  57. package/dist/esm/src/service/team/schemas/designated-sub.z.d.ts +22 -1
  58. package/dist/esm/src/service/team/schemas/designated-sub.z.js +6 -4
  59. package/dist/esm/src/service/team/schemas/designated-sub.z.test.js +11 -1
  60. package/dist/esm/src/service/team/schemas/libero-sub.z.d.ts +9 -0
  61. package/dist/esm/src/service/team/schemas/tactics.z.d.ts +18 -0
  62. package/dist/esm/src/service/team/schemas/team.z.d.ts +18 -0
  63. package/package.json +6 -1
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NOTIFICATION_REGISTRY = void 0;
4
+ function readString(value) {
5
+ return typeof value === 'string' && value !== '' ? value : null;
6
+ }
7
+ function teamPath(payload) {
8
+ const teamId = readString(payload.teamId);
9
+ return teamId != null ? `/team/${encodeURIComponent(teamId)}` : '/';
10
+ }
11
+ // MATCH_RESULT copy is recipient-relative: `result` is WIN/LOSS from the recipient's view and `side` marks
12
+ // which team is theirs, so the OTHER team is the opponent. When side/names are missing, do not name a winner.
13
+ function matchOpponent(payload) {
14
+ const homeTeam = typeof payload.homeTeam === 'object' && payload.homeTeam != null ? payload.homeTeam : {};
15
+ const awayTeam = typeof payload.awayTeam === 'object' && payload.awayTeam != null ? payload.awayTeam : {};
16
+ const homeName = readString(homeTeam.name);
17
+ const awayName = readString(awayTeam.name);
18
+ if (payload.side === 'HOME')
19
+ return awayName;
20
+ if (payload.side === 'AWAY')
21
+ return homeName;
22
+ return null;
23
+ }
24
+ function injuredName(payload) {
25
+ // Matches the old Sim injuredPlayerName fallback so a name-less payload never renders a subjectless sentence.
26
+ return readString(payload.playerNickname) ?? readString(payload.playerName) ?? 'A player';
27
+ }
28
+ exports.NOTIFICATION_REGISTRY = {
29
+ MATCH_RESULT: {
30
+ emitsPush: true,
31
+ deepLink: (p) => {
32
+ const matchId = readString(p.matchId);
33
+ return matchId != null ? `/match/${encodeURIComponent(matchId)}` : '/';
34
+ },
35
+ pushTitleKey: 'matchResult.title',
36
+ pushBodyKey: (p) => {
37
+ const outcome = p.result === 'WIN' ? 'won' : 'lost';
38
+ const named = matchOpponent(p) != null ? 'Named' : 'Unnamed';
39
+ return `matchResult.${outcome}${named}`;
40
+ },
41
+ params: (p) => ({ opponent: matchOpponent(p) ?? '' }),
42
+ richRender: 'MATCH_RESULT',
43
+ catalogKeys: ['matchResult.title', 'matchResult.wonNamed', 'matchResult.wonUnnamed', 'matchResult.lostNamed', 'matchResult.lostUnnamed']
44
+ },
45
+ INJURY: {
46
+ emitsPush: true,
47
+ deepLink: () => '/infirmary',
48
+ pushTitleKey: 'injury.title',
49
+ pushBodyKey: 'injury.body',
50
+ inAppMessageKey: 'injury.body',
51
+ params: (p) => ({ name: injuredName(p) }),
52
+ catalogKeys: ['injury.title', 'injury.body']
53
+ },
54
+ INJURY_RECOVERED: {
55
+ emitsPush: true,
56
+ deepLink: teamPath,
57
+ pushTitleKey: 'injuryRecovered.title',
58
+ pushBodyKey: 'injuryRecovered.body',
59
+ inAppMessageKey: 'injuryRecovered.body',
60
+ params: (p) => ({ name: injuredName(p) }),
61
+ catalogKeys: ['injuryRecovered.title', 'injuryRecovered.body']
62
+ },
63
+ SEASON_END: {
64
+ emitsPush: true,
65
+ deepLink: (p) => {
66
+ const leagueId = readString(p.leagueId);
67
+ return leagueId != null ? `/league/${encodeURIComponent(leagueId)}` : '/league';
68
+ },
69
+ pushTitleKey: 'seasonEnd.title',
70
+ pushBodyKey: 'seasonEnd.body',
71
+ inAppMessageKey: 'seasonEnd.body',
72
+ catalogKeys: ['seasonEnd.title', 'seasonEnd.body']
73
+ },
74
+ GRANT_RECEIVED: {
75
+ emitsPush: true,
76
+ deepLink: () => '/recruit',
77
+ pushTitleKey: 'grant.title',
78
+ pushBodyKey: 'grant.body',
79
+ inAppMessageKey: 'grant.body',
80
+ catalogKeys: ['grant.title', 'grant.body']
81
+ },
82
+ PROMOTION: {
83
+ emitsPush: true,
84
+ deepLink: teamPath,
85
+ pushTitleKey: 'promotion.title',
86
+ pushBodyKey: 'promotion.body',
87
+ inAppMessageKey: 'promotion.body',
88
+ catalogKeys: ['promotion.title', 'promotion.body']
89
+ },
90
+ DAILY_LOGIN: {
91
+ emitsPush: true,
92
+ deepLink: () => '/recruit',
93
+ pushTitleKey: 'dailyLogin.title',
94
+ pushBodyKey: 'dailyLogin.body',
95
+ inAppMessageKey: 'dailyLogin.body',
96
+ catalogKeys: ['dailyLogin.title', 'dailyLogin.body']
97
+ },
98
+ WELCOME: {
99
+ emitsPush: true,
100
+ deepLink: () => '/recruit',
101
+ pushTitleKey: 'welcome.title',
102
+ pushBodyKey: 'welcome.body',
103
+ richRender: 'WELCOME',
104
+ catalogKeys: ['welcome.title', 'welcome.body']
105
+ },
106
+ // In-app only (no push); the UI keeps a bespoke renderer (amount formatting) and its own `compensation` label.
107
+ COMPENSATION: {
108
+ emitsPush: false,
109
+ richRender: 'COMPENSATION',
110
+ catalogKeys: []
111
+ }
112
+ };
@@ -0,0 +1,10 @@
1
+ import { type NotificationLocale } from './notification-type';
2
+ export interface RenderedPush {
3
+ title: string;
4
+ body: string;
5
+ data: Record<string, string>;
6
+ }
7
+ export declare function interpolate(template: string, params: Record<string, string>): string;
8
+ export declare function translateNotification(locale: NotificationLocale, key: string, params?: Record<string, string>): string;
9
+ export declare function renderPush(type: string, payload: Record<string, unknown>, locale: NotificationLocale): RenderedPush | undefined;
10
+ export declare function notificationPath(type: string, payload: Record<string, unknown>): string;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interpolate = interpolate;
4
+ exports.translateNotification = translateNotification;
5
+ exports.renderPush = renderPush;
6
+ exports.notificationPath = notificationPath;
7
+ const notification_type_1 = require("./notification-type");
8
+ const registry_1 = require("./registry");
9
+ const catalog_1 = require("./catalog");
10
+ function readNested(node, dotKey) {
11
+ let current = node;
12
+ for (const part of dotKey.split('.')) {
13
+ if (typeof current !== 'object' || current == null)
14
+ return undefined;
15
+ current = current[part];
16
+ }
17
+ return typeof current === 'string' ? current : undefined;
18
+ }
19
+ function lookupCatalog(locale, dotKey) {
20
+ return readNested(catalog_1.NOTIFICATION_CATALOG[locale], dotKey) ??
21
+ readNested(catalog_1.NOTIFICATION_CATALOG[notification_type_1.DEFAULT_NOTIFICATION_LOCALE], dotKey) ??
22
+ dotKey;
23
+ }
24
+ function resolveKey(resolver, payload) {
25
+ if (resolver == null)
26
+ return undefined;
27
+ return typeof resolver === 'function' ? resolver(payload) : resolver;
28
+ }
29
+ function interpolate(template, params) {
30
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => params[key] ?? '');
31
+ }
32
+ // Resolve one catalog key to a localized, interpolated string. Missing key/locale falls back to English,
33
+ // then to the raw key. Exposed so consumers can render notification copy off the shared catalog too.
34
+ function translateNotification(locale, key, params = {}) {
35
+ return interpolate(lookupCatalog(locale, key), params);
36
+ }
37
+ // Build the localized push payload for a notification. Returns undefined for in-app-only types (emitsPush
38
+ // false, e.g. COMPENSATION). Unknown/future types fall back to the generic copy and the root path, matching
39
+ // the previous hardcoded fallback. Callers pass the recipient's locale (normalizeNotificationLocale first).
40
+ function renderPush(type, payload, locale) {
41
+ const buildData = (path) => ({ type, payload: JSON.stringify(payload), path });
42
+ const descriptor = registry_1.NOTIFICATION_REGISTRY[type];
43
+ if (descriptor == null) {
44
+ return {
45
+ title: translateNotification(locale, 'generic.title'),
46
+ body: translateNotification(locale, 'generic.body'),
47
+ data: buildData('/')
48
+ };
49
+ }
50
+ if (!descriptor.emitsPush)
51
+ return undefined;
52
+ const params = descriptor.params?.(payload) ?? {};
53
+ const titleKey = resolveKey(descriptor.pushTitleKey, payload) ?? 'generic.title';
54
+ const bodyKey = resolveKey(descriptor.pushBodyKey, payload) ?? 'generic.body';
55
+ return {
56
+ title: translateNotification(locale, titleKey, params),
57
+ body: translateNotification(locale, bodyKey, params),
58
+ data: buildData(descriptor.deepLink?.(payload) ?? '/')
59
+ };
60
+ }
61
+ // Deep-link path for a type/payload, used for both the push data.path and the in-app click target.
62
+ function notificationPath(type, payload) {
63
+ return registry_1.NOTIFICATION_REGISTRY[type]?.deepLink?.(payload) ?? '/';
64
+ }
@@ -22,6 +22,10 @@ export declare enum ScoreDirection {
22
22
  TRAILING = "TRAILING",
23
23
  LEADING = "LEADING"
24
24
  }
25
+ export declare enum Comparison {
26
+ AT_LEAST = "AT_LEAST",
27
+ AT_MOST = "AT_MOST"
28
+ }
25
29
  export interface AsapCondition {
26
30
  readonly type: PinchConditionType.ASAP;
27
31
  }
@@ -38,6 +42,7 @@ export interface ScoreDiffCondition {
38
42
  readonly type: PinchConditionType.SCORE_DIFF;
39
43
  readonly direction: ScoreDirection;
40
44
  readonly points: number;
45
+ readonly comparison?: Comparison;
41
46
  }
42
47
  export interface AfterRotationsCondition {
43
48
  readonly type: PinchConditionType.AFTER_ROTATIONS;
@@ -50,10 +55,12 @@ export interface FromSetCondition {
50
55
  export interface MinOwnScoreCondition {
51
56
  readonly type: PinchConditionType.MIN_OWN_SCORE;
52
57
  readonly score: number;
58
+ readonly comparison?: Comparison;
53
59
  }
54
60
  export interface MinOpponentScoreCondition {
55
61
  readonly type: PinchConditionType.MIN_OPPONENT_SCORE;
56
62
  readonly score: number;
63
+ readonly comparison?: Comparison;
57
64
  }
58
65
  export interface PhaseCondition {
59
66
  readonly type: PinchConditionType.PHASE;
@@ -3,7 +3,7 @@
3
3
  // wins back the serve, out the moment the serve is lost). Each condition is evaluated against the live set
4
4
  // state; a pinch entry combines them with ALL (every condition must hold) or ANY (one is enough).
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ScoreDirection = exports.OpponentRelation = exports.MatchPhase = exports.PinchConditionType = void 0;
6
+ exports.Comparison = exports.ScoreDirection = exports.OpponentRelation = exports.MatchPhase = exports.PinchConditionType = void 0;
7
7
  var PinchConditionType;
8
8
  (function (PinchConditionType) {
9
9
  PinchConditionType["ASAP"] = "ASAP";
@@ -34,3 +34,12 @@ var ScoreDirection;
34
34
  ScoreDirection["TRAILING"] = "TRAILING";
35
35
  ScoreDirection["LEADING"] = "LEADING";
36
36
  })(ScoreDirection || (exports.ScoreDirection = ScoreDirection = {}));
37
+ // Comparison direction for a numeric-threshold condition (SCORE_DIFF / MIN_OWN_SCORE / MIN_OPPONENT_SCORE).
38
+ // AT_LEAST ("Or more", value >= threshold) is the default when absent, so every existing stored condition keeps
39
+ // its `>=` behavior. AT_MOST ("Or less", value <= threshold) lets a rule fire as a value SHRINKS (e.g. a sub-back
40
+ // once "Leading by 2 or less" holds, instead of the always-implied "Leading by 2 or more").
41
+ var Comparison;
42
+ (function (Comparison) {
43
+ Comparison["AT_LEAST"] = "AT_LEAST";
44
+ Comparison["AT_MOST"] = "AT_MOST";
45
+ })(Comparison || (exports.Comparison = Comparison = {}));
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { Player } from '../../player';
3
3
  import { EnergyBand } from '../energy-band';
4
- import { MatchPhase, OpponentRelation, PinchConditionType, ScoreDirection } from '../pinch-condition';
4
+ import { Comparison, MatchPhase, OpponentRelation, PinchConditionType, ScoreDirection } from '../pinch-condition';
5
5
  export declare const SubBandSchema: z.ZodUnion<readonly [z.ZodEnum<typeof EnergyBand>, z.ZodLiteral<"NEVER">]>;
6
6
  export declare const PinchConditionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
7
7
  type: z.ZodLiteral<PinchConditionType.ASAP>;
@@ -16,6 +16,7 @@ export declare const PinchConditionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
16
16
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
17
17
  direction: z.ZodEnum<typeof ScoreDirection>;
18
18
  points: z.ZodNumber;
19
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
19
20
  }, z.core.$strip>, z.ZodObject<{
20
21
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
21
22
  rotations: z.ZodNumber;
@@ -25,9 +26,11 @@ export declare const PinchConditionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
25
26
  }, z.core.$strip>, z.ZodObject<{
26
27
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
27
28
  score: z.ZodNumber;
29
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
28
30
  }, z.core.$strip>, z.ZodObject<{
29
31
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
30
32
  score: z.ZodNumber;
33
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
31
34
  }, z.core.$strip>, z.ZodObject<{
32
35
  type: z.ZodLiteral<PinchConditionType.PHASE>;
33
36
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -64,6 +67,7 @@ export declare const SetSubConfigSchema: z.ZodObject<{
64
67
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
65
68
  direction: z.ZodEnum<typeof ScoreDirection>;
66
69
  points: z.ZodNumber;
70
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
67
71
  }, z.core.$strip>, z.ZodObject<{
68
72
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
69
73
  rotations: z.ZodNumber;
@@ -73,9 +77,11 @@ export declare const SetSubConfigSchema: z.ZodObject<{
73
77
  }, z.core.$strip>, z.ZodObject<{
74
78
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
75
79
  score: z.ZodNumber;
80
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
76
81
  }, z.core.$strip>, z.ZodObject<{
77
82
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
78
83
  score: z.ZodNumber;
84
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
79
85
  }, z.core.$strip>, z.ZodObject<{
80
86
  type: z.ZodLiteral<PinchConditionType.PHASE>;
81
87
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -99,6 +105,7 @@ export declare const SetSubConfigSchema: z.ZodObject<{
99
105
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
100
106
  direction: z.ZodEnum<typeof ScoreDirection>;
101
107
  points: z.ZodNumber;
108
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
102
109
  }, z.core.$strip>, z.ZodObject<{
103
110
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
104
111
  rotations: z.ZodNumber;
@@ -108,9 +115,11 @@ export declare const SetSubConfigSchema: z.ZodObject<{
108
115
  }, z.core.$strip>, z.ZodObject<{
109
116
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
110
117
  score: z.ZodNumber;
118
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
111
119
  }, z.core.$strip>, z.ZodObject<{
112
120
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
113
121
  score: z.ZodNumber;
122
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
114
123
  }, z.core.$strip>, z.ZodObject<{
115
124
  type: z.ZodLiteral<PinchConditionType.PHASE>;
116
125
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -140,6 +149,7 @@ export declare const DesignatedSubSchema: z.ZodObject<{
140
149
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
141
150
  direction: z.ZodEnum<typeof ScoreDirection>;
142
151
  points: z.ZodNumber;
152
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
143
153
  }, z.core.$strip>, z.ZodObject<{
144
154
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
145
155
  rotations: z.ZodNumber;
@@ -149,9 +159,11 @@ export declare const DesignatedSubSchema: z.ZodObject<{
149
159
  }, z.core.$strip>, z.ZodObject<{
150
160
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
151
161
  score: z.ZodNumber;
162
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
152
163
  }, z.core.$strip>, z.ZodObject<{
153
164
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
154
165
  score: z.ZodNumber;
166
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
155
167
  }, z.core.$strip>, z.ZodObject<{
156
168
  type: z.ZodLiteral<PinchConditionType.PHASE>;
157
169
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -175,6 +187,7 @@ export declare const DesignatedSubSchema: z.ZodObject<{
175
187
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
176
188
  direction: z.ZodEnum<typeof ScoreDirection>;
177
189
  points: z.ZodNumber;
190
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
178
191
  }, z.core.$strip>, z.ZodObject<{
179
192
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
180
193
  rotations: z.ZodNumber;
@@ -184,9 +197,11 @@ export declare const DesignatedSubSchema: z.ZodObject<{
184
197
  }, z.core.$strip>, z.ZodObject<{
185
198
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
186
199
  score: z.ZodNumber;
200
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
187
201
  }, z.core.$strip>, z.ZodObject<{
188
202
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
189
203
  score: z.ZodNumber;
204
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
190
205
  }, z.core.$strip>, z.ZodObject<{
191
206
  type: z.ZodLiteral<PinchConditionType.PHASE>;
192
207
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -214,6 +229,7 @@ export declare const DesignatedSubSchema: z.ZodObject<{
214
229
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
215
230
  direction: z.ZodEnum<typeof ScoreDirection>;
216
231
  points: z.ZodNumber;
232
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
217
233
  }, z.core.$strip>, z.ZodObject<{
218
234
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
219
235
  rotations: z.ZodNumber;
@@ -223,9 +239,11 @@ export declare const DesignatedSubSchema: z.ZodObject<{
223
239
  }, z.core.$strip>, z.ZodObject<{
224
240
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
225
241
  score: z.ZodNumber;
242
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
226
243
  }, z.core.$strip>, z.ZodObject<{
227
244
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
228
245
  score: z.ZodNumber;
246
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
229
247
  }, z.core.$strip>, z.ZodObject<{
230
248
  type: z.ZodLiteral<PinchConditionType.PHASE>;
231
249
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -249,6 +267,7 @@ export declare const DesignatedSubSchema: z.ZodObject<{
249
267
  type: z.ZodLiteral<PinchConditionType.SCORE_DIFF>;
250
268
  direction: z.ZodEnum<typeof ScoreDirection>;
251
269
  points: z.ZodNumber;
270
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
252
271
  }, z.core.$strip>, z.ZodObject<{
253
272
  type: z.ZodLiteral<PinchConditionType.AFTER_ROTATIONS>;
254
273
  rotations: z.ZodNumber;
@@ -258,9 +277,11 @@ export declare const DesignatedSubSchema: z.ZodObject<{
258
277
  }, z.core.$strip>, z.ZodObject<{
259
278
  type: z.ZodLiteral<PinchConditionType.MIN_OWN_SCORE>;
260
279
  score: z.ZodNumber;
280
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
261
281
  }, z.core.$strip>, z.ZodObject<{
262
282
  type: z.ZodLiteral<PinchConditionType.MIN_OPPONENT_SCORE>;
263
283
  score: z.ZodNumber;
284
+ comparison: z.ZodOptional<z.ZodEnum<typeof Comparison>>;
264
285
  }, z.core.$strip>, z.ZodObject<{
265
286
  type: z.ZodLiteral<PinchConditionType.PHASE>;
266
287
  phase: z.ZodEnum<typeof MatchPhase>;
@@ -13,11 +13,13 @@ exports.PinchConditionSchema = zod_1.z.discriminatedUnion('type', [
13
13
  zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.ASAP) }),
14
14
  zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.TEAM_SET_POINT), margin: zod_1.z.number().int().min(1).max(25), opponent: zod_1.z.nativeEnum(pinch_condition_1.OpponentRelation) }),
15
15
  zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.OPPONENT_SET_POINT), margin: zod_1.z.number().int().min(1).max(25) }),
16
- zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.SCORE_DIFF), direction: zod_1.z.nativeEnum(pinch_condition_1.ScoreDirection), points: zod_1.z.number().int().min(1).max(25) }),
16
+ // SCORE_DIFF / MIN_OWN_SCORE / MIN_OPPONENT_SCORE carry an optional comparison direction ("Or more" AT_LEAST,
17
+ // the default; "Or less" AT_MOST). Absent = AT_LEAST so existing conditions keep their `>=` behavior.
18
+ zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.SCORE_DIFF), direction: zod_1.z.nativeEnum(pinch_condition_1.ScoreDirection), points: zod_1.z.number().int().min(1).max(25), comparison: zod_1.z.nativeEnum(pinch_condition_1.Comparison).optional() }),
17
19
  zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.AFTER_ROTATIONS), rotations: zod_1.z.number().int().min(1).max(6) }),
18
20
  zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.FROM_SET), set: zod_1.z.number().int().min(1).max(5) }),
19
- zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.MIN_OWN_SCORE), score: zod_1.z.number().int().min(0).max(40) }),
20
- zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.MIN_OPPONENT_SCORE), score: zod_1.z.number().int().min(0).max(40) }),
21
+ zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.MIN_OWN_SCORE), score: zod_1.z.number().int().min(0).max(40), comparison: zod_1.z.nativeEnum(pinch_condition_1.Comparison).optional() }),
22
+ zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.MIN_OPPONENT_SCORE), score: zod_1.z.number().int().min(0).max(40), comparison: zod_1.z.nativeEnum(pinch_condition_1.Comparison).optional() }),
21
23
  // PHASE is used by the libero deployment rule (which reuses this schema); pinch servers never offer it.
22
24
  zod_1.z.object({ type: zod_1.z.literal(pinch_condition_1.PinchConditionType.PHASE), phase: zod_1.z.nativeEnum(pinch_condition_1.MatchPhase) })
23
25
  ]);
@@ -59,6 +59,16 @@ const test_helpers_1 = require("../../test-helpers");
59
59
  (0, globals_1.it)('rejects a non-integer numeric field', () => {
60
60
  (0, globals_1.expect)(designated_sub_z_1.PinchConditionSchema.safeParse({ type: pinch_condition_1.PinchConditionType.FROM_SET, set: 2.5 }).success).toBe(false);
61
61
  });
62
+ (0, globals_1.it)('accepts an optional comparison (Or more / Or less) on the numeric-threshold conditions', () => {
63
+ (0, globals_1.expect)(designated_sub_z_1.PinchConditionSchema.safeParse({ type: pinch_condition_1.PinchConditionType.SCORE_DIFF, direction: pinch_condition_1.ScoreDirection.LEADING, points: 2, comparison: pinch_condition_1.Comparison.AT_MOST }).success).toBe(true);
64
+ (0, globals_1.expect)(designated_sub_z_1.PinchConditionSchema.safeParse({ type: pinch_condition_1.PinchConditionType.MIN_OWN_SCORE, score: 20, comparison: pinch_condition_1.Comparison.AT_MOST }).success).toBe(true);
65
+ (0, globals_1.expect)(designated_sub_z_1.PinchConditionSchema.safeParse({ type: pinch_condition_1.PinchConditionType.MIN_OPPONENT_SCORE, score: 20, comparison: pinch_condition_1.Comparison.AT_LEAST }).success).toBe(true);
66
+ // absent comparison stays valid (defaults to AT_LEAST at eval time)
67
+ (0, globals_1.expect)(designated_sub_z_1.PinchConditionSchema.safeParse({ type: pinch_condition_1.PinchConditionType.SCORE_DIFF, direction: pinch_condition_1.ScoreDirection.LEADING, points: 2 }).success).toBe(true);
68
+ });
69
+ (0, globals_1.it)('rejects an invalid comparison value', () => {
70
+ (0, globals_1.expect)(designated_sub_z_1.PinchConditionSchema.safeParse({ type: pinch_condition_1.PinchConditionType.MIN_OWN_SCORE, score: 20, comparison: 'EXACTLY' }).success).toBe(false);
71
+ });
62
72
  });
63
73
  (0, globals_1.describe)('DesignatedSubSchema', () => {
64
74
  const country = (0, test_helpers_1.makeCountry)();
@@ -27,6 +27,7 @@ export declare const LiberoSetSubConfigSchema: z.ZodObject<{
27
27
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
28
28
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
29
29
  points: z.ZodNumber;
30
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
30
31
  }, z.core.$strip>, z.ZodObject<{
31
32
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
32
33
  rotations: z.ZodNumber;
@@ -36,9 +37,11 @@ export declare const LiberoSetSubConfigSchema: z.ZodObject<{
36
37
  }, z.core.$strip>, z.ZodObject<{
37
38
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
38
39
  score: z.ZodNumber;
40
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
39
41
  }, z.core.$strip>, z.ZodObject<{
40
42
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
41
43
  score: z.ZodNumber;
44
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
42
45
  }, z.core.$strip>, z.ZodObject<{
43
46
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
44
47
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -67,6 +70,7 @@ export declare const LiberoSubConfigSchema: z.ZodObject<{
67
70
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
68
71
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
69
72
  points: z.ZodNumber;
73
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
70
74
  }, z.core.$strip>, z.ZodObject<{
71
75
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
72
76
  rotations: z.ZodNumber;
@@ -76,9 +80,11 @@ export declare const LiberoSubConfigSchema: z.ZodObject<{
76
80
  }, z.core.$strip>, z.ZodObject<{
77
81
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
78
82
  score: z.ZodNumber;
83
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
79
84
  }, z.core.$strip>, z.ZodObject<{
80
85
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
81
86
  score: z.ZodNumber;
87
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
82
88
  }, z.core.$strip>, z.ZodObject<{
83
89
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
84
90
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -105,6 +111,7 @@ export declare const LiberoSubConfigSchema: z.ZodObject<{
105
111
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
106
112
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
107
113
  points: z.ZodNumber;
114
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
108
115
  }, z.core.$strip>, z.ZodObject<{
109
116
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
110
117
  rotations: z.ZodNumber;
@@ -114,9 +121,11 @@ export declare const LiberoSubConfigSchema: z.ZodObject<{
114
121
  }, z.core.$strip>, z.ZodObject<{
115
122
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
116
123
  score: z.ZodNumber;
124
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
117
125
  }, z.core.$strip>, z.ZodObject<{
118
126
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
119
127
  score: z.ZodNumber;
128
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
120
129
  }, z.core.$strip>, z.ZodObject<{
121
130
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
122
131
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -38,6 +38,7 @@ export declare const TacticsInputSchema: z.ZodObject<{
38
38
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
39
39
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
40
40
  points: z.ZodNumber;
41
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
41
42
  }, z.core.$strip>, z.ZodObject<{
42
43
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
43
44
  rotations: z.ZodNumber;
@@ -47,9 +48,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
47
48
  }, z.core.$strip>, z.ZodObject<{
48
49
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
49
50
  score: z.ZodNumber;
51
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
50
52
  }, z.core.$strip>, z.ZodObject<{
51
53
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
52
54
  score: z.ZodNumber;
55
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
53
56
  }, z.core.$strip>, z.ZodObject<{
54
57
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
55
58
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -73,6 +76,7 @@ export declare const TacticsInputSchema: z.ZodObject<{
73
76
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
74
77
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
75
78
  points: z.ZodNumber;
79
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
76
80
  }, z.core.$strip>, z.ZodObject<{
77
81
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
78
82
  rotations: z.ZodNumber;
@@ -82,9 +86,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
82
86
  }, z.core.$strip>, z.ZodObject<{
83
87
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
84
88
  score: z.ZodNumber;
89
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
85
90
  }, z.core.$strip>, z.ZodObject<{
86
91
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
87
92
  score: z.ZodNumber;
93
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
88
94
  }, z.core.$strip>, z.ZodObject<{
89
95
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
90
96
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -112,6 +118,7 @@ export declare const TacticsInputSchema: z.ZodObject<{
112
118
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
113
119
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
114
120
  points: z.ZodNumber;
121
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
115
122
  }, z.core.$strip>, z.ZodObject<{
116
123
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
117
124
  rotations: z.ZodNumber;
@@ -121,9 +128,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
121
128
  }, z.core.$strip>, z.ZodObject<{
122
129
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
123
130
  score: z.ZodNumber;
131
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
124
132
  }, z.core.$strip>, z.ZodObject<{
125
133
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
126
134
  score: z.ZodNumber;
135
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
127
136
  }, z.core.$strip>, z.ZodObject<{
128
137
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
129
138
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -147,6 +156,7 @@ export declare const TacticsInputSchema: z.ZodObject<{
147
156
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
148
157
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
149
158
  points: z.ZodNumber;
159
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
150
160
  }, z.core.$strip>, z.ZodObject<{
151
161
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
152
162
  rotations: z.ZodNumber;
@@ -156,9 +166,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
156
166
  }, z.core.$strip>, z.ZodObject<{
157
167
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
158
168
  score: z.ZodNumber;
169
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
159
170
  }, z.core.$strip>, z.ZodObject<{
160
171
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
161
172
  score: z.ZodNumber;
173
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
162
174
  }, z.core.$strip>, z.ZodObject<{
163
175
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
164
176
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -190,6 +202,7 @@ export declare const TacticsInputSchema: z.ZodObject<{
190
202
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
191
203
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
192
204
  points: z.ZodNumber;
205
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
193
206
  }, z.core.$strip>, z.ZodObject<{
194
207
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
195
208
  rotations: z.ZodNumber;
@@ -199,9 +212,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
199
212
  }, z.core.$strip>, z.ZodObject<{
200
213
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
201
214
  score: z.ZodNumber;
215
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
202
216
  }, z.core.$strip>, z.ZodObject<{
203
217
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
204
218
  score: z.ZodNumber;
219
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
205
220
  }, z.core.$strip>, z.ZodObject<{
206
221
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
207
222
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
@@ -228,6 +243,7 @@ export declare const TacticsInputSchema: z.ZodObject<{
228
243
  type: z.ZodLiteral<import("..").PinchConditionType.SCORE_DIFF>;
229
244
  direction: z.ZodEnum<typeof import("..").ScoreDirection>;
230
245
  points: z.ZodNumber;
246
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
231
247
  }, z.core.$strip>, z.ZodObject<{
232
248
  type: z.ZodLiteral<import("..").PinchConditionType.AFTER_ROTATIONS>;
233
249
  rotations: z.ZodNumber;
@@ -237,9 +253,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
237
253
  }, z.core.$strip>, z.ZodObject<{
238
254
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OWN_SCORE>;
239
255
  score: z.ZodNumber;
256
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
240
257
  }, z.core.$strip>, z.ZodObject<{
241
258
  type: z.ZodLiteral<import("..").PinchConditionType.MIN_OPPONENT_SCORE>;
242
259
  score: z.ZodNumber;
260
+ comparison: z.ZodOptional<z.ZodEnum<typeof import("..").Comparison>>;
243
261
  }, z.core.$strip>, z.ZodObject<{
244
262
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
245
263
  phase: z.ZodEnum<typeof import("..").MatchPhase>;