-
Notifications
You must be signed in to change notification settings - Fork 222
/
Copy pathindex.ts
98 lines (79 loc) · 2.16 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import DATA from "./data";
type Fraction = [number, number];
const VALUES: DurationValue[] = [];
DATA.forEach(([denominator, shorthand, names]) =>
add(denominator, shorthand, names),
);
export interface DurationValue {
empty: boolean;
value: number;
name: string;
fraction: Fraction;
shorthand: string;
dots: string;
names: string[];
}
const NoDuration: DurationValue = {
empty: true,
name: "",
value: 0,
fraction: [0, 0],
shorthand: "",
dots: "",
names: [],
};
export function names(): string[] {
return VALUES.reduce((names, duration) => {
duration.names.forEach((name) => names.push(name));
return names;
}, [] as string[]);
}
export function shorthands(): string[] {
return VALUES.map((dur) => dur.shorthand);
}
const REGEX = /^([^.]+)(\.*)$/;
export function get(name: string): DurationValue {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, simple, dots] = REGEX.exec(name) || [];
const base = VALUES.find(
(dur) => dur.shorthand === simple || dur.names.includes(simple),
);
if (!base) {
return NoDuration;
}
const fraction = calcDots(base.fraction, dots.length);
const value = fraction[0] / fraction[1];
return { ...base, name, dots, value, fraction };
}
export const value = (name: string) => get(name).value;
export const fraction = (name: string) => get(name).fraction;
/** @deprecated */
export default { names, shorthands, get, value, fraction };
//// PRIVATE ////
function add(denominator: number, shorthand: string, names: string[]) {
VALUES.push({
empty: false,
dots: "",
name: "",
value: 1 / denominator,
fraction: denominator < 1 ? [1 / denominator, 1] : [1, denominator],
shorthand,
names,
});
}
function calcDots(fraction: Fraction, dots: number): Fraction {
const pow = Math.pow(2, dots);
let numerator = fraction[0] * pow;
let denominator = fraction[1] * pow;
const base = numerator;
// add fractions
for (let i = 0; i < dots; i++) {
numerator += base / Math.pow(2, i + 1);
}
// simplify
while (numerator % 2 === 0 && denominator % 2 === 0) {
numerator /= 2;
denominator /= 2;
}
return [numerator, denominator];
}