@algoux/standard-ranklist-renderer-component-vue 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.
package/dist/index.js ADDED
@@ -0,0 +1,1317 @@
1
+ import "@algoux/standard-ranklist-renderer-component-styles";
2
+ import { defineComponent, ref, computed, watch, watchEffect, onMounted, onBeforeUnmount, openBlock, createElementBlock, normalizeClass, createElementVNode, normalizeStyle, toDisplayString, createCommentVNode, renderSlot, nextTick, createBlock, withCtx, Fragment, renderList, unref, withDirectives, vModelText, h, withModifiers, createVNode, mergeProps, createTextVNode } from "vue";
3
+ import { SRK_ANIMATED_MODAL_ROOT_CLASS, MODAL_ANIMATION_DURATION_MS, lockModalBodyScroll, unlockModalBodyScroll, ensureModalInteractionTracker, resolveModalTransformOrigin, registerModalFocusScope, unregisterModalFocusScope, getSolutionModalTitle, getSolutionResultMeta, formatSolutionTimestamp, getMarkerPresentation, resolveSrkAssetUrl, getProgressMaxAvailableMinutes, getProgressDurationMinutes, isProgressEnded, getProgressMetrics, getProblemHeaderBackgroundImage, getRankProblemStatusCellPresentation, captureModalTriggerPointFromMouseEvent, caniuse, shouldShowTimeColumn, calculateProblemStatisticsFooter, calculateDirtPercentage, calculateSEValue, srkSupportedVersions, formatProblemStatisticsAcceptedMinute, formatProblemStatisticsAverageHardness, formatProblemStatisticsPercent } from "@algoux/standard-ranklist-renderer-component-core";
4
+ import { EnumTheme, resolveUserMarkers, resolveText, secToTimeStr, numberToAlphabet, formatTimeDuration, resolveStyle } from "@algoux/standard-ranklist-utils";
5
+ const _hoisted_1$7 = ["data-srk-modal-state"];
6
+ const _hoisted_2$7 = ["aria-labelledby"];
7
+ const _hoisted_3$5 = { class: "srk-modal-content" };
8
+ const _hoisted_4$5 = {
9
+ key: 0,
10
+ class: "srk-modal-header"
11
+ };
12
+ const _hoisted_5$5 = { class: "srk-modal-body" };
13
+ const _sfc_main$7 = defineComponent({
14
+ __name: "Modal",
15
+ props: {
16
+ open: { type: Boolean },
17
+ title: {},
18
+ width: {},
19
+ rootClassName: {},
20
+ wrapClassName: {},
21
+ style: {},
22
+ destroyOnClose: { type: Boolean, default: true },
23
+ closeOnEsc: { type: Boolean, default: true },
24
+ closeOnMaskClick: { type: Boolean, default: true }
25
+ },
26
+ emits: ["close", "update:open"],
27
+ setup(__props, { emit: __emit }) {
28
+ let nextModalId = 0;
29
+ const props = __props;
30
+ const emit = __emit;
31
+ const titleId = `srk-vue-modal-title-${++nextModalId}`;
32
+ const dialogRef = ref(null);
33
+ const isMounted = ref(props.open || !props.destroyOnClose);
34
+ const animationState = ref(props.open ? "pre-open" : "closing");
35
+ const transformOrigin = ref({ x: 0, y: 0 });
36
+ let closeTimer = null;
37
+ let openTimer = null;
38
+ let focusScopeId = null;
39
+ const shouldRender = computed(() => isMounted.value || !props.destroyOnClose);
40
+ const rootClasses = computed(() => ["srk-modal-root", SRK_ANIMATED_MODAL_ROOT_CLASS, props.rootClassName].filter(Boolean));
41
+ const shouldLockBody = computed(() => props.open || props.destroyOnClose && isMounted.value);
42
+ const dialogStyle = computed(() => {
43
+ var _a, _b;
44
+ return {
45
+ ...props.style,
46
+ width: props.width ? `${props.width}px` : (_a = props.style) == null ? void 0 : _a.width,
47
+ ["--srk-modal-origin-x"]: `${transformOrigin.value.x}px`,
48
+ ["--srk-modal-origin-y"]: `${transformOrigin.value.y}px`,
49
+ ["--srk-modal-max-width"]: props.width ? `${props.width}px` : typeof ((_b = props.style) == null ? void 0 : _b.width) === "string" ? props.style.width : void 0
50
+ };
51
+ });
52
+ function clearTimers() {
53
+ if (typeof window === "undefined") {
54
+ closeTimer = null;
55
+ openTimer = null;
56
+ return;
57
+ }
58
+ if (closeTimer !== null) {
59
+ window.clearTimeout(closeTimer);
60
+ closeTimer = null;
61
+ }
62
+ if (openTimer !== null) {
63
+ window.clearTimeout(openTimer);
64
+ openTimer = null;
65
+ }
66
+ }
67
+ async function queueOpenAnimation() {
68
+ await nextTick();
69
+ if (typeof window === "undefined" || !props.open || !isMounted.value || animationState.value !== "pre-open") {
70
+ return;
71
+ }
72
+ registerFocusScope();
73
+ const resolution = resolveModalTransformOrigin(dialogRef.value);
74
+ transformOrigin.value = resolution.origin;
75
+ openTimer = window.setTimeout(() => {
76
+ animationState.value = "opening";
77
+ openTimer = null;
78
+ }, 0);
79
+ }
80
+ function registerFocusScope() {
81
+ const nextFocusScopeId = registerModalFocusScope(dialogRef.value, {
82
+ onEscape: handleEscape
83
+ });
84
+ if (focusScopeId === null) {
85
+ focusScopeId = nextFocusScopeId;
86
+ }
87
+ }
88
+ function releaseFocusScope() {
89
+ if (focusScopeId !== null) {
90
+ unregisterModalFocusScope(focusScopeId);
91
+ focusScopeId = null;
92
+ }
93
+ }
94
+ function requestClose(reason) {
95
+ emit("update:open", false);
96
+ emit("close", reason);
97
+ }
98
+ function handleMaskMouseDown(event) {
99
+ if (props.closeOnMaskClick && event.target === event.currentTarget) {
100
+ requestClose("mask");
101
+ }
102
+ }
103
+ function handleEscape(event) {
104
+ if (props.open && props.closeOnEsc) {
105
+ requestClose("escape");
106
+ }
107
+ }
108
+ watch(() => props.open, async (open) => {
109
+ clearTimers();
110
+ if (open) {
111
+ isMounted.value = true;
112
+ transformOrigin.value = { x: 0, y: 0 };
113
+ animationState.value = "pre-open";
114
+ await queueOpenAnimation();
115
+ return;
116
+ }
117
+ releaseFocusScope();
118
+ animationState.value = "closing";
119
+ if (!props.destroyOnClose) {
120
+ isMounted.value = true;
121
+ return;
122
+ }
123
+ if (isMounted.value && typeof window !== "undefined") {
124
+ closeTimer = window.setTimeout(() => {
125
+ isMounted.value = false;
126
+ closeTimer = null;
127
+ }, MODAL_ANIMATION_DURATION_MS);
128
+ }
129
+ }, { immediate: true });
130
+ watchEffect((onCleanup) => {
131
+ if (!shouldLockBody.value) {
132
+ return;
133
+ }
134
+ lockModalBodyScroll();
135
+ onCleanup(() => {
136
+ unlockModalBodyScroll();
137
+ });
138
+ });
139
+ onMounted(() => {
140
+ ensureModalInteractionTracker();
141
+ if (props.open) {
142
+ registerFocusScope();
143
+ }
144
+ });
145
+ onBeforeUnmount(() => {
146
+ clearTimers();
147
+ releaseFocusScope();
148
+ });
149
+ return (_ctx, _cache) => {
150
+ return shouldRender.value ? (openBlock(), createElementBlock("div", {
151
+ key: 0,
152
+ class: normalizeClass(rootClasses.value),
153
+ "data-srk-modal-state": animationState.value
154
+ }, [
155
+ _cache[2] || (_cache[2] = createElementVNode("div", { class: "srk-modal-mask" }, null, -1)),
156
+ createElementVNode("div", {
157
+ class: normalizeClass(["srk-modal-wrap", __props.wrapClassName]),
158
+ tabindex: "-1",
159
+ onMousedown: handleMaskMouseDown
160
+ }, [
161
+ createElementVNode("div", {
162
+ class: "srk-modal",
163
+ role: "dialog",
164
+ "aria-modal": "true",
165
+ "aria-labelledby": __props.title ? titleId : void 0,
166
+ "data-srk-modal-panel": "true",
167
+ tabindex: "-1",
168
+ ref_key: "dialogRef",
169
+ ref: dialogRef,
170
+ style: normalizeStyle(dialogStyle.value)
171
+ }, [
172
+ createElementVNode("div", _hoisted_3$5, [
173
+ createElementVNode("button", {
174
+ "aria-label": "Close",
175
+ class: "srk-modal-close",
176
+ type: "button",
177
+ onClick: _cache[0] || (_cache[0] = ($event) => requestClose("close-button"))
178
+ }, [..._cache[1] || (_cache[1] = [
179
+ createElementVNode("span", { class: "srk-modal-close-x" }, null, -1)
180
+ ])]),
181
+ __props.title !== void 0 ? (openBlock(), createElementBlock("div", _hoisted_4$5, [
182
+ createElementVNode("div", {
183
+ id: titleId,
184
+ class: "srk-modal-title"
185
+ }, toDisplayString(__props.title), 1)
186
+ ])) : createCommentVNode("", true),
187
+ createElementVNode("div", _hoisted_5$5, [
188
+ renderSlot(_ctx.$slots, "default")
189
+ ])
190
+ ])
191
+ ], 12, _hoisted_2$7)
192
+ ], 34)
193
+ ], 10, _hoisted_1$7)) : createCommentVNode("", true);
194
+ };
195
+ }
196
+ });
197
+ const _hoisted_1$6 = { class: "srk-common-table srk-solutions-table" };
198
+ const _hoisted_2$6 = { class: "srk--text-right" };
199
+ const _sfc_main$6 = defineComponent({
200
+ __name: "DefaultSolutionModal",
201
+ props: {
202
+ open: { type: Boolean },
203
+ user: {},
204
+ problem: {},
205
+ problemIndex: {},
206
+ solutions: { default: () => [] },
207
+ title: {},
208
+ width: { default: 320 },
209
+ rootClassName: { default: "srk-general-modal-root" },
210
+ wrapClassName: { default: "srk-solutions-modal" },
211
+ style: {}
212
+ },
213
+ emits: ["close", "update:open"],
214
+ setup(__props, { emit: __emit }) {
215
+ const props = __props;
216
+ const emit = __emit;
217
+ const cachedPayload = ref(props.user ? {
218
+ user: props.user,
219
+ problem: props.problem,
220
+ problemIndex: props.problemIndex,
221
+ solutions: props.solutions
222
+ } : null);
223
+ watch([() => props.user, () => props.problem, () => props.problemIndex, () => props.solutions], ([user, problem, problemIndex, solutions]) => {
224
+ if (user) {
225
+ cachedPayload.value = {
226
+ user,
227
+ problem,
228
+ problemIndex,
229
+ solutions
230
+ };
231
+ }
232
+ }, { immediate: true });
233
+ const resolvedTitle = computed(() => props.title || (cachedPayload.value ? getSolutionModalTitle(cachedPayload.value.problemIndex, cachedPayload.value.user) : ""));
234
+ return (_ctx, _cache) => {
235
+ return cachedPayload.value ? (openBlock(), createBlock(_sfc_main$7, {
236
+ key: 0,
237
+ open: __props.open,
238
+ title: resolvedTitle.value,
239
+ width: __props.width,
240
+ "root-class-name": __props.rootClassName,
241
+ "wrap-class-name": __props.wrapClassName,
242
+ style: normalizeStyle(__props.style),
243
+ onClose: _cache[0] || (_cache[0] = (reason) => emit("close", reason)),
244
+ "onUpdate:open": _cache[1] || (_cache[1] = (value) => emit("update:open", value))
245
+ }, {
246
+ default: withCtx(() => [
247
+ createElementVNode("table", _hoisted_1$6, [
248
+ _cache[2] || (_cache[2] = createElementVNode("thead", null, [
249
+ createElementVNode("tr", null, [
250
+ createElementVNode("th", { class: "srk--text-left" }, "Result"),
251
+ createElementVNode("th", { class: "srk--text-right" }, "Time")
252
+ ])
253
+ ], -1)),
254
+ createElementVNode("tbody", null, [
255
+ (openBlock(true), createElementBlock(Fragment, null, renderList(cachedPayload.value.solutions, (solution, index) => {
256
+ var _a;
257
+ return openBlock(), createElementBlock("tr", {
258
+ key: `${solution.result}_${(_a = solution.time) == null ? void 0 : _a[0]}_${index}`
259
+ }, [
260
+ createElementVNode("td", null, [
261
+ createElementVNode("span", {
262
+ class: normalizeClass(["srk-solution-result-text", unref(getSolutionResultMeta)(solution.result).className])
263
+ }, toDisplayString(unref(getSolutionResultMeta)(solution.result).label), 3)
264
+ ]),
265
+ createElementVNode("td", _hoisted_2$6, toDisplayString(unref(formatSolutionTimestamp)(solution)), 1)
266
+ ]);
267
+ }), 128))
268
+ ])
269
+ ])
270
+ ]),
271
+ _: 1
272
+ }, 8, ["open", "title", "width", "root-class-name", "wrap-class-name", "style"])) : createCommentVNode("", true);
273
+ };
274
+ }
275
+ });
276
+ const _hoisted_1$5 = { class: "srk-user-modal-info" };
277
+ const _hoisted_2$5 = { class: "srk-user-modal-info-user-name" };
278
+ const _hoisted_3$4 = {
279
+ key: 0,
280
+ class: "srk-user-modal-info-user-second-name"
281
+ };
282
+ const _hoisted_4$4 = { class: "srk-user-modal-info-labels" };
283
+ const _hoisted_5$4 = { class: "srk-user-modal-info-labels-label srk-user-modal-info-labels-label-preset-general" };
284
+ const _hoisted_6$3 = {
285
+ key: 1,
286
+ class: "srk-user-modal-info-team-members"
287
+ };
288
+ const _hoisted_7$3 = {
289
+ key: 0,
290
+ class: "srk-user-modal-info-team-members-slash"
291
+ };
292
+ const _hoisted_8$3 = {
293
+ key: 2,
294
+ class: "srk-user-modal-info-photo"
295
+ };
296
+ const _hoisted_9$3 = ["src"];
297
+ const _sfc_main$5 = defineComponent({
298
+ __name: "DefaultUserModal",
299
+ props: {
300
+ open: { type: Boolean },
301
+ user: {},
302
+ markers: { default: () => [] },
303
+ theme: { default: EnumTheme.light },
304
+ title: { default: "User Info" },
305
+ width: { default: 420 },
306
+ rootClassName: { default: "srk-general-modal-root" },
307
+ wrapClassName: { default: "srk-user-modal" },
308
+ style: {},
309
+ formatSrkAssetUrl: {}
310
+ },
311
+ emits: ["close", "update:open"],
312
+ setup(__props, { emit: __emit }) {
313
+ const props = __props;
314
+ const emit = __emit;
315
+ const cachedUser = ref(props.user || null);
316
+ watch(() => props.user, (user) => {
317
+ if (user) {
318
+ cachedUser.value = user;
319
+ }
320
+ }, { immediate: true });
321
+ const resolvedMarkers = computed(() => cachedUser.value ? resolveUserMarkers(cachedUser.value, props.markers).map((marker) => ({
322
+ marker,
323
+ presentation: getMarkerPresentation(marker, props.theme)
324
+ })) : []);
325
+ function formatAssetUrl(url, field) {
326
+ return resolveSrkAssetUrl(url, field, props.formatSrkAssetUrl);
327
+ }
328
+ return (_ctx, _cache) => {
329
+ return cachedUser.value ? (openBlock(), createBlock(_sfc_main$7, {
330
+ key: 0,
331
+ open: __props.open,
332
+ title: __props.title,
333
+ width: __props.width,
334
+ "root-class-name": __props.rootClassName,
335
+ "wrap-class-name": __props.wrapClassName,
336
+ style: normalizeStyle(__props.style),
337
+ onClose: _cache[0] || (_cache[0] = (reason) => emit("close", reason)),
338
+ "onUpdate:open": _cache[1] || (_cache[1] = (value) => emit("update:open", value))
339
+ }, {
340
+ default: withCtx(() => [
341
+ createElementVNode("div", _hoisted_1$5, [
342
+ createElementVNode("h3", _hoisted_2$5, toDisplayString(unref(resolveText)(cachedUser.value.name)), 1),
343
+ cachedUser.value.organization ? (openBlock(), createElementBlock("p", _hoisted_3$4, toDisplayString(unref(resolveText)(cachedUser.value.organization)), 1)) : createCommentVNode("", true),
344
+ createElementVNode("div", _hoisted_4$4, [
345
+ createElementVNode("span", _hoisted_5$4, toDisplayString(cachedUser.value.official === false ? "\uFF0A \u975E\u6B63\u5F0F\u53C2\u52A0\u8005" : "\u6B63\u5F0F\u53C2\u52A0\u8005"), 1),
346
+ (openBlock(true), createElementBlock(Fragment, null, renderList(resolvedMarkers.value, (marker) => {
347
+ return openBlock(), createElementBlock("span", {
348
+ key: marker.marker.id,
349
+ class: normalizeClass(["srk-user-modal-info-labels-label", marker.presentation.className]),
350
+ style: normalizeStyle(marker.presentation.style)
351
+ }, toDisplayString(unref(resolveText)(marker.marker.label)), 7);
352
+ }), 128))
353
+ ]),
354
+ cachedUser.value.teamMembers && cachedUser.value.teamMembers.length ? (openBlock(), createElementBlock("div", _hoisted_6$3, [
355
+ (openBlock(true), createElementBlock(Fragment, null, renderList(cachedUser.value.teamMembers, (member, index) => {
356
+ return openBlock(), createElementBlock(Fragment, {
357
+ key: unref(resolveText)(member.name)
358
+ }, [
359
+ index > 0 ? (openBlock(), createElementBlock("span", _hoisted_7$3, " / ")) : createCommentVNode("", true),
360
+ createElementVNode("span", null, toDisplayString(unref(resolveText)(member.name)), 1)
361
+ ], 64);
362
+ }), 128))
363
+ ])) : createCommentVNode("", true),
364
+ cachedUser.value.photo ? (openBlock(), createElementBlock("div", _hoisted_8$3, [
365
+ createElementVNode("img", {
366
+ src: formatAssetUrl(cachedUser.value.photo, "user.photo"),
367
+ alt: "User portrait",
368
+ class: "srk-user-modal-info-photo-img"
369
+ }, null, 8, _hoisted_9$3)
370
+ ])) : createCommentVNode("", true)
371
+ ])
372
+ ]),
373
+ _: 1
374
+ }, 8, ["open", "title", "width", "root-class-name", "wrap-class-name", "style"])) : createCommentVNode("", true);
375
+ };
376
+ }
377
+ });
378
+ const _hoisted_1$4 = { class: "srk-progress-bar-container" };
379
+ const _hoisted_2$4 = { class: "srk-progress-bar" };
380
+ const _hoisted_3$3 = { class: "srk-progress-bar-body" };
381
+ const _hoisted_4$3 = {
382
+ key: 0,
383
+ class: "srk-progress-slider-layer"
384
+ };
385
+ const _hoisted_5$3 = ["max", "title"];
386
+ const _hoisted_6$2 = { class: "srk-progress-secondary-area" };
387
+ const _hoisted_7$2 = { class: "srk-progress-secondary-area-center" };
388
+ const _hoisted_8$2 = {
389
+ key: 0,
390
+ class: "srk-progress-time-machine-status"
391
+ };
392
+ const _hoisted_9$2 = {
393
+ key: 1,
394
+ class: "srk-progress-live-text"
395
+ };
396
+ const _hoisted_10$1 = {
397
+ key: 2,
398
+ style: { "visibility": "hidden" }
399
+ };
400
+ const _sfc_main$4 = defineComponent({
401
+ __name: "ProgressBar",
402
+ props: {
403
+ data: {},
404
+ enableTimeTravel: { type: Boolean, default: false },
405
+ live: { type: Boolean, default: false },
406
+ td: { default: 0 }
407
+ },
408
+ emits: ["timeTravel"],
409
+ setup(__props, { emit: __emit }) {
410
+ const props = __props;
411
+ const emit = __emit;
412
+ const localTime = ref(Date.now());
413
+ const inTimeMachine = ref(false);
414
+ const timeTravelIsChanging = ref(false);
415
+ const timeTravelCurrentValue = ref(getProgressMaxAvailableMinutes(props.data.contest, localTime.value, props.td));
416
+ const timeTravelValue = ref(null);
417
+ let liveInterval;
418
+ const durationMinutes = computed(() => getProgressDurationMinutes(props.data.contest));
419
+ const maxAvailableMinutes = computed(() => getProgressMaxAvailableMinutes(props.data.contest, localTime.value, props.td));
420
+ const isEnded = computed(() => isProgressEnded(props.data.contest, localTime.value, props.td));
421
+ const progressMetrics = computed(() => getProgressMetrics(props.data, localTime.value, props.td, timeTravelCurrentValue.value, inTimeMachine.value));
422
+ function handleProgressTimer() {
423
+ localTime.value = Date.now();
424
+ if (isEnded.value && liveInterval !== void 0) {
425
+ window.clearInterval(liveInterval);
426
+ liveInterval = void 0;
427
+ }
428
+ }
429
+ function syncLiveInterval(live) {
430
+ if (typeof window === "undefined") {
431
+ return;
432
+ }
433
+ if (live && liveInterval === void 0) {
434
+ liveInterval = window.setInterval(handleProgressTimer, 1e3);
435
+ }
436
+ if (!live && liveInterval !== void 0) {
437
+ window.clearInterval(liveInterval);
438
+ liveInterval = void 0;
439
+ }
440
+ }
441
+ function handleTimeTravelChange(value) {
442
+ const exited = value >= durationMinutes.value || value >= maxAvailableMinutes.value;
443
+ emit("timeTravel", exited ? null : value * 60 * 1e3);
444
+ inTimeMachine.value = !exited;
445
+ timeTravelValue.value = exited ? null : value * 60 * 1e3;
446
+ timeTravelIsChanging.value = false;
447
+ }
448
+ function beginTimeTravel() {
449
+ timeTravelIsChanging.value = true;
450
+ inTimeMachine.value = true;
451
+ }
452
+ function commitTimeTravel() {
453
+ if (timeTravelIsChanging.value) {
454
+ handleTimeTravelChange(timeTravelCurrentValue.value);
455
+ }
456
+ }
457
+ watch(maxAvailableMinutes, (value) => {
458
+ if (!timeTravelIsChanging.value && timeTravelValue.value === null) {
459
+ timeTravelCurrentValue.value = value;
460
+ }
461
+ });
462
+ watch(() => props.live, (live) => syncLiveInterval(live), { immediate: true });
463
+ watch(() => props.data.contest.title, () => {
464
+ timeTravelIsChanging.value = false;
465
+ timeTravelCurrentValue.value = maxAvailableMinutes.value;
466
+ timeTravelValue.value = null;
467
+ inTimeMachine.value = false;
468
+ emit("timeTravel", null);
469
+ });
470
+ onBeforeUnmount(() => {
471
+ if (liveInterval !== void 0) {
472
+ window.clearInterval(liveInterval);
473
+ liveInterval = void 0;
474
+ }
475
+ });
476
+ return (_ctx, _cache) => {
477
+ return openBlock(), createElementBlock("div", _hoisted_1$4, [
478
+ createElementVNode("div", _hoisted_2$4, [
479
+ createElementVNode("div", _hoisted_3$3, [
480
+ createElementVNode("div", {
481
+ class: "srk-progress-bar-segment srk-progress-bar-normal",
482
+ style: normalizeStyle({ width: `${progressMetrics.value.frozenBreakpoint * 100}%` })
483
+ }, [
484
+ createElementVNode("div", {
485
+ class: "srk-progress-bar-fill",
486
+ style: normalizeStyle({ width: `${progressMetrics.value.normalInnerPercent}%` })
487
+ }, null, 4)
488
+ ], 4),
489
+ createElementVNode("div", {
490
+ class: "srk-progress-bar-segment srk-progress-bar-frozen",
491
+ style: normalizeStyle({ width: `${(1 - progressMetrics.value.frozenBreakpoint) * 100}%` })
492
+ }, [
493
+ createElementVNode("div", {
494
+ class: "srk-progress-bar-fill",
495
+ style: normalizeStyle({ width: `${progressMetrics.value.frozenInnerPercent}%` })
496
+ }, null, 4)
497
+ ], 4)
498
+ ]),
499
+ __props.enableTimeTravel && progressMetrics.value.supportRegen ? (openBlock(), createElementBlock("div", _hoisted_4$3, [
500
+ timeTravelIsChanging.value ? (openBlock(), createElementBlock("div", {
501
+ key: 0,
502
+ class: "srk-progress-slider-tooltip",
503
+ style: normalizeStyle({ left: `${durationMinutes.value ? timeTravelCurrentValue.value / durationMinutes.value * 100 : 0}%` })
504
+ }, toDisplayString(unref(secToTimeStr)(timeTravelCurrentValue.value * 60)), 5)) : createCommentVNode("", true),
505
+ withDirectives(createElementVNode("input", {
506
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => timeTravelCurrentValue.value = $event),
507
+ "aria-label": "Time Travel",
508
+ class: "srk-progress-slider",
509
+ max: durationMinutes.value,
510
+ min: "0",
511
+ step: "1",
512
+ title: unref(secToTimeStr)(timeTravelCurrentValue.value * 60),
513
+ type: "range",
514
+ onBlur: commitTimeTravel,
515
+ onKeydown: beginTimeTravel,
516
+ onKeyup: commitTimeTravel,
517
+ onMousedown: beginTimeTravel,
518
+ onMouseup: commitTimeTravel,
519
+ onTouchend: commitTimeTravel,
520
+ onTouchstart: beginTimeTravel
521
+ }, null, 40, _hoisted_5$3), [
522
+ [
523
+ vModelText,
524
+ timeTravelCurrentValue.value,
525
+ void 0,
526
+ { number: true }
527
+ ]
528
+ ])
529
+ ])) : createCommentVNode("", true)
530
+ ]),
531
+ createElementVNode("div", _hoisted_6$2, [
532
+ createElementVNode("div", {
533
+ class: "srk-progress-secondary-area-left",
534
+ style: normalizeStyle(__props.live || inTimeMachine.value ? {} : { display: "none" })
535
+ }, " Elapsed: " + toDisplayString(unref(secToTimeStr)(Math.round(progressMetrics.value.elapsed / 1e3))), 5),
536
+ createElementVNode("div", _hoisted_7$2, [
537
+ inTimeMachine.value ? (openBlock(), createElementBlock("div", _hoisted_8$2, [..._cache[1] || (_cache[1] = [
538
+ createElementVNode("div", { class: "srk-progress-time-machine-text" }, "Time Travel Mode", -1)
539
+ ])])) : __props.live && !isEnded.value ? (openBlock(), createElementBlock("div", _hoisted_9$2, "Live")) : (openBlock(), createElementBlock("div", _hoisted_10$1, "SRK"))
540
+ ]),
541
+ createElementVNode("div", {
542
+ class: "srk-progress-secondary-area-right",
543
+ style: normalizeStyle(__props.live || inTimeMachine.value ? {} : { display: "none" })
544
+ }, " Remaining: " + toDisplayString(unref(secToTimeStr)(Math.round(progressMetrics.value.remaining / 1e3))), 5)
545
+ ])
546
+ ]);
547
+ };
548
+ }
549
+ });
550
+ const _hoisted_1$3 = ["href"];
551
+ const _hoisted_2$3 = { class: "srk--display-block" };
552
+ const _hoisted_3$2 = ["title"];
553
+ const _hoisted_4$2 = { class: "srk--display-block" };
554
+ const _hoisted_5$2 = ["title"];
555
+ const _sfc_main$3 = defineComponent({
556
+ __name: "ProblemHeaderCell",
557
+ props: {
558
+ problem: {},
559
+ index: {},
560
+ theme: { default: EnumTheme.light }
561
+ },
562
+ setup(__props) {
563
+ const props = __props;
564
+ const alias = computed(() => props.problem.alias || numberToAlphabet(props.index));
565
+ const stat = computed(() => props.problem.statistics);
566
+ const statDesc = computed(() => {
567
+ if (!stat.value) {
568
+ return "";
569
+ }
570
+ const ratio = stat.value.submitted ? (stat.value.accepted / stat.value.submitted * 100).toFixed(1) : 0;
571
+ return `${stat.value.accepted} / ${stat.value.submitted} (${ratio}%)`;
572
+ });
573
+ const backgroundImage = computed(() => getProblemHeaderBackgroundImage(props.problem.style, props.theme));
574
+ return (_ctx, _cache) => {
575
+ return openBlock(), createElementBlock("th", {
576
+ class: "srk--nowrap srk-problem-header",
577
+ style: normalizeStyle({ backgroundImage: backgroundImage.value })
578
+ }, [
579
+ __props.problem.link ? (openBlock(), createElementBlock("a", {
580
+ key: 0,
581
+ href: __props.problem.link,
582
+ target: "_blank",
583
+ rel: "noopener noreferrer",
584
+ style: { "color": "unset" }
585
+ }, [
586
+ createElementVNode("span", _hoisted_2$3, toDisplayString(alias.value), 1),
587
+ stat.value ? (openBlock(), createElementBlock("span", {
588
+ key: 0,
589
+ class: "srk--display-block srk-problem-stats",
590
+ title: statDesc.value
591
+ }, toDisplayString(stat.value.accepted), 9, _hoisted_3$2)) : createCommentVNode("", true)
592
+ ], 8, _hoisted_1$3)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
593
+ createElementVNode("span", _hoisted_4$2, toDisplayString(alias.value), 1),
594
+ stat.value ? (openBlock(), createElementBlock("span", {
595
+ key: 0,
596
+ class: "srk--display-block srk-problem-stats",
597
+ title: statDesc.value
598
+ }, toDisplayString(stat.value.accepted), 9, _hoisted_5$2)) : createCommentVNode("", true)
599
+ ], 64))
600
+ ], 4);
601
+ };
602
+ }
603
+ });
604
+ const _hoisted_1$2 = {
605
+ key: 0,
606
+ class: "srk-prest-status-block-fb-star"
607
+ };
608
+ const _hoisted_2$2 = {
609
+ key: 4,
610
+ class: "srk-status-placeholder-cell srk--text-center srk--nowrap"
611
+ };
612
+ const fbStar = "\u2605";
613
+ const _sfc_main$2 = defineComponent({
614
+ __name: "StatusCell",
615
+ props: {
616
+ status: {},
617
+ problem: {},
618
+ problemIndex: {},
619
+ user: {},
620
+ row: {},
621
+ rowIndex: {},
622
+ ranklist: {},
623
+ onSolutionClick: {},
624
+ statusCellPreset: { default: "classic" },
625
+ statusColorAsText: { type: Boolean, default: false },
626
+ emptyStatusPlaceholder: { default: null }
627
+ },
628
+ setup(__props) {
629
+ const props = __props;
630
+ const solutions = computed(() => [...props.status.solutions || []].reverse());
631
+ const isClickable = computed(() => solutions.value.length > 0 && !!props.onSolutionClick);
632
+ const commonClassName = computed(() => [
633
+ "srk-prest-status-block",
634
+ "srk--text-center",
635
+ "srk--nowrap",
636
+ {
637
+ "srk--cursor-pointer": isClickable.value,
638
+ "srk-prest-status-block-color-text": props.statusColorAsText
639
+ }
640
+ ]);
641
+ function emitSolutionClick(event) {
642
+ var _a, _b;
643
+ if (!isClickable.value) {
644
+ return;
645
+ }
646
+ captureModalTriggerPointFromMouseEvent(event, {
647
+ source: "status-cell",
648
+ context: {
649
+ rowIndex: props.rowIndex,
650
+ problemIndex: props.problemIndex,
651
+ problemAlias: ((_a = props.problem) == null ? void 0 : _a.alias) || null,
652
+ problemTitle: props.problem ? resolveText(props.problem.title) : null,
653
+ userId: props.user.id || null
654
+ }
655
+ });
656
+ (_b = props.onSolutionClick) == null ? void 0 : _b.call(props, {
657
+ user: props.user,
658
+ row: props.row,
659
+ rowIndex: props.rowIndex,
660
+ problemIndex: props.problemIndex,
661
+ problem: props.problem,
662
+ status: props.status,
663
+ solutions: solutions.value,
664
+ ranklist: props.ranklist
665
+ });
666
+ }
667
+ const StatusBody = defineComponent({
668
+ props: {
669
+ status: {
670
+ type: Object,
671
+ required: true
672
+ },
673
+ ranklist: {
674
+ type: Object,
675
+ required: true
676
+ },
677
+ preset: {
678
+ type: String,
679
+ required: true
680
+ }
681
+ },
682
+ setup(childProps) {
683
+ return () => {
684
+ const status = childProps.status;
685
+ const ranklist = childProps.ranklist;
686
+ const preset = childProps.preset;
687
+ const presentation = getRankProblemStatusCellPresentation(status, ranklist, preset);
688
+ if (typeof presentation.score === "number") {
689
+ return [
690
+ h("span", { class: "srk-prest-status-block-score" }, presentation.score),
691
+ h("span", { class: "srk-prest-status-block-score-details" }, presentation.scoreDetails)
692
+ ];
693
+ }
694
+ if (presentation.secondary !== void 0) {
695
+ return [
696
+ h("span", { class: "srk-prest-status-block-primary" }, presentation.primary || ""),
697
+ " ",
698
+ h("span", { class: "srk-prest-status-block-secondary" }, presentation.secondary)
699
+ ];
700
+ }
701
+ return presentation.primary || "";
702
+ };
703
+ }
704
+ });
705
+ return (_ctx, _cache) => {
706
+ return __props.status.result === "FB" ? (openBlock(), createElementBlock("td", {
707
+ key: 0,
708
+ class: normalizeClass([commonClassName.value, "srk-prest-status-block-fb"]),
709
+ onClick: withModifiers(emitSolutionClick, ["prevent"])
710
+ }, [
711
+ __props.statusColorAsText ? (openBlock(), createElementBlock("span", _hoisted_1$2, toDisplayString(fbStar))) : createCommentVNode("", true),
712
+ createVNode(unref(StatusBody), {
713
+ status: __props.status,
714
+ ranklist: __props.ranklist,
715
+ preset: __props.statusCellPreset
716
+ }, null, 8, ["status", "ranklist", "preset"])
717
+ ], 2)) : __props.status.result === "AC" ? (openBlock(), createElementBlock("td", {
718
+ key: 1,
719
+ class: normalizeClass([commonClassName.value, "srk-prest-status-block-accepted"]),
720
+ onClick: withModifiers(emitSolutionClick, ["prevent"])
721
+ }, [
722
+ createVNode(unref(StatusBody), {
723
+ status: __props.status,
724
+ ranklist: __props.ranklist,
725
+ preset: __props.statusCellPreset
726
+ }, null, 8, ["status", "ranklist", "preset"])
727
+ ], 2)) : __props.status.result === "?" ? (openBlock(), createElementBlock("td", {
728
+ key: 2,
729
+ class: normalizeClass([commonClassName.value, "srk-prest-status-block-frozen"]),
730
+ onClick: withModifiers(emitSolutionClick, ["prevent"])
731
+ }, [
732
+ createVNode(unref(StatusBody), {
733
+ status: __props.status,
734
+ ranklist: __props.ranklist,
735
+ preset: __props.statusCellPreset
736
+ }, null, 8, ["status", "ranklist", "preset"])
737
+ ], 2)) : __props.status.result === "RJ" ? (openBlock(), createElementBlock("td", {
738
+ key: 3,
739
+ class: normalizeClass([commonClassName.value, "srk-prest-status-block-failed"]),
740
+ onClick: withModifiers(emitSolutionClick, ["prevent"])
741
+ }, [
742
+ createVNode(unref(StatusBody), {
743
+ status: __props.status,
744
+ ranklist: __props.ranklist,
745
+ preset: __props.statusCellPreset
746
+ }, null, 8, ["status", "ranklist", "preset"])
747
+ ], 2)) : (openBlock(), createElementBlock("td", _hoisted_2$2, toDisplayString(__props.emptyStatusPlaceholder), 1));
748
+ };
749
+ }
750
+ });
751
+ const _hoisted_1$1 = { class: "srk-user-cell-content" };
752
+ const _hoisted_2$1 = {
753
+ key: 0,
754
+ class: "srk-user-avatar"
755
+ };
756
+ const _hoisted_3$1 = ["src"];
757
+ const _hoisted_4$1 = { class: "srk-user-body" };
758
+ const _hoisted_5$1 = { class: "srk-user-name-row" };
759
+ const _hoisted_6$1 = ["title"];
760
+ const _hoisted_7$1 = { class: "srk-marker-dot-group" };
761
+ const _hoisted_8$1 = ["data-tooltip"];
762
+ const _hoisted_9$1 = {
763
+ key: 0,
764
+ class: "srk-user-secondary-text srk--text-ellipsis",
765
+ title: ""
766
+ };
767
+ const _sfc_main$1 = defineComponent({
768
+ __name: "UserCell",
769
+ props: {
770
+ user: {},
771
+ row: {},
772
+ rowIndex: {},
773
+ ranklist: {},
774
+ markers: { default: () => [] },
775
+ theme: { default: EnumTheme.light },
776
+ formatSrkAssetUrl: {},
777
+ onUserClick: {},
778
+ hideOrganization: { type: Boolean, default: false },
779
+ hideAvatar: { type: Boolean, default: false }
780
+ },
781
+ setup(__props) {
782
+ const props = __props;
783
+ const name = computed(() => resolveText(props.user.name));
784
+ const userMarkers = computed(() => resolveUserMarkers(props.user, props.markers));
785
+ const resolvedMarkers = computed(() => userMarkers.value.map((marker) => ({
786
+ marker,
787
+ presentation: getMarkerPresentation(marker, props.theme)
788
+ })));
789
+ function emitUserClick(event) {
790
+ var _a;
791
+ captureModalTriggerPointFromMouseEvent(event, {
792
+ source: "user-cell",
793
+ context: {
794
+ rowIndex: props.rowIndex,
795
+ userId: props.user.id || null,
796
+ userName: name.value
797
+ }
798
+ });
799
+ (_a = props.onUserClick) == null ? void 0 : _a.call(props, {
800
+ user: props.user,
801
+ row: props.row,
802
+ rowIndex: props.rowIndex,
803
+ ranklist: props.ranklist
804
+ });
805
+ }
806
+ return (_ctx, _cache) => {
807
+ return openBlock(), createElementBlock("td", {
808
+ class: normalizeClass(["srk--text-left srk--nowrap srk-user-cell", { "srk--cursor-pointer": !!__props.onUserClick }]),
809
+ title: "",
810
+ onClick: withModifiers(emitUserClick, ["prevent"])
811
+ }, [
812
+ createElementVNode("div", _hoisted_1$1, [
813
+ __props.user.avatar && !__props.hideAvatar ? (openBlock(), createElementBlock("div", _hoisted_2$1, [
814
+ createElementVNode("img", {
815
+ src: __props.formatSrkAssetUrl(__props.user.avatar, "user.avatar"),
816
+ alt: "User Avatar"
817
+ }, null, 8, _hoisted_3$1)
818
+ ])) : createCommentVNode("", true),
819
+ createElementVNode("div", _hoisted_4$1, [
820
+ createElementVNode("div", _hoisted_5$1, [
821
+ createElementVNode("span", {
822
+ class: "srk-user-name-text",
823
+ title: name.value
824
+ }, toDisplayString(name.value), 9, _hoisted_6$1),
825
+ createElementVNode("span", _hoisted_7$1, [
826
+ (openBlock(true), createElementBlock(Fragment, null, renderList(resolvedMarkers.value, (marker) => {
827
+ return openBlock(), createElementBlock("span", {
828
+ key: marker.marker.id,
829
+ class: normalizeClass(["srk-marker srk-marker-dot srk--c-tooltip", marker.presentation.className]),
830
+ style: normalizeStyle(marker.presentation.style),
831
+ "data-tooltip": unref(resolveText)(marker.marker.label)
832
+ }, null, 14, _hoisted_8$1);
833
+ }), 128))
834
+ ])
835
+ ]),
836
+ __props.user.organization && !__props.hideOrganization ? (openBlock(), createElementBlock("p", _hoisted_9$1, toDisplayString(unref(resolveText)(__props.user.organization)), 1)) : createCommentVNode("", true)
837
+ ])
838
+ ])
839
+ ], 2);
840
+ };
841
+ }
842
+ });
843
+ const _hoisted_1 = { key: 0 };
844
+ const _hoisted_2 = { key: 1 };
845
+ const _hoisted_3 = {
846
+ key: 2,
847
+ class: "srk-common-table srk-main"
848
+ };
849
+ const _hoisted_4 = {
850
+ key: 0,
851
+ class: "srk-organization-header srk--text-left srk--nowrap"
852
+ };
853
+ const _hoisted_5 = { class: "srk--text-left srk--nowrap" };
854
+ const _hoisted_6 = { class: "srk--text-right srk--nowrap" };
855
+ const _hoisted_7 = {
856
+ key: 1,
857
+ class: "srk--text-right srk--nowrap"
858
+ };
859
+ const _hoisted_8 = {
860
+ key: 2,
861
+ class: "srk-dirt-header srk--text-right srk--nowrap"
862
+ };
863
+ const _hoisted_9 = {
864
+ key: 3,
865
+ class: "srk-se-header srk--text-right srk--nowrap"
866
+ };
867
+ const _hoisted_10 = { class: "srk-organization-cell-content" };
868
+ const _hoisted_11 = {
869
+ key: 0,
870
+ class: "srk-user-avatar"
871
+ };
872
+ const _hoisted_12 = ["src"];
873
+ const _hoisted_13 = ["title"];
874
+ const _hoisted_14 = { class: "srk--text-right srk--nowrap" };
875
+ const _hoisted_15 = {
876
+ key: 1,
877
+ class: "srk--text-right srk--nowrap"
878
+ };
879
+ const _hoisted_16 = {
880
+ key: 2,
881
+ class: "srk-dirt-cell srk--text-right srk--nowrap"
882
+ };
883
+ const _hoisted_17 = {
884
+ key: 3,
885
+ class: "srk-se-cell srk--text-right srk--nowrap"
886
+ };
887
+ const _hoisted_18 = { key: 0 };
888
+ const _hoisted_19 = ["colspan"];
889
+ const _hoisted_20 = ["data-tooltip"];
890
+ const _hoisted_21 = { class: "srk-problem-statistics-footer-primary" };
891
+ const _hoisted_22 = { class: "srk-problem-statistics-footer-secondary" };
892
+ const _hoisted_23 = {
893
+ key: 0,
894
+ class: "srk-problem-statistics-footer-cell srk-extra-statistics-footer-cell srk-dirt-footer-cell srk--nowrap"
895
+ };
896
+ const _hoisted_24 = {
897
+ key: 1,
898
+ class: "srk-problem-statistics-footer-cell srk-extra-statistics-footer-cell srk-se-footer-cell srk--nowrap"
899
+ };
900
+ const _hoisted_25 = { class: "srk-problem-statistics-footer-row srk-problem-statistics-footer-problem-label-row" };
901
+ const _hoisted_26 = ["colspan"];
902
+ const _hoisted_27 = { class: "srk--display-block" };
903
+ const _hoisted_28 = {
904
+ key: 0,
905
+ class: "srk-problem-statistics-footer-cell srk-extra-statistics-footer-cell srk-dirt-footer-cell srk--nowrap"
906
+ };
907
+ const _hoisted_29 = {
908
+ key: 1,
909
+ class: "srk-problem-statistics-footer-cell srk-extra-statistics-footer-cell srk-se-footer-cell srk--nowrap"
910
+ };
911
+ const _sfc_main = defineComponent({
912
+ __name: "Ranklist",
913
+ props: {
914
+ data: {},
915
+ theme: { default: EnumTheme.light },
916
+ borderedRows: { type: Boolean, default: false },
917
+ rowBordered: { type: Boolean, default: false },
918
+ columnBordered: { type: Boolean, default: false },
919
+ stripedRows: { type: Boolean, default: false },
920
+ formatSrkAssetUrl: {},
921
+ splitOrganization: { type: Boolean, default: false },
922
+ columnTitles: {},
923
+ statusCellPreset: { default: "classic" },
924
+ statusColorAsText: { type: Boolean, default: false },
925
+ showProblemStatisticsFooter: { type: Boolean, default: false },
926
+ showDirtColumn: { type: Boolean, default: false },
927
+ showSEColumn: { type: Boolean, default: false },
928
+ emptyStatusPlaceholder: { default: null },
929
+ userAvatarPlacement: { default: "user" }
930
+ },
931
+ emits: ["userClick", "solutionClick"],
932
+ setup(__props, { emit: __emit }) {
933
+ const props = __props;
934
+ const emit = __emit;
935
+ const resolvedTheme = computed(() => props.theme);
936
+ const supportedVersions = srkSupportedVersions;
937
+ const isSupportedVersion = computed(() => caniuse(props.data.version));
938
+ const showTimeColumn = computed(() => shouldShowTimeColumn(props.data.rows));
939
+ const showAvatarInOrganization = computed(() => props.splitOrganization && props.userAvatarPlacement === "organization");
940
+ const problemStatistics = computed(() => props.showProblemStatisticsFooter || props.showSEColumn ? calculateProblemStatisticsFooter(props.data) : []);
941
+ const leftFooterColumnCount = computed(() => props.data.series.length + 1 + 1 + (showTimeColumn.value ? 1 : 0) + (props.splitOrganization ? 1 : 0));
942
+ const problemStatisticsFooterRows = [
943
+ {
944
+ key: "accepted",
945
+ label: "Accepted",
946
+ tooltip: "Number of participants who solved this problem"
947
+ },
948
+ {
949
+ key: "tried",
950
+ label: "Tried",
951
+ tooltip: "Number of participants who attempted this problem"
952
+ },
953
+ {
954
+ key: "submitted",
955
+ label: "Submitted",
956
+ tooltip: "Total number of valid submissions for this problem"
957
+ },
958
+ {
959
+ key: "dirt",
960
+ label: "Dirt",
961
+ tooltip: "Wrong submissions among participants who solved this problem"
962
+ },
963
+ {
964
+ key: "se",
965
+ label: "SE",
966
+ tooltip: "Average hardness, calculated as (participants - accepted) / participants"
967
+ },
968
+ {
969
+ key: "firstAccepted",
970
+ label: "FB at",
971
+ tooltip: "First Blood at, also known as first solve time, in minutes"
972
+ },
973
+ {
974
+ key: "lastAccepted",
975
+ label: "LB at",
976
+ tooltip: "Last Blood at, also known as last solve time, in minutes"
977
+ }
978
+ ];
979
+ function formatAssetUrl(url, field) {
980
+ return resolveSrkAssetUrl(url, field, props.formatSrkAssetUrl);
981
+ }
982
+ function getRankValues(row) {
983
+ return row.rankValues || props.data.series.map(() => ({ rank: null, segmentIndex: null }));
984
+ }
985
+ function getRankText(rankValue, row) {
986
+ return rankValue.rank ? rankValue.rank : row.user.official === false ? "\uFF0A" : "";
987
+ }
988
+ function isSeriesSegmentedColumn(series) {
989
+ return ((series == null ? void 0 : series.segments) || []).some((segment) => typeof segment.style === "string");
990
+ }
991
+ function resolveSeriesColumnTitle(series, index) {
992
+ var _a, _b, _c;
993
+ const seriesTitles = (_a = props.columnTitles) == null ? void 0 : _a.series;
994
+ if (typeof seriesTitles === "function") {
995
+ return (_b = seriesTitles(series, index)) != null ? _b : series.title;
996
+ }
997
+ if (Array.isArray(seriesTitles)) {
998
+ return (_c = seriesTitles[index]) != null ? _c : series.title;
999
+ }
1000
+ return series.title;
1001
+ }
1002
+ function resolveColumnTitle(key, fallback) {
1003
+ var _a, _b;
1004
+ return (_b = (_a = props.columnTitles) == null ? void 0 : _a[key]) != null ? _b : fallback;
1005
+ }
1006
+ function resolveSeriesSegment(rankValue, series) {
1007
+ const index = rankValue.segmentIndex || rankValue.segmentIndex === 0 ? rankValue.segmentIndex : -1;
1008
+ return ((series == null ? void 0 : series.segments) || [])[index] || {};
1009
+ }
1010
+ function getSeriesSegmentClass(rankValue, series) {
1011
+ const segmentStyle = resolveSeriesSegment(rankValue, series).style;
1012
+ return typeof segmentStyle === "string" ? `srk-preset-series-segment-${segmentStyle}` : "";
1013
+ }
1014
+ function getSeriesSegmentStyle(rankValue, series) {
1015
+ const emptyColor = {
1016
+ [EnumTheme.light]: void 0,
1017
+ [EnumTheme.dark]: void 0
1018
+ };
1019
+ const segmentStyle = resolveSeriesSegment(rankValue, series).style;
1020
+ if (!segmentStyle || typeof segmentStyle === "string") {
1021
+ return {};
1022
+ }
1023
+ const style = resolveStyle(segmentStyle);
1024
+ const textColor = style.textColor || emptyColor;
1025
+ const backgroundColor = style.backgroundColor || emptyColor;
1026
+ return {
1027
+ color: textColor[props.theme],
1028
+ backgroundColor: backgroundColor[props.theme]
1029
+ };
1030
+ }
1031
+ function getStatusSolutions(status) {
1032
+ return [...status.solutions || []].reverse();
1033
+ }
1034
+ function getProblemStatisticsFooterCellPrimary(key, stat) {
1035
+ switch (key) {
1036
+ case "accepted":
1037
+ return stat.accepted;
1038
+ case "tried":
1039
+ return stat.tried;
1040
+ case "submitted":
1041
+ return stat.submitted;
1042
+ case "dirt":
1043
+ return stat.dirt;
1044
+ case "se":
1045
+ return formatProblemStatisticsAverageHardness(stat);
1046
+ case "firstAccepted":
1047
+ return formatProblemStatisticsAcceptedMinute(stat.firstAcceptedTime);
1048
+ case "lastAccepted":
1049
+ return formatProblemStatisticsAcceptedMinute(stat.lastAcceptedTime);
1050
+ default:
1051
+ return "";
1052
+ }
1053
+ }
1054
+ function getProblemStatisticsFooterCellSecondary(key, stat) {
1055
+ switch (key) {
1056
+ case "accepted":
1057
+ return formatProblemStatisticsPercent(stat.accepted, stat.participantCount);
1058
+ case "tried":
1059
+ return formatProblemStatisticsPercent(stat.tried, stat.participantCount);
1060
+ case "dirt":
1061
+ return formatProblemStatisticsPercent(stat.dirt, stat.dirtSubmitted);
1062
+ default:
1063
+ return void 0;
1064
+ }
1065
+ }
1066
+ function emitUserClick(payloadOrRow, rowIndex, event) {
1067
+ if ("ranklist" in payloadOrRow) {
1068
+ emit("userClick", payloadOrRow);
1069
+ return;
1070
+ }
1071
+ if (event) {
1072
+ captureModalTriggerPointFromMouseEvent(event, {
1073
+ source: "user-cell",
1074
+ context: {
1075
+ rowIndex: rowIndex || 0,
1076
+ userId: payloadOrRow.user.id || null,
1077
+ userName: resolveText(payloadOrRow.user.name)
1078
+ }
1079
+ });
1080
+ }
1081
+ emit("userClick", {
1082
+ user: payloadOrRow.user,
1083
+ row: payloadOrRow,
1084
+ rowIndex: rowIndex || 0,
1085
+ ranklist: props.data
1086
+ });
1087
+ }
1088
+ function emitSolutionClick(payloadOrRow, rowIndex, status, problemIndex, event) {
1089
+ if ("solutions" in payloadOrRow) {
1090
+ emit("solutionClick", payloadOrRow);
1091
+ return;
1092
+ }
1093
+ const resolvedProblemIndex = problemIndex || 0;
1094
+ const resolvedStatus = status || payloadOrRow.statuses[resolvedProblemIndex];
1095
+ if (event) {
1096
+ const problem = props.data.problems[resolvedProblemIndex];
1097
+ captureModalTriggerPointFromMouseEvent(event, {
1098
+ source: "status-cell",
1099
+ context: {
1100
+ rowIndex: rowIndex || 0,
1101
+ problemIndex: resolvedProblemIndex,
1102
+ problemAlias: (problem == null ? void 0 : problem.alias) || null,
1103
+ problemTitle: problem ? resolveText(problem.title) : null,
1104
+ userId: payloadOrRow.user.id || null
1105
+ }
1106
+ });
1107
+ }
1108
+ emit("solutionClick", {
1109
+ user: payloadOrRow.user,
1110
+ row: payloadOrRow,
1111
+ rowIndex: rowIndex || 0,
1112
+ problemIndex: resolvedProblemIndex,
1113
+ problem: props.data.problems[resolvedProblemIndex],
1114
+ status: resolvedStatus,
1115
+ solutions: getStatusSolutions(resolvedStatus),
1116
+ ranklist: props.data
1117
+ });
1118
+ }
1119
+ return (_ctx, _cache) => {
1120
+ return __props.data.type !== "general" ? (openBlock(), createElementBlock("div", _hoisted_1, 'srk type "' + toDisplayString(__props.data.type) + '" is not supported', 1)) : !isSupportedVersion.value ? (openBlock(), createElementBlock("div", _hoisted_2, ' srk version "' + toDisplayString(__props.data.version) + '" is not supported (current supported: ' + toDisplayString(unref(supportedVersions)) + ") ", 1)) : (openBlock(), createElementBlock("div", _hoisted_3, [
1121
+ createElementVNode("table", {
1122
+ class: normalizeClass({
1123
+ "srk-table-row-bordered": __props.borderedRows || __props.rowBordered,
1124
+ "srk-table-column-bordered": __props.columnBordered,
1125
+ "srk-table-row-striped": __props.stripedRows
1126
+ })
1127
+ }, [
1128
+ createElementVNode("thead", null, [
1129
+ createElementVNode("tr", null, [
1130
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.data.series, (seriesItem, seriesIndex) => {
1131
+ return openBlock(), createElementBlock("th", {
1132
+ key: seriesItem.title,
1133
+ class: normalizeClass(["srk-series-header srk--text-right srk--nowrap", { "srk-series-segmented-column": isSeriesSegmentedColumn(seriesItem) }])
1134
+ }, toDisplayString(resolveSeriesColumnTitle(seriesItem, seriesIndex)), 3);
1135
+ }), 128)),
1136
+ __props.splitOrganization ? (openBlock(), createElementBlock("th", _hoisted_4, toDisplayString(resolveColumnTitle("organization", "Organization")), 1)) : createCommentVNode("", true),
1137
+ createElementVNode("th", _hoisted_5, toDisplayString(resolveColumnTitle("user", "Name")), 1),
1138
+ createElementVNode("th", _hoisted_6, toDisplayString(resolveColumnTitle("score", "Score")), 1),
1139
+ showTimeColumn.value ? (openBlock(), createElementBlock("th", _hoisted_7, toDisplayString(resolveColumnTitle("time", "Time")), 1)) : createCommentVNode("", true),
1140
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.data.problems, (problem, problemIndex) => {
1141
+ return renderSlot(_ctx.$slots, "problem-header-cell", mergeProps({
1142
+ key: problem.alias || unref(resolveText)(problem.title) || problemIndex,
1143
+ ref_for: true
1144
+ }, { problem, problemIndex, index: problemIndex, theme: resolvedTheme.value }), () => [
1145
+ createVNode(_sfc_main$3, {
1146
+ problem,
1147
+ index: problemIndex,
1148
+ theme: resolvedTheme.value
1149
+ }, null, 8, ["problem", "index", "theme"])
1150
+ ]);
1151
+ }), 128)),
1152
+ __props.showDirtColumn ? (openBlock(), createElementBlock("th", _hoisted_8, toDisplayString(resolveColumnTitle("dirt", "Dirt")), 1)) : createCommentVNode("", true),
1153
+ __props.showSEColumn ? (openBlock(), createElementBlock("th", _hoisted_9, toDisplayString(resolveColumnTitle("se", "SE")), 1)) : createCommentVNode("", true)
1154
+ ])
1155
+ ]),
1156
+ createElementVNode("tbody", null, [
1157
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.data.rows, (row, rowIndex) => {
1158
+ return openBlock(), createElementBlock("tr", {
1159
+ key: row.user.id || unref(resolveText)(row.user.name)
1160
+ }, [
1161
+ (openBlock(true), createElementBlock(Fragment, null, renderList(getRankValues(row), (rankValue, seriesIndex) => {
1162
+ var _a;
1163
+ return openBlock(), createElementBlock("td", {
1164
+ key: ((_a = __props.data.series[seriesIndex]) == null ? void 0 : _a.title) || seriesIndex,
1165
+ class: normalizeClass(["srk--text-right srk--nowrap", [
1166
+ getSeriesSegmentClass(rankValue, __props.data.series[seriesIndex]),
1167
+ { "srk-series-segmented-column": isSeriesSegmentedColumn(__props.data.series[seriesIndex]) }
1168
+ ]]),
1169
+ style: normalizeStyle(getSeriesSegmentStyle(rankValue, __props.data.series[seriesIndex]))
1170
+ }, toDisplayString(getRankText(rankValue, row)), 7);
1171
+ }), 128)),
1172
+ __props.splitOrganization ? (openBlock(), createElementBlock("td", {
1173
+ key: 0,
1174
+ class: normalizeClass(["srk-organization-cell srk--text-left srk--nowrap", { "srk-organization-cell-avatar": showAvatarInOrganization.value && !!row.user.avatar }])
1175
+ }, [
1176
+ createElementVNode("div", _hoisted_10, [
1177
+ showAvatarInOrganization.value && row.user.avatar ? (openBlock(), createElementBlock("div", _hoisted_11, [
1178
+ createElementVNode("img", {
1179
+ src: formatAssetUrl(row.user.avatar, "user.avatar"),
1180
+ alt: "User Avatar"
1181
+ }, null, 8, _hoisted_12)
1182
+ ])) : createCommentVNode("", true),
1183
+ createElementVNode("span", {
1184
+ class: "srk-organization-name-text",
1185
+ title: row.user.organization ? unref(resolveText)(row.user.organization) : ""
1186
+ }, toDisplayString(row.user.organization ? unref(resolveText)(row.user.organization) : ""), 9, _hoisted_13)
1187
+ ])
1188
+ ], 2)) : createCommentVNode("", true),
1189
+ renderSlot(_ctx.$slots, "user-cell", mergeProps({ ref_for: true }, {
1190
+ user: row.user,
1191
+ row,
1192
+ rowIndex,
1193
+ ranklist: __props.data,
1194
+ markers: __props.data.markers,
1195
+ theme: resolvedTheme.value,
1196
+ hideOrganization: __props.splitOrganization,
1197
+ hideAvatar: showAvatarInOrganization.value,
1198
+ onClick: (event) => emitUserClick(row, rowIndex, event)
1199
+ }), () => [
1200
+ createVNode(_sfc_main$1, {
1201
+ user: row.user,
1202
+ row,
1203
+ "row-index": rowIndex,
1204
+ ranklist: __props.data,
1205
+ markers: __props.data.markers,
1206
+ theme: resolvedTheme.value,
1207
+ "format-srk-asset-url": formatAssetUrl,
1208
+ "on-user-click": emitUserClick,
1209
+ "hide-organization": __props.splitOrganization,
1210
+ "hide-avatar": showAvatarInOrganization.value
1211
+ }, null, 8, ["user", "row", "row-index", "ranklist", "markers", "theme", "hide-organization", "hide-avatar"])
1212
+ ]),
1213
+ createElementVNode("td", _hoisted_14, toDisplayString(row.score.value), 1),
1214
+ showTimeColumn.value ? (openBlock(), createElementBlock("td", _hoisted_15, toDisplayString(row.score.time ? unref(formatTimeDuration)(row.score.time, "min", Math.floor) : "-"), 1)) : createCommentVNode("", true),
1215
+ (openBlock(true), createElementBlock(Fragment, null, renderList(row.statuses, (status, problemIndex) => {
1216
+ var _a;
1217
+ return renderSlot(_ctx.$slots, "status-cell", mergeProps({
1218
+ key: ((_a = __props.data.problems[problemIndex]) == null ? void 0 : _a.alias) || problemIndex,
1219
+ ref_for: true
1220
+ }, {
1221
+ status,
1222
+ problem: __props.data.problems[problemIndex],
1223
+ problemIndex,
1224
+ user: row.user,
1225
+ row,
1226
+ rowIndex,
1227
+ ranklist: __props.data,
1228
+ solutions: getStatusSolutions(status),
1229
+ statusCellPreset: __props.statusCellPreset,
1230
+ statusColorAsText: __props.statusColorAsText,
1231
+ emptyStatusPlaceholder: __props.emptyStatusPlaceholder,
1232
+ onClick: (event) => emitSolutionClick(row, rowIndex, status, problemIndex, event)
1233
+ }), () => [
1234
+ createVNode(_sfc_main$2, {
1235
+ status,
1236
+ problem: __props.data.problems[problemIndex],
1237
+ "problem-index": problemIndex,
1238
+ user: row.user,
1239
+ row,
1240
+ "row-index": rowIndex,
1241
+ ranklist: __props.data,
1242
+ "on-solution-click": emitSolutionClick,
1243
+ "status-cell-preset": __props.statusCellPreset,
1244
+ "status-color-as-text": __props.statusColorAsText,
1245
+ "empty-status-placeholder": __props.emptyStatusPlaceholder
1246
+ }, null, 8, ["status", "problem", "problem-index", "user", "row", "row-index", "ranklist", "status-cell-preset", "status-color-as-text", "empty-status-placeholder"])
1247
+ ]);
1248
+ }), 128)),
1249
+ __props.showDirtColumn ? (openBlock(), createElementBlock("td", _hoisted_16, toDisplayString(unref(calculateDirtPercentage)(row)), 1)) : createCommentVNode("", true),
1250
+ __props.showSEColumn ? (openBlock(), createElementBlock("td", _hoisted_17, toDisplayString(unref(calculateSEValue)(row, problemStatistics.value)), 1)) : createCommentVNode("", true)
1251
+ ]);
1252
+ }), 128))
1253
+ ]),
1254
+ __props.showProblemStatisticsFooter ? (openBlock(), createElementBlock("tfoot", _hoisted_18, [
1255
+ (openBlock(), createElementBlock(Fragment, null, renderList(problemStatisticsFooterRows, (footerRow) => {
1256
+ return createElementVNode("tr", {
1257
+ key: footerRow.key,
1258
+ class: "srk-problem-statistics-footer-row"
1259
+ }, [
1260
+ createElementVNode("td", {
1261
+ class: "srk-problem-statistics-footer-labels srk--text-right srk--nowrap",
1262
+ colspan: leftFooterColumnCount.value
1263
+ }, [
1264
+ createElementVNode("span", {
1265
+ class: "srk-problem-statistics-footer-label srk--c-tooltip",
1266
+ "data-tooltip": footerRow.tooltip
1267
+ }, toDisplayString(footerRow.label), 9, _hoisted_20)
1268
+ ], 8, _hoisted_19),
1269
+ (openBlock(true), createElementBlock(Fragment, null, renderList(problemStatistics.value, (stat, problemIndex) => {
1270
+ var _a;
1271
+ return openBlock(), createElementBlock("td", {
1272
+ key: ((_a = __props.data.problems[problemIndex]) == null ? void 0 : _a.alias) || problemIndex,
1273
+ class: "srk-problem-statistics-footer-cell srk--text-center srk--nowrap"
1274
+ }, [
1275
+ createElementVNode("span", _hoisted_21, toDisplayString(getProblemStatisticsFooterCellPrimary(footerRow.key, stat)), 1),
1276
+ getProblemStatisticsFooterCellSecondary(footerRow.key, stat) !== void 0 ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
1277
+ _cache[0] || (_cache[0] = createTextVNode(toDisplayString(" ") + " ", -1)),
1278
+ createElementVNode("span", _hoisted_22, toDisplayString(getProblemStatisticsFooterCellSecondary(footerRow.key, stat)), 1)
1279
+ ], 64)) : createCommentVNode("", true)
1280
+ ]);
1281
+ }), 128)),
1282
+ __props.showDirtColumn ? (openBlock(), createElementBlock("td", _hoisted_23, [..._cache[1] || (_cache[1] = [
1283
+ createElementVNode("span", { class: "srk-problem-statistics-footer-primary" }, null, -1)
1284
+ ])])) : createCommentVNode("", true),
1285
+ __props.showSEColumn ? (openBlock(), createElementBlock("td", _hoisted_24, [..._cache[2] || (_cache[2] = [
1286
+ createElementVNode("span", { class: "srk-problem-statistics-footer-primary" }, null, -1)
1287
+ ])])) : createCommentVNode("", true)
1288
+ ]);
1289
+ }), 64)),
1290
+ createElementVNode("tr", _hoisted_25, [
1291
+ createElementVNode("td", {
1292
+ class: "srk-problem-statistics-footer-labels srk--text-right srk--nowrap",
1293
+ colspan: leftFooterColumnCount.value
1294
+ }, null, 8, _hoisted_26),
1295
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.data.problems, (problem, problemIndex) => {
1296
+ return openBlock(), createElementBlock("td", {
1297
+ key: problem.alias || unref(resolveText)(problem.title) || problemIndex,
1298
+ class: "srk-problem-statistics-footer-cell srk-problem-statistics-footer-problem-header srk-problem-header srk--text-center srk--nowrap",
1299
+ style: normalizeStyle({ backgroundImage: unref(getProblemHeaderBackgroundImage)(problem.style, resolvedTheme.value, 0) })
1300
+ }, [
1301
+ createElementVNode("span", _hoisted_27, toDisplayString(problem.alias || unref(numberToAlphabet)(problemIndex)), 1)
1302
+ ], 4);
1303
+ }), 128)),
1304
+ __props.showDirtColumn ? (openBlock(), createElementBlock("td", _hoisted_28, [..._cache[3] || (_cache[3] = [
1305
+ createElementVNode("span", { class: "srk-problem-statistics-footer-primary" }, null, -1)
1306
+ ])])) : createCommentVNode("", true),
1307
+ __props.showSEColumn ? (openBlock(), createElementBlock("td", _hoisted_29, [..._cache[4] || (_cache[4] = [
1308
+ createElementVNode("span", { class: "srk-problem-statistics-footer-primary" }, null, -1)
1309
+ ])])) : createCommentVNode("", true)
1310
+ ])
1311
+ ])) : createCommentVNode("", true)
1312
+ ], 2)
1313
+ ]));
1314
+ };
1315
+ }
1316
+ });
1317
+ export { _sfc_main$6 as DefaultSolutionModal, _sfc_main$5 as DefaultUserModal, _sfc_main$7 as Modal, _sfc_main$4 as ProgressBar, _sfc_main as Ranklist };