@higher.archi/boe 1.0.29 → 1.0.31
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/evaluation/decay.d.ts +13 -2
- package/dist/core/evaluation/decay.d.ts.map +1 -1
- package/dist/core/evaluation/decay.js +24 -0
- package/dist/core/evaluation/decay.js.map +1 -1
- package/dist/core/types/rule.d.ts +25 -1
- package/dist/core/types/rule.d.ts.map +1 -1
- package/dist/core/types/rule.js +28 -0
- package/dist/core/types/rule.js.map +1 -1
- package/dist/engines/bayesian/index.d.ts +1 -1
- package/dist/engines/bayesian/index.d.ts.map +1 -1
- package/dist/engines/bayesian/index.js +2 -1
- package/dist/engines/bayesian/index.js.map +1 -1
- package/dist/engines/bayesian/types.d.ts +10 -1
- package/dist/engines/bayesian/types.d.ts.map +1 -1
- package/dist/engines/bayesian/types.js +16 -1
- package/dist/engines/bayesian/types.js.map +1 -1
- package/dist/engines/constraint/types.d.ts +36 -5
- package/dist/engines/constraint/types.d.ts.map +1 -1
- package/dist/engines/constraint/types.js +44 -1
- package/dist/engines/constraint/types.js.map +1 -1
- package/dist/engines/decay/index.d.ts +1 -1
- package/dist/engines/decay/index.d.ts.map +1 -1
- package/dist/engines/decay/index.js +5 -1
- package/dist/engines/decay/index.js.map +1 -1
- package/dist/engines/decay/types.d.ts +26 -4
- package/dist/engines/decay/types.d.ts.map +1 -1
- package/dist/engines/decay/types.js +30 -1
- package/dist/engines/decay/types.js.map +1 -1
- package/dist/engines/defeasible/index.d.ts +1 -1
- package/dist/engines/defeasible/index.d.ts.map +1 -1
- package/dist/engines/defeasible/index.js +8 -1
- package/dist/engines/defeasible/index.js.map +1 -1
- package/dist/engines/defeasible/types.d.ts +40 -5
- package/dist/engines/defeasible/types.d.ts.map +1 -1
- package/dist/engines/defeasible/types.js +56 -1
- package/dist/engines/defeasible/types.js.map +1 -1
- package/dist/engines/ensemble/index.d.ts +1 -0
- package/dist/engines/ensemble/index.d.ts.map +1 -1
- package/dist/engines/ensemble/index.js +5 -1
- package/dist/engines/ensemble/index.js.map +1 -1
- package/dist/engines/ensemble/types.d.ts +17 -2
- package/dist/engines/ensemble/types.d.ts.map +1 -1
- package/dist/engines/ensemble/types.js +23 -0
- package/dist/engines/ensemble/types.js.map +1 -1
- package/dist/engines/expert/index.d.ts +1 -1
- package/dist/engines/expert/index.d.ts.map +1 -1
- package/dist/engines/expert/index.js +3 -1
- package/dist/engines/expert/index.js.map +1 -1
- package/dist/engines/expert/types.d.ts +11 -1
- package/dist/engines/expert/types.d.ts.map +1 -1
- package/dist/engines/expert/types.js +18 -1
- package/dist/engines/expert/types.js.map +1 -1
- package/dist/engines/fuzzy/fuzzy.types.d.ts +65 -8
- package/dist/engines/fuzzy/fuzzy.types.d.ts.map +1 -1
- package/dist/engines/fuzzy/fuzzy.types.js +89 -1
- package/dist/engines/fuzzy/fuzzy.types.js.map +1 -1
- package/dist/engines/loyalty/compiler.d.ts +11 -0
- package/dist/engines/loyalty/compiler.d.ts.map +1 -0
- package/dist/engines/loyalty/compiler.js +144 -0
- package/dist/engines/loyalty/compiler.js.map +1 -0
- package/dist/engines/loyalty/engine.d.ts +76 -0
- package/dist/engines/loyalty/engine.d.ts.map +1 -0
- package/dist/engines/loyalty/engine.js +132 -0
- package/dist/engines/loyalty/engine.js.map +1 -0
- package/dist/engines/loyalty/index.d.ts +9 -0
- package/dist/engines/loyalty/index.d.ts.map +1 -0
- package/dist/engines/loyalty/index.js +24 -0
- package/dist/engines/loyalty/index.js.map +1 -0
- package/dist/engines/loyalty/strategy.d.ts +35 -0
- package/dist/engines/loyalty/strategy.d.ts.map +1 -0
- package/dist/engines/loyalty/strategy.js +405 -0
- package/dist/engines/loyalty/strategy.js.map +1 -0
- package/dist/engines/loyalty/types.d.ts +221 -0
- package/dist/engines/loyalty/types.d.ts.map +1 -0
- package/dist/engines/loyalty/types.js +51 -0
- package/dist/engines/loyalty/types.js.map +1 -0
- package/dist/engines/menu-engineering/compiler.d.ts +11 -0
- package/dist/engines/menu-engineering/compiler.d.ts.map +1 -0
- package/dist/engines/menu-engineering/compiler.js +119 -0
- package/dist/engines/menu-engineering/compiler.js.map +1 -0
- package/dist/engines/menu-engineering/engine.d.ts +32 -0
- package/dist/engines/menu-engineering/engine.d.ts.map +1 -0
- package/dist/engines/menu-engineering/engine.js +40 -0
- package/dist/engines/menu-engineering/engine.js.map +1 -0
- package/dist/engines/menu-engineering/index.d.ts +9 -0
- package/dist/engines/menu-engineering/index.d.ts.map +1 -0
- package/dist/engines/menu-engineering/index.js +21 -0
- package/dist/engines/menu-engineering/index.js.map +1 -0
- package/dist/engines/menu-engineering/strategy.d.ts +18 -0
- package/dist/engines/menu-engineering/strategy.d.ts.map +1 -0
- package/dist/engines/menu-engineering/strategy.js +318 -0
- package/dist/engines/menu-engineering/strategy.js.map +1 -0
- package/dist/engines/menu-engineering/types.d.ts +187 -0
- package/dist/engines/menu-engineering/types.d.ts.map +1 -0
- package/dist/engines/menu-engineering/types.js +27 -0
- package/dist/engines/menu-engineering/types.js.map +1 -0
- package/dist/engines/monte-carlo/index.d.ts +1 -1
- package/dist/engines/monte-carlo/index.d.ts.map +1 -1
- package/dist/engines/monte-carlo/index.js +5 -1
- package/dist/engines/monte-carlo/index.js.map +1 -1
- package/dist/engines/monte-carlo/types.d.ts +16 -1
- package/dist/engines/monte-carlo/types.d.ts.map +1 -1
- package/dist/engines/monte-carlo/types.js +23 -1
- package/dist/engines/monte-carlo/types.js.map +1 -1
- package/dist/engines/negotiation/index.d.ts +1 -0
- package/dist/engines/negotiation/index.d.ts.map +1 -1
- package/dist/engines/negotiation/index.js +7 -1
- package/dist/engines/negotiation/index.js.map +1 -1
- package/dist/engines/negotiation/types.d.ts +23 -4
- package/dist/engines/negotiation/types.d.ts.map +1 -1
- package/dist/engines/negotiation/types.js +27 -0
- package/dist/engines/negotiation/types.js.map +1 -1
- package/dist/engines/prediction/index.d.ts +1 -1
- package/dist/engines/prediction/index.d.ts.map +1 -1
- package/dist/engines/prediction/index.js +6 -1
- package/dist/engines/prediction/index.js.map +1 -1
- package/dist/engines/prediction/types.d.ts +35 -5
- package/dist/engines/prediction/types.d.ts.map +1 -1
- package/dist/engines/prediction/types.js +39 -1
- package/dist/engines/prediction/types.js.map +1 -1
- package/dist/engines/pricing/index.d.ts +2 -2
- package/dist/engines/pricing/index.d.ts.map +1 -1
- package/dist/engines/pricing/index.js +3 -1
- package/dist/engines/pricing/index.js.map +1 -1
- package/dist/engines/pricing/types.d.ts +15 -1
- package/dist/engines/pricing/types.d.ts.map +1 -1
- package/dist/engines/pricing/types.js +16 -1
- package/dist/engines/pricing/types.js.map +1 -1
- package/dist/engines/ranking/index.d.ts +1 -1
- package/dist/engines/ranking/index.d.ts.map +1 -1
- package/dist/engines/ranking/index.js +6 -1
- package/dist/engines/ranking/index.js.map +1 -1
- package/dist/engines/ranking/types.d.ts +32 -5
- package/dist/engines/ranking/types.d.ts.map +1 -1
- package/dist/engines/ranking/types.js +36 -1
- package/dist/engines/ranking/types.js.map +1 -1
- package/dist/engines/recipe-costing/compiler.d.ts +11 -0
- package/dist/engines/recipe-costing/compiler.d.ts.map +1 -0
- package/dist/engines/recipe-costing/compiler.js +177 -0
- package/dist/engines/recipe-costing/compiler.js.map +1 -0
- package/dist/engines/recipe-costing/engine.d.ts +32 -0
- package/dist/engines/recipe-costing/engine.d.ts.map +1 -0
- package/dist/engines/recipe-costing/engine.js +40 -0
- package/dist/engines/recipe-costing/engine.js.map +1 -0
- package/dist/engines/recipe-costing/index.d.ts +9 -0
- package/dist/engines/recipe-costing/index.d.ts.map +1 -0
- package/dist/engines/recipe-costing/index.js +21 -0
- package/dist/engines/recipe-costing/index.js.map +1 -0
- package/dist/engines/recipe-costing/strategy.d.ts +20 -0
- package/dist/engines/recipe-costing/strategy.d.ts.map +1 -0
- package/dist/engines/recipe-costing/strategy.js +265 -0
- package/dist/engines/recipe-costing/strategy.js.map +1 -0
- package/dist/engines/recipe-costing/types.d.ts +213 -0
- package/dist/engines/recipe-costing/types.d.ts.map +1 -0
- package/dist/engines/recipe-costing/types.js +36 -0
- package/dist/engines/recipe-costing/types.js.map +1 -0
- package/dist/engines/scoring/index.d.ts +1 -1
- package/dist/engines/scoring/index.d.ts.map +1 -1
- package/dist/engines/scoring/index.js +3 -1
- package/dist/engines/scoring/index.js.map +1 -1
- package/dist/engines/scoring/types.d.ts +8 -1
- package/dist/engines/scoring/types.d.ts.map +1 -1
- package/dist/engines/scoring/types.js +18 -1
- package/dist/engines/scoring/types.js.map +1 -1
- package/dist/engines/sentiment/index.d.ts +1 -1
- package/dist/engines/sentiment/index.d.ts.map +1 -1
- package/dist/engines/sentiment/index.js +3 -1
- package/dist/engines/sentiment/index.js.map +1 -1
- package/dist/engines/sentiment/types.d.ts +13 -2
- package/dist/engines/sentiment/types.d.ts.map +1 -1
- package/dist/engines/sentiment/types.js +17 -1
- package/dist/engines/sentiment/types.js.map +1 -1
- package/dist/engines/state-machine/index.d.ts +1 -1
- package/dist/engines/state-machine/index.d.ts.map +1 -1
- package/dist/engines/state-machine/index.js +5 -1
- package/dist/engines/state-machine/index.js.map +1 -1
- package/dist/engines/state-machine/types.d.ts +7 -0
- package/dist/engines/state-machine/types.d.ts.map +1 -1
- package/dist/engines/state-machine/types.js +14 -0
- package/dist/engines/state-machine/types.js.map +1 -1
- package/dist/engines/utility/index.d.ts +2 -2
- package/dist/engines/utility/index.d.ts.map +1 -1
- package/dist/engines/utility/index.js +4 -1
- package/dist/engines/utility/index.js.map +1 -1
- package/dist/engines/utility/types.d.ts +21 -3
- package/dist/engines/utility/types.d.ts.map +1 -1
- package/dist/engines/utility/types.js +37 -1
- package/dist/engines/utility/types.js.map +1 -1
- package/dist/index.d.ts +30 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/evaluation/decay.ts +13 -2
- package/src/core/types/rule.ts +25 -1
- package/src/engines/bayesian/index.ts +1 -0
- package/src/engines/bayesian/types.ts +10 -8
- package/src/engines/constraint/types.ts +40 -11
- package/src/engines/decay/index.ts +4 -0
- package/src/engines/decay/types.ts +26 -4
- package/src/engines/defeasible/index.ts +7 -0
- package/src/engines/defeasible/types.ts +42 -18
- package/src/engines/ensemble/index.ts +6 -0
- package/src/engines/ensemble/types.ts +17 -13
- package/src/engines/expert/index.ts +1 -0
- package/src/engines/expert/types.ts +11 -9
- package/src/engines/fuzzy/fuzzy.types.ts +65 -31
- package/src/engines/loyalty/compiler.ts +174 -0
- package/src/engines/loyalty/engine.ts +174 -0
- package/src/engines/loyalty/index.ts +52 -0
- package/src/engines/loyalty/strategy.ts +532 -0
- package/src/engines/loyalty/types.ts +283 -0
- package/src/engines/menu-engineering/compiler.ts +145 -0
- package/src/engines/menu-engineering/engine.ts +48 -0
- package/src/engines/menu-engineering/index.ts +47 -0
- package/src/engines/menu-engineering/strategy.ts +414 -0
- package/src/engines/menu-engineering/types.ts +242 -0
- package/src/engines/monte-carlo/index.ts +1 -0
- package/src/engines/monte-carlo/types.ts +16 -21
- package/src/engines/negotiation/index.ts +8 -0
- package/src/engines/negotiation/types.ts +23 -4
- package/src/engines/prediction/index.ts +5 -0
- package/src/engines/prediction/types.ts +35 -5
- package/src/engines/pricing/index.ts +3 -1
- package/src/engines/pricing/types.ts +17 -1
- package/src/engines/ranking/index.ts +5 -0
- package/src/engines/ranking/types.ts +32 -11
- package/src/engines/recipe-costing/compiler.ts +219 -0
- package/src/engines/recipe-costing/engine.ts +48 -0
- package/src/engines/recipe-costing/index.ts +48 -0
- package/src/engines/recipe-costing/strategy.ts +357 -0
- package/src/engines/recipe-costing/types.ts +269 -0
- package/src/engines/scoring/index.ts +2 -0
- package/src/engines/scoring/types.ts +8 -6
- package/src/engines/sentiment/index.ts +2 -0
- package/src/engines/sentiment/types.ts +13 -2
- package/src/engines/state-machine/index.ts +3 -0
- package/src/engines/state-machine/types.ts +8 -0
- package/src/engines/utility/index.ts +5 -0
- package/src/engines/utility/types.ts +23 -3
- package/src/index.ts +182 -7
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Menu Engineering Engine Strategy
|
|
4
|
+
*
|
|
5
|
+
* Core execution logic for all menu engineering strategies:
|
|
6
|
+
* - classify: categorize items into Stars/Plowhorses/Puzzles/Dogs
|
|
7
|
+
* - price-optimization: model price change impacts with elasticity
|
|
8
|
+
* - mix-analysis: analyze category/daypart mix with divergence detection
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.menuEngineeringStrategy = exports.MenuEngineeringExecutor = void 0;
|
|
12
|
+
// ========================================
|
|
13
|
+
// Helpers
|
|
14
|
+
// ========================================
|
|
15
|
+
function round(value, decimals) {
|
|
16
|
+
const factor = Math.pow(10, decimals);
|
|
17
|
+
return Math.round(value * factor) / factor;
|
|
18
|
+
}
|
|
19
|
+
function classifyItem(salesMixPct, contributionMargin, mixThreshold, marginThreshold) {
|
|
20
|
+
const highMix = salesMixPct >= mixThreshold;
|
|
21
|
+
const highMargin = contributionMargin >= marginThreshold;
|
|
22
|
+
if (highMix && highMargin)
|
|
23
|
+
return 'star';
|
|
24
|
+
if (highMix && !highMargin)
|
|
25
|
+
return 'plowhorse';
|
|
26
|
+
if (!highMix && highMargin)
|
|
27
|
+
return 'puzzle';
|
|
28
|
+
return 'dog';
|
|
29
|
+
}
|
|
30
|
+
function getRecommendation(classification) {
|
|
31
|
+
switch (classification) {
|
|
32
|
+
case 'star':
|
|
33
|
+
return 'Maintain quality and visibility. Signature item -- protect pricing and placement.';
|
|
34
|
+
case 'plowhorse':
|
|
35
|
+
return 'Popular but low margin. Consider portion adjustments, ingredient substitution, or slight price increase.';
|
|
36
|
+
case 'puzzle':
|
|
37
|
+
return 'High margin but low sales. Improve menu placement, rename, or bundle with popular items.';
|
|
38
|
+
case 'dog':
|
|
39
|
+
return 'Low popularity and low margin. Consider removing, repositioning, or reworking the recipe.';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function computeClassifiedItems(items, mixThreshold, marginThreshold) {
|
|
43
|
+
const totalSalesCount = items.reduce((sum, item) => sum + item.salesCount, 0);
|
|
44
|
+
const classifiedItems = items.map(item => {
|
|
45
|
+
const contributionMargin = round(item.sellingPrice - item.plateCost, 2);
|
|
46
|
+
const foodCostPct = item.sellingPrice > 0
|
|
47
|
+
? round((item.plateCost / item.sellingPrice) * 100, 2)
|
|
48
|
+
: 0;
|
|
49
|
+
const salesMixPct = totalSalesCount > 0
|
|
50
|
+
? round((item.salesCount / totalSalesCount) * 100, 2)
|
|
51
|
+
: 0;
|
|
52
|
+
const classification = classifyItem(salesMixPct, contributionMargin, mixThreshold, marginThreshold);
|
|
53
|
+
return {
|
|
54
|
+
id: item.id,
|
|
55
|
+
name: item.name,
|
|
56
|
+
category: item.category,
|
|
57
|
+
sellingPrice: item.sellingPrice,
|
|
58
|
+
plateCost: item.plateCost,
|
|
59
|
+
salesCount: item.salesCount,
|
|
60
|
+
contributionMargin,
|
|
61
|
+
foodCostPct,
|
|
62
|
+
salesMixPct,
|
|
63
|
+
classification,
|
|
64
|
+
recommendation: getRecommendation(classification)
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
return { classifiedItems, totalSalesCount };
|
|
68
|
+
}
|
|
69
|
+
function computeSummary(items) {
|
|
70
|
+
const totalItems = items.length;
|
|
71
|
+
const totalSalesCount = items.reduce((sum, i) => sum + i.salesCount, 0);
|
|
72
|
+
const totalRevenue = items.reduce((sum, i) => sum + i.sellingPrice * i.salesCount, 0);
|
|
73
|
+
const totalCost = items.reduce((sum, i) => sum + i.plateCost * i.salesCount, 0);
|
|
74
|
+
const totalProfit = round(totalRevenue - totalCost, 2);
|
|
75
|
+
const avgContributionMargin = totalItems > 0
|
|
76
|
+
? round(items.reduce((sum, i) => sum + i.contributionMargin, 0) / totalItems, 2)
|
|
77
|
+
: 0;
|
|
78
|
+
const avgFoodCostPct = totalItems > 0
|
|
79
|
+
? round(items.reduce((sum, i) => sum + i.foodCostPct, 0) / totalItems, 2)
|
|
80
|
+
: 0;
|
|
81
|
+
const avgSalesMixPct = totalItems > 0
|
|
82
|
+
? round(100 / totalItems, 2)
|
|
83
|
+
: 0;
|
|
84
|
+
const classificationCounts = {
|
|
85
|
+
star: 0,
|
|
86
|
+
plowhorse: 0,
|
|
87
|
+
puzzle: 0,
|
|
88
|
+
dog: 0
|
|
89
|
+
};
|
|
90
|
+
for (const item of items) {
|
|
91
|
+
classificationCounts[item.classification]++;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
totalItems,
|
|
95
|
+
totalSalesCount,
|
|
96
|
+
totalRevenue: round(totalRevenue, 2),
|
|
97
|
+
totalCost: round(totalCost, 2),
|
|
98
|
+
totalProfit,
|
|
99
|
+
avgContributionMargin,
|
|
100
|
+
avgFoodCostPct,
|
|
101
|
+
avgSalesMixPct,
|
|
102
|
+
classificationCounts
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// ========================================
|
|
106
|
+
// Strategy Executor
|
|
107
|
+
// ========================================
|
|
108
|
+
class MenuEngineeringExecutor {
|
|
109
|
+
run(ruleSet, _options = {}) {
|
|
110
|
+
switch (ruleSet.strategy) {
|
|
111
|
+
case 'classify':
|
|
112
|
+
return this.runClassify(ruleSet);
|
|
113
|
+
case 'price-optimization':
|
|
114
|
+
return this.runPriceOptimization(ruleSet);
|
|
115
|
+
case 'mix-analysis':
|
|
116
|
+
return this.runMixAnalysis(ruleSet);
|
|
117
|
+
default:
|
|
118
|
+
throw new Error(`Unknown menu engineering strategy: '${ruleSet.strategy}'`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// ========================================
|
|
122
|
+
// Classify Strategy
|
|
123
|
+
// ========================================
|
|
124
|
+
runClassify(ruleSet) {
|
|
125
|
+
const startTime = performance.now();
|
|
126
|
+
// Compute thresholds
|
|
127
|
+
const items = ruleSet.items;
|
|
128
|
+
const totalSalesCount = items.reduce((sum, i) => sum + i.salesCount, 0);
|
|
129
|
+
const margins = items.map(i => i.sellingPrice - i.plateCost);
|
|
130
|
+
const mixPcts = items.map(i => totalSalesCount > 0 ? (i.salesCount / totalSalesCount) * 100 : 0);
|
|
131
|
+
const avgMargin = margins.reduce((sum, m) => sum + m, 0) / margins.length;
|
|
132
|
+
const avgMix = mixPcts.reduce((sum, m) => sum + m, 0) / mixPcts.length;
|
|
133
|
+
const mixThreshold = ruleSet.config.mixThresholdMode === 'custom'
|
|
134
|
+
? ruleSet.config.customMixThreshold
|
|
135
|
+
: avgMix;
|
|
136
|
+
const marginThreshold = ruleSet.config.marginThresholdMode === 'custom'
|
|
137
|
+
? ruleSet.config.customMarginThreshold
|
|
138
|
+
: avgMargin;
|
|
139
|
+
const { classifiedItems } = computeClassifiedItems(items, mixThreshold, marginThreshold);
|
|
140
|
+
const summary = computeSummary(classifiedItems);
|
|
141
|
+
const executionTimeMs = round((performance.now() - startTime) * 100, 0) / 100;
|
|
142
|
+
return {
|
|
143
|
+
items: classifiedItems,
|
|
144
|
+
summary,
|
|
145
|
+
executionTimeMs
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// ========================================
|
|
149
|
+
// Price Optimization Strategy
|
|
150
|
+
// ========================================
|
|
151
|
+
runPriceOptimization(ruleSet) {
|
|
152
|
+
const startTime = performance.now();
|
|
153
|
+
// Run baseline classify
|
|
154
|
+
const items = ruleSet.items;
|
|
155
|
+
const totalSalesCount = items.reduce((sum, i) => sum + i.salesCount, 0);
|
|
156
|
+
const margins = items.map(i => i.sellingPrice - i.plateCost);
|
|
157
|
+
const mixPcts = items.map(i => totalSalesCount > 0 ? (i.salesCount / totalSalesCount) * 100 : 0);
|
|
158
|
+
const avgMargin = margins.reduce((sum, m) => sum + m, 0) / margins.length;
|
|
159
|
+
const avgMix = mixPcts.reduce((sum, m) => sum + m, 0) / mixPcts.length;
|
|
160
|
+
const { classifiedItems: baselineItems } = computeClassifiedItems(items, avgMix, avgMargin);
|
|
161
|
+
// Build lookup maps
|
|
162
|
+
const baselineMap = new Map(baselineItems.map(i => [i.id, i]));
|
|
163
|
+
const priceChangeMap = new Map(ruleSet.config.priceChanges.map(pc => [pc.itemId, pc]));
|
|
164
|
+
const elasticityMap = new Map();
|
|
165
|
+
for (const e of ruleSet.config.elasticities) {
|
|
166
|
+
if (e.itemId) {
|
|
167
|
+
elasticityMap.set(`item:${e.itemId}`, e.elasticity);
|
|
168
|
+
}
|
|
169
|
+
if (e.category) {
|
|
170
|
+
elasticityMap.set(`cat:${e.category}`, e.elasticity);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Apply price changes and compute new projected items
|
|
174
|
+
const modifiedItems = items.map(item => {
|
|
175
|
+
const change = priceChangeMap.get(item.id);
|
|
176
|
+
if (!change)
|
|
177
|
+
return item;
|
|
178
|
+
return { ...item, sellingPrice: change.newPrice };
|
|
179
|
+
});
|
|
180
|
+
// Estimate new sales counts based on elasticity
|
|
181
|
+
const projectedItems = modifiedItems.map(item => {
|
|
182
|
+
const change = priceChangeMap.get(item.id);
|
|
183
|
+
if (!change)
|
|
184
|
+
return item;
|
|
185
|
+
const originalItem = items.find(i => i.id === item.id);
|
|
186
|
+
const priceChangePct = (change.newPrice - originalItem.sellingPrice) / originalItem.sellingPrice;
|
|
187
|
+
// Resolve elasticity: item-specific > category > default
|
|
188
|
+
let elasticity = ruleSet.config.defaultElasticity;
|
|
189
|
+
if (elasticityMap.has(`item:${item.id}`)) {
|
|
190
|
+
elasticity = elasticityMap.get(`item:${item.id}`);
|
|
191
|
+
}
|
|
192
|
+
else if (item.category && elasticityMap.has(`cat:${item.category}`)) {
|
|
193
|
+
elasticity = elasticityMap.get(`cat:${item.category}`);
|
|
194
|
+
}
|
|
195
|
+
const estimatedNewSalesCount = Math.max(0, Math.round(originalItem.salesCount * (1 + elasticity * priceChangePct)));
|
|
196
|
+
return { ...item, salesCount: estimatedNewSalesCount };
|
|
197
|
+
});
|
|
198
|
+
// Re-classify with new data
|
|
199
|
+
const newTotalSalesCount = projectedItems.reduce((sum, i) => sum + i.salesCount, 0);
|
|
200
|
+
const newMargins = projectedItems.map(i => i.sellingPrice - i.plateCost);
|
|
201
|
+
const newMixPcts = projectedItems.map(i => newTotalSalesCount > 0 ? (i.salesCount / newTotalSalesCount) * 100 : 0);
|
|
202
|
+
const newAvgMargin = newMargins.reduce((sum, m) => sum + m, 0) / newMargins.length;
|
|
203
|
+
const newAvgMix = newMixPcts.reduce((sum, m) => sum + m, 0) / newMixPcts.length;
|
|
204
|
+
const { classifiedItems: newClassifiedItems } = computeClassifiedItems(projectedItems, newAvgMix, newAvgMargin);
|
|
205
|
+
const newClassifiedMap = new Map(newClassifiedItems.map(i => [i.id, i]));
|
|
206
|
+
// Build optimization results for changed items
|
|
207
|
+
const optimizationItems = [];
|
|
208
|
+
for (const change of ruleSet.config.priceChanges) {
|
|
209
|
+
const baseline = baselineMap.get(change.itemId);
|
|
210
|
+
const projected = newClassifiedMap.get(change.itemId);
|
|
211
|
+
const originalItem = items.find(i => i.id === change.itemId);
|
|
212
|
+
const priceChangePct = round(((change.newPrice - originalItem.sellingPrice) / originalItem.sellingPrice) * 100, 2);
|
|
213
|
+
const originalRevenue = originalItem.sellingPrice * originalItem.salesCount;
|
|
214
|
+
const originalProfit = baseline.contributionMargin * originalItem.salesCount;
|
|
215
|
+
const projectedRevenue = projected.sellingPrice * projected.salesCount;
|
|
216
|
+
const projectedProfit = projected.contributionMargin * projected.salesCount;
|
|
217
|
+
optimizationItems.push({
|
|
218
|
+
id: change.itemId,
|
|
219
|
+
name: baseline.name,
|
|
220
|
+
originalPrice: originalItem.sellingPrice,
|
|
221
|
+
newPrice: change.newPrice,
|
|
222
|
+
priceChangePct,
|
|
223
|
+
originalMargin: baseline.contributionMargin,
|
|
224
|
+
newMargin: projected.contributionMargin,
|
|
225
|
+
estimatedNewSalesCount: projected.salesCount,
|
|
226
|
+
originalClassification: baseline.classification,
|
|
227
|
+
newClassification: projected.classification,
|
|
228
|
+
projectedRevenueChange: round(projectedRevenue - originalRevenue, 2),
|
|
229
|
+
projectedProfitChange: round(projectedProfit - originalProfit, 2)
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const summary = computeSummary(newClassifiedItems);
|
|
233
|
+
const executionTimeMs = round((performance.now() - startTime) * 100, 0) / 100;
|
|
234
|
+
return {
|
|
235
|
+
items: optimizationItems,
|
|
236
|
+
summary,
|
|
237
|
+
executionTimeMs
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
// ========================================
|
|
241
|
+
// Mix Analysis Strategy
|
|
242
|
+
// ========================================
|
|
243
|
+
runMixAnalysis(ruleSet) {
|
|
244
|
+
const startTime = performance.now();
|
|
245
|
+
const items = ruleSet.items;
|
|
246
|
+
const groupField = ruleSet.config.groupBy === 'daypart'
|
|
247
|
+
? ruleSet.config.daypartField
|
|
248
|
+
: 'category';
|
|
249
|
+
// Group items
|
|
250
|
+
const groups = new Map();
|
|
251
|
+
for (const item of items) {
|
|
252
|
+
const key = item[groupField] ?? 'uncategorized';
|
|
253
|
+
if (!groups.has(key)) {
|
|
254
|
+
groups.set(key, []);
|
|
255
|
+
}
|
|
256
|
+
groups.get(key).push(item);
|
|
257
|
+
}
|
|
258
|
+
// Compute overall totals for mix percentages
|
|
259
|
+
const overallTotalSalesCount = items.reduce((sum, i) => sum + i.salesCount, 0);
|
|
260
|
+
const overallTotalRevenue = items.reduce((sum, i) => sum + i.sellingPrice * i.salesCount, 0);
|
|
261
|
+
const overallTotalProfit = items.reduce((sum, i) => sum + (i.sellingPrice - i.plateCost) * i.salesCount, 0);
|
|
262
|
+
// Run classify within each group and compute category-level metrics
|
|
263
|
+
const categories = [];
|
|
264
|
+
for (const [category, groupItems] of groups) {
|
|
265
|
+
// Classify within group
|
|
266
|
+
const totalGroupSales = groupItems.reduce((sum, i) => sum + i.salesCount, 0);
|
|
267
|
+
const groupMargins = groupItems.map(i => i.sellingPrice - i.plateCost);
|
|
268
|
+
const groupMixPcts = groupItems.map(i => totalGroupSales > 0 ? (i.salesCount / totalGroupSales) * 100 : 0);
|
|
269
|
+
const groupAvgMargin = groupMargins.reduce((sum, m) => sum + m, 0) / groupMargins.length;
|
|
270
|
+
const groupAvgMix = groupMixPcts.reduce((sum, m) => sum + m, 0) / groupMixPcts.length;
|
|
271
|
+
const { classifiedItems } = computeClassifiedItems(groupItems, groupAvgMix, groupAvgMargin);
|
|
272
|
+
const totalRevenue = groupItems.reduce((sum, i) => sum + i.sellingPrice * i.salesCount, 0);
|
|
273
|
+
const totalCost = groupItems.reduce((sum, i) => sum + i.plateCost * i.salesCount, 0);
|
|
274
|
+
const totalProfit = totalRevenue - totalCost;
|
|
275
|
+
const avgContributionMargin = groupItems.length > 0
|
|
276
|
+
? round(groupItems.reduce((sum, i) => sum + (i.sellingPrice - i.plateCost), 0) / groupItems.length, 2)
|
|
277
|
+
: 0;
|
|
278
|
+
categories.push({
|
|
279
|
+
category,
|
|
280
|
+
itemCount: groupItems.length,
|
|
281
|
+
totalSalesCount: totalGroupSales,
|
|
282
|
+
totalRevenue: round(totalRevenue, 2),
|
|
283
|
+
totalCost: round(totalCost, 2),
|
|
284
|
+
totalProfit: round(totalProfit, 2),
|
|
285
|
+
avgContributionMargin,
|
|
286
|
+
salesMixPct: overallTotalSalesCount > 0
|
|
287
|
+
? round((totalGroupSales / overallTotalSalesCount) * 100, 2)
|
|
288
|
+
: 0,
|
|
289
|
+
revenueMixPct: overallTotalRevenue > 0
|
|
290
|
+
? round((totalRevenue / overallTotalRevenue) * 100, 2)
|
|
291
|
+
: 0,
|
|
292
|
+
profitMixPct: overallTotalProfit > 0
|
|
293
|
+
? round((totalProfit / overallTotalProfit) * 100, 2)
|
|
294
|
+
: 0,
|
|
295
|
+
items: classifiedItems
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
// Sort categories by revenue descending
|
|
299
|
+
categories.sort((a, b) => b.totalRevenue - a.totalRevenue);
|
|
300
|
+
// Compute overall summary using all items classified globally
|
|
301
|
+
const allMargins = items.map(i => i.sellingPrice - i.plateCost);
|
|
302
|
+
const allMixPcts = items.map(i => overallTotalSalesCount > 0 ? (i.salesCount / overallTotalSalesCount) * 100 : 0);
|
|
303
|
+
const overallAvgMargin = allMargins.reduce((sum, m) => sum + m, 0) / allMargins.length;
|
|
304
|
+
const overallAvgMix = allMixPcts.reduce((sum, m) => sum + m, 0) / allMixPcts.length;
|
|
305
|
+
const { classifiedItems: allClassified } = computeClassifiedItems(items, overallAvgMix, overallAvgMargin);
|
|
306
|
+
const summary = computeSummary(allClassified);
|
|
307
|
+
const executionTimeMs = round((performance.now() - startTime) * 100, 0) / 100;
|
|
308
|
+
return {
|
|
309
|
+
categories,
|
|
310
|
+
summary,
|
|
311
|
+
executionTimeMs
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
exports.MenuEngineeringExecutor = MenuEngineeringExecutor;
|
|
316
|
+
/** Singleton instance */
|
|
317
|
+
exports.menuEngineeringStrategy = new MenuEngineeringExecutor();
|
|
318
|
+
//# sourceMappingURL=strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../../src/engines/menu-engineering/strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Menu Engineering Engine Types
|
|
3
|
+
*
|
|
4
|
+
* Classifies menu items into Stars/Plowhorses/Puzzles/Dogs based on
|
|
5
|
+
* sales mix percentage and contribution margin. Supports price optimization
|
|
6
|
+
* with elasticity modeling and category-level mix analysis.
|
|
7
|
+
*/
|
|
8
|
+
/** Menu engineering strategy to use */
|
|
9
|
+
export declare const MenuEngineeringStrategies: {
|
|
10
|
+
readonly classify: "classify";
|
|
11
|
+
readonly priceOptimization: "price-optimization";
|
|
12
|
+
readonly mixAnalysis: "mix-analysis";
|
|
13
|
+
};
|
|
14
|
+
export type MenuEngineeringStrategy = typeof MenuEngineeringStrategies[keyof typeof MenuEngineeringStrategies];
|
|
15
|
+
/** Menu item classification quadrant */
|
|
16
|
+
export declare const MenuClassifications: {
|
|
17
|
+
readonly star: "star";
|
|
18
|
+
readonly plowhorse: "plowhorse";
|
|
19
|
+
readonly puzzle: "puzzle";
|
|
20
|
+
readonly dog: "dog";
|
|
21
|
+
};
|
|
22
|
+
export type MenuClassification = typeof MenuClassifications[keyof typeof MenuClassifications];
|
|
23
|
+
/** A menu item with sales and cost data */
|
|
24
|
+
export type MenuItem = {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
category?: string;
|
|
28
|
+
sellingPrice: number;
|
|
29
|
+
plateCost: number;
|
|
30
|
+
salesCount: number;
|
|
31
|
+
};
|
|
32
|
+
/** Price elasticity for an item or category */
|
|
33
|
+
export type PriceElasticity = {
|
|
34
|
+
itemId?: string;
|
|
35
|
+
category?: string;
|
|
36
|
+
elasticity: number;
|
|
37
|
+
};
|
|
38
|
+
/** A proposed price change for a menu item */
|
|
39
|
+
export type PriceChange = {
|
|
40
|
+
itemId: string;
|
|
41
|
+
newPrice: number;
|
|
42
|
+
};
|
|
43
|
+
/** Configuration for classify strategy */
|
|
44
|
+
export type ClassifyConfig = {
|
|
45
|
+
mixThresholdMode?: 'average' | 'custom';
|
|
46
|
+
customMixThreshold?: number;
|
|
47
|
+
marginThresholdMode?: 'average' | 'custom';
|
|
48
|
+
customMarginThreshold?: number;
|
|
49
|
+
};
|
|
50
|
+
/** Configuration for price-optimization strategy */
|
|
51
|
+
export type PriceOptimizationConfig = {
|
|
52
|
+
priceChanges: PriceChange[];
|
|
53
|
+
elasticities?: PriceElasticity[];
|
|
54
|
+
defaultElasticity?: number;
|
|
55
|
+
};
|
|
56
|
+
/** Configuration for mix-analysis strategy */
|
|
57
|
+
export type MixAnalysisConfig = {
|
|
58
|
+
groupBy?: 'category' | 'daypart';
|
|
59
|
+
daypartField?: string;
|
|
60
|
+
};
|
|
61
|
+
type MenuEngineeringRuleSetBase = {
|
|
62
|
+
id: string;
|
|
63
|
+
name?: string;
|
|
64
|
+
mode: 'menu-engineering';
|
|
65
|
+
items: MenuItem[];
|
|
66
|
+
};
|
|
67
|
+
/** Classify strategy: categorize items into quadrants */
|
|
68
|
+
export type ClassifyRuleSet = MenuEngineeringRuleSetBase & {
|
|
69
|
+
strategy: 'classify';
|
|
70
|
+
config?: ClassifyConfig;
|
|
71
|
+
};
|
|
72
|
+
/** Price-optimization strategy: model price change impacts */
|
|
73
|
+
export type PriceOptimizationRuleSet = MenuEngineeringRuleSetBase & {
|
|
74
|
+
strategy: 'price-optimization';
|
|
75
|
+
config: PriceOptimizationConfig;
|
|
76
|
+
};
|
|
77
|
+
/** Mix-analysis strategy: analyze category/daypart mix */
|
|
78
|
+
export type MixAnalysisRuleSet = MenuEngineeringRuleSetBase & {
|
|
79
|
+
strategy: 'mix-analysis';
|
|
80
|
+
config?: MixAnalysisConfig;
|
|
81
|
+
};
|
|
82
|
+
export type MenuEngineeringRuleSet = ClassifyRuleSet | PriceOptimizationRuleSet | MixAnalysisRuleSet;
|
|
83
|
+
type CompiledMenuEngineeringRuleSetBase = {
|
|
84
|
+
id: string;
|
|
85
|
+
name?: string;
|
|
86
|
+
mode: 'menu-engineering';
|
|
87
|
+
items: MenuItem[];
|
|
88
|
+
};
|
|
89
|
+
export type CompiledClassifyRuleSet = CompiledMenuEngineeringRuleSetBase & {
|
|
90
|
+
strategy: 'classify';
|
|
91
|
+
config: Required<ClassifyConfig>;
|
|
92
|
+
};
|
|
93
|
+
export type CompiledPriceOptimizationRuleSet = CompiledMenuEngineeringRuleSetBase & {
|
|
94
|
+
strategy: 'price-optimization';
|
|
95
|
+
config: {
|
|
96
|
+
priceChanges: PriceChange[];
|
|
97
|
+
elasticities: PriceElasticity[];
|
|
98
|
+
defaultElasticity: number;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
export type CompiledMixAnalysisRuleSet = CompiledMenuEngineeringRuleSetBase & {
|
|
102
|
+
strategy: 'mix-analysis';
|
|
103
|
+
config: {
|
|
104
|
+
groupBy: 'category' | 'daypart';
|
|
105
|
+
daypartField: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
export type CompiledMenuEngineeringRuleSet = CompiledClassifyRuleSet | CompiledPriceOptimizationRuleSet | CompiledMixAnalysisRuleSet;
|
|
109
|
+
/** A classified menu item with computed metrics */
|
|
110
|
+
export type ClassifiedItem = {
|
|
111
|
+
id: string;
|
|
112
|
+
name: string;
|
|
113
|
+
category?: string;
|
|
114
|
+
sellingPrice: number;
|
|
115
|
+
plateCost: number;
|
|
116
|
+
salesCount: number;
|
|
117
|
+
contributionMargin: number;
|
|
118
|
+
foodCostPct: number;
|
|
119
|
+
salesMixPct: number;
|
|
120
|
+
classification: MenuClassification;
|
|
121
|
+
recommendation: string;
|
|
122
|
+
};
|
|
123
|
+
/** Summary statistics for the menu */
|
|
124
|
+
export type MenuSummary = {
|
|
125
|
+
totalItems: number;
|
|
126
|
+
totalSalesCount: number;
|
|
127
|
+
totalRevenue: number;
|
|
128
|
+
totalCost: number;
|
|
129
|
+
totalProfit: number;
|
|
130
|
+
avgContributionMargin: number;
|
|
131
|
+
avgFoodCostPct: number;
|
|
132
|
+
avgSalesMixPct: number;
|
|
133
|
+
classificationCounts: Record<MenuClassification, number>;
|
|
134
|
+
};
|
|
135
|
+
/** A price-optimized menu item with projected impact */
|
|
136
|
+
export type PriceOptimizationItem = {
|
|
137
|
+
id: string;
|
|
138
|
+
name: string;
|
|
139
|
+
originalPrice: number;
|
|
140
|
+
newPrice: number;
|
|
141
|
+
priceChangePct: number;
|
|
142
|
+
originalMargin: number;
|
|
143
|
+
newMargin: number;
|
|
144
|
+
estimatedNewSalesCount: number;
|
|
145
|
+
originalClassification: MenuClassification;
|
|
146
|
+
newClassification: MenuClassification;
|
|
147
|
+
projectedRevenueChange: number;
|
|
148
|
+
projectedProfitChange: number;
|
|
149
|
+
};
|
|
150
|
+
/** Category-level mix analysis result */
|
|
151
|
+
export type CategoryMixResult = {
|
|
152
|
+
category: string;
|
|
153
|
+
itemCount: number;
|
|
154
|
+
totalSalesCount: number;
|
|
155
|
+
totalRevenue: number;
|
|
156
|
+
totalCost: number;
|
|
157
|
+
totalProfit: number;
|
|
158
|
+
avgContributionMargin: number;
|
|
159
|
+
salesMixPct: number;
|
|
160
|
+
revenueMixPct: number;
|
|
161
|
+
profitMixPct: number;
|
|
162
|
+
items: ClassifiedItem[];
|
|
163
|
+
};
|
|
164
|
+
/** Result from classify strategy */
|
|
165
|
+
export type ClassifyResult = {
|
|
166
|
+
items: ClassifiedItem[];
|
|
167
|
+
summary: MenuSummary;
|
|
168
|
+
executionTimeMs: number;
|
|
169
|
+
};
|
|
170
|
+
/** Result from price-optimization strategy */
|
|
171
|
+
export type PriceOptimizationResult = {
|
|
172
|
+
items: PriceOptimizationItem[];
|
|
173
|
+
summary: MenuSummary;
|
|
174
|
+
executionTimeMs: number;
|
|
175
|
+
};
|
|
176
|
+
/** Result from mix-analysis strategy */
|
|
177
|
+
export type MixAnalysisResult = {
|
|
178
|
+
categories: CategoryMixResult[];
|
|
179
|
+
summary: MenuSummary;
|
|
180
|
+
executionTimeMs: number;
|
|
181
|
+
};
|
|
182
|
+
/** Union of all menu engineering results */
|
|
183
|
+
export type MenuEngineeringResult = ClassifyResult | PriceOptimizationResult | MixAnalysisResult;
|
|
184
|
+
/** Runtime options */
|
|
185
|
+
export type MenuEngineeringOptions = Record<string, never>;
|
|
186
|
+
export {};
|
|
187
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/engines/menu-engineering/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Menu Engineering Engine Types
|
|
4
|
+
*
|
|
5
|
+
* Classifies menu items into Stars/Plowhorses/Puzzles/Dogs based on
|
|
6
|
+
* sales mix percentage and contribution margin. Supports price optimization
|
|
7
|
+
* with elasticity modeling and category-level mix analysis.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.MenuClassifications = exports.MenuEngineeringStrategies = void 0;
|
|
11
|
+
// ========================================
|
|
12
|
+
// Semantic Types
|
|
13
|
+
// ========================================
|
|
14
|
+
/** Menu engineering strategy to use */
|
|
15
|
+
exports.MenuEngineeringStrategies = {
|
|
16
|
+
classify: 'classify',
|
|
17
|
+
priceOptimization: 'price-optimization',
|
|
18
|
+
mixAnalysis: 'mix-analysis',
|
|
19
|
+
};
|
|
20
|
+
/** Menu item classification quadrant */
|
|
21
|
+
exports.MenuClassifications = {
|
|
22
|
+
star: 'star',
|
|
23
|
+
plowhorse: 'plowhorse',
|
|
24
|
+
puzzle: 'puzzle',
|
|
25
|
+
dog: 'dog',
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/engines/menu-engineering/types.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,2CAA2C;AAC3C,iBAAiB;AACjB,2CAA2C;AAE3C,uCAAuC;AAC1B,QAAA,yBAAyB,GAAG;IACvC,QAAQ,EAAE,UAAU;IACpB,iBAAiB,EAAE,oBAAoB;IACvC,WAAW,EAAE,cAAc;CACnB,CAAC;AAGX,wCAAwC;AAC3B,QAAA,mBAAmB,GAAG;IACjC,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,KAAK;CACF,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Run thousands of simulations with probabilistic inputs to get
|
|
6
6
|
* statistical distributions of possible outcomes.
|
|
7
7
|
*/
|
|
8
|
-
export { EstimateType, PercentOrNumber, TriangularVariable, NormalVariable, UniformVariable, DiscreteVariable, MonteCarloVariable, MonteCarloOutput, MonteCarloRuleSet, MonteCarloConfig, CompiledVariable, CompiledOutput, CompiledMonteCarloRuleSet, MonteCarloOptions, OutputStatistics, HistogramBin, SensitivityAnalysis, MonteCarloResult } from './types';
|
|
8
|
+
export { EstimateTypes, EstimateType, PercentOrNumber, TriangularVariable, NormalVariable, UniformVariable, DiscreteVariable, MonteCarloVariable, MonteCarloOutput, MonteCarloRuleSet, MonteCarloConfig, CompiledVariable, CompiledOutput, CompiledMonteCarloRuleSet, MonteCarloOptions, OutputStatistics, HistogramBin, SensitivityAnalysis, MonteCarloResult } from './types';
|
|
9
9
|
export { compileMonteCarloRuleSet } from './compiler';
|
|
10
10
|
export { MonteCarloStrategy, monteCarloStrategy } from './strategy';
|
|
11
11
|
export { MonteCarloEngine } from './engine';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engines/monte-carlo/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAEL,YAAY,EACZ,eAAe,EAEf,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAElB,gBAAgB,EAEhB,iBAAiB,EACjB,gBAAgB,EAEhB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EAEzB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engines/monte-carlo/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAEL,aAAa,EACb,YAAY,EACZ,eAAe,EAEf,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAElB,gBAAgB,EAEhB,iBAAiB,EACjB,gBAAgB,EAEhB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EAEzB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
* statistical distributions of possible outcomes.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.MonteCarloEngine = exports.monteCarloStrategy = exports.MonteCarloStrategy = exports.compileMonteCarloRuleSet = void 0;
|
|
10
|
+
exports.MonteCarloEngine = exports.monteCarloStrategy = exports.MonteCarloStrategy = exports.compileMonteCarloRuleSet = exports.EstimateTypes = void 0;
|
|
11
|
+
// Types
|
|
12
|
+
var types_1 = require("./types");
|
|
13
|
+
// Estimate types
|
|
14
|
+
Object.defineProperty(exports, "EstimateTypes", { enumerable: true, get: function () { return types_1.EstimateTypes; } });
|
|
11
15
|
// Compiler
|
|
12
16
|
var compiler_1 = require("./compiler");
|
|
13
17
|
Object.defineProperty(exports, "compileMonteCarloRuleSet", { enumerable: true, get: function () { return compiler_1.compileMonteCarloRuleSet; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engines/monte-carlo/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engines/monte-carlo/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,QAAQ;AACR,iCA0BiB;AAzBf,iBAAiB;AACjB,sGAAA,aAAa,OAAA;AA0Bf,WAAW;AACX,uCAAsD;AAA7C,oHAAA,wBAAwB,OAAA;AAEjC,WAAW;AACX,uCAAoE;AAA3D,8GAAA,kBAAkB,OAAA;AAAE,8GAAA,kBAAkB,OAAA;AAE/C,SAAS;AACT,mCAA4C;AAAnC,0GAAA,gBAAgB,OAAA"}
|
|
@@ -33,7 +33,22 @@ export declare const ITERATION_PRESETS: Record<IterationPreset, number>;
|
|
|
33
33
|
* Estimate type determines the probability distribution shape.
|
|
34
34
|
* Multiple aliases supported for different audiences.
|
|
35
35
|
*/
|
|
36
|
-
export
|
|
36
|
+
export declare const EstimateTypes: {
|
|
37
|
+
readonly bestLikelyWorst: "best-likely-worst";
|
|
38
|
+
readonly lowMidHigh: "low-mid-high";
|
|
39
|
+
readonly minExpectedMax: "min-expected-max";
|
|
40
|
+
readonly optimisticRealisticPessimistic: "optimistic-realistic-pessimistic";
|
|
41
|
+
readonly typicallyAround: "typically-around";
|
|
42
|
+
readonly bellCurve: "bell-curve";
|
|
43
|
+
readonly normal: "normal";
|
|
44
|
+
readonly anywhereFrom: "anywhere-from";
|
|
45
|
+
readonly uniform: "uniform";
|
|
46
|
+
readonly anyBetween: "any-between";
|
|
47
|
+
readonly oneOf: "one-of";
|
|
48
|
+
readonly weighted: "weighted";
|
|
49
|
+
readonly choice: "choice";
|
|
50
|
+
};
|
|
51
|
+
export type EstimateType = typeof EstimateTypes[keyof typeof EstimateTypes];
|
|
37
52
|
/**
|
|
38
53
|
* Percent or number value
|
|
39
54
|
* Strings ending in '%' are parsed: '50%' -> 0.50
|