@algoux/standard-ranklist-renderer-component-angular 0.5.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 +21 -0
- package/README.md +100 -0
- package/dist/README.md +100 -0
- package/dist/esm2022/algoux-standard-ranklist-renderer-component-angular.mjs +5 -0
- package/dist/esm2022/lib/index.mjs +8 -0
- package/dist/esm2022/lib/modal/default-solution-modal.component.mjs +146 -0
- package/dist/esm2022/lib/modal/default-user-modal.component.mjs +172 -0
- package/dist/esm2022/lib/modal/modal-interactions.mjs +2 -0
- package/dist/esm2022/lib/modal/modal.component.mjs +263 -0
- package/dist/esm2022/lib/progress/progress-bar.component.mjs +247 -0
- package/dist/esm2022/lib/progress/progress-utils.mjs +45 -0
- package/dist/esm2022/lib/ranklist/ranklist-utils.mjs +110 -0
- package/dist/esm2022/lib/ranklist/ranklist.component.mjs +593 -0
- package/dist/esm2022/lib/ranklist/status-cell-template.directive.mjs +18 -0
- package/dist/esm2022/lib/ranklist/user-cell-template.directive.mjs +18 -0
- package/dist/esm2022/lib/types.mjs +2 -0
- package/dist/esm2022/public-api.mjs +2 -0
- package/dist/fesm2022/algoux-standard-ranklist-renderer-component-angular.mjs +1585 -0
- package/dist/fesm2022/algoux-standard-ranklist-renderer-component-angular.mjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/index.d.ts +8 -0
- package/dist/lib/modal/default-solution-modal.component.d.ts +30 -0
- package/dist/lib/modal/default-user-modal.component.d.ts +34 -0
- package/dist/lib/modal/modal-interactions.d.ts +1 -0
- package/dist/lib/modal/modal.component.d.ts +49 -0
- package/dist/lib/progress/progress-bar.component.d.ts +31 -0
- package/dist/lib/progress/progress-utils.d.ts +15 -0
- package/dist/lib/ranklist/ranklist-utils.d.ts +22 -0
- package/dist/lib/ranklist/ranklist.component.d.ts +57 -0
- package/dist/lib/ranklist/status-cell-template.directive.d.ts +23 -0
- package/dist/lib/ranklist/user-cell-template.directive.d.ts +20 -0
- package/dist/lib/types.d.ts +27 -0
- package/dist/public-api.d.ts +1 -0
- package/package.json +57 -0
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3Jlc3MtdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Byb2dyZXNzL3Byb2dyZXNzLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsa0JBQWtCLEdBQ25CLE1BQU0saUNBQWlDLENBQUM7QUFhekMsTUFBTSxVQUFVLDBCQUEwQixDQUFDLE9BQW9CO0lBQzdELE9BQU8sa0JBQWtCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBRUQsTUFBTSxVQUFVLDhCQUE4QixDQUFDLE9BQW9CLEVBQUUsU0FBaUIsRUFBRSxFQUFFLEdBQUcsQ0FBQztJQUM1RixNQUFNLE9BQU8sR0FBRyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDcEQsTUFBTSxXQUFXLEdBQUcsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUNuQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDakgsQ0FBQztBQUVELE1BQU0sVUFBVSxlQUFlLENBQUMsT0FBb0IsRUFBRSxTQUFpQixFQUFFLEVBQUUsR0FBRyxDQUFDO0lBQzdFLE1BQU0sT0FBTyxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNwRCxNQUFNLEtBQUssR0FBRyxPQUFPLEdBQUcsa0JBQWtCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNuRSxNQUFNLFdBQVcsR0FBRyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ25DLE9BQU8sV0FBVyxJQUFJLEtBQUssQ0FBQztBQUM5QixDQUFDO0FBRUQsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxJQUFrQixFQUNsQixTQUFpQixFQUNqQixFQUFVLEVBQ1Ysc0JBQThCLEVBQzlCLGFBQXNCO0lBRXRCLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3BELE1BQU0sS0FBSyxHQUFHLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25FLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRyxNQUFNLFdBQVcsR0FBRyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ25DLE1BQU0sTUFBTSxHQUFHLEtBQUssR0FBRyxPQUFPLENBQUM7SUFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxZQUFZLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsR0FBRyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDckUsTUFBTSxTQUFTLEdBQUcsTUFBTSxHQUFHLE9BQU8sQ0FBQztJQUNuQyxNQUFNLFFBQVEsR0FBRyxLQUFLLEdBQUcsWUFBWSxDQUFDO0lBQ3RDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLEdBQUcsT0FBTyxFQUFFLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNHLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLGFBQWEsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEcsTUFBTSxhQUFhLEdBQUcsT0FBTyxHQUFHLGFBQWEsQ0FBQztJQUM5QyxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQyxHQUFHLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVHLE1BQU0saUJBQWlCLEdBQUcsc0JBQXNCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztJQUM3RCxNQUFNLG1CQUFtQixHQUFHLE1BQU0sR0FBRyxpQkFBaUIsQ0FBQztJQUV2RCxPQUFPO1FBQ0wsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLE9BQU87UUFDcEQsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLFNBQVM7UUFDMUQsZ0JBQWdCO1FBQ2hCLGtCQUFrQjtRQUNsQixrQkFBa0I7UUFDbEIsaUJBQWlCO1FBQ2pCLG1CQUFtQjtRQUNuQixZQUFZLEVBQUUscUJBQXFCLENBQUMsSUFBSSxDQUFDO0tBQzFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBzcmsgZnJvbSAnQGFsZ291eC9zdGFuZGFyZC1yYW5rbGlzdCc7XG5pbXBvcnQge1xuICBjYW5SZWdlbmVyYXRlUmFua2xpc3QsXG4gIGZvcm1hdFRpbWVEdXJhdGlvbixcbn0gZnJvbSAnQGFsZ291eC9zdGFuZGFyZC1yYW5rbGlzdC11dGlscyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJvZ3Jlc3NNZXRyaWNzIHtcbiAgZWxhcHNlZDogbnVtYmVyO1xuICByZW1haW5pbmc6IG51bWJlcjtcbiAgZnJvemVuQnJlYWtwb2ludDogbnVtYmVyO1xuICBub3JtYWxJbm5lclBlcmNlbnQ6IG51bWJlcjtcbiAgZnJvemVuSW5uZXJQZXJjZW50OiBudW1iZXI7XG4gIHRpbWVUcmF2ZWxFbGFwc2VkOiBudW1iZXI7XG4gIHRpbWVUcmF2ZWxSZW1haW5pbmc6IG51bWJlcjtcbiAgc3VwcG9ydFJlZ2VuOiBib29sZWFuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJvZ3Jlc3NEdXJhdGlvbk1pbnV0ZXMoY29udGVzdDogc3JrLkNvbnRlc3QpOiBudW1iZXIge1xuICByZXR1cm4gZm9ybWF0VGltZUR1cmF0aW9uKGNvbnRlc3QuZHVyYXRpb24sICdtaW4nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2dyZXNzTWF4QXZhaWxhYmxlTWludXRlcyhjb250ZXN0OiBzcmsuQ29udGVzdCwgbG9jYWxUaW1lOiBudW1iZXIsIHRkID0gMCk6IG51bWJlciB7XG4gIGNvbnN0IHN0YXJ0QXQgPSBuZXcgRGF0ZShjb250ZXN0LnN0YXJ0QXQpLmdldFRpbWUoKTtcbiAgY29uc3QgY3VycmVudFRpbWUgPSBsb2NhbFRpbWUgLSB0ZDtcbiAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KE1hdGguZmxvb3IoKGN1cnJlbnRUaW1lIC0gc3RhcnRBdCkgLyA2MDAwMCksIDApLCBnZXRQcm9ncmVzc0R1cmF0aW9uTWludXRlcyhjb250ZXN0KSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Byb2dyZXNzRW5kZWQoY29udGVzdDogc3JrLkNvbnRlc3QsIGxvY2FsVGltZTogbnVtYmVyLCB0ZCA9IDApOiBib29sZWFuIHtcbiAgY29uc3Qgc3RhcnRBdCA9IG5ldyBEYXRlKGNvbnRlc3Quc3RhcnRBdCkuZ2V0VGltZSgpO1xuICBjb25zdCBlbmRBdCA9IHN0YXJ0QXQgKyBmb3JtYXRUaW1lRHVyYXRpb24oY29udGVzdC5kdXJhdGlvbiwgJ21zJyk7XG4gIGNvbnN0IGN1cnJlbnRUaW1lID0gbG9jYWxUaW1lIC0gdGQ7XG4gIHJldHVybiBjdXJyZW50VGltZSA+PSBlbmRBdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2dyZXNzTWV0cmljcyhcbiAgZGF0YTogc3JrLlJhbmtsaXN0LFxuICBsb2NhbFRpbWU6IG51bWJlcixcbiAgdGQ6IG51bWJlcixcbiAgdGltZVRyYXZlbEN1cnJlbnRWYWx1ZTogbnVtYmVyLFxuICBpblRpbWVNYWNoaW5lOiBib29sZWFuLFxuKTogUHJvZ3Jlc3NNZXRyaWNzIHtcbiAgY29uc3QgeyBjb250ZXN0IH0gPSBkYXRhO1xuICBjb25zdCBzdGFydEF0ID0gbmV3IERhdGUoY29udGVzdC5zdGFydEF0KS5nZXRUaW1lKCk7XG4gIGNvbnN0IGVuZEF0ID0gc3RhcnRBdCArIGZvcm1hdFRpbWVEdXJhdGlvbihjb250ZXN0LmR1cmF0aW9uLCAnbXMnKTtcbiAgY29uc3QgZnJvemVuTGVuZ3RoID0gY29udGVzdC5mcm96ZW5EdXJhdGlvbiA/IGZvcm1hdFRpbWVEdXJhdGlvbihjb250ZXN0LmZyb3plbkR1cmF0aW9uLCAnbXMnKSA6IDA7XG4gIGNvbnN0IGN1cnJlbnRUaW1lID0gbG9jYWxUaW1lIC0gdGQ7XG4gIGNvbnN0IGxlbmd0aCA9IGVuZEF0IC0gc3RhcnRBdDtcbiAgY29uc3QgZnJvemVuQnJlYWtwb2ludCA9IGxlbmd0aCA/IDEgLSBmcm96ZW5MZW5ndGggLyBsZW5ndGggOiAxO1xuICBjb25zdCBlbGFwc2VkID0gTWF0aC5taW4oTWF0aC5tYXgoY3VycmVudFRpbWUgLSBzdGFydEF0LCAwKSwgbGVuZ3RoKTtcbiAgY29uc3QgcmVtYWluaW5nID0gbGVuZ3RoIC0gZWxhcHNlZDtcbiAgY29uc3QgZnJvemVuQXQgPSBlbmRBdCAtIGZyb3plbkxlbmd0aDtcbiAgY29uc3QgcGVyY2VudCA9IGxlbmd0aCA/IChlbGFwc2VkIC8gbGVuZ3RoKSAqIDEwMCA6IDA7XG4gIGNvbnN0IG5vcm1hbFBlcmNlbnQgPSBsZW5ndGggPyAoTWF0aC5tYXgoTWF0aC5taW4oY3VycmVudFRpbWUsIGZyb3plbkF0KSAtIHN0YXJ0QXQsIDApIC8gbGVuZ3RoKSAqIDEwMCA6IDA7XG4gIGNvbnN0IG5vcm1hbElubmVyUGVyY2VudCA9IE1hdGgubWluKDEwMCwgZnJvemVuQnJlYWtwb2ludCA/IG5vcm1hbFBlcmNlbnQgLyBmcm96ZW5CcmVha3BvaW50IDogMCk7XG4gIGNvbnN0IGZyb3plblBlcmNlbnQgPSBwZXJjZW50IC0gbm9ybWFsUGVyY2VudDtcbiAgY29uc3QgZnJvemVuSW5uZXJQZXJjZW50ID0gTWF0aC5taW4oMTAwLCAxIC0gZnJvemVuQnJlYWtwb2ludCA/IGZyb3plblBlcmNlbnQgLyAoMSAtIGZyb3plbkJyZWFrcG9pbnQpIDogMCk7XG4gIGNvbnN0IHRpbWVUcmF2ZWxFbGFwc2VkID0gdGltZVRyYXZlbEN1cnJlbnRWYWx1ZSAqIDYwICogMTAwMDtcbiAgY29uc3QgdGltZVRyYXZlbFJlbWFpbmluZyA9IGxlbmd0aCAtIHRpbWVUcmF2ZWxFbGFwc2VkO1xuXG4gIHJldHVybiB7XG4gICAgZWxhcHNlZDogaW5UaW1lTWFjaGluZSA/IHRpbWVUcmF2ZWxFbGFwc2VkIDogZWxhcHNlZCxcbiAgICByZW1haW5pbmc6IGluVGltZU1hY2hpbmUgPyB0aW1lVHJhdmVsUmVtYWluaW5nIDogcmVtYWluaW5nLFxuICAgIGZyb3plbkJyZWFrcG9pbnQsXG4gICAgbm9ybWFsSW5uZXJQZXJjZW50LFxuICAgIGZyb3plbklubmVyUGVyY2VudCxcbiAgICB0aW1lVHJhdmVsRWxhcHNlZCxcbiAgICB0aW1lVHJhdmVsUmVtYWluaW5nLFxuICAgIHN1cHBvcnRSZWdlbjogY2FuUmVnZW5lcmF0ZVJhbmtsaXN0KGRhdGEpLFxuICB9O1xufVxuIl19
|