@voltro/plugin-leaderboards 0.0.0-stage → 0.88.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.
- package/CHANGELOG.md +24492 -0
- package/LICENSE +61 -0
- package/README.md +1087 -2
- package/SECURITY.md +56 -0
- package/THIRD-PARTY-NOTICES.md +5603 -0
- package/dist/administration.js +4 -0
- package/dist/bracketAdmission.js +293 -0
- package/dist/bracketAdmissionPolicy.js +21 -0
- package/dist/bracketInstallation.js +132 -0
- package/dist/bracketMatchPorts.js +4 -0
- package/dist/bracketMatches.js +545 -0
- package/dist/brackets.d.ts +149 -0
- package/dist/brackets.js +378 -0
- package/dist/bucketStore.js +92 -0
- package/dist/buckets.js +8 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +16 -0
- package/dist/glicko2.js +71 -0
- package/dist/index.d.ts +1208 -0
- package/dist/index.js +15 -0
- package/dist/inspect.js +83 -0
- package/dist/json.js +38 -0
- package/dist/leaderboard.d.ts +49 -0
- package/dist/leaderboard.js +56 -0
- package/dist/leagueSchedule.js +39 -0
- package/dist/leagues.js +30 -0
- package/dist/openskill.js +73 -0
- package/dist/plugin.js +337 -0
- package/dist/portLifetime.js +66 -0
- package/dist/ports.d.ts +294 -0
- package/dist/ports.js +6 -0
- package/dist/rankQuery.js +23 -0
- package/dist/ranking.d.ts +42 -0
- package/dist/ranking.js +70 -0
- package/dist/rating.d.ts +103 -0
- package/dist/rating.js +49 -0
- package/dist/ratingPools.js +133 -0
- package/dist/ratingStore.js +333 -0
- package/dist/ratingStrategies.js +107 -0
- package/dist/records.d.ts +116 -0
- package/dist/records.js +87 -0
- package/dist/rpc.d.ts +321 -0
- package/dist/rpc.js +305 -0
- package/dist/score.d.ts +13 -0
- package/dist/score.js +26 -0
- package/dist/server.d.ts +1477 -0
- package/dist/server.js +17 -0
- package/dist/service.js +948 -0
- package/dist/subjectFences.js +43 -0
- package/dist/tables.entity.js +187 -0
- package/dist/testing.d.ts +872 -0
- package/dist/testing.js +367 -0
- package/dist/tournament-app/tournament.advance.workflow.server.tsx +3 -0
- package/dist/tournament-app/tournament.advance.workflow.tsx +12 -0
- package/dist/tournament-app/tournament.stage.workflow.server.tsx +3 -0
- package/dist/tournament-app/tournament.stage.workflow.tsx +10 -0
- package/dist/tournamentInstallation.js +167 -0
- package/dist/tournamentPrizes.js +33 -0
- package/dist/tournamentStage.js +150 -0
- package/dist/tournamentStagePorts.js +4 -0
- package/dist/tournamentWorkflow.js +100 -0
- package/dist/tournamentWorkflowSchemas.js +53 -0
- package/dist/tournaments.d.ts +32 -0
- package/dist/tournaments.js +20 -0
- package/dist/web.d.ts +175 -0
- package/dist/web.js +16 -0
- package/package.json +113 -4
|
@@ -0,0 +1,872 @@
|
|
|
1
|
+
import { Context } from 'effect';
|
|
2
|
+
import { DataStore } from '@voltro/database';
|
|
3
|
+
import { Effect } from 'effect';
|
|
4
|
+
import { Layer } from 'effect';
|
|
5
|
+
import { PluginPrivacyRequest } from '@voltro/protocol';
|
|
6
|
+
import { Schema } from 'effect';
|
|
7
|
+
import { Subject } from '@voltro/protocol';
|
|
8
|
+
import { YieldableError } from 'effect/Cause';
|
|
9
|
+
|
|
10
|
+
declare interface AdmissionState {
|
|
11
|
+
readonly version: 1;
|
|
12
|
+
readonly definition: BracketAdmissionDefinition;
|
|
13
|
+
readonly phase: 'open' | 'sealed' | 'erasing' | 'cancelled';
|
|
14
|
+
readonly entries: ReadonlyArray<BracketAdmissionEntry>;
|
|
15
|
+
readonly eraseRequest: string | null;
|
|
16
|
+
readonly eraseTarget: string | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare interface BracketAdmissionDefinition {
|
|
20
|
+
readonly registrationOpensAt: number;
|
|
21
|
+
readonly registrationClosesAt: number;
|
|
22
|
+
readonly checkInOpensAt: number;
|
|
23
|
+
readonly checkInClosesAt: number;
|
|
24
|
+
readonly maxEntries: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare interface BracketAdmissionEntrants {
|
|
28
|
+
readonly phase: AdmissionState['phase'];
|
|
29
|
+
readonly entries: ReadonlyArray<BracketAdmissionEntry>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare interface BracketAdmissionEntry {
|
|
33
|
+
readonly ownerId: string;
|
|
34
|
+
readonly joinedAt: number;
|
|
35
|
+
readonly checkedInAt: number | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare interface BracketAdmissionExport extends BracketAdmissionEntry {
|
|
39
|
+
readonly tournamentId: string;
|
|
40
|
+
readonly phase: BracketAdmissionStatus['phase'];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export declare const bracketAdmissionFakeLayer: (overrides?: Partial<BracketAdmissionService>) => Layer.Layer<BracketAdmissionPort>;
|
|
44
|
+
|
|
45
|
+
/** Browser-safe Tag; consumers depend on admission, never a SQL adapter. */
|
|
46
|
+
declare class BracketAdmissionPort extends BracketAdmissionPort_base {
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
declare const BracketAdmissionPort_base: Context.ServiceClass<BracketAdmissionPort, "@voltro/BracketAdmissionPort", {
|
|
50
|
+
create(subject: Subject, scope: BracketAdmissionScope, definition: BracketAdmissionDefinition): Effect.Effect<void, LeaderboardError>;
|
|
51
|
+
register(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionStatus, LeaderboardError>;
|
|
52
|
+
checkIn(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionStatus, LeaderboardError>;
|
|
53
|
+
status(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionStatus, LeaderboardError>;
|
|
54
|
+
seal(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionRoster, LeaderboardError>;
|
|
55
|
+
/** Trusted read of every registration with its check-in, for notifications. */
|
|
56
|
+
entrants(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionEntrants, LeaderboardError>;
|
|
57
|
+
exportSubject(request: PluginPrivacyRequest): Effect.Effect<ReadonlyArray<BracketAdmissionExport>, LeaderboardError>;
|
|
58
|
+
eraseSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
59
|
+
}>;
|
|
60
|
+
|
|
61
|
+
export declare const bracketAdmissionPortFixture: () => {
|
|
62
|
+
kind: "port";
|
|
63
|
+
tag: typeof BracketAdmissionPort;
|
|
64
|
+
fakeLayer: Layer.Layer<BracketAdmissionPort, never, never>;
|
|
65
|
+
probe: {
|
|
66
|
+
run: () => Promise<"invalid_board" | "invalid_score" | "invalid_record" | "invalid_input" | "overflow" | "unavailable" | "forbidden" | "not_found" | "conflict" | "erased" | "limit_exceeded" | "unexpected-success">;
|
|
67
|
+
expected: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export declare const bracketAdmissionPortSystemFixture: Readonly<{
|
|
72
|
+
kind: "port";
|
|
73
|
+
tag: typeof BracketAdmissionPort;
|
|
74
|
+
fakeLayer: Layer.Layer<BracketAdmissionPort, never, never>;
|
|
75
|
+
probe: {
|
|
76
|
+
run: () => Effect.Effect<string, never, never>;
|
|
77
|
+
expected: string;
|
|
78
|
+
};
|
|
79
|
+
}>;
|
|
80
|
+
|
|
81
|
+
declare interface BracketAdmissionRoster {
|
|
82
|
+
readonly checkedIn: ReadonlyArray<string>;
|
|
83
|
+
readonly noShows: ReadonlyArray<string>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
declare interface BracketAdmissionScope {
|
|
87
|
+
readonly tenantId: string;
|
|
88
|
+
readonly tournamentId: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
declare type BracketAdmissionService = Context.Service.Shape<typeof BracketAdmissionPort>;
|
|
92
|
+
|
|
93
|
+
declare interface BracketAdmissionStatus {
|
|
94
|
+
readonly phase: AdmissionState['phase'];
|
|
95
|
+
readonly entries: number;
|
|
96
|
+
readonly checkedIn: number;
|
|
97
|
+
readonly own: BracketAdmissionEntry | null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export declare const bracketAdmissionSystemFakeLayer: Layer.Layer<BracketAdmissionPort, never, never>;
|
|
101
|
+
|
|
102
|
+
declare interface BracketMatchObservation {
|
|
103
|
+
readonly id: string;
|
|
104
|
+
readonly round: number;
|
|
105
|
+
readonly left: string | null;
|
|
106
|
+
readonly right: string | null;
|
|
107
|
+
readonly status: 'pending' | 'ready' | 'walkover' | 'complete';
|
|
108
|
+
readonly winnerId: string | null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
declare interface BracketProgress {
|
|
112
|
+
readonly matches: ReadonlyArray<BracketMatchObservation>;
|
|
113
|
+
readonly champion: string | null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
declare interface BracketResult {
|
|
117
|
+
readonly matchId: string;
|
|
118
|
+
readonly winnerId: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
declare type BracketSlot = {
|
|
122
|
+
readonly kind: 'entrant';
|
|
123
|
+
readonly entrantId: string;
|
|
124
|
+
} | {
|
|
125
|
+
readonly kind: 'winner';
|
|
126
|
+
readonly matchId: string;
|
|
127
|
+
} | {
|
|
128
|
+
readonly kind: 'bye';
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
declare interface BracketState extends TournamentBracketDefinition {
|
|
132
|
+
readonly version: 1;
|
|
133
|
+
readonly phase: 'active' | 'paused' | 'complete' | 'erasing' | 'cancelled';
|
|
134
|
+
readonly withdrawn: boolean;
|
|
135
|
+
readonly provisions: ReadonlyArray<Provision>;
|
|
136
|
+
readonly results: ReadonlyArray<Result>;
|
|
137
|
+
readonly disputes: ReadonlyArray<Dispute>;
|
|
138
|
+
readonly settlement: {
|
|
139
|
+
readonly requestId: string;
|
|
140
|
+
readonly winnerId: string;
|
|
141
|
+
readonly complete: boolean;
|
|
142
|
+
} | null;
|
|
143
|
+
readonly erase: {
|
|
144
|
+
readonly requestId: string;
|
|
145
|
+
readonly targetDigest: string;
|
|
146
|
+
} | null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export declare const bucketAssignSystemFixture: Readonly<{
|
|
150
|
+
kind: "slot";
|
|
151
|
+
defaultImplementation: LeaderboardBucketAssign;
|
|
152
|
+
defaultProbe: {
|
|
153
|
+
run: () => Effect.Effect<string, never, never>;
|
|
154
|
+
expected: string;
|
|
155
|
+
};
|
|
156
|
+
overrideProbe: {
|
|
157
|
+
run: () => Effect.Effect<string, never, never>;
|
|
158
|
+
expected: string;
|
|
159
|
+
};
|
|
160
|
+
}>;
|
|
161
|
+
|
|
162
|
+
declare const defaultLeaderboardBucketAssign: LeaderboardBucketAssign;
|
|
163
|
+
|
|
164
|
+
declare const defaultLeaderboardRankQuery: LeaderboardRankQuery;
|
|
165
|
+
|
|
166
|
+
/** Decay is applied on fresh participated match application, never on a read or
|
|
167
|
+
* retry. The default preserves the exact prior; no periodic decay job exists. */
|
|
168
|
+
declare const defaultRatingDecay: RatingDecayPolicy;
|
|
169
|
+
|
|
170
|
+
declare const defaultRatingPlacement: RatingPlacementPolicy;
|
|
171
|
+
|
|
172
|
+
declare const defaultRatingRate: RatingRateStrategy;
|
|
173
|
+
|
|
174
|
+
declare interface Dispute extends TournamentDisputeIntent {
|
|
175
|
+
readonly ownerId: string;
|
|
176
|
+
readonly resolutionId: string | null;
|
|
177
|
+
readonly winnerId: string | null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
declare interface DoubleEliminationBracket {
|
|
181
|
+
readonly format: 'double-elimination';
|
|
182
|
+
readonly version: 1;
|
|
183
|
+
readonly entrants: ReadonlyArray<TournamentEntrant>;
|
|
184
|
+
readonly matches: ReadonlyArray<DoubleEliminationMatch>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
declare interface DoubleEliminationMatch {
|
|
188
|
+
readonly id: string;
|
|
189
|
+
readonly stage: 'winners' | 'losers' | 'final' | 'reset';
|
|
190
|
+
readonly round: number;
|
|
191
|
+
readonly left: DoubleEliminationSlot;
|
|
192
|
+
readonly right: DoubleEliminationSlot;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
declare interface DoubleEliminationObservation extends Omit<BracketMatchObservation, 'status'> {
|
|
196
|
+
readonly stage: DoubleEliminationMatch['stage'];
|
|
197
|
+
readonly status: BracketMatchObservation['status'] | 'empty' | 'inactive';
|
|
198
|
+
readonly loserId: string | null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
declare interface DoubleEliminationProgress {
|
|
202
|
+
readonly matches: ReadonlyArray<DoubleEliminationObservation>;
|
|
203
|
+
readonly champion: string | null;
|
|
204
|
+
readonly losses: ReadonlyArray<{
|
|
205
|
+
readonly entrantId: string;
|
|
206
|
+
readonly losses: number;
|
|
207
|
+
}>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
declare type DoubleEliminationSlot = BracketSlot | {
|
|
211
|
+
readonly kind: 'loser';
|
|
212
|
+
readonly matchId: string;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export declare const eloFixture: () => {
|
|
216
|
+
rate: EloRate;
|
|
217
|
+
input: {
|
|
218
|
+
teams: {
|
|
219
|
+
id: string;
|
|
220
|
+
rating: number;
|
|
221
|
+
}[][];
|
|
222
|
+
ranks: number[];
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
declare interface EloInput {
|
|
227
|
+
readonly teams: ReadonlyArray<ReadonlyArray<EloPlayer>>;
|
|
228
|
+
readonly ranks: ReadonlyArray<number>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
declare interface EloOptions {
|
|
232
|
+
readonly k?: number;
|
|
233
|
+
readonly scale?: number;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
declare interface EloPlayer {
|
|
237
|
+
readonly id: string;
|
|
238
|
+
readonly rating: number;
|
|
239
|
+
readonly weight?: number;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
declare type EloRate = (input: EloInput) => ReadonlyArray<ReadonlyArray<EloResult>>;
|
|
243
|
+
|
|
244
|
+
declare interface EloResult {
|
|
245
|
+
readonly id: string;
|
|
246
|
+
readonly previous: number;
|
|
247
|
+
readonly rating: number;
|
|
248
|
+
readonly delta: number;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Explicit replacements may override methods; every omitted method refuses. */
|
|
252
|
+
export declare const fakeBracketAdmissionService: (overrides?: Partial<BracketAdmissionService>) => BracketAdmissionService;
|
|
253
|
+
|
|
254
|
+
export declare const fakeTournamentBracketService: (overrides?: Partial<TournamentBracketService>) => TournamentBracketService;
|
|
255
|
+
|
|
256
|
+
export declare const fakeTournamentStageService: (overrides?: Partial<TournamentStageService>) => TournamentStageService;
|
|
257
|
+
|
|
258
|
+
declare interface Glicko2Options {
|
|
259
|
+
readonly tau?: number;
|
|
260
|
+
readonly epsilon?: number;
|
|
261
|
+
readonly maxIterations?: number;
|
|
262
|
+
readonly maxOpponents?: number;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Choose one actual capacity-admitted candidate. Grouping/SQL writer admission,
|
|
266
|
+
* membership and capacity stay inside the adapter. */
|
|
267
|
+
declare type LeaderboardBucketAssign = (context: LeaderboardBucketContext) => string;
|
|
268
|
+
|
|
269
|
+
export declare const leaderboardBucketAssignFixture: () => {
|
|
270
|
+
readonly bucketAssign: typeof defaultLeaderboardBucketAssign;
|
|
271
|
+
readonly context: LeaderboardBucketContext;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
declare interface LeaderboardBucketCandidate {
|
|
275
|
+
readonly id: string;
|
|
276
|
+
readonly ordinal: number;
|
|
277
|
+
readonly entries: number;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
declare interface LeaderboardBucketContext {
|
|
281
|
+
readonly tenantId: string;
|
|
282
|
+
readonly board: string;
|
|
283
|
+
readonly periodId: string;
|
|
284
|
+
readonly ownerId: string;
|
|
285
|
+
readonly assign: 'hash' | 'skill' | 'cohort';
|
|
286
|
+
readonly size: number;
|
|
287
|
+
readonly group: string | null;
|
|
288
|
+
readonly candidates: ReadonlyArray<LeaderboardBucketCandidate>;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
declare class LeaderboardError extends LeaderboardError_base {
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
declare const LeaderboardError_base: Schema.Class<LeaderboardError, Schema.TaggedStruct<"LeaderboardError", {
|
|
295
|
+
readonly code: Schema.Literals<readonly ["invalid_board", "invalid_score", "invalid_record", "invalid_input", "overflow", "unavailable", "forbidden", "not_found", "conflict", "erased", "limit_exceeded"]>;
|
|
296
|
+
}>, YieldableError>;
|
|
297
|
+
|
|
298
|
+
/** Actual pure implementations; not a whole-system conformance fixture. */
|
|
299
|
+
export declare const leaderboardPureFixture: {
|
|
300
|
+
record: (ownerId?: string) => LeaderboardRankRecord;
|
|
301
|
+
applyScore: (previous: string | bigint | number | null, submitted: string | bigint | number, operator: ScoreOperator, sort?: LeaderboardSort) => string;
|
|
302
|
+
tiebreak: LeaderboardTiebreak;
|
|
303
|
+
periodSummary: (records: ReadonlyArray< RankedLeaderboardRecord>, top?: number) => Readonly<{
|
|
304
|
+
participants: number;
|
|
305
|
+
top: readonly RankedLeaderboardRecord[];
|
|
306
|
+
}>;
|
|
307
|
+
hashBucket: (tenantId: string, periodId: string, ownerId: string, bucketCount: number) => number;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
/** Complete ordered record identities. The adapter supplies consecutive ordinal
|
|
311
|
+
* ranks and all values from its SQL snapshot, never from strategy output. */
|
|
312
|
+
declare type LeaderboardRankQuery = (context: LeaderboardRankQueryContext) => Effect.Effect<ReadonlyArray<string>, LeaderboardError>;
|
|
313
|
+
|
|
314
|
+
/** The admitted complete SQL snapshot is detached from the storage rows. A
|
|
315
|
+
* dialect implementation may use the declared read capability; writes are not
|
|
316
|
+
* part of this strategy's contract. Every returned ID must belong to records. */
|
|
317
|
+
declare interface LeaderboardRankQueryContext {
|
|
318
|
+
readonly tenantId: string;
|
|
319
|
+
readonly board: string;
|
|
320
|
+
readonly periodId: string;
|
|
321
|
+
/** null is the global view; a value is the admitted owner's current cohort. */
|
|
322
|
+
readonly bucketId: string | null;
|
|
323
|
+
readonly sort: LeaderboardSort;
|
|
324
|
+
readonly maxRecords: number;
|
|
325
|
+
readonly records: ReadonlyArray<LeaderboardRankRecord>;
|
|
326
|
+
readonly tiebreak: LeaderboardTiebreak;
|
|
327
|
+
readonly query: DataStore['query'];
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/** Supply the real store's read capability when a dialect slot needs SQL. The
|
|
331
|
+
* default itself remains a pure Effect over the captured fixture records. */
|
|
332
|
+
export declare const leaderboardRankQueryFixture: (query: DataStore["query"]) => {
|
|
333
|
+
readonly rankQuery: typeof defaultLeaderboardRankQuery;
|
|
334
|
+
readonly context: LeaderboardRankQueryContext;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
declare interface LeaderboardRankRecord {
|
|
338
|
+
readonly id: string;
|
|
339
|
+
readonly tenantId: string;
|
|
340
|
+
readonly board: string;
|
|
341
|
+
readonly periodId: string;
|
|
342
|
+
readonly ownerId: string;
|
|
343
|
+
readonly score: string;
|
|
344
|
+
readonly subscore: string;
|
|
345
|
+
readonly updatedAt: number;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
declare type LeaderboardRecord = typeof LeaderboardRecordSchema.Type;
|
|
349
|
+
|
|
350
|
+
export declare const leaderboardRecordFixture: (ownerId?: string) => LeaderboardRankRecord;
|
|
351
|
+
|
|
352
|
+
declare const LeaderboardRecordSchema: Schema.Struct<{
|
|
353
|
+
readonly id: Schema.String;
|
|
354
|
+
readonly board: Schema.String;
|
|
355
|
+
readonly periodId: Schema.String;
|
|
356
|
+
readonly ownerId: Schema.String;
|
|
357
|
+
readonly score: Schema.String;
|
|
358
|
+
readonly subscore: Schema.String;
|
|
359
|
+
readonly numSubmits: Schema.Number;
|
|
360
|
+
readonly metadata: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
361
|
+
readonly updatedAt: Schema.Number;
|
|
362
|
+
readonly bucket: Schema.NullOr<Schema.String>;
|
|
363
|
+
}>;
|
|
364
|
+
|
|
365
|
+
declare type LeaderboardSort = 'asc' | 'desc';
|
|
366
|
+
|
|
367
|
+
declare type LeaderboardTiebreak = (left: LeaderboardRankRecord, right: LeaderboardRankRecord) => number;
|
|
368
|
+
|
|
369
|
+
declare interface OpenSkillOptions {
|
|
370
|
+
readonly beta?: number;
|
|
371
|
+
readonly tau?: number;
|
|
372
|
+
readonly kappa?: number;
|
|
373
|
+
readonly ordinalZ?: number;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export declare const periodSummarySystemFixture: Readonly<{
|
|
377
|
+
kind: "slot";
|
|
378
|
+
defaultImplementation: (records: ReadonlyArray< RankedLeaderboardRecord>, top?: number) => Readonly<{
|
|
379
|
+
participants: number;
|
|
380
|
+
top: readonly RankedLeaderboardRecord[];
|
|
381
|
+
}>;
|
|
382
|
+
defaultProbe: {
|
|
383
|
+
run: () => Effect.Effect<number, never, never>;
|
|
384
|
+
expected: number;
|
|
385
|
+
};
|
|
386
|
+
overrideProbe: {
|
|
387
|
+
run: () => Effect.Effect<number, never, never>;
|
|
388
|
+
expected: number;
|
|
389
|
+
};
|
|
390
|
+
}>;
|
|
391
|
+
|
|
392
|
+
declare interface Provision extends TournamentRoomWork {
|
|
393
|
+
readonly roomId: string | null;
|
|
394
|
+
readonly epoch: number | null;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
declare interface RankedLeaderboardRecord extends LeaderboardRankRecord {
|
|
398
|
+
readonly rank: number;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export declare const rankQuerySystemFixture: Readonly<{
|
|
402
|
+
kind: "slot";
|
|
403
|
+
defaultImplementation: LeaderboardRankQuery;
|
|
404
|
+
defaultProbe: {
|
|
405
|
+
run: () => Effect.Effect<readonly string[], LeaderboardError, never>;
|
|
406
|
+
expected: string[];
|
|
407
|
+
};
|
|
408
|
+
overrideProbe: {
|
|
409
|
+
run: () => Effect.Effect<string[], never, never>;
|
|
410
|
+
expected: string[];
|
|
411
|
+
};
|
|
412
|
+
}>;
|
|
413
|
+
|
|
414
|
+
declare interface RatingDecayContext extends RatingPlacementContext {
|
|
415
|
+
readonly state: RatingState;
|
|
416
|
+
readonly games: number;
|
|
417
|
+
readonly updatedAt: number;
|
|
418
|
+
readonly elapsedMs: number;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
declare type RatingDecayPolicy = (context: RatingDecayContext) => RatingState;
|
|
422
|
+
|
|
423
|
+
export declare const ratingDecaySystemFixture: Readonly<{
|
|
424
|
+
kind: "slot";
|
|
425
|
+
defaultImplementation: RatingDecayPolicy;
|
|
426
|
+
defaultProbe: {
|
|
427
|
+
run: () => Effect.Effect<{
|
|
428
|
+
readonly algorithm: "elo";
|
|
429
|
+
readonly rating: number;
|
|
430
|
+
} | {
|
|
431
|
+
readonly algorithm: "openskill";
|
|
432
|
+
readonly mu: number;
|
|
433
|
+
readonly sigma: number;
|
|
434
|
+
} | {
|
|
435
|
+
readonly algorithm: "glicko2";
|
|
436
|
+
readonly rating: number;
|
|
437
|
+
readonly deviation: number;
|
|
438
|
+
readonly volatility: number;
|
|
439
|
+
}, never, never>;
|
|
440
|
+
expected: {
|
|
441
|
+
readonly algorithm: "elo";
|
|
442
|
+
readonly rating: number;
|
|
443
|
+
} | {
|
|
444
|
+
readonly algorithm: "openskill";
|
|
445
|
+
readonly mu: number;
|
|
446
|
+
readonly sigma: number;
|
|
447
|
+
} | {
|
|
448
|
+
readonly algorithm: "glicko2";
|
|
449
|
+
readonly rating: number;
|
|
450
|
+
readonly deviation: number;
|
|
451
|
+
readonly volatility: number;
|
|
452
|
+
};
|
|
453
|
+
};
|
|
454
|
+
overrideProbe: {
|
|
455
|
+
run: () => Effect.Effect<{
|
|
456
|
+
decayed: boolean;
|
|
457
|
+
}, never, never>;
|
|
458
|
+
expected: {
|
|
459
|
+
decayed: boolean;
|
|
460
|
+
};
|
|
461
|
+
};
|
|
462
|
+
}>;
|
|
463
|
+
|
|
464
|
+
declare interface RatingPlacementContext {
|
|
465
|
+
readonly tenantId: string;
|
|
466
|
+
readonly ownerId: string;
|
|
467
|
+
readonly pool: ResolvedRatingPool;
|
|
468
|
+
readonly at: number;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
declare type RatingPlacementPolicy = (context: RatingPlacementContext) => RatingState;
|
|
472
|
+
|
|
473
|
+
export declare const ratingPlacementSystemFixture: Readonly<{
|
|
474
|
+
kind: "slot";
|
|
475
|
+
defaultImplementation: RatingPlacementPolicy;
|
|
476
|
+
defaultProbe: {
|
|
477
|
+
run: () => Effect.Effect<{
|
|
478
|
+
readonly algorithm: "elo";
|
|
479
|
+
readonly rating: number;
|
|
480
|
+
} | {
|
|
481
|
+
readonly algorithm: "openskill";
|
|
482
|
+
readonly mu: number;
|
|
483
|
+
readonly sigma: number;
|
|
484
|
+
} | {
|
|
485
|
+
readonly algorithm: "glicko2";
|
|
486
|
+
readonly rating: number;
|
|
487
|
+
readonly deviation: number;
|
|
488
|
+
readonly volatility: number;
|
|
489
|
+
}, never, never>;
|
|
490
|
+
expected: {
|
|
491
|
+
readonly algorithm: "elo";
|
|
492
|
+
readonly rating: number;
|
|
493
|
+
} | {
|
|
494
|
+
readonly algorithm: "openskill";
|
|
495
|
+
readonly mu: number;
|
|
496
|
+
readonly sigma: number;
|
|
497
|
+
} | {
|
|
498
|
+
readonly algorithm: "glicko2";
|
|
499
|
+
readonly rating: number;
|
|
500
|
+
readonly deviation: number;
|
|
501
|
+
readonly volatility: number;
|
|
502
|
+
};
|
|
503
|
+
};
|
|
504
|
+
overrideProbe: {
|
|
505
|
+
run: () => Effect.Effect<{
|
|
506
|
+
placed: boolean;
|
|
507
|
+
}, never, never>;
|
|
508
|
+
expected: {
|
|
509
|
+
placed: boolean;
|
|
510
|
+
};
|
|
511
|
+
};
|
|
512
|
+
}>;
|
|
513
|
+
|
|
514
|
+
declare interface RatingRateContext {
|
|
515
|
+
readonly tenantId: string;
|
|
516
|
+
readonly matchId: string;
|
|
517
|
+
readonly pool: ResolvedRatingPool;
|
|
518
|
+
readonly at: number;
|
|
519
|
+
readonly teams: ReadonlyArray<ReadonlyArray<RatingStrategyPlayer>>;
|
|
520
|
+
readonly ranks: ReadonlyArray<number>;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
declare type RatingRateStrategy = (context: RatingRateContext) => ReadonlyArray<RatingStrategyResult>;
|
|
524
|
+
|
|
525
|
+
export declare const ratingRateSystemFixture: Readonly<{
|
|
526
|
+
kind: "slot";
|
|
527
|
+
defaultImplementation: RatingRateStrategy;
|
|
528
|
+
defaultProbe: {
|
|
529
|
+
run: () => Effect.Effect<string[], never, never>;
|
|
530
|
+
expected: string[];
|
|
531
|
+
};
|
|
532
|
+
overrideProbe: {
|
|
533
|
+
run: () => Effect.Effect<string[], never, never>;
|
|
534
|
+
expected: string[];
|
|
535
|
+
};
|
|
536
|
+
}>;
|
|
537
|
+
|
|
538
|
+
declare type RatingState = typeof RatingStateSchema.Type;
|
|
539
|
+
|
|
540
|
+
declare const RatingStateSchema: Schema.Union<readonly [Schema.Struct<{
|
|
541
|
+
readonly algorithm: Schema.Literal<"elo">;
|
|
542
|
+
readonly rating: Schema.Number;
|
|
543
|
+
}>, Schema.Struct<{
|
|
544
|
+
readonly algorithm: Schema.Literal<"openskill">;
|
|
545
|
+
readonly mu: Schema.Number;
|
|
546
|
+
readonly sigma: Schema.Number;
|
|
547
|
+
}>, Schema.Struct<{
|
|
548
|
+
readonly algorithm: Schema.Literal<"glicko2">;
|
|
549
|
+
readonly rating: Schema.Number;
|
|
550
|
+
readonly deviation: Schema.Number;
|
|
551
|
+
readonly volatility: Schema.Number;
|
|
552
|
+
}>]>;
|
|
553
|
+
|
|
554
|
+
export declare const ratingStrategiesFixture: () => {
|
|
555
|
+
readonly rate: typeof defaultRatingRate;
|
|
556
|
+
readonly placementPolicy: typeof defaultRatingPlacement;
|
|
557
|
+
readonly decay: typeof defaultRatingDecay;
|
|
558
|
+
readonly context: RatingRateContext;
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
declare interface RatingStrategyPlayer {
|
|
562
|
+
readonly ownerId: string;
|
|
563
|
+
readonly state: RatingState;
|
|
564
|
+
readonly games: number;
|
|
565
|
+
readonly updatedAt: number | null;
|
|
566
|
+
readonly weight: number;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
declare interface RatingStrategyResult {
|
|
570
|
+
readonly ownerId: string;
|
|
571
|
+
readonly state: RatingState;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
declare interface ResolvedRatingPool {
|
|
575
|
+
readonly name: string;
|
|
576
|
+
readonly algorithm: RatingState['algorithm'];
|
|
577
|
+
readonly initial: RatingState;
|
|
578
|
+
readonly options: EloOptions | OpenSkillOptions | Glicko2Options;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
declare interface Result extends TournamentResultReport {
|
|
582
|
+
readonly reportedWinnerId: string;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
declare interface RoundRobinRound {
|
|
586
|
+
readonly round: number;
|
|
587
|
+
readonly pairs: ReadonlyArray<TournamentPair>;
|
|
588
|
+
readonly bye: string | null;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
declare type ScoreOperator = 'best' | 'set' | 'increment' | 'decrement';
|
|
592
|
+
|
|
593
|
+
declare interface SingleEliminationBracket {
|
|
594
|
+
readonly format: 'single-elimination';
|
|
595
|
+
readonly version: 1;
|
|
596
|
+
readonly entrants: ReadonlyArray<TournamentEntrant>;
|
|
597
|
+
readonly matches: ReadonlyArray<SingleEliminationMatch>;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
declare interface SingleEliminationMatch {
|
|
601
|
+
readonly id: string;
|
|
602
|
+
readonly round: number;
|
|
603
|
+
readonly left: BracketSlot;
|
|
604
|
+
readonly right: BracketSlot;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/** Trusted service submission, never a player score-intent payload. */
|
|
608
|
+
declare interface SubmitLeaderboardInput {
|
|
609
|
+
readonly tenantId: string;
|
|
610
|
+
readonly board: string;
|
|
611
|
+
readonly ownerId: string;
|
|
612
|
+
readonly submissionId: string;
|
|
613
|
+
readonly score: string;
|
|
614
|
+
readonly subscore?: string;
|
|
615
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
616
|
+
readonly roomId?: string;
|
|
617
|
+
readonly matchId?: string;
|
|
618
|
+
readonly tournamentId?: string;
|
|
619
|
+
readonly bucketSkill?: number;
|
|
620
|
+
readonly bucketCohort?: string;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
declare interface SwissPairing {
|
|
624
|
+
readonly pairs: ReadonlyArray<TournamentPair>;
|
|
625
|
+
readonly bye: string | null;
|
|
626
|
+
readonly searchNodes: number;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
declare interface SwissStanding extends TournamentEntrant {
|
|
630
|
+
/** Whole scoring units selected by the studio (for example win2/draw1). */
|
|
631
|
+
readonly points: number;
|
|
632
|
+
readonly byes: number;
|
|
633
|
+
readonly opponents: ReadonlyArray<string>;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export declare const tiebreakSystemFixture: Readonly<{
|
|
637
|
+
kind: "slot";
|
|
638
|
+
defaultImplementation: LeaderboardTiebreak;
|
|
639
|
+
defaultProbe: {
|
|
640
|
+
run: () => Effect.Effect<string[], never, never>;
|
|
641
|
+
expected: string[];
|
|
642
|
+
};
|
|
643
|
+
overrideProbe: {
|
|
644
|
+
run: () => Effect.Effect<string[], never, never>;
|
|
645
|
+
expected: string[];
|
|
646
|
+
};
|
|
647
|
+
}>;
|
|
648
|
+
|
|
649
|
+
declare interface TournamentBracketDefinition {
|
|
650
|
+
readonly format: TournamentBracketFormat;
|
|
651
|
+
readonly entrants: ReadonlyArray<TournamentEntrant>;
|
|
652
|
+
/** Swiss only: rounds to play (default: enough to separate a winner, ceil(log2 entrants)). */
|
|
653
|
+
readonly rounds?: number | undefined;
|
|
654
|
+
/** Immutable application prize/Room/no-show policy identity, not a price. */
|
|
655
|
+
readonly ruleVersion: string;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
declare interface TournamentBracketExport {
|
|
659
|
+
readonly tournamentId: string;
|
|
660
|
+
readonly phase: BracketState['phase'];
|
|
661
|
+
readonly seed: number;
|
|
662
|
+
readonly matches: ReadonlyArray<{
|
|
663
|
+
readonly matchId: string;
|
|
664
|
+
readonly roomId: string;
|
|
665
|
+
readonly won: boolean;
|
|
666
|
+
}>;
|
|
667
|
+
readonly disputes: ReadonlyArray<TournamentDisputeIntent & {
|
|
668
|
+
readonly resolutionId: string | null;
|
|
669
|
+
}>;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export declare const tournamentBracketFakeLayer: (overrides?: Partial<TournamentBracketService>) => Layer.Layer<TournamentBracketPort>;
|
|
673
|
+
|
|
674
|
+
declare type TournamentBracketFormat = 'single-elimination' | 'double-elimination' | 'round-robin' | 'swiss';
|
|
675
|
+
|
|
676
|
+
/** A bracket match with the Room it plays in, once one was provisioned. */
|
|
677
|
+
declare type TournamentBracketMatch = (BracketProgress['matches'][number] | DoubleEliminationProgress['matches'][number]) & {
|
|
678
|
+
readonly roomId: string | null;
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
/** Trusted server coordinator contract; SQL types are erased imports only. */
|
|
682
|
+
declare class TournamentBracketPort extends TournamentBracketPort_base {
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
declare const TournamentBracketPort_base: Context.ServiceClass<TournamentBracketPort, "@voltro/TournamentBracketPort", {
|
|
686
|
+
create(subject: Subject, scope: BracketAdmissionScope, definition: TournamentBracketDefinition): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
687
|
+
report(subject: Subject, scope: BracketAdmissionScope, report: TournamentResultReport): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
688
|
+
dispute(subject: Subject, scope: BracketAdmissionScope, intent: TournamentDisputeIntent): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
689
|
+
resolve(subject: Subject, scope: BracketAdmissionScope, intent: TournamentDisputeResolution): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
690
|
+
advance(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
691
|
+
status(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
692
|
+
exportSubject(request: PluginPrivacyRequest): Effect.Effect<ReadonlyArray<TournamentBracketExport>, LeaderboardError>;
|
|
693
|
+
eraseSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
694
|
+
}>;
|
|
695
|
+
|
|
696
|
+
export declare const tournamentBracketPortFixture: () => {
|
|
697
|
+
kind: "port";
|
|
698
|
+
tag: typeof TournamentBracketPort;
|
|
699
|
+
fakeLayer: Layer.Layer<TournamentBracketPort, never, never>;
|
|
700
|
+
probe: {
|
|
701
|
+
run: () => Promise<"invalid_board" | "invalid_score" | "invalid_record" | "invalid_input" | "overflow" | "unavailable" | "forbidden" | "not_found" | "conflict" | "erased" | "limit_exceeded" | "unexpected-success">;
|
|
702
|
+
expected: string;
|
|
703
|
+
};
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
export declare const tournamentBracketPortSystemFixture: Readonly<{
|
|
707
|
+
kind: "port";
|
|
708
|
+
tag: typeof TournamentBracketPort;
|
|
709
|
+
fakeLayer: Layer.Layer<TournamentBracketPort, never, never>;
|
|
710
|
+
probe: {
|
|
711
|
+
run: () => Effect.Effect<string, never, never>;
|
|
712
|
+
expected: string;
|
|
713
|
+
};
|
|
714
|
+
}>;
|
|
715
|
+
|
|
716
|
+
declare type TournamentBracketService = Context.Service.Shape<typeof TournamentBracketPort>;
|
|
717
|
+
|
|
718
|
+
declare interface TournamentBracketStatus {
|
|
719
|
+
readonly phase: BracketState['phase'];
|
|
720
|
+
readonly format: TournamentBracketFormat;
|
|
721
|
+
readonly champion: string | null;
|
|
722
|
+
readonly matches: ReadonlyArray<TournamentBracketMatch>;
|
|
723
|
+
readonly unresolvedDisputes: number;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
export declare const tournamentBracketSystemFakeLayer: Layer.Layer<TournamentBracketPort, never, never>;
|
|
727
|
+
|
|
728
|
+
declare interface TournamentDisputeIntent {
|
|
729
|
+
readonly disputeId: string;
|
|
730
|
+
readonly matchId: string;
|
|
731
|
+
readonly reason: 'result_mismatch' | 'no_show' | 'connection';
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
declare interface TournamentDisputeResolution {
|
|
735
|
+
readonly disputeId: string;
|
|
736
|
+
readonly resolutionId: string;
|
|
737
|
+
readonly winnerId: string;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
declare interface TournamentEntrant {
|
|
741
|
+
readonly entrantId: string;
|
|
742
|
+
readonly seed: number;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
declare interface TournamentPair {
|
|
746
|
+
readonly left: string;
|
|
747
|
+
readonly right: string;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/** Actual pairing primitives, with no simulated SQL, Room or prize outcome. */
|
|
751
|
+
export declare const tournamentPairingFixture: () => Readonly<{
|
|
752
|
+
entrants: readonly Readonly<{
|
|
753
|
+
entrantId: `p${number}`;
|
|
754
|
+
seed: number;
|
|
755
|
+
}>[];
|
|
756
|
+
standings: readonly Readonly<{
|
|
757
|
+
points: 0;
|
|
758
|
+
byes: 0;
|
|
759
|
+
opponents: readonly string[];
|
|
760
|
+
entrantId: `p${number}`;
|
|
761
|
+
seed: number;
|
|
762
|
+
}>[];
|
|
763
|
+
roundRobin: (input: ReadonlyArray< TournamentEntrant>, options?: {
|
|
764
|
+
readonly doubleRound?: boolean;
|
|
765
|
+
readonly limits?: Partial< TournamentPairingLimits>;
|
|
766
|
+
}) => ReadonlyArray< RoundRobinRound>;
|
|
767
|
+
swissPairings: (input: ReadonlyArray< SwissStanding>, config?: Partial< TournamentPairingLimits>) => SwissPairing;
|
|
768
|
+
seedSingleElimination: (input: ReadonlyArray< TournamentEntrant>, config?: Partial< TournamentPairingLimits>) => SingleEliminationBracket;
|
|
769
|
+
advanceSingleElimination: (input: SingleEliminationBracket, inputResults: ReadonlyArray< BracketResult>, config?: Partial< TournamentPairingLimits>) => BracketProgress;
|
|
770
|
+
seedDoubleElimination: (input: ReadonlyArray< TournamentEntrant>, config?: Partial< TournamentPairingLimits>) => DoubleEliminationBracket;
|
|
771
|
+
advanceDoubleElimination: (input: DoubleEliminationBracket, inputResults: ReadonlyArray< BracketResult>, config?: Partial< TournamentPairingLimits>) => DoubleEliminationProgress;
|
|
772
|
+
}>;
|
|
773
|
+
|
|
774
|
+
declare interface TournamentPairingLimits {
|
|
775
|
+
readonly maxEntrants: number;
|
|
776
|
+
readonly maxMatches: number;
|
|
777
|
+
readonly maxSearchNodes: number;
|
|
778
|
+
readonly maxInputBytes: number;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
declare interface TournamentResultReport extends TournamentRoomReceipt {
|
|
782
|
+
readonly matchId: string;
|
|
783
|
+
readonly reportId: string;
|
|
784
|
+
readonly winnerId: string;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
declare interface TournamentRoomReceipt {
|
|
788
|
+
readonly roomId: string;
|
|
789
|
+
readonly epoch: number;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
declare interface TournamentRoomWork extends BracketAdmissionScope {
|
|
793
|
+
readonly matchId: string;
|
|
794
|
+
readonly requestId: string;
|
|
795
|
+
readonly left: string;
|
|
796
|
+
readonly right: string;
|
|
797
|
+
readonly ruleVersion: string;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
export declare const tournamentStageFakeLayer: (overrides?: Partial<TournamentStageService>) => Layer.Layer<TournamentStagePort>;
|
|
801
|
+
|
|
802
|
+
declare const TournamentStagePayload: Schema.Struct<{
|
|
803
|
+
readonly format: Schema.Literals<readonly ["single-elimination", "double-elimination", "round-robin", "swiss"]>;
|
|
804
|
+
readonly ruleVersion: Schema.String;
|
|
805
|
+
readonly tenantId: Schema.String;
|
|
806
|
+
readonly tournamentId: Schema.String;
|
|
807
|
+
readonly runKey: Schema.String;
|
|
808
|
+
}>;
|
|
809
|
+
|
|
810
|
+
declare type TournamentStagePayload = typeof TournamentStagePayload.Type;
|
|
811
|
+
|
|
812
|
+
declare class TournamentStagePort extends TournamentStagePort_base {
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
declare const TournamentStagePort_base: Context.ServiceClass<TournamentStagePort, "@voltro/TournamentStagePort", {
|
|
816
|
+
window(subject: Subject, payload: TournamentStagePayload): Effect.Effect<BracketAdmissionDefinition, LeaderboardError>;
|
|
817
|
+
notify(subject: Subject, payload: TournamentStagePayload, phase: "registration" | "check-in"): Effect.Effect<{
|
|
818
|
+
readonly notified: boolean;
|
|
819
|
+
}, LeaderboardError>;
|
|
820
|
+
seed(subject: Subject, payload: TournamentStagePayload): Effect.Effect<TournamentWorkflowSummary, LeaderboardError>;
|
|
821
|
+
}>;
|
|
822
|
+
|
|
823
|
+
export declare const tournamentStagePortFixture: () => {
|
|
824
|
+
kind: "port";
|
|
825
|
+
tag: typeof TournamentStagePort;
|
|
826
|
+
fakeLayer: Layer.Layer<TournamentStagePort, never, never>;
|
|
827
|
+
probe: {
|
|
828
|
+
run: () => Promise<"invalid_board" | "invalid_score" | "invalid_record" | "invalid_input" | "overflow" | "unavailable" | "forbidden" | "not_found" | "conflict" | "erased" | "limit_exceeded" | "unexpected-success">;
|
|
829
|
+
expected: string;
|
|
830
|
+
};
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
export declare const tournamentStagePortSystemFixture: Readonly<{
|
|
834
|
+
kind: "port";
|
|
835
|
+
tag: typeof TournamentStagePort;
|
|
836
|
+
fakeLayer: Layer.Layer<TournamentStagePort, never, never>;
|
|
837
|
+
probe: {
|
|
838
|
+
run: () => Effect.Effect<string, never, never>;
|
|
839
|
+
expected: string;
|
|
840
|
+
};
|
|
841
|
+
}>;
|
|
842
|
+
|
|
843
|
+
declare type TournamentStageService = Context.Service.Shape<typeof TournamentStagePort>;
|
|
844
|
+
|
|
845
|
+
export declare const tournamentStageSystemFakeLayer: Layer.Layer<TournamentStagePort, never, never>;
|
|
846
|
+
|
|
847
|
+
/** Counts only: no roster/winner/ratings/Room credentials in workflow journals. */
|
|
848
|
+
declare const TournamentWorkflowSummary: Schema.Struct<{
|
|
849
|
+
readonly phase: Schema.Literals<readonly ["active", "paused", "complete", "erasing", "cancelled"]>;
|
|
850
|
+
readonly ready: Schema.Int;
|
|
851
|
+
readonly completed: Schema.Int;
|
|
852
|
+
/** Advance work still open: ready matches without a Room, plus the champion's settlement. */
|
|
853
|
+
readonly waiting: Schema.Int;
|
|
854
|
+
readonly unresolvedDisputes: Schema.Int;
|
|
855
|
+
}>;
|
|
856
|
+
|
|
857
|
+
declare type TournamentWorkflowSummary = typeof TournamentWorkflowSummary.Type;
|
|
858
|
+
|
|
859
|
+
export declare const validateSystemFixture: Readonly<{
|
|
860
|
+
kind: "slot";
|
|
861
|
+
defaultImplementation: (input: SubmitLeaderboardInput, previous: LeaderboardRecord | null, tx: DataStore) => Effect.Effect<void, LeaderboardError>;
|
|
862
|
+
defaultProbe: {
|
|
863
|
+
run: () => Effect.Effect<string, LeaderboardError, never>;
|
|
864
|
+
expected: string;
|
|
865
|
+
};
|
|
866
|
+
overrideProbe: {
|
|
867
|
+
run: () => Effect.Effect<string, never, never>;
|
|
868
|
+
expected: string;
|
|
869
|
+
};
|
|
870
|
+
}>;
|
|
871
|
+
|
|
872
|
+
export { }
|