Skip to content

Commit aa61e3a

Browse files
committed
Merge branch 'feat/sla-computer' into chore/all-my-stuffs
# Conflicts: # components.d.ts # package.json # pnpm-lock.yaml # src/tools/index.ts
2 parents 261ae3a + 6fadc83 commit aa61e3a

File tree

7 files changed

+420
-3
lines changed

7 files changed

+420
-3
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
"@tiptap/starter-kit": "2.1.6",
8080
"@tiptap/vue-3": "2.0.3",
8181
"@types/emscripten": "^1.39.10",
82+
"@types/big.js": "^6.2.2",
8283
"@types/figlet": "^1.5.8",
8384
"@types/markdown-it": "^13.0.7",
8485
"@types/potrace": "^2.1.5",
@@ -95,6 +96,7 @@
9596
"@zxing/library": "^0.21.0",
9697
"arr-diff": "^4.0.0",
9798
"bcryptjs": "^2.4.3",
99+
"big.js": "^6.2.2",
98100
"change-case": "^4.1.2",
99101
"chatgpt-prompt-splitter": "^1.0.5",
100102
"chinesegen": "^0.3.3",

pnpm-lock.yaml

Lines changed: 17 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tools/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { tool as basicAuthGenerator } from './basic-auth-generator';
44
import { tool as dnsQueries } from './dns-queries';
55
import { tool as icoConverter } from './ico-converter';
66
import { tool as jsonEditor } from './json-editor';
7+
import { tool as slaCalculator } from './sla-calculator';
78
import { tool as emailNormalizer } from './email-normalizer';
89
import { tool as bounceParser } from './bounce-parser';
910
import { tool as codeHighlighter } from './code-highlighter';
@@ -358,6 +359,8 @@ export const toolsByCategory: ToolCategory[] = [
358359
durationCalculator,
359360
dateDurationCalculator,
360361
benchmarkBuilder,
362+
benchmarkBuilder,
363+
slaCalculator,
361364
],
362365
},
363366
{

src/tools/sla-calculator/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Clock } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'SLA calculator',
6+
path: '/sla-calculator',
7+
description: 'Service Level Agreement Calcultator',
8+
keywords: ['sla', 'service', 'level', 'agreement', 'calculator'],
9+
component: () => import('./sla-calculator.vue'),
10+
icon: Clock,
11+
createdAt: new Date('2024-05-11'),
12+
});
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { downTimeToSLA, slaToDowntimes } from './sla-calculator.service';
3+
4+
describe('sla-calculator', () => {
5+
describe('downTimeToSLA', () => {
6+
it('compute correct values', () => {
7+
expect(downTimeToSLA({
8+
downTimeSeconds: 100,
9+
mondayHours: 16,
10+
tuesdayHours: 6,
11+
wednesdayHours: 4,
12+
thursdayHours: 24,
13+
fridayHours: 21,
14+
saturdayHours: 16,
15+
sundayHours: 13,
16+
})).to.deep.eq({
17+
slaForDay: null,
18+
slaForMonth: 99.99361155031703,
19+
slaForQuarter: 99.99787051677234,
20+
slaForWeek: 99.97222222222223,
21+
slaForYear: 99.99946762919309,
22+
});
23+
expect(downTimeToSLA({
24+
downTimeSeconds: 86400 / 10000,
25+
})).to.deep.eq({
26+
slaForDay: 99.99,
27+
slaForMonth: 99.99967145115916,
28+
slaForQuarter: 99.99989048371972,
29+
slaForWeek: 99.99857142857142,
30+
slaForYear: 99.99997262092992,
31+
});
32+
expect(downTimeToSLA({
33+
downTimeSeconds: 86400 / 2,
34+
})).to.deep.eq({
35+
slaForDay: 50,
36+
slaForMonth: 98.35725579580689,
37+
slaForQuarter: 99.45241859860229,
38+
slaForWeek: 92.85714285714286,
39+
slaForYear: 99.86310464965058,
40+
});
41+
});
42+
});
43+
describe('slaToDowntimes', () => {
44+
it('compute correct values', () => {
45+
expect(slaToDowntimes({
46+
targetSLA: 99,
47+
mondayHours: 9,
48+
tuesdayHours: 24,
49+
wednesdayHours: 10,
50+
thursdayHours: 8,
51+
fridayHours: 3,
52+
saturdayHours: 24,
53+
sundayHours: 4,
54+
})).to.deep.eq({
55+
secondsPerDay: null,
56+
secondsPerMonth: 12835.665,
57+
secondsPerQuarter: 38506.995,
58+
secondsPerWeek: 2952,
59+
secondsPerYear: 154027.98,
60+
});
61+
expect(slaToDowntimes({
62+
targetSLA: 99.99,
63+
})).to.deep.eq({
64+
secondsPerDay: 8.64,
65+
secondsPerMonth: 262.9746,
66+
secondsPerQuarter: 788.9238,
67+
secondsPerWeek: 60.48,
68+
secondsPerYear: 3155.6952,
69+
});
70+
expect(slaToDowntimes({
71+
targetSLA: 99,
72+
})).to.deep.eq({
73+
secondsPerDay: 864,
74+
secondsPerMonth: 26297.46,
75+
secondsPerQuarter: 78892.38,
76+
secondsPerWeek: 6048,
77+
secondsPerYear: 315569.52,
78+
});
79+
});
80+
});
81+
});
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import Big from 'big.js';
2+
3+
const hoursDay = Big('24');
4+
const daysWeek = Big('7');
5+
const monthsYear = Big('12');
6+
const daysYear = Big('365.2425');
7+
const weeksYear = daysYear.div(daysWeek);
8+
const daysMonth = daysYear.div(monthsYear);
9+
const weeksMonth = daysMonth.div(daysWeek);
10+
11+
interface DaysHours {
12+
mondayHours?: number
13+
tuesdayHours?: number
14+
wednesdayHours?: number
15+
thursdayHours?: number
16+
fridayHours?: number
17+
saturdayHours?: number
18+
sundayHours?: number
19+
}
20+
21+
function prepareDurations({
22+
mondayHours = 24,
23+
tuesdayHours = 24,
24+
wednesdayHours = 24,
25+
thursdayHours = 24,
26+
fridayHours = 24,
27+
saturdayHours = 24,
28+
sundayHours = 24,
29+
}: DaysHours) {
30+
const durHoursWeek = Big(mondayHours).plus(tuesdayHours).plus(wednesdayHours).plus(thursdayHours).plus(fridayHours).plus(saturdayHours).plus(sundayHours);
31+
const durSecondsWeek = durHoursWeek.mul('3600');
32+
const durSecondsDay = durSecondsWeek.div(daysWeek);
33+
const durSecondsMonth = durSecondsWeek.mul(weeksMonth);
34+
const durSecondsQuarter = durSecondsMonth.mul('3');
35+
const durSecondsYear = durSecondsWeek.mul(weeksYear);
36+
const fullWeekHours = daysWeek.mul(hoursDay);
37+
38+
return {
39+
durHoursWeek,
40+
durSecondsWeek,
41+
durSecondsDay,
42+
durSecondsMonth,
43+
durSecondsQuarter,
44+
durSecondsYear,
45+
fullWeekHours,
46+
};
47+
}
48+
49+
export function downTimeToSLA({
50+
downTimeSeconds,
51+
mondayHours = 24,
52+
tuesdayHours = 24,
53+
wednesdayHours = 24,
54+
thursdayHours = 24,
55+
fridayHours = 24,
56+
saturdayHours = 24,
57+
sundayHours = 24,
58+
}: {
59+
downTimeSeconds: number
60+
} & DaysHours) {
61+
const {
62+
durHoursWeek,
63+
durSecondsWeek,
64+
durSecondsDay,
65+
durSecondsMonth,
66+
durSecondsQuarter,
67+
durSecondsYear,
68+
fullWeekHours,
69+
} = prepareDurations({
70+
mondayHours, tuesdayHours, wednesdayHours, thursdayHours, fridayHours, saturdayHours, sundayHours,
71+
});
72+
73+
const one = Big('1');
74+
const hundred = Big('100');
75+
const downTimeSecondsBig = Big(downTimeSeconds);
76+
77+
return {
78+
slaForDay: fullWeekHours.eq(durHoursWeek) ? one.minus(downTimeSecondsBig.div(durSecondsDay)).mul(hundred).toNumber() : null,
79+
slaForWeek: one.minus(downTimeSecondsBig.div(durSecondsWeek)).mul(hundred).toNumber(),
80+
slaForMonth: one.minus(downTimeSecondsBig.div(durSecondsMonth)).mul(hundred).toNumber(),
81+
slaForQuarter: one.minus(downTimeSecondsBig.div(durSecondsQuarter)).mul(hundred).toNumber(),
82+
slaForYear: one.minus(downTimeSecondsBig.div(durSecondsYear)).mul(hundred).toNumber(),
83+
};
84+
}
85+
86+
export function slaToDowntimes({
87+
targetSLA,
88+
mondayHours = 24,
89+
tuesdayHours = 24,
90+
wednesdayHours = 24,
91+
thursdayHours = 24,
92+
fridayHours = 24,
93+
saturdayHours = 24,
94+
sundayHours = 24,
95+
}: {
96+
targetSLA: number
97+
mondayHours?: number
98+
tuesdayHours?: number
99+
wednesdayHours?: number
100+
thursdayHours?: number
101+
fridayHours?: number
102+
saturdayHours?: number
103+
sundayHours?: number
104+
}) {
105+
const {
106+
durHoursWeek,
107+
durSecondsWeek,
108+
durSecondsDay,
109+
durSecondsMonth,
110+
durSecondsQuarter,
111+
durSecondsYear,
112+
fullWeekHours,
113+
} = prepareDurations({
114+
mondayHours, tuesdayHours, wednesdayHours, thursdayHours, fridayHours, saturdayHours, sundayHours,
115+
});
116+
117+
const allowedDowntime = Big('1').minus(Big(targetSLA).div('100'));
118+
119+
return {
120+
secondsPerDay: fullWeekHours.eq(durHoursWeek) ? allowedDowntime.mul(durSecondsDay).toNumber() : null,
121+
secondsPerWeek: allowedDowntime.mul(durSecondsWeek).toNumber(),
122+
secondsPerMonth: allowedDowntime.mul(durSecondsMonth).toNumber(),
123+
secondsPerQuarter: allowedDowntime.mul(durSecondsQuarter).toNumber(),
124+
secondsPerYear: allowedDowntime.mul(durSecondsYear).toNumber(),
125+
};
126+
}

0 commit comments

Comments
 (0)