@classytic/stage 0.2.0 → 0.3.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/LICENSE +1 -1
- package/README.md +5 -1
- package/dist/assets/index.mjs +0 -1
- package/dist/builder/Palette.mjs +50 -89
- package/dist/builder/SceneBuilder.mjs +15 -73
- package/dist/core/index.d.mts +2 -1
- package/dist/core/index.mjs +2 -1
- package/dist/core/math.d.mts +26 -0
- package/dist/core/math.mjs +37 -0
- package/dist/finance/bizsim.d.mts +93 -0
- package/dist/finance/bizsim.mjs +117 -0
- package/dist/finance/index.d.mts +118 -0
- package/dist/finance/index.mjs +203 -0
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +4 -4
- package/dist/interaction/MovableDot.mjs +19 -0
- package/dist/interaction/useDraggable.mjs +24 -4
- package/dist/math/calculus.d.mts +22 -1
- package/dist/math/calculus.mjs +156 -2
- package/dist/math/index.d.mts +2 -2
- package/dist/math/index.mjs +2 -2
- package/dist/math/latex.mjs +8 -0
- package/dist/primitives/Dot.d.mts +2 -15
- package/dist/primitives/Dot.mjs +6 -4
- package/dist/primitives/Grid.d.mts +33 -17
- package/dist/primitives/Grid.mjs +89 -17
- package/dist/primitives/Label.d.mts +1 -14
- package/dist/primitives/Label.mjs +3 -2
- package/dist/primitives/Lines.d.mts +4 -32
- package/dist/primitives/Lines.mjs +10 -8
- package/dist/primitives/Shapes.d.mts +5 -43
- package/dist/primitives/Shapes.mjs +12 -10
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/primitives/props.mjs +31 -0
- package/dist/scene/Scene.d.mts +6 -1
- package/dist/scene/Scene.mjs +15 -40
- package/dist/view/Stage.mjs +4 -11
- package/package.json +30 -22
- package/styles.css +125 -8
- package/dist/assets/kit/index.mjs +0 -4
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { BalanceSheet, BizAction, BizState, IncomeStatement, applyBiz, balanceSheet, incomeStatement, initialBiz, runBiz } from "./bizsim.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/finance/index.d.ts
|
|
4
|
+
/** Simple interest I = P·r·t (interest only, not the total). */
|
|
5
|
+
declare function simpleInterest(principal: number, rate: number, years: number): number;
|
|
6
|
+
/** Amount after compound interest, A = P(1 + r/m)^(m·t). */
|
|
7
|
+
declare function compoundAmount(principal: number, rate: number, years: number, m?: number): number;
|
|
8
|
+
/** Compound interest earned (total − principal). */
|
|
9
|
+
declare function compoundInterest(principal: number, rate: number, years: number, m?: number): number;
|
|
10
|
+
/** Future value of a lump sum, FV = P(1+r)^n. */
|
|
11
|
+
declare function futureValue(principal: number, rate: number, n: number): number;
|
|
12
|
+
/** Present value of a future lump sum, PV = FV/(1+r)^n. */
|
|
13
|
+
declare function presentValue(fv: number, rate: number, n: number): number;
|
|
14
|
+
/** Effective annual rate from a nominal rate compounded m times/year. */
|
|
15
|
+
declare function effectiveRate(nominal: number, m: number): number;
|
|
16
|
+
/** Rule of 72: approximate years for money to double at a given annual rate. */
|
|
17
|
+
declare function rule72(rate: number): number;
|
|
18
|
+
/** Yearly simple-vs-compound growth series, for the "money snowball" curve. */
|
|
19
|
+
declare function growthSeries(principal: number, rate: number, years: number): {
|
|
20
|
+
year: number;
|
|
21
|
+
simple: number;
|
|
22
|
+
compound: number;
|
|
23
|
+
}[];
|
|
24
|
+
interface AmortRow {
|
|
25
|
+
period: number;
|
|
26
|
+
interest: number;
|
|
27
|
+
principal: number;
|
|
28
|
+
balance: number;
|
|
29
|
+
}
|
|
30
|
+
interface AmortResult {
|
|
31
|
+
payment: number;
|
|
32
|
+
totalInterest: number;
|
|
33
|
+
schedule: AmortRow[];
|
|
34
|
+
}
|
|
35
|
+
/** Amortize a loan into equal payments; returns the payment, total interest, and per-period schedule. */
|
|
36
|
+
declare function amortize(principal: number, annualRate: number, years: number, m?: number): AmortResult;
|
|
37
|
+
interface DepRow {
|
|
38
|
+
year: number;
|
|
39
|
+
depreciation: number;
|
|
40
|
+
bookValue: number;
|
|
41
|
+
}
|
|
42
|
+
/** Straight-line depreciation: equal charge (cost − residual)/life each year. */
|
|
43
|
+
declare function straightLine(cost: number, residual: number, life: number): {
|
|
44
|
+
perYear: number;
|
|
45
|
+
schedule: DepRow[];
|
|
46
|
+
};
|
|
47
|
+
/** Reducing-balance depreciation: a fixed % of the falling book value each year. */
|
|
48
|
+
declare function reducingBalance(cost: number, rate: number, life: number): DepRow[];
|
|
49
|
+
interface CostModel {
|
|
50
|
+
fixedCost: number;
|
|
51
|
+
price: number;
|
|
52
|
+
variableCost: number;
|
|
53
|
+
}
|
|
54
|
+
interface BreakEven {
|
|
55
|
+
contributionPerUnit: number;
|
|
56
|
+
units: number;
|
|
57
|
+
revenue: number;
|
|
58
|
+
contributionMargin: number;
|
|
59
|
+
}
|
|
60
|
+
/** Break-even: units where contribution covers fixed cost; plus revenue and margin. */
|
|
61
|
+
declare function breakEven({
|
|
62
|
+
fixedCost,
|
|
63
|
+
price,
|
|
64
|
+
variableCost
|
|
65
|
+
}: CostModel): BreakEven;
|
|
66
|
+
/** Profit at a given output: units·(price − variable) − fixed. */
|
|
67
|
+
declare function profitAt(units: number, m: CostModel): number;
|
|
68
|
+
/** Margin of safety = actual output − break-even output (units). */
|
|
69
|
+
declare function marginOfSafety(currentUnits: number, breakEvenUnits: number): number;
|
|
70
|
+
type InvMethod = 'fifo' | 'lifo' | 'avco';
|
|
71
|
+
interface InvMove {
|
|
72
|
+
type: 'buy' | 'sell';
|
|
73
|
+
qty: number;
|
|
74
|
+
unitCost?: number;
|
|
75
|
+
}
|
|
76
|
+
interface InvResult {
|
|
77
|
+
cogs: number;
|
|
78
|
+
closingValue: number;
|
|
79
|
+
closingQty: number;
|
|
80
|
+
}
|
|
81
|
+
/** Value stock and cost of goods sold under FIFO, LIFO or weighted-average (AVCO). */
|
|
82
|
+
declare function inventoryValue(method: InvMethod, moves: InvMove[]): InvResult;
|
|
83
|
+
/** Economic order quantity: √(2·D·S / H) — demand D, order cost S, holding cost/unit H. */
|
|
84
|
+
declare function eoq(annualDemand: number, orderCost: number, holdingCostPerUnit: number): number;
|
|
85
|
+
/** Reorder level = usage during the lead time, plus any buffer (safety) stock. */
|
|
86
|
+
declare function reorderLevel(usagePerDay: number, leadTimeDays: number, bufferStock?: number): number;
|
|
87
|
+
/** Split a total cost across cost-centres in proportion to a basis (floor area sq ft, headcount, machine hours…). */
|
|
88
|
+
declare function apportion(total: number, weights: number[]): number[];
|
|
89
|
+
interface FinInputs {
|
|
90
|
+
currentAssets: number;
|
|
91
|
+
inventory: number;
|
|
92
|
+
currentLiabilities: number;
|
|
93
|
+
nonCurrentLiabilities: number;
|
|
94
|
+
equity: number;
|
|
95
|
+
revenue: number;
|
|
96
|
+
costOfSales: number;
|
|
97
|
+
expenses?: number;
|
|
98
|
+
grossProfit?: number;
|
|
99
|
+
netProfit?: number;
|
|
100
|
+
capitalEmployed?: number;
|
|
101
|
+
}
|
|
102
|
+
interface Ratios {
|
|
103
|
+
current: number;
|
|
104
|
+
quick: number;
|
|
105
|
+
gearing: number;
|
|
106
|
+
grossMargin: number;
|
|
107
|
+
netMargin: number;
|
|
108
|
+
roce: number;
|
|
109
|
+
inventoryTurnover: number;
|
|
110
|
+
}
|
|
111
|
+
/** Standard analysis ratios from summary figures (liquidity, gearing, profitability, efficiency). */
|
|
112
|
+
declare function ratios(f: FinInputs): Ratios;
|
|
113
|
+
/** Net present value; `cashflows[0]` is the initial outlay (usually negative). */
|
|
114
|
+
declare function npv(rate: number, cashflows: number[]): number;
|
|
115
|
+
/** Payback period in years (fractional), from year-0 outlay + yearly inflows. */
|
|
116
|
+
declare function payback(cashflows: number[]): number;
|
|
117
|
+
//#endregion
|
|
118
|
+
export { AmortResult, AmortRow, BalanceSheet, BizAction, BizState, BreakEven, CostModel, DepRow, FinInputs, IncomeStatement, InvMethod, InvMove, InvResult, Ratios, amortize, applyBiz, apportion, balanceSheet, breakEven, compoundAmount, compoundInterest, effectiveRate, eoq, futureValue, growthSeries, incomeStatement, initialBiz, inventoryValue, marginOfSafety, npv, payback, presentValue, profitAt, ratios, reducingBalance, reorderLevel, rule72, runBiz, simpleInterest, straightLine };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { applyBiz, balanceSheet, incomeStatement, initialBiz, runBiz } from "./bizsim.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/finance/index.ts
|
|
4
|
+
/** Simple interest I = P·r·t (interest only, not the total). */
|
|
5
|
+
function simpleInterest(principal, rate, years) {
|
|
6
|
+
return principal * rate * years;
|
|
7
|
+
}
|
|
8
|
+
/** Amount after compound interest, A = P(1 + r/m)^(m·t). */
|
|
9
|
+
function compoundAmount(principal, rate, years, m = 1) {
|
|
10
|
+
return principal * Math.pow(1 + rate / m, m * years);
|
|
11
|
+
}
|
|
12
|
+
/** Compound interest earned (total − principal). */
|
|
13
|
+
function compoundInterest(principal, rate, years, m = 1) {
|
|
14
|
+
return compoundAmount(principal, rate, years, m) - principal;
|
|
15
|
+
}
|
|
16
|
+
/** Future value of a lump sum, FV = P(1+r)^n. */
|
|
17
|
+
function futureValue(principal, rate, n) {
|
|
18
|
+
return principal * Math.pow(1 + rate, n);
|
|
19
|
+
}
|
|
20
|
+
/** Present value of a future lump sum, PV = FV/(1+r)^n. */
|
|
21
|
+
function presentValue(fv, rate, n) {
|
|
22
|
+
return fv / Math.pow(1 + rate, n);
|
|
23
|
+
}
|
|
24
|
+
/** Effective annual rate from a nominal rate compounded m times/year. */
|
|
25
|
+
function effectiveRate(nominal, m) {
|
|
26
|
+
return Math.pow(1 + nominal / m, m) - 1;
|
|
27
|
+
}
|
|
28
|
+
/** Rule of 72: approximate years for money to double at a given annual rate. */
|
|
29
|
+
function rule72(rate) {
|
|
30
|
+
return 72 / (rate * 100);
|
|
31
|
+
}
|
|
32
|
+
/** Yearly simple-vs-compound growth series, for the "money snowball" curve. */
|
|
33
|
+
function growthSeries(principal, rate, years) {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (let y = 0; y <= years; y++) out.push({
|
|
36
|
+
year: y,
|
|
37
|
+
simple: principal * (1 + rate * y),
|
|
38
|
+
compound: principal * Math.pow(1 + rate, y)
|
|
39
|
+
});
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
/** Amortize a loan into equal payments; returns the payment, total interest, and per-period schedule. */
|
|
43
|
+
function amortize(principal, annualRate, years, m = 12) {
|
|
44
|
+
const n = Math.round(years * m), i = annualRate / m;
|
|
45
|
+
const payment = i === 0 ? principal / n : principal * i / (1 - Math.pow(1 + i, -n));
|
|
46
|
+
const schedule = [];
|
|
47
|
+
let bal = principal;
|
|
48
|
+
for (let k = 1; k <= n; k++) {
|
|
49
|
+
const interest = bal * i;
|
|
50
|
+
const princ = payment - interest;
|
|
51
|
+
bal = Math.max(0, bal - princ);
|
|
52
|
+
schedule.push({
|
|
53
|
+
period: k,
|
|
54
|
+
interest,
|
|
55
|
+
principal: princ,
|
|
56
|
+
balance: bal
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
payment,
|
|
61
|
+
totalInterest: payment * n - principal,
|
|
62
|
+
schedule
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** Straight-line depreciation: equal charge (cost − residual)/life each year. */
|
|
66
|
+
function straightLine(cost, residual, life) {
|
|
67
|
+
const perYear = (cost - residual) / life;
|
|
68
|
+
const schedule = [];
|
|
69
|
+
for (let y = 1; y <= life; y++) schedule.push({
|
|
70
|
+
year: y,
|
|
71
|
+
depreciation: perYear,
|
|
72
|
+
bookValue: cost - perYear * y
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
perYear,
|
|
76
|
+
schedule
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Reducing-balance depreciation: a fixed % of the falling book value each year. */
|
|
80
|
+
function reducingBalance(cost, rate, life) {
|
|
81
|
+
const schedule = [];
|
|
82
|
+
let bv = cost;
|
|
83
|
+
for (let y = 1; y <= life; y++) {
|
|
84
|
+
const dep = bv * rate;
|
|
85
|
+
bv -= dep;
|
|
86
|
+
schedule.push({
|
|
87
|
+
year: y,
|
|
88
|
+
depreciation: dep,
|
|
89
|
+
bookValue: bv
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return schedule;
|
|
93
|
+
}
|
|
94
|
+
/** Break-even: units where contribution covers fixed cost; plus revenue and margin. */
|
|
95
|
+
function breakEven({ fixedCost, price, variableCost }) {
|
|
96
|
+
const contributionPerUnit = price - variableCost;
|
|
97
|
+
const units = contributionPerUnit > 0 ? fixedCost / contributionPerUnit : Infinity;
|
|
98
|
+
return {
|
|
99
|
+
contributionPerUnit,
|
|
100
|
+
units,
|
|
101
|
+
revenue: units * price,
|
|
102
|
+
contributionMargin: price > 0 ? contributionPerUnit / price : 0
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** Profit at a given output: units·(price − variable) − fixed. */
|
|
106
|
+
function profitAt(units, m) {
|
|
107
|
+
return units * (m.price - m.variableCost) - m.fixedCost;
|
|
108
|
+
}
|
|
109
|
+
/** Margin of safety = actual output − break-even output (units). */
|
|
110
|
+
function marginOfSafety(currentUnits, breakEvenUnits) {
|
|
111
|
+
return currentUnits - breakEvenUnits;
|
|
112
|
+
}
|
|
113
|
+
/** Value stock and cost of goods sold under FIFO, LIFO or weighted-average (AVCO). */
|
|
114
|
+
function inventoryValue(method, moves) {
|
|
115
|
+
let cogs = 0;
|
|
116
|
+
if (method === "avco") {
|
|
117
|
+
let qty = 0, val = 0;
|
|
118
|
+
for (const m of moves) if (m.type === "buy") {
|
|
119
|
+
qty += m.qty;
|
|
120
|
+
val += m.qty * (m.unitCost ?? 0);
|
|
121
|
+
} else {
|
|
122
|
+
const avg = qty > 0 ? val / qty : 0;
|
|
123
|
+
cogs += m.qty * avg;
|
|
124
|
+
val -= m.qty * avg;
|
|
125
|
+
qty -= m.qty;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
cogs,
|
|
129
|
+
closingValue: val,
|
|
130
|
+
closingQty: qty
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const lots = [];
|
|
134
|
+
for (const m of moves) {
|
|
135
|
+
if (m.type === "buy") {
|
|
136
|
+
lots.push({
|
|
137
|
+
qty: m.qty,
|
|
138
|
+
cost: m.unitCost ?? 0
|
|
139
|
+
});
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
let need = m.qty;
|
|
143
|
+
while (need > 0 && lots.length) {
|
|
144
|
+
const idx = method === "fifo" ? 0 : lots.length - 1;
|
|
145
|
+
const lot = lots[idx];
|
|
146
|
+
const take = Math.min(need, lot.qty);
|
|
147
|
+
cogs += take * lot.cost;
|
|
148
|
+
lot.qty -= take;
|
|
149
|
+
need -= take;
|
|
150
|
+
if (lot.qty === 0) lots.splice(idx, 1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
cogs,
|
|
155
|
+
closingValue: lots.reduce((a, l) => a + l.qty * l.cost, 0),
|
|
156
|
+
closingQty: lots.reduce((a, l) => a + l.qty, 0)
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/** Economic order quantity: √(2·D·S / H) — demand D, order cost S, holding cost/unit H. */
|
|
160
|
+
function eoq(annualDemand, orderCost, holdingCostPerUnit) {
|
|
161
|
+
return holdingCostPerUnit > 0 ? Math.sqrt(2 * annualDemand * orderCost / holdingCostPerUnit) : Infinity;
|
|
162
|
+
}
|
|
163
|
+
/** Reorder level = usage during the lead time, plus any buffer (safety) stock. */
|
|
164
|
+
function reorderLevel(usagePerDay, leadTimeDays, bufferStock = 0) {
|
|
165
|
+
return usagePerDay * leadTimeDays + bufferStock;
|
|
166
|
+
}
|
|
167
|
+
/** Split a total cost across cost-centres in proportion to a basis (floor area sq ft, headcount, machine hours…). */
|
|
168
|
+
function apportion(total, weights) {
|
|
169
|
+
const sum = weights.reduce((a, b) => a + b, 0) || 1;
|
|
170
|
+
return weights.map((w) => total * w / sum);
|
|
171
|
+
}
|
|
172
|
+
/** Standard analysis ratios from summary figures (liquidity, gearing, profitability, efficiency). */
|
|
173
|
+
function ratios(f) {
|
|
174
|
+
const grossProfit = f.grossProfit ?? f.revenue - f.costOfSales;
|
|
175
|
+
const netProfit = f.netProfit ?? grossProfit - (f.expenses ?? 0);
|
|
176
|
+
const capEmp = f.capitalEmployed ?? f.equity + f.nonCurrentLiabilities;
|
|
177
|
+
return {
|
|
178
|
+
current: f.currentAssets / f.currentLiabilities,
|
|
179
|
+
quick: (f.currentAssets - f.inventory) / f.currentLiabilities,
|
|
180
|
+
gearing: f.nonCurrentLiabilities / (f.equity + f.nonCurrentLiabilities),
|
|
181
|
+
grossMargin: grossProfit / f.revenue,
|
|
182
|
+
netMargin: netProfit / f.revenue,
|
|
183
|
+
roce: netProfit / capEmp,
|
|
184
|
+
inventoryTurnover: f.costOfSales / f.inventory
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/** Net present value; `cashflows[0]` is the initial outlay (usually negative). */
|
|
188
|
+
function npv(rate, cashflows) {
|
|
189
|
+
return cashflows.reduce((a, cf, t) => a + cf / Math.pow(1 + rate, t), 0);
|
|
190
|
+
}
|
|
191
|
+
/** Payback period in years (fractional), from year-0 outlay + yearly inflows. */
|
|
192
|
+
function payback(cashflows) {
|
|
193
|
+
let cum = 0;
|
|
194
|
+
for (let t = 0; t < cashflows.length; t++) {
|
|
195
|
+
const prev = cum;
|
|
196
|
+
cum += cashflows[t];
|
|
197
|
+
if (cum >= 0 && t > 0) return t - 1 + -prev / cashflows[t];
|
|
198
|
+
}
|
|
199
|
+
return Infinity;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//#endregion
|
|
203
|
+
export { amortize, applyBiz, apportion, balanceSheet, breakEven, compoundAmount, compoundInterest, effectiveRate, eoq, futureValue, growthSeries, incomeStatement, initialBiz, inventoryValue, marginOfSafety, npv, payback, presentValue, profitAt, ratios, reducingBalance, reorderLevel, rule72, runBiz, simpleInterest, straightLine };
|
package/dist/index.d.mts
CHANGED
|
@@ -15,6 +15,7 @@ import { Palette, PaletteProps } from "./builder/Palette.mjs";
|
|
|
15
15
|
import { CoordsContext, DragOverlayContext, StageRefContext, useCoords, useDragOverlay, useStageRef } from "./core/context.mjs";
|
|
16
16
|
import { ClockProvider, ClockProviderProps, FrameDriver, FrameInfo, useFrameLoop } from "./core/clock.mjs";
|
|
17
17
|
import { Learner, LearnerProvider, LearnerResult, PriorAttempts, useLearner } from "./core/learner.mjs";
|
|
18
|
+
import { approxEq, clamp, clamp01, gcd, remap, round, snapTo, toDeg, toRad } from "./core/math.mjs";
|
|
18
19
|
import { RichSpan, Script, parseRichText } from "./core/richText.mjs";
|
|
19
20
|
import { StepProgress, StepProgressProvider, StepScope, StepSpec, StepState, useStepProgress } from "./steps/index.mjs";
|
|
20
21
|
import { Stage, StageProps } from "./view/Stage.mjs";
|
|
@@ -26,7 +27,7 @@ import { Line, LineProps, Ray, Segment, SegmentProps, Vector, VectorProps } from
|
|
|
26
27
|
import { Circle, CircleProps, Ellipse, EllipseProps, Path, PathProps, Polygon, PolygonProps, Polyline, PolylineProps } from "./primitives/Shapes.mjs";
|
|
27
28
|
import { Label, LabelProps } from "./primitives/Label.mjs";
|
|
28
29
|
import { Tex, TexProps } from "./primitives/Tex.mjs";
|
|
29
|
-
import { Axes, AxesProps, Grid, GridProps, niceStep } from "./primitives/Grid.mjs";
|
|
30
|
+
import { Axes, AxesProps, ClearZone, Grid, GridProps, clearOfLabel, niceStep } from "./primitives/Grid.mjs";
|
|
30
31
|
import { OfXProps, OfYProps, ParametricProps, Plot } from "./primitives/Plot.mjs";
|
|
31
32
|
import { CanvasLayer, CanvasLayerProps } from "./primitives/CanvasLayer.mjs";
|
|
32
33
|
import { useScreenToMath } from "./interaction/useScreenToMath.mjs";
|
|
@@ -42,7 +43,7 @@ import { Scene, SceneProps } from "./scene/Scene.mjs";
|
|
|
42
43
|
import { RenderOpts, renderElements } from "./scene/render.mjs";
|
|
43
44
|
import { BinOp, Node, compileNode, evaluate, freeVars } from "./math/ast.mjs";
|
|
44
45
|
import { parse as parse$1 } from "./math/parse.mjs";
|
|
45
|
-
import { differentiate, simplify } from "./math/calculus.mjs";
|
|
46
|
+
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
46
47
|
import { CompiledFn, compile } from "./math/compile.mjs";
|
|
47
48
|
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
48
49
|
import { CompiledExpr, ExprError, ExprResult, compileExpr } from "./math/index.mjs";
|
|
@@ -53,4 +54,4 @@ import { toLatex } from "./logic/latex.mjs";
|
|
|
53
54
|
import { Cube, Minimization, cubeCovers, cubeOfSelection, cubeTerm, minimalCover, minimize, primeImplicants } from "./logic/minimize.mjs";
|
|
54
55
|
import { CompiledLogic, LogicResult, compileLogic } from "./logic/index.mjs";
|
|
55
56
|
import { AssetResolveArgs, AssetSpec, assetMeta, getAsset, listAssets, registerAsset } from "./scene/assets.mjs";
|
|
56
|
-
export { type A11yProps, AUTHORING_TOOLS, type AriaSliderProps, type AssetGeometry, type AssetResolveArgs, type AssetSpec, Axes, type AxesProps, type BinOp, type Binding, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, type CanvasLayerProps, Circle, type CircleProps, type CircleVal, type Classification, ClockProvider, type ClockProviderProps, type Command, type CommandResult, type CompiledExpr, type CompiledFn, type CompiledLogic, type Constrain, type ControlMap, type ControlPick, type ControlSpec, type ControlSurface, type CoordinateSystem, CoordsContext, type CoordsOptions, type Cube, DELETE, type DerivedDef, type DerivedElement, type DerivedKind, type DispatchOpts, Dot, type DotProps, DragOverlayContext, type DraggableHandlers, EVALUATORS, Editor, type ElementBase, type ElementStyle, Ellipse, type EllipseProps, type EvalCtx, type ExprError, type ExprResult, type FrameDriver, type FrameInfo, type FreeElement, type FreeNote, type FreePoint, type FreeScalar, GEOMETRY_TOOLS, type GlyphBox, Grid, type GridProps, HangerHook, type HangerHookProps, type HitCandidate, INTERSECT, type IconName, type Id, type InstanceState, LINE, type LNode, type LabMeta, Label, type LabelProps, type Learner, LearnerProvider, type LearnerResult, Line, type LineProps, type BinOp$1 as LogicBinOp, type LogicResult, MEASURE, MIDPOINT, type Matrix, type Minimization, MovableDot, type MovableDotProps, type MutatePatch, NOTE, type Node, type NumOrRef, OP_REFS, type OfXProps, type OfYProps, type Op, POINT, Palette, type PaletteProps, type ParametricProps, Path, type PathProps, Plot, Point, Polygon, type PolygonProps, Polyline, type PolylineProps, type PressSpringOpts, type PriorAttempts, Ray, type Ref, type RenderOpts, type Resolved, type RichSpan, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, type SceneBuilderProps, type SceneDoc, type SceneElement, type SceneMeta, type SceneProps, SceneStore, type Vec2 as SceneVec2, type Script, Segment, type SegmentProps, type ShapeLineVal, type Size, Stage, StageAssetDefs, type StageProps, StageRefContext, type StepProgress, StepProgressProvider, StepScope, type StepSpec, type StepState, type StyleProps, Tex, type TexProps, type Tool, type ToolCtx, ToolIcon, type TruthRow, type TruthTable, type UseDraggable, type UseDraggableArgs, type Val, type Vec2, Vector, type VectorProps, type ViewBox, WeightGlyph, XBlockGlyph, applyCommand, assetMeta, classify, collectRemoved, compile, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, getAsset, getControlSurface, hitTest, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, renderElements, resolve, serialize, simplify, toCNF, toDNF, toLatex$1 as toLatex, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useImpulse, useInView, useLearner, usePressSpring, useScreenToMath, useStageRef, useStepProgress, vec };
|
|
57
|
+
export { type A11yProps, AUTHORING_TOOLS, type AriaSliderProps, type AssetGeometry, type AssetResolveArgs, type AssetSpec, Axes, type AxesProps, type BinOp, type Binding, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, type CanvasLayerProps, Circle, type CircleProps, type CircleVal, type Classification, type ClearZone, ClockProvider, type ClockProviderProps, type Command, type CommandResult, type CompiledExpr, type CompiledFn, type CompiledLogic, type Constrain, type ControlMap, type ControlPick, type ControlSpec, type ControlSurface, type CoordinateSystem, CoordsContext, type CoordsOptions, type Cube, DELETE, type DerivedDef, type DerivedElement, type DerivedKind, type DispatchOpts, Dot, type DotProps, DragOverlayContext, type DraggableHandlers, EVALUATORS, Editor, type ElementBase, type ElementStyle, Ellipse, type EllipseProps, type EvalCtx, type ExprError, type ExprResult, type FrameDriver, type FrameInfo, type FreeElement, type FreeNote, type FreePoint, type FreeScalar, GEOMETRY_TOOLS, type GlyphBox, Grid, type GridProps, HangerHook, type HangerHookProps, type HitCandidate, INTERSECT, type IconName, type Id, type InstanceState, LINE, type LNode, type LabMeta, Label, type LabelProps, type Learner, LearnerProvider, type LearnerResult, Line, type LineProps, type BinOp$1 as LogicBinOp, type LogicResult, MEASURE, MIDPOINT, type Matrix, type Minimization, MovableDot, type MovableDotProps, type MutatePatch, NOTE, type Node, type NumOrRef, OP_REFS, type OfXProps, type OfYProps, type Op, POINT, Palette, type PaletteProps, type ParametricProps, Path, type PathProps, Plot, Point, Polygon, type PolygonProps, Polyline, type PolylineProps, type PressSpringOpts, type PriorAttempts, Ray, type Ref, type RenderOpts, type Resolved, type RichSpan, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, type SceneBuilderProps, type SceneDoc, type SceneElement, type SceneMeta, type SceneProps, SceneStore, type Vec2 as SceneVec2, type Script, Segment, type SegmentProps, type ShapeLineVal, type Size, Stage, StageAssetDefs, type StageProps, StageRefContext, type StepProgress, StepProgressProvider, StepScope, type StepSpec, type StepState, type StyleProps, Tex, type TexProps, type Tool, type ToolCtx, ToolIcon, type TruthRow, type TruthTable, type UseDraggable, type UseDraggableArgs, type Val, type Vec2, Vector, type VectorProps, type ViewBox, WeightGlyph, XBlockGlyph, applyCommand, approxEq, assetMeta, clamp, clamp01, classify, clearOfLabel, collectRemoved, compile, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, definiteIntegral, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, gcd, getAsset, getControlSurface, hitTest, integrate, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, remap, renderElements, resolve, round, serialize, simplify, snapTo, toCNF, toDNF, toDeg, toLatex$1 as toLatex, toRad, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useImpulse, useInView, useLearner, usePressSpring, useScreenToMath, useStageRef, useStepProgress, vec };
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { CoordsContext, DragOverlayContext, StageRefContext, useCoords, useDragO
|
|
|
5
5
|
import { ClockProvider, useFrameLoop } from "./core/clock.mjs";
|
|
6
6
|
import { getControlSurface, listControlSurfaces, onControlChange, useControlSurface } from "./core/control.mjs";
|
|
7
7
|
import { LearnerProvider, useLearner } from "./core/learner.mjs";
|
|
8
|
+
import { approxEq, clamp, clamp01, gcd, remap, round, snapTo, toDeg, toRad } from "./core/math.mjs";
|
|
8
9
|
import { StepProgressProvider, StepScope, useStepProgress } from "./steps/index.mjs";
|
|
9
10
|
import { useElementSize } from "./view/useElementSize.mjs";
|
|
10
11
|
import { Stage } from "./view/Stage.mjs";
|
|
@@ -14,7 +15,7 @@ import { Line, Ray, Segment, Vector } from "./primitives/Lines.mjs";
|
|
|
14
15
|
import { Circle, Ellipse, Path, Polygon, Polyline } from "./primitives/Shapes.mjs";
|
|
15
16
|
import { Label } from "./primitives/Label.mjs";
|
|
16
17
|
import { Tex } from "./primitives/Tex.mjs";
|
|
17
|
-
import { Axes, Grid, niceStep } from "./primitives/Grid.mjs";
|
|
18
|
+
import { Axes, Grid, clearOfLabel, niceStep } from "./primitives/Grid.mjs";
|
|
18
19
|
import { Plot } from "./primitives/Plot.mjs";
|
|
19
20
|
import { CanvasLayer } from "./primitives/CanvasLayer.mjs";
|
|
20
21
|
import { useScreenToMath } from "./interaction/useScreenToMath.mjs";
|
|
@@ -27,7 +28,7 @@ import { OP_REFS, isRef, parentIds } from "./scene/schema.mjs";
|
|
|
27
28
|
import { assetMeta, getAsset, listAssets, registerAsset } from "./scene/assets.mjs";
|
|
28
29
|
import { compileNode, evaluate, freeVars } from "./math/ast.mjs";
|
|
29
30
|
import { parse as parse$1 } from "./math/parse.mjs";
|
|
30
|
-
import { differentiate, simplify } from "./math/calculus.mjs";
|
|
31
|
+
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
31
32
|
import { compile } from "./math/compile.mjs";
|
|
32
33
|
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
33
34
|
import { compileExpr } from "./math/index.mjs";
|
|
@@ -46,7 +47,6 @@ import { AUTHORING_TOOLS, CIRCLE, DELETE, GEOMETRY_TOOLS, INTERSECT, LINE, MEASU
|
|
|
46
47
|
import { SceneBuilder } from "./builder/SceneBuilder.mjs";
|
|
47
48
|
import { StageAssetDefs } from "./assets/kit/svg-defs.mjs";
|
|
48
49
|
import { BucketGlyph, HangerHook, WeightGlyph, XBlockGlyph } from "./assets/kit/glyphs.mjs";
|
|
49
|
-
import "./assets/kit/index.mjs";
|
|
50
50
|
import { evalBool, freeVars as freeVars$1 } from "./logic/ast.mjs";
|
|
51
51
|
import { parseLogic } from "./logic/parse.mjs";
|
|
52
52
|
import { classify, equivalent, toCNF, toDNF, truthTable } from "./logic/table.mjs";
|
|
@@ -54,4 +54,4 @@ import { toLatex } from "./logic/latex.mjs";
|
|
|
54
54
|
import { cubeCovers, cubeOfSelection, cubeTerm, minimalCover, minimize, primeImplicants } from "./logic/minimize.mjs";
|
|
55
55
|
import { compileLogic } from "./logic/index.mjs";
|
|
56
56
|
|
|
57
|
-
export { AUTHORING_TOOLS, Axes, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, Circle, ClockProvider, CoordsContext, DELETE, Dot, DragOverlayContext, EVALUATORS, Editor, Ellipse, GEOMETRY_TOOLS, Grid, HangerHook, INTERSECT, LINE, Label, LearnerProvider, Line, MEASURE, MIDPOINT, MovableDot, NOTE, OP_REFS, POINT, Palette, Path, Plot, Point, Polygon, Polyline, Ray, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, SceneStore, Segment, Stage, StageAssetDefs, StageRefContext, StepProgressProvider, StepScope, Tex, ToolIcon, Vector, WeightGlyph, XBlockGlyph, applyCommand, assetMeta, classify, collectRemoved, compile, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, getAsset, getControlSurface, hitTest, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, renderElements, resolve, serialize, simplify, toCNF, toDNF, toLatex$1 as toLatex, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useImpulse, useInView, useLearner, usePressSpring, useScreenToMath, useStageRef, useStepProgress, vec };
|
|
57
|
+
export { AUTHORING_TOOLS, Axes, BucketGlyph, CIRCLE, CURRENT_SCHEMA_VERSION, CanvasLayer, Circle, ClockProvider, CoordsContext, DELETE, Dot, DragOverlayContext, EVALUATORS, Editor, Ellipse, GEOMETRY_TOOLS, Grid, HangerHook, INTERSECT, LINE, Label, LearnerProvider, Line, MEASURE, MIDPOINT, MovableDot, NOTE, OP_REFS, POINT, Palette, Path, Plot, Point, Polygon, Polyline, Ray, SCALAR, SEGMENT, SELECT, Scene, SceneBuilder, SceneStore, Segment, Stage, StageAssetDefs, StageRefContext, StepProgressProvider, StepScope, Tex, ToolIcon, Vector, WeightGlyph, XBlockGlyph, applyCommand, approxEq, assetMeta, clamp, clamp01, classify, clearOfLabel, collectRemoved, compile, compileExpr, compileLogic, compileNode, controlsFromScene, createCoords, cubeCovers, cubeOfSelection, cubeTerm, definiteIntegral, differentiate, emptyDoc, equivalent, evalBool, evaluate, fmt, freeVars, gcd, getAsset, getControlSurface, hitTest, integrate, inverse, isAssetGeom, isCircleVal, isDerived, isFree, isLineVal, isRef, isVec2, listAssets, listControlSurfaces, freeVars$1 as logicFreeVars, toLatex as logicToLatex, mat, migrate, minimalCover, minimize, niceStep, numOf, onControlChange, parentIds, parse, parse$1 as parseExpr, parseLogic, parseRichText, primeImplicants, registerAsset, remap, renderElements, resolve, round, serialize, simplify, snapTo, toCNF, toDNF, toDeg, toLatex$1 as toLatex, toRad, truthTable, useControlSurface, useCoords, useDragOverlay, useDraggable, useEditor, useElementSize, useFrameLoop, useImpulse, useInView, useLearner, usePressSpring, useScreenToMath, useStageRef, useStepProgress, vec };
|
|
@@ -56,6 +56,7 @@ function MovableDot({ value, onMove, constrain, color = ACCENT, r = 7, ariaLabel
|
|
|
56
56
|
...step !== void 0 ? { step } : {}
|
|
57
57
|
});
|
|
58
58
|
const [hovered, setHovered] = useState(false);
|
|
59
|
+
const [interacted, setInteracted] = useState(false);
|
|
59
60
|
const press = usePressSpring(dragging, {
|
|
60
61
|
to: 1,
|
|
61
62
|
stiffness: 360,
|
|
@@ -87,6 +88,14 @@ function MovableDot({ value, onMove, constrain, color = ACCENT, r = 7, ariaLabel
|
|
|
87
88
|
...handlers,
|
|
88
89
|
...ariaProps,
|
|
89
90
|
"aria-label": ariaLabel,
|
|
91
|
+
onPointerDown: (e) => {
|
|
92
|
+
setInteracted(true);
|
|
93
|
+
handlers.onPointerDown(e);
|
|
94
|
+
},
|
|
95
|
+
onKeyDown: (e) => {
|
|
96
|
+
setInteracted(true);
|
|
97
|
+
handlers.onKeyDown(e);
|
|
98
|
+
},
|
|
90
99
|
onPointerEnter: () => setHovered(true),
|
|
91
100
|
onPointerLeave: () => setHovered(false),
|
|
92
101
|
style: {
|
|
@@ -100,6 +109,16 @@ function MovableDot({ value, onMove, constrain, color = ACCENT, r = 7, ariaLabel
|
|
|
100
109
|
r: Math.max(r + 14, 12),
|
|
101
110
|
fill: "transparent"
|
|
102
111
|
}),
|
|
112
|
+
!interacted && !dragging && /* @__PURE__ */ jsx("circle", {
|
|
113
|
+
className: "stage-nudge",
|
|
114
|
+
cx: px,
|
|
115
|
+
cy: py,
|
|
116
|
+
r: r + 5,
|
|
117
|
+
fill: "none",
|
|
118
|
+
stroke: color,
|
|
119
|
+
strokeWidth: 1.5,
|
|
120
|
+
style: { pointerEvents: "none" }
|
|
121
|
+
}),
|
|
103
122
|
dragging ? /* @__PURE__ */ jsx("circle", {
|
|
104
123
|
cx: px,
|
|
105
124
|
cy: py,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useScreenToMath } from "./useScreenToMath.mjs";
|
|
4
|
-
import { useCallback, useRef, useState } from "react";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
5
|
|
|
6
6
|
//#region src/interaction/useDraggable.ts
|
|
7
7
|
function constrained(p, start, constrain) {
|
|
@@ -20,6 +20,20 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
20
20
|
const toMath = useScreenToMath();
|
|
21
21
|
const [dragging, setDragging] = useState(false);
|
|
22
22
|
const startRef = useRef(value);
|
|
23
|
+
const onMoveRef = useRef(onMove);
|
|
24
|
+
onMoveRef.current = onMove;
|
|
25
|
+
const pendingRef = useRef(null);
|
|
26
|
+
const rafRef = useRef(0);
|
|
27
|
+
const flushMove = useCallback(() => {
|
|
28
|
+
rafRef.current = 0;
|
|
29
|
+
const p = pendingRef.current;
|
|
30
|
+
if (!p) return;
|
|
31
|
+
pendingRef.current = null;
|
|
32
|
+
onMoveRef.current(p, "move");
|
|
33
|
+
}, []);
|
|
34
|
+
useEffect(() => () => {
|
|
35
|
+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
36
|
+
}, []);
|
|
23
37
|
const onPointerDown = useCallback((e) => {
|
|
24
38
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
25
39
|
startRef.current = value;
|
|
@@ -30,19 +44,25 @@ function useDraggable({ value, onMove, constrain, step = .5, range }) {
|
|
|
30
44
|
if (!dragging) return;
|
|
31
45
|
const m = toMath(e);
|
|
32
46
|
if (!m) return;
|
|
33
|
-
|
|
47
|
+
pendingRef.current = constrained({
|
|
34
48
|
x: m[0],
|
|
35
49
|
y: m[1]
|
|
36
|
-
}, startRef.current, constrain)
|
|
50
|
+
}, startRef.current, constrain);
|
|
51
|
+
if (!rafRef.current) rafRef.current = requestAnimationFrame(flushMove);
|
|
37
52
|
}, [
|
|
38
53
|
dragging,
|
|
39
54
|
toMath,
|
|
40
55
|
constrain,
|
|
41
|
-
|
|
56
|
+
flushMove
|
|
42
57
|
]);
|
|
43
58
|
const onPointerUp = useCallback((e) => {
|
|
44
59
|
if (!dragging) return;
|
|
45
60
|
setDragging(false);
|
|
61
|
+
if (rafRef.current) {
|
|
62
|
+
cancelAnimationFrame(rafRef.current);
|
|
63
|
+
rafRef.current = 0;
|
|
64
|
+
}
|
|
65
|
+
pendingRef.current = null;
|
|
46
66
|
const m = toMath(e);
|
|
47
67
|
onMove(m ? constrained({
|
|
48
68
|
x: m[0],
|
package/dist/math/calculus.d.mts
CHANGED
|
@@ -3,7 +3,28 @@ import { Node } from "./ast.mjs";
|
|
|
3
3
|
//#region src/math/calculus.d.ts
|
|
4
4
|
/** Exact symbolic derivative, or `null` if a non-differentiable node is present. */
|
|
5
5
|
declare function differentiate(node: Node, x: string): Node | null;
|
|
6
|
+
/**
|
|
7
|
+
* Exact symbolic antiderivative with respect to `x`, or `null` when this engine cannot do it.
|
|
8
|
+
*
|
|
9
|
+
* The constant of integration is NOT included. That is deliberate: `+ c` is the single most
|
|
10
|
+
* commonly dropped mark in the topic, so it belongs in the lesson's own working where a learner
|
|
11
|
+
* has to write it, not silently bolted on by the engine.
|
|
12
|
+
*
|
|
13
|
+
* Covers the Cambridge P1/P3 toolkit: linearity, the power rule including the `1/x → ln|x|`
|
|
14
|
+
* exception, and any of the above composed with a LINEAR inner function. Returns null for
|
|
15
|
+
* integration by parts, by non-linear substitution, and partial fractions, so a caller can fall
|
|
16
|
+
* back to the numerical `integrate` in `core/numeric` and show area rather than a wrong formula.
|
|
17
|
+
*/
|
|
18
|
+
declare function integrate(node: Node, x: string): Node | null;
|
|
19
|
+
/**
|
|
20
|
+
* A definite integral evaluated exactly: `F(b) - F(a)`.
|
|
21
|
+
*
|
|
22
|
+
* Returned as a NUMBER rather than a node, because that is what a lesson compares a learner's
|
|
23
|
+
* answer against. Null when the antiderivative is not elementary, or when either limit lands
|
|
24
|
+
* somewhere the expression is not defined.
|
|
25
|
+
*/
|
|
26
|
+
declare function definiteIntegral(node: Node, x: string, lower: number, upper: number): number | null;
|
|
6
27
|
/** Fold constants and trivial identities so derivative output is readable. */
|
|
7
28
|
declare function simplify(node: Node): Node;
|
|
8
29
|
//#endregion
|
|
9
|
-
export { differentiate, simplify };
|
|
30
|
+
export { definiteIntegral, differentiate, integrate, simplify };
|