@voltro/plugin-leaderboards 0.0.0-stage → 0.87.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 +24329 -0
- package/LICENSE +61 -0
- package/README.md +1087 -2
- package/SECURITY.md +56 -0
- package/THIRD-PARTY-NOTICES.md +5007 -0
- package/dist/administration.js +5 -0
- package/dist/bracketAdmission.js +294 -0
- package/dist/bracketAdmissionPolicy.js +22 -0
- package/dist/bracketInstallation.js +133 -0
- package/dist/bracketMatchPorts.js +5 -0
- package/dist/bracketMatches.js +546 -0
- package/dist/brackets.d.ts +149 -0
- package/dist/brackets.js +379 -0
- package/dist/bucketStore.js +93 -0
- package/dist/buckets.js +9 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +17 -0
- package/dist/glicko2.js +72 -0
- package/dist/index.d.ts +1208 -0
- package/dist/index.js +15 -0
- package/dist/inspect.js +84 -0
- package/dist/json.js +39 -0
- package/dist/leaderboard.d.ts +49 -0
- package/dist/leaderboard.js +57 -0
- package/dist/leagueSchedule.js +40 -0
- package/dist/leagues.js +31 -0
- package/dist/openskill.js +74 -0
- package/dist/plugin.js +338 -0
- package/dist/portLifetime.js +67 -0
- package/dist/ports.d.ts +294 -0
- package/dist/ports.js +7 -0
- package/dist/rankQuery.js +24 -0
- package/dist/ranking.d.ts +42 -0
- package/dist/ranking.js +71 -0
- package/dist/rating.d.ts +103 -0
- package/dist/rating.js +50 -0
- package/dist/ratingPools.js +134 -0
- package/dist/ratingStore.js +334 -0
- package/dist/ratingStrategies.js +108 -0
- package/dist/records.d.ts +116 -0
- package/dist/records.js +88 -0
- package/dist/rpc.d.ts +321 -0
- package/dist/rpc.js +306 -0
- package/dist/score.d.ts +13 -0
- package/dist/score.js +27 -0
- package/dist/server.d.ts +1477 -0
- package/dist/server.js +17 -0
- package/dist/service.js +949 -0
- package/dist/subjectFences.js +44 -0
- package/dist/tables.entity.js +188 -0
- package/dist/testing.d.ts +872 -0
- package/dist/testing.js +368 -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 +168 -0
- package/dist/tournamentPrizes.js +34 -0
- package/dist/tournamentStage.js +151 -0
- package/dist/tournamentStagePorts.js +5 -0
- package/dist/tournamentWorkflow.js +101 -0
- package/dist/tournamentWorkflowSchemas.js +54 -0
- package/dist/tournaments.d.ts +32 -0
- package/dist/tournaments.js +21 -0
- package/dist/web.d.ts +175 -0
- package/dist/web.js +17 -0
- package/package.json +113 -4
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,1477 @@
|
|
|
1
|
+
import { AppContext } from '@voltro/runtime';
|
|
2
|
+
import { BrandedScheduleDefinition } from '@voltro/runtime';
|
|
3
|
+
import { ColumnBuilder } from '@voltro/database';
|
|
4
|
+
import { Context } from 'effect';
|
|
5
|
+
import { DataStore } from '@voltro/database';
|
|
6
|
+
import { Effect } from 'effect';
|
|
7
|
+
import { FieldDefinitions } from '@voltro/database';
|
|
8
|
+
import { Layer } from 'effect';
|
|
9
|
+
import { PluginPrivacyRequest } from '@voltro/protocol';
|
|
10
|
+
import { PluginPrivacyTarget } from '@voltro/protocol';
|
|
11
|
+
import { Schema } from 'effect';
|
|
12
|
+
import { Subject } from '@voltro/protocol';
|
|
13
|
+
import { systemSubject } from '@voltro/protocol';
|
|
14
|
+
import { Table } from '@voltro/database';
|
|
15
|
+
import { TableLike } from '@voltro/database';
|
|
16
|
+
import { WorkflowEngine } from 'effect/workflow/WorkflowEngine';
|
|
17
|
+
import { WorkflowInstance } from 'effect/workflow/WorkflowEngine';
|
|
18
|
+
import { YieldableError } from 'effect/Cause';
|
|
19
|
+
|
|
20
|
+
export declare const acceptLeaderboardSubmission: NonNullable<LeaderboardStoreOptions['validate']>;
|
|
21
|
+
|
|
22
|
+
declare interface AdmissionState {
|
|
23
|
+
readonly version: 1;
|
|
24
|
+
readonly definition: BracketAdmissionDefinition;
|
|
25
|
+
readonly phase: 'open' | 'sealed' | 'erasing' | 'cancelled';
|
|
26
|
+
readonly entries: ReadonlyArray<BracketAdmissionEntry>;
|
|
27
|
+
readonly eraseRequest: string | null;
|
|
28
|
+
readonly eraseTarget: string | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export declare interface ApplyRatingMatchInput {
|
|
32
|
+
readonly tenantId: string;
|
|
33
|
+
readonly pool: string;
|
|
34
|
+
readonly matchId: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export declare const BRACKET_ADMISSIONS_TABLE = "_voltro_tournament_admissions";
|
|
38
|
+
|
|
39
|
+
export declare type BracketAdmissionBinding = {
|
|
40
|
+
readonly backend: 'sql';
|
|
41
|
+
readonly options: BracketAdmissionOptions;
|
|
42
|
+
} | {
|
|
43
|
+
readonly backend: 'custom';
|
|
44
|
+
readonly version: string;
|
|
45
|
+
readonly service: BracketAdmissionService;
|
|
46
|
+
readonly sources: ReadonlyArray<string>;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export declare interface BracketAdmissionConfiguration {
|
|
50
|
+
readonly backend: 'sql' | 'custom';
|
|
51
|
+
readonly version: string;
|
|
52
|
+
readonly maxTenantTournaments: number | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
declare interface BracketAdmissionDefinition {
|
|
56
|
+
readonly registrationOpensAt: number;
|
|
57
|
+
readonly registrationClosesAt: number;
|
|
58
|
+
readonly checkInOpensAt: number;
|
|
59
|
+
readonly checkInClosesAt: number;
|
|
60
|
+
readonly maxEntries: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export declare interface BracketAdmissionEntrants {
|
|
64
|
+
readonly phase: AdmissionState['phase'];
|
|
65
|
+
readonly entries: ReadonlyArray<BracketAdmissionEntry>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export declare interface BracketAdmissionEntry {
|
|
69
|
+
readonly ownerId: string;
|
|
70
|
+
readonly joinedAt: number;
|
|
71
|
+
readonly checkedInAt: number | null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export declare interface BracketAdmissionExport extends BracketAdmissionEntry {
|
|
75
|
+
readonly tournamentId: string;
|
|
76
|
+
readonly phase: BracketAdmissionStatus['phase'];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export declare const bracketAdmissionLayer: (store: DataStore, options: BracketAdmissionOptions) => Layer.Layer<BracketAdmissionPort>;
|
|
80
|
+
|
|
81
|
+
export declare interface BracketAdmissionOptions {
|
|
82
|
+
readonly epochNow: () => number;
|
|
83
|
+
readonly maxTenantTournaments?: number;
|
|
84
|
+
/** Normal current application guards; no successful policy is provided. */
|
|
85
|
+
authorize(subject: Subject, scope: BracketAdmissionScope, operation: 'create' | 'register' | 'checkIn' | 'status' | 'seal' | 'entrants'): Effect.Effect<void, LeaderboardError>;
|
|
86
|
+
/** Permanent Subject admission fence + await every accepted app association. */
|
|
87
|
+
withdrawSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
88
|
+
/** Cancel and await actual Rooms/timers/rewards that use this sealed roster. */
|
|
89
|
+
withdrawTournament(scope: BracketAdmissionScope, request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
90
|
+
authorizeExport(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Browser-safe Tag; consumers depend on admission, never a SQL adapter. */
|
|
94
|
+
export declare class BracketAdmissionPort extends BracketAdmissionPort_base {
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
declare const BracketAdmissionPort_base: Context.ServiceClass<BracketAdmissionPort, "@voltro/BracketAdmissionPort", {
|
|
98
|
+
create(subject: Subject, scope: BracketAdmissionScope, definition: BracketAdmissionDefinition): Effect.Effect<void, LeaderboardError>;
|
|
99
|
+
register(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionStatus, LeaderboardError>;
|
|
100
|
+
checkIn(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionStatus, LeaderboardError>;
|
|
101
|
+
status(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionStatus, LeaderboardError>;
|
|
102
|
+
seal(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionRoster, LeaderboardError>;
|
|
103
|
+
/** Trusted read of every registration with its check-in, for notifications. */
|
|
104
|
+
entrants(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionEntrants, LeaderboardError>;
|
|
105
|
+
exportSubject(request: PluginPrivacyRequest): Effect.Effect<ReadonlyArray<BracketAdmissionExport>, LeaderboardError>;
|
|
106
|
+
eraseSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
107
|
+
}>;
|
|
108
|
+
|
|
109
|
+
export declare interface BracketAdmissionRoster {
|
|
110
|
+
readonly checkedIn: ReadonlyArray<string>;
|
|
111
|
+
readonly noShows: ReadonlyArray<string>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export declare interface BracketAdmissionScope {
|
|
115
|
+
readonly tenantId: string;
|
|
116
|
+
readonly tournamentId: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export declare type BracketAdmissionService = Context.Service.Shape<typeof BracketAdmissionPort>;
|
|
120
|
+
|
|
121
|
+
/** Ordinary schema contribution; the optional installed SQL system owns it. */
|
|
122
|
+
export declare const bracketAdmissionsTable: TableLike;
|
|
123
|
+
|
|
124
|
+
export declare interface BracketAdmissionStatus {
|
|
125
|
+
readonly phase: AdmissionState['phase'];
|
|
126
|
+
readonly entries: number;
|
|
127
|
+
readonly checkedIn: number;
|
|
128
|
+
readonly own: BracketAdmissionEntry | null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
declare interface BracketMatchObservation {
|
|
132
|
+
readonly id: string;
|
|
133
|
+
readonly round: number;
|
|
134
|
+
readonly left: string | null;
|
|
135
|
+
readonly right: string | null;
|
|
136
|
+
readonly status: 'pending' | 'ready' | 'walkover' | 'complete';
|
|
137
|
+
readonly winnerId: string | null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
declare interface BracketProgress {
|
|
141
|
+
readonly matches: ReadonlyArray<BracketMatchObservation>;
|
|
142
|
+
readonly champion: string | null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
declare type BracketSlot = {
|
|
146
|
+
readonly kind: 'entrant';
|
|
147
|
+
readonly entrantId: string;
|
|
148
|
+
} | {
|
|
149
|
+
readonly kind: 'winner';
|
|
150
|
+
readonly matchId: string;
|
|
151
|
+
} | {
|
|
152
|
+
readonly kind: 'bye';
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
declare interface BracketState extends TournamentBracketDefinition {
|
|
156
|
+
readonly version: 1;
|
|
157
|
+
readonly phase: 'active' | 'paused' | 'complete' | 'erasing' | 'cancelled';
|
|
158
|
+
readonly withdrawn: boolean;
|
|
159
|
+
readonly provisions: ReadonlyArray<Provision>;
|
|
160
|
+
readonly results: ReadonlyArray<Result>;
|
|
161
|
+
readonly disputes: ReadonlyArray<Dispute>;
|
|
162
|
+
readonly settlement: {
|
|
163
|
+
readonly requestId: string;
|
|
164
|
+
readonly winnerId: string;
|
|
165
|
+
readonly complete: boolean;
|
|
166
|
+
} | null;
|
|
167
|
+
readonly erase: {
|
|
168
|
+
readonly requestId: string;
|
|
169
|
+
readonly targetDigest: string;
|
|
170
|
+
} | null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export declare interface CloseLeaderboardTournamentInput {
|
|
174
|
+
readonly tenantId: string;
|
|
175
|
+
readonly tournament: string;
|
|
176
|
+
readonly requestId: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export declare const dataStoreBracketAdmissions: (store: DataStore, input: BracketAdmissionOptions) => BracketAdmissionService;
|
|
180
|
+
|
|
181
|
+
/** Bounded SQL snapshot foundation: no hot board, reset scheduler or client writes. */
|
|
182
|
+
export declare const dataStoreLeaderboards: (store: DataStore, input: LeaderboardStoreOptions) => {
|
|
183
|
+
assignLeague: (subject: Subject, original: {
|
|
184
|
+
readonly tenantId: string;
|
|
185
|
+
readonly league: string;
|
|
186
|
+
readonly ownerId: string;
|
|
187
|
+
readonly division: string;
|
|
188
|
+
}) => Effect.Effect<{
|
|
189
|
+
readonly league: string;
|
|
190
|
+
readonly division: string;
|
|
191
|
+
}, LeaderboardError>;
|
|
192
|
+
myLeague: (subject: Subject, league: string) => Effect.Effect<{
|
|
193
|
+
readonly league: string;
|
|
194
|
+
readonly division: string;
|
|
195
|
+
readonly assigned: boolean;
|
|
196
|
+
}, LeaderboardError>;
|
|
197
|
+
rollLeague: (subject: Subject, original: {
|
|
198
|
+
readonly tenantId: string;
|
|
199
|
+
readonly league: string;
|
|
200
|
+
readonly requestId: string;
|
|
201
|
+
readonly closedAt: number;
|
|
202
|
+
}) => Effect.Effect<{
|
|
203
|
+
readonly divisions: ReadonlyArray<{
|
|
204
|
+
readonly division: string;
|
|
205
|
+
readonly closedPeriodId: string;
|
|
206
|
+
readonly activePeriodId: string;
|
|
207
|
+
}>;
|
|
208
|
+
readonly movements: ReadonlyArray<LeagueMovement>;
|
|
209
|
+
}, LeaderboardError>;
|
|
210
|
+
leagueTenants: (subject: Subject, original: {
|
|
211
|
+
readonly league: string;
|
|
212
|
+
readonly after?: string | null;
|
|
213
|
+
readonly limit: number;
|
|
214
|
+
}) => Effect.Effect<{
|
|
215
|
+
readonly tenants: ReadonlyArray<string>;
|
|
216
|
+
readonly next: string | null;
|
|
217
|
+
}, LeaderboardError>;
|
|
218
|
+
prepareRatingMatch: (subject: Subject, original: PrepareRatingMatchInput) => Effect.Effect< RatingMatchReceipt, LeaderboardError, never>;
|
|
219
|
+
applyRatingMatch: (subject: Subject, original: ApplyRatingMatchInput) => Effect.Effect< RatingMatchReceipt, LeaderboardError, never>;
|
|
220
|
+
myRating: (subject: Subject, poolName: string) => Effect.Effect<{
|
|
221
|
+
pool: string;
|
|
222
|
+
state: {
|
|
223
|
+
readonly algorithm: "elo";
|
|
224
|
+
readonly rating: number;
|
|
225
|
+
} | {
|
|
226
|
+
readonly algorithm: "openskill";
|
|
227
|
+
readonly mu: number;
|
|
228
|
+
readonly sigma: number;
|
|
229
|
+
} | {
|
|
230
|
+
readonly algorithm: "glicko2";
|
|
231
|
+
readonly rating: number;
|
|
232
|
+
readonly deviation: number;
|
|
233
|
+
readonly volatility: number;
|
|
234
|
+
};
|
|
235
|
+
games: number;
|
|
236
|
+
updatedAt: number | null;
|
|
237
|
+
}, LeaderboardError, never>;
|
|
238
|
+
pendingRatingMatches: (subject: Subject, tenantId: string, poolName: string, limit?: number) => Effect.Effect<{
|
|
239
|
+
tenantId: string;
|
|
240
|
+
pool: string;
|
|
241
|
+
matchId: string;
|
|
242
|
+
}[], LeaderboardError, never>;
|
|
243
|
+
closeTournament: (subject: Subject, original: CloseLeaderboardTournamentInput) => Effect.Effect<RollLeaderboardPeriodResult, LeaderboardError>;
|
|
244
|
+
joinTournament: (subject: Subject, tournamentName: string) => Effect.Effect<{
|
|
245
|
+
readonly tournament: string;
|
|
246
|
+
readonly joinedAt: number;
|
|
247
|
+
readonly attemptsLeft: number;
|
|
248
|
+
}, LeaderboardError, never>;
|
|
249
|
+
tournamentStatus: (subject: Subject, tournamentName: string) => Effect.Effect<{
|
|
250
|
+
readonly tournament: string;
|
|
251
|
+
readonly board: string;
|
|
252
|
+
readonly startsAt: number;
|
|
253
|
+
readonly endsAt: number;
|
|
254
|
+
readonly observedAt: number;
|
|
255
|
+
readonly joinRequired: boolean;
|
|
256
|
+
readonly state: "open" | "upcoming" | "ended";
|
|
257
|
+
readonly entry: {
|
|
258
|
+
readonly tournament: string;
|
|
259
|
+
readonly joinedAt: number;
|
|
260
|
+
readonly attemptsLeft: number;
|
|
261
|
+
} | null;
|
|
262
|
+
}, LeaderboardError, never>;
|
|
263
|
+
rollPeriod: (subject: Subject, original: RollLeaderboardPeriodInput) => Effect.Effect<RollLeaderboardPeriodResult, LeaderboardError>;
|
|
264
|
+
history: (subject: Subject, boardName: string, limit?: number) => Effect.Effect<{
|
|
265
|
+
readonly id: string;
|
|
266
|
+
readonly board: string;
|
|
267
|
+
readonly startsAt: number;
|
|
268
|
+
readonly endsAt: number | null;
|
|
269
|
+
readonly state: "closed" | "active" | "archived";
|
|
270
|
+
readonly summary: {
|
|
271
|
+
readonly participants: number;
|
|
272
|
+
readonly top: readonly {
|
|
273
|
+
readonly id: string;
|
|
274
|
+
readonly tenantId: string;
|
|
275
|
+
readonly board: string;
|
|
276
|
+
readonly periodId: string;
|
|
277
|
+
readonly ownerId: string;
|
|
278
|
+
readonly score: string;
|
|
279
|
+
readonly subscore: string;
|
|
280
|
+
readonly updatedAt: number;
|
|
281
|
+
readonly rank: number;
|
|
282
|
+
}[];
|
|
283
|
+
} | null;
|
|
284
|
+
}[], LeaderboardError, never>;
|
|
285
|
+
submit: (subject: Subject, original: SubmitLeaderboardInput) => Effect.Effect<LeaderboardRecord, LeaderboardError>;
|
|
286
|
+
top: (subject: Subject, boardName: string, limit?: number, scope?: "global" | "bucket") => Effect.Effect<{
|
|
287
|
+
rank: number;
|
|
288
|
+
id: string;
|
|
289
|
+
board: string;
|
|
290
|
+
periodId: string;
|
|
291
|
+
ownerId: string;
|
|
292
|
+
score: string;
|
|
293
|
+
subscore: string;
|
|
294
|
+
numSubmits: number;
|
|
295
|
+
metadata: {
|
|
296
|
+
readonly [x: string]: unknown;
|
|
297
|
+
};
|
|
298
|
+
updatedAt: number;
|
|
299
|
+
bucket: string | null;
|
|
300
|
+
}[], LeaderboardError, never>;
|
|
301
|
+
me: (subject: Subject, boardName: string) => Effect.Effect<{
|
|
302
|
+
rank: number;
|
|
303
|
+
id: string;
|
|
304
|
+
board: string;
|
|
305
|
+
periodId: string;
|
|
306
|
+
ownerId: string;
|
|
307
|
+
score: string;
|
|
308
|
+
subscore: string;
|
|
309
|
+
numSubmits: number;
|
|
310
|
+
metadata: {
|
|
311
|
+
readonly [x: string]: unknown;
|
|
312
|
+
};
|
|
313
|
+
updatedAt: number;
|
|
314
|
+
bucket: string | null;
|
|
315
|
+
} | null, LeaderboardError, never>;
|
|
316
|
+
around: (subject: Subject, boardName: string, radius?: number) => Effect.Effect<{
|
|
317
|
+
rank: number;
|
|
318
|
+
id: string;
|
|
319
|
+
board: string;
|
|
320
|
+
periodId: string;
|
|
321
|
+
ownerId: string;
|
|
322
|
+
score: string;
|
|
323
|
+
subscore: string;
|
|
324
|
+
numSubmits: number;
|
|
325
|
+
metadata: {
|
|
326
|
+
readonly [x: string]: unknown;
|
|
327
|
+
};
|
|
328
|
+
updatedAt: number;
|
|
329
|
+
bucket: string | null;
|
|
330
|
+
}[], LeaderboardError, never>;
|
|
331
|
+
exportSubject: (target: PluginPrivacyTarget) => Effect.Effect<{
|
|
332
|
+
records: {
|
|
333
|
+
readonly id: string;
|
|
334
|
+
readonly board: string;
|
|
335
|
+
readonly periodId: string;
|
|
336
|
+
readonly ownerId: string;
|
|
337
|
+
readonly score: string;
|
|
338
|
+
readonly subscore: string;
|
|
339
|
+
readonly numSubmits: number;
|
|
340
|
+
readonly metadata: {
|
|
341
|
+
readonly [x: string]: unknown;
|
|
342
|
+
};
|
|
343
|
+
readonly updatedAt: number;
|
|
344
|
+
readonly bucket: string | null;
|
|
345
|
+
}[];
|
|
346
|
+
submissions: {
|
|
347
|
+
id: unknown;
|
|
348
|
+
board: unknown;
|
|
349
|
+
periodId: unknown;
|
|
350
|
+
record: {
|
|
351
|
+
readonly id: string;
|
|
352
|
+
readonly board: string;
|
|
353
|
+
readonly periodId: string;
|
|
354
|
+
readonly ownerId: string;
|
|
355
|
+
readonly score: string;
|
|
356
|
+
readonly subscore: string;
|
|
357
|
+
readonly numSubmits: number;
|
|
358
|
+
readonly metadata: {
|
|
359
|
+
readonly [x: string]: unknown;
|
|
360
|
+
};
|
|
361
|
+
readonly updatedAt: number;
|
|
362
|
+
readonly bucket: string | null;
|
|
363
|
+
};
|
|
364
|
+
roomId: unknown;
|
|
365
|
+
matchId: unknown;
|
|
366
|
+
tournamentId: unknown;
|
|
367
|
+
at: number;
|
|
368
|
+
}[];
|
|
369
|
+
bucketAssignments: {
|
|
370
|
+
board: unknown;
|
|
371
|
+
periodId: unknown;
|
|
372
|
+
bucket: unknown;
|
|
373
|
+
group: unknown;
|
|
374
|
+
assignedAt: number;
|
|
375
|
+
}[];
|
|
376
|
+
leagues: {
|
|
377
|
+
league: unknown;
|
|
378
|
+
division: unknown;
|
|
379
|
+
updatedAt: number;
|
|
380
|
+
}[];
|
|
381
|
+
leagueMoves: {
|
|
382
|
+
league: unknown;
|
|
383
|
+
from: string;
|
|
384
|
+
to: string;
|
|
385
|
+
at: number;
|
|
386
|
+
}[];
|
|
387
|
+
periodSummaries: {
|
|
388
|
+
periodId: string;
|
|
389
|
+
board: string;
|
|
390
|
+
startsAt: number;
|
|
391
|
+
endsAt: number;
|
|
392
|
+
record: RankedLeaderboardRecord;
|
|
393
|
+
}[];
|
|
394
|
+
tournamentEntries: {
|
|
395
|
+
readonly tournament: string;
|
|
396
|
+
readonly joinedAt: number;
|
|
397
|
+
readonly attemptsLeft: number;
|
|
398
|
+
}[];
|
|
399
|
+
ratings: {
|
|
400
|
+
pool: unknown;
|
|
401
|
+
state: unknown;
|
|
402
|
+
games: unknown;
|
|
403
|
+
updatedAt: number;
|
|
404
|
+
}[];
|
|
405
|
+
ratingResults: {
|
|
406
|
+
pool: unknown;
|
|
407
|
+
matchId: {} | null;
|
|
408
|
+
previous: unknown;
|
|
409
|
+
current: unknown;
|
|
410
|
+
at: number;
|
|
411
|
+
}[];
|
|
412
|
+
pendingRatingMatches: {
|
|
413
|
+
pool: unknown;
|
|
414
|
+
matchId: unknown;
|
|
415
|
+
weight: number;
|
|
416
|
+
rank: number | undefined;
|
|
417
|
+
preparedAt: number;
|
|
418
|
+
}[];
|
|
419
|
+
}, LeaderboardError, never>;
|
|
420
|
+
eraseSubject: (target: PluginPrivacyTarget) => Effect.Effect<void, LeaderboardError, never>;
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
export declare const dataStoreTournamentBrackets: (store: DataStore, offered: TournamentBracketOptions) => TournamentBracketService;
|
|
424
|
+
|
|
425
|
+
export declare const dataStoreTournamentStages: (store: DataStore, offered: TournamentStageOptions) => TournamentStageService;
|
|
426
|
+
|
|
427
|
+
export declare const defaultLeaderboardBucketAssign: LeaderboardBucketAssign;
|
|
428
|
+
|
|
429
|
+
export declare const defaultLeaderboardRankQuery: LeaderboardRankQuery;
|
|
430
|
+
|
|
431
|
+
/** Equal primary score: higher subscore, then earlier submission, then binary owner/record ID. */
|
|
432
|
+
export declare const defaultLeaderboardTiebreak: LeaderboardTiebreak;
|
|
433
|
+
|
|
434
|
+
export declare const defaultPeriodSummary: (records: ReadonlyArray<RankedLeaderboardRecord>, top?: number) => Readonly<{
|
|
435
|
+
participants: number;
|
|
436
|
+
top: readonly RankedLeaderboardRecord[];
|
|
437
|
+
}>;
|
|
438
|
+
|
|
439
|
+
/** Decay is applied on fresh participated match application, never on a read or
|
|
440
|
+
* retry. The default preserves the exact prior; no periodic decay job exists. */
|
|
441
|
+
export declare const defaultRatingDecay: RatingDecayPolicy;
|
|
442
|
+
|
|
443
|
+
export declare const defaultRatingPlacement: RatingPlacementPolicy;
|
|
444
|
+
|
|
445
|
+
export declare const defaultRatingRate: RatingRateStrategy;
|
|
446
|
+
|
|
447
|
+
/** A schedule that closes a league for every tenant with members at each firing. The firing
|
|
448
|
+
* instant is the close time and names the request, so a retried or overlapping run moves
|
|
449
|
+
* nobody twice. A tenant that fails does not stop the others; the run then fails and the
|
|
450
|
+
* next one retries only what is still open. */
|
|
451
|
+
export declare const defineLeagueRollSchedule: (input: LeagueRollScheduleOptions) => BrandedScheduleDefinition;
|
|
452
|
+
|
|
453
|
+
declare interface Dispute extends TournamentDisputeIntent {
|
|
454
|
+
readonly ownerId: string;
|
|
455
|
+
readonly resolutionId: string | null;
|
|
456
|
+
readonly winnerId: string | null;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
declare interface DoubleEliminationMatch {
|
|
460
|
+
readonly id: string;
|
|
461
|
+
readonly stage: 'winners' | 'losers' | 'final' | 'reset';
|
|
462
|
+
readonly round: number;
|
|
463
|
+
readonly left: DoubleEliminationSlot;
|
|
464
|
+
readonly right: DoubleEliminationSlot;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
declare interface DoubleEliminationObservation extends Omit<BracketMatchObservation, 'status'> {
|
|
468
|
+
readonly stage: DoubleEliminationMatch['stage'];
|
|
469
|
+
readonly status: BracketMatchObservation['status'] | 'empty' | 'inactive';
|
|
470
|
+
readonly loserId: string | null;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
declare interface DoubleEliminationProgress {
|
|
474
|
+
readonly matches: ReadonlyArray<DoubleEliminationObservation>;
|
|
475
|
+
readonly champion: string | null;
|
|
476
|
+
readonly losses: ReadonlyArray<{
|
|
477
|
+
readonly entrantId: string;
|
|
478
|
+
readonly losses: number;
|
|
479
|
+
}>;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
declare type DoubleEliminationSlot = BracketSlot | {
|
|
483
|
+
readonly kind: 'loser';
|
|
484
|
+
readonly matchId: string;
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
declare interface EloOptions {
|
|
488
|
+
readonly k?: number;
|
|
489
|
+
readonly scale?: number;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
declare interface Glicko2Options {
|
|
493
|
+
readonly tau?: number;
|
|
494
|
+
readonly epsilon?: number;
|
|
495
|
+
readonly maxIterations?: number;
|
|
496
|
+
readonly maxOpponents?: number;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export declare class LeaderboardAdministration extends LeaderboardAdministration_base {
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
declare const LeaderboardAdministration_base: Context.ServiceClass<LeaderboardAdministration, "@voltro/LeaderboardAdministration", LeaderboardAdministrationService>;
|
|
503
|
+
|
|
504
|
+
/** Internal server service for this leaf plugin's handlers, not a game-stack Port. */
|
|
505
|
+
export declare type LeaderboardAdministrationService = Omit<ReturnType<typeof dataStoreLeaderboards>, 'exportSubject' | 'eraseSubject'>;
|
|
506
|
+
|
|
507
|
+
export declare const leaderboardBoardsTable: Table<"_voltro_lb_boards", FieldDefinitions<{
|
|
508
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
509
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
510
|
+
readonly name: ColumnBuilder<string, "text", boolean>;
|
|
511
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
512
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
513
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
514
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
515
|
+
}>, true, never>;
|
|
516
|
+
|
|
517
|
+
/** Choose one actual capacity-admitted candidate. Grouping/SQL writer admission,
|
|
518
|
+
* membership and capacity stay inside the adapter. */
|
|
519
|
+
export declare type LeaderboardBucketAssign = (context: LeaderboardBucketContext) => string;
|
|
520
|
+
|
|
521
|
+
export declare const leaderboardBucketAssignmentsTable: Table<"_voltro_lb_bucket_assignments", FieldDefinitions<{
|
|
522
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
523
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
524
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
525
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
526
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
527
|
+
readonly bucket: ColumnBuilder<string, "text", boolean>;
|
|
528
|
+
readonly ordinal: ColumnBuilder<number, "integer", boolean>;
|
|
529
|
+
readonly groupKey: ColumnBuilder<string, "text", boolean>;
|
|
530
|
+
readonly group: ColumnBuilder<string | null, "text", boolean>;
|
|
531
|
+
readonly assignedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
532
|
+
}>, true, "voltro_lb_bucket_assignments_group_idx">;
|
|
533
|
+
|
|
534
|
+
export declare interface LeaderboardBucketCandidate {
|
|
535
|
+
readonly id: string;
|
|
536
|
+
readonly ordinal: number;
|
|
537
|
+
readonly entries: number;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export declare interface LeaderboardBucketContext {
|
|
541
|
+
readonly tenantId: string;
|
|
542
|
+
readonly board: string;
|
|
543
|
+
readonly periodId: string;
|
|
544
|
+
readonly ownerId: string;
|
|
545
|
+
readonly assign: 'hash' | 'skill' | 'cohort';
|
|
546
|
+
readonly size: number;
|
|
547
|
+
readonly group: string | null;
|
|
548
|
+
readonly candidates: ReadonlyArray<LeaderboardBucketCandidate>;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
declare interface LeaderboardDefinition<S extends Schema.Codec<unknown, unknown>> {
|
|
552
|
+
readonly name: string;
|
|
553
|
+
readonly sort?: LeaderboardSort;
|
|
554
|
+
readonly operator?: ScoreOperator;
|
|
555
|
+
readonly metadata: S;
|
|
556
|
+
/** Only service-owned writes exist in this foundation; no client score route. */
|
|
557
|
+
readonly submit?: {
|
|
558
|
+
readonly via: 'service-only';
|
|
559
|
+
};
|
|
560
|
+
readonly reset?: {
|
|
561
|
+
readonly cron: string;
|
|
562
|
+
readonly timezone: string;
|
|
563
|
+
readonly keepHistory: number;
|
|
564
|
+
} | undefined;
|
|
565
|
+
readonly maxRankRecords?: number;
|
|
566
|
+
readonly maxPageSize?: number;
|
|
567
|
+
readonly buckets?: {
|
|
568
|
+
readonly size: number;
|
|
569
|
+
readonly assign: 'hash' | 'skill' | 'cohort';
|
|
570
|
+
readonly skillWidth?: number;
|
|
571
|
+
} | undefined;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
declare interface LeaderboardDescriptor<S extends Schema.Codec<unknown, unknown>> {
|
|
575
|
+
readonly kind: 'leaderboard';
|
|
576
|
+
readonly name: string;
|
|
577
|
+
readonly sort: LeaderboardSort;
|
|
578
|
+
readonly operator: ScoreOperator;
|
|
579
|
+
readonly metadata: S;
|
|
580
|
+
readonly submit: {
|
|
581
|
+
readonly via: 'service-only';
|
|
582
|
+
};
|
|
583
|
+
readonly reset: LeaderboardDefinition<S>['reset'];
|
|
584
|
+
readonly maxRankRecords: number;
|
|
585
|
+
readonly maxPageSize: number;
|
|
586
|
+
readonly buckets: LeaderboardDefinition<S>['buckets'];
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
declare class LeaderboardError extends LeaderboardError_base {
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
declare const LeaderboardError_base: Schema.Class<LeaderboardError, Schema.TaggedStruct<"LeaderboardError", {
|
|
593
|
+
readonly code: Schema.Literals<readonly ["invalid_board", "invalid_score", "invalid_record", "invalid_input", "overflow", "unavailable", "forbidden", "not_found", "conflict", "erased", "limit_exceeded"]>;
|
|
594
|
+
}>, YieldableError>;
|
|
595
|
+
|
|
596
|
+
/** League membership: one division per owner and league (id derived from tenant, league, owner). */
|
|
597
|
+
export declare const leaderboardLeagueMembersTable: Table<"_voltro_lb_league_members", FieldDefinitions<{
|
|
598
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
599
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
600
|
+
readonly league: ColumnBuilder<string, "text", boolean>;
|
|
601
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
602
|
+
readonly division: ColumnBuilder<string, "text", boolean>;
|
|
603
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
604
|
+
}>, true, "voltro_lb_league_members_division_idx" | "voltro_lb_league_members_league_idx">;
|
|
605
|
+
|
|
606
|
+
/** One receipt per league close request: the movements it applied, returned on retry. */
|
|
607
|
+
export declare const leaderboardLeagueRollsTable: Table<"_voltro_lb_league_rolls", FieldDefinitions<{
|
|
608
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
609
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
610
|
+
readonly league: ColumnBuilder<string, "text", boolean>;
|
|
611
|
+
readonly movements: ColumnBuilder<unknown, "json", boolean>;
|
|
612
|
+
readonly at: ColumnBuilder<Date, "timestamp", boolean>;
|
|
613
|
+
}>, true, never>;
|
|
614
|
+
|
|
615
|
+
export declare const leaderboardPeriodsTable: Table<"_voltro_lb_periods", FieldDefinitions<{
|
|
616
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
617
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
618
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
619
|
+
readonly startsAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
620
|
+
readonly endsAt: ColumnBuilder<Date | null, "timestamp", boolean>;
|
|
621
|
+
readonly state: ColumnBuilder<"closed" | "active" | "archived", "text", boolean>;
|
|
622
|
+
readonly summary: ColumnBuilder<unknown, "json", boolean>;
|
|
623
|
+
readonly previousPeriodId: ColumnBuilder<string | null, "text", boolean>;
|
|
624
|
+
readonly requestKey: ColumnBuilder<string | null, "text", boolean>;
|
|
625
|
+
}>, true, never>;
|
|
626
|
+
|
|
627
|
+
export declare interface LeaderboardPeriodSummary {
|
|
628
|
+
readonly participants: number;
|
|
629
|
+
readonly top: ReadonlyArray<RankedLeaderboardRecord>;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/** A summary selector may only retain exact records from the captured snapshot. */
|
|
633
|
+
export declare type LeaderboardPeriodSummarySlot = (records: ReadonlyArray<RankedLeaderboardRecord>) => LeaderboardPeriodSummary;
|
|
634
|
+
|
|
635
|
+
/** Complete ordered record identities. The adapter supplies consecutive ordinal
|
|
636
|
+
* ranks and all values from its SQL snapshot, never from strategy output. */
|
|
637
|
+
export declare type LeaderboardRankQuery = (context: LeaderboardRankQueryContext) => Effect.Effect<ReadonlyArray<string>, LeaderboardError>;
|
|
638
|
+
|
|
639
|
+
/** The admitted complete SQL snapshot is detached from the storage rows. A
|
|
640
|
+
* dialect implementation may use the declared read capability; writes are not
|
|
641
|
+
* part of this strategy's contract. Every returned ID must belong to records. */
|
|
642
|
+
export declare interface LeaderboardRankQueryContext {
|
|
643
|
+
readonly tenantId: string;
|
|
644
|
+
readonly board: string;
|
|
645
|
+
readonly periodId: string;
|
|
646
|
+
/** null is the global view; a value is the admitted owner's current cohort. */
|
|
647
|
+
readonly bucketId: string | null;
|
|
648
|
+
readonly sort: LeaderboardSort;
|
|
649
|
+
readonly maxRecords: number;
|
|
650
|
+
readonly records: ReadonlyArray<LeaderboardRankRecord>;
|
|
651
|
+
readonly tiebreak: LeaderboardTiebreak;
|
|
652
|
+
readonly query: DataStore['query'];
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
declare interface LeaderboardRankRecord {
|
|
656
|
+
readonly id: string;
|
|
657
|
+
readonly tenantId: string;
|
|
658
|
+
readonly board: string;
|
|
659
|
+
readonly periodId: string;
|
|
660
|
+
readonly ownerId: string;
|
|
661
|
+
readonly score: string;
|
|
662
|
+
readonly subscore: string;
|
|
663
|
+
readonly updatedAt: number;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export declare const leaderboardRatingMatchesTable: Table<"_voltro_lb_rating_matches", FieldDefinitions<{
|
|
667
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
668
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
669
|
+
readonly pool: ColumnBuilder<string, "text", boolean>;
|
|
670
|
+
readonly matchId: ColumnBuilder<string | null, "text", boolean>;
|
|
671
|
+
readonly requestKey: ColumnBuilder<string, "text", boolean>;
|
|
672
|
+
readonly state: ColumnBuilder<"erased" | "applied" | "prepared", "text", boolean>;
|
|
673
|
+
readonly input: ColumnBuilder<unknown, "json", boolean>;
|
|
674
|
+
readonly participants: ColumnBuilder<number, "integer", boolean>;
|
|
675
|
+
readonly preparedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
676
|
+
readonly appliedAt: ColumnBuilder<Date | null, "timestamp", boolean>;
|
|
677
|
+
}>, true, never>;
|
|
678
|
+
|
|
679
|
+
export declare const leaderboardRatingPoolsTable: Table<"_voltro_lb_rating_pools", FieldDefinitions<{
|
|
680
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
681
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
682
|
+
readonly name: ColumnBuilder<string, "text", boolean>;
|
|
683
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
684
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
685
|
+
}>, true, never>;
|
|
686
|
+
|
|
687
|
+
export declare const leaderboardRatingResultsTable: Table<"_voltro_lb_rating_results", FieldDefinitions<{
|
|
688
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
689
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
690
|
+
readonly pool: ColumnBuilder<string, "text", boolean>;
|
|
691
|
+
readonly matchKey: ColumnBuilder<string, "text", boolean>;
|
|
692
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
693
|
+
readonly previous: ColumnBuilder<unknown, "json", boolean>;
|
|
694
|
+
readonly current: ColumnBuilder<unknown, "json", boolean>;
|
|
695
|
+
readonly at: ColumnBuilder<Date, "timestamp", boolean>;
|
|
696
|
+
}>, true, never>;
|
|
697
|
+
|
|
698
|
+
export declare const leaderboardRatingsTable: Table<"_voltro_lb_ratings", FieldDefinitions<{
|
|
699
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
700
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
701
|
+
readonly pool: ColumnBuilder<string, "text", boolean>;
|
|
702
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
703
|
+
readonly state: ColumnBuilder<unknown, "json", boolean>;
|
|
704
|
+
readonly games: ColumnBuilder<number, "integer", boolean>;
|
|
705
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
706
|
+
}>, true, never>;
|
|
707
|
+
|
|
708
|
+
declare type LeaderboardRecord = typeof LeaderboardRecordSchema.Type;
|
|
709
|
+
|
|
710
|
+
declare const LeaderboardRecordSchema: Schema.Struct<{
|
|
711
|
+
readonly id: Schema.String;
|
|
712
|
+
readonly board: Schema.String;
|
|
713
|
+
readonly periodId: Schema.String;
|
|
714
|
+
readonly ownerId: Schema.String;
|
|
715
|
+
readonly score: Schema.String;
|
|
716
|
+
readonly subscore: Schema.String;
|
|
717
|
+
readonly numSubmits: Schema.Number;
|
|
718
|
+
readonly metadata: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
719
|
+
readonly updatedAt: Schema.Number;
|
|
720
|
+
readonly bucket: Schema.NullOr<Schema.String>;
|
|
721
|
+
}>;
|
|
722
|
+
|
|
723
|
+
export declare const leaderboardRecordsTable: Table<"_voltro_lb_records", FieldDefinitions<{
|
|
724
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
725
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
726
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
727
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
728
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
729
|
+
readonly score: ColumnBuilder<string, "bigint", boolean>;
|
|
730
|
+
readonly subscore: ColumnBuilder<string, "bigint", boolean>;
|
|
731
|
+
readonly numSubmits: ColumnBuilder<number, "integer", boolean>;
|
|
732
|
+
readonly metadata: ColumnBuilder<unknown, "json", boolean>;
|
|
733
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
734
|
+
readonly bucket: ColumnBuilder<string | null, "text", boolean>;
|
|
735
|
+
}>, true, "voltro_lb_records_rank_idx">;
|
|
736
|
+
|
|
737
|
+
declare type LeaderboardSort = 'asc' | 'desc';
|
|
738
|
+
|
|
739
|
+
export declare interface LeaderboardStoreOptions {
|
|
740
|
+
readonly boards: ReadonlyArray<LeaderboardDescriptor<Schema.Codec<unknown, unknown>>>;
|
|
741
|
+
readonly tournaments?: ReadonlyArray<TournamentDescriptor>;
|
|
742
|
+
/** Leagues over declared, non-bucketed boards (`defineLeague`); a board belongs to at most one league. */
|
|
743
|
+
readonly leagues?: ReadonlyArray<LeagueDefinition>;
|
|
744
|
+
readonly ratingPools?: ReadonlyArray<RatingPoolDefinition>;
|
|
745
|
+
readonly ratingStrategies?: RatingStrategies;
|
|
746
|
+
/** Explicit verified service callers; none are authorized by default. System tasks are trusted. */
|
|
747
|
+
readonly allowedServices?: ReadonlyArray<string>;
|
|
748
|
+
readonly validate?: (input: SubmitLeaderboardInput, previous: LeaderboardRecord | null, tx: DataStore) => Effect.Effect<void, LeaderboardError>;
|
|
749
|
+
readonly tiebreak?: LeaderboardTiebreak;
|
|
750
|
+
readonly rankQuery?: LeaderboardRankQuery;
|
|
751
|
+
readonly bucketAssign?: LeaderboardBucketAssign;
|
|
752
|
+
readonly bucketStrategyVersion?: string;
|
|
753
|
+
readonly periodSummary?: LeaderboardPeriodSummarySlot;
|
|
754
|
+
readonly maxPeriodRows?: number;
|
|
755
|
+
readonly maxSummaryBytes?: number;
|
|
756
|
+
readonly maxMetadataBytes?: number;
|
|
757
|
+
readonly maxExportRows?: number;
|
|
758
|
+
readonly maxSubmissionsPerOwner?: number;
|
|
759
|
+
readonly now?: () => number;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/** Optional app-shaped discovery root. App configuration must provide actual
|
|
763
|
+
* Stage/Bracket services and privacy; exporting sources does not install them. */
|
|
764
|
+
export declare const leaderboardsTournamentSources: string;
|
|
765
|
+
|
|
766
|
+
export declare const leaderboardSubjectsTable: Table<"_voltro_lb_subject_admission", FieldDefinitions<{
|
|
767
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
768
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
769
|
+
readonly subjectId: ColumnBuilder<string | null, "text", boolean>;
|
|
770
|
+
readonly erased: ColumnBuilder<boolean, "boolean", boolean>;
|
|
771
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
772
|
+
}>, true, never>;
|
|
773
|
+
|
|
774
|
+
export declare const leaderboardSubmissionsTable: Table<"_voltro_lb_submissions", FieldDefinitions<{
|
|
775
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
776
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
777
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
778
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
779
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
780
|
+
readonly requestKey: ColumnBuilder<string, "text", boolean>;
|
|
781
|
+
readonly record: ColumnBuilder<unknown, "json", boolean>;
|
|
782
|
+
readonly roomId: ColumnBuilder<string | null, "text", boolean>;
|
|
783
|
+
readonly matchId: ColumnBuilder<string | null, "text", boolean>;
|
|
784
|
+
readonly at: ColumnBuilder<Date, "timestamp", boolean>;
|
|
785
|
+
readonly tournamentId: ColumnBuilder<string | null, "text", boolean>;
|
|
786
|
+
}>, true, never>;
|
|
787
|
+
|
|
788
|
+
export declare const leaderboardTables: readonly [ Table<"_voltro_lb_boards", FieldDefinitions<{
|
|
789
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
790
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
791
|
+
readonly name: ColumnBuilder<string, "text", boolean>;
|
|
792
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
793
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
794
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
795
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
796
|
+
}>, true, never>, Table<"_voltro_lb_records", FieldDefinitions<{
|
|
797
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
798
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
799
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
800
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
801
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
802
|
+
readonly score: ColumnBuilder<string, "bigint", boolean>;
|
|
803
|
+
readonly subscore: ColumnBuilder<string, "bigint", boolean>;
|
|
804
|
+
readonly numSubmits: ColumnBuilder<number, "integer", boolean>;
|
|
805
|
+
readonly metadata: ColumnBuilder<unknown, "json", boolean>;
|
|
806
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
807
|
+
readonly bucket: ColumnBuilder<string | null, "text", boolean>;
|
|
808
|
+
}>, true, "voltro_lb_records_rank_idx">, Table<"_voltro_lb_periods", FieldDefinitions<{
|
|
809
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
810
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
811
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
812
|
+
readonly startsAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
813
|
+
readonly endsAt: ColumnBuilder<Date | null, "timestamp", boolean>;
|
|
814
|
+
readonly state: ColumnBuilder<"closed" | "active" | "archived", "text", boolean>;
|
|
815
|
+
readonly summary: ColumnBuilder<unknown, "json", boolean>;
|
|
816
|
+
readonly previousPeriodId: ColumnBuilder<string | null, "text", boolean>;
|
|
817
|
+
readonly requestKey: ColumnBuilder<string | null, "text", boolean>;
|
|
818
|
+
}>, true, never>, Table<"_voltro_lb_submissions", FieldDefinitions<{
|
|
819
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
820
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
821
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
822
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
823
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
824
|
+
readonly requestKey: ColumnBuilder<string, "text", boolean>;
|
|
825
|
+
readonly record: ColumnBuilder<unknown, "json", boolean>;
|
|
826
|
+
readonly roomId: ColumnBuilder<string | null, "text", boolean>;
|
|
827
|
+
readonly matchId: ColumnBuilder<string | null, "text", boolean>;
|
|
828
|
+
readonly at: ColumnBuilder<Date, "timestamp", boolean>;
|
|
829
|
+
readonly tournamentId: ColumnBuilder<string | null, "text", boolean>;
|
|
830
|
+
}>, true, never>, Table<"_voltro_lb_subject_admission", FieldDefinitions<{
|
|
831
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
832
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
833
|
+
readonly subjectId: ColumnBuilder<string | null, "text", boolean>;
|
|
834
|
+
readonly erased: ColumnBuilder<boolean, "boolean", boolean>;
|
|
835
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
836
|
+
}>, true, never>, Table<"_voltro_lb_tournaments", FieldDefinitions<{
|
|
837
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
838
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
839
|
+
readonly name: ColumnBuilder<string, "text", boolean>;
|
|
840
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
841
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
842
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
843
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
844
|
+
readonly numEntries: ColumnBuilder<number, "integer", boolean>;
|
|
845
|
+
}>, true, never>, Table<"_voltro_lb_tournament_entries", FieldDefinitions<{
|
|
846
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
847
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
848
|
+
readonly tournamentId: ColumnBuilder<string, "text", boolean>;
|
|
849
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
850
|
+
readonly joinedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
851
|
+
readonly attemptsLeft: ColumnBuilder<number, "integer", boolean>;
|
|
852
|
+
}>, true, never>, Table<"_voltro_lb_rating_pools", FieldDefinitions<{
|
|
853
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
854
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
855
|
+
readonly name: ColumnBuilder<string, "text", boolean>;
|
|
856
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
857
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
858
|
+
}>, true, never>, Table<"_voltro_lb_ratings", FieldDefinitions<{
|
|
859
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
860
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
861
|
+
readonly pool: ColumnBuilder<string, "text", boolean>;
|
|
862
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
863
|
+
readonly state: ColumnBuilder<unknown, "json", boolean>;
|
|
864
|
+
readonly games: ColumnBuilder<number, "integer", boolean>;
|
|
865
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
866
|
+
}>, true, never>, Table<"_voltro_lb_rating_matches", FieldDefinitions<{
|
|
867
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
868
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
869
|
+
readonly pool: ColumnBuilder<string, "text", boolean>;
|
|
870
|
+
readonly matchId: ColumnBuilder<string | null, "text", boolean>;
|
|
871
|
+
readonly requestKey: ColumnBuilder<string, "text", boolean>;
|
|
872
|
+
readonly state: ColumnBuilder<"erased" | "applied" | "prepared", "text", boolean>;
|
|
873
|
+
readonly input: ColumnBuilder<unknown, "json", boolean>;
|
|
874
|
+
readonly participants: ColumnBuilder<number, "integer", boolean>;
|
|
875
|
+
readonly preparedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
876
|
+
readonly appliedAt: ColumnBuilder<Date | null, "timestamp", boolean>;
|
|
877
|
+
}>, true, never>, Table<"_voltro_lb_rating_results", FieldDefinitions<{
|
|
878
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
879
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
880
|
+
readonly pool: ColumnBuilder<string, "text", boolean>;
|
|
881
|
+
readonly matchKey: ColumnBuilder<string, "text", boolean>;
|
|
882
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
883
|
+
readonly previous: ColumnBuilder<unknown, "json", boolean>;
|
|
884
|
+
readonly current: ColumnBuilder<unknown, "json", boolean>;
|
|
885
|
+
readonly at: ColumnBuilder<Date, "timestamp", boolean>;
|
|
886
|
+
}>, true, never>, Table<"_voltro_lb_bucket_assignments", FieldDefinitions<{
|
|
887
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
888
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
889
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
890
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
891
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
892
|
+
readonly bucket: ColumnBuilder<string, "text", boolean>;
|
|
893
|
+
readonly ordinal: ColumnBuilder<number, "integer", boolean>;
|
|
894
|
+
readonly groupKey: ColumnBuilder<string, "text", boolean>;
|
|
895
|
+
readonly group: ColumnBuilder<string | null, "text", boolean>;
|
|
896
|
+
readonly assignedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
897
|
+
}>, true, "voltro_lb_bucket_assignments_group_idx">, Table<"_voltro_lb_league_members", FieldDefinitions<{
|
|
898
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
899
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
900
|
+
readonly league: ColumnBuilder<string, "text", boolean>;
|
|
901
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
902
|
+
readonly division: ColumnBuilder<string, "text", boolean>;
|
|
903
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
904
|
+
}>, true, "voltro_lb_league_members_division_idx" | "voltro_lb_league_members_league_idx">, Table<"_voltro_lb_league_rolls", FieldDefinitions<{
|
|
905
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
906
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
907
|
+
readonly league: ColumnBuilder<string, "text", boolean>;
|
|
908
|
+
readonly movements: ColumnBuilder<unknown, "json", boolean>;
|
|
909
|
+
readonly at: ColumnBuilder<Date, "timestamp", boolean>;
|
|
910
|
+
}>, true, never>];
|
|
911
|
+
|
|
912
|
+
declare type LeaderboardTiebreak = (left: LeaderboardRankRecord, right: LeaderboardRankRecord) => number;
|
|
913
|
+
|
|
914
|
+
export declare const leaderboardTournamentEntriesTable: Table<"_voltro_lb_tournament_entries", FieldDefinitions<{
|
|
915
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
916
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
917
|
+
readonly tournamentId: ColumnBuilder<string, "text", boolean>;
|
|
918
|
+
readonly ownerId: ColumnBuilder<string, "text", boolean>;
|
|
919
|
+
readonly joinedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
920
|
+
readonly attemptsLeft: ColumnBuilder<number, "integer", boolean>;
|
|
921
|
+
}>, true, never>;
|
|
922
|
+
|
|
923
|
+
export declare const leaderboardTournamentsTable: Table<"_voltro_lb_tournaments", FieldDefinitions<{
|
|
924
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
925
|
+
readonly tenantId: ColumnBuilder<string, "text", boolean>;
|
|
926
|
+
readonly name: ColumnBuilder<string, "text", boolean>;
|
|
927
|
+
readonly board: ColumnBuilder<string, "text", boolean>;
|
|
928
|
+
readonly periodId: ColumnBuilder<string, "text", boolean>;
|
|
929
|
+
readonly config: ColumnBuilder<unknown, "json", boolean>;
|
|
930
|
+
readonly admission: ColumnBuilder<number, "integer", boolean>;
|
|
931
|
+
readonly numEntries: ColumnBuilder<number, "integer", boolean>;
|
|
932
|
+
}>, true, never>;
|
|
933
|
+
|
|
934
|
+
/** A league: ordered division boards (best first) whose periods close together; at each
|
|
935
|
+
* close the best `promote` of a division move up and the worst `relegate` move down. */
|
|
936
|
+
declare interface LeagueDefinition {
|
|
937
|
+
readonly name: string;
|
|
938
|
+
/** Board names, top division first; each a declared, non-bucketed board of this plugin. */
|
|
939
|
+
readonly divisions: readonly [string, string, ...string[]];
|
|
940
|
+
readonly promote: number;
|
|
941
|
+
readonly relegate: number;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
declare interface LeagueMovement {
|
|
945
|
+
readonly ownerId: string;
|
|
946
|
+
readonly from: string;
|
|
947
|
+
readonly to: string;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
export declare interface LeagueRollScheduleOptions {
|
|
951
|
+
readonly league: string;
|
|
952
|
+
/** When the league closes, e.g. `'0 0 * * 1'` for Mondays at midnight. */
|
|
953
|
+
readonly cron: string;
|
|
954
|
+
readonly timezone?: string;
|
|
955
|
+
/** Tenants per page (default 100) and pages per run (default 100). */
|
|
956
|
+
readonly pageSize?: number;
|
|
957
|
+
readonly maxPages?: number;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
declare interface OpenSkillOptions {
|
|
961
|
+
readonly beta?: number;
|
|
962
|
+
readonly tau?: number;
|
|
963
|
+
readonly kappa?: number;
|
|
964
|
+
readonly ordinalZ?: number;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
export declare type PrepareRatingMatchInput = typeof PrepareRatingMatchSchema.Type;
|
|
968
|
+
|
|
969
|
+
declare const PrepareRatingMatchSchema: Schema.Struct<{
|
|
970
|
+
readonly tenantId: Schema.NonEmptyString;
|
|
971
|
+
readonly pool: Schema.NonEmptyString;
|
|
972
|
+
readonly matchId: Schema.NonEmptyString;
|
|
973
|
+
readonly teams: Schema.$Array<Schema.$Array<Schema.Struct<{
|
|
974
|
+
readonly ownerId: Schema.NonEmptyString;
|
|
975
|
+
readonly weight: Schema.optional<Schema.Number>;
|
|
976
|
+
}>>>;
|
|
977
|
+
readonly ranks: Schema.$Array<Schema.Number>;
|
|
978
|
+
}>;
|
|
979
|
+
|
|
980
|
+
declare interface Provision extends TournamentRoomWork {
|
|
981
|
+
readonly roomId: string | null;
|
|
982
|
+
readonly epoch: number | null;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
declare interface RankedLeaderboardRecord extends LeaderboardRankRecord {
|
|
986
|
+
readonly rank: number;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
export declare interface RatingDecayContext extends RatingPlacementContext {
|
|
990
|
+
readonly state: RatingState;
|
|
991
|
+
readonly games: number;
|
|
992
|
+
readonly updatedAt: number;
|
|
993
|
+
readonly elapsedMs: number;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
export declare type RatingDecayPolicy = (context: RatingDecayContext) => RatingState;
|
|
997
|
+
|
|
998
|
+
export declare interface RatingMatchReceipt {
|
|
999
|
+
readonly pool: string;
|
|
1000
|
+
readonly matchId: string;
|
|
1001
|
+
readonly participants: number;
|
|
1002
|
+
readonly state: 'prepared' | 'applied';
|
|
1003
|
+
readonly preparedAt: number;
|
|
1004
|
+
readonly appliedAt: number | null;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
export declare interface RatingPlacementContext {
|
|
1008
|
+
readonly tenantId: string;
|
|
1009
|
+
readonly ownerId: string;
|
|
1010
|
+
readonly pool: ResolvedRatingPool;
|
|
1011
|
+
readonly at: number;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export declare type RatingPlacementPolicy = (context: RatingPlacementContext) => RatingState;
|
|
1015
|
+
|
|
1016
|
+
export declare type RatingPoolDefinition = {
|
|
1017
|
+
readonly name: string;
|
|
1018
|
+
readonly algorithm: 'elo';
|
|
1019
|
+
readonly initial?: {
|
|
1020
|
+
readonly rating: number;
|
|
1021
|
+
};
|
|
1022
|
+
readonly options?: EloOptions;
|
|
1023
|
+
} | {
|
|
1024
|
+
readonly name: string;
|
|
1025
|
+
readonly algorithm: 'openskill';
|
|
1026
|
+
readonly initial?: {
|
|
1027
|
+
readonly mu: number;
|
|
1028
|
+
readonly sigma: number;
|
|
1029
|
+
};
|
|
1030
|
+
readonly options?: OpenSkillOptions;
|
|
1031
|
+
} | {
|
|
1032
|
+
readonly name: string;
|
|
1033
|
+
readonly algorithm: 'glicko2';
|
|
1034
|
+
readonly initial?: {
|
|
1035
|
+
readonly rating: number;
|
|
1036
|
+
readonly deviation: number;
|
|
1037
|
+
readonly volatility: number;
|
|
1038
|
+
};
|
|
1039
|
+
readonly options?: Glicko2Options;
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
export declare interface RatingRateContext {
|
|
1043
|
+
readonly tenantId: string;
|
|
1044
|
+
readonly matchId: string;
|
|
1045
|
+
readonly pool: ResolvedRatingPool;
|
|
1046
|
+
readonly at: number;
|
|
1047
|
+
readonly teams: ReadonlyArray<ReadonlyArray<RatingStrategyPlayer>>;
|
|
1048
|
+
readonly ranks: ReadonlyArray<number>;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
export declare type RatingRateStrategy = (context: RatingRateContext) => ReadonlyArray<RatingStrategyResult>;
|
|
1052
|
+
|
|
1053
|
+
export declare type RatingState = typeof RatingStateSchema.Type;
|
|
1054
|
+
|
|
1055
|
+
declare const RatingStateSchema: Schema.Union<readonly [Schema.Struct<{
|
|
1056
|
+
readonly algorithm: Schema.Literal<"elo">;
|
|
1057
|
+
readonly rating: Schema.Number;
|
|
1058
|
+
}>, Schema.Struct<{
|
|
1059
|
+
readonly algorithm: Schema.Literal<"openskill">;
|
|
1060
|
+
readonly mu: Schema.Number;
|
|
1061
|
+
readonly sigma: Schema.Number;
|
|
1062
|
+
}>, Schema.Struct<{
|
|
1063
|
+
readonly algorithm: Schema.Literal<"glicko2">;
|
|
1064
|
+
readonly rating: Schema.Number;
|
|
1065
|
+
readonly deviation: Schema.Number;
|
|
1066
|
+
readonly volatility: Schema.Number;
|
|
1067
|
+
}>]>;
|
|
1068
|
+
|
|
1069
|
+
export declare interface RatingStrategies {
|
|
1070
|
+
/** Required for any custom callback. Change it whenever rule meaning changes;
|
|
1071
|
+
* the SQL pool configuration refuses conflicting versions across writers. */
|
|
1072
|
+
readonly version?: string;
|
|
1073
|
+
readonly rate?: RatingRateStrategy;
|
|
1074
|
+
readonly placementPolicy?: RatingPlacementPolicy;
|
|
1075
|
+
readonly decay?: RatingDecayPolicy;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
export declare interface RatingStrategyPlayer {
|
|
1079
|
+
readonly ownerId: string;
|
|
1080
|
+
readonly state: RatingState;
|
|
1081
|
+
readonly games: number;
|
|
1082
|
+
readonly updatedAt: number | null;
|
|
1083
|
+
readonly weight: number;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
export declare interface RatingStrategyResult {
|
|
1087
|
+
readonly ownerId: string;
|
|
1088
|
+
readonly state: RatingState;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/** Trusted server read; callers still own current authorization. Complete
|
|
1092
|
+
* state admission precedes projection, and no participant enters its result. */
|
|
1093
|
+
export declare const readBracketAdmissionWindow: (store: DataStore, offered: BracketAdmissionScope) => Effect.Effect<{
|
|
1094
|
+
readonly phase: BracketAdmissionStatus["phase"];
|
|
1095
|
+
readonly definition: BracketAdmissionDefinition;
|
|
1096
|
+
}, LeaderboardError>;
|
|
1097
|
+
|
|
1098
|
+
/** Reports a verified match result, then queues `tournament.advance` for the tournament (the
|
|
1099
|
+
* report ID is the run key), so the next ready matches get their Rooms without another call.
|
|
1100
|
+
* Runs per tournament one at a time; a start during a run waits instead of being dropped. */
|
|
1101
|
+
export declare const reportTournamentResult: (ctx: TournamentWorkflowStarter, tournaments: Pick<TournamentBracketService, "report">, subject: Subject, scope: BracketAdmissionScope, report: TournamentResultReport) => Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1102
|
+
|
|
1103
|
+
/** Borrowed SQL is the roster truth. No workflow, timer, cache or Rooms host is
|
|
1104
|
+
* created. Explicit current guards and all-node privacy remain app-owned. */
|
|
1105
|
+
export declare const resolveBracketAdmissionOptions: (input: BracketAdmissionOptions) => BracketAdmissionOptions;
|
|
1106
|
+
|
|
1107
|
+
export declare interface ResolvedRatingPool {
|
|
1108
|
+
readonly name: string;
|
|
1109
|
+
readonly algorithm: RatingState['algorithm'];
|
|
1110
|
+
readonly initial: RatingState;
|
|
1111
|
+
readonly options: EloOptions | OpenSkillOptions | Glicko2Options;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/** Durable SQL graph and external-work journal. All external services are
|
|
1115
|
+
* explicitly supplied; callbacks are requirements, not distributed proof. */
|
|
1116
|
+
export declare const resolveTournamentBracketOptions: (input: TournamentBracketOptions) => TournamentBracketOptions;
|
|
1117
|
+
|
|
1118
|
+
export declare const resolveTournamentStageOptions: (options: TournamentStageOptions) => TournamentStageOptions;
|
|
1119
|
+
|
|
1120
|
+
declare interface Result extends TournamentResultReport {
|
|
1121
|
+
readonly reportedWinnerId: string;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
export declare interface RollLeaderboardPeriodInput {
|
|
1125
|
+
readonly tenantId: string;
|
|
1126
|
+
readonly board: string;
|
|
1127
|
+
readonly requestId: string;
|
|
1128
|
+
readonly expectedPeriodId: string;
|
|
1129
|
+
/** Stable intended boundary, retained on retry; never supplied by a player. */
|
|
1130
|
+
readonly closedAt: number;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
export declare interface RollLeaderboardPeriodResult {
|
|
1134
|
+
readonly closedPeriodId: string;
|
|
1135
|
+
readonly activePeriodId: string;
|
|
1136
|
+
readonly closedAt: number;
|
|
1137
|
+
readonly summary: LeaderboardPeriodSummary;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
declare type ScoreOperator = 'best' | 'set' | 'increment' | 'decrement';
|
|
1141
|
+
|
|
1142
|
+
/** Trusted service submission, never a player score-intent payload. */
|
|
1143
|
+
declare interface SubmitLeaderboardInput {
|
|
1144
|
+
readonly tenantId: string;
|
|
1145
|
+
readonly board: string;
|
|
1146
|
+
readonly ownerId: string;
|
|
1147
|
+
readonly submissionId: string;
|
|
1148
|
+
readonly score: string;
|
|
1149
|
+
readonly subscore?: string;
|
|
1150
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
1151
|
+
readonly roomId?: string;
|
|
1152
|
+
readonly matchId?: string;
|
|
1153
|
+
readonly tournamentId?: string;
|
|
1154
|
+
readonly bucketSkill?: number;
|
|
1155
|
+
readonly bucketCohort?: string;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
export declare const summarizeTournamentStatus: (status: TournamentBracketStatus) => TournamentWorkflowSummary;
|
|
1159
|
+
|
|
1160
|
+
export declare const TOURNAMENT_BRACKETS_TABLE = "_voltro_brackets";
|
|
1161
|
+
|
|
1162
|
+
export declare const tournamentAdvanceExecutor: (context: Pick<AppContext, "request">) => (input: TournamentAdvancePayload) => Effect.Effect<{
|
|
1163
|
+
readonly phase: "cancelled" | "complete" | "active" | "paused" | "erasing";
|
|
1164
|
+
readonly ready: number;
|
|
1165
|
+
readonly completed: number;
|
|
1166
|
+
readonly waiting: number;
|
|
1167
|
+
readonly unresolvedDisputes: number;
|
|
1168
|
+
}, LeaderboardError, TournamentBracketPort | WorkflowEngine | WorkflowInstance>;
|
|
1169
|
+
|
|
1170
|
+
declare const TournamentAdvancePayload: Schema.Struct<{
|
|
1171
|
+
readonly tenantId: Schema.String;
|
|
1172
|
+
readonly tournamentId: Schema.String;
|
|
1173
|
+
readonly runKey: Schema.String;
|
|
1174
|
+
}>;
|
|
1175
|
+
|
|
1176
|
+
declare type TournamentAdvancePayload = typeof TournamentAdvancePayload.Type;
|
|
1177
|
+
|
|
1178
|
+
export declare type TournamentBinding = ({
|
|
1179
|
+
readonly backend: 'sql';
|
|
1180
|
+
readonly options: TournamentBracketOptions;
|
|
1181
|
+
} | {
|
|
1182
|
+
readonly backend: 'custom';
|
|
1183
|
+
readonly version: string;
|
|
1184
|
+
readonly service: TournamentBracketService;
|
|
1185
|
+
readonly sources: ReadonlyArray<string>;
|
|
1186
|
+
}) & {
|
|
1187
|
+
readonly stage?: TournamentStageBinding;
|
|
1188
|
+
readonly workflowSources?: string;
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
export declare interface TournamentBracketDefinition {
|
|
1192
|
+
readonly format: TournamentBracketFormat;
|
|
1193
|
+
readonly entrants: ReadonlyArray<TournamentEntrant>;
|
|
1194
|
+
/** Swiss only: rounds to play (default: enough to separate a winner, ceil(log2 entrants)). */
|
|
1195
|
+
readonly rounds?: number | undefined;
|
|
1196
|
+
/** Immutable application prize/Room/no-show policy identity, not a price. */
|
|
1197
|
+
readonly ruleVersion: string;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
export declare interface TournamentBracketExport {
|
|
1201
|
+
readonly tournamentId: string;
|
|
1202
|
+
readonly phase: BracketState['phase'];
|
|
1203
|
+
readonly seed: number;
|
|
1204
|
+
readonly matches: ReadonlyArray<{
|
|
1205
|
+
readonly matchId: string;
|
|
1206
|
+
readonly roomId: string;
|
|
1207
|
+
readonly won: boolean;
|
|
1208
|
+
}>;
|
|
1209
|
+
readonly disputes: ReadonlyArray<TournamentDisputeIntent & {
|
|
1210
|
+
readonly resolutionId: string | null;
|
|
1211
|
+
}>;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
export declare type TournamentBracketFormat = 'single-elimination' | 'double-elimination' | 'round-robin' | 'swiss';
|
|
1215
|
+
|
|
1216
|
+
export declare const tournamentBracketLayer: (store: DataStore, options: TournamentBracketOptions) => Layer.Layer<TournamentBracketPort>;
|
|
1217
|
+
|
|
1218
|
+
/** A bracket match with the Room it plays in, once one was provisioned. */
|
|
1219
|
+
export declare type TournamentBracketMatch = (BracketProgress['matches'][number] | DoubleEliminationProgress['matches'][number]) & {
|
|
1220
|
+
readonly roomId: string | null;
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
export declare interface TournamentBracketOptions {
|
|
1224
|
+
readonly epochNow: () => number;
|
|
1225
|
+
readonly maxTenantTournaments?: number;
|
|
1226
|
+
authorize(subject: Subject, scope: BracketAdmissionScope, operation: 'create' | 'report' | 'dispute' | 'resolve' | 'advance' | 'status'): Effect.Effect<void, LeaderboardError>;
|
|
1227
|
+
/** Actual durable Room creation/reservations: same request returns same Room,
|
|
1228
|
+
* enforces private roster/options/current grants, and awaits accepted work. */
|
|
1229
|
+
provisionRoom(work: TournamentRoomWork): Effect.Effect<TournamentRoomReceipt, LeaderboardError>;
|
|
1230
|
+
verifyResult(subject: Subject, scope: BracketAdmissionScope, report: TournamentResultReport): Effect.Effect<void, LeaderboardError>;
|
|
1231
|
+
/** The real economy/inventory/Inbox participant owns atomic idempotency. */
|
|
1232
|
+
settleChampion(work: BracketAdmissionScope & {
|
|
1233
|
+
readonly requestId: string;
|
|
1234
|
+
readonly winnerId: string;
|
|
1235
|
+
readonly ruleVersion: string;
|
|
1236
|
+
}): Effect.Effect<void, LeaderboardError>;
|
|
1237
|
+
withdrawSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
1238
|
+
/** Must withdraw pending request identities too, even with lost Room replies. */
|
|
1239
|
+
withdrawTournament(scope: BracketAdmissionScope, request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
1240
|
+
authorizeExport(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
/** Trusted server coordinator contract; SQL types are erased imports only. */
|
|
1244
|
+
export declare class TournamentBracketPort extends TournamentBracketPort_base {
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
declare const TournamentBracketPort_base: Context.ServiceClass<TournamentBracketPort, "@voltro/TournamentBracketPort", {
|
|
1248
|
+
create(subject: Subject, scope: BracketAdmissionScope, definition: TournamentBracketDefinition): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1249
|
+
report(subject: Subject, scope: BracketAdmissionScope, report: TournamentResultReport): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1250
|
+
dispute(subject: Subject, scope: BracketAdmissionScope, intent: TournamentDisputeIntent): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1251
|
+
resolve(subject: Subject, scope: BracketAdmissionScope, intent: TournamentDisputeResolution): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1252
|
+
advance(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1253
|
+
status(subject: Subject, scope: BracketAdmissionScope): Effect.Effect<TournamentBracketStatus, LeaderboardError>;
|
|
1254
|
+
exportSubject(request: PluginPrivacyRequest): Effect.Effect<ReadonlyArray<TournamentBracketExport>, LeaderboardError>;
|
|
1255
|
+
eraseSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
1256
|
+
}>;
|
|
1257
|
+
|
|
1258
|
+
export declare type TournamentBracketService = Context.Service.Shape<typeof TournamentBracketPort>;
|
|
1259
|
+
|
|
1260
|
+
/** Explicit ordinary schema contribution; no hidden startup or timer. */
|
|
1261
|
+
export declare const tournamentBracketsTable: TableLike;
|
|
1262
|
+
|
|
1263
|
+
export declare interface TournamentBracketStatus {
|
|
1264
|
+
readonly phase: BracketState['phase'];
|
|
1265
|
+
readonly format: TournamentBracketFormat;
|
|
1266
|
+
readonly champion: string | null;
|
|
1267
|
+
readonly matches: ReadonlyArray<TournamentBracketMatch>;
|
|
1268
|
+
readonly unresolvedDisputes: number;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
export declare interface TournamentConfiguration {
|
|
1272
|
+
readonly backend: 'sql' | 'custom';
|
|
1273
|
+
readonly version: string;
|
|
1274
|
+
readonly maxTenantTournaments: number | null;
|
|
1275
|
+
readonly stage: {
|
|
1276
|
+
readonly backend: 'sql' | 'custom';
|
|
1277
|
+
readonly version: string;
|
|
1278
|
+
} | null;
|
|
1279
|
+
readonly workflowSource: 'default' | 'custom' | null;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
declare interface TournamentDefinition {
|
|
1283
|
+
readonly name: string;
|
|
1284
|
+
readonly board: string;
|
|
1285
|
+
readonly startsAt: number;
|
|
1286
|
+
readonly endsAt: number;
|
|
1287
|
+
readonly maxEntries: number;
|
|
1288
|
+
readonly joinRequired?: boolean;
|
|
1289
|
+
readonly attemptsPerEntry?: number;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
declare interface TournamentDescriptor extends Omit<TournamentDefinition, 'joinRequired' | 'attemptsPerEntry'> {
|
|
1293
|
+
readonly kind: 'tournament';
|
|
1294
|
+
readonly format: 'time-window';
|
|
1295
|
+
readonly joinRequired: boolean;
|
|
1296
|
+
readonly attemptsPerEntry: number;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
export declare interface TournamentDisputeIntent {
|
|
1300
|
+
readonly disputeId: string;
|
|
1301
|
+
readonly matchId: string;
|
|
1302
|
+
readonly reason: 'result_mismatch' | 'no_show' | 'connection';
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
export declare interface TournamentDisputeResolution {
|
|
1306
|
+
readonly disputeId: string;
|
|
1307
|
+
readonly resolutionId: string;
|
|
1308
|
+
readonly winnerId: string;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
declare interface TournamentEntrant {
|
|
1312
|
+
readonly entrantId: string;
|
|
1313
|
+
readonly seed: number;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
/** A tournament stage's `notifyEntrants` participant: when registration or check-in opens, every
|
|
1317
|
+
* registered player gets an inbox message (at check-in only those not checked in yet). Each
|
|
1318
|
+
* message is keyed by the stage request and the player, so a retried reminder sends none twice. */
|
|
1319
|
+
export declare const tournamentInboxNotice: (liveops: TournamentInboxSource, admissions: () => {
|
|
1320
|
+
entrants(subject: ReturnType<typeof systemSubject>, scope: BracketAdmissionScope): Effect.Effect<BracketAdmissionEntrants, unknown>;
|
|
1321
|
+
}, options: TournamentInboxNoticeOptions) => (work: {
|
|
1322
|
+
readonly tenantId: string;
|
|
1323
|
+
readonly tournamentId: string;
|
|
1324
|
+
readonly phase: "registration" | "check-in";
|
|
1325
|
+
readonly requestId: string;
|
|
1326
|
+
}) => Effect.Effect<void, LeaderboardError>;
|
|
1327
|
+
|
|
1328
|
+
export declare interface TournamentInboxNoticeOptions {
|
|
1329
|
+
/** Inbox templates per stage phase; `tournamentId` and `phase` are passed as parameters. */
|
|
1330
|
+
readonly templates: {
|
|
1331
|
+
readonly registration: string;
|
|
1332
|
+
readonly 'check-in': string;
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
/** A tournament bracket's `settleChampion` participant: the champion gets an inbox message with
|
|
1337
|
+
* the prize attachments. The bracket's settlement request is the inbox request ID, so a retried
|
|
1338
|
+
* settlement sends one message. */
|
|
1339
|
+
export declare const tournamentInboxPrize: (liveops: TournamentInboxSource, options: TournamentInboxPrizeOptions) => (work: {
|
|
1340
|
+
readonly tenantId: string;
|
|
1341
|
+
readonly tournamentId: string;
|
|
1342
|
+
readonly requestId: string;
|
|
1343
|
+
readonly winnerId: string;
|
|
1344
|
+
}) => Effect.Effect<void, LeaderboardError>;
|
|
1345
|
+
|
|
1346
|
+
export declare interface TournamentInboxPrizeOptions {
|
|
1347
|
+
/** A declared LiveOps inbox template; `tournamentId` is passed as a message parameter. */
|
|
1348
|
+
readonly templateId: string;
|
|
1349
|
+
/** Rewards the champion claims from the message (`{ kind: 'currency', currency, amount }` or `{ kind: 'item', itemId, qty }`). */
|
|
1350
|
+
readonly attachments?: ReadonlyArray<Readonly<Record<string, unknown>>>;
|
|
1351
|
+
/** How long the message stays claimable; omitted: until claimed. */
|
|
1352
|
+
readonly expiresInMs?: number;
|
|
1353
|
+
readonly now?: () => number;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
/** The slice of an installed LiveOps plugin the prize participant uses (no package dependency). */
|
|
1357
|
+
export declare interface TournamentInboxSource {
|
|
1358
|
+
readonly inbox: () => {
|
|
1359
|
+
send(authority: ReturnType<typeof systemSubject>, tenantId: string, ownerId: string, input: {
|
|
1360
|
+
readonly requestId: string;
|
|
1361
|
+
readonly templateId: string;
|
|
1362
|
+
readonly params: Readonly<Record<string, string | number | boolean | null>>;
|
|
1363
|
+
readonly attachments: ReadonlyArray<Readonly<Record<string, unknown>>>;
|
|
1364
|
+
readonly expiresAt: number | null;
|
|
1365
|
+
}): Effect.Effect<unknown, unknown>;
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
export declare interface TournamentResultReport extends TournamentRoomReceipt {
|
|
1370
|
+
readonly matchId: string;
|
|
1371
|
+
readonly reportId: string;
|
|
1372
|
+
readonly winnerId: string;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
export declare interface TournamentRoomReceipt {
|
|
1376
|
+
readonly roomId: string;
|
|
1377
|
+
readonly epoch: number;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
export declare interface TournamentRoomWork extends BracketAdmissionScope {
|
|
1381
|
+
readonly matchId: string;
|
|
1382
|
+
readonly requestId: string;
|
|
1383
|
+
readonly left: string;
|
|
1384
|
+
readonly right: string;
|
|
1385
|
+
readonly ruleVersion: string;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
export declare type TournamentStageBinding = ({
|
|
1389
|
+
readonly backend: 'sql';
|
|
1390
|
+
readonly options: Omit<TournamentStageOptions, 'admissions' | 'brackets'>;
|
|
1391
|
+
} | {
|
|
1392
|
+
readonly backend: 'custom';
|
|
1393
|
+
readonly version: string;
|
|
1394
|
+
readonly service: TournamentStageService;
|
|
1395
|
+
}) & {
|
|
1396
|
+
readonly privacy: TournamentStagePrivacy;
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
/** Absolute sleeps retain the admitted instant on replay. Every checkpointed
|
|
1400
|
+
* result contains only configuration or aggregate status, never player data. */
|
|
1401
|
+
export declare const tournamentStageExecutor: (context: Pick<AppContext, "request">) => (input: TournamentStagePayload) => Effect.Effect<{
|
|
1402
|
+
readonly phase: "cancelled" | "complete" | "active" | "paused" | "erasing";
|
|
1403
|
+
readonly ready: number;
|
|
1404
|
+
readonly completed: number;
|
|
1405
|
+
readonly waiting: number;
|
|
1406
|
+
readonly unresolvedDisputes: number;
|
|
1407
|
+
}, LeaderboardError, TournamentBracketPort | TournamentStagePort | WorkflowEngine | WorkflowInstance>;
|
|
1408
|
+
|
|
1409
|
+
export declare const tournamentStageLayer: (store: DataStore, options: TournamentStageOptions) => Layer.Layer<TournamentStagePort>;
|
|
1410
|
+
|
|
1411
|
+
export declare interface TournamentStageOptions {
|
|
1412
|
+
readonly epochNow: () => number;
|
|
1413
|
+
readonly admissions: Pick<BracketAdmissionService, 'seal'>;
|
|
1414
|
+
readonly brackets: Pick<TournamentBracketService, 'create'>;
|
|
1415
|
+
authorize(subject: Subject, scope: BracketAdmissionScope, operation: 'window' | 'notify' | 'seed'): Effect.Effect<void, LeaderboardError>;
|
|
1416
|
+
/** Current SQL/rating/no-show preparation participant. Same request must
|
|
1417
|
+
* recover the same durable seed decision, never reread a changed prior. */
|
|
1418
|
+
seedRoster(work: TournamentStagePayload & BracketAdmissionRoster & {
|
|
1419
|
+
readonly requestId: string;
|
|
1420
|
+
}): Effect.Effect<ReadonlyArray<TournamentEntrant>, LeaderboardError>;
|
|
1421
|
+
/** Actual Inbox/Push idempotency and external withdrawal remain required. */
|
|
1422
|
+
notifyEntrants(work: TournamentStagePayload & {
|
|
1423
|
+
readonly phase: 'registration' | 'check-in';
|
|
1424
|
+
readonly requestId: string;
|
|
1425
|
+
}): Effect.Effect<void, LeaderboardError>;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
declare const TournamentStagePayload: Schema.Struct<{
|
|
1429
|
+
readonly format: Schema.Literals<readonly ["single-elimination", "double-elimination", "round-robin", "swiss"]>;
|
|
1430
|
+
readonly ruleVersion: Schema.String;
|
|
1431
|
+
readonly tenantId: Schema.String;
|
|
1432
|
+
readonly tournamentId: Schema.String;
|
|
1433
|
+
readonly runKey: Schema.String;
|
|
1434
|
+
}>;
|
|
1435
|
+
|
|
1436
|
+
declare type TournamentStagePayload = typeof TournamentStagePayload.Type;
|
|
1437
|
+
|
|
1438
|
+
export declare class TournamentStagePort extends TournamentStagePort_base {
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
declare const TournamentStagePort_base: Context.ServiceClass<TournamentStagePort, "@voltro/TournamentStagePort", {
|
|
1442
|
+
window(subject: Subject, payload: TournamentStagePayload): Effect.Effect<BracketAdmissionDefinition, LeaderboardError>;
|
|
1443
|
+
notify(subject: Subject, payload: TournamentStagePayload, phase: "registration" | "check-in"): Effect.Effect<{
|
|
1444
|
+
readonly notified: boolean;
|
|
1445
|
+
}, LeaderboardError>;
|
|
1446
|
+
seed(subject: Subject, payload: TournamentStagePayload): Effect.Effect<TournamentWorkflowSummary, LeaderboardError>;
|
|
1447
|
+
}>;
|
|
1448
|
+
|
|
1449
|
+
export declare interface TournamentStagePrivacy {
|
|
1450
|
+
/** Own subject data from actual seed/notification participants, no peer export. */
|
|
1451
|
+
exportSubject(request: PluginPrivacyRequest): Effect.Effect<unknown, LeaderboardError>;
|
|
1452
|
+
/** Permanently withdraw accepted seed/reminder work before subject cleanup. */
|
|
1453
|
+
eraseSubject(request: PluginPrivacyRequest): Effect.Effect<void, LeaderboardError>;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
export declare type TournamentStageService = Context.Service.Shape<typeof TournamentStagePort>;
|
|
1457
|
+
|
|
1458
|
+
/** The part of a handler's `ctx` this needs: the app's workflow service. */
|
|
1459
|
+
export declare interface TournamentWorkflowStarter {
|
|
1460
|
+
readonly workflows?: {
|
|
1461
|
+
start(workflowName: string, payload: unknown): Promise<unknown>;
|
|
1462
|
+
} | undefined;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
/** Counts only: no roster/winner/ratings/Room credentials in workflow journals. */
|
|
1466
|
+
declare const TournamentWorkflowSummary: Schema.Struct<{
|
|
1467
|
+
readonly phase: Schema.Literals<readonly ["active", "paused", "complete", "erasing", "cancelled"]>;
|
|
1468
|
+
readonly ready: Schema.Int;
|
|
1469
|
+
readonly completed: Schema.Int;
|
|
1470
|
+
/** Advance work still open: ready matches without a Room, plus the champion's settlement. */
|
|
1471
|
+
readonly waiting: Schema.Int;
|
|
1472
|
+
readonly unresolvedDisputes: Schema.Int;
|
|
1473
|
+
}>;
|
|
1474
|
+
|
|
1475
|
+
declare type TournamentWorkflowSummary = typeof TournamentWorkflowSummary.Type;
|
|
1476
|
+
|
|
1477
|
+
export { }
|