@algoux/standard-ranklist-renderer-component-angular 0.6.0 → 0.6.1

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.
Files changed (32) hide show
  1. package/dist/README.md +148 -0
  2. package/dist/esm2022/algoux-standard-ranklist-renderer-component-angular.mjs +5 -0
  3. package/dist/esm2022/lib/index.mjs +8 -0
  4. package/dist/esm2022/lib/modal/default-solution-modal.component.mjs +146 -0
  5. package/dist/esm2022/lib/modal/default-user-modal.component.mjs +172 -0
  6. package/dist/esm2022/lib/modal/modal-interactions.mjs +2 -0
  7. package/dist/esm2022/lib/modal/modal.component.mjs +263 -0
  8. package/dist/esm2022/lib/progress/progress-bar.component.mjs +247 -0
  9. package/dist/esm2022/lib/progress/progress-utils.mjs +45 -0
  10. package/dist/esm2022/lib/ranklist/ranklist-utils.mjs +110 -0
  11. package/dist/esm2022/lib/ranklist/ranklist.component.mjs +1013 -0
  12. package/dist/esm2022/lib/ranklist/status-cell-template.directive.mjs +18 -0
  13. package/dist/esm2022/lib/ranklist/user-cell-template.directive.mjs +18 -0
  14. package/dist/esm2022/lib/types.mjs +2 -0
  15. package/dist/esm2022/public-api.mjs +2 -0
  16. package/dist/fesm2022/algoux-standard-ranklist-renderer-component-angular.mjs +2005 -0
  17. package/dist/fesm2022/algoux-standard-ranklist-renderer-component-angular.mjs.map +1 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/lib/index.d.ts +8 -0
  20. package/dist/lib/modal/default-solution-modal.component.d.ts +30 -0
  21. package/dist/lib/modal/default-user-modal.component.d.ts +34 -0
  22. package/dist/lib/modal/modal-interactions.d.ts +1 -0
  23. package/dist/lib/modal/modal.component.d.ts +49 -0
  24. package/dist/lib/progress/progress-bar.component.d.ts +31 -0
  25. package/dist/lib/progress/progress-utils.d.ts +15 -0
  26. package/dist/lib/ranklist/ranklist-utils.d.ts +22 -0
  27. package/dist/lib/ranklist/ranklist.component.d.ts +88 -0
  28. package/dist/lib/ranklist/status-cell-template.directive.d.ts +26 -0
  29. package/dist/lib/ranklist/user-cell-template.directive.d.ts +22 -0
  30. package/dist/lib/types.d.ts +29 -0
  31. package/dist/public-api.d.ts +1 -0
  32. package/package.json +3 -3
@@ -0,0 +1,263 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, EventEmitter, Input, Output, ViewChild, } from '@angular/core';
3
+ import { MODAL_ANIMATION_DURATION_MS, SRK_ANIMATED_MODAL_ROOT_CLASS, ensureModalInteractionTracker, lockModalBodyScroll, registerModalFocusScope, resolveModalTransformOrigin, unlockModalBodyScroll, unregisterModalFocusScope, } from './modal-interactions';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ export class ModalComponent {
7
+ open = false;
8
+ title;
9
+ width;
10
+ rootClassName;
11
+ wrapClassName;
12
+ destroyOnClose = true;
13
+ closeOnEsc = true;
14
+ closeOnMaskClick = true;
15
+ panelStyle = {};
16
+ openChange = new EventEmitter();
17
+ close = new EventEmitter();
18
+ dialogRef;
19
+ isMounted = this.open || !this.destroyOnClose;
20
+ animationState = this.open ? 'pre-open' : 'closing';
21
+ transformOrigin = { x: 0, y: 0 };
22
+ closeTimer = null;
23
+ openTimer = null;
24
+ bodyScrollLocked = false;
25
+ focusScopeId = null;
26
+ constructor() {
27
+ if (typeof document !== 'undefined') {
28
+ ensureModalInteractionTracker();
29
+ }
30
+ }
31
+ ngOnChanges(changes) {
32
+ if (changes['open'] || changes['destroyOnClose']) {
33
+ this.syncOpenState();
34
+ }
35
+ }
36
+ ngAfterViewChecked() {
37
+ if (this.open) {
38
+ this.registerFocusScope();
39
+ }
40
+ }
41
+ ngOnDestroy() {
42
+ this.clearTimers();
43
+ this.releaseFocusScope();
44
+ if (this.bodyScrollLocked) {
45
+ unlockModalBodyScroll();
46
+ this.bodyScrollLocked = false;
47
+ }
48
+ }
49
+ handleEscape(event) {
50
+ if (this.open && this.closeOnEsc) {
51
+ this.requestClose('escape');
52
+ }
53
+ }
54
+ handleMaskMouseDown(event) {
55
+ if (this.closeOnMaskClick && event.target === event.currentTarget) {
56
+ this.requestClose('mask');
57
+ }
58
+ }
59
+ requestClose(reason) {
60
+ this.openChange.emit(false);
61
+ this.close.emit(reason);
62
+ }
63
+ shouldRender() {
64
+ return this.isMounted || !this.destroyOnClose;
65
+ }
66
+ rootClasses() {
67
+ return [SRK_ANIMATED_MODAL_ROOT_CLASS, this.rootClassName].filter(Boolean);
68
+ }
69
+ dialogStyle() {
70
+ return {
71
+ ...this.panelStyle,
72
+ width: this.width ? `${this.width}px` : this.panelStyle?.['width'],
73
+ '--srk-modal-origin-x': `${this.transformOrigin.x}px`,
74
+ '--srk-modal-origin-y': `${this.transformOrigin.y}px`,
75
+ '--srk-modal-max-width': this.width
76
+ ? `${this.width}px`
77
+ : typeof this.panelStyle?.['width'] === 'string'
78
+ ? this.panelStyle['width']
79
+ : undefined,
80
+ };
81
+ }
82
+ clearTimers() {
83
+ if (this.closeTimer !== null) {
84
+ window.clearTimeout(this.closeTimer);
85
+ this.closeTimer = null;
86
+ }
87
+ if (this.openTimer !== null) {
88
+ window.clearTimeout(this.openTimer);
89
+ this.openTimer = null;
90
+ }
91
+ }
92
+ syncOpenState() {
93
+ this.clearTimers();
94
+ if (this.open) {
95
+ this.isMounted = true;
96
+ this.transformOrigin = { x: 0, y: 0 };
97
+ this.animationState = 'pre-open';
98
+ if (typeof window !== 'undefined') {
99
+ this.openTimer = window.setTimeout(() => {
100
+ this.registerFocusScope();
101
+ const resolution = resolveModalTransformOrigin(this.dialogRef?.nativeElement || null);
102
+ this.transformOrigin = resolution.origin;
103
+ this.animationState = 'opening';
104
+ this.openTimer = null;
105
+ }, 0);
106
+ }
107
+ }
108
+ else {
109
+ this.releaseFocusScope();
110
+ this.animationState = 'closing';
111
+ if (!this.destroyOnClose) {
112
+ this.isMounted = true;
113
+ }
114
+ else if (this.isMounted && typeof window !== 'undefined') {
115
+ this.closeTimer = window.setTimeout(() => {
116
+ this.isMounted = false;
117
+ this.updateBodyScrollLock();
118
+ this.closeTimer = null;
119
+ }, MODAL_ANIMATION_DURATION_MS);
120
+ }
121
+ }
122
+ this.updateBodyScrollLock();
123
+ }
124
+ updateBodyScrollLock() {
125
+ const shouldLock = this.open || (this.destroyOnClose && this.isMounted);
126
+ if (shouldLock && !this.bodyScrollLocked) {
127
+ lockModalBodyScroll();
128
+ this.bodyScrollLocked = true;
129
+ return;
130
+ }
131
+ if (!shouldLock && this.bodyScrollLocked) {
132
+ unlockModalBodyScroll();
133
+ this.bodyScrollLocked = false;
134
+ }
135
+ }
136
+ registerFocusScope() {
137
+ const nextFocusScopeId = registerModalFocusScope(this.dialogRef?.nativeElement || null, {
138
+ onEscape: this.closeOnEsc ? (event) => this.handleEscape(event) : undefined,
139
+ });
140
+ if (this.focusScopeId === null) {
141
+ this.focusScopeId = nextFocusScopeId;
142
+ }
143
+ }
144
+ releaseFocusScope() {
145
+ if (this.focusScopeId !== null) {
146
+ unregisterModalFocusScope(this.focusScopeId);
147
+ this.focusScopeId = null;
148
+ }
149
+ }
150
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
151
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ModalComponent, isStandalone: true, selector: "srk-modal", inputs: { open: "open", title: "title", width: "width", rootClassName: "rootClassName", wrapClassName: "wrapClassName", destroyOnClose: "destroyOnClose", closeOnEsc: "closeOnEsc", closeOnMaskClick: "closeOnMaskClick", panelStyle: "panelStyle" }, outputs: { openChange: "openChange", close: "close" }, viewQueries: [{ propertyName: "dialogRef", first: true, predicate: ["dialog"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
152
+ <div *ngIf="shouldRender()" class="srk-modal-root" [ngClass]="rootClasses()" [attr.data-srk-modal-state]="animationState">
153
+ <div class="srk-modal-mask"></div>
154
+ <div
155
+ class="srk-modal-wrap"
156
+ [ngClass]="wrapClassName"
157
+ tabindex="-1"
158
+ (mousedown)="handleMaskMouseDown($event)"
159
+ >
160
+ <div
161
+ #dialog
162
+ class="srk-modal"
163
+ role="dialog"
164
+ aria-modal="true"
165
+ [attr.aria-label]="title || undefined"
166
+ data-srk-modal-panel="true"
167
+ tabindex="-1"
168
+ [ngStyle]="dialogStyle()"
169
+ >
170
+ <div class="srk-modal-content">
171
+ <button
172
+ aria-label="Close"
173
+ class="srk-modal-close"
174
+ type="button"
175
+ (click)="requestClose('close-button')"
176
+ >
177
+ <span class="srk-modal-close-x"></span>
178
+ </button>
179
+ <div *ngIf="title !== undefined" class="srk-modal-header">
180
+ <div class="srk-modal-title">{{ title }}</div>
181
+ </div>
182
+ <div class="srk-modal-body">
183
+ <ng-content />
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
190
+ }
191
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ModalComponent, decorators: [{
192
+ type: Component,
193
+ args: [{
194
+ selector: 'srk-modal',
195
+ standalone: true,
196
+ imports: [CommonModule],
197
+ template: `
198
+ <div *ngIf="shouldRender()" class="srk-modal-root" [ngClass]="rootClasses()" [attr.data-srk-modal-state]="animationState">
199
+ <div class="srk-modal-mask"></div>
200
+ <div
201
+ class="srk-modal-wrap"
202
+ [ngClass]="wrapClassName"
203
+ tabindex="-1"
204
+ (mousedown)="handleMaskMouseDown($event)"
205
+ >
206
+ <div
207
+ #dialog
208
+ class="srk-modal"
209
+ role="dialog"
210
+ aria-modal="true"
211
+ [attr.aria-label]="title || undefined"
212
+ data-srk-modal-panel="true"
213
+ tabindex="-1"
214
+ [ngStyle]="dialogStyle()"
215
+ >
216
+ <div class="srk-modal-content">
217
+ <button
218
+ aria-label="Close"
219
+ class="srk-modal-close"
220
+ type="button"
221
+ (click)="requestClose('close-button')"
222
+ >
223
+ <span class="srk-modal-close-x"></span>
224
+ </button>
225
+ <div *ngIf="title !== undefined" class="srk-modal-header">
226
+ <div class="srk-modal-title">{{ title }}</div>
227
+ </div>
228
+ <div class="srk-modal-body">
229
+ <ng-content />
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ `,
236
+ }]
237
+ }], ctorParameters: () => [], propDecorators: { open: [{
238
+ type: Input
239
+ }], title: [{
240
+ type: Input
241
+ }], width: [{
242
+ type: Input
243
+ }], rootClassName: [{
244
+ type: Input
245
+ }], wrapClassName: [{
246
+ type: Input
247
+ }], destroyOnClose: [{
248
+ type: Input
249
+ }], closeOnEsc: [{
250
+ type: Input
251
+ }], closeOnMaskClick: [{
252
+ type: Input
253
+ }], panelStyle: [{
254
+ type: Input
255
+ }], openChange: [{
256
+ type: Output
257
+ }], close: [{
258
+ type: Output
259
+ }], dialogRef: [{
260
+ type: ViewChild,
261
+ args: ['dialog']
262
+ }] } });
263
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9tb2RhbC9tb2RhbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxTQUFTLEVBRVQsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IsNkJBQTZCLEVBQzdCLDZCQUE2QixFQUM3QixtQkFBbUIsRUFDbkIsdUJBQXVCLEVBQ3ZCLDJCQUEyQixFQUMzQixxQkFBcUIsRUFDckIseUJBQXlCLEdBQzFCLE1BQU0sc0JBQXNCLENBQUM7OztBQWdEOUIsTUFBTSxPQUFPLGNBQWM7SUFDaEIsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUNiLEtBQUssQ0FBVTtJQUNmLEtBQUssQ0FBVTtJQUNmLGFBQWEsQ0FBVTtJQUN2QixhQUFhLENBQVU7SUFDdkIsY0FBYyxHQUFHLElBQUksQ0FBQztJQUN0QixVQUFVLEdBQUcsSUFBSSxDQUFDO0lBQ2xCLGdCQUFnQixHQUFHLElBQUksQ0FBQztJQUN4QixVQUFVLEdBQW9DLEVBQUUsQ0FBQztJQUVoRCxVQUFVLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztJQUN6QyxLQUFLLEdBQUcsSUFBSSxZQUFZLEVBQW9CLENBQUM7SUFFbEMsU0FBUyxDQUE4QjtJQUU1RCxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDOUMsY0FBYyxHQUF1QyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUN4RixlQUFlLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFD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QUFuQixNQUFNO2dCQUNHLEtBQUs7c0JBQWQsTUFBTTtnQkFFYyxTQUFTO3NCQUE3QixTQUFTO3VCQUFDLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3Q2hlY2tlZCxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgTU9EQUxfQU5JTUFUSU9OX0RVUkFUSU9OX01TLFxuICBTUktfQU5JTUFURURfTU9EQUxfUk9PVF9DTEFTUyxcbiAgZW5zdXJlTW9kYWxJbnRlcmFjdGlvblRyYWNrZXIsXG4gIGxvY2tNb2RhbEJvZHlTY3JvbGwsXG4gIHJlZ2lzdGVyTW9kYWxGb2N1c1Njb3BlLFxuICByZXNvbHZlTW9kYWxUcmFuc2Zvcm1PcmlnaW4sXG4gIHVubG9ja01vZGFsQm9keVNjcm9sbCxcbiAgdW5yZWdpc3Rlck1vZGFsRm9jdXNTY29wZSxcbn0gZnJvbSAnLi9tb2RhbC1pbnRlcmFjdGlvbnMnO1xuXG5leHBvcnQgdHlwZSBNb2RhbENsb3NlUmVhc29uID0gJ21hc2snIHwgJ2Nsb3NlLWJ1dHRvbicgfCAnZXNjYXBlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3JrLW1vZGFsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiAqbmdJZj1cInNob3VsZFJlbmRlcigpXCIgY2xhc3M9XCJzcmstbW9kYWwtcm9vdFwiIFtuZ0NsYXNzXT1cInJvb3RDbGFzc2VzKClcIiBbYXR0ci5kYXRhLXNyay1tb2RhbC1zdGF0ZV09XCJhbmltYXRpb25TdGF0ZVwiPlxuICAgICAgPGRpdiBjbGFzcz1cInNyay1tb2RhbC1tYXNrXCI+PC9kaXY+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwic3JrLW1vZGFsLXdyYXBcIlxuICAgICAgICBbbmdDbGFzc109XCJ3cmFwQ2xhc3NOYW1lXCJcbiAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAgIChtb3VzZWRvd24pPVwiaGFuZGxlTWFza01vdXNlRG93bigkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICNkaWFsb2dcbiAgICAgICAgICBjbGFzcz1cInNyay1tb2RhbFwiXG4gICAgICAgICAgcm9sZT1cImRpYWxvZ1wiXG4gICAgICAgICAgYXJpYS1tb2RhbD1cInRydWVcIlxuICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwidGl0bGUgfHwgdW5kZWZpbmVkXCJcbiAgICAgICAgICBkYXRhLXNyay1tb2RhbC1wYW5lbD1cInRydWVcIlxuICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgIFtuZ1N0eWxlXT1cImRpYWxvZ1N0eWxlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInNyay1tb2RhbC1jb250ZW50XCI+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJDbG9zZVwiXG4gICAgICAgICAgICAgIGNsYXNzPVwic3JrLW1vZGFsLWNsb3NlXCJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJyZXF1ZXN0Q2xvc2UoJ2Nsb3NlLWJ1dHRvbicpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzcmstbW9kYWwtY2xvc2UteFwiPjwvc3Bhbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cInRpdGxlICE9PSB1bmRlZmluZWRcIiBjbGFzcz1cInNyay1tb2RhbC1oZWFkZXJcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNyay1tb2RhbC10aXRsZVwiPnt7IHRpdGxlIH19PC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcmstbW9kYWwtYm9keVwiPlxuICAgICAgICAgICAgICA8bmctY29udGVudCAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIE1vZGFsQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3Q2hlY2tlZCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKSBvcGVuID0gZmFsc2U7XG4gIEBJbnB1dCgpIHRpdGxlPzogc3RyaW5nO1xuICBASW5wdXQoKSB3aWR0aD86IG51bWJlcjtcbiAgQElucHV0KCkgcm9vdENsYXNzTmFtZT86IHN0cmluZztcbiAgQElucHV0KCkgd3JhcENsYXNzTmFtZT86IHN0cmluZztcbiAgQElucHV0KCkgZGVzdHJveU9uQ2xvc2UgPSB0cnVlO1xuICBASW5wdXQoKSBjbG9zZU9uRXNjID0gdHJ1ZTtcbiAgQElucHV0KCkgY2xvc2VPbk1hc2tDbGljayA9IHRydWU7XG4gIEBJbnB1dCgpIHBhbmVsU3R5bGU6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IG51bWJlcj4gPSB7fTtcblxuICBAT3V0cHV0KCkgb3BlbkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcbiAgQE91dHB1dCgpIGNsb3NlID0gbmV3IEV2ZW50RW1pdHRlcjxNb2RhbENsb3NlUmVhc29uPigpO1xuXG4gIEBWaWV3Q2hpbGQoJ2RpYWxvZycpIGRpYWxvZ1JlZj86IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xuXG4gIGlzTW91bnRlZCA9IHRoaXMub3BlbiB8fCAhdGhpcy5kZXN0cm95T25DbG9zZTtcbiAgYW5pbWF0aW9uU3RhdGU6ICdwcmUtb3BlbicgfCAnb3BlbmluZycgfCAnY2xvc2luZycgPSB0aGlzLm9wZW4gPyAncHJlLW9wZW4nIDogJ2Nsb3NpbmcnO1xuICB0cmFuc2Zvcm1PcmlnaW4gPSB7IHg6IDAsIHk6IDAgfTtcbiAgcHJpdmF0ZSBjbG9zZVRpbWVyOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBvcGVuVGltZXI6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJvZHlTY3JvbGxMb2NrZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBmb2N1c1Njb3BlSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBlbnN1cmVNb2RhbEludGVyYWN0aW9uVHJhY2tlcigpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlc1snb3BlbiddIHx8IGNoYW5nZXNbJ2Rlc3Ryb3lPbkNsb3NlJ10pIHtcbiAgICAgIHRoaXMuc3luY09wZW5TdGF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3Q2hlY2tlZCgpIHtcbiAgICBpZiAodGhpcy5vcGVuKSB7XG4gICAgICB0aGlzLnJlZ2lzdGVyRm9jdXNTY29wZSgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuY2xlYXJUaW1lcnMoKTtcbiAgICB0aGlzLnJlbGVhc2VGb2N1c1Njb3BlKCk7XG4gICAgaWYgKHRoaXMuYm9keVNjcm9sbExvY2tlZCkge1xuICAgICAgdW5sb2NrTW9kYWxCb2R5U2Nyb2xsKCk7XG4gICAgICB0aGlzLmJvZHlTY3JvbGxMb2NrZWQgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVFc2NhcGUoZXZlbnQ/OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgaWYgKHRoaXMub3BlbiAmJiB0aGlzLmNsb3NlT25Fc2MpIHtcbiAgICAgIHRoaXMucmVxdWVzdENsb3NlKCdlc2NhcGUnKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVNYXNrTW91c2VEb3duKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgaWYgKHRoaXMuY2xvc2VPbk1hc2tDbGljayAmJiBldmVudC50YXJnZXQgPT09IGV2ZW50LmN1cnJlbnRUYXJnZXQpIHtcbiAgICAgIHRoaXMucmVxdWVzdENsb3NlKCdtYXNrJyk7XG4gICAgfVxuICB9XG5cbiAgcmVxdWVzdENsb3NlKHJlYXNvbjogTW9kYWxDbG9zZVJlYXNvbikge1xuICAgIHRoaXMub3BlbkNoYW5nZS5lbWl0KGZhbHNlKTtcbiAgICB0aGlzLmNsb3NlLmVtaXQocmVhc29uKTtcbiAgfVxuXG4gIHNob3VsZFJlbmRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5pc01vdW50ZWQgfHwgIXRoaXMuZGVzdHJveU9uQ2xvc2U7XG4gIH1cblxuICByb290Q2xhc3NlcygpIHtcbiAgICByZXR1cm4gW1NSS19BTklNQVRFRF9NT0RBTF9ST09UX0NMQVNTLCB0aGlzLnJvb3RDbGFzc05hbWVdLmZpbHRlcihCb29sZWFuKTtcbiAgfVxuXG4gIGRpYWxvZ1N0eWxlKCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLnBhbmVsU3R5bGUsXG4gICAgICB3aWR0aDogdGhpcy53aWR0aCA/IGAke3RoaXMud2lkdGh9cHhgIDogdGhpcy5wYW5lbFN0eWxlPy5bJ3dpZHRoJ10sXG4gICAgICAnLS1zcmstbW9kYWwtb3JpZ2luLXgnOiBgJHt0aGlzLnRyYW5zZm9ybU9yaWdpbi54fXB4YCxcbiAgICAgICctLXNyay1tb2RhbC1vcmlnaW4teSc6IGAke3RoaXMudHJhbnNmb3JtT3JpZ2luLnl9cHhgLFxuICAgICAgJy0tc3JrLW1vZGFsLW1heC13aWR0aCc6IHRoaXMud2lkdGhcbiAgICAgICAgPyBgJHt0aGlzLndpZHRofXB4YFxuICAgICAgICA6IHR5cGVvZiB0aGlzLnBhbmVsU3R5bGU/Llsnd2lkdGgnXSA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IHRoaXMucGFuZWxTdHlsZVsnd2lkdGgnXVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGNsZWFyVGltZXJzKCkge1xuICAgIGlmICh0aGlzLmNsb3NlVGltZXIgIT09IG51bGwpIHtcbiAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5jbG9zZVRpbWVyKTtcbiAgICAgIHRoaXMuY2xvc2VUaW1lciA9IG51bGw7XG4gICAgfVxuICAgIGlmICh0aGlzLm9wZW5UaW1lciAhPT0gbnVsbCkge1xuICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aGlzLm9wZW5UaW1lcik7XG4gICAgICB0aGlzLm9wZW5UaW1lciA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzeW5jT3BlblN0YXRlKCkge1xuICAgIHRoaXMuY2xlYXJUaW1lcnMoKTtcblxuICAgIGlmICh0aGlzLm9wZW4pIHtcbiAgICAgIHRoaXMuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMudHJhbnNmb3JtT3JpZ2luID0geyB4OiAwLCB5OiAwIH07XG4gICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gJ3ByZS1vcGVuJztcbiAgICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aGlzLm9wZW5UaW1lciA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICB0aGlzLnJlZ2lzdGVyRm9jdXNTY29wZSgpO1xuICAgICAgICAgIGNvbnN0IHJlc29sdXRpb24gPSByZXNvbHZlTW9kYWxUcmFuc2Zvcm1PcmlnaW4odGhpcy5kaWFsb2dSZWY/Lm5hdGl2ZUVsZW1lbnQgfHwgbnVsbCk7XG4gICAgICAgICAgdGhpcy50cmFuc2Zvcm1PcmlnaW4gPSByZXNvbHV0aW9uLm9yaWdpbjtcbiAgICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gJ29wZW5pbmcnO1xuICAgICAgICAgIHRoaXMub3BlblRpbWVyID0gbnVsbDtcbiAgICAgICAgfSwgMCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVsZWFzZUZvY3VzU2NvcGUoKTtcbiAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSAnY2xvc2luZyc7XG4gICAgICBpZiAoIXRoaXMuZGVzdHJveU9uQ2xvc2UpIHtcbiAgICAgICAgdGhpcy5pc01vdW50ZWQgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmlzTW91bnRlZCAmJiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aGlzLmNsb3NlVGltZXIgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy5pc01vdW50ZWQgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZUJvZHlTY3JvbGxMb2NrKCk7XG4gICAgICAgICAgdGhpcy5jbG9zZVRpbWVyID0gbnVsbDtcbiAgICAgICAgfSwgTU9EQUxfQU5JTUFUSU9OX0RVUkFUSU9OX01TKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZUJvZHlTY3JvbGxMb2NrKCk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUJvZHlTY3JvbGxMb2NrKCkge1xuICAgIGNvbnN0IHNob3VsZExvY2sgPSB0aGlzLm9wZW4gfHwgKHRoaXMuZGVzdHJveU9uQ2xvc2UgJiYgdGhpcy5pc01vdW50ZWQpO1xuICAgIGlmIChzaG91bGRMb2NrICYmICF0aGlzLmJvZHlTY3JvbGxMb2NrZWQpIHtcbiAgICAgIGxvY2tNb2RhbEJvZHlTY3JvbGwoKTtcbiAgICAgIHRoaXMuYm9keVNjcm9sbExvY2tlZCA9IHRydWU7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghc2hvdWxkTG9jayAmJiB0aGlzLmJvZHlTY3JvbGxMb2NrZWQpIHtcbiAgICAgIHVubG9ja01vZGFsQm9keVNjcm9sbCgpO1xuICAgICAgdGhpcy5ib2R5U2Nyb2xsTG9ja2VkID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlckZvY3VzU2NvcGUoKSB7XG4gICAgY29uc3QgbmV4dEZvY3VzU2NvcGVJZCA9IHJlZ2lzdGVyTW9kYWxGb2N1c1Njb3BlKHRoaXMuZGlhbG9nUmVmPy5uYXRpdmVFbGVtZW50IHx8IG51bGwsIHtcbiAgICAgIG9uRXNjYXBlOiB0aGlzLmNsb3NlT25Fc2MgPyAoZXZlbnQpID0+IHRoaXMuaGFuZGxlRXNjYXBlKGV2ZW50KSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICBpZiAodGhpcy5mb2N1c1Njb3BlSWQgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZm9jdXNTY29wZUlkID0gbmV4dEZvY3VzU2NvcGVJZDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbGVhc2VGb2N1c1Njb3BlKCkge1xuICAgIGlmICh0aGlzLmZvY3VzU2NvcGVJZCAhPT0gbnVsbCkge1xuICAgICAgdW5yZWdpc3Rlck1vZGFsRm9jdXNTY29wZSh0aGlzLmZvY3VzU2NvcGVJZCk7XG4gICAgICB0aGlzLmZvY3VzU2NvcGVJZCA9IG51bGw7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,247 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, EventEmitter, Input, Output, } from '@angular/core';
3
+ import { secToTimeStr } from '@algoux/standard-ranklist-utils';
4
+ import { getProgressDurationMinutes, getProgressMaxAvailableMinutes, getProgressMetrics, isProgressEnded, } from './progress-utils';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/common";
7
+ export class ProgressBarComponent {
8
+ data;
9
+ enableTimeTravel = false;
10
+ live = false;
11
+ td = 0;
12
+ timeTravel = new EventEmitter();
13
+ localTime = Date.now();
14
+ inTimeMachine = false;
15
+ timeTravelIsChanging = false;
16
+ timeTravelCurrentValue = 0;
17
+ timeTravelValue = null;
18
+ liveInterval;
19
+ ngOnInit() {
20
+ this.timeTravelCurrentValue = this.maxAvailableMinutes();
21
+ if (this.live) {
22
+ this.liveInterval = window.setInterval(() => this.handleProgressTimer(), 1000);
23
+ }
24
+ }
25
+ ngOnDestroy() {
26
+ if (this.liveInterval) {
27
+ window.clearInterval(this.liveInterval);
28
+ }
29
+ }
30
+ secToTimeStr(seconds) {
31
+ return secToTimeStr(Math.round(seconds));
32
+ }
33
+ timeLabel(minutes) {
34
+ return secToTimeStr(minutes * 60);
35
+ }
36
+ durationMinutes() {
37
+ return getProgressDurationMinutes(this.data.contest);
38
+ }
39
+ maxAvailableMinutes() {
40
+ return getProgressMaxAvailableMinutes(this.data.contest, this.localTime, this.td);
41
+ }
42
+ isEnded() {
43
+ return isProgressEnded(this.data.contest, this.localTime, this.td);
44
+ }
45
+ progressMetrics() {
46
+ return getProgressMetrics(this.data, this.localTime, this.td, this.timeTravelCurrentValue, this.inTimeMachine);
47
+ }
48
+ beginTimeTravel() {
49
+ this.timeTravelIsChanging = true;
50
+ this.inTimeMachine = true;
51
+ }
52
+ updateTimeTravelValue(event) {
53
+ this.timeTravelCurrentValue = Number(event.target.value);
54
+ }
55
+ commitTimeTravel() {
56
+ if (this.timeTravelIsChanging) {
57
+ this.handleTimeTravelChange(this.timeTravelCurrentValue);
58
+ }
59
+ }
60
+ handleProgressTimer() {
61
+ this.localTime = Date.now();
62
+ if (this.isEnded() && this.liveInterval) {
63
+ window.clearInterval(this.liveInterval);
64
+ }
65
+ if (!this.timeTravelIsChanging && this.timeTravelValue === null) {
66
+ this.timeTravelCurrentValue = this.maxAvailableMinutes();
67
+ }
68
+ }
69
+ handleTimeTravelChange(value) {
70
+ const exited = value >= this.durationMinutes() || value >= this.maxAvailableMinutes();
71
+ this.timeTravel.emit(exited ? null : value * 60 * 1000);
72
+ this.inTimeMachine = !exited;
73
+ this.timeTravelValue = exited ? null : value * 60 * 1000;
74
+ this.timeTravelIsChanging = false;
75
+ }
76
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
77
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ProgressBarComponent, isStandalone: true, selector: "srk-progress-bar", inputs: { data: "data", enableTimeTravel: "enableTimeTravel", live: "live", td: "td" }, outputs: { timeTravel: "timeTravel" }, ngImport: i0, template: `
78
+ <div class="srk-progress-bar-container">
79
+ <div class="srk-progress-bar">
80
+ <div class="srk-progress-bar-body">
81
+ <div
82
+ class="srk-progress-bar-segment srk-progress-bar-normal"
83
+ [style.width.%]="progressMetrics().frozenBreakpoint * 100"
84
+ >
85
+ <div class="srk-progress-bar-fill" [style.width.%]="progressMetrics().normalInnerPercent"></div>
86
+ </div>
87
+ <div
88
+ class="srk-progress-bar-segment srk-progress-bar-frozen"
89
+ [style.width.%]="(1 - progressMetrics().frozenBreakpoint) * 100"
90
+ >
91
+ <div class="srk-progress-bar-fill" [style.width.%]="progressMetrics().frozenInnerPercent"></div>
92
+ </div>
93
+ </div>
94
+ <div
95
+ *ngIf="enableTimeTravel && progressMetrics().supportRegen"
96
+ class="srk-progress-slider-layer"
97
+ >
98
+ <div
99
+ *ngIf="timeTravelIsChanging"
100
+ class="srk-progress-slider-tooltip"
101
+ [style.left.%]="durationMinutes() ? (timeTravelCurrentValue / durationMinutes()) * 100 : 0"
102
+ >
103
+ {{ timeLabel(timeTravelCurrentValue) }}
104
+ </div>
105
+ <input
106
+ aria-label="Time Travel"
107
+ class="srk-progress-slider"
108
+ min="0"
109
+ step="1"
110
+ type="range"
111
+ [max]="durationMinutes()"
112
+ [title]="timeLabel(timeTravelCurrentValue)"
113
+ [value]="timeTravelCurrentValue"
114
+ (blur)="commitTimeTravel()"
115
+ (input)="updateTimeTravelValue($event)"
116
+ (keydown)="beginTimeTravel()"
117
+ (keyup)="commitTimeTravel()"
118
+ (mousedown)="beginTimeTravel()"
119
+ (mouseup)="commitTimeTravel()"
120
+ (touchend)="commitTimeTravel()"
121
+ (touchstart)="beginTimeTravel()"
122
+ />
123
+ </div>
124
+ </div>
125
+ <div class="srk-progress-secondary-area">
126
+ <div
127
+ class="srk-progress-secondary-area-left"
128
+ [style.display]="live || inTimeMachine ? '' : 'none'"
129
+ >
130
+ Elapsed: {{ secToTimeStr(progressMetrics().elapsed / 1000) }}
131
+ </div>
132
+ <div class="srk-progress-secondary-area-center">
133
+ <div *ngIf="inTimeMachine" class="srk-progress-time-machine-status">
134
+ <div class="srk-progress-time-machine-text">Time Travel Mode</div>
135
+ </div>
136
+ <div *ngIf="!inTimeMachine && live && !isEnded()" class="srk-progress-live-text">
137
+ Live
138
+ </div>
139
+ <div *ngIf="!inTimeMachine && (!live || isEnded())" style="visibility: hidden">
140
+ SRK
141
+ </div>
142
+ </div>
143
+ <div
144
+ class="srk-progress-secondary-area-right"
145
+ [style.display]="live || inTimeMachine ? '' : 'none'"
146
+ >
147
+ Remaining: {{ secToTimeStr(progressMetrics().remaining / 1000) }}
148
+ </div>
149
+ </div>
150
+ </div>
151
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
152
+ }
153
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProgressBarComponent, decorators: [{
154
+ type: Component,
155
+ args: [{
156
+ selector: 'srk-progress-bar',
157
+ standalone: true,
158
+ imports: [CommonModule],
159
+ template: `
160
+ <div class="srk-progress-bar-container">
161
+ <div class="srk-progress-bar">
162
+ <div class="srk-progress-bar-body">
163
+ <div
164
+ class="srk-progress-bar-segment srk-progress-bar-normal"
165
+ [style.width.%]="progressMetrics().frozenBreakpoint * 100"
166
+ >
167
+ <div class="srk-progress-bar-fill" [style.width.%]="progressMetrics().normalInnerPercent"></div>
168
+ </div>
169
+ <div
170
+ class="srk-progress-bar-segment srk-progress-bar-frozen"
171
+ [style.width.%]="(1 - progressMetrics().frozenBreakpoint) * 100"
172
+ >
173
+ <div class="srk-progress-bar-fill" [style.width.%]="progressMetrics().frozenInnerPercent"></div>
174
+ </div>
175
+ </div>
176
+ <div
177
+ *ngIf="enableTimeTravel && progressMetrics().supportRegen"
178
+ class="srk-progress-slider-layer"
179
+ >
180
+ <div
181
+ *ngIf="timeTravelIsChanging"
182
+ class="srk-progress-slider-tooltip"
183
+ [style.left.%]="durationMinutes() ? (timeTravelCurrentValue / durationMinutes()) * 100 : 0"
184
+ >
185
+ {{ timeLabel(timeTravelCurrentValue) }}
186
+ </div>
187
+ <input
188
+ aria-label="Time Travel"
189
+ class="srk-progress-slider"
190
+ min="0"
191
+ step="1"
192
+ type="range"
193
+ [max]="durationMinutes()"
194
+ [title]="timeLabel(timeTravelCurrentValue)"
195
+ [value]="timeTravelCurrentValue"
196
+ (blur)="commitTimeTravel()"
197
+ (input)="updateTimeTravelValue($event)"
198
+ (keydown)="beginTimeTravel()"
199
+ (keyup)="commitTimeTravel()"
200
+ (mousedown)="beginTimeTravel()"
201
+ (mouseup)="commitTimeTravel()"
202
+ (touchend)="commitTimeTravel()"
203
+ (touchstart)="beginTimeTravel()"
204
+ />
205
+ </div>
206
+ </div>
207
+ <div class="srk-progress-secondary-area">
208
+ <div
209
+ class="srk-progress-secondary-area-left"
210
+ [style.display]="live || inTimeMachine ? '' : 'none'"
211
+ >
212
+ Elapsed: {{ secToTimeStr(progressMetrics().elapsed / 1000) }}
213
+ </div>
214
+ <div class="srk-progress-secondary-area-center">
215
+ <div *ngIf="inTimeMachine" class="srk-progress-time-machine-status">
216
+ <div class="srk-progress-time-machine-text">Time Travel Mode</div>
217
+ </div>
218
+ <div *ngIf="!inTimeMachine && live && !isEnded()" class="srk-progress-live-text">
219
+ Live
220
+ </div>
221
+ <div *ngIf="!inTimeMachine && (!live || isEnded())" style="visibility: hidden">
222
+ SRK
223
+ </div>
224
+ </div>
225
+ <div
226
+ class="srk-progress-secondary-area-right"
227
+ [style.display]="live || inTimeMachine ? '' : 'none'"
228
+ >
229
+ Remaining: {{ secToTimeStr(progressMetrics().remaining / 1000) }}
230
+ </div>
231
+ </div>
232
+ </div>
233
+ `,
234
+ }]
235
+ }], propDecorators: { data: [{
236
+ type: Input,
237
+ args: [{ required: true }]
238
+ }], enableTimeTravel: [{
239
+ type: Input
240
+ }], live: [{
241
+ type: Input
242
+ }], td: [{
243
+ type: Input
244
+ }], timeTravel: [{
245
+ type: Output
246
+ }] } });
247
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3Jlc3MtYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcHJvZ3Jlc3MvcHJvZ3Jlc3MtYmFyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDL0QsT0FBTyxFQUNMLDBCQUEwQixFQUMxQiw4QkFBOEIsRUFDOUIsa0JBQWtCLEVBQ2xCLGVBQWUsR0FDaEIsTUFBTSxrQkFBa0IsQ0FBQzs7O0FBa0YxQixNQUFNLE9BQU8sb0JBQW9CO0lBQ0osSUFBSSxDQUFnQjtJQUN0QyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFDekIsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUNiLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFFTixVQUFVLEdBQUcsSUFBSSxZQUFZLEVBQWlCLENBQUM7SUFFekQsU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QixhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLG9CQUFvQixHQUFHLEtBQUssQ0FBQztJQUM3QixzQkFBc0IsR0FBRyxDQUFDLENBQUM7SUFDM0IsZUFBZSxHQUFrQixJQUFJLENBQUM7SUFFOUIsWUFBWSxDQUFVO0lBRTlCLFFBQVE7UUFDTixJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDekQsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFF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QUUsR0FBRyxJQUFJLENBQUM7UUFDekQsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQztJQUNwQyxDQUFDO3dHQTFGVSxvQkFBb0I7NEZBQXBCLG9CQUFvQiwyTUE1RXJCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBFVCwyREEzRVMsWUFBWTs7NEZBNkVYLG9CQUFvQjtrQkFoRmhDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGtCQUFrQjtvQkFDNUIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQztvQkFDdkIsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBFVDtpQkFDRjs4QkFFNEIsSUFBSTtzQkFBOUIsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBQ2hCLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csRUFBRTtzQkFBVixLQUFLO2dCQUVJLFVBQVU7c0JBQW5CLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSAqIGFzIHNyayBmcm9tICdAYWxnb3V4L3N0YW5kYXJkLXJhbmtsaXN0JztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgc2VjVG9UaW1lU3RyIH0gZnJvbSAnQGFsZ291eC9zdGFuZGFyZC1yYW5rbGlzdC11dGlscyc7XG5pbXBvcnQge1xuICBnZXRQcm9ncmVzc0R1cmF0aW9uTWludXRlcyxcbiAgZ2V0UHJvZ3Jlc3NNYXhBdmFpbGFibGVNaW51dGVzLFxuICBnZXRQcm9ncmVzc01ldHJpY3MsXG4gIGlzUHJvZ3Jlc3NFbmRlZCxcbn0gZnJvbSAnLi9wcm9ncmVzcy11dGlscyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3Nyay1wcm9ncmVzcy1iYXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwic3JrLXByb2dyZXNzLWJhci1jb250YWluZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzcmstcHJvZ3Jlc3MtYmFyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzcmstcHJvZ3Jlc3MtYmFyLWJvZHlcIj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cInNyay1wcm9ncmVzcy1iYXItc2VnbWVudCBzcmstcHJvZ3Jlc3MtYmFyLW5vcm1hbFwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJwcm9ncmVzc01ldHJpY3MoKS5mcm96ZW5CcmVha3BvaW50ICogMTAwXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3JrLXByb2dyZXNzLWJhci1maWxsXCIgW3N0eWxlLndpZHRoLiVdPVwicHJvZ3Jlc3NNZXRyaWNzKCkubm9ybWFsSW5uZXJQZXJjZW50XCI+PC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJzcmstcHJvZ3Jlc3MtYmFyLXNlZ21lbnQgc3JrLXByb2dyZXNzLWJhci1mcm96ZW5cIlxuICAgICAgICAgICAgW3N0eWxlLndpZHRoLiVdPVwiKDEgLSBwcm9ncmVzc01ldHJpY3MoKS5mcm96ZW5CcmVha3BvaW50KSAqIDEwMFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNyay1wcm9ncmVzcy1iYXItZmlsbFwiIFtzdHlsZS53aWR0aC4lXT1cInByb2dyZXNzTWV0cmljcygpLmZyb3plbklubmVyUGVyY2VudFwiPjwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICpuZ0lmPVwiZW5hYmxlVGltZVRyYXZlbCAmJiBwcm9ncmVzc01ldHJpY3MoKS5zdXBwb3J0UmVnZW5cIlxuICAgICAgICAgIGNsYXNzPVwic3JrLXByb2dyZXNzLXNsaWRlci1sYXllclwiXG4gICAgICAgID5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAqbmdJZj1cInRpbWVUcmF2ZWxJc0NoYW5naW5nXCJcbiAgICAgICAgICAgIGNsYXNzPVwic3JrLXByb2dyZXNzLXNsaWRlci10b29sdGlwXCJcbiAgICAgICAgICAgIFtzdHlsZS5sZWZ0LiVdPVwiZHVyYXRpb25NaW51dGVzKCkgPyAodGltZVRyYXZlbEN1cnJlbnRWYWx1ZSAvIGR1cmF0aW9uTWludXRlcygpKSAqIDEwMCA6IDBcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7IHRpbWVMYWJlbCh0aW1lVHJhdmVsQ3VycmVudFZhbHVlKSB9fVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgYXJpYS1sYWJlbD1cIlRpbWUgVHJhdmVsXCJcbiAgICAgICAgICAgIGNsYXNzPVwic3JrLXByb2dyZXNzLXNsaWRlclwiXG4gICAgICAgICAgICBtaW49XCIwXCJcbiAgICAgICAgICAgIHN0ZXA9XCIxXCJcbiAgICAgICAgICAgIHR5cGU9XCJyYW5nZVwiXG4gICAgICAgICAgICBbbWF4XT1cImR1cmF0aW9uTWludXRlcygpXCJcbiAgICAgICAgICAgIFt0aXRsZV09XCJ0aW1lTGFiZWwodGltZVRyYXZlbEN1cnJlbnRWYWx1ZSlcIlxuICAgICAgICAgICAgW3ZhbHVlXT1cInRpbWVUcmF2ZWxDdXJyZW50VmFsdWVcIlxuICAgICAgICAgICAgKGJsdXIpPVwiY29tbWl0VGltZVRyYXZlbCgpXCJcbiAgICAgICAgICAgIChpbnB1dCk9XCJ1cGRhdGVUaW1lVHJhdmVsVmFsdWUoJGV2ZW50KVwiXG4gICAgICAgICAgICAoa2V5ZG93bik9XCJiZWdpblRpbWVUcmF2ZWwoKVwiXG4gICAgICAgICAgICAoa2V5dXApPVwiY29tbWl0VGltZVRyYXZlbCgpXCJcbiAgICAgICAgICAgIChtb3VzZWRvd24pPVwiYmVnaW5UaW1lVHJhdmVsKClcIlxuICAgICAgICAgICAgKG1vdXNldXApPVwiY29tbWl0VGltZVRyYXZlbCgpXCJcbiAgICAgICAgICAgICh0b3VjaGVuZCk9XCJjb21taXRUaW1lVHJhdmVsKClcIlxuICAgICAgICAgICAgKHRvdWNoc3RhcnQpPVwiYmVnaW5UaW1lVHJhdmVsKClcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic3JrLXByb2dyZXNzLXNlY29uZGFyeS1hcmVhXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cInNyay1wcm9ncmVzcy1zZWNvbmRhcnktYXJlYS1sZWZ0XCJcbiAgICAgICAgICBbc3R5bGUuZGlzcGxheV09XCJsaXZlIHx8IGluVGltZU1hY2hpbmUgPyAnJyA6ICdub25lJ1wiXG4gICAgICAgID5cbiAgICAgICAgICBFbGFwc2VkOiB7eyBzZWNUb1RpbWVTdHIocHJvZ3Jlc3NNZXRyaWNzKCkuZWxhcHNlZCAvIDEwMDApIH19XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwic3JrLXByb2dyZXNzLXNlY29uZGFyeS1hcmVhLWNlbnRlclwiPlxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJpblRpbWVNYWNoaW5lXCIgY2xhc3M9XCJzcmstcHJvZ3Jlc3MtdGltZS1tYWNoaW5lLXN0YXR1c1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNyay1wcm9ncmVzcy10aW1lLW1hY2hpbmUtdGV4dFwiPlRpbWUgVHJhdmVsIE1vZGU8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWluVGltZU1hY2hpbmUgJiYgbGl2ZSAmJiAhaXNFbmRlZCgpXCIgY2xhc3M9XCJzcmstcHJvZ3Jlc3MtbGl2ZS10ZXh0XCI+XG4gICAgICAgICAgICBMaXZlXG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cIiFpblRpbWVNYWNoaW5lICYmICghbGl2ZSB8fCBpc0VuZGVkKCkpXCIgc3R5bGU9XCJ2aXNpYmlsaXR5OiBoaWRkZW5cIj5cbiAgICAgICAgICAgIFNSS1xuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzPVwic3JrLXByb2dyZXNzLXNlY29uZGFyeS1hcmVhLXJpZ2h0XCJcbiAgICAgICAgICBbc3R5bGUuZGlzcGxheV09XCJsaXZlIHx8IGluVGltZU1hY2hpbmUgPyAnJyA6ICdub25lJ1wiXG4gICAgICAgID5cbiAgICAgICAgICBSZW1haW5pbmc6IHt7IHNlY1RvVGltZVN0cihwcm9ncmVzc01ldHJpY3MoKS5yZW1haW5pbmcgLyAxMDAwKSB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBQcm9ncmVzc0JhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgZGF0YSE6IHNyay5SYW5rbGlzdDtcbiAgQElucHV0KCkgZW5hYmxlVGltZVRyYXZlbCA9IGZhbHNlO1xuICBASW5wdXQoKSBsaXZlID0gZmFsc2U7XG4gIEBJbnB1dCgpIHRkID0gMDtcblxuICBAT3V0cHV0KCkgdGltZVRyYXZlbCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyIHwgbnVsbD4oKTtcblxuICBsb2NhbFRpbWUgPSBEYXRlLm5vdygpO1xuICBpblRpbWVNYWNoaW5lID0gZmFsc2U7XG4gIHRpbWVUcmF2ZWxJc0NoYW5naW5nID0gZmFsc2U7XG4gIHRpbWVUcmF2ZWxDdXJyZW50VmFsdWUgPSAwO1xuICB0aW1lVHJhdmVsVmFsdWU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgbGl2ZUludGVydmFsPzogbnVtYmVyO1xuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMudGltZVRyYXZlbEN1cnJlbnRWYWx1ZSA9IHRoaXMubWF4QXZhaWxhYmxlTWludXRlcygpO1xuICAgIGlmICh0aGlzLmxpdmUpIHtcbiAgICAgIHRoaXMubGl2ZUludGVydmFsID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHRoaXMuaGFuZGxlUHJvZ3Jlc3NUaW1lcigpLCAxMDAwKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5saXZlSW50ZXJ2YWwpIHtcbiAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKHRoaXMubGl2ZUludGVydmFsKTtcbiAgICB9XG4gIH1cblxuICBzZWNUb1RpbWVTdHIoc2Vjb25kczogbnVtYmVyKSB7XG4gICAgcmV0dXJuIHNlY1RvVGltZVN0cihNYXRoLnJvdW5kKHNlY29uZHMpKTtcbiAgfVxuXG4gIHRpbWVMYWJlbChtaW51dGVzOiBudW1iZXIpIHtcbiAgICByZXR1cm4gc2VjVG9UaW1lU3RyKG1pbnV0ZXMgKiA2MCk7XG4gIH1cblxuICBkdXJhdGlvbk1pbnV0ZXMoKSB7XG4gICAgcmV0dXJuIGdldFByb2dyZXNzRHVyYXRpb25NaW51dGVzKHRoaXMuZGF0YS5jb250ZXN0KTtcbiAgfVxuXG4gIG1heEF2YWlsYWJsZU1pbnV0ZXMoKSB7XG4gICAgcmV0dXJuIGdldFByb2dyZXNzTWF4QXZhaWxhYmxlTWludXRlcyh0aGlzLmRhdGEuY29udGVzdCwgdGhpcy5sb2NhbFRpbWUsIHRoaXMudGQpO1xuICB9XG5cbiAgaXNFbmRlZCgpIHtcbiAgICByZXR1cm4gaXNQcm9ncmVzc0VuZGVkKHRoaXMuZGF0YS5jb250ZXN0LCB0aGlzLmxvY2FsVGltZSwgdGhpcy50ZCk7XG4gIH1cblxuICBwcm9ncmVzc01ldHJpY3MoKSB7XG4gICAgcmV0dXJuIGdldFByb2dyZXNzTWV0cmljcyhcbiAgICAgIHRoaXMuZGF0YSxcbiAgICAgIHRoaXMubG9jYWxUaW1lLFxuICAgICAgdGhpcy50ZCxcbiAgICAgIHRoaXMudGltZVRyYXZlbEN1cnJlbnRWYWx1ZSxcbiAgICAgIHRoaXMuaW5UaW1lTWFjaGluZSxcbiAgICApO1xuICB9XG5cbiAgYmVnaW5UaW1lVHJhdmVsKCkge1xuICAgIHRoaXMudGltZVRyYXZlbElzQ2hhbmdpbmcgPSB0cnVlO1xuICAgIHRoaXMuaW5UaW1lTWFjaGluZSA9IHRydWU7XG4gIH1cblxuICB1cGRhdGVUaW1lVHJhdmVsVmFsdWUoZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy50aW1lVHJhdmVsQ3VycmVudFZhbHVlID0gTnVtYmVyKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUpO1xuICB9XG5cbiAgY29tbWl0VGltZVRyYXZlbCgpIHtcbiAgICBpZiAodGhpcy50aW1lVHJhdmVsSXNDaGFuZ2luZykge1xuICAgICAgdGhpcy5oYW5kbGVUaW1lVHJhdmVsQ2hhbmdlKHRoaXMudGltZVRyYXZlbEN1cnJlbnRWYWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVQcm9ncmVzc1RpbWVyKCkge1xuICAgIHRoaXMubG9jYWxUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBpZiAodGhpcy5pc0VuZGVkKCkgJiYgdGhpcy5saXZlSW50ZXJ2YWwpIHtcbiAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKHRoaXMubGl2ZUludGVydmFsKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnRpbWVUcmF2ZWxJc0NoYW5naW5nICYmIHRoaXMudGltZVRyYXZlbFZhbHVlID09PSBudWxsKSB7XG4gICAgICB0aGlzLnRpbWVUcmF2ZWxDdXJyZW50VmFsdWUgPSB0aGlzLm1heEF2YWlsYWJsZU1pbnV0ZXMoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVRpbWVUcmF2ZWxDaGFuZ2UodmFsdWU6IG51bWJlcikge1xuICAgIGNvbnN0IGV4aXRlZCA9IHZhbHVlID49IHRoaXMuZHVyYXRpb25NaW51dGVzKCkgfHwgdmFsdWUgPj0gdGhpcy5tYXhBdmFpbGFibGVNaW51dGVzKCk7XG4gICAgdGhpcy50aW1lVHJhdmVsLmVtaXQoZXhpdGVkID8gbnVsbCA6IHZhbHVlICogNjAgKiAxMDAwKTtcbiAgICB0aGlzLmluVGltZU1hY2hpbmUgPSAhZXhpdGVkO1xuICAgIHRoaXMudGltZVRyYXZlbFZhbHVlID0gZXhpdGVkID8gbnVsbCA6IHZhbHVlICogNjAgKiAxMDAwO1xuICAgIHRoaXMudGltZVRyYXZlbElzQ2hhbmdpbmcgPSBmYWxzZTtcbiAgfVxufVxuIl19
@@ -0,0 +1,45 @@
1
+ import { canRegenerateRanklist, formatTimeDuration, } from '@algoux/standard-ranklist-utils';
2
+ export function getProgressDurationMinutes(contest) {
3
+ return formatTimeDuration(contest.duration, 'min');
4
+ }
5
+ export function getProgressMaxAvailableMinutes(contest, localTime, td = 0) {
6
+ const startAt = new Date(contest.startAt).getTime();
7
+ const currentTime = localTime - td;
8
+ return Math.min(Math.max(Math.floor((currentTime - startAt) / 60000), 0), getProgressDurationMinutes(contest));
9
+ }
10
+ export function isProgressEnded(contest, localTime, td = 0) {
11
+ const startAt = new Date(contest.startAt).getTime();
12
+ const endAt = startAt + formatTimeDuration(contest.duration, 'ms');
13
+ const currentTime = localTime - td;
14
+ return currentTime >= endAt;
15
+ }
16
+ export function getProgressMetrics(data, localTime, td, timeTravelCurrentValue, inTimeMachine) {
17
+ const { contest } = data;
18
+ const startAt = new Date(contest.startAt).getTime();
19
+ const endAt = startAt + formatTimeDuration(contest.duration, 'ms');
20
+ const frozenLength = contest.frozenDuration ? formatTimeDuration(contest.frozenDuration, 'ms') : 0;
21
+ const currentTime = localTime - td;
22
+ const length = endAt - startAt;
23
+ const frozenBreakpoint = length ? 1 - frozenLength / length : 1;
24
+ const elapsed = Math.min(Math.max(currentTime - startAt, 0), length);
25
+ const remaining = length - elapsed;
26
+ const frozenAt = endAt - frozenLength;
27
+ const percent = length ? (elapsed / length) * 100 : 0;
28
+ const normalPercent = length ? (Math.max(Math.min(currentTime, frozenAt) - startAt, 0) / length) * 100 : 0;
29
+ const normalInnerPercent = Math.min(100, frozenBreakpoint ? normalPercent / frozenBreakpoint : 0);
30
+ const frozenPercent = percent - normalPercent;
31
+ const frozenInnerPercent = Math.min(100, 1 - frozenBreakpoint ? frozenPercent / (1 - frozenBreakpoint) : 0);
32
+ const timeTravelElapsed = timeTravelCurrentValue * 60 * 1000;
33
+ const timeTravelRemaining = length - timeTravelElapsed;
34
+ return {
35
+ elapsed: inTimeMachine ? timeTravelElapsed : elapsed,
36
+ remaining: inTimeMachine ? timeTravelRemaining : remaining,
37
+ frozenBreakpoint,
38
+ normalInnerPercent,
39
+ frozenInnerPercent,
40
+ timeTravelElapsed,
41
+ timeTravelRemaining,
42
+ supportRegen: canRegenerateRanklist(data),
43
+ };
44
+ }
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3Jlc3MtdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Byb2dyZXNzL3Byb2dyZXNzLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsa0JBQWtCLEdBQ25CLE1BQU0saUNBQWlDLENBQUM7QUFhekMsTUFBTSxVQUFVLDBCQUEwQixDQUFDLE9BQW9CO0lBQzdELE9BQU8sa0JBQWtCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBRUQsTUFBTSxVQUFVLDhCQUE4QixDQUFDLE9BQW9CLEVBQUUsU0FBaUIsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUM1RixNQUFNLE9BQU8sR0FBRyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEQsTUFBTSxXQUFXLEdBQUcsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUNuQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDakgsQ0FBQztBQUVELE1BQU0sVUFBVSxlQUFlLENBQUMsT0FBb0IsRUFBRSxTQUFpQixFQUFFLEVBQUUsR0FBRyxDQUFDO0lBQzdFLE1BQU0sT0FBTyxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNwRCxNQUFNLEtBQUssR0FBRyxPQUFPLEdBQUcsa0JBQWtCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNuRSxNQUFNLFdBQVcsR0FBRyxTQUFTLEdB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IHR5cGUgKiBhcyBzcmsgZnJvbSAnQGFsZ291eC9zdGFuZGFyZC1yYW5rbGlzdCc7XG5pbXBvcnQge1xuICBjYW5SZWdlbmVyYXRlUmFua2xpc3QsXG4gIGZvcm1hdFRpbWVEdXJhdGlvbixcbn0gZnJvbSAnQGFsZ291eC9zdGFuZGFyZC1yYW5rbGlzdC11dGlscyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJvZ3Jlc3NNZXRyaWNzIHtcbiAgZWxhcHNlZDogbnVtYmVyO1xuICByZW1haW5pbmc6IG51bWJlcjtcbiAgZnJvemVuQnJlYWtwb2ludDogbnVtYmVyO1xuICBub3JtYWxJbm5lclBlcmNlbnQ6IG51bWJlcjtcbiAgZnJvemVuSW5uZXJQZXJjZW50OiBudW1iZXI7XG4gIHRpbWVUcmF2ZWxFbGFwc2VkOiBudW1iZXI7XG4gIHRpbWVUcmF2ZWxSZW1haW5pbmc6IG51bWJlcjtcbiAgc3VwcG9ydFJlZ2VuOiBib29sZWFuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJvZ3Jlc3NEdXJhdGlvbk1pbnV0ZXMoY29udGVzdDogc3JrLkNvbnRlc3QpOiBudW1iZXIge1xuICByZXR1cm4gZm9ybWF0VGltZUR1cmF0aW9uKGNvbnRlc3QuZHVyYXRpb24sICdtaW4nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2dyZXNzTWF4QXZhaWxhYmxlTWludXRlcyhjb250ZXN0OiBzcmsuQ29udGVzdCwgbG9jYWxUaW1lOiBudW1iZXIsIHRkID0gMCk6IG51bWJlciB7XG4gIGNvbnN0IHN0YXJ0QXQgPSBuZXcgRGF0ZShjb250ZXN0LnN0YXJ0QXQpLmdldFRpbWUoKTtcbiAgY29uc3QgY3VycmVudFRpbWUgPSBsb2NhbFRpbWUgLSB0ZDtcbiAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KE1hdGguZmxvb3IoKGN1cnJlbnRUaW1lIC0gc3RhcnRBdCkgLyA2MDAwMCksIDApLCBnZXRQcm9ncmVzc0R1cmF0aW9uTWludXRlcyhjb250ZXN0KSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Byb2dyZXNzRW5kZWQoY29udGVzdDogc3JrLkNvbnRlc3QsIGxvY2FsVGltZTogbnVtYmVyLCB0ZCA9IDApOiBib29sZWFuIHtcbiAgY29uc3Qgc3RhcnRBdCA9IG5ldyBEYXRlKGNvbnRlc3Quc3RhcnRBdCkuZ2V0VGltZSgpO1xuICBjb25zdCBlbmRBdCA9IHN0YXJ0QXQgKyBmb3JtYXRUaW1lRHVyYXRpb24oY29udGVzdC5kdXJhdGlvbiwgJ21zJyk7XG4gIGNvbnN0IGN1cnJlbnRUaW1lID0gbG9jYWxUaW1lIC0gdGQ7XG4gIHJldHVybiBjdXJyZW50VGltZSA+PSBlbmRBdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2dyZXNzTWV0cmljcyhcbiAgZGF0YTogc3JrLlJhbmtsaXN0LFxuICBsb2NhbFRpbWU6IG51bWJlcixcbiAgdGQ6IG51bWJlcixcbiAgdGltZVRyYXZlbEN1cnJlbnRWYWx1ZTogbnVtYmVyLFxuICBpblRpbWVNYWNoaW5lOiBib29sZWFuLFxuKTogUHJvZ3Jlc3NNZXRyaWNzIHtcbiAgY29uc3QgeyBjb250ZXN0IH0gPSBkYXRhO1xuICBjb25zdCBzdGFydEF0ID0gbmV3IERhdGUoY29udGVzdC5zdGFydEF0KS5nZXRUaW1lKCk7XG4gIGNvbnN0IGVuZEF0ID0gc3RhcnRBdCArIGZvcm1hdFRpbWVEdXJhdGlvbihjb250ZXN0LmR1cmF0aW9uLCAnbXMnKTtcbiAgY29uc3QgZnJvemVuTGVuZ3RoID0gY29udGVzdC5mcm96ZW5EdXJhdGlvbiA/IGZvcm1hdFRpbWVEdXJhdGlvbihjb250ZXN0LmZyb3plbkR1cmF0aW9uLCAnbXMnKSA6IDA7XG4gIGNvbnN0IGN1cnJlbnRUaW1lID0gbG9jYWxUaW1lIC0gdGQ7XG4gIGNvbnN0IGxlbmd0aCA9IGVuZEF0IC0gc3RhcnRBdDtcbiAgY29uc3QgZnJvemVuQnJlYWtwb2ludCA9IGxlbmd0aCA/IDEgLSBmcm96ZW5MZW5ndGggLyBsZW5ndGggOiAxO1xuICBjb25zdCBlbGFwc2VkID0gTWF0aC5taW4oTWF0aC5tYXgoY3VycmVudFRpbWUgLSBzdGFydEF0LCAwKSwgbGVuZ3RoKTtcbiAgY29uc3QgcmVtYWluaW5nID0gbGVuZ3RoIC0gZWxhcHNlZDtcbiAgY29uc3QgZnJvemVuQXQgPSBlbmRBdCAtIGZyb3plbkxlbmd0aDtcbiAgY29uc3QgcGVyY2VudCA9IGxlbmd0aCA/IChlbGFwc2VkIC8gbGVuZ3RoKSAqIDEwMCA6IDA7XG4gIGNvbnN0IG5vcm1hbFBlcmNlbnQgPSBsZW5ndGggPyAoTWF0aC5tYXgoTWF0aC5taW4oY3VycmVudFRpbWUsIGZyb3plbkF0KSAtIHN0YXJ0QXQsIDApIC8gbGVuZ3RoKSAqIDEwMCA6IDA7XG4gIGNvbnN0IG5vcm1hbElubmVyUGVyY2VudCA9IE1hdGgubWluKDEwMCwgZnJvemVuQnJlYWtwb2ludCA/IG5vcm1hbFBlcmNlbnQgLyBmcm96ZW5CcmVha3BvaW50IDogMCk7XG4gIGNvbnN0IGZyb3plblBlcmNlbnQgPSBwZXJjZW50IC0gbm9ybWFsUGVyY2VudDtcbiAgY29uc3QgZnJvemVuSW5uZXJQZXJjZW50ID0gTWF0aC5taW4oMTAwLCAxIC0gZnJvemVuQnJlYWtwb2ludCA/IGZyb3plblBlcmNlbnQgLyAoMSAtIGZyb3plbkJyZWFrcG9pbnQpIDogMCk7XG4gIGNvbnN0IHRpbWVUcmF2ZWxFbGFwc2VkID0gdGltZVRyYXZlbEN1cnJlbnRWYWx1ZSAqIDYwICogMTAwMDtcbiAgY29uc3QgdGltZVRyYXZlbFJlbWFpbmluZyA9IGxlbmd0aCAtIHRpbWVUcmF2ZWxFbGFwc2VkO1xuXG4gIHJldHVybiB7XG4gICAgZWxhcHNlZDogaW5UaW1lTWFjaGluZSA/IHRpbWVUcmF2ZWxFbGFwc2VkIDogZWxhcHNlZCxcbiAgICByZW1haW5pbmc6IGluVGltZU1hY2hpbmUgPyB0aW1lVHJhdmVsUmVtYWluaW5nIDogcmVtYWluaW5nLFxuICAgIGZyb3plbkJyZWFrcG9pbnQsXG4gICAgbm9ybWFsSW5uZXJQZXJjZW50LFxuICAgIGZyb3plbklubmVyUGVyY2VudCxcbiAgICB0aW1lVHJhdmVsRWxhcHNlZCxcbiAgICB0aW1lVHJhdmVsUmVtYWluaW5nLFxuICAgIHN1cHBvcnRSZWdlbjogY2FuUmVnZW5lcmF0ZVJhbmtsaXN0KGRhdGEpLFxuICB9O1xufVxuIl19