@higher.archi/boe 1.0.21 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/types/rule.d.ts +1 -1
- package/dist/core/types/rule.d.ts.map +1 -1
- package/dist/engines/ranking/compiler.d.ts +12 -0
- package/dist/engines/ranking/compiler.d.ts.map +1 -0
- package/dist/engines/ranking/compiler.js +163 -0
- package/dist/engines/ranking/compiler.js.map +1 -0
- package/dist/engines/ranking/engine.d.ts +48 -0
- package/dist/engines/ranking/engine.d.ts.map +1 -0
- package/dist/engines/ranking/engine.js +89 -0
- package/dist/engines/ranking/engine.js.map +1 -0
- package/dist/engines/ranking/index.d.ts +9 -0
- package/dist/engines/ranking/index.d.ts.map +1 -0
- package/dist/engines/ranking/index.js +23 -0
- package/dist/engines/ranking/index.js.map +1 -0
- package/dist/engines/ranking/strategy.d.ts +21 -0
- package/dist/engines/ranking/strategy.d.ts.map +1 -0
- package/dist/engines/ranking/strategy.js +250 -0
- package/dist/engines/ranking/strategy.js.map +1 -0
- package/dist/engines/ranking/types.d.ts +142 -0
- package/dist/engines/ranking/types.d.ts.map +1 -0
- package/dist/engines/ranking/types.js +46 -0
- package/dist/engines/ranking/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/types/rule.ts +1 -1
- package/src/engines/ranking/compiler.ts +194 -0
- package/src/engines/ranking/engine.ts +120 -0
- package/src/engines/ranking/index.ts +46 -0
- package/src/engines/ranking/strategy.ts +333 -0
- package/src/engines/ranking/types.ts +231 -0
- package/src/index.ts +36 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ranking Engine Types
|
|
3
|
+
*
|
|
4
|
+
* Comparative scoring engine that ranks N entities relative to each other.
|
|
5
|
+
* Supports score-based ranking, Elo ratings, and head-to-head pairwise comparison.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
CompiledScoringRuleSet,
|
|
10
|
+
ScoringOptions,
|
|
11
|
+
ScoringTierMatch,
|
|
12
|
+
TierDefinition
|
|
13
|
+
} from '../scoring/types';
|
|
14
|
+
import type { SemanticPriority } from '../utility/types';
|
|
15
|
+
|
|
16
|
+
// ========================================
|
|
17
|
+
// Semantic Types
|
|
18
|
+
// ========================================
|
|
19
|
+
|
|
20
|
+
/** Ranking algorithm to use */
|
|
21
|
+
export type RankingStrategy = 'score' | 'elo' | 'head-to-head';
|
|
22
|
+
|
|
23
|
+
/** Sort direction for rankings */
|
|
24
|
+
export type RankingDirection = 'highest-first' | 'lowest-first';
|
|
25
|
+
|
|
26
|
+
/** Human-readable percentile bracket */
|
|
27
|
+
export type PercentileLabel =
|
|
28
|
+
| 'top-1%'
|
|
29
|
+
| 'top-5%'
|
|
30
|
+
| 'top-10%'
|
|
31
|
+
| 'top-25%'
|
|
32
|
+
| 'top-50%'
|
|
33
|
+
| 'bottom-half';
|
|
34
|
+
|
|
35
|
+
/** Rank movement since previous ranking */
|
|
36
|
+
export type Movement = 'climbed' | 'steady' | 'dropped';
|
|
37
|
+
|
|
38
|
+
/** Elo K-factor presets controlling rating volatility */
|
|
39
|
+
export type KFactorPreset = 'volatile' | 'standard' | 'stable';
|
|
40
|
+
|
|
41
|
+
export const K_FACTOR_VALUES: Record<KFactorPreset, number> = {
|
|
42
|
+
'volatile': 32, // New entities, fast adjustment
|
|
43
|
+
'standard': 16, // Default
|
|
44
|
+
'stable': 8 // Established entities, slow drift
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export function isKFactorPreset(value: unknown): value is KFactorPreset {
|
|
48
|
+
return typeof value === 'string' && value in K_FACTOR_VALUES;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ========================================
|
|
52
|
+
// Resolver Functions
|
|
53
|
+
// ========================================
|
|
54
|
+
|
|
55
|
+
/** Map a percentile (0-100) to a semantic label */
|
|
56
|
+
export function resolvePercentileLabel(percentile: number): PercentileLabel {
|
|
57
|
+
if (percentile >= 99) return 'top-1%';
|
|
58
|
+
if (percentile >= 95) return 'top-5%';
|
|
59
|
+
if (percentile >= 90) return 'top-10%';
|
|
60
|
+
if (percentile >= 75) return 'top-25%';
|
|
61
|
+
if (percentile >= 50) return 'top-50%';
|
|
62
|
+
return 'bottom-half';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Map rank change to a semantic movement label */
|
|
66
|
+
export function resolveMovement(previousRank: number, currentRank: number): Movement {
|
|
67
|
+
if (currentRank < previousRank) return 'climbed'; // lower rank number = better
|
|
68
|
+
if (currentRank > previousRank) return 'dropped';
|
|
69
|
+
return 'steady';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ========================================
|
|
73
|
+
// Criterion Types (Head-to-Head)
|
|
74
|
+
// ========================================
|
|
75
|
+
|
|
76
|
+
/** A dimension for pairwise comparison */
|
|
77
|
+
export type RankingCriterion = {
|
|
78
|
+
id: string;
|
|
79
|
+
name?: string;
|
|
80
|
+
weight: number | SemanticPriority; // 'critical', 'high', 'medium', 'low'
|
|
81
|
+
direction: RankingDirection;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** Compiled criterion with resolved numeric weight */
|
|
85
|
+
export type CompiledRankingCriterion = {
|
|
86
|
+
id: string;
|
|
87
|
+
name?: string;
|
|
88
|
+
weight: number; // normalized to sum to 1.0
|
|
89
|
+
direction: RankingDirection;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// ========================================
|
|
93
|
+
// Strategy-Specific Config Types
|
|
94
|
+
// ========================================
|
|
95
|
+
|
|
96
|
+
export type ScoreRankingConfig<T extends TierDefinition = TierDefinition> = {
|
|
97
|
+
direction?: RankingDirection; // default: 'highest-first'
|
|
98
|
+
tiers?: T[];
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export type EloConfig = {
|
|
102
|
+
initialRating?: number; // default: 1500
|
|
103
|
+
kFactor?: KFactorPreset | number; // default: 'standard'
|
|
104
|
+
direction?: RankingDirection;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export type HeadToHeadConfig = {
|
|
108
|
+
direction?: RankingDirection;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// ========================================
|
|
112
|
+
// Source RuleSet Types (Discriminated Union)
|
|
113
|
+
// ========================================
|
|
114
|
+
|
|
115
|
+
type RankingRuleSetBase = {
|
|
116
|
+
id: string;
|
|
117
|
+
name?: string;
|
|
118
|
+
mode: 'ranking';
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/** Score strategy: point at a scoring ruleset, rank entities by totalScore */
|
|
122
|
+
export type ScoreRankingRuleSet<T extends TierDefinition = TierDefinition> = RankingRuleSetBase & {
|
|
123
|
+
strategy: 'score';
|
|
124
|
+
scoringRuleset: CompiledScoringRuleSet<T>;
|
|
125
|
+
scoringOptions?: ScoringOptions;
|
|
126
|
+
entityType: string;
|
|
127
|
+
config?: ScoreRankingConfig<T>;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/** Elo strategy: process match history, compute ratings */
|
|
131
|
+
export type EloRankingRuleSet = RankingRuleSetBase & {
|
|
132
|
+
strategy: 'elo';
|
|
133
|
+
entityType: string;
|
|
134
|
+
matchType?: string; // default: 'MatchResult'
|
|
135
|
+
config?: EloConfig;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/** Head-to-head strategy: pairwise comparison on weighted criteria */
|
|
139
|
+
export type HeadToHeadRankingRuleSet = RankingRuleSetBase & {
|
|
140
|
+
strategy: 'head-to-head';
|
|
141
|
+
entityType: string;
|
|
142
|
+
criteria: RankingCriterion[];
|
|
143
|
+
config?: HeadToHeadConfig;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export type RankingRuleSet<T extends TierDefinition = TierDefinition> =
|
|
147
|
+
| ScoreRankingRuleSet<T>
|
|
148
|
+
| EloRankingRuleSet
|
|
149
|
+
| HeadToHeadRankingRuleSet;
|
|
150
|
+
|
|
151
|
+
// ========================================
|
|
152
|
+
// Compiled RuleSet Types
|
|
153
|
+
// ========================================
|
|
154
|
+
|
|
155
|
+
type CompiledRankingRuleSetBase = {
|
|
156
|
+
id: string;
|
|
157
|
+
name?: string;
|
|
158
|
+
mode: 'ranking';
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export type CompiledScoreRankingRuleSet<T extends TierDefinition = TierDefinition> = CompiledRankingRuleSetBase & {
|
|
162
|
+
strategy: 'score';
|
|
163
|
+
scoringRuleset: CompiledScoringRuleSet<T>;
|
|
164
|
+
scoringOptions?: ScoringOptions;
|
|
165
|
+
entityType: string;
|
|
166
|
+
config: {
|
|
167
|
+
direction: RankingDirection;
|
|
168
|
+
tiers?: T[];
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export type CompiledEloRankingRuleSet = CompiledRankingRuleSetBase & {
|
|
173
|
+
strategy: 'elo';
|
|
174
|
+
entityType: string;
|
|
175
|
+
matchType: string;
|
|
176
|
+
config: {
|
|
177
|
+
initialRating: number;
|
|
178
|
+
kFactor: number;
|
|
179
|
+
direction: RankingDirection;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export type CompiledHeadToHeadRankingRuleSet = CompiledRankingRuleSetBase & {
|
|
184
|
+
strategy: 'head-to-head';
|
|
185
|
+
entityType: string;
|
|
186
|
+
criteria: CompiledRankingCriterion[];
|
|
187
|
+
config: {
|
|
188
|
+
direction: RankingDirection;
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export type CompiledRankingRuleSet<T extends TierDefinition = TierDefinition> =
|
|
193
|
+
| CompiledScoreRankingRuleSet<T>
|
|
194
|
+
| CompiledEloRankingRuleSet
|
|
195
|
+
| CompiledHeadToHeadRankingRuleSet;
|
|
196
|
+
|
|
197
|
+
// ========================================
|
|
198
|
+
// Runtime Types
|
|
199
|
+
// ========================================
|
|
200
|
+
|
|
201
|
+
/** Previous ranking for movement tracking */
|
|
202
|
+
export type PreviousRanking = {
|
|
203
|
+
entityId: string;
|
|
204
|
+
rank: number;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** Runtime options */
|
|
208
|
+
export type RankingOptions = {
|
|
209
|
+
previousRankings?: PreviousRanking[];
|
|
210
|
+
onRank?: (entity: RankedEntity) => void;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/** Per-entity result */
|
|
214
|
+
export type RankedEntity<T extends TierDefinition = TierDefinition> = {
|
|
215
|
+
entityId: string;
|
|
216
|
+
rank: number; // 1-based
|
|
217
|
+
score: number;
|
|
218
|
+
percentile: number; // 0-100
|
|
219
|
+
percentileLabel: PercentileLabel;
|
|
220
|
+
tier?: ScoringTierMatch<T>;
|
|
221
|
+
movement?: Movement; // only when previousRankings provided
|
|
222
|
+
delta?: number; // rank positions changed (positive = climbed)
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/** Full ranking result */
|
|
226
|
+
export type RankingResult<T extends TierDefinition = TierDefinition> = {
|
|
227
|
+
rankings: RankedEntity<T>[];
|
|
228
|
+
totalEntities: number;
|
|
229
|
+
strategy: RankingStrategy;
|
|
230
|
+
executionTimeMs: number;
|
|
231
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -409,6 +409,42 @@ export type {
|
|
|
409
409
|
ExpertMemberConfig, ScoringMemberConfig
|
|
410
410
|
} from './engines/ensemble';
|
|
411
411
|
|
|
412
|
+
// Ranking
|
|
413
|
+
export {
|
|
414
|
+
RankingEngine,
|
|
415
|
+
RankingExecutor,
|
|
416
|
+
compileRankingRuleSet,
|
|
417
|
+
rankingStrategy,
|
|
418
|
+
K_FACTOR_VALUES,
|
|
419
|
+
isKFactorPreset,
|
|
420
|
+
resolvePercentileLabel,
|
|
421
|
+
resolveMovement
|
|
422
|
+
} from './engines/ranking';
|
|
423
|
+
export type {
|
|
424
|
+
RankingStrategy,
|
|
425
|
+
RankingDirection,
|
|
426
|
+
PercentileLabel,
|
|
427
|
+
Movement,
|
|
428
|
+
KFactorPreset,
|
|
429
|
+
RankingCriterion,
|
|
430
|
+
CompiledRankingCriterion,
|
|
431
|
+
ScoreRankingConfig,
|
|
432
|
+
EloConfig,
|
|
433
|
+
HeadToHeadConfig,
|
|
434
|
+
ScoreRankingRuleSet,
|
|
435
|
+
EloRankingRuleSet,
|
|
436
|
+
HeadToHeadRankingRuleSet,
|
|
437
|
+
RankingRuleSet,
|
|
438
|
+
CompiledScoreRankingRuleSet,
|
|
439
|
+
CompiledEloRankingRuleSet,
|
|
440
|
+
CompiledHeadToHeadRankingRuleSet,
|
|
441
|
+
CompiledRankingRuleSet,
|
|
442
|
+
PreviousRanking,
|
|
443
|
+
RankingOptions,
|
|
444
|
+
RankedEntity,
|
|
445
|
+
RankingResult
|
|
446
|
+
} from './engines/ranking';
|
|
447
|
+
|
|
412
448
|
// ========================================
|
|
413
449
|
// Utility Functions (from old modules, re-exported for convenience)
|
|
414
450
|
// ========================================
|