@bgord/tools 0.17.2 → 1.0.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/dist/age-years.vo.d.ts +11 -0
- package/dist/age-years.vo.js +9 -0
- package/dist/age.vo.d.ts +11 -16
- package/dist/age.vo.js +20 -31
- package/dist/api-key.vo.d.ts +3 -1
- package/dist/api-key.vo.js +10 -5
- package/dist/basename.vo.d.ts +9 -9
- package/dist/basename.vo.js +22 -22
- package/dist/clock.vo.d.ts +10 -4
- package/dist/clock.vo.js +12 -14
- package/dist/date-calculator.service.d.ts +2 -1
- package/dist/date-formatter.service.d.ts +3 -4
- package/dist/date-range.vo.d.ts +7 -1
- package/dist/date-range.vo.js +5 -2
- package/dist/day-iso-id.vo.d.ts +5 -2
- package/dist/day-iso-id.vo.js +11 -7
- package/dist/day.vo.d.ts +4 -3
- package/dist/day.vo.js +18 -16
- package/dist/directory-path-absolute.vo.d.ts +10 -6
- package/dist/directory-path-absolute.vo.js +19 -17
- package/dist/directory-path-relative.vo.d.ts +10 -7
- package/dist/directory-path-relative.vo.js +18 -17
- package/dist/division-factor.vo.d.ts +7 -0
- package/dist/division-factor.vo.js +9 -0
- package/dist/duration-ms.vo.d.ts +6 -0
- package/dist/duration-ms.vo.js +3 -0
- package/dist/duration.service.d.ts +2 -14
- package/dist/duration.service.js +16 -35
- package/dist/email-mask.service.d.ts +1 -6
- package/dist/email-mask.service.js +6 -8
- package/dist/etags.vo.d.ts +4 -3
- package/dist/etags.vo.js +3 -3
- package/dist/extension.vo.d.ts +6 -4
- package/dist/extension.vo.js +15 -10
- package/dist/feature-flag-value.vo.d.ts +10 -0
- package/dist/feature-flag-value.vo.js +8 -0
- package/dist/feature-flag.vo.d.ts +1 -7
- package/dist/feature-flag.vo.js +1 -7
- package/dist/file-path-absolute-schema.vo.d.ts +10 -7
- package/dist/file-path-absolute-schema.vo.js +17 -17
- package/dist/file-path-relative-schema.vo.d.ts +10 -7
- package/dist/file-path-relative-schema.vo.js +14 -12
- package/dist/file-path.vo.d.ts +4 -4
- package/dist/file-path.vo.js +8 -8
- package/dist/filename-from-string.vo.d.ts +4 -2
- package/dist/filename-from-string.vo.js +10 -8
- package/dist/filename-suffix.vo.d.ts +7 -3
- package/dist/filename-suffix.vo.js +13 -7
- package/dist/filename.vo.d.ts +2 -0
- package/dist/filename.vo.js +8 -2
- package/dist/height-milimiters.vo.d.ts +6 -0
- package/dist/height-milimiters.vo.js +10 -0
- package/dist/height.vo.d.ts +3 -20
- package/dist/height.vo.js +11 -62
- package/dist/hour-format.service.js +1 -1
- package/dist/hour-schema.vo.d.ts +7 -0
- package/dist/hour-schema.vo.js +8 -0
- package/dist/hour.vo.d.ts +4 -3
- package/dist/hour.vo.js +8 -8
- package/dist/iban-mask.service.d.ts +1 -3
- package/dist/iban-mask.service.js +2 -2
- package/dist/iban-schema.vo.d.ts +7 -0
- package/dist/iban-schema.vo.js +10 -0
- package/dist/iban.vo.d.ts +4 -10
- package/dist/iban.vo.js +6 -13
- package/dist/image.vo.d.ts +6 -4
- package/dist/image.vo.js +13 -12
- package/dist/index.d.ts +24 -2
- package/dist/index.js +24 -2
- package/dist/language.vo.d.ts +2 -1
- package/dist/language.vo.js +6 -4
- package/dist/linear-regression.service.d.ts +27 -0
- package/dist/{simple-linear-regression.service.js → linear-regression.service.js} +17 -15
- package/dist/mean.service.d.ts +3 -1
- package/dist/mean.service.js +3 -4
- package/dist/mime-types.vo.d.ts +1 -2
- package/dist/mime-value.vo.d.ts +9 -0
- package/dist/mime-value.vo.js +9 -0
- package/dist/mime.vo.d.ts +11 -17
- package/dist/mime.vo.js +10 -27
- package/dist/min-max-scaler.service.d.ts +7 -5
- package/dist/min-max-scaler.service.js +12 -10
- package/dist/minute-schema.vo.d.ts +7 -0
- package/dist/minute-schema.vo.js +8 -0
- package/dist/minute.vo.d.ts +4 -3
- package/dist/minute.vo.js +8 -8
- package/dist/money-amount.vo.d.ts +7 -0
- package/dist/money-amount.vo.js +7 -0
- package/dist/money.vo.d.ts +9 -18
- package/dist/money.vo.js +14 -27
- package/dist/month-iso-id.vo.d.ts +4 -2
- package/dist/month-iso-id.vo.js +13 -7
- package/dist/month.vo.d.ts +4 -3
- package/dist/month.vo.js +21 -21
- package/dist/multiplication-factor.vo.d.ts +7 -0
- package/dist/multiplication-factor.vo.js +9 -0
- package/dist/object-key.vo.d.ts +9 -6
- package/dist/object-key.vo.js +20 -19
- package/dist/outlier-detector.service.d.ts +3 -1
- package/dist/outlier-detector.service.js +2 -2
- package/dist/package-version-schema.vo.d.ts +11 -0
- package/dist/package-version-schema.vo.js +15 -0
- package/dist/package-version.vo.d.ts +11 -20
- package/dist/package-version.vo.js +11 -20
- package/dist/pagination-page.vo.d.ts +6 -0
- package/dist/pagination-page.vo.js +7 -0
- package/dist/pagination-skip.vo.d.ts +7 -0
- package/dist/pagination-skip.vo.js +9 -0
- package/dist/pagination-take.vo.d.ts +7 -0
- package/dist/pagination-take.vo.js +9 -0
- package/dist/pagination.service.d.ts +3 -8
- package/dist/pagination.service.js +5 -12
- package/dist/percentage.service.d.ts +3 -1
- package/dist/percentage.service.js +2 -2
- package/dist/population-standard-deviation.service.d.ts +3 -1
- package/dist/population-standard-deviation.service.js +5 -4
- package/dist/quarter-iso-id.vo.d.ts +3 -2
- package/dist/quarter-iso-id.vo.js +7 -9
- package/dist/quarter.vo.d.ts +2 -1
- package/dist/quarter.vo.js +10 -7
- package/dist/random.service.d.ts +3 -4
- package/dist/random.service.js +5 -11
- package/dist/rate-limiter.service.d.ts +2 -2
- package/dist/rate-limiter.service.js +8 -8
- package/dist/reordering-item-position-value.vo.d.ts +6 -0
- package/dist/reordering-item-position-value.vo.js +6 -0
- package/dist/reordering.service.d.ts +7 -23
- package/dist/reordering.service.js +15 -24
- package/dist/revision-value.vo.d.ts +7 -0
- package/dist/revision-value.vo.js +6 -0
- package/dist/revision.vo.d.ts +6 -13
- package/dist/revision.vo.js +10 -22
- package/dist/rounding.adapter.d.ts +7 -2
- package/dist/rounding.adapter.js +13 -5
- package/dist/size-bytes.vo.d.ts +6 -0
- package/dist/size-bytes.vo.js +7 -0
- package/dist/size.vo.d.ts +15 -15
- package/dist/size.vo.js +41 -51
- package/dist/stopwatch.service.d.ts +3 -1
- package/dist/stopwatch.service.js +2 -2
- package/dist/sum.service.js +8 -8
- package/dist/thousands-separator.service.js +4 -1
- package/dist/time.service.d.ts +8 -0
- package/dist/time.service.js +13 -0
- package/dist/timestamp.vo.d.ts +1 -1
- package/dist/timestamp.vo.js +4 -5
- package/dist/timezone.vo.d.ts +4 -1
- package/dist/timezone.vo.js +12 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/week-iso-id.vo.d.ts +4 -2
- package/dist/week-iso-id.vo.js +15 -9
- package/dist/week.vo.d.ts +4 -3
- package/dist/week.vo.js +21 -22
- package/dist/weekday.vo.d.ts +1 -1
- package/dist/weekday.vo.js +6 -8
- package/dist/weight-grams.vo.d.ts +7 -0
- package/dist/weight-grams.vo.js +7 -0
- package/dist/weight.vo.d.ts +12 -35
- package/dist/weight.vo.js +23 -72
- package/dist/year-iso-id.vo.d.ts +3 -2
- package/dist/year-iso-id.vo.js +6 -4
- package/dist/year.vo.d.ts +5 -6
- package/dist/year.vo.js +21 -26
- package/dist/z-score.service.d.ts +3 -1
- package/dist/z-score.service.js +2 -2
- package/package.json +4 -4
- package/readme.md +21 -2
- package/src/age-years.vo.ts +14 -0
- package/src/age.vo.ts +22 -35
- package/src/api-key.vo.ts +11 -5
- package/src/basename.vo.ts +24 -22
- package/src/clock.vo.ts +16 -17
- package/src/date-calculator.service.ts +2 -1
- package/src/date-formatter.service.ts +4 -5
- package/src/date-range.vo.ts +6 -2
- package/src/day-iso-id.vo.ts +12 -8
- package/src/day.vo.ts +27 -24
- package/src/directory-path-absolute.vo.ts +23 -18
- package/src/directory-path-relative.vo.ts +21 -18
- package/src/division-factor.vo.ts +13 -0
- package/src/duration-ms.vo.ts +7 -0
- package/src/duration.service.ts +16 -40
- package/src/email-mask.service.ts +7 -15
- package/src/etags.vo.ts +4 -5
- package/src/extension.vo.ts +17 -10
- package/src/feature-flag-value.vo.ts +12 -0
- package/src/feature-flag.vo.ts +1 -9
- package/src/file-path-absolute-schema.vo.ts +18 -17
- package/src/file-path-relative-schema.vo.ts +15 -12
- package/src/file-path.vo.ts +8 -8
- package/src/filename-from-string.vo.ts +12 -9
- package/src/filename-suffix.vo.ts +14 -7
- package/src/filename.vo.ts +11 -2
- package/src/height-milimiters.vo.ts +12 -0
- package/src/height.vo.ts +12 -83
- package/src/hour-format.service.ts +2 -1
- package/src/hour-schema.vo.ts +12 -0
- package/src/hour.vo.ts +12 -12
- package/src/iban-mask.service.ts +3 -5
- package/src/iban-schema.vo.ts +15 -0
- package/src/iban.vo.ts +9 -22
- package/src/image.vo.ts +14 -12
- package/src/index.ts +24 -2
- package/src/language.vo.ts +7 -4
- package/src/linear-regression.service.ts +71 -0
- package/src/mean.service.ts +3 -5
- package/src/mime-types.vo.ts +1 -3
- package/src/mime-value.vo.ts +12 -0
- package/src/mime.vo.ts +12 -33
- package/src/min-max-scaler.service.ts +13 -11
- package/src/minute-schema.vo.ts +12 -0
- package/src/minute.vo.ts +12 -12
- package/src/money-amount.vo.ts +11 -0
- package/src/money.vo.ts +20 -38
- package/src/month-iso-id.vo.ts +14 -7
- package/src/month.vo.ts +25 -24
- package/src/multiplication-factor.vo.ts +13 -0
- package/src/object-key.vo.ts +25 -21
- package/src/outlier-detector.service.ts +2 -2
- package/src/package-version-schema.vo.ts +21 -0
- package/src/package-version.vo.ts +17 -33
- package/src/pagination-page.vo.ts +11 -0
- package/src/pagination-skip.vo.ts +13 -0
- package/src/pagination-take.vo.ts +13 -0
- package/src/pagination.service.ts +5 -22
- package/src/percentage.service.ts +2 -2
- package/src/population-standard-deviation.service.ts +5 -4
- package/src/quarter-iso-id.vo.ts +7 -10
- package/src/quarter.vo.ts +14 -9
- package/src/random.service.ts +6 -9
- package/src/rate-limiter.service.ts +9 -8
- package/src/reordering-item-position-value.vo.ts +10 -0
- package/src/reordering.service.ts +19 -28
- package/src/revision-value.vo.ts +10 -0
- package/src/revision.vo.ts +10 -25
- package/src/rounding.adapter.ts +16 -3
- package/src/size-bytes.vo.ts +11 -0
- package/src/size.vo.ts +43 -54
- package/src/stopwatch.service.ts +3 -3
- package/src/sum.service.ts +8 -8
- package/src/thousands-separator.service.ts +4 -1
- package/src/time.service.ts +15 -0
- package/src/timestamp.vo.ts +4 -5
- package/src/timezone.vo.ts +12 -6
- package/src/week-iso-id.vo.ts +16 -12
- package/src/week.vo.ts +26 -28
- package/src/weekday.vo.ts +6 -9
- package/src/weight-grams.vo.ts +11 -0
- package/src/weight.vo.ts +28 -85
- package/src/year-iso-id.vo.ts +7 -4
- package/src/year.vo.ts +27 -33
- package/src/z-score.service.ts +2 -2
- package/dist/simple-linear-regression.service.d.ts +0 -25
- package/dist/streak-calculator.service.d.ts +0 -13
- package/dist/streak-calculator.service.js +0 -22
- package/src/simple-linear-regression.service.ts +0 -69
- package/src/streak-calculator.service.ts +0 -32
package/src/weight.vo.ts
CHANGED
|
@@ -1,87 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { DivisionFactorType } from "./division-factor.vo";
|
|
2
|
+
import type { MultiplicationFactorType } from "./multiplication-factor.vo";
|
|
3
|
+
import { RoundToNearest } from "./rounding.adapter";
|
|
3
4
|
import type { RoundingPort } from "./rounding.port";
|
|
4
|
-
|
|
5
|
-
export enum WeightUnit {
|
|
6
|
-
kg = "kg",
|
|
7
|
-
lb = "lb",
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const WeightNonFiniteError = { error: "weight.non_finite" } as const;
|
|
11
|
-
export const WeightNegativeError = { error: "weight.negative" } as const;
|
|
12
|
-
export const WeightNonPositiveError = { error: "weight.non_positive" } as const;
|
|
13
|
-
export const WeightGramsNonNegativeError = { error: "weight.grams_non_negative" } as const;
|
|
14
|
-
|
|
15
|
-
const WeightQuantityNumber = z
|
|
16
|
-
.number(WeightNonFiniteError)
|
|
17
|
-
.refine(Number.isFinite, WeightNonFiniteError)
|
|
18
|
-
.min(0, WeightNegativeError);
|
|
19
|
-
|
|
20
|
-
const DivisionScalarNumber = z
|
|
21
|
-
.number(WeightNonFiniteError)
|
|
22
|
-
.refine(Number.isFinite, WeightNonFiniteError)
|
|
23
|
-
.gt(0, WeightNonPositiveError);
|
|
24
|
-
|
|
25
|
-
const CanonicalGramsInteger = z
|
|
26
|
-
.number(WeightGramsNonNegativeError)
|
|
27
|
-
.int(WeightGramsNonNegativeError)
|
|
28
|
-
.min(0, WeightGramsNonNegativeError);
|
|
5
|
+
import { WeightGrams } from "./weight-grams.vo";
|
|
29
6
|
|
|
30
7
|
export class Weight {
|
|
31
8
|
private static readonly GRAMS_PER_KILOGRAM = 1_000;
|
|
32
|
-
private static readonly POUNDS_PER_KILOGRAM = 2.2046226218487757;
|
|
33
|
-
private static readonly KILOGRAMS_PER_POUND = 1 / Weight.POUNDS_PER_KILOGRAM;
|
|
34
9
|
|
|
35
|
-
private constructor(
|
|
10
|
+
private constructor(
|
|
11
|
+
private readonly grams: number,
|
|
12
|
+
private readonly rounding: RoundingPort = new RoundToNearest(),
|
|
13
|
+
) {}
|
|
36
14
|
|
|
37
|
-
static fromKilograms(kilograms: number): Weight {
|
|
38
|
-
const
|
|
39
|
-
const gramsRounded = Math.round(kilogramsParsed * Weight.GRAMS_PER_KILOGRAM);
|
|
40
|
-
const grams = CanonicalGramsInteger.parse(gramsRounded);
|
|
15
|
+
static fromKilograms(kilograms: number, rounding: RoundingPort = new RoundToNearest()): Weight {
|
|
16
|
+
const grams = rounding.round(kilograms * Weight.GRAMS_PER_KILOGRAM);
|
|
41
17
|
|
|
42
|
-
return new Weight(grams);
|
|
18
|
+
return new Weight(WeightGrams.parse(grams), rounding);
|
|
43
19
|
}
|
|
44
20
|
|
|
45
|
-
static
|
|
46
|
-
|
|
47
|
-
const gramsRounded = Math.round(poundsParsed * Weight.KILOGRAMS_PER_POUND * Weight.GRAMS_PER_KILOGRAM);
|
|
48
|
-
const grams = CanonicalGramsInteger.parse(gramsRounded);
|
|
49
|
-
|
|
50
|
-
return new Weight(grams);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static fromGrams(grams: number): Weight {
|
|
54
|
-
const gramsParsed = WeightQuantityNumber.parse(grams);
|
|
55
|
-
const gramsRounded = Math.round(gramsParsed);
|
|
56
|
-
const integerGrams = CanonicalGramsInteger.parse(gramsRounded);
|
|
57
|
-
|
|
58
|
-
return new Weight(integerGrams);
|
|
21
|
+
static fromGrams(grams: number, rounding: RoundingPort = new RoundToNearest()): Weight {
|
|
22
|
+
return new Weight(WeightGrams.parse(grams), rounding);
|
|
59
23
|
}
|
|
60
24
|
|
|
61
25
|
static zero(): Weight {
|
|
62
26
|
return new Weight(0);
|
|
63
27
|
}
|
|
64
28
|
|
|
65
|
-
|
|
29
|
+
get(): number {
|
|
66
30
|
return this.grams;
|
|
67
31
|
}
|
|
68
32
|
|
|
69
|
-
toKilograms(
|
|
33
|
+
toKilograms(): number {
|
|
70
34
|
const kilograms = this.grams / Weight.GRAMS_PER_KILOGRAM;
|
|
71
35
|
|
|
72
|
-
return rounding
|
|
36
|
+
return this.rounding.round(kilograms);
|
|
73
37
|
}
|
|
74
38
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return rounding ? rounding.round(pounds) : pounds;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
format(unit: WeightUnit, rounding: RoundingPort = new RoundToDecimal(2)): string {
|
|
82
|
-
const value = unit === WeightUnit.kg ? this.toKilograms(rounding) : this.toPounds(rounding);
|
|
83
|
-
|
|
84
|
-
return `${value.toString()} ${unit}`;
|
|
39
|
+
format(): string {
|
|
40
|
+
return `${this.grams} g`;
|
|
85
41
|
}
|
|
86
42
|
|
|
87
43
|
add(other: Weight): Weight {
|
|
@@ -94,31 +50,22 @@ export class Weight {
|
|
|
94
50
|
return new Weight(result < 0 ? 0 : result);
|
|
95
51
|
}
|
|
96
52
|
|
|
97
|
-
multiply(factor:
|
|
98
|
-
const
|
|
99
|
-
const gramsRounded = Math.round(this.grams * factorParsed);
|
|
100
|
-
const grams = CanonicalGramsInteger.parse(gramsRounded);
|
|
53
|
+
multiply(factor: MultiplicationFactorType): Weight {
|
|
54
|
+
const grams = this.rounding.round(this.grams * factor);
|
|
101
55
|
|
|
102
|
-
return new Weight(grams);
|
|
56
|
+
return new Weight(WeightGrams.parse(grams));
|
|
103
57
|
}
|
|
104
58
|
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
const gramsRounded = Math.round(this.grams / divisorParsed);
|
|
108
|
-
const grams = CanonicalGramsInteger.parse(gramsRounded);
|
|
59
|
+
divide(divisor: DivisionFactorType): Weight {
|
|
60
|
+
const grams = this.rounding.round(this.grams / divisor);
|
|
109
61
|
|
|
110
|
-
return new Weight(grams);
|
|
62
|
+
return new Weight(WeightGrams.parse(grams));
|
|
111
63
|
}
|
|
112
64
|
|
|
113
65
|
equals(other: Weight): boolean {
|
|
114
66
|
return this.grams === other.grams;
|
|
115
67
|
}
|
|
116
68
|
|
|
117
|
-
compare(other: Weight): -1 | 0 | 1 {
|
|
118
|
-
if (this.grams === other.grams) return 0;
|
|
119
|
-
return this.grams < other.grams ? -1 : 1;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
69
|
greaterThan(other: Weight): boolean {
|
|
123
70
|
return this.grams > other.grams;
|
|
124
71
|
}
|
|
@@ -139,15 +86,11 @@ export class Weight {
|
|
|
139
86
|
return this.grams === 0;
|
|
140
87
|
}
|
|
141
88
|
|
|
142
|
-
|
|
143
|
-
return this.
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
toJSON(): { g: number } {
|
|
147
|
-
return { g: this.grams };
|
|
89
|
+
toString(): string {
|
|
90
|
+
return this.format();
|
|
148
91
|
}
|
|
149
92
|
|
|
150
|
-
|
|
151
|
-
return
|
|
93
|
+
toJSON(): number {
|
|
94
|
+
return this.grams;
|
|
152
95
|
}
|
|
153
96
|
}
|
package/src/year-iso-id.vo.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
|
|
3
|
-
export const YearIsoIdError = {
|
|
3
|
+
export const YearIsoIdError = { Type: "year.iso.id.type", BadChars: "year.iso.id.bad.chars" } as const;
|
|
4
|
+
|
|
5
|
+
// Four digits
|
|
6
|
+
const YEAR_ISO_ID_CHARS_WHITELIST = /^[0-9]{4}$/;
|
|
4
7
|
|
|
5
8
|
export const YearIsoId = z
|
|
6
|
-
.string(YearIsoIdError)
|
|
7
|
-
.regex(
|
|
8
|
-
.
|
|
9
|
+
.string(YearIsoIdError.Type)
|
|
10
|
+
.regex(YEAR_ISO_ID_CHARS_WHITELIST, YearIsoIdError.BadChars)
|
|
11
|
+
.brand("YearIsoId");
|
|
9
12
|
|
|
10
13
|
export type YearIsoIdType = z.infer<typeof YearIsoId>;
|
package/src/year.vo.ts
CHANGED
|
@@ -3,59 +3,53 @@ import { DateRange } from "./date-range.vo";
|
|
|
3
3
|
import { Timestamp, type TimestampType } from "./timestamp.vo";
|
|
4
4
|
import { YearIsoId, type YearIsoIdType } from "./year-iso-id.vo";
|
|
5
5
|
|
|
6
|
-
export const YearInvalidIntegerError = "year.invalid_integer" as const;
|
|
7
|
-
export const YearOutOfRangeError = "year.out_of_range" as const;
|
|
8
|
-
|
|
9
6
|
export class Year extends DateRange {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
isLeapYear(): boolean {
|
|
15
|
-
const year = getYear(this.getStart());
|
|
7
|
+
static fromTimestamp(timestamp: TimestampType): Year {
|
|
8
|
+
const start = Timestamp.parse(startOfYear(timestamp).getTime());
|
|
9
|
+
const end = Timestamp.parse(endOfYear(timestamp).getTime());
|
|
16
10
|
|
|
17
|
-
return (
|
|
11
|
+
return new Year(start, end);
|
|
18
12
|
}
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
static fromNow(now: TimestampType): Year {
|
|
15
|
+
return Year.fromTimestamp(now);
|
|
16
|
+
}
|
|
22
17
|
|
|
23
|
-
|
|
18
|
+
static fromNumber(candidate: number): Year {
|
|
19
|
+
return Year.fromIsoId(YearIsoId.parse(String(candidate)));
|
|
24
20
|
}
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
const
|
|
22
|
+
static fromIsoId(isoId: YearIsoIdType): Year {
|
|
23
|
+
const reference = Date.UTC(Number(isoId));
|
|
28
24
|
|
|
29
|
-
return Year.fromTimestamp(Timestamp.parse(
|
|
25
|
+
return Year.fromTimestamp(Timestamp.parse(reference));
|
|
30
26
|
}
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return Year.fromTimestamp(Timestamp.parse(shifted));
|
|
28
|
+
toIsoId(): YearIsoIdType {
|
|
29
|
+
return YearIsoId.parse(String(getYear(this.getStart())));
|
|
36
30
|
}
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const end = Timestamp.parse(endOfYear(timestamp).getTime());
|
|
32
|
+
isLeapYear(): boolean {
|
|
33
|
+
const year = getYear(this.getStart());
|
|
41
34
|
|
|
42
|
-
return
|
|
35
|
+
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
43
36
|
}
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
return
|
|
38
|
+
previous(): Year {
|
|
39
|
+
return this.shift(-1);
|
|
47
40
|
}
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
next(): Year {
|
|
43
|
+
return this.shift(1);
|
|
44
|
+
}
|
|
52
45
|
|
|
53
|
-
|
|
46
|
+
shift(count: number): Year {
|
|
47
|
+
const shifted = addYears(this.getStart(), count).getTime();
|
|
54
48
|
|
|
55
|
-
return Year.fromTimestamp(
|
|
49
|
+
return Year.fromTimestamp(Timestamp.parse(shifted));
|
|
56
50
|
}
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
return
|
|
52
|
+
toString(): string {
|
|
53
|
+
return this.toIsoId();
|
|
60
54
|
}
|
|
61
55
|
}
|
package/src/z-score.service.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { PopulationStandardDeviation } from "./population-standard-deviation.ser
|
|
|
3
3
|
import { RoundToDecimal } from "./rounding.adapter";
|
|
4
4
|
import type { RoundingPort } from "./rounding.port";
|
|
5
5
|
|
|
6
|
-
export const
|
|
6
|
+
export const ZScoreError = { NotEnoughValues: "z.score.not.enough.values" } as const;
|
|
7
7
|
|
|
8
8
|
export class ZScore {
|
|
9
9
|
private readonly mean: number;
|
|
@@ -13,7 +13,7 @@ export class ZScore {
|
|
|
13
13
|
values: number[],
|
|
14
14
|
private readonly rounding: RoundingPort = new RoundToDecimal(2),
|
|
15
15
|
) {
|
|
16
|
-
if (values.length < 2) throw new Error(
|
|
16
|
+
if (values.length < 2) throw new Error(ZScoreError.NotEnoughValues);
|
|
17
17
|
|
|
18
18
|
this.mean = Mean.calculate(values);
|
|
19
19
|
this.standardDeviation = PopulationStandardDeviation.calculate(values);
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { RoundingPort } from "./rounding.port";
|
|
2
|
-
export type SLRPairType = {
|
|
3
|
-
x: number;
|
|
4
|
-
y: number;
|
|
5
|
-
};
|
|
6
|
-
export type SLRParamsType = {
|
|
7
|
-
a: number;
|
|
8
|
-
b: number;
|
|
9
|
-
};
|
|
10
|
-
export type SLRPredictionType = number;
|
|
11
|
-
export declare const SLRMinPairsError: "slr.min.pairs";
|
|
12
|
-
export declare const SLRSumXTooBigError: "slr.sum.x.too.big";
|
|
13
|
-
export declare const SLRSumYTooBigError: "slr.sum.y.too.big";
|
|
14
|
-
export declare const SLRSumXSquaredTooBigError: "slr.sum.x.squared.too.big";
|
|
15
|
-
export declare const SLRSumXTimesYTooBigError: "slr.sum.x.times.y.too.big";
|
|
16
|
-
export declare const SLRModelCreationError: "slr.model.creation";
|
|
17
|
-
export declare class SimpleLinearRegression {
|
|
18
|
-
private static readonly DEFAULT_ROUNDING;
|
|
19
|
-
private readonly params;
|
|
20
|
-
private readonly rounding;
|
|
21
|
-
constructor(params: SLRParamsType, rounding?: RoundingPort);
|
|
22
|
-
static fromPairs(pairs: SLRPairType[], rounding?: RoundingPort): SimpleLinearRegression;
|
|
23
|
-
predict(x: SLRPairType["x"], rounding?: RoundingPort): SLRPredictionType;
|
|
24
|
-
inspect(): SimpleLinearRegression["params"];
|
|
25
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
type DateType = string;
|
|
2
|
-
export type StreakType = {
|
|
3
|
-
cutoff: DateType;
|
|
4
|
-
dates: DateType[];
|
|
5
|
-
streak: number;
|
|
6
|
-
};
|
|
7
|
-
export declare class StreakCalculator {
|
|
8
|
-
private readonly cutoff;
|
|
9
|
-
constructor(now?: Date);
|
|
10
|
-
calculate(inputDates: DateType[]): StreakType;
|
|
11
|
-
static format(date: Date | number): DateType;
|
|
12
|
-
}
|
|
13
|
-
export {};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { format, subDays } from "date-fns";
|
|
2
|
-
export class StreakCalculator {
|
|
3
|
-
cutoff;
|
|
4
|
-
constructor(now = new Date()) {
|
|
5
|
-
this.cutoff = StreakCalculator.format(now);
|
|
6
|
-
}
|
|
7
|
-
calculate(inputDates) {
|
|
8
|
-
const dates = Array.from(new Set(inputDates));
|
|
9
|
-
const datesSet = new Set(dates);
|
|
10
|
-
let streak = 0;
|
|
11
|
-
let cursor = this.cutoff;
|
|
12
|
-
while (datesSet.has(cursor)) {
|
|
13
|
-
streak++;
|
|
14
|
-
const cursorDate = new Date(`${cursor}T00:00:00Z`);
|
|
15
|
-
cursor = StreakCalculator.format(subDays(cursorDate, 1));
|
|
16
|
-
}
|
|
17
|
-
return { cutoff: this.cutoff, dates, streak };
|
|
18
|
-
}
|
|
19
|
-
static format(date) {
|
|
20
|
-
return format(date, "yyyy-MM-dd");
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { RoundToNearest } from "./rounding.adapter";
|
|
2
|
-
import type { RoundingPort } from "./rounding.port";
|
|
3
|
-
|
|
4
|
-
export type SLRPairType = { x: number; y: number };
|
|
5
|
-
export type SLRParamsType = { a: number; b: number };
|
|
6
|
-
export type SLRPredictionType = number;
|
|
7
|
-
|
|
8
|
-
export const SLRMinPairsError = "slr.min.pairs" as const;
|
|
9
|
-
export const SLRSumXTooBigError = "slr.sum.x.too.big" as const;
|
|
10
|
-
export const SLRSumYTooBigError = "slr.sum.y.too.big" as const;
|
|
11
|
-
export const SLRSumXSquaredTooBigError = "slr.sum.x.squared.too.big" as const;
|
|
12
|
-
export const SLRSumXTimesYTooBigError = "slr.sum.x.times.y.too.big" as const;
|
|
13
|
-
export const SLRModelCreationError = "slr.model.creation" as const;
|
|
14
|
-
|
|
15
|
-
export class SimpleLinearRegression {
|
|
16
|
-
private static readonly DEFAULT_ROUNDING: RoundingPort = new RoundToNearest();
|
|
17
|
-
|
|
18
|
-
private readonly params: SLRParamsType;
|
|
19
|
-
private readonly rounding: RoundingPort;
|
|
20
|
-
|
|
21
|
-
constructor(params: SLRParamsType, rounding?: RoundingPort) {
|
|
22
|
-
this.params = params;
|
|
23
|
-
this.rounding = rounding ?? SimpleLinearRegression.DEFAULT_ROUNDING;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
static fromPairs(pairs: SLRPairType[], rounding?: RoundingPort): SimpleLinearRegression {
|
|
27
|
-
const count = pairs.length;
|
|
28
|
-
|
|
29
|
-
if (count < 2) throw new Error(SLRMinPairsError);
|
|
30
|
-
|
|
31
|
-
let sumX = 0;
|
|
32
|
-
let sumY = 0;
|
|
33
|
-
let sumXX = 0;
|
|
34
|
-
let sumXY = 0;
|
|
35
|
-
|
|
36
|
-
for (let index = 0; index < count; index++) {
|
|
37
|
-
const pair = pairs[index];
|
|
38
|
-
sumX += pair.x;
|
|
39
|
-
sumY += pair.y;
|
|
40
|
-
sumXX += pair.x * pair.x;
|
|
41
|
-
sumXY += pair.x * pair.y;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (Math.abs(sumX) >= Number.MAX_SAFE_INTEGER) throw new Error(SLRSumXTooBigError);
|
|
45
|
-
if (Math.abs(sumY) >= Number.MAX_SAFE_INTEGER) throw new Error(SLRSumYTooBigError);
|
|
46
|
-
if (Math.abs(sumXY) >= Number.MAX_SAFE_INTEGER) throw new Error(SLRSumXTimesYTooBigError);
|
|
47
|
-
if (Math.abs(sumXX) >= Number.MAX_SAFE_INTEGER) throw new Error(SLRSumXSquaredTooBigError);
|
|
48
|
-
|
|
49
|
-
const bDenominator = sumXX - sumX ** 2 / count;
|
|
50
|
-
|
|
51
|
-
if (bDenominator === 0) throw new Error(SLRModelCreationError);
|
|
52
|
-
|
|
53
|
-
const b = (sumXY - (sumX * sumY) / count) / bDenominator;
|
|
54
|
-
const a = (sumY - b * sumX) / count;
|
|
55
|
-
|
|
56
|
-
return new SimpleLinearRegression({ a, b }, rounding);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
predict(x: SLRPairType["x"], rounding?: RoundingPort): SLRPredictionType {
|
|
60
|
-
const chosen = rounding ?? this.rounding;
|
|
61
|
-
const prediction = this.params.b * x + this.params.a;
|
|
62
|
-
|
|
63
|
-
return chosen.round(prediction);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
inspect(): SimpleLinearRegression["params"] {
|
|
67
|
-
return this.params;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { format, subDays } from "date-fns";
|
|
2
|
-
|
|
3
|
-
type DateType = string;
|
|
4
|
-
export type StreakType = { cutoff: DateType; dates: DateType[]; streak: number };
|
|
5
|
-
|
|
6
|
-
export class StreakCalculator {
|
|
7
|
-
private readonly cutoff: DateType;
|
|
8
|
-
|
|
9
|
-
constructor(now: Date = new Date()) {
|
|
10
|
-
this.cutoff = StreakCalculator.format(now);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
calculate(inputDates: DateType[]): StreakType {
|
|
14
|
-
const dates = Array.from(new Set(inputDates));
|
|
15
|
-
const datesSet = new Set(dates);
|
|
16
|
-
|
|
17
|
-
let streak = 0;
|
|
18
|
-
let cursor = this.cutoff;
|
|
19
|
-
|
|
20
|
-
while (datesSet.has(cursor)) {
|
|
21
|
-
streak++;
|
|
22
|
-
const cursorDate = new Date(`${cursor}T00:00:00Z`);
|
|
23
|
-
cursor = StreakCalculator.format(subDays(cursorDate, 1));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return { cutoff: this.cutoff, dates, streak };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
static format(date: Date | number): DateType {
|
|
30
|
-
return format(date, "yyyy-MM-dd");
|
|
31
|
-
}
|
|
32
|
-
}
|