@tx5dr/plugin-api 1.7.12 → 2.5.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/README.md +475 -17
- package/dist/__tests__/adif.test.js +107 -0
- package/dist/__tests__/adif.test.js.map +1 -1
- package/dist/__tests__/capability-context.test.d.ts +2 -0
- package/dist/__tests__/capability-context.test.d.ts.map +1 -0
- package/dist/__tests__/capability-context.test.js +99 -0
- package/dist/__tests__/capability-context.test.js.map +1 -0
- package/dist/__tests__/testing-utils.test.js +234 -15
- package/dist/__tests__/testing-utils.test.js.map +1 -1
- package/dist/capabilities.d.ts +38 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +50 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/compatibility.d.ts +15 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +71 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/contest-logbook-ui/assets/contest-log.css +1 -0
- package/dist/contest-logbook-ui/assets/contest-log.js +40 -0
- package/dist/contest-logbook-ui/contest-log.html +13 -0
- package/dist/context.d.ts +125 -54
- package/dist/context.d.ts.map +1 -1
- package/dist/definition.d.ts +98 -21
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +8 -1
- package/dist/definition.js.map +1 -1
- package/dist/ft8/StandardQSOPluginRuntime.d.ts +142 -0
- package/dist/ft8/StandardQSOPluginRuntime.d.ts.map +1 -0
- package/dist/ft8/StandardQSOPluginRuntime.js +1592 -0
- package/dist/ft8/StandardQSOPluginRuntime.js.map +1 -0
- package/dist/ft8/index.d.ts +22 -0
- package/dist/ft8/index.d.ts.map +1 -0
- package/dist/ft8/index.js +176 -0
- package/dist/ft8/index.js.map +1 -0
- package/dist/helpers.d.ts +417 -132
- package/dist/helpers.d.ts.map +1 -1
- package/dist/hooks.d.ts +56 -34
- package/dist/hooks.d.ts.map +1 -1
- package/dist/host-dependencies.d.ts +101 -0
- package/dist/host-dependencies.d.ts.map +1 -1
- package/dist/index.d.ts +20 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +539 -13
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +9 -1
- package/dist/runtime.js.map +1 -1
- package/dist/settings.d.ts +31 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/simulation.d.ts +60 -0
- package/dist/simulation.d.ts.map +1 -0
- package/dist/simulation.js +2 -0
- package/dist/simulation.js.map +1 -0
- package/dist/sync.d.ts +98 -6
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +6 -0
- package/dist/sync.js.map +1 -1
- package/dist/testing/index.d.ts +74 -12
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +372 -105
- package/dist/testing/index.js.map +1 -1
- package/dist/toolkit/contest/CabrilloBuilder.d.ts +7 -0
- package/dist/toolkit/contest/CabrilloBuilder.d.ts.map +1 -0
- package/dist/toolkit/contest/CabrilloBuilder.js +11 -0
- package/dist/toolkit/contest/CabrilloBuilder.js.map +1 -0
- package/dist/toolkit/contest/ContestCategorySchema.d.ts +11 -0
- package/dist/toolkit/contest/ContestCategorySchema.d.ts.map +1 -0
- package/dist/toolkit/contest/ContestCategorySchema.js +6 -0
- package/dist/toolkit/contest/ContestCategorySchema.js.map +1 -0
- package/dist/toolkit/contest/ContestLogbook.d.ts +223 -0
- package/dist/toolkit/contest/ContestLogbook.d.ts.map +1 -0
- package/dist/toolkit/contest/ContestLogbook.js +845 -0
- package/dist/toolkit/contest/ContestLogbook.js.map +1 -0
- package/dist/toolkit/contest/ContestQsoEnvelopeAdapter.d.ts +28 -0
- package/dist/toolkit/contest/ContestQsoEnvelopeAdapter.d.ts.map +1 -0
- package/dist/toolkit/contest/ContestQsoEnvelopeAdapter.js +79 -0
- package/dist/toolkit/contest/ContestQsoEnvelopeAdapter.js.map +1 -0
- package/dist/toolkit/contest/ContestQsoProjector.d.ts +12 -0
- package/dist/toolkit/contest/ContestQsoProjector.d.ts.map +1 -0
- package/dist/toolkit/contest/ContestQsoProjector.js +13 -0
- package/dist/toolkit/contest/ContestQsoProjector.js.map +1 -0
- package/dist/toolkit/contest/ContestSessionNotifier.d.ts +9 -0
- package/dist/toolkit/contest/ContestSessionNotifier.d.ts.map +1 -0
- package/dist/toolkit/contest/ContestSessionNotifier.js +13 -0
- package/dist/toolkit/contest/ContestSessionNotifier.js.map +1 -0
- package/dist/toolkit/contest/ContestSessionRepository.d.ts +21 -0
- package/dist/toolkit/contest/ContestSessionRepository.d.ts.map +1 -0
- package/dist/toolkit/contest/ContestSessionRepository.js +27 -0
- package/dist/toolkit/contest/ContestSessionRepository.js.map +1 -0
- package/dist/toolkit/contest/DefaultContestSession.d.ts +105 -0
- package/dist/toolkit/contest/DefaultContestSession.d.ts.map +1 -0
- package/dist/toolkit/contest/DefaultContestSession.js +387 -0
- package/dist/toolkit/contest/DefaultContestSession.js.map +1 -0
- package/dist/toolkit/contest/DefaultContestWorkbench.d.ts +100 -0
- package/dist/toolkit/contest/DefaultContestWorkbench.d.ts.map +1 -0
- package/dist/toolkit/contest/DefaultContestWorkbench.js +33 -0
- package/dist/toolkit/contest/DefaultContestWorkbench.js.map +1 -0
- package/dist/toolkit/contest/FT8ContestDefinition.d.ts +83 -0
- package/dist/toolkit/contest/FT8ContestDefinition.d.ts.map +1 -0
- package/dist/toolkit/contest/FT8ContestDefinition.js +167 -0
- package/dist/toolkit/contest/FT8ContestDefinition.js.map +1 -0
- package/dist/toolkit/contest/FT8ContestModules.d.ts +178 -0
- package/dist/toolkit/contest/FT8ContestModules.d.ts.map +1 -0
- package/dist/toolkit/contest/FT8ContestModules.js +247 -0
- package/dist/toolkit/contest/FT8ContestModules.js.map +1 -0
- package/dist/toolkit/contest/FT8ContestPlugin.d.ts +55 -0
- package/dist/toolkit/contest/FT8ContestPlugin.d.ts.map +1 -0
- package/dist/toolkit/contest/FT8ContestPlugin.js +322 -0
- package/dist/toolkit/contest/FT8ContestPlugin.js.map +1 -0
- package/dist/toolkit/contest/FT8ContestTestKit.d.ts +12 -0
- package/dist/toolkit/contest/FT8ContestTestKit.d.ts.map +1 -0
- package/dist/toolkit/contest/FT8ContestTestKit.js +60 -0
- package/dist/toolkit/contest/FT8ContestTestKit.js.map +1 -0
- package/dist/toolkit/contest/contest-toolkit.test.d.ts +2 -0
- package/dist/toolkit/contest/contest-toolkit.test.d.ts.map +1 -0
- package/dist/toolkit/contest/contest-toolkit.test.js +1196 -0
- package/dist/toolkit/contest/contest-toolkit.test.js.map +1 -0
- package/dist/toolkit/contest/index.d.ts +14 -0
- package/dist/toolkit/contest/index.d.ts.map +1 -0
- package/dist/toolkit/contest/index.js +14 -0
- package/dist/toolkit/contest/index.js.map +1 -0
- package/dist/toolkit/index.d.ts +3 -0
- package/dist/toolkit/index.d.ts.map +1 -0
- package/dist/toolkit/index.js +3 -0
- package/dist/toolkit/index.js.map +1 -0
- package/dist/toolkit/parallel-qso/AuthorizationLease.d.ts +15 -0
- package/dist/toolkit/parallel-qso/AuthorizationLease.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/AuthorizationLease.js +25 -0
- package/dist/toolkit/parallel-qso/AuthorizationLease.js.map +1 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.d.ts +40 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.js +81 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.js.map +1 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.test.d.ts +2 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.test.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.test.js +31 -0
- package/dist/toolkit/parallel-qso/BoundedCallSessionController.test.js.map +1 -0
- package/dist/toolkit/parallel-qso/CompletionTracker.d.ts +20 -0
- package/dist/toolkit/parallel-qso/CompletionTracker.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/CompletionTracker.js +20 -0
- package/dist/toolkit/parallel-qso/CompletionTracker.js.map +1 -0
- package/dist/toolkit/parallel-qso/LaneFrequencyController.d.ts +19 -0
- package/dist/toolkit/parallel-qso/LaneFrequencyController.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/LaneFrequencyController.js +23 -0
- package/dist/toolkit/parallel-qso/LaneFrequencyController.js.map +1 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.d.ts +134 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.js +554 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.js.map +1 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.test.d.ts +2 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.test.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.test.js +470 -0
- package/dist/toolkit/parallel-qso/ParallelQSOCoordinator.test.js.map +1 -0
- package/dist/toolkit/parallel-qso/PostCompletionRecoveryLease.d.ts +20 -0
- package/dist/toolkit/parallel-qso/PostCompletionRecoveryLease.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/PostCompletionRecoveryLease.js +29 -0
- package/dist/toolkit/parallel-qso/PostCompletionRecoveryLease.js.map +1 -0
- package/dist/toolkit/parallel-qso/ProtocolLane.d.ts +50 -0
- package/dist/toolkit/parallel-qso/ProtocolLane.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/ProtocolLane.js +2 -0
- package/dist/toolkit/parallel-qso/ProtocolLane.js.map +1 -0
- package/dist/toolkit/parallel-qso/controllers.test.d.ts +2 -0
- package/dist/toolkit/parallel-qso/controllers.test.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/controllers.test.js +36 -0
- package/dist/toolkit/parallel-qso/controllers.test.js.map +1 -0
- package/dist/toolkit/parallel-qso/index.d.ts +8 -0
- package/dist/toolkit/parallel-qso/index.d.ts.map +1 -0
- package/dist/toolkit/parallel-qso/index.js +8 -0
- package/dist/toolkit/parallel-qso/index.js.map +1 -0
- package/dist/utils/adif.d.ts +1 -1
- package/dist/utils/adif.d.ts.map +1 -1
- package/dist/utils/adif.js +96 -51
- package/dist/utils/adif.js.map +1 -1
- package/dist/utils/qso-text-fields.d.ts +7 -1
- package/dist/utils/qso-text-fields.d.ts.map +1 -1
- package/dist/utils/qso-text-fields.js +74 -6
- package/dist/utils/qso-text-fields.js.map +1 -1
- package/package.json +28 -6
- package/src/bridge.d.ts +3 -0
- package/tokens.css +51 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { PluginPermission } from '@tx5dr/contracts';
|
|
2
|
+
import type { PluginCleanupContext, PluginContextFor, StrategyPluginContext } from '../../context.js';
|
|
3
|
+
import type { PluginDefinition } from '../../definition.js';
|
|
4
|
+
import type { PluginHooks } from '../../hooks.js';
|
|
5
|
+
import { type QueuedStrategyRuntime, type StrategyRuntime } from '../../runtime.js';
|
|
6
|
+
import type { ContestLogbookModule } from './ContestLogbook.js';
|
|
7
|
+
import type { VersionedContestSession } from './ContestSessionRepository.js';
|
|
8
|
+
import type { FT8ContestDefinition } from './FT8ContestDefinition.js';
|
|
9
|
+
import type { FT8ContestQso } from './FT8ContestModules.js';
|
|
10
|
+
export declare const FT8_CONTEST_MIN_PLUGIN_API_VERSION = "2.5.0";
|
|
11
|
+
export interface FT8RuntimeModule<TContest> {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
create(contest: TContest, context: StrategyPluginContext): StrategyRuntime;
|
|
14
|
+
}
|
|
15
|
+
export type FT8ParallelRuntime = QueuedStrategyRuntime & Required<Pick<StrategyRuntime, 'getTransmissions' | 'onTransmissionsCompleted'>>;
|
|
16
|
+
export type FT8RuntimeFactory<TContest> = (contest: TContest, context: StrategyPluginContext) => StrategyRuntime;
|
|
17
|
+
export declare function defineFT8RuntimeModule<TContest>(module: FT8RuntimeModule<TContest>): FT8RuntimeModule<TContest>;
|
|
18
|
+
export type ContestModuleCleanup = (context: PluginCleanupContext) => void | Promise<void>;
|
|
19
|
+
export interface ContestLifecycleModule<TContest, Permissions extends readonly PluginPermission[] = readonly []> {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
setup(input: {
|
|
22
|
+
contest: TContest;
|
|
23
|
+
context: PluginContextFor<Permissions>;
|
|
24
|
+
/** Stable owner used by modules that publish process-global events. */
|
|
25
|
+
pluginName: string;
|
|
26
|
+
}): void | ContestModuleCleanup | Promise<void | ContestModuleCleanup>;
|
|
27
|
+
}
|
|
28
|
+
/** Lifecycle module for versioned contest state. Storage mechanics stay module-owned. */
|
|
29
|
+
export interface ContestSessionModule<TContest, Permissions extends readonly PluginPermission[] = readonly []> extends ContestLifecycleModule<TContest, Permissions> {
|
|
30
|
+
}
|
|
31
|
+
/** Lifecycle module for an optional contest page/workbench protocol. */
|
|
32
|
+
export interface ContestWorkbenchModule<TContest, Permissions extends readonly PluginPermission[] = readonly []> extends ContestLifecycleModule<TContest, Permissions> {
|
|
33
|
+
}
|
|
34
|
+
export declare function defineContestSessionModule<TContest, Permissions extends readonly PluginPermission[] = readonly []>(module: ContestSessionModule<TContest, Permissions>): ContestSessionModule<TContest, Permissions>;
|
|
35
|
+
export declare function defineContestWorkbenchModule<TContest, Permissions extends readonly PluginPermission[] = readonly []>(module: ContestWorkbenchModule<TContest, Permissions>): ContestWorkbenchModule<TContest, Permissions>;
|
|
36
|
+
export interface ComposeFT8ContestPluginInput<TExchange, TQso extends FT8ContestQso<TExchange>, TSubmissionOptions, Permissions extends readonly PluginPermission[], SessionPermissions extends readonly PluginPermission[] = Permissions, WorkbenchPermissions extends readonly PluginPermission[] = Permissions> extends Omit<PluginDefinition<Permissions>, 'apiVersion' | 'type' | 'createStrategyRuntime' | 'onLoad' | 'onUnload' | 'hooks'> {
|
|
37
|
+
contest: FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>;
|
|
38
|
+
runtime: FT8RuntimeModule<FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>> | FT8RuntimeFactory<FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>>;
|
|
39
|
+
session?: ContestSessionModule<FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>, SessionPermissions> & RequiredPermissionsAvailable<Permissions, SessionPermissions>;
|
|
40
|
+
workbench?: ContestWorkbenchModule<FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>, WorkbenchPermissions> & RequiredPermissionsAvailable<Permissions, WorkbenchPermissions>;
|
|
41
|
+
logbook?: ContestLogbookModule<FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>, VersionedContestSession, Permissions>;
|
|
42
|
+
hooks?: PluginHooks<Permissions>;
|
|
43
|
+
onLoad?(context: PluginContextFor<Permissions>): void | Promise<void>;
|
|
44
|
+
onUnload?(context: PluginCleanupContext): void | Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
type RequiredPermissionsAvailable<Actual extends readonly PluginPermission[], Required extends readonly PluginPermission[]> = Exclude<Required[number], Actual[number]> extends never ? unknown : {
|
|
47
|
+
readonly missingPluginPermissions: Exclude<Required[number], Actual[number]>;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Convenience assembler for an operator-scoped FT8 strategy plugin.
|
|
51
|
+
* Authors can skip it and wire the same public modules through definePlugin().
|
|
52
|
+
*/
|
|
53
|
+
export declare function composeFT8ContestPlugin<TExchange, TQso extends FT8ContestQso<TExchange>, TSubmissionOptions = void, const Permissions extends readonly PluginPermission[] = readonly [], SessionPermissions extends readonly PluginPermission[] = Permissions, WorkbenchPermissions extends readonly PluginPermission[] = Permissions>(input: ComposeFT8ContestPluginInput<TExchange, TQso, TSubmissionOptions, Permissions, SessionPermissions, WorkbenchPermissions>): PluginDefinition<Permissions>;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=FT8ContestPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FT8ContestPlugin.d.ts","sourceRoot":"","sources":["../../../src/toolkit/contest/FT8ContestPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { assertPluginApiCompatible, comparePluginApiVersions } from '../../compatibility.js';
|
|
2
|
+
import { isQueuedStrategyRuntime, } from '../../runtime.js';
|
|
3
|
+
export const FT8_CONTEST_MIN_PLUGIN_API_VERSION = '2.5.0';
|
|
4
|
+
export function defineFT8RuntimeModule(module) {
|
|
5
|
+
return module;
|
|
6
|
+
}
|
|
7
|
+
export function defineContestSessionModule(module) {
|
|
8
|
+
return module;
|
|
9
|
+
}
|
|
10
|
+
export function defineContestWorkbenchModule(module) {
|
|
11
|
+
return module;
|
|
12
|
+
}
|
|
13
|
+
function runtimeFactory(runtime) {
|
|
14
|
+
return typeof runtime === 'function' ? runtime : (contest, context) => runtime.create(contest, context);
|
|
15
|
+
}
|
|
16
|
+
function contestRuntimeContext(context, getMessagePresentation) {
|
|
17
|
+
if (!getMessagePresentation)
|
|
18
|
+
return context;
|
|
19
|
+
return {
|
|
20
|
+
...context,
|
|
21
|
+
operator: {
|
|
22
|
+
...context.operator,
|
|
23
|
+
async hasWorkedCallsign(callsign, options) {
|
|
24
|
+
const presentation = getMessagePresentation(context.operator.id);
|
|
25
|
+
if (!presentation)
|
|
26
|
+
return context.operator.hasWorkedCallsign(callsign, options);
|
|
27
|
+
const normalizedCallsign = callsign.trim().toUpperCase();
|
|
28
|
+
const currentBand = context.radio.band.trim().toUpperCase();
|
|
29
|
+
return presentation.assignments.some((assignment) => (assignment.subject.trim().toUpperCase() === normalizedCallsign
|
|
30
|
+
&& (options?.anyBand === true || assignment.partition?.trim().toUpperCase() === currentBand)));
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function decorateRuntime(runtime, decorate, context, getMessagePresentation) {
|
|
36
|
+
return new Proxy(runtime, {
|
|
37
|
+
get(target, property, receiver) {
|
|
38
|
+
if (property === 'decide') {
|
|
39
|
+
return async (...args) => {
|
|
40
|
+
const result = await target.decide(...args);
|
|
41
|
+
const messagePresentation = getMessagePresentation?.(context.operator.id);
|
|
42
|
+
const qsoCompletion = result.qsoCompletion
|
|
43
|
+
? decorate(result.qsoCompletion, context)
|
|
44
|
+
: undefined;
|
|
45
|
+
const qsoCompletions = result.qsoCompletions?.map((effect) => decorate(effect, context));
|
|
46
|
+
return {
|
|
47
|
+
...result,
|
|
48
|
+
snapshot: messagePresentation
|
|
49
|
+
? { ...result.snapshot, messagePresentation }
|
|
50
|
+
: result.snapshot,
|
|
51
|
+
...(qsoCompletion ? { qsoCompletion } : {}),
|
|
52
|
+
...(qsoCompletions ? { qsoCompletions } : {}),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (property === 'getSnapshot') {
|
|
57
|
+
return () => {
|
|
58
|
+
const snapshot = target.getSnapshot();
|
|
59
|
+
const messagePresentation = getMessagePresentation?.(context.operator.id);
|
|
60
|
+
return messagePresentation ? { ...snapshot, messagePresentation } : snapshot;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const value = Reflect.get(target, property, receiver);
|
|
64
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function mergeHooks(hooks) {
|
|
69
|
+
const active = hooks.filter((hook) => hook !== undefined);
|
|
70
|
+
if (active.length === 0)
|
|
71
|
+
return undefined;
|
|
72
|
+
return {
|
|
73
|
+
async onAutoCallCandidate(slotInfo, messages, ctx) {
|
|
74
|
+
let proposal;
|
|
75
|
+
for (const hook of active) {
|
|
76
|
+
proposal = await hook.onAutoCallCandidate?.(slotInfo, messages, ctx) ?? proposal;
|
|
77
|
+
}
|
|
78
|
+
return proposal;
|
|
79
|
+
},
|
|
80
|
+
async onConfigureAutoCallExecution(request, plan, ctx) {
|
|
81
|
+
let nextPlan = plan;
|
|
82
|
+
for (const hook of active) {
|
|
83
|
+
nextPlan = await hook.onConfigureAutoCallExecution?.(request, nextPlan, ctx) ?? nextPlan;
|
|
84
|
+
}
|
|
85
|
+
return nextPlan;
|
|
86
|
+
},
|
|
87
|
+
async onFilterCandidates(candidates, ctx) {
|
|
88
|
+
let next = candidates;
|
|
89
|
+
for (const hook of active) {
|
|
90
|
+
next = await hook.onFilterCandidates?.(next, ctx) ?? next;
|
|
91
|
+
}
|
|
92
|
+
return next;
|
|
93
|
+
},
|
|
94
|
+
async onScoreCandidates(candidates, ctx) {
|
|
95
|
+
let next = candidates;
|
|
96
|
+
for (const hook of active) {
|
|
97
|
+
next = await hook.onScoreCandidates?.(next, ctx) ?? next;
|
|
98
|
+
}
|
|
99
|
+
return next;
|
|
100
|
+
},
|
|
101
|
+
async onSlotStart(slotInfo, messages, ctx) {
|
|
102
|
+
for (const hook of active)
|
|
103
|
+
await hook.onSlotStart?.(slotInfo, messages, ctx);
|
|
104
|
+
},
|
|
105
|
+
async onSlotActivity(event, ctx) {
|
|
106
|
+
for (const hook of active)
|
|
107
|
+
await hook.onSlotActivity?.(event, ctx);
|
|
108
|
+
},
|
|
109
|
+
async onDecode(messages, ctx) {
|
|
110
|
+
for (const hook of active)
|
|
111
|
+
await hook.onDecode?.(messages, ctx);
|
|
112
|
+
},
|
|
113
|
+
async onFrequencyChange(state, ctx) {
|
|
114
|
+
for (const hook of active)
|
|
115
|
+
await hook.onFrequencyChange?.(state, ctx);
|
|
116
|
+
},
|
|
117
|
+
async onQSOStart(info, ctx) {
|
|
118
|
+
for (const hook of active)
|
|
119
|
+
await hook.onQSOStart?.(info, ctx);
|
|
120
|
+
},
|
|
121
|
+
async onQSOComplete(record, ctx) {
|
|
122
|
+
for (const hook of active)
|
|
123
|
+
await hook.onQSOComplete?.(record, ctx);
|
|
124
|
+
},
|
|
125
|
+
async onQSOFail(info, ctx) {
|
|
126
|
+
for (const hook of active)
|
|
127
|
+
await hook.onQSOFail?.(info, ctx);
|
|
128
|
+
},
|
|
129
|
+
async onTimer(timerId, ctx) {
|
|
130
|
+
for (const hook of active)
|
|
131
|
+
await hook.onTimer?.(timerId, ctx);
|
|
132
|
+
},
|
|
133
|
+
async onUserAction(actionId, payload, ctx) {
|
|
134
|
+
for (const hook of active)
|
|
135
|
+
await hook.onUserAction?.(actionId, payload, ctx);
|
|
136
|
+
},
|
|
137
|
+
async onConfigChange(changes, ctx) {
|
|
138
|
+
for (const hook of active)
|
|
139
|
+
await hook.onConfigChange?.(changes, ctx);
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function mergeRecordMap(first, second) {
|
|
144
|
+
const merged = { ...(first ?? {}), ...(second ?? {}) };
|
|
145
|
+
return (Object.keys(merged).length > 0 ? merged : undefined);
|
|
146
|
+
}
|
|
147
|
+
function mergeArrayById(first, second) {
|
|
148
|
+
const result = [];
|
|
149
|
+
const index = new Map();
|
|
150
|
+
for (const item of [...first ?? [], ...second ?? []]) {
|
|
151
|
+
const existing = index.get(item.id);
|
|
152
|
+
if (existing === undefined) {
|
|
153
|
+
index.set(item.id, result.length);
|
|
154
|
+
result.push(item);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
result[existing] = item;
|
|
158
|
+
}
|
|
159
|
+
return result.length > 0 ? result : undefined;
|
|
160
|
+
}
|
|
161
|
+
function mergeQuickSettings(first, second) {
|
|
162
|
+
const result = [];
|
|
163
|
+
const index = new Map();
|
|
164
|
+
for (const item of [...first ?? [], ...second ?? []]) {
|
|
165
|
+
const existing = index.get(item.settingKey);
|
|
166
|
+
if (existing === undefined) {
|
|
167
|
+
index.set(item.settingKey, result.length);
|
|
168
|
+
result.push(item);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
result[existing] = item;
|
|
172
|
+
}
|
|
173
|
+
return result.length > 0 ? result : undefined;
|
|
174
|
+
}
|
|
175
|
+
function assertContestRuntimeFeatures(runtime, features) {
|
|
176
|
+
if (features.targetQueue === 1 && !isQueuedStrategyRuntime(runtime)) {
|
|
177
|
+
throw new Error('contest_runtime_target_queue_requires_queued_strategy');
|
|
178
|
+
}
|
|
179
|
+
if (features.parallelTargetQueue === 1
|
|
180
|
+
&& (typeof runtime.getTransmissions !== 'function'
|
|
181
|
+
|| typeof runtime.onTransmissionsCompleted !== 'function')) {
|
|
182
|
+
throw new Error('contest_runtime_parallel_queue_requires_parallel_runtime');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Convenience assembler for an operator-scoped FT8 strategy plugin.
|
|
187
|
+
* Authors can skip it and wire the same public modules through definePlugin().
|
|
188
|
+
*/
|
|
189
|
+
export function composeFT8ContestPlugin(input) {
|
|
190
|
+
const { contest, runtime, session, workbench, logbook, hooks, settings, quickSettings, panels, ui, onLoad, onUnload, strategyFeatures, minPluginApiVersion: declaredMinPluginApiVersion, ...metadata } = input;
|
|
191
|
+
if (declaredMinPluginApiVersion
|
|
192
|
+
&& (comparePluginApiVersions(declaredMinPluginApiVersion, FT8_CONTEST_MIN_PLUGIN_API_VERSION) ?? -1) < 0) {
|
|
193
|
+
throw new Error(`contest_plugin_api_floor_too_low:${declaredMinPluginApiVersion}`);
|
|
194
|
+
}
|
|
195
|
+
const minPluginApiVersion = declaredMinPluginApiVersion
|
|
196
|
+
?? FT8_CONTEST_MIN_PLUGIN_API_VERSION;
|
|
197
|
+
const createRuntime = runtimeFactory(runtime);
|
|
198
|
+
const cleanups = new Map();
|
|
199
|
+
const requiredOperatingFeatures = {
|
|
200
|
+
...(contest.operating.humanInitiation === 'required' ? { manualInitiation: 1 } : {}),
|
|
201
|
+
maxConcurrentStreams: contest.operating.maxConcurrentQsos,
|
|
202
|
+
maxSimultaneousSignals: contest.operating.maxSimultaneousSignals,
|
|
203
|
+
};
|
|
204
|
+
for (const key of [
|
|
205
|
+
'manualInitiation',
|
|
206
|
+
'maxConcurrentStreams',
|
|
207
|
+
'maxSimultaneousSignals',
|
|
208
|
+
]) {
|
|
209
|
+
if (requiredOperatingFeatures[key] !== undefined
|
|
210
|
+
&& strategyFeatures?.[key] !== undefined
|
|
211
|
+
&& strategyFeatures[key] !== requiredOperatingFeatures[key]) {
|
|
212
|
+
throw new Error(`contest_operating_strategy_feature_conflict:${key}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const mergedFeatures = {
|
|
216
|
+
...strategyFeatures,
|
|
217
|
+
...requiredOperatingFeatures,
|
|
218
|
+
};
|
|
219
|
+
if (contest.operating.maxConcurrentQsos > 1) {
|
|
220
|
+
mergedFeatures.targetQueue = 1;
|
|
221
|
+
mergedFeatures.parallelTargetQueue = 1;
|
|
222
|
+
}
|
|
223
|
+
if (mergedFeatures.parallelTargetQueue === 1 && mergedFeatures.targetQueue !== 1) {
|
|
224
|
+
throw new Error('contest_operating_parallel_queue_requires_target_queue');
|
|
225
|
+
}
|
|
226
|
+
if (mergedFeatures.queueActivation !== undefined && mergedFeatures.targetQueue !== 1) {
|
|
227
|
+
throw new Error('contest_operating_queue_activation_requires_target_queue');
|
|
228
|
+
}
|
|
229
|
+
if (logbook && !metadata.permissions?.includes('logbook:session')) {
|
|
230
|
+
throw new Error('contest_logbook_missing_permission:logbook:session');
|
|
231
|
+
}
|
|
232
|
+
if (logbook && !metadata.permissions?.includes('plugin:event-bus')) {
|
|
233
|
+
throw new Error('contest_logbook_missing_permission:plugin:event-bus');
|
|
234
|
+
}
|
|
235
|
+
const mergedHooks = mergeHooks([logbook?.hooks, hooks]);
|
|
236
|
+
const mergedSettings = mergeRecordMap(logbook?.settings, settings);
|
|
237
|
+
const mergedQuickSettings = mergeQuickSettings(logbook?.quickSettings, quickSettings);
|
|
238
|
+
const mergedPanels = mergeArrayById(logbook?.panels, panels);
|
|
239
|
+
const mergedUi = logbook?.ui || ui
|
|
240
|
+
? {
|
|
241
|
+
dir: ui?.dir ?? logbook?.ui?.dir,
|
|
242
|
+
pages: mergeArrayById(logbook?.ui?.pages, ui?.pages),
|
|
243
|
+
}
|
|
244
|
+
: undefined;
|
|
245
|
+
const mergedSession = (session ?? logbook?.session);
|
|
246
|
+
const mergedWorkbench = (workbench ?? logbook?.workbench);
|
|
247
|
+
return {
|
|
248
|
+
...metadata,
|
|
249
|
+
apiVersion: 2,
|
|
250
|
+
minPluginApiVersion,
|
|
251
|
+
type: 'strategy',
|
|
252
|
+
strategyFeatures: mergedFeatures,
|
|
253
|
+
...(mergedSettings ? { settings: mergedSettings } : {}),
|
|
254
|
+
...(mergedQuickSettings ? { quickSettings: mergedQuickSettings } : {}),
|
|
255
|
+
...(mergedPanels ? { panels: mergedPanels } : {}),
|
|
256
|
+
...(mergedUi ? { ui: mergedUi } : {}),
|
|
257
|
+
hooks: mergedHooks,
|
|
258
|
+
createStrategyRuntime(context) {
|
|
259
|
+
assertPluginApiCompatible(minPluginApiVersion, metadata.name, context.pluginApiVersion);
|
|
260
|
+
const runtime = createRuntime(contest, contestRuntimeContext(context, logbook?.getMessagePresentation));
|
|
261
|
+
assertContestRuntimeFeatures(runtime, mergedFeatures);
|
|
262
|
+
if (!logbook?.decorateCompletion && !logbook?.getMessagePresentation)
|
|
263
|
+
return runtime;
|
|
264
|
+
const decorateCompletion = logbook.decorateCompletion
|
|
265
|
+
?? ((effect) => effect);
|
|
266
|
+
return decorateRuntime(runtime, decorateCompletion, context, logbook.getMessagePresentation);
|
|
267
|
+
},
|
|
268
|
+
async onLoad(context) {
|
|
269
|
+
const instanceCleanups = [];
|
|
270
|
+
cleanups.set(context.operator.id, instanceCleanups);
|
|
271
|
+
try {
|
|
272
|
+
if (mergedSession) {
|
|
273
|
+
const cleanup = await mergedSession.setup({
|
|
274
|
+
contest,
|
|
275
|
+
context: context,
|
|
276
|
+
pluginName: metadata.name,
|
|
277
|
+
});
|
|
278
|
+
if (cleanup)
|
|
279
|
+
instanceCleanups.push(cleanup);
|
|
280
|
+
}
|
|
281
|
+
if (mergedWorkbench) {
|
|
282
|
+
const cleanup = await mergedWorkbench.setup({
|
|
283
|
+
contest,
|
|
284
|
+
context: context,
|
|
285
|
+
pluginName: metadata.name,
|
|
286
|
+
});
|
|
287
|
+
if (cleanup)
|
|
288
|
+
instanceCleanups.push(cleanup);
|
|
289
|
+
}
|
|
290
|
+
await onLoad?.(context);
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
cleanups.delete(context.operator.id);
|
|
294
|
+
for (const cleanup of instanceCleanups.reverse())
|
|
295
|
+
await cleanup(context);
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
async onUnload(context) {
|
|
300
|
+
let firstError;
|
|
301
|
+
try {
|
|
302
|
+
await onUnload?.(context);
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
firstError = error;
|
|
306
|
+
}
|
|
307
|
+
const instanceCleanups = cleanups.get(context.operator.id) ?? [];
|
|
308
|
+
cleanups.delete(context.operator.id);
|
|
309
|
+
for (const cleanup of instanceCleanups.reverse()) {
|
|
310
|
+
try {
|
|
311
|
+
await cleanup(context);
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
firstError ??= error;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (firstError)
|
|
318
|
+
throw firstError;
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=FT8ContestPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FT8ContestPlugin.js","sourceRoot":"","sources":["../../../src/toolkit/contest/FT8ContestPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FT8ContestDefinition } from './FT8ContestDefinition.js';
|
|
2
|
+
import type { CompletionEvidence, ContestExchangeFields, ContestScoreSummary, FT8ContestQso } from './FT8ContestModules.js';
|
|
3
|
+
/** Framework-neutral golden assertions for a composed contest definition. */
|
|
4
|
+
export declare function createFT8ContestTestKit<TExchange, TQso extends FT8ContestQso<TExchange>, TSubmissionOptions = void>(contest: FT8ContestDefinition<TExchange, TQso, TSubmissionOptions>): {
|
|
5
|
+
exchange(fields: ContestExchangeFields, expected: TExchange, canonicalFields?: ContestExchangeFields): void;
|
|
6
|
+
invalidExchange(fields: Readonly<Record<string, string>>, expectedCode: string): void;
|
|
7
|
+
completion(evidence: CompletionEvidence<TExchange>, expected: boolean): void;
|
|
8
|
+
dupe(first: TQso, second: TQso, expected?: boolean): void;
|
|
9
|
+
score(records: readonly TQso[], expected: Partial<ContestScoreSummary>): void;
|
|
10
|
+
submission(records: readonly TQso[], options: TSubmissionOptions, expected: string): void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=FT8ContestTestKit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FT8ContestTestKit.d.ts","sourceRoot":"","sources":["../../../src/toolkit/contest/FT8ContestTestKit.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,EACd,MAAM,wBAAwB,CAAC;AAwBhC,6EAA6E;AAC7E,wBAAgB,uBAAuB,CACrC,SAAS,EACT,IAAI,SAAS,aAAa,CAAC,SAAS,CAAC,EACrC,kBAAkB,GAAG,IAAI,EACzB,OAAO,EAAE,oBAAoB,CAAC,SAAS,EAAE,IAAI,EAAE,kBAAkB,CAAC;qBAGtD,qBAAqB,YACnB,SAAS,oBACF,qBAAqB,GACrC,IAAI;4BAciB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,gBAAgB,MAAM,GAAG,IAAI;yBAMhE,kBAAkB,CAAC,SAAS,CAAC,YAAY,OAAO,GAAG,IAAI;gBAGhE,IAAI,UAAU,IAAI,uBAAoB,IAAI;mBAGvC,SAAS,IAAI,EAAE,YAAY,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI;wBAMzD,SAAS,IAAI,EAAE,WAAW,kBAAkB,YAAY,MAAM,GAAG,IAAI;EAI5F"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { formatFT8ContestSubmission, scoreFT8ContestQsos, } from './FT8ContestDefinition.js';
|
|
2
|
+
function canonicalize(value) {
|
|
3
|
+
if (Array.isArray(value))
|
|
4
|
+
return value.map(canonicalize);
|
|
5
|
+
if (value && typeof value === 'object') {
|
|
6
|
+
return Object.fromEntries(Object.entries(value)
|
|
7
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
8
|
+
.map(([key, nested]) => [key, canonicalize(nested)]));
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
function stableJson(value) {
|
|
13
|
+
return JSON.stringify(canonicalize(value));
|
|
14
|
+
}
|
|
15
|
+
function assertEqual(actual, expected, label) {
|
|
16
|
+
if (stableJson(actual) !== stableJson(expected)) {
|
|
17
|
+
throw new Error(`${label}: expected ${JSON.stringify(expected)}, received ${JSON.stringify(actual)}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Framework-neutral golden assertions for a composed contest definition. */
|
|
21
|
+
export function createFT8ContestTestKit(contest) {
|
|
22
|
+
return {
|
|
23
|
+
exchange(fields, expected, canonicalFields = contest.exchange.encode(expected)) {
|
|
24
|
+
const decoded = contest.exchange.decode(fields);
|
|
25
|
+
if (!decoded.ok) {
|
|
26
|
+
throw new Error(`contest_exchange_decode_failed:${decoded.issues.map((issue) => issue.code).join(',')}`);
|
|
27
|
+
}
|
|
28
|
+
assertEqual(decoded.value, expected, 'contest_exchange_mismatch');
|
|
29
|
+
const encoded = contest.exchange.encode(decoded.value);
|
|
30
|
+
assertEqual(encoded, canonicalFields, 'contest_exchange_canonical_fields_mismatch');
|
|
31
|
+
const roundTripped = contest.exchange.decode(encoded);
|
|
32
|
+
if (!roundTripped.ok) {
|
|
33
|
+
throw new Error(`contest_exchange_round_trip_failed:${roundTripped.issues.map((issue) => issue.code).join(',')}`);
|
|
34
|
+
}
|
|
35
|
+
assertEqual(roundTripped.value, expected, 'contest_exchange_round_trip_mismatch');
|
|
36
|
+
},
|
|
37
|
+
invalidExchange(fields, expectedCode) {
|
|
38
|
+
const decoded = contest.exchange.decode(fields);
|
|
39
|
+
if (decoded.ok || !decoded.issues.some((issue) => issue.code === expectedCode)) {
|
|
40
|
+
throw new Error(`contest_exchange_expected_issue:${expectedCode}`);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
completion(evidence, expected) {
|
|
44
|
+
assertEqual(contest.completion.evaluate(evidence).complete, expected, 'contest_completion_mismatch');
|
|
45
|
+
},
|
|
46
|
+
dupe(first, second, expected = true) {
|
|
47
|
+
assertEqual(contest.dupe.key(first) === contest.dupe.key(second), expected, 'contest_dupe_mismatch');
|
|
48
|
+
},
|
|
49
|
+
score(records, expected) {
|
|
50
|
+
const summary = scoreFT8ContestQsos(contest, records);
|
|
51
|
+
for (const [key, value] of Object.entries(expected)) {
|
|
52
|
+
assertEqual(summary[key], value, `contest_score_${key}_mismatch`);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
submission(records, options, expected) {
|
|
56
|
+
assertEqual(formatFT8ContestSubmission(contest, records, options), expected, 'contest_submission_mismatch');
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=FT8ContestTestKit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FT8ContestTestKit.js","sourceRoot":"","sources":["../../../src/toolkit/contest/FT8ContestTestKit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contest-toolkit.test.d.ts","sourceRoot":"","sources":["../../../src/toolkit/contest/contest-toolkit.test.ts"],"names":[],"mappings":""}
|