@juki-team/commons 0.1.40 → 0.1.42

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/esm/index.js CHANGED
@@ -598,6 +598,9 @@ var WebSocketSubscriptionEvent;
598
598
  WebSocketSubscriptionEvent["UNSUBSCRIBE_CLIENT_TRACK"] = "UNSUBSCRIBE_CLIENT_TRACK";
599
599
  WebSocketSubscriptionEvent["SUBSCRIBE_USER_NOTIFICATION"] = "SUBSCRIBE_USER_NOTIFICATION";
600
600
  WebSocketSubscriptionEvent["UNSUBSCRIBE_USER_NOTIFICATION"] = "UNSUBSCRIBE_USER_NOTIFICATION";
601
+ // an administrator watching the data (screenshots, location, device) sent by another client
602
+ WebSocketSubscriptionEvent["SUBSCRIBE_CLIENT_TRACK_DATA"] = "SUBSCRIBE_CLIENT_TRACK_DATA";
603
+ WebSocketSubscriptionEvent["UNSUBSCRIBE_CLIENT_TRACK_DATA"] = "UNSUBSCRIBE_CLIENT_TRACK_DATA";
601
604
  })(WebSocketSubscriptionEvent || (WebSocketSubscriptionEvent = {}));
602
605
  var WebSocketResponseEvent;
603
606
  (function (WebSocketResponseEvent) {
@@ -621,6 +624,20 @@ var WebSocketResponseEvent;
621
624
  WebSocketResponseEvent["USER_NOTIFICATION_SUBMISSION"] = "USER_NOTIFICATION_SUBMISSION";
622
625
  WebSocketResponseEvent["USER_NOTIFICATION_CONTEST_CLARIFICATION"] = "USER_NOTIFICATION_CONTEST_CLARIFICATION";
623
626
  })(WebSocketResponseEvent || (WebSocketResponseEvent = {}));
627
+ /**
628
+ * Roles of a contest, with the same names as the contest members in the DB.
629
+ * Each role has its own Ably channel: `contest:{contestKey}:{role}` (see `CHANNEL_CONTEST`).
630
+ * The inclusions follow `getContestAccessPermissions`:
631
+ * spectators ⊇ managers ⊇ administrators, spectators ⊇ participants, spectators ⊇ guests
632
+ */
633
+ var ContestChannelRole;
634
+ (function (ContestChannelRole) {
635
+ ContestChannelRole["ADMINISTRATORS"] = "administrators";
636
+ ContestChannelRole["MANAGERS"] = "managers";
637
+ ContestChannelRole["PARTICIPANTS"] = "participants";
638
+ ContestChannelRole["GUESTS"] = "guests";
639
+ ContestChannelRole["SPECTATORS"] = "spectators";
640
+ })(ContestChannelRole || (ContestChannelRole = {}));
624
641
 
625
642
  var DataViewMode;
626
643
  (function (DataViewMode) {
@@ -1378,21 +1395,6 @@ const COURSE_ROLE = {
1378
1395
  [CourseRole.SUPER_ADMIN]: { value: CourseRole.SUPER_ADMIN, label: 'super admin', level: 0 },
1379
1396
  };
1380
1397
 
1381
- const isWorksheetAssignment = (assignment) => {
1382
- return assignment.type === AssignmentClass.WORKSHEET;
1383
- };
1384
- const isCourseAssignment = (assignment) => {
1385
- return assignment.type === AssignmentClass.COURSE;
1386
- };
1387
- const isContestAssignment = (assignment) => {
1388
- return assignment.type === AssignmentClass.CONTEST;
1389
- };
1390
-
1391
- const getAssignmentCommentKey = (classKey, cycleKey, sessionKey, assignmentKey) => `class:${classKey}|cycle:${cycleKey}|session:${sessionKey}|assignment:${assignmentKey}`;
1392
- const getAssignmentUserCommentKey = (classKey, cycleKey, sessionKey, assignmentKey, userNickname, userCompany) => `class:${classKey}|cycle:${cycleKey}|session:${sessionKey}|assignment:${assignmentKey}|user_nickname:${userNickname}|user_company:${userCompany}`;
1393
- const getProblemCommentKey = (problemKey) => `problem:${problemKey}`;
1394
- const getContestCommentKey = (contestKey) => `contest:${contestKey}`;
1395
-
1396
1398
  function isStringJson(str) {
1397
1399
  try {
1398
1400
  if (typeof str === 'string') {
@@ -1580,484 +1582,384 @@ const areArraysDifferent = (a, b) => {
1580
1582
  return false;
1581
1583
  };
1582
1584
 
1583
- const isEndlessContest = (settings) => {
1584
- return settings?.startTimestamp === MIN_DATE.getTime()
1585
- && settings?.frozenTimestamp === MAX_DATE.getTime()
1586
- && settings?.quietTimestamp === MAX_DATE.getTime()
1587
- && settings?.endTimestamp === MAX_DATE.getTime()
1588
- && settings?.penalty === 0;
1589
- };
1590
- const isGlobalContest = (settings) => {
1591
- return settings?.startTimestamp === 0
1592
- && settings?.frozenTimestamp === 0
1593
- && settings?.quietTimestamp === 0
1594
- && settings?.endTimestamp === 0
1595
- && settings?.penalty === 0;
1596
- };
1597
- const isPastContest = (settings) => {
1598
- return Date.now() > (settings?.endTimestamp ?? 0);
1599
- };
1600
- const isFutureContest = (settings) => {
1601
- return (settings?.startTimestamp ?? 0) > Date.now();
1602
- };
1603
-
1604
- const getDocumentAccess = (document) => {
1605
- switch (true) {
1606
- case (document?.members?.rankAdministrators === EntityMembersRank.NONE || document?.members?.rankAdministrators === EntityMembersRank.CLOSE)
1607
- && document?.members?.rankManagers === EntityMembersRank.OPEN
1608
- && (document?.members?.rankGuests === EntityMembersRank.NONE || document?.members?.rankGuests === EntityMembersRank.CLOSE || document?.members?.rankGuests === EntityMembersRank.OPEN)
1609
- && document?.members?.rankSpectators === EntityMembersRank.OPEN
1610
- && (document?.members?.rankParticipants === EntityMembersRank.NONE || document?.members?.rankParticipants === EntityMembersRank.CLOSE || document?.members?.rankParticipants === EntityMembersRank.OPEN):
1611
- return EntityAccess.EXPOSED;
1612
- case (document?.members?.rankAdministrators === EntityMembersRank.NONE || document?.members?.rankAdministrators === EntityMembersRank.CLOSE)
1613
- && document?.members?.rankManagers === EntityMembersRank.CLOSE
1614
- && (document?.members?.rankGuests === EntityMembersRank.NONE || document?.members?.rankGuests === EntityMembersRank.CLOSE || document?.members?.rankGuests === EntityMembersRank.OPEN)
1615
- && document?.members?.rankSpectators === EntityMembersRank.OPEN
1616
- && (document?.members?.rankParticipants === EntityMembersRank.NONE || document?.members?.rankParticipants === EntityMembersRank.CLOSE || document?.members?.rankParticipants === EntityMembersRank.OPEN):
1617
- return EntityAccess.PUBLIC;
1618
- case (document?.members?.rankAdministrators === EntityMembersRank.NONE || document?.members?.rankAdministrators === EntityMembersRank.CLOSE)
1619
- && document?.members?.rankManagers === EntityMembersRank.CLOSE
1620
- && (document?.members?.rankGuests === EntityMembersRank.NONE || document?.members?.rankGuests === EntityMembersRank.CLOSE || document?.members?.rankGuests === EntityMembersRank.OPEN)
1621
- && document?.members?.rankSpectators === EntityMembersRank.CLOSE
1622
- && (document?.members?.rankParticipants === EntityMembersRank.NONE || document?.members?.rankParticipants === EntityMembersRank.CLOSE || document?.members?.rankParticipants === EntityMembersRank.OPEN):
1623
- return EntityAccess.RESTRICTED;
1624
- case document?.members?.rankAdministrators === EntityMembersRank.NONE
1625
- && document?.members?.rankManagers === EntityMembersRank.NONE
1626
- && document?.members?.rankGuests === EntityMembersRank.NONE
1627
- && document?.members?.rankSpectators === EntityMembersRank.NONE
1628
- && document?.members?.rankParticipants === EntityMembersRank.NONE:
1629
- return EntityAccess.PRIVATE;
1630
- default:
1631
- return EntityAccess.PRIVATE;
1632
- }
1633
- };
1634
- const isUserMember = (member) => {
1635
- return typeof member.userId === 'string';
1636
- };
1637
- const isTeamMember = (member) => {
1638
- return typeof member.teamId === 'string';
1639
- };
1640
- const toEntityMembersDTO = (members) => {
1641
- return {
1642
- rankAdministrators: members.rankAdministrators,
1643
- administrators: Object.keys(members.administrators),
1644
- rankManagers: members.rankManagers,
1645
- managers: Object.keys(members.managers),
1646
- rankParticipants: members.rankParticipants,
1647
- participants: Object.keys(members.participants),
1648
- rankGuests: members.rankGuests,
1649
- guests: Object.keys(members.guests),
1650
- rankSpectators: members.rankSpectators,
1651
- spectators: Object.keys(members.spectators),
1652
- };
1653
- };
1585
+ const YEARS = range(1970, 2100);
1586
+ const MONTH_NAMES = [
1587
+ 'January',
1588
+ 'February',
1589
+ 'March',
1590
+ 'April',
1591
+ 'May',
1592
+ 'June',
1593
+ 'July',
1594
+ 'August',
1595
+ 'September',
1596
+ 'October',
1597
+ 'November',
1598
+ 'December',
1599
+ ];
1600
+ const DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
1601
+ const HOURS = range(0, 24);
1602
+ const MINUTES = range(0, 60);
1603
+ const SECONDS = range(0, 60);
1604
+ const MILLISECONDS = range(0, 1000);
1605
+ const MAX_DATE = new Date(8640000000000000);
1606
+ const MIN_DATE = new Date(0);
1654
1607
 
1655
- function removeExtension(fileName) {
1656
- const i = fileName.lastIndexOf('.');
1657
- return i !== -1 ? fileName.substring(0, i) : fileName;
1658
- }
1608
+ const SUPPORT_EMAIL = 'support@juki.app';
1609
+ const JUKI_APP_EMAIL_TEMPLATE = `<div style="width: 100%; background: #F2F2F2;">
1610
+ <div style="background: #164066; width: 100%;">
1611
+ <div style="height: 56px; color: white; width: 100px; margin: 0 auto">
1612
+ <img
1613
+ src="https://images.juki.pub/assets/juki-app-horizontal-white-logo.svg"
1614
+ alt="juki app logo"
1615
+ height="56px"
1616
+ style="padding:10px; box-sizing: border-box"
1617
+ />
1618
+ </div>
1619
+ </div>
1620
+ <div style="padding: 24px; color: #333333; font-family: sans-serif; font-size: 16px; line-height: 24px;">
1621
+ <div style="max-width: 520px; margin: 0 auto; padding: 24px; background: white; border-radius: 6px;">
1622
+ <section style="padding: 0 0 1em 0; border-bottom: 1px solid #828282;">
1623
+ {{content}}
1624
+ </section>
1625
+ <div style="font-size: 14px; text-align: center; color: #828282; line-height: 16px; padding-top: 1em">
1626
+ <p style="margin: 0;">
1627
+ Si tú no realizaste la solicitud, escribenos a
1628
+ <a href="mailto:${SUPPORT_EMAIL}" style="color: #2468A6; text-decoration: none;">
1629
+ ${SUPPORT_EMAIL}
1630
+ </a>
1631
+ </p>
1632
+ <p style="margin: 0;">
1633
+ Este mensaje fue enviado por el equipo de
1634
+ <a href="https://juki.app" style="color: #2468A6; text-decoration: none;">
1635
+ juki.app
1636
+ </a>
1637
+ </p>
1638
+ </div>
1639
+ </div>
1640
+ </div>
1641
+ </div>`;
1659
1642
 
1660
- // https://dev.to/jsmccrumb/asynchronous-setinterval-4j69
1661
- const asyncIntervals = [];
1662
- const runAsyncInterval = async (cb, interval, intervalIndex) => {
1663
- await cb();
1664
- if (asyncIntervals[intervalIndex]) {
1665
- setTimeout(() => runAsyncInterval(cb, interval, intervalIndex), interval);
1666
- }
1667
- };
1668
- const setAsyncInterval = (cb, interval) => {
1669
- if (cb && typeof cb === 'function') {
1670
- const intervalIndex = asyncIntervals.length;
1671
- asyncIntervals.push(true);
1672
- void runAsyncInterval(cb, interval, intervalIndex);
1673
- return intervalIndex;
1674
- }
1675
- else {
1676
- throw new Error('Callback must be a function');
1677
- }
1678
- };
1679
- const clearAsyncInterval = (intervalIndex) => {
1680
- if (asyncIntervals[intervalIndex]) {
1681
- asyncIntervals[intervalIndex] = false;
1682
- }
1683
- };
1643
+ const EMPTY_DOCUMENT_MEMBERS = () => ({
1644
+ access: EntityAccess.PRIVATE,
1645
+ managers: {},
1646
+ spectators: {},
1647
+ });
1648
+ const EMPTY_ENTITY_MEMBERS = () => ({
1649
+ rankAdministrators: EntityMembersRank.CLOSE,
1650
+ administrators: {},
1651
+ rankManagers: EntityMembersRank.CLOSE,
1652
+ managers: {},
1653
+ rankGuests: EntityMembersRank.CLOSE,
1654
+ guests: {},
1655
+ rankSpectators: EntityMembersRank.CLOSE,
1656
+ spectators: {},
1657
+ rankParticipants: EntityMembersRank.CLOSE,
1658
+ participants: {},
1659
+ });
1684
1660
 
1685
- const getDataOfTestCase = (testCase, timeLimit, memoryLimit) => {
1686
- const { timeUsed, memoryUsed, exitCode } = getDataLog(testCase?.log);
1687
- const timeLimitExceeded = timeUsed > timeLimit;
1688
- const memoryLimitExceeded = memoryUsed > memoryLimit;
1689
- const runtimeError = exitCode !== 0;
1690
- const compilationError = testCase?.status === SubmissionRunStatus.COMPILATION_ERROR;
1691
- return {
1692
- compilationError,
1693
- timeUsed,
1694
- timeLimitExceeded: timeLimitExceeded,
1695
- memoryUsed,
1696
- memoryLimitExceeded: memoryLimitExceeded,
1697
- exitCode,
1698
- runtimeError,
1699
- failed: !!testCase?.log && (timeLimitExceeded || memoryLimitExceeded || runtimeError),
1700
- };
1701
- };
1702
- const getVerdictFromTestCase = (testCaseValue, timeLimit, memoryLimit) => {
1703
- const { compilationError, timeLimitExceeded, memoryLimitExceeded, runtimeError, timeUsed, memoryUsed, exitCode, } = getDataOfTestCase(testCaseValue, timeLimit, memoryLimit);
1704
- return {
1705
- verdict: compilationError
1706
- ? ProblemVerdict.CE
1707
- : timeLimitExceeded
1708
- ? ProblemVerdict.TLE
1709
- : memoryLimitExceeded
1710
- ? ProblemVerdict.MLE
1711
- : runtimeError
1712
- ? ProblemVerdict.RE
1713
- : testCaseValue.out === testCaseValue.testOut
1714
- ? ProblemVerdict.AC
1715
- : testCaseValue.withPE && testCaseValue.out.split(' ').join('').split('\n').join('') === testCaseValue.testOut.split(' ').join('').split('\n').join('')
1716
- ? ProblemVerdict.PE
1717
- : !testCaseValue.withPE && testCaseValue.out.split(' ').join('').split('\n').join('') === testCaseValue.testOut.split(' ').join('').split('\n').join('')
1718
- ? ProblemVerdict.AC
1719
- : ProblemVerdict.WA,
1720
- timeUsed,
1721
- memoryUsed,
1722
- exitCode,
1723
- };
1724
- };
1725
- const mergeVerdicts = (first, second) => {
1726
- let verdict = first.verdict;
1727
- if (second.verdict === ProblemVerdict.RE) {
1728
- verdict = ProblemVerdict.RE;
1729
- }
1730
- else if (second.verdict === ProblemVerdict.TLE && verdict != ProblemVerdict.RE) {
1731
- verdict = ProblemVerdict.TLE;
1732
- }
1733
- else if (second.verdict === ProblemVerdict.MLE
1734
- && verdict !== ProblemVerdict.TLE
1735
- && verdict !== ProblemVerdict.RE) {
1736
- verdict = ProblemVerdict.MLE;
1737
- }
1738
- else if (second.verdict === ProblemVerdict.WA
1739
- && verdict !== ProblemVerdict.MLE
1740
- && verdict !== ProblemVerdict.TLE
1741
- && verdict !== ProblemVerdict.RE) {
1742
- verdict = ProblemVerdict.WA;
1743
- }
1744
- else if (second.verdict === ProblemVerdict.PE
1745
- && verdict !== ProblemVerdict.WA
1746
- && verdict !== ProblemVerdict.MLE
1747
- && verdict !== ProblemVerdict.TLE
1748
- && verdict !== ProblemVerdict.RE) {
1749
- verdict = ProblemVerdict.PE;
1750
- }
1751
- else if (second.verdict === ProblemVerdict.PA
1752
- && verdict !== ProblemVerdict.PE
1753
- && verdict !== ProblemVerdict.WA
1754
- && verdict !== ProblemVerdict.MLE
1755
- && verdict !== ProblemVerdict.TLE
1756
- && verdict !== ProblemVerdict.RE) {
1757
- verdict = ProblemVerdict.PA;
1758
- }
1759
- else if (second.verdict === ProblemVerdict.AC
1760
- && verdict !== ProblemVerdict.PA
1761
- && verdict !== ProblemVerdict.PE
1762
- && verdict !== ProblemVerdict.WA
1763
- && verdict !== ProblemVerdict.MLE
1764
- && verdict !== ProblemVerdict.TLE
1765
- && verdict !== ProblemVerdict.RE) {
1766
- verdict = ProblemVerdict.AC;
1767
- }
1768
- return {
1769
- timeUsed: Math.max(first.timeUsed, second.timeUsed),
1770
- memoryUsed: Math.max(first.memoryUsed, second.memoryUsed),
1771
- exitCode: first.exitCode || second.exitCode,
1772
- verdict,
1773
- };
1661
+ const JUDGE = {
1662
+ // [Judge.CUSTOMER]: {
1663
+ // value: Judge.CUSTOMER,
1664
+ // label: '',
1665
+ // logo: 'https://images.juki.pub/c/juki-judge-logo-horizontal-color.svg',
1666
+ // logoSize: [ 883.991, 435 ],
1667
+ // url: '',
1668
+ // // getLoginUrl: () => '',
1669
+ // // getProfileUrl: () => '',
1670
+ // // getSubmitUrl: () => '',
1671
+ // // getSubmissionUrl: () => '',
1672
+ // // getProblemUrl: (key: string) => `/problem/view/${key}`,
1673
+ // // getUserSubmissionsUrl: () => '',
1674
+ // },
1675
+ [Judge.JUKI_JUDGE]: {
1676
+ value: Judge.JUKI_JUDGE,
1677
+ label: 'Juki Judge',
1678
+ logo: 'https://images.juki.pub/c/juki-judge-logo-horizontal-color.svg',
1679
+ logoSize: [883.991, 435],
1680
+ url: 'https://judge.juki.app',
1681
+ // getLoginUrl: () => '',
1682
+ // getProfileUrl: () => '',
1683
+ // getSubmitUrl: () => '',
1684
+ // getSubmissionUrl: () => '',
1685
+ // getProblemUrl: (key: string) => `https://judge.juki.app/problem/view/${key}`,
1686
+ // getUserSubmissionsUrl: () => '',
1687
+ },
1688
+ [Judge.CODEFORCES]: {
1689
+ value: Judge.CODEFORCES,
1690
+ label: 'Codeforces',
1691
+ logo: 'https://images.juki.pub/c/codeforces-logo-horizontal-color.svg',
1692
+ logoSize: [1232.75, 145.12],
1693
+ url: 'https://codeforces.com',
1694
+ // getLoginUrl: () => 'https://codeforces.com/enter',
1695
+ // getProfileUrl: () => '',
1696
+ // getSubmitUrl: () => 'https://codeforces.com/problemset/submit',
1697
+ // getSubmissionUrl: (problemKey: string, submissionId: string) => {
1698
+ // const [ contestId ] = problemKey.split('-');
1699
+ // return `https://codeforces.com/problemset/submission/${contestId}/${submissionId}`;
1700
+ // },
1701
+ // getProblemUrl: (problemKey: string) => {
1702
+ // const [ contestId, index ] = problemKey.split('-');
1703
+ // return `https://codeforces.com/problemset/problem/${contestId}/${index}`;
1704
+ // },
1705
+ // getUserSubmissionsUrl: () => '',
1706
+ },
1707
+ [Judge.CODEFORCES_GYM]: {
1708
+ value: Judge.CODEFORCES_GYM,
1709
+ label: 'Codeforces Gym',
1710
+ logo: 'https://images.juki.pub/c/codeforces-logo-horizontal-color.svg',
1711
+ logoSize: [1232.75, 145.12],
1712
+ url: 'https://codeforces.com',
1713
+ // getLoginUrl: () => 'https://codeforces.com/enter',
1714
+ // getProfileUrl: () => '',
1715
+ // getSubmitUrl: (problemKey: string) => {
1716
+ // const [ gymContestId, index ] = problemKey.split('-');
1717
+ // return `https://codeforces.com/gym/${gymContestId}/submit`;
1718
+ // },
1719
+ // getSubmissionUrl: (problemKey: string, submissionId: string) => {
1720
+ // const [ gymContestId ] = problemKey.split('-');
1721
+ // return `https://codeforces.com/gym/${gymContestId}/submission/${submissionId}`;
1722
+ // },
1723
+ // getProblemUrl: (problemKey: string) => {
1724
+ // const [ gymContestId, index ] = problemKey.split('-');
1725
+ // return `https://codeforces.com/gym/${gymContestId}/problem/${index}`;
1726
+ // },
1727
+ // getUserSubmissionsUrl: () => '',
1728
+ },
1729
+ [Judge.JV_UMSA]: {
1730
+ value: Judge.JV_UMSA,
1731
+ label: 'Juez Virtual UMSA',
1732
+ logo: 'https://images.juki.pub/c/codeforces-logo-horizontal-color.svg',
1733
+ logoSize: [1232.75, 145.12],
1734
+ url: 'https://jv.umsa.bo',
1735
+ // getLoginUrl: () => 'https://jv.umsa.bo/oj/login.php',
1736
+ // getProfileUrl: () => 'https://jv.umsa.bo/oj/userInfo.php',
1737
+ // getSubmitUrl: (problemKey: string) => {
1738
+ // // single problem: '1019'
1739
+ // // cib problem: '1019-A'
1740
+ // const isContestProblem = problemKey.includes('-');
1741
+ // // A -> 0, B -> 1, C -> 2, D -> 3, E -> 4, F -> 5, G -> 6, H -> 7, I -> 8, J -> 9
1742
+ // const params = problemKey.split('-');
1743
+ // return isContestProblem
1744
+ // ? `https://jv.umsa.bo/oj/submitpage.php?cid=${params[0]}&pid=${params[1].charCodeAt(0) - 65}`
1745
+ // : `https://jv.umsa.bo/oj/submitpage.php?id=${problemKey}`;
1746
+ // },
1747
+ // getSubmissionUrl: (problemKey: string, submissionId: string, username: string) => {
1748
+ // // return `https://jv.umsa.bo/status.php?problem_id=&user_id=${username}&language=-1&jresult=-1`;
1749
+ // return `https://jv.umsa.bo/oj/showsource.php?id=${submissionId}`;
1750
+ // },
1751
+ // getProblemUrl: (problemKey: string) => {
1752
+ // const isContestProblem = problemKey.includes('-');
1753
+ // const params = problemKey.split('-');
1754
+ // return isContestProblem
1755
+ // ? `https://jv.umsa.bo/oj/problem.php?cid=${params[0]}&pid=${params[1].charCodeAt(0) - 65}`
1756
+ // : `https://jv.umsa.bo/oj/problem.php?id=${problemKey}`;
1757
+ // },
1758
+ // getUserSubmissionsUrl: (username: string) => `https://jv.umsa.bo/oj/status.php?user_id=${username}`,
1759
+ },
1760
+ [Judge.UVA_ONLINE_JUDGE]: {
1761
+ value: Judge.UVA_ONLINE_JUDGE,
1762
+ label: 'Uva Online Judge',
1763
+ logo: 'https://images.juki.pub/c/uva-online-judge-logo-color.png',
1764
+ logoSize: [150, 135.994],
1765
+ url: 'https://onlinejudge.org',
1766
+ },
1767
+ [Judge.AT_CODER]: {
1768
+ value: Judge.AT_CODER,
1769
+ label: 'AtCoder',
1770
+ logo: 'https://images.juki.pub/c/at-coder-logo-color.png',
1771
+ logoSize: [762.997, 675],
1772
+ url: 'https://atcoder.jp',
1773
+ },
1774
+ [Judge.CODECHEF]: {
1775
+ value: Judge.CODECHEF,
1776
+ label: 'Codechef',
1777
+ logo: 'https://images.juki.pub/c/codechef-logo-color.svg',
1778
+ logoSize: [1207.7, 453.17],
1779
+ url: 'https://www.codechef.com',
1780
+ },
1781
+ [Judge.TOPCODER]: {
1782
+ value: Judge.TOPCODER,
1783
+ label: 'Topcoder',
1784
+ logo: 'https://images.juki.pub/c/topcoder-logo-color.png',
1785
+ logoSize: [971.99, 415.99],
1786
+ url: 'https://www.topcoder.com',
1787
+ },
1788
+ [Judge.LEETCODE]: {
1789
+ value: Judge.LEETCODE,
1790
+ label: 'LeetCode',
1791
+ logo: 'https://images.juki.pub/assets/leetcode-logo-color.svg',
1792
+ logoSize: [95, 111],
1793
+ url: 'https://leetcode.com',
1794
+ // getProblemUrl: (problemKey: string) => {
1795
+ // return `https://leetcode.com/problems/${problemKey.replace('PL-', '')}`;
1796
+ // },
1797
+ // getProfileUrl: (userNickname: string) => {
1798
+ // return `https://leetcode.com/u/${userNickname}`;
1799
+ // },
1800
+ // getSubmissionUrl: (problemKey: string, submissionId: string, username: string, submissionRunId: string) => {
1801
+ // return `https://leetcode.com/problems/${problemKey.replace('PL-', '')}/submissions/${submissionRunId}`;
1802
+ // },
1803
+ },
1774
1804
  };
1775
- const getDataLog = (log) => {
1776
- const lines = log?.split?.('\n') || [];
1777
- let timeUsed = 0;
1778
- let memoryUsed = 0;
1779
- let exitCode = -1;
1780
- if (lines.length > 4) {
1781
- for (const line of lines) {
1782
- if (line.startsWith('time:')) {
1783
- timeUsed = +line.split(':')[1];
1784
- if (Number.isNaN(timeUsed)) {
1785
- timeUsed = 0;
1786
- }
1787
- timeUsed *= 1000;
1788
- }
1789
- else if (line.startsWith('max-rss:')) {
1790
- memoryUsed = parseInt(line.split(':')[1], 10); // en KB
1791
- }
1792
- else if (line.startsWith('exitcode:')) {
1793
- exitCode = parseInt(line.split(':')[1], 10);
1794
- }
1795
- }
1796
- }
1797
- else if (lines.length >= 3) {
1798
- timeUsed = +lines[0];
1799
- memoryUsed = +lines[1];
1800
- exitCode = +lines[2];
1801
- }
1802
- return {
1803
- timeUsed: Number.isNaN(timeUsed) ? 0 : timeUsed,
1804
- memoryUsed: Number.isNaN(memoryUsed) ? 0 : memoryUsed,
1805
- exitCode: Number.isNaN(exitCode) ? -1 : exitCode,
1806
- };
1805
+ const RUNNER_ACCEPTED_PROBLEM_MODES = [
1806
+ ProblemScoringMode.TOTAL,
1807
+ ProblemScoringMode.SUBTASK,
1808
+ ProblemScoringMode.PARTIAL,
1809
+ ];
1810
+ const RUNNER_ACCEPTED_PROBLEM_TYPES = [
1811
+ ProblemType.STANDARD,
1812
+ ProblemType.DYNAMIC,
1813
+ ];
1814
+ const RUNNER_ACCEPTED_PROGRAMMING_LANGUAGES = [
1815
+ CodeLanguage.C_11,
1816
+ CodeLanguage.CPP_11,
1817
+ CodeLanguage.CPP_20,
1818
+ CodeLanguage.JAVA_21,
1819
+ CodeLanguage.PYTHON_3,
1820
+ CodeLanguage.PYTHON_PYPY_3,
1821
+ CodeLanguage.JAVASCRIPT_NODE_JS_22,
1822
+ CodeLanguage.PSEUDOCODE_PSEINT,
1823
+ ];
1824
+ const ACCEPTED_PROGRAMMING_LANGUAGES = [
1825
+ ...RUNNER_ACCEPTED_PROGRAMMING_LANGUAGES,
1826
+ ];
1827
+ const PROBLEM_VERDICT = {
1828
+ [ProblemVerdict.NONE]: { value: ProblemVerdict.NONE, label: 'none', color: '#555555' },
1829
+ [ProblemVerdict.PENDING]: { value: ProblemVerdict.PENDING, label: 'pending', color: '#79B6FD' },
1830
+ [ProblemVerdict.HIDDEN]: { value: ProblemVerdict.HIDDEN, label: 'hidden', color: '#555555' },
1831
+ [ProblemVerdict.AC]: { value: ProblemVerdict.AC, label: 'accepted', color: '#43D787' },
1832
+ [ProblemVerdict.PE]: { value: ProblemVerdict.PE, label: 'presentation error', color: '#55db93' },
1833
+ [ProblemVerdict.PA]: { value: ProblemVerdict.PA, label: 'partial accepted', color: '#55db93' },
1834
+ [ProblemVerdict.CE]: { value: ProblemVerdict.CE, label: 'compilation error', color: '#FE9F9F' },
1835
+ [ProblemVerdict.RE]: { value: ProblemVerdict.RE, label: 'runtime error', color: '#FE9F9F' },
1836
+ [ProblemVerdict.TLE]: { value: ProblemVerdict.TLE, label: 'time limit exceed', color: '#FE9F9F' },
1837
+ [ProblemVerdict.MLE]: { value: ProblemVerdict.MLE, label: 'memory limit exceed', color: '#FE9F9F' },
1838
+ [ProblemVerdict.WA]: { value: ProblemVerdict.WA, label: 'wrong answer', color: '#FE9F9F' },
1807
1839
  };
1808
-
1809
- function memorySizeOf(obj) {
1810
- let bytes = 0;
1811
- function sizeOf(obj) {
1812
- if (obj !== null && obj !== undefined) {
1813
- switch (typeof obj) {
1814
- case "number":
1815
- bytes += 8;
1816
- break;
1817
- case "string":
1818
- bytes += obj.length * 2;
1819
- break;
1820
- case "boolean":
1821
- bytes += 4;
1822
- break;
1823
- case "object":
1824
- const objClass = Object.prototype.toString.call(obj).slice(8, -1);
1825
- if (objClass === "Object" || objClass === "Array") {
1826
- for (const key in obj) {
1827
- if (!obj.hasOwnProperty(key))
1828
- continue;
1829
- bytes += key.length * 2;
1830
- sizeOf(obj[key]);
1831
- }
1832
- }
1833
- else
1834
- bytes += obj.toString().length * 2;
1835
- break;
1836
- }
1837
- }
1838
- return bytes;
1839
- }
1840
- return sizeOf(obj);
1841
- }
1842
-
1843
- /* eslint-disable no-extend-native */
1844
- Date.prototype.changeYear = function (year) {
1845
- const newDate = new Date(this);
1846
- newDate.setFullYear(year);
1847
- return newDate;
1848
- };
1849
- Date.prototype.changeMonth = function (monthIndex) {
1850
- const newDate = new Date(this);
1851
- newDate.setMonth(monthIndex);
1852
- return newDate;
1853
- };
1854
- Date.prototype.changeDay = function (date) {
1855
- const newDate = new Date(this);
1856
- newDate.setDate(date);
1857
- return newDate;
1858
- };
1859
- Date.prototype.changeHours = function (hours) {
1860
- const newDate = new Date(this);
1861
- newDate.setHours(hours);
1862
- return newDate;
1863
- };
1864
- Date.prototype.changeMinutes = function (minutes) {
1865
- const newDate = new Date(this);
1866
- newDate.setMinutes(minutes);
1867
- return newDate;
1868
- };
1869
- Date.prototype.changeSeconds = function (seconds) {
1870
- const newDate = new Date(this);
1871
- newDate.setSeconds(seconds);
1872
- return newDate;
1873
- };
1874
- Date.prototype.changeMilliseconds = function (milliseconds) {
1875
- const newDate = new Date(this);
1876
- newDate.setMilliseconds(milliseconds);
1877
- return newDate;
1878
- };
1879
- Date.prototype.decreaseYear = function (count = 1) {
1880
- return this.changeYear(this.getFullYear() - count);
1881
- };
1882
- Date.prototype.increaseYear = function (count = 1) {
1883
- return this.changeYear(this.getFullYear() + count);
1884
- };
1885
- Date.prototype.decreaseMonth = function () {
1886
- const newDate = new Date(this);
1887
- newDate.setMonth(newDate.getMonth() - 1);
1888
- return newDate;
1889
- };
1890
- Date.prototype.increaseMonth = function () {
1891
- const newDate = new Date(this);
1892
- newDate.setMonth(newDate.getMonth() + 1);
1893
- return newDate;
1894
- };
1895
- Date.prototype.increaseDay = function () {
1896
- const newDate = new Date(this);
1897
- newDate.setDate(newDate.getDate() + 1);
1898
- return newDate;
1899
- };
1900
- Date.prototype.decreaseDay = function () {
1901
- const newDate = new Date(this);
1902
- newDate.setDate(newDate.getDate() - 1);
1903
- return newDate;
1904
- };
1905
- Date.prototype.startOfYear = function () {
1906
- const newDate = new Date(this);
1907
- newDate.setMonth(0);
1908
- return newDate.startOfMonth();
1909
- };
1910
- Date.prototype.endOfYear = function () {
1911
- const nextMonth = this.increaseYear().startOfYear();
1912
- return new Date(nextMonth.getTime() - 1);
1913
- };
1914
- Date.prototype.startOfMonth = function () {
1915
- const newDate = new Date(this);
1916
- newDate.setDate(1);
1917
- return newDate.startOfDay();
1918
- };
1919
- Date.prototype.endOfMonth = function () {
1920
- const nextMonth = this.increaseMonth().startOfMonth();
1921
- return new Date(nextMonth.getTime() - 1);
1922
- };
1923
- Date.prototype.startOfWeek = function () {
1924
- const newDate = new Date(this);
1925
- while (newDate.getDay()) {
1926
- newDate.setDate(newDate.getDate() - 1);
1927
- }
1928
- return newDate.startOfDay();
1929
- };
1930
- Date.prototype.endOfWeek = function () {
1931
- const newDate = new Date(this);
1932
- while (newDate.getDay() < 6) {
1933
- newDate.setDate(newDate.getDate() - 1);
1934
- }
1935
- return newDate.endOfDay();
1936
- };
1937
- Date.prototype.startOfDay = function () {
1938
- const newDate = new Date(this);
1939
- newDate.setHours(0, 0, 0, 0);
1940
- return newDate;
1941
- };
1942
- Date.prototype.endOfDay = function () {
1943
- const newDate = new Date(this);
1944
- newDate.setHours(23, 59, 59, 999);
1945
- return newDate;
1946
- };
1947
- Date.prototype.startOfHour = function () {
1948
- const newDate = new Date(this);
1949
- newDate.setMinutes(0, 0, 0);
1950
- return newDate;
1951
- };
1952
- Date.prototype.endOfHour = function () {
1953
- const newDate = new Date(this);
1954
- newDate.setMinutes(59, 59, 999);
1955
- return newDate;
1956
- };
1957
- Date.prototype.startOfMinute = function () {
1958
- const newDate = new Date(this);
1959
- newDate.setSeconds(0, 0);
1960
- return newDate;
1840
+ const PROBLEM_VERDICTS = [
1841
+ ProblemVerdict.NONE,
1842
+ ProblemVerdict.PENDING,
1843
+ ProblemVerdict.AC,
1844
+ ProblemVerdict.PE,
1845
+ ProblemVerdict.PA,
1846
+ ProblemVerdict.CE,
1847
+ ProblemVerdict.RE,
1848
+ ProblemVerdict.TLE,
1849
+ ProblemVerdict.MLE,
1850
+ ProblemVerdict.WA,
1851
+ ];
1852
+ const SUBMISSION_RUN_STATUS = {
1853
+ [SubmissionRunStatus.NONE]: { value: SubmissionRunStatus.NONE, label: 'none' }, // status
1854
+ [SubmissionRunStatus.RECEIVED]: { value: SubmissionRunStatus.RECEIVED, label: 'received' }, // state
1855
+ [SubmissionRunStatus.COMPILING]: { value: SubmissionRunStatus.COMPILING, label: 'compiling' }, // state
1856
+ [SubmissionRunStatus.COMPILED]: { value: SubmissionRunStatus.COMPILED, label: 'compiled' }, // status
1857
+ [SubmissionRunStatus.COMPILATION_ERROR]: { value: SubmissionRunStatus.COMPILATION_ERROR, label: 'compilation error' }, // status
1858
+ [SubmissionRunStatus.FETCHING_TEST_CASES]: {
1859
+ value: SubmissionRunStatus.FETCHING_TEST_CASES,
1860
+ label: 'fetching test cases',
1861
+ }, // state
1862
+ [SubmissionRunStatus.RUNNING_TEST_CASE]: { value: SubmissionRunStatus.RUNNING_TEST_CASE, label: 'running test case' }, // state
1863
+ [SubmissionRunStatus.RUNNING_TEST_CASES]: {
1864
+ value: SubmissionRunStatus.RUNNING_TEST_CASES,
1865
+ label: 'running test cases',
1866
+ }, // state
1867
+ [SubmissionRunStatus.RUNNING_SAMPLE_TEST_CASES]: {
1868
+ value: SubmissionRunStatus.RUNNING_SAMPLE_TEST_CASES,
1869
+ label: 'running sample cases',
1870
+ }, // state
1871
+ [SubmissionRunStatus.EXECUTED_TEST_CASE]: {
1872
+ value: SubmissionRunStatus.EXECUTED_TEST_CASE,
1873
+ label: 'executed test case',
1874
+ }, // status
1875
+ [SubmissionRunStatus.FAILED_TEST_CASE]: { value: SubmissionRunStatus.FAILED_TEST_CASE, label: 'failed test case' }, // status
1876
+ [SubmissionRunStatus.JUDGING_TEST_CASE]: { value: SubmissionRunStatus.JUDGING_TEST_CASE, label: 'judging test case' }, // state
1877
+ [SubmissionRunStatus.GRADING]: { value: SubmissionRunStatus.GRADING, label: 'grading' }, // status
1878
+ [SubmissionRunStatus.FAILED]: { value: SubmissionRunStatus.FAILED, label: 'failed' }, // status
1879
+ [SubmissionRunStatus.COMPLETED]: { value: SubmissionRunStatus.COMPLETED, label: 'completed' }, // status
1961
1880
  };
1962
- Date.prototype.endOfMinute = function () {
1963
- const newDate = new Date(this);
1964
- newDate.setSeconds(59, 999);
1965
- return newDate;
1881
+ const RUNNER_TYPE = {
1882
+ [RunnerType.HIGH_PERFORMANCE]: { value: RunnerType.HIGH_PERFORMANCE, label: 'high performance' },
1883
+ [RunnerType.LOW_PERFORMANCE]: { value: RunnerType.LOW_PERFORMANCE, label: 'low performance' },
1966
1884
  };
1967
- Date.prototype.startOfSecond = function () {
1968
- const newDate = new Date(this);
1969
- newDate.setMilliseconds(0);
1970
- return newDate;
1885
+
1886
+ const PROBLEM_INPUT = {
1887
+ [ProblemInput.STANDARD]: { value: ProblemInput.STANDARD, label: 'standard' },
1888
+ [ProblemInput.INTERACTIVE]: { value: ProblemInput.INTERACTIVE, label: 'interactive' },
1971
1889
  };
1972
- Date.prototype.endOfSecond = function () {
1973
- const newDate = new Date(this);
1974
- newDate.setMilliseconds(999);
1975
- return newDate;
1890
+ const PROBLEM_OUTPUT = {
1891
+ [ProblemOutput.STANDARD]: { value: ProblemOutput.STANDARD, label: 'standard' },
1892
+ [ProblemOutput.DYNAMIC]: { value: ProblemOutput.DYNAMIC, label: 'dynamic' },
1893
+ [ProblemOutput.INTERACTIVE]: { value: ProblemOutput.INTERACTIVE, label: 'interactive' },
1976
1894
  };
1977
- Date.prototype.isToday = function () {
1978
- const today = new Date();
1979
- return this.isSameDay(today);
1895
+ const PROBLEM_MODES = [ProblemScoringMode.TOTAL, ProblemScoringMode.SUBTASK, ProblemScoringMode.PARTIAL];
1896
+ const PROBLEM_MODE = {
1897
+ [ProblemScoringMode.TOTAL]: {
1898
+ value: ProblemScoringMode.TOTAL,
1899
+ label: 'total',
1900
+ description: 'if all test cases are Accepted the result is Accepted '
1901
+ + 'otherwise it will be Runtime Error, Time Limited Exceeded, Memory Limited Exceeded, Wrong Answer or Presentation Error in that order.',
1902
+ },
1903
+ [ProblemScoringMode.SUBTASK]: {
1904
+ value: ProblemScoringMode.SUBTASK,
1905
+ label: 'subtask',
1906
+ description: 'the test cases are grouped and each group of test cases is assigned a score, '
1907
+ + 'if all test cases in a group are Accepted then the score assigned to that group of test cases is added to total score, '
1908
+ + 'if total score is equal to the sum of the assigned scores of all groups of test cases then the result is Accepted, '
1909
+ + 'otherwise if the total score is greater than zero the result is Partial Accepted with the total accumulated score, '
1910
+ + 'otherwise it will be Runtime Error, Time Limited Exceeded, Memory Limited Exceeded, Wrong Answer or Presentation Error in that order.',
1911
+ },
1912
+ [ProblemScoringMode.PARTIAL]: {
1913
+ value: ProblemScoringMode.PARTIAL,
1914
+ label: 'partial',
1915
+ description: 'the test cases are grouped and each group is associated with X points, '
1916
+ + 'and each test case in a group scores X points ',
1917
+ },
1980
1918
  };
1981
- Date.prototype.isEqual = function (date) {
1982
- return this.getTime() === date.getTime();
1919
+ const PROBLEM_TYPES = [ProblemType.STANDARD, ProblemType.DYNAMIC, ProblemType.INTERACTIVE];
1920
+ const PROBLEM_TYPE = {
1921
+ [ProblemType.STANDARD]: {
1922
+ value: ProblemType.STANDARD,
1923
+ label: 'standard',
1924
+ description: 'The contestant submit a single source code in one of the allowed programming languages. '
1925
+ + 'The source code is either standalone or to be compiled. '
1926
+ + 'The resulting user\'s executable does I/O standard input and output. '
1927
+ + 'The output produced by the contestant\'s program is then compared to the correct output using a simple diff algorithm.',
1928
+ },
1929
+ [ProblemType.INTERACTIVE]: {
1930
+ value: ProblemType.INTERACTIVE, label: 'interactive', description: 'developing..',
1931
+ },
1932
+ [ProblemType.DYNAMIC]: {
1933
+ value: ProblemType.DYNAMIC,
1934
+ label: 'dynamic',
1935
+ description: 'The contestant submit a single source code in one of the allowed programming languages. '
1936
+ + 'The user\'s source code is either standalone or to be compiled. '
1937
+ + 'The resulting user\'s executable does I/O standard input and output. '
1938
+ + 'The output produced by the contestant\'s program is saved. '
1939
+ + 'The problem editor save a single source code in C++ 17. '
1940
+ + 'The editor\'s source code can read judge input filepath argv[1], judge output filepath argv[2], user\'s output filepath argv[3], user\'s error filepath argv[4], user\'s log filepath argv[5], user\'s source filepath argv[6] and submission information filepath argv[7] (companyId, submitId, runId, userId, contestId, problemId, language, userNickname, timestamp). '
1941
+ + 'The resulting editor\'s executable should be "AC" or a number between 1 and 100 for partial accepted',
1942
+ },
1983
1943
  };
1984
- Date.prototype.isSameYear = function (date) {
1985
- return this.getFullYear() === date.getFullYear();
1986
- };
1987
- Date.prototype.isSameMonth = function (date) {
1988
- return this.isSameYear(date) && this.getMonth() === date.getMonth();
1989
- };
1990
- Date.prototype.isSameDay = function (date) {
1991
- return this.isSameMonth(date) && this.getDate() === date.getDate();
1992
- };
1993
- Date.prototype.isSameHour = function (date) {
1994
- return this.isSameDay(date) && this.getHours() === date.getHours();
1995
- };
1996
- Date.prototype.isSameMinute = function (date) {
1997
- return this.isSameHour(date) && this.getMinutes() === date.getMinutes();
1998
- };
1999
- Date.prototype.isSameSecond = function (date) {
2000
- return this.isSameMinute(date) && this.getSeconds() === date.getSeconds();
2001
- };
2002
- Date.prototype.isSameMillisecond = function (date) {
2003
- return this.isEqual(date);
2004
- };
2005
- Date.prototype.isValidDate = function () {
2006
- return this instanceof Date && !isNaN(this.getTime());
2007
- };
2008
- Date.prototype.isYearAfter = function (date) {
2009
- return this.getFullYear() > date.getFullYear();
2010
- };
2011
- Date.prototype.isMonthAfter = function (date) {
2012
- return this.isYearAfter(date) || (this.isSameYear(date) && this.getMonth() > date.getMonth());
2013
- };
2014
- Date.prototype.isDayAfter = function (date) {
2015
- return this.isMonthAfter(date) || (this.isSameMonth(date) && this.getDate() > date.getDate());
2016
- };
2017
- Date.prototype.isHoursAfter = function (date) {
2018
- return this.isDayAfter(date) || (this.isSameDay(date) && this.getHours() > date.getHours());
2019
- };
2020
- Date.prototype.isMinutesAfter = function (date) {
2021
- return this.isHoursAfter(date) || (this.isSameHour(date) && this.getMinutes() > date.getMinutes());
2022
- };
2023
- Date.prototype.isSecondsAfter = function (date) {
2024
- return this.isMinutesAfter(date) || (this.isSameMinute(date) && this.getSeconds() > date.getSeconds());
2025
- };
2026
- Date.prototype.isMillisecondsAfter = function (date) {
2027
- return this.isSecondsAfter(date) || (this.isSameSecond(date) && this.getMilliseconds() > date.getMilliseconds());
2028
- };
2029
- Date.prototype.isAfter = function (date) {
2030
- return this.getTime() > date.getTime();
2031
- };
2032
- Date.prototype.isYearBefore = function (date) {
2033
- return this.getFullYear() < date.getFullYear();
2034
- };
2035
- Date.prototype.isMonthBefore = function (date) {
2036
- return this.isYearBefore(date) || (this.isSameYear(date) && this.getMonth() < date.getMonth());
2037
- };
2038
- Date.prototype.isDayBefore = function (date) {
2039
- return this.isMonthBefore(date) || (this.isSameMonth(date) && this.getDate() < date.getDate());
2040
- };
2041
- Date.prototype.isHoursBefore = function (date) {
2042
- return this.isDayBefore(date) || (this.isSameDay(date) && this.getHours() < date.getHours());
2043
- };
2044
- Date.prototype.isMinutesBefore = function (date) {
2045
- return this.isHoursBefore(date) || (this.isSameHour(date) && this.getMinutes() < date.getMinutes());
2046
- };
2047
- Date.prototype.isSecondsBefore = function (date) {
2048
- return this.isMinutesBefore(date) || (this.isSameMinute(date) && this.getSeconds() < date.getSeconds());
2049
- };
2050
- Date.prototype.isMillisecondsBefore = function (date) {
2051
- return this.isSecondsBefore(date) || (this.isSameSecond(date) && this.getMilliseconds() < date.getMilliseconds());
2052
- };
2053
- Date.prototype.isBefore = function (date) {
2054
- return this.getTime() < date.getTime();
2055
- };
2056
- Date.prototype.isWithinInterval = function ({ start, end }, cmp = '[]') {
2057
- return (cmp.charAt(0) === '[' ? this.isEqual(start) || this.isAfter(start) : this.isAfter(start)) &&
2058
- (cmp.charAt(1) === '[' ? this.isEqual(end) || this.isBefore(end) : this.isBefore(end));
1944
+ const PROBLEM_ROLE = {
1945
+ [Role.RESTRICTED]: { value: Role.RESTRICTED, label: 'restricted', level: 7 },
1946
+ [Role.GUEST]: { value: Role.GUEST, label: 'guest', level: 6 },
1947
+ [Role.REGULAR]: { value: Role.REGULAR, label: 'regular', level: 5 },
1948
+ [Role.CREATOR]: { value: Role.CREATOR, label: 'creator', level: 4 },
1949
+ [Role.MANAGER]: { value: Role.MANAGER, label: 'manager', level: 3 },
1950
+ [Role.MASTER]: { value: Role.MASTER, label: 'master', level: 2 },
1951
+ [Role.ADMIN]: { value: Role.ADMIN, label: 'admin', level: 1 },
1952
+ [Role.SUPER_ADMIN]: { value: Role.SUPER_ADMIN, label: 'super admin', level: 0 },
2059
1953
  };
2060
1954
 
1955
+ const _TYPE = ':type';
1956
+ const _KEY = ':key';
1957
+ const _TAB = ':tab';
1958
+ const _SUB_TAB = ':subTab?';
1959
+ const _SUB_SUB_TAB = ':subSubTab?';
1960
+ const PAGE = 'page';
1961
+ const PAGE_SIZE = 'size';
1962
+
2061
1963
  const ERROR = {
2062
1964
  // Http Errors
2063
1965
  [ErrorCode.ERR500]: { value: ErrorCode.ERR500, message: 'internal server error', status: 500 },
@@ -2215,1133 +2117,1357 @@ const ERROR = {
2215
2117
  [ErrorCode.ERR0820]: { value: ErrorCode.ERR0820, message: 'file is archived', status: 400 },
2216
2118
  };
2217
2119
 
2218
- class JkError extends Error {
2219
- constructor(code, custom) {
2220
- const message = custom?.message || ERROR[code].message;
2221
- super(message);
2222
- this.message = message;
2223
- this.code = code;
2224
- if (custom?.stack) {
2225
- this.stack = custom.stack;
2226
- }
2227
- if (custom?.data) {
2228
- this.data = custom.data;
2229
- }
2230
- }
2231
- }
2232
-
2233
- /* eslint-disable no-extend-native */
2234
- Number.prototype.padStart = function (maxLength, fillString = '0') {
2235
- return (this + '').padStart(maxLength, fillString);
2120
+ const FILE_TYPE = {
2121
+ [FileType.FILE]: { value: FileType.FILE, label: 'file' },
2122
+ [FileType.FOLDER]: { value: FileType.FOLDER, label: 'folder' },
2236
2123
  };
2237
- Number.prototype.padEnd = function (maxLength, fillString = '0') {
2238
- return (this + '').padEnd(maxLength, fillString);
2124
+ const FILE_ROLE = {
2125
+ [Role.RESTRICTED]: { value: Role.RESTRICTED, label: 'restricted', level: 5 },
2126
+ [Role.GUEST]: { value: Role.GUEST, label: 'guest', level: 4 },
2127
+ [Role.REGULAR]: { value: Role.REGULAR, label: 'regular', level: 3 },
2128
+ [Role.MASTER]: { value: Role.MASTER, label: 'master', level: 2 },
2129
+ [Role.ADMIN]: { value: Role.ADMIN, label: 'admin', level: 1 },
2130
+ [Role.SUPER_ADMIN]: { value: Role.SUPER_ADMIN, label: 'super admin', level: 0 },
2239
2131
  };
2240
-
2241
- function toJkError(err) {
2242
- const error = new Error();
2243
- let code = err?.code;
2244
- if (!(code in ErrorCode)) {
2245
- code = ErrorCode.ERR500;
2246
- }
2247
- return new JkError(code, {
2248
- message: err?.message || error.message,
2249
- stack: err?.stack || error.stack,
2250
- data: err?.data || null,
2251
- });
2252
- }
2253
- function errorsResponse(message, ...errors) {
2254
- return {
2255
- success: false,
2256
- message: message,
2257
- errors: errors.map(error => ({
2258
- code: error.code,
2259
- message: error.message,
2260
- detail: error.stack || new Error().stack || '',
2261
- data: error.data,
2262
- })),
2263
- };
2264
- }
2265
- function contentResponse(message, content) {
2266
- return {
2267
- success: true,
2268
- message,
2269
- content,
2270
- };
2271
- }
2272
- function contentsResponse(message, contents, meta) {
2273
- return {
2274
- success: true,
2275
- message,
2276
- contents,
2277
- meta,
2278
- };
2279
- }
2280
- const cleanRequest = (responseText) => {
2281
- if (!isStringJson(responseText)) {
2282
- // this occurs when the endpoint don't exits or server is down
2283
- const response = {
2284
- success: false,
2285
- message: ERROR[ErrorCode.ERR9999].message,
2286
- errors: [{ code: ErrorCode.ERR9999, detail: '', message: ERROR[ErrorCode.ERR9999].message }],
2287
- };
2288
- consoleError({ message: 'response is not string json, success false on cleaning request', responseText, response });
2289
- // jukiApiManager.reportError({ message: 'success false on cleaning request', responseText, response });
2290
- return response;
2291
- }
2292
- const responseJson = JSON.parse(responseText);
2293
- if (typeof responseJson.success === 'boolean') {
2294
- if (responseJson.success === true && typeof responseJson.message === 'string' && responseJson.content) { // V1
2295
- return {
2296
- success: true,
2297
- message: responseJson.message,
2298
- content: responseJson.content,
2299
- };
2300
- }
2301
- else if (responseJson.success === true && typeof responseJson.message === 'string' && Array.isArray(responseJson.contents) && responseJson.meta) { // V1
2302
- return {
2303
- success: true,
2304
- message: responseJson.message,
2305
- contents: responseJson.contents,
2306
- meta: responseJson.meta,
2307
- };
2308
- }
2309
- else if (responseJson.success === false && typeof responseJson.message === 'string' && Array.isArray(responseJson.errors)) { // V1
2310
- const response = {
2311
- success: false,
2312
- message: responseJson.message,
2313
- errors: responseJson.errors,
2314
- };
2315
- consoleError({ message: 'success false on cleaning request', responseText, response });
2316
- // jukiApiManager.reportError({ message: 'success false on cleaning request', responseText, response });
2317
- return response;
2318
- }
2319
- }
2320
- const response = {
2321
- success: false,
2322
- message: ERROR[ErrorCode.ERR9998].message,
2323
- errors: [{ code: ErrorCode.ERR9998, detail: '', message: ERROR[ErrorCode.ERR9998].message }],
2324
- };
2325
- consoleError({ message: 'success false on cleaning request', responseText, response });
2326
- // jukiApiManager.reportError({ message: 'success false on cleaning request', responseText, response });
2327
- return response;
2132
+ const ENTITY_STATE = {
2133
+ [EntityState.RELEASED]: {
2134
+ value: EntityState.RELEASED,
2135
+ label: 'released',
2136
+ },
2137
+ [EntityState.ARCHIVED]: {
2138
+ value: EntityState.ARCHIVED,
2139
+ label: 'archived',
2140
+ },
2328
2141
  };
2329
- const getDefaultMeta = (contents, sort) => {
2330
- return { sort: sort ?? [], page: 1, size: contents.length, totalElements: contents.length, filter: {} };
2142
+ const ENTITY_ACCESS = {
2143
+ [EntityAccess.PRIVATE]: {
2144
+ value: EntityAccess.PRIVATE,
2145
+ label: 'private',
2146
+ description: 'the record will be visible and editable only to the owner',
2147
+ },
2148
+ [EntityAccess.RESTRICTED]: {
2149
+ value: EntityAccess.RESTRICTED,
2150
+ label: 'restricted',
2151
+ description: 'the record will be visible to viewers and the owner and editable to editors and the owner',
2152
+ },
2153
+ [EntityAccess.PUBLIC]: {
2154
+ value: EntityAccess.PUBLIC,
2155
+ label: 'public',
2156
+ description: 'the record will be visible to anyone and editable to editors and the owner',
2157
+ },
2158
+ [EntityAccess.EXPOSED]: {
2159
+ value: EntityAccess.EXPOSED,
2160
+ label: 'exposed',
2161
+ description: 'the record will be visible and editable to anyone',
2162
+ },
2331
2163
  };
2332
2164
 
2333
- const isWebsocketSubscription = (event) => {
2334
- return (Object.values(WebSocketSubscriptionEvent).includes(event?.event) || Object.values(WebSocketMessageEvent).includes(event?.event))
2335
- && typeof event?.clientId === 'string' && !!event.clientId;
2336
- };
2337
- // Custom CHANNEL_PUBLISH_MESSAGES
2338
- const isPingWebSocketEventDTO = (event) => {
2339
- return isWebsocketSubscription(event)
2340
- && event?.event === WebSocketMessageEvent.PING;
2165
+ const SYSTEM_ROLE = {
2166
+ [SystemRole.GUEST]: { value: SystemRole.GUEST, label: 'guest', level: 5 },
2167
+ [SystemRole.REGULAR]: { value: SystemRole.REGULAR, label: 'regular', level: 4 },
2168
+ [SystemRole.MANAGER]: { value: SystemRole.MANAGER, label: 'manager', level: 3 },
2169
+ [SystemRole.MASTER]: { value: SystemRole.MASTER, label: 'master', level: 2 },
2170
+ [SystemRole.ADMIN]: { value: SystemRole.ADMIN, label: 'admin', level: 1 },
2171
+ [SystemRole.SUPER_ADMIN]: { value: SystemRole.SUPER_ADMIN, label: 'super admin', level: 0 },
2341
2172
  };
2342
- const isClientTrackLocationWebSocketEventDTO = (event) => {
2343
- return isWebsocketSubscription(event)
2344
- && event?.event === WebSocketMessageEvent.CLIENT_TRACK_LOCATION;
2173
+
2174
+ const MEMBER_ROLE = {
2175
+ [MemberRole.COACH]: { value: MemberRole.COACH, label: 'coach' },
2176
+ [MemberRole.CO_COACH]: { value: MemberRole.CO_COACH, label: 'co-coach' },
2177
+ [MemberRole.STAFF]: { value: MemberRole.STAFF, label: 'staff' },
2178
+ [MemberRole.ATTENDEE]: { value: MemberRole.ATTENDEE, label: 'attendee' },
2179
+ [MemberRole.RESERVE]: { value: MemberRole.RESERVE, label: 'reserve' },
2180
+ [MemberRole.CONTESTANT]: { value: MemberRole.CONTESTANT, label: 'contestant' },
2345
2181
  };
2346
- const isClientTrackScreenshotWebSocketEventDTO = (event) => {
2347
- return isWebsocketSubscription(event)
2348
- && event?.event === WebSocketMessageEvent.CLIENT_TRACK_SCREENSHOT;
2349
- };
2350
- const isClientTrackDeviceWebSocketEventDTO = (event) => {
2351
- return isWebsocketSubscription(event)
2352
- && event?.event === WebSocketMessageEvent.CLIENT_TRACK_DEVICE;
2182
+ const TEAM_ROLE = {
2183
+ [TeamRole.RESTRICTED]: { value: TeamRole.RESTRICTED, label: 'restricted', level: 5 },
2184
+ [TeamRole.GUEST]: { value: TeamRole.GUEST, label: 'guest', level: 4 },
2185
+ [TeamRole.REGULAR]: { value: TeamRole.REGULAR, label: 'regular', level: 3 },
2186
+ [TeamRole.MANAGER]: { value: TeamRole.MANAGER, label: 'manager', level: 2 },
2187
+ [TeamRole.ADMIN]: { value: TeamRole.ADMIN, label: 'admin', level: 1 },
2188
+ [TeamRole.SUPER_ADMIN]: { value: TeamRole.SUPER_ADMIN, label: 'super admin', level: 0 },
2353
2189
  };
2354
- const isChatCompletionsWebSocketEventDTO = (event) => {
2355
- return isWebsocketSubscription(event)
2356
- && event?.event === WebSocketMessageEvent.CHAT_COMPLETIONS;
2190
+
2191
+ const ONE_SECOND = 1000;
2192
+ const SEC_30 = ONE_SECOND * 30;
2193
+ const SEC_60 = ONE_SECOND * 60;
2194
+ const SEC_90 = ONE_SECOND * 90;
2195
+ const SEC_120 = ONE_SECOND * 120;
2196
+ const ONE_MINUTE = ONE_SECOND * 60;
2197
+ const ONE_HOUR = ONE_MINUTE * 60;
2198
+ const ONE_DAY = ONE_HOUR * 24;
2199
+ const ONE_WEEK = ONE_DAY * 7;
2200
+
2201
+ const USER_STATUS = {
2202
+ [UserStatus.ACTIVE]: { value: UserStatus.ACTIVE, label: 'active' },
2203
+ [UserStatus.REPORTED]: { value: UserStatus.REPORTED, label: 'reported' },
2204
+ [UserStatus.ARCHIVED]: { value: UserStatus.ARCHIVED, label: 'archived' },
2357
2205
  };
2358
- // CHANNEL_PUBLISH_SUBSCRIPTIONS
2359
- const isSubscribeCodeRunStatusWebSocketEventDTO = (event) => {
2360
- return isWebsocketSubscription(event)
2361
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CODE_RUN_STATUS
2362
- && typeof event?.runId === 'string' && !!event.runId;
2206
+ const USER_ROLE = {
2207
+ [UserRole.RESTRICTED]: { value: UserRole.RESTRICTED, label: 'restricted', level: 6 },
2208
+ [UserRole.GUEST]: { value: UserRole.GUEST, label: 'guest', level: 5 },
2209
+ [UserRole.LIMITED]: { value: UserRole.LIMITED, label: 'limited', level: 4 },
2210
+ [UserRole.REGULAR]: { value: UserRole.REGULAR, label: 'regular', level: 3 },
2211
+ [UserRole.MANAGER]: { value: UserRole.MANAGER, label: 'manager', level: 2 },
2212
+ [UserRole.ADMIN]: { value: UserRole.ADMIN, label: 'admin', level: 1 },
2213
+ [UserRole.SUPER_ADMIN]: { value: UserRole.SUPER_ADMIN, label: 'super admin', level: 0 },
2363
2214
  };
2364
- const isUnsubscribeCodeRunStatusWebSocketEventDTO = (event) => {
2365
- return isWebsocketSubscription(event)
2366
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CODE_RUN_STATUS
2367
- && typeof event?.runId === 'string' && !!event.runId;
2215
+ const EMPTY_USER_PERMISSIONS = {
2216
+ users: {
2217
+ create: false,
2218
+ manage: false,
2219
+ administrate: false,
2220
+ },
2221
+ problems: {
2222
+ create: false,
2223
+ manage: false,
2224
+ },
2225
+ submissions: {
2226
+ manage: false,
2227
+ },
2228
+ contests: {
2229
+ create: false,
2230
+ manage: false,
2231
+ },
2232
+ company: {
2233
+ manage: false,
2234
+ administrate: false,
2235
+ },
2236
+ services: {
2237
+ administrate: false,
2238
+ },
2368
2239
  };
2369
- const isSubscribeSubmissionRunStatusWebSocketEventDTO = (event) => {
2370
- return isWebsocketSubscription(event)
2371
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_SUBMISSION_RUN_STATUS
2372
- && typeof event?.submitId === 'string' && !!event.submitId;
2240
+
2241
+ // LEGACY channels (fan-out per client through the subscriptions registry in Redis)
2242
+ const CHANNEL_PUBLISH_SUBSCRIPTIONS = 'pub:subscriptions';
2243
+ const CHANNEL_SUBSCRIBE_NOTIFICATIONS = 'sub:notifications';
2244
+ const CHANNEL_SUBSCRIBE_CLIENT = (clientId) => `sub:client:${clientId}`;
2245
+ const CHANNEL_PUBLISH_MESSAGES = 'pub:messages';
2246
+ const CHANNEL_PRESENCE_CLIENT = 'pre:client';
2247
+ // TOPIC channels
2248
+ // The backend publishes each event once on the channel of its topic and Ably does the fan-out.
2249
+ // Who can subscribe to each channel is decided by the API in the Ably token (capability), never by the client.
2250
+ // Dynamic segments are encoded so a key can never inject a `:` (the Ably segment separator used by the wildcards).
2251
+ const segment = (value) => encodeURIComponent(value);
2252
+ /** private: events of one session (code runs, requested data, client track commands) */
2253
+ const CHANNEL_SESSION = (sessionId) => `session:${segment(sessionId)}`;
2254
+ /** private: events of one user (own submissions while the contest is frozen, notifications) */
2255
+ const CHANNEL_USER = (userId) => `user:${segment(userId)}`;
2256
+ /** public: status of a submission when it is visible to everyone */
2257
+ const CHANNEL_SUBMISSION = (submitId) => `submission:${segment(submitId)}`;
2258
+ /** public: changes of a problem */
2259
+ const CHANNEL_PROBLEM = (problemKey) => `problem:${segment(problemKey)}`;
2260
+ /** per role: events of a contest for one role (and the roles above it, see `ContestChannelRole`) */
2261
+ const CHANNEL_CONTEST = (contestKey, role) => `contest:${segment(contestKey)}:${role}`;
2262
+ /** system administrators only: data sent by a tracked client (screenshots, location, device) */
2263
+ const CHANNEL_CLIENT_TRACK = (trackedClientId) => `client-track:${segment(trackedClientId)}`;
2264
+ // capability resources (wildcards) of the public channels
2265
+ const CHANNEL_SUBMISSION_ALL = 'submission:*';
2266
+ const CHANNEL_PROBLEM_ALL = 'problem:*';
2267
+ const CHANNEL_CLIENT_TRACK_ALL = 'client-track:*';
2268
+ /**
2269
+ * Returns the contest and role of a `CHANNEL_CONTEST` channel name, or null if it is not one.
2270
+ */
2271
+ const getContestChannelParams = (channel) => {
2272
+ const [namespace, contestKey, role, ...rest] = channel.split(':');
2273
+ if (namespace !== 'contest' || !contestKey || rest.length || !Object.values(ContestChannelRole).includes(role)) {
2274
+ return null;
2275
+ }
2276
+ return { contestKey: decodeURIComponent(contestKey), role: role };
2373
2277
  };
2374
- const isUnsubscribeSubmissionRunStatusWebSocketEventDTO = (event) => {
2375
- return isWebsocketSubscription(event)
2376
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_SUBMISSION_RUN_STATUS
2377
- && typeof event?.submitId === 'string' && !!event.submitId;
2278
+
2279
+ const NEW_PAGE_SHEET = () => ({
2280
+ id: v4(),
2281
+ type: WorksheetType.NEW_PAGE,
2282
+ title: '',
2283
+ points: 0,
2284
+ });
2285
+ const ASPECT_RATIO = {
2286
+ [AspectRatio.RATIO_21_9]: {
2287
+ aspectRatio: AspectRatio.RATIO_21_9,
2288
+ width: 2520,
2289
+ height: 1080,
2290
+ decimal: 21 / 9,
2291
+ label: 'ultrawide',
2292
+ },
2293
+ [AspectRatio.RATIO_20_9]: {
2294
+ aspectRatio: AspectRatio.RATIO_20_9,
2295
+ width: 2400,
2296
+ height: 1080,
2297
+ decimal: 20 / 9,
2298
+ label: 'mobile wide',
2299
+ },
2300
+ [AspectRatio.RATIO_16_9]: {
2301
+ aspectRatio: AspectRatio.RATIO_16_9,
2302
+ width: 1920,
2303
+ height: 1080,
2304
+ decimal: 16 / 9,
2305
+ label: 'widescreen',
2306
+ },
2307
+ [AspectRatio.RATIO_16_10]: {
2308
+ aspectRatio: AspectRatio.RATIO_16_10,
2309
+ width: 1920,
2310
+ height: 1200,
2311
+ decimal: 16 / 10,
2312
+ label: 'widescreen tall',
2313
+ },
2314
+ [AspectRatio.RATIO_3_2]: {
2315
+ aspectRatio: AspectRatio.RATIO_3_2,
2316
+ width: 1440,
2317
+ height: 960,
2318
+ decimal: 3 / 2,
2319
+ label: 'balanced',
2320
+ },
2321
+ [AspectRatio.RATIO_4_3]: {
2322
+ aspectRatio: AspectRatio.RATIO_4_3,
2323
+ width: 1024,
2324
+ height: 768,
2325
+ decimal: 4 / 3,
2326
+ label: 'standard',
2327
+ },
2328
+ [AspectRatio.RATIO_5_4]: {
2329
+ aspectRatio: AspectRatio.RATIO_5_4,
2330
+ width: 1280,
2331
+ height: 1024,
2332
+ decimal: 5 / 4,
2333
+ label: 'square old',
2334
+ },
2335
+ [AspectRatio.RATIO_1_1]: {
2336
+ aspectRatio: AspectRatio.RATIO_1_1,
2337
+ width: 1000,
2338
+ height: 1000,
2339
+ decimal: 1,
2340
+ label: 'square',
2341
+ },
2378
2342
  };
2379
- const isSubscribeGetDataWebSocketEventDTO = (event) => {
2380
- return isWebsocketSubscription(event)
2381
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_GET_DATA;
2343
+
2344
+ var ContestProblemBlockedByType;
2345
+ (function (ContestProblemBlockedByType) {
2346
+ ContestProblemBlockedByType["UNMET_PREREQUISITES"] = "UNMET_PREREQUISITES";
2347
+ ContestProblemBlockedByType["MAX_ACCEPTED_SUBMISSIONS_ACHIEVED"] = "MAX_ACCEPTED_SUBMISSIONS_ACHIEVED";
2348
+ ContestProblemBlockedByType["START_TIME_IN_THE_FUTURE"] = "START_TIME_IN_THE_FUTURE";
2349
+ ContestProblemBlockedByType["END_TIME_IN_THE_PAST"] = "END_TIME_IN_THE_PAST";
2350
+ })(ContestProblemBlockedByType || (ContestProblemBlockedByType = {}));
2351
+
2352
+ var MemberType;
2353
+ (function (MemberType) {
2354
+ MemberType["USER"] = "USER";
2355
+ MemberType["TEAM"] = "TEAM";
2356
+ })(MemberType || (MemberType = {}));
2357
+
2358
+ const isWorksheetAssignment = (assignment) => {
2359
+ return assignment.type === AssignmentClass.WORKSHEET;
2382
2360
  };
2383
- const isUnsubscribeGetDataWebSocketEventDTO = (event) => {
2384
- return isWebsocketSubscription(event)
2385
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_GET_DATA;
2361
+ const isCourseAssignment = (assignment) => {
2362
+ return assignment.type === AssignmentClass.COURSE;
2386
2363
  };
2387
- const isSubscribeProblemCrawledWebSocketEventDTO = (event) => {
2388
- return isWebsocketSubscription(event)
2389
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_PROBLEM_CRAWLED;
2364
+ const isContestAssignment = (assignment) => {
2365
+ return assignment.type === AssignmentClass.CONTEST;
2390
2366
  };
2391
- const isUnsubscribeProblemCrawledWebSocketEventDTO = (event) => {
2392
- return isWebsocketSubscription(event)
2393
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_PROBLEM_CRAWLED;
2367
+
2368
+ const getAssignmentCommentKey = (classKey, cycleKey, sessionKey, assignmentKey) => `class:${classKey}|cycle:${cycleKey}|session:${sessionKey}|assignment:${assignmentKey}`;
2369
+ const getAssignmentUserCommentKey = (classKey, cycleKey, sessionKey, assignmentKey, userNickname, userCompany) => `class:${classKey}|cycle:${cycleKey}|session:${sessionKey}|assignment:${assignmentKey}|user_nickname:${userNickname}|user_company:${userCompany}`;
2370
+ const getProblemCommentKey = (problemKey) => `problem:${problemKey}`;
2371
+ const getContestCommentKey = (contestKey) => `contest:${contestKey}`;
2372
+
2373
+ const isEndlessContest = (settings) => {
2374
+ return settings?.startTimestamp === MIN_DATE.getTime()
2375
+ && settings?.frozenTimestamp === MAX_DATE.getTime()
2376
+ && settings?.quietTimestamp === MAX_DATE.getTime()
2377
+ && settings?.endTimestamp === MAX_DATE.getTime()
2378
+ && settings?.penalty === 0;
2394
2379
  };
2395
- const isSubscribeSubmissionsCrawlWebSocketEventDTO = (event) => {
2396
- return isWebsocketSubscription(event)
2397
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_SUBMISSIONS_CRAWL;
2380
+ const isGlobalContest = (settings) => {
2381
+ return settings?.startTimestamp === 0
2382
+ && settings?.frozenTimestamp === 0
2383
+ && settings?.quietTimestamp === 0
2384
+ && settings?.endTimestamp === 0
2385
+ && settings?.penalty === 0;
2398
2386
  };
2399
- const isUnsubscribeSubmissionsCrawlWebSocketEventDTO = (event) => {
2400
- return isWebsocketSubscription(event)
2401
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_SUBMISSIONS_CRAWL;
2387
+ const isPastContest = (settings) => {
2388
+ return Date.now() > (settings?.endTimestamp ?? 0);
2402
2389
  };
2403
- const isSubscribeContestChangesWebSocketEventDTO = (event) => {
2404
- return isWebsocketSubscription(event)
2405
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CONTEST_CHANGES;
2390
+ const isFutureContest = (settings) => {
2391
+ return (settings?.startTimestamp ?? 0) > Date.now();
2406
2392
  };
2407
- const isUnsubscribeContestChangesWebSocketEventDTO = (event) => {
2408
- return isWebsocketSubscription(event)
2409
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CONTEST_CHANGES;
2393
+
2394
+ const getDocumentAccess = (document) => {
2395
+ switch (true) {
2396
+ case (document?.members?.rankAdministrators === EntityMembersRank.NONE || document?.members?.rankAdministrators === EntityMembersRank.CLOSE)
2397
+ && document?.members?.rankManagers === EntityMembersRank.OPEN
2398
+ && (document?.members?.rankGuests === EntityMembersRank.NONE || document?.members?.rankGuests === EntityMembersRank.CLOSE || document?.members?.rankGuests === EntityMembersRank.OPEN)
2399
+ && document?.members?.rankSpectators === EntityMembersRank.OPEN
2400
+ && (document?.members?.rankParticipants === EntityMembersRank.NONE || document?.members?.rankParticipants === EntityMembersRank.CLOSE || document?.members?.rankParticipants === EntityMembersRank.OPEN):
2401
+ return EntityAccess.EXPOSED;
2402
+ case (document?.members?.rankAdministrators === EntityMembersRank.NONE || document?.members?.rankAdministrators === EntityMembersRank.CLOSE)
2403
+ && document?.members?.rankManagers === EntityMembersRank.CLOSE
2404
+ && (document?.members?.rankGuests === EntityMembersRank.NONE || document?.members?.rankGuests === EntityMembersRank.CLOSE || document?.members?.rankGuests === EntityMembersRank.OPEN)
2405
+ && document?.members?.rankSpectators === EntityMembersRank.OPEN
2406
+ && (document?.members?.rankParticipants === EntityMembersRank.NONE || document?.members?.rankParticipants === EntityMembersRank.CLOSE || document?.members?.rankParticipants === EntityMembersRank.OPEN):
2407
+ return EntityAccess.PUBLIC;
2408
+ case (document?.members?.rankAdministrators === EntityMembersRank.NONE || document?.members?.rankAdministrators === EntityMembersRank.CLOSE)
2409
+ && document?.members?.rankManagers === EntityMembersRank.CLOSE
2410
+ && (document?.members?.rankGuests === EntityMembersRank.NONE || document?.members?.rankGuests === EntityMembersRank.CLOSE || document?.members?.rankGuests === EntityMembersRank.OPEN)
2411
+ && document?.members?.rankSpectators === EntityMembersRank.CLOSE
2412
+ && (document?.members?.rankParticipants === EntityMembersRank.NONE || document?.members?.rankParticipants === EntityMembersRank.CLOSE || document?.members?.rankParticipants === EntityMembersRank.OPEN):
2413
+ return EntityAccess.RESTRICTED;
2414
+ case document?.members?.rankAdministrators === EntityMembersRank.NONE
2415
+ && document?.members?.rankManagers === EntityMembersRank.NONE
2416
+ && document?.members?.rankGuests === EntityMembersRank.NONE
2417
+ && document?.members?.rankSpectators === EntityMembersRank.NONE
2418
+ && document?.members?.rankParticipants === EntityMembersRank.NONE:
2419
+ return EntityAccess.PRIVATE;
2420
+ default:
2421
+ return EntityAccess.PRIVATE;
2422
+ }
2410
2423
  };
2411
- const isSubscribeClientTrackWebSocketEventDTO = (event) => {
2412
- return isWebsocketSubscription(event)
2413
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CLIENT_TRACK;
2424
+ const isUserMember = (member) => {
2425
+ return typeof member.userId === 'string';
2414
2426
  };
2415
- const isUnsubscribeClientTrackWebSocketEventDTO = (event) => {
2416
- return isWebsocketSubscription(event)
2417
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CLIENT_TRACK;
2427
+ const isTeamMember = (member) => {
2428
+ return typeof member.teamId === 'string';
2418
2429
  };
2419
- const isSubscribeUserNotificationWebSocketEventDTO = (event) => {
2420
- return isWebsocketSubscription(event)
2421
- && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_USER_NOTIFICATION;
2430
+ const toEntityMembersDTO = (members) => {
2431
+ return {
2432
+ rankAdministrators: members.rankAdministrators,
2433
+ administrators: Object.keys(members.administrators),
2434
+ rankManagers: members.rankManagers,
2435
+ managers: Object.keys(members.managers),
2436
+ rankParticipants: members.rankParticipants,
2437
+ participants: Object.keys(members.participants),
2438
+ rankGuests: members.rankGuests,
2439
+ guests: Object.keys(members.guests),
2440
+ rankSpectators: members.rankSpectators,
2441
+ spectators: Object.keys(members.spectators),
2442
+ };
2422
2443
  };
2423
- const isUnsubscribeUserNotificationWebSocketEventDTO = (event) => {
2424
- return isWebsocketSubscription(event)
2425
- && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_USER_NOTIFICATION;
2444
+
2445
+ function removeExtension(fileName) {
2446
+ const i = fileName.lastIndexOf('.');
2447
+ return i !== -1 ? fileName.substring(0, i) : fileName;
2448
+ }
2449
+
2450
+ // https://dev.to/jsmccrumb/asynchronous-setinterval-4j69
2451
+ const asyncIntervals = [];
2452
+ const runAsyncInterval = async (cb, interval, intervalIndex) => {
2453
+ await cb();
2454
+ if (asyncIntervals[intervalIndex]) {
2455
+ setTimeout(() => runAsyncInterval(cb, interval, intervalIndex), interval);
2456
+ }
2426
2457
  };
2427
- // is WebSocketResponseEventDTO, CHANNEL_SUBSCRIBE_CLIENT
2428
- const isWebSocketResponseEventDTO = (event) => {
2429
- return Object.values(WebSocketResponseEvent).includes(event?.event)
2430
- && typeof event?.key === 'string'
2431
- && typeof event?.connectionId === 'string'
2432
- && typeof event?.messageTimestamp === 'number' && !!event.messageTimestamp;
2458
+ const setAsyncInterval = (cb, interval) => {
2459
+ if (cb && typeof cb === 'function') {
2460
+ const intervalIndex = asyncIntervals.length;
2461
+ asyncIntervals.push(true);
2462
+ void runAsyncInterval(cb, interval, intervalIndex);
2463
+ return intervalIndex;
2464
+ }
2465
+ else {
2466
+ throw new Error('Callback must be a function');
2467
+ }
2433
2468
  };
2434
- const isPongWebSocketResponseEventDTO = (event) => {
2435
- return isWebSocketResponseEventDTO(event)
2436
- && event?.event === WebSocketResponseEvent.PONG
2437
- && !!event?.data;
2469
+ const clearAsyncInterval = (intervalIndex) => {
2470
+ if (asyncIntervals[intervalIndex]) {
2471
+ asyncIntervals[intervalIndex] = false;
2472
+ }
2438
2473
  };
2439
- const isCodeRunStatusMessageWebSocketResponseEventDTO = (event) => {
2440
- return isWebSocketResponseEventDTO(event)
2441
- && event?.event === WebSocketResponseEvent.CODE_RUN_STATUS
2442
- && typeof event?.runId === 'string' && !!event.runId
2443
- && event?.status in SubmissionRunStatus;
2474
+
2475
+ const getDataOfTestCase = (testCase, timeLimit, memoryLimit) => {
2476
+ const { timeUsed, memoryUsed, exitCode } = getDataLog(testCase?.log);
2477
+ const timeLimitExceeded = timeUsed > timeLimit;
2478
+ const memoryLimitExceeded = memoryUsed > memoryLimit;
2479
+ const runtimeError = exitCode !== 0;
2480
+ const compilationError = testCase?.status === SubmissionRunStatus.COMPILATION_ERROR;
2481
+ return {
2482
+ compilationError,
2483
+ timeUsed,
2484
+ timeLimitExceeded: timeLimitExceeded,
2485
+ memoryUsed,
2486
+ memoryLimitExceeded: memoryLimitExceeded,
2487
+ exitCode,
2488
+ runtimeError,
2489
+ failed: !!testCase?.log && (timeLimitExceeded || memoryLimitExceeded || runtimeError),
2490
+ };
2444
2491
  };
2445
- const isSubmissionRunStatusMessageWebSocketResponseEventDTO = (event) => {
2446
- return isWebSocketResponseEventDTO(event)
2447
- && event?.event === WebSocketResponseEvent.SUBMISSION_RUN_STATUS
2448
- && typeof event?.submitId === 'string' && !!event.submitId
2449
- && event?.status in SubmissionRunStatus
2450
- && event?.verdict in ProblemVerdict
2451
- && typeof event?.points === 'number';
2492
+ const getVerdictFromTestCase = (testCaseValue, timeLimit, memoryLimit) => {
2493
+ const { compilationError, timeLimitExceeded, memoryLimitExceeded, runtimeError, timeUsed, memoryUsed, exitCode, } = getDataOfTestCase(testCaseValue, timeLimit, memoryLimit);
2494
+ return {
2495
+ verdict: compilationError
2496
+ ? ProblemVerdict.CE
2497
+ : timeLimitExceeded
2498
+ ? ProblemVerdict.TLE
2499
+ : memoryLimitExceeded
2500
+ ? ProblemVerdict.MLE
2501
+ : runtimeError
2502
+ ? ProblemVerdict.RE
2503
+ : testCaseValue.out === testCaseValue.testOut
2504
+ ? ProblemVerdict.AC
2505
+ : testCaseValue.withPE && testCaseValue.out.split(' ').join('').split('\n').join('') === testCaseValue.testOut.split(' ').join('').split('\n').join('')
2506
+ ? ProblemVerdict.PE
2507
+ : !testCaseValue.withPE && testCaseValue.out.split(' ').join('').split('\n').join('') === testCaseValue.testOut.split(' ').join('').split('\n').join('')
2508
+ ? ProblemVerdict.AC
2509
+ : ProblemVerdict.WA,
2510
+ timeUsed,
2511
+ memoryUsed,
2512
+ exitCode,
2513
+ };
2452
2514
  };
2453
- const isUserMessageWebSocketResponseEventDTO = (event) => {
2454
- return isWebSocketResponseEventDTO(event)
2455
- && event?.event === WebSocketResponseEvent.USER_MESSAGE
2456
- && typeof event?.user?.nickname === 'string' && !!event.user?.nickname
2457
- && typeof event?.user?.imageUrl === 'string' && !!event.user?.imageUrl
2458
- && typeof event?.user?.company?.key === 'string' && !!event.user?.company?.key
2459
- && !!event?.content;
2515
+ const mergeVerdicts = (first, second) => {
2516
+ let verdict = first.verdict;
2517
+ if (second.verdict === ProblemVerdict.RE) {
2518
+ verdict = ProblemVerdict.RE;
2519
+ }
2520
+ else if (second.verdict === ProblemVerdict.TLE && verdict != ProblemVerdict.RE) {
2521
+ verdict = ProblemVerdict.TLE;
2522
+ }
2523
+ else if (second.verdict === ProblemVerdict.MLE
2524
+ && verdict !== ProblemVerdict.TLE
2525
+ && verdict !== ProblemVerdict.RE) {
2526
+ verdict = ProblemVerdict.MLE;
2527
+ }
2528
+ else if (second.verdict === ProblemVerdict.WA
2529
+ && verdict !== ProblemVerdict.MLE
2530
+ && verdict !== ProblemVerdict.TLE
2531
+ && verdict !== ProblemVerdict.RE) {
2532
+ verdict = ProblemVerdict.WA;
2533
+ }
2534
+ else if (second.verdict === ProblemVerdict.PE
2535
+ && verdict !== ProblemVerdict.WA
2536
+ && verdict !== ProblemVerdict.MLE
2537
+ && verdict !== ProblemVerdict.TLE
2538
+ && verdict !== ProblemVerdict.RE) {
2539
+ verdict = ProblemVerdict.PE;
2540
+ }
2541
+ else if (second.verdict === ProblemVerdict.PA
2542
+ && verdict !== ProblemVerdict.PE
2543
+ && verdict !== ProblemVerdict.WA
2544
+ && verdict !== ProblemVerdict.MLE
2545
+ && verdict !== ProblemVerdict.TLE
2546
+ && verdict !== ProblemVerdict.RE) {
2547
+ verdict = ProblemVerdict.PA;
2548
+ }
2549
+ else if (second.verdict === ProblemVerdict.AC
2550
+ && verdict !== ProblemVerdict.PA
2551
+ && verdict !== ProblemVerdict.PE
2552
+ && verdict !== ProblemVerdict.WA
2553
+ && verdict !== ProblemVerdict.MLE
2554
+ && verdict !== ProblemVerdict.TLE
2555
+ && verdict !== ProblemVerdict.RE) {
2556
+ verdict = ProblemVerdict.AC;
2557
+ }
2558
+ return {
2559
+ timeUsed: Math.max(first.timeUsed, second.timeUsed),
2560
+ memoryUsed: Math.max(first.memoryUsed, second.memoryUsed),
2561
+ exitCode: first.exitCode || second.exitCode,
2562
+ verdict,
2563
+ };
2460
2564
  };
2461
- const isSendDataWebSocketResponseEventDTO = (event) => {
2462
- return [
2463
- WebSocketResponseEvent.SEND_DATA_ECS_TASK_DEFINITIONS_LIST,
2464
- WebSocketResponseEvent.SEND_DATA_EC2_INSTANCES_LIST,
2465
- WebSocketResponseEvent.SEND_DATA_ECS_TASKS_LIST,
2466
- WebSocketResponseEvent.SEND_DATA_SSM_SESSIONS_LIST,
2467
- WebSocketResponseEvent.SEND_DATA_RUN_COMMAND,
2468
- WebSocketResponseEvent.SEND_DATA_CLIENT_TRACK,
2469
- WebSocketResponseEvent.SEND_DATA_CHAT_COMPLETIONS,
2470
- ].includes(event?.event)
2471
- && typeof event?.dataId === 'string' && !!event.dataId
2472
- && !!event?.content;
2565
+ const getDataLog = (log) => {
2566
+ const lines = log?.split?.('\n') || [];
2567
+ let timeUsed = 0;
2568
+ let memoryUsed = 0;
2569
+ let exitCode = -1;
2570
+ if (lines.length > 4) {
2571
+ for (const line of lines) {
2572
+ if (line.startsWith('time:')) {
2573
+ timeUsed = +line.split(':')[1];
2574
+ if (Number.isNaN(timeUsed)) {
2575
+ timeUsed = 0;
2576
+ }
2577
+ timeUsed *= 1000;
2578
+ }
2579
+ else if (line.startsWith('max-rss:')) {
2580
+ memoryUsed = parseInt(line.split(':')[1], 10); // en KB
2581
+ }
2582
+ else if (line.startsWith('exitcode:')) {
2583
+ exitCode = parseInt(line.split(':')[1], 10);
2584
+ }
2585
+ }
2586
+ }
2587
+ else if (lines.length >= 3) {
2588
+ timeUsed = +lines[0];
2589
+ memoryUsed = +lines[1];
2590
+ exitCode = +lines[2];
2591
+ }
2592
+ return {
2593
+ timeUsed: Number.isNaN(timeUsed) ? 0 : timeUsed,
2594
+ memoryUsed: Number.isNaN(memoryUsed) ? 0 : memoryUsed,
2595
+ exitCode: Number.isNaN(exitCode) ? -1 : exitCode,
2596
+ };
2473
2597
  };
2474
- const isSendDataEcsTaskDefinitionListWebSocketResponseEventDTO = (event) => {
2475
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2476
- && event?.event === WebSocketResponseEvent.SEND_DATA_ECS_TASK_DEFINITIONS_LIST;
2598
+
2599
+ function memorySizeOf(obj) {
2600
+ let bytes = 0;
2601
+ function sizeOf(obj) {
2602
+ if (obj !== null && obj !== undefined) {
2603
+ switch (typeof obj) {
2604
+ case "number":
2605
+ bytes += 8;
2606
+ break;
2607
+ case "string":
2608
+ bytes += obj.length * 2;
2609
+ break;
2610
+ case "boolean":
2611
+ bytes += 4;
2612
+ break;
2613
+ case "object":
2614
+ const objClass = Object.prototype.toString.call(obj).slice(8, -1);
2615
+ if (objClass === "Object" || objClass === "Array") {
2616
+ for (const key in obj) {
2617
+ if (!obj.hasOwnProperty(key))
2618
+ continue;
2619
+ bytes += key.length * 2;
2620
+ sizeOf(obj[key]);
2621
+ }
2622
+ }
2623
+ else
2624
+ bytes += obj.toString().length * 2;
2625
+ break;
2626
+ }
2627
+ }
2628
+ return bytes;
2629
+ }
2630
+ return sizeOf(obj);
2631
+ }
2632
+
2633
+ /* eslint-disable no-extend-native */
2634
+ Date.prototype.changeYear = function (year) {
2635
+ const newDate = new Date(this);
2636
+ newDate.setFullYear(year);
2637
+ return newDate;
2477
2638
  };
2478
- const isSendDataEc2InstancesListWebSocketResponseEventDTO = (event) => {
2479
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2480
- && event?.event === WebSocketResponseEvent.SEND_DATA_EC2_INSTANCES_LIST;
2639
+ Date.prototype.changeMonth = function (monthIndex) {
2640
+ const newDate = new Date(this);
2641
+ newDate.setMonth(monthIndex);
2642
+ return newDate;
2481
2643
  };
2482
- const isSendDataEcsTasksListWebSocketResponseEventDTO = (event) => {
2483
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2484
- && event?.event === WebSocketResponseEvent.SEND_DATA_ECS_TASKS_LIST;
2644
+ Date.prototype.changeDay = function (date) {
2645
+ const newDate = new Date(this);
2646
+ newDate.setDate(date);
2647
+ return newDate;
2485
2648
  };
2486
- const isSendDataSsmSessionsListWebSocketResponseEventDTO = (event) => {
2487
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2488
- && event?.event === WebSocketResponseEvent.SEND_DATA_SSM_SESSIONS_LIST;
2649
+ Date.prototype.changeHours = function (hours) {
2650
+ const newDate = new Date(this);
2651
+ newDate.setHours(hours);
2652
+ return newDate;
2489
2653
  };
2490
- const isSendDataRunCommandWebSocketResponseEventDTO = (event) => {
2491
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2492
- && event?.event === WebSocketResponseEvent.SEND_DATA_RUN_COMMAND;
2654
+ Date.prototype.changeMinutes = function (minutes) {
2655
+ const newDate = new Date(this);
2656
+ newDate.setMinutes(minutes);
2657
+ return newDate;
2493
2658
  };
2494
- const isSendDataClientTrackWebSocketResponseEventDTO = (event) => {
2495
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2496
- && event?.event === WebSocketResponseEvent.SEND_DATA_CLIENT_TRACK;
2659
+ Date.prototype.changeSeconds = function (seconds) {
2660
+ const newDate = new Date(this);
2661
+ newDate.setSeconds(seconds);
2662
+ return newDate;
2497
2663
  };
2498
- const isSenDataChatCompletionsWebSocketResponseEventDTO = (event) => {
2499
- return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
2500
- && event?.event === WebSocketResponseEvent.SEND_DATA_CHAT_COMPLETIONS;
2664
+ Date.prototype.changeMilliseconds = function (milliseconds) {
2665
+ const newDate = new Date(this);
2666
+ newDate.setMilliseconds(milliseconds);
2667
+ return newDate;
2501
2668
  };
2502
- const isProblemCrawledWebSocketResponseEventDTO = (event) => {
2503
- return isWebSocketResponseEventDTO(event)
2504
- && event?.event === WebSocketResponseEvent.PROBLEM_CRAWLED
2505
- && !!event?.content;
2669
+ Date.prototype.decreaseYear = function (count = 1) {
2670
+ return this.changeYear(this.getFullYear() - count);
2506
2671
  };
2507
- const isSubmissionsCrawlWebSocketResponseEventDTO = (event) => {
2508
- return isWebSocketResponseEventDTO(event)
2509
- && event?.event === WebSocketResponseEvent.SUBMISSIONS_CRAWL
2510
- && !!event?.content;
2672
+ Date.prototype.increaseYear = function (count = 1) {
2673
+ return this.changeYear(this.getFullYear() + count);
2511
2674
  };
2512
- const isContestChangesWebSocketResponseEventDTO = (event) => {
2513
- return isWebSocketResponseEventDTO(event)
2514
- && event?.event === WebSocketResponseEvent.CONTEST_CHANGES
2515
- && !!event?.content;
2675
+ Date.prototype.decreaseMonth = function () {
2676
+ const newDate = new Date(this);
2677
+ newDate.setMonth(newDate.getMonth() - 1);
2678
+ return newDate;
2516
2679
  };
2517
- const isClientTrackWebSocketResponseEventDTO = (event) => {
2518
- return isWebSocketResponseEventDTO(event)
2519
- && event?.event === WebSocketResponseEvent.CLIENT_TRACK;
2680
+ Date.prototype.increaseMonth = function () {
2681
+ const newDate = new Date(this);
2682
+ newDate.setMonth(newDate.getMonth() + 1);
2683
+ return newDate;
2520
2684
  };
2521
- const isUserNotificationWebSocketResponseEventDTO = (event) => {
2522
- return [
2523
- WebSocketResponseEvent.USER_NOTIFICATION_SUBMISSION,
2524
- WebSocketResponseEvent.USER_NOTIFICATION_CONTEST_CLARIFICATION,
2525
- ].includes(event?.event)
2526
- && !!event?.content;
2685
+ Date.prototype.increaseDay = function () {
2686
+ const newDate = new Date(this);
2687
+ newDate.setDate(newDate.getDate() + 1);
2688
+ return newDate;
2527
2689
  };
2528
- const isUserNotificationSubmissionWebSocketResponseEventDTO = (event) => {
2529
- return isWebSocketResponseEventDTO(event) && isUserNotificationWebSocketResponseEventDTO(event)
2530
- && event?.event === WebSocketResponseEvent.USER_NOTIFICATION_SUBMISSION;
2690
+ Date.prototype.decreaseDay = function () {
2691
+ const newDate = new Date(this);
2692
+ newDate.setDate(newDate.getDate() - 1);
2693
+ return newDate;
2531
2694
  };
2532
- const isUserNotificationContestClarificationWebSocketResponseEventDTO = (event) => {
2533
- return isWebSocketResponseEventDTO(event) && isUserNotificationWebSocketResponseEventDTO(event)
2534
- && event?.event === WebSocketResponseEvent.USER_NOTIFICATION_CONTEST_CLARIFICATION;
2695
+ Date.prototype.startOfYear = function () {
2696
+ const newDate = new Date(this);
2697
+ newDate.setMonth(0);
2698
+ return newDate.startOfMonth();
2535
2699
  };
2536
- // generic
2537
- const getWebSocketResponseEventKey = (event, clientId, id) => {
2538
- return `${event}-${clientId}-${id}`;
2700
+ Date.prototype.endOfYear = function () {
2701
+ const nextMonth = this.increaseYear().startOfYear();
2702
+ return new Date(nextMonth.getTime() - 1);
2539
2703
  };
2540
-
2541
- function splitTime(timeRemaining) {
2542
- const remaining = [];
2543
- // const aYearMilliseconds = 1000 * 60 * 60 * 24 * 365;
2544
- // const remainingYears = Math.floor(timeRemaining / aYearMilliseconds);
2545
- // remaining.push({ remaining: remainingYears, label: 'years', milliseconds: aYearMilliseconds });
2546
- // const aWeekMilliseconds = 1000 * 60 * 60 * 24 * 7;
2547
- // const remainingWeeks = Math.floor((timeRemaining % aYearMilliseconds) / aWeekMilliseconds);
2548
- // remaining.push({ remaining: remainingWeeks, label: 'weeks', milliseconds: aWeekMilliseconds });
2549
- const aSecondMilliseconds = 1000;
2550
- const aMinuteMilliseconds = aSecondMilliseconds * 60;
2551
- const aHourMilliseconds = aMinuteMilliseconds * 60;
2552
- const aDayMilliseconds = aHourMilliseconds * 24;
2553
- const aWeekMilliseconds = aDayMilliseconds * 7;
2554
- const remainingWeeks = Math.floor(timeRemaining / aWeekMilliseconds);
2555
- remaining.push({
2556
- remaining: remainingWeeks,
2557
- label: remainingWeeks === 1 ? 'week' : 'weeks',
2558
- abbreviatedLabel: 'w',
2559
- milliseconds: aWeekMilliseconds,
2560
- digits: 2,
2561
- });
2562
- const remainingDays = Math.floor((timeRemaining % aWeekMilliseconds) / aDayMilliseconds);
2563
- remaining.push({
2564
- remaining: remainingDays,
2565
- label: remainingDays === 1 ? 'day' : 'days',
2566
- abbreviatedLabel: 'd',
2567
- milliseconds: aDayMilliseconds,
2568
- digits: 2,
2569
- });
2570
- const remainingHours = Math.floor((timeRemaining % aDayMilliseconds) / aHourMilliseconds);
2571
- remaining.push({
2572
- remaining: remainingHours,
2573
- label: remainingHours === 1 ? 'hour' : 'hours',
2574
- abbreviatedLabel: 'h',
2575
- milliseconds: aHourMilliseconds,
2576
- digits: 2,
2577
- });
2578
- const remainingMinutes = Math.floor((timeRemaining % aHourMilliseconds) / aMinuteMilliseconds);
2579
- remaining.push({
2580
- remaining: remainingMinutes,
2581
- label: remainingMinutes === 1 ? 'minute' : 'minutes',
2582
- abbreviatedLabel: 'm',
2583
- milliseconds: aMinuteMilliseconds,
2584
- digits: 2,
2585
- });
2586
- const remainingSeconds = Math.floor((timeRemaining % aMinuteMilliseconds) / aSecondMilliseconds);
2587
- remaining.push({
2588
- remaining: remainingSeconds,
2589
- label: remainingSeconds === 1 ? 'second' : 'seconds',
2590
- abbreviatedLabel: 's',
2591
- milliseconds: aSecondMilliseconds,
2592
- digits: 2,
2593
- });
2594
- const remainingMilliseconds = Math.floor(timeRemaining % aSecondMilliseconds);
2595
- remaining.push({
2596
- remaining: remainingMilliseconds,
2597
- label: remainingMilliseconds === 1 ? 'millisecond' : 'milliseconds',
2598
- abbreviatedLabel: 'ms',
2599
- milliseconds: 1,
2600
- digits: 3,
2601
- });
2602
- // while (remaining[0].remaining <= 0) {
2603
- // remaining.shift();
2604
- // if (remaining.length === 3) {
2605
- // break;
2606
- // }
2607
- // }
2608
- return remaining;
2609
- }
2610
- function normalizeToLocalStartOfDay(timestamp) {
2611
- const date = new Date(timestamp);
2612
- return new Date(date.getFullYear(), date.getMonth(), date.getDate());
2613
- }
2614
- function normalizeToLocalStartOfHour(timestamp) {
2615
- const date = new Date(timestamp);
2616
- return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours());
2617
- }
2618
- function normalizeToLocalStartOfMinutes(timestamp) {
2619
- const date = new Date(timestamp);
2620
- return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes());
2621
- }
2622
- function normalizeToLocalStartOfSeconds(timestamp) {
2623
- const date = new Date(timestamp);
2624
- return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes());
2625
- }
2626
- const getYears = (d) => d.getFullYear();
2627
- const getMonths = (d) => d.getFullYear() * 12 + d.getMonth();
2628
- const getDays = (d) => {
2629
- return Math.floor(normalizeToLocalStartOfDay(d).getTime() / ONE_DAY);
2704
+ Date.prototype.startOfMonth = function () {
2705
+ const newDate = new Date(this);
2706
+ newDate.setDate(1);
2707
+ return newDate.startOfDay();
2630
2708
  };
2631
- const getHours = (d) => {
2632
- return Math.floor(normalizeToLocalStartOfHour(d).getTime() / ONE_HOUR);
2709
+ Date.prototype.endOfMonth = function () {
2710
+ const nextMonth = this.increaseMonth().startOfMonth();
2711
+ return new Date(nextMonth.getTime() - 1);
2633
2712
  };
2634
- const getMinutes = (d) => {
2635
- return Math.floor(normalizeToLocalStartOfMinutes(d).getTime() / ONE_MINUTE);
2713
+ Date.prototype.startOfWeek = function () {
2714
+ const newDate = new Date(this);
2715
+ while (newDate.getDay()) {
2716
+ newDate.setDate(newDate.getDate() - 1);
2717
+ }
2718
+ return newDate.startOfDay();
2636
2719
  };
2637
- const getSeconds = (d) => {
2638
- return Math.floor(normalizeToLocalStartOfSeconds(d).getTime() / 1000);
2720
+ Date.prototype.endOfWeek = function () {
2721
+ const newDate = new Date(this);
2722
+ while (newDate.getDay() < 6) {
2723
+ newDate.setDate(newDate.getDate() - 1);
2724
+ }
2725
+ return newDate.endOfDay();
2639
2726
  };
2640
- const getMilliseconds = (d) => d.getTime();
2641
-
2642
- const getUserKey = (userNickname, userCompanyKey) => {
2643
- return userNickname + '|' + userCompanyKey;
2727
+ Date.prototype.startOfDay = function () {
2728
+ const newDate = new Date(this);
2729
+ newDate.setHours(0, 0, 0, 0);
2730
+ return newDate;
2644
2731
  };
2645
- const getParamsOfUserKey = (userKey) => {
2646
- const [userNickname, userCompanyKey] = userKey.split('|');
2647
- return { userNickname, userCompanyKey };
2732
+ Date.prototype.endOfDay = function () {
2733
+ const newDate = new Date(this);
2734
+ newDate.setHours(23, 59, 59, 999);
2735
+ return newDate;
2648
2736
  };
2649
- const getClientId = (sessionId, uiId) => {
2650
- return `${sessionId}|${uiId}`;
2737
+ Date.prototype.startOfHour = function () {
2738
+ const newDate = new Date(this);
2739
+ newDate.setMinutes(0, 0, 0);
2740
+ return newDate;
2651
2741
  };
2652
- const getParamsOfClientId = (clientId) => {
2653
- const [sessionId, uiId] = clientId.split('|');
2654
- return { sessionId, uiId };
2742
+ Date.prototype.endOfHour = function () {
2743
+ const newDate = new Date(this);
2744
+ newDate.setMinutes(59, 59, 999);
2745
+ return newDate;
2655
2746
  };
2656
-
2657
- const NEW_PAGE_SHEET = () => ({
2658
- id: v4(),
2659
- type: WorksheetType.NEW_PAGE,
2660
- title: '',
2661
- points: 0,
2662
- });
2663
- const ASPECT_RATIO = {
2664
- [AspectRatio.RATIO_21_9]: {
2665
- aspectRatio: AspectRatio.RATIO_21_9,
2666
- width: 2520,
2667
- height: 1080,
2668
- decimal: 21 / 9,
2669
- label: 'ultrawide',
2670
- },
2671
- [AspectRatio.RATIO_20_9]: {
2672
- aspectRatio: AspectRatio.RATIO_20_9,
2673
- width: 2400,
2674
- height: 1080,
2675
- decimal: 20 / 9,
2676
- label: 'mobile wide',
2677
- },
2678
- [AspectRatio.RATIO_16_9]: {
2679
- aspectRatio: AspectRatio.RATIO_16_9,
2680
- width: 1920,
2681
- height: 1080,
2682
- decimal: 16 / 9,
2683
- label: 'widescreen',
2684
- },
2685
- [AspectRatio.RATIO_16_10]: {
2686
- aspectRatio: AspectRatio.RATIO_16_10,
2687
- width: 1920,
2688
- height: 1200,
2689
- decimal: 16 / 10,
2690
- label: 'widescreen tall',
2691
- },
2692
- [AspectRatio.RATIO_3_2]: {
2693
- aspectRatio: AspectRatio.RATIO_3_2,
2694
- width: 1440,
2695
- height: 960,
2696
- decimal: 3 / 2,
2697
- label: 'balanced',
2698
- },
2699
- [AspectRatio.RATIO_4_3]: {
2700
- aspectRatio: AspectRatio.RATIO_4_3,
2701
- width: 1024,
2702
- height: 768,
2703
- decimal: 4 / 3,
2704
- label: 'standard',
2705
- },
2706
- [AspectRatio.RATIO_5_4]: {
2707
- aspectRatio: AspectRatio.RATIO_5_4,
2708
- width: 1280,
2709
- height: 1024,
2710
- decimal: 5 / 4,
2711
- label: 'square old',
2712
- },
2713
- [AspectRatio.RATIO_1_1]: {
2714
- aspectRatio: AspectRatio.RATIO_1_1,
2715
- width: 1000,
2716
- height: 1000,
2717
- decimal: 1,
2718
- label: 'square',
2719
- },
2747
+ Date.prototype.startOfMinute = function () {
2748
+ const newDate = new Date(this);
2749
+ newDate.setSeconds(0, 0);
2750
+ return newDate;
2720
2751
  };
2721
-
2722
- const getWorksheetsInPages = (initialSheets) => {
2723
- const sheets = [...initialSheets];
2724
- if (sheets[0]?.type !== WorksheetType.NEW_PAGE) {
2725
- sheets.unshift(NEW_PAGE_SHEET());
2726
- }
2727
- let newPage = sheets[0];
2728
- let content = [];
2729
- const sheetsByPages = [];
2730
- for (let i = 1; i < sheets.length; i++) {
2731
- const sheet = sheets[i];
2732
- if (sheet.type === WorksheetType.NEW_PAGE) {
2733
- sheetsByPages.push({
2734
- header: newPage,
2735
- content: [...content],
2736
- });
2737
- newPage = sheet;
2738
- content = [];
2739
- }
2740
- else {
2741
- content.push(sheet);
2742
- }
2743
- }
2744
- sheetsByPages.push({
2745
- header: newPage,
2746
- content: [...content],
2747
- });
2748
- return sheetsByPages;
2752
+ Date.prototype.endOfMinute = function () {
2753
+ const newDate = new Date(this);
2754
+ newDate.setSeconds(59, 999);
2755
+ return newDate;
2749
2756
  };
2750
- const getSummaryWorksheetsInPages = (initialSheets) => {
2751
- const sheets = [...initialSheets];
2752
- if (sheets[0]?.type !== WorksheetType.NEW_PAGE) {
2753
- sheets.unshift(NEW_PAGE_SHEET());
2754
- }
2755
- let newPage = sheets[0];
2756
- let content = [];
2757
- const sheetsByPages = [];
2758
- for (let i = 1; i < sheets.length; i++) {
2759
- const sheet = sheets[i];
2760
- if (sheet.type === WorksheetType.NEW_PAGE) {
2761
- sheetsByPages.push({
2762
- header: newPage,
2763
- content: content.map(c => ({
2764
- id: c.id,
2765
- type: c.type,
2766
- title: c.title,
2767
- points: c.points,
2768
- })),
2769
- });
2770
- newPage = sheet;
2771
- content = [];
2772
- }
2773
- else {
2774
- content.push(sheet);
2775
- }
2776
- }
2777
- sheetsByPages.push({
2778
- header: newPage,
2779
- content: [...content],
2780
- });
2781
- return sheetsByPages;
2757
+ Date.prototype.startOfSecond = function () {
2758
+ const newDate = new Date(this);
2759
+ newDate.setMilliseconds(0);
2760
+ return newDate;
2782
2761
  };
2783
- const getTotalExercisesOfSummaryWorksheetsInPages = (content) => content.reduce((sum, { content }) => sum + content.reduce((sum, { type }) => sum + +(type === WorksheetType.QUIZ_OPTIONS || type === WorksheetType.QUIZ_PROBLEM || type === WorksheetType.QUIZ_TEXT), 0), 0);
2784
- const isBasicWorksheet = (value) => {
2785
- return typeof value?.id == 'string' && value.id
2786
- && Object.values(WorksheetType).includes(value?.type)
2787
- && typeof value?.title == 'string'
2788
- && typeof value?.points == 'number';
2762
+ Date.prototype.endOfSecond = function () {
2763
+ const newDate = new Date(this);
2764
+ newDate.setMilliseconds(999);
2765
+ return newDate;
2789
2766
  };
2790
- const isJkmdSheet = (value) => {
2791
- return isBasicWorksheet(value)
2792
- && value?.type === WorksheetType.JK_MD
2793
- && typeof value?.content == 'string';
2767
+ Date.prototype.isToday = function () {
2768
+ const today = new Date();
2769
+ return this.isSameDay(today);
2794
2770
  };
2795
- const isCodeEditorSheet = (value) => {
2796
- return isBasicWorksheet(value)
2797
- && value?.type === WorksheetType.CODE_EDITOR
2798
- && typeof value?.sourceCode === 'object' && value?.sourceCode !== null
2799
- && value?.testCases === 'object' && value?.testCases !== null
2800
- && Array.isArray(value?.languages)
2801
- && typeof value?.height == 'number';
2771
+ Date.prototype.isEqual = function (date) {
2772
+ return this.getTime() === date.getTime();
2802
2773
  };
2803
- const isQuizProblemSheet = (value) => {
2804
- return isBasicWorksheet(value)
2805
- && value?.type === WorksheetType.QUIZ_PROBLEM
2806
- && Object.values(Judge).includes(value?.problemJudge) || typeof value?.problemJudge === 'string'
2807
- && typeof value?.problemKey == 'string'
2808
- && Array.isArray(value?.languages)
2809
- && typeof value?.height == 'number';
2774
+ Date.prototype.isSameYear = function (date) {
2775
+ return this.getFullYear() === date.getFullYear();
2810
2776
  };
2811
- const isQuizOptionsSheet = (value) => {
2812
- return isBasicWorksheet(value)
2813
- && value?.type === WorksheetType.QUIZ_OPTIONS
2814
- && typeof value?.description == 'string'
2815
- && Array.isArray(value?.options)
2816
- && value?.options.every((option) => typeof option?.label == 'string' && typeof option?.correct == 'boolean' && typeof option?.id == 'string')
2817
- && typeof value?.multiple == 'boolean'
2818
- && (value?.scoringMode === 'TOTAL' || value?.scoringMode === 'PARTIAL');
2777
+ Date.prototype.isSameMonth = function (date) {
2778
+ return this.isSameYear(date) && this.getMonth() === date.getMonth();
2819
2779
  };
2820
- const isQuizTextSheet = (value) => {
2821
- return isBasicWorksheet(value)
2822
- && value?.type === WorksheetType.QUIZ_TEXT
2823
- && typeof value?.description == 'string'
2824
- && typeof value?.answer == 'string'
2825
- && ['text', 'number', 'textarea'].includes(value?.inputType);
2780
+ Date.prototype.isSameDay = function (date) {
2781
+ return this.isSameMonth(date) && this.getDate() === date.getDate();
2782
+ };
2783
+ Date.prototype.isSameHour = function (date) {
2784
+ return this.isSameDay(date) && this.getHours() === date.getHours();
2785
+ };
2786
+ Date.prototype.isSameMinute = function (date) {
2787
+ return this.isSameHour(date) && this.getMinutes() === date.getMinutes();
2788
+ };
2789
+ Date.prototype.isSameSecond = function (date) {
2790
+ return this.isSameMinute(date) && this.getSeconds() === date.getSeconds();
2791
+ };
2792
+ Date.prototype.isSameMillisecond = function (date) {
2793
+ return this.isEqual(date);
2794
+ };
2795
+ Date.prototype.isValidDate = function () {
2796
+ return this instanceof Date && !isNaN(this.getTime());
2797
+ };
2798
+ Date.prototype.isYearAfter = function (date) {
2799
+ return this.getFullYear() > date.getFullYear();
2800
+ };
2801
+ Date.prototype.isMonthAfter = function (date) {
2802
+ return this.isYearAfter(date) || (this.isSameYear(date) && this.getMonth() > date.getMonth());
2803
+ };
2804
+ Date.prototype.isDayAfter = function (date) {
2805
+ return this.isMonthAfter(date) || (this.isSameMonth(date) && this.getDate() > date.getDate());
2806
+ };
2807
+ Date.prototype.isHoursAfter = function (date) {
2808
+ return this.isDayAfter(date) || (this.isSameDay(date) && this.getHours() > date.getHours());
2809
+ };
2810
+ Date.prototype.isMinutesAfter = function (date) {
2811
+ return this.isHoursAfter(date) || (this.isSameHour(date) && this.getMinutes() > date.getMinutes());
2812
+ };
2813
+ Date.prototype.isSecondsAfter = function (date) {
2814
+ return this.isMinutesAfter(date) || (this.isSameMinute(date) && this.getSeconds() > date.getSeconds());
2815
+ };
2816
+ Date.prototype.isMillisecondsAfter = function (date) {
2817
+ return this.isSecondsAfter(date) || (this.isSameSecond(date) && this.getMilliseconds() > date.getMilliseconds());
2818
+ };
2819
+ Date.prototype.isAfter = function (date) {
2820
+ return this.getTime() > date.getTime();
2821
+ };
2822
+ Date.prototype.isYearBefore = function (date) {
2823
+ return this.getFullYear() < date.getFullYear();
2824
+ };
2825
+ Date.prototype.isMonthBefore = function (date) {
2826
+ return this.isYearBefore(date) || (this.isSameYear(date) && this.getMonth() < date.getMonth());
2827
+ };
2828
+ Date.prototype.isDayBefore = function (date) {
2829
+ return this.isMonthBefore(date) || (this.isSameMonth(date) && this.getDate() < date.getDate());
2830
+ };
2831
+ Date.prototype.isHoursBefore = function (date) {
2832
+ return this.isDayBefore(date) || (this.isSameDay(date) && this.getHours() < date.getHours());
2833
+ };
2834
+ Date.prototype.isMinutesBefore = function (date) {
2835
+ return this.isHoursBefore(date) || (this.isSameHour(date) && this.getMinutes() < date.getMinutes());
2836
+ };
2837
+ Date.prototype.isSecondsBefore = function (date) {
2838
+ return this.isMinutesBefore(date) || (this.isSameMinute(date) && this.getSeconds() < date.getSeconds());
2839
+ };
2840
+ Date.prototype.isMillisecondsBefore = function (date) {
2841
+ return this.isSecondsBefore(date) || (this.isSameSecond(date) && this.getMilliseconds() < date.getMilliseconds());
2842
+ };
2843
+ Date.prototype.isBefore = function (date) {
2844
+ return this.getTime() < date.getTime();
2845
+ };
2846
+ Date.prototype.isWithinInterval = function ({ start, end }, cmp = '[]') {
2847
+ return (cmp.charAt(0) === '[' ? this.isEqual(start) || this.isAfter(start) : this.isAfter(start)) &&
2848
+ (cmp.charAt(1) === '[' ? this.isEqual(end) || this.isBefore(end) : this.isBefore(end));
2826
2849
  };
2827
2850
 
2828
- const YEARS = range(1970, 2100);
2829
- const MONTH_NAMES = [
2830
- 'January',
2831
- 'February',
2832
- 'March',
2833
- 'April',
2834
- 'May',
2835
- 'June',
2836
- 'July',
2837
- 'August',
2838
- 'September',
2839
- 'October',
2840
- 'November',
2841
- 'December',
2842
- ];
2843
- const DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
2844
- const HOURS = range(0, 24);
2845
- const MINUTES = range(0, 60);
2846
- const SECONDS = range(0, 60);
2847
- const MILLISECONDS = range(0, 1000);
2848
- const MAX_DATE = new Date(8640000000000000);
2849
- const MIN_DATE = new Date(0);
2851
+ class JkError extends Error {
2852
+ constructor(code, custom) {
2853
+ const message = custom?.message || ERROR[code].message;
2854
+ super(message);
2855
+ this.message = message;
2856
+ this.code = code;
2857
+ if (custom?.stack) {
2858
+ this.stack = custom.stack;
2859
+ }
2860
+ if (custom?.data) {
2861
+ this.data = custom.data;
2862
+ }
2863
+ }
2864
+ }
2850
2865
 
2851
- const SUPPORT_EMAIL = 'support@juki.app';
2852
- const JUKI_APP_EMAIL_TEMPLATE = `<div style="width: 100%; background: #F2F2F2;">
2853
- <div style="background: #164066; width: 100%;">
2854
- <div style="height: 56px; color: white; width: 100px; margin: 0 auto">
2855
- <img
2856
- src="https://images.juki.pub/assets/juki-app-horizontal-white-logo.svg"
2857
- alt="juki app logo"
2858
- height="56px"
2859
- style="padding:10px; box-sizing: border-box"
2860
- />
2861
- </div>
2862
- </div>
2863
- <div style="padding: 24px; color: #333333; font-family: sans-serif; font-size: 16px; line-height: 24px;">
2864
- <div style="max-width: 520px; margin: 0 auto; padding: 24px; background: white; border-radius: 6px;">
2865
- <section style="padding: 0 0 1em 0; border-bottom: 1px solid #828282;">
2866
- {{content}}
2867
- </section>
2868
- <div style="font-size: 14px; text-align: center; color: #828282; line-height: 16px; padding-top: 1em">
2869
- <p style="margin: 0;">
2870
- Si tú no realizaste la solicitud, escribenos a
2871
- <a href="mailto:${SUPPORT_EMAIL}" style="color: #2468A6; text-decoration: none;">
2872
- ${SUPPORT_EMAIL}
2873
- </a>
2874
- </p>
2875
- <p style="margin: 0;">
2876
- Este mensaje fue enviado por el equipo de
2877
- <a href="https://juki.app" style="color: #2468A6; text-decoration: none;">
2878
- juki.app
2879
- </a>
2880
- </p>
2881
- </div>
2882
- </div>
2883
- </div>
2884
- </div>`;
2866
+ /* eslint-disable no-extend-native */
2867
+ Number.prototype.padStart = function (maxLength, fillString = '0') {
2868
+ return (this + '').padStart(maxLength, fillString);
2869
+ };
2870
+ Number.prototype.padEnd = function (maxLength, fillString = '0') {
2871
+ return (this + '').padEnd(maxLength, fillString);
2872
+ };
2885
2873
 
2886
- const EMPTY_DOCUMENT_MEMBERS = () => ({
2887
- access: EntityAccess.PRIVATE,
2888
- managers: {},
2889
- spectators: {},
2890
- });
2891
- const EMPTY_ENTITY_MEMBERS = () => ({
2892
- rankAdministrators: EntityMembersRank.CLOSE,
2893
- administrators: {},
2894
- rankManagers: EntityMembersRank.CLOSE,
2895
- managers: {},
2896
- rankGuests: EntityMembersRank.CLOSE,
2897
- guests: {},
2898
- rankSpectators: EntityMembersRank.CLOSE,
2899
- spectators: {},
2900
- rankParticipants: EntityMembersRank.CLOSE,
2901
- participants: {},
2902
- });
2874
+ function toJkError(err) {
2875
+ const error = new Error();
2876
+ let code = err?.code;
2877
+ if (!(code in ErrorCode)) {
2878
+ code = ErrorCode.ERR500;
2879
+ }
2880
+ return new JkError(code, {
2881
+ message: err?.message || error.message,
2882
+ stack: err?.stack || error.stack,
2883
+ data: err?.data || null,
2884
+ });
2885
+ }
2886
+ function errorsResponse(message, ...errors) {
2887
+ return {
2888
+ success: false,
2889
+ message: message,
2890
+ errors: errors.map(error => ({
2891
+ code: error.code,
2892
+ message: error.message,
2893
+ detail: error.stack || new Error().stack || '',
2894
+ data: error.data,
2895
+ })),
2896
+ };
2897
+ }
2898
+ function contentResponse(message, content) {
2899
+ return {
2900
+ success: true,
2901
+ message,
2902
+ content,
2903
+ };
2904
+ }
2905
+ function contentsResponse(message, contents, meta) {
2906
+ return {
2907
+ success: true,
2908
+ message,
2909
+ contents,
2910
+ meta,
2911
+ };
2912
+ }
2913
+ const cleanRequest = (responseText) => {
2914
+ if (!isStringJson(responseText)) {
2915
+ // this occurs when the endpoint don't exits or server is down
2916
+ const response = {
2917
+ success: false,
2918
+ message: ERROR[ErrorCode.ERR9999].message,
2919
+ errors: [{ code: ErrorCode.ERR9999, detail: '', message: ERROR[ErrorCode.ERR9999].message }],
2920
+ };
2921
+ consoleError({ message: 'response is not string json, success false on cleaning request', responseText, response });
2922
+ // jukiApiManager.reportError({ message: 'success false on cleaning request', responseText, response });
2923
+ return response;
2924
+ }
2925
+ const responseJson = JSON.parse(responseText);
2926
+ if (typeof responseJson.success === 'boolean') {
2927
+ if (responseJson.success === true && typeof responseJson.message === 'string' && responseJson.content) { // V1
2928
+ return {
2929
+ success: true,
2930
+ message: responseJson.message,
2931
+ content: responseJson.content,
2932
+ };
2933
+ }
2934
+ else if (responseJson.success === true && typeof responseJson.message === 'string' && Array.isArray(responseJson.contents) && responseJson.meta) { // V1
2935
+ return {
2936
+ success: true,
2937
+ message: responseJson.message,
2938
+ contents: responseJson.contents,
2939
+ meta: responseJson.meta,
2940
+ };
2941
+ }
2942
+ else if (responseJson.success === false && typeof responseJson.message === 'string' && Array.isArray(responseJson.errors)) { // V1
2943
+ const response = {
2944
+ success: false,
2945
+ message: responseJson.message,
2946
+ errors: responseJson.errors,
2947
+ };
2948
+ consoleError({ message: 'success false on cleaning request', responseText, response });
2949
+ // jukiApiManager.reportError({ message: 'success false on cleaning request', responseText, response });
2950
+ return response;
2951
+ }
2952
+ }
2953
+ const response = {
2954
+ success: false,
2955
+ message: ERROR[ErrorCode.ERR9998].message,
2956
+ errors: [{ code: ErrorCode.ERR9998, detail: '', message: ERROR[ErrorCode.ERR9998].message }],
2957
+ };
2958
+ consoleError({ message: 'success false on cleaning request', responseText, response });
2959
+ // jukiApiManager.reportError({ message: 'success false on cleaning request', responseText, response });
2960
+ return response;
2961
+ };
2962
+ const getDefaultMeta = (contents, sort) => {
2963
+ return { sort: sort ?? [], page: 1, size: contents.length, totalElements: contents.length, filter: {} };
2964
+ };
2903
2965
 
2904
- const JUDGE = {
2905
- // [Judge.CUSTOMER]: {
2906
- // value: Judge.CUSTOMER,
2907
- // label: '',
2908
- // logo: 'https://images.juki.pub/c/juki-judge-logo-horizontal-color.svg',
2909
- // logoSize: [ 883.991, 435 ],
2910
- // url: '',
2911
- // // getLoginUrl: () => '',
2912
- // // getProfileUrl: () => '',
2913
- // // getSubmitUrl: () => '',
2914
- // // getSubmissionUrl: () => '',
2915
- // // getProblemUrl: (key: string) => `/problem/view/${key}`,
2916
- // // getUserSubmissionsUrl: () => '',
2917
- // },
2918
- [Judge.JUKI_JUDGE]: {
2919
- value: Judge.JUKI_JUDGE,
2920
- label: 'Juki Judge',
2921
- logo: 'https://images.juki.pub/c/juki-judge-logo-horizontal-color.svg',
2922
- logoSize: [883.991, 435],
2923
- url: 'https://judge.juki.app',
2924
- // getLoginUrl: () => '',
2925
- // getProfileUrl: () => '',
2926
- // getSubmitUrl: () => '',
2927
- // getSubmissionUrl: () => '',
2928
- // getProblemUrl: (key: string) => `https://judge.juki.app/problem/view/${key}`,
2929
- // getUserSubmissionsUrl: () => '',
2930
- },
2931
- [Judge.CODEFORCES]: {
2932
- value: Judge.CODEFORCES,
2933
- label: 'Codeforces',
2934
- logo: 'https://images.juki.pub/c/codeforces-logo-horizontal-color.svg',
2935
- logoSize: [1232.75, 145.12],
2936
- url: 'https://codeforces.com',
2937
- // getLoginUrl: () => 'https://codeforces.com/enter',
2938
- // getProfileUrl: () => '',
2939
- // getSubmitUrl: () => 'https://codeforces.com/problemset/submit',
2940
- // getSubmissionUrl: (problemKey: string, submissionId: string) => {
2941
- // const [ contestId ] = problemKey.split('-');
2942
- // return `https://codeforces.com/problemset/submission/${contestId}/${submissionId}`;
2943
- // },
2944
- // getProblemUrl: (problemKey: string) => {
2945
- // const [ contestId, index ] = problemKey.split('-');
2946
- // return `https://codeforces.com/problemset/problem/${contestId}/${index}`;
2947
- // },
2948
- // getUserSubmissionsUrl: () => '',
2949
- },
2950
- [Judge.CODEFORCES_GYM]: {
2951
- value: Judge.CODEFORCES_GYM,
2952
- label: 'Codeforces Gym',
2953
- logo: 'https://images.juki.pub/c/codeforces-logo-horizontal-color.svg',
2954
- logoSize: [1232.75, 145.12],
2955
- url: 'https://codeforces.com',
2956
- // getLoginUrl: () => 'https://codeforces.com/enter',
2957
- // getProfileUrl: () => '',
2958
- // getSubmitUrl: (problemKey: string) => {
2959
- // const [ gymContestId, index ] = problemKey.split('-');
2960
- // return `https://codeforces.com/gym/${gymContestId}/submit`;
2961
- // },
2962
- // getSubmissionUrl: (problemKey: string, submissionId: string) => {
2963
- // const [ gymContestId ] = problemKey.split('-');
2964
- // return `https://codeforces.com/gym/${gymContestId}/submission/${submissionId}`;
2965
- // },
2966
- // getProblemUrl: (problemKey: string) => {
2967
- // const [ gymContestId, index ] = problemKey.split('-');
2968
- // return `https://codeforces.com/gym/${gymContestId}/problem/${index}`;
2969
- // },
2970
- // getUserSubmissionsUrl: () => '',
2971
- },
2972
- [Judge.JV_UMSA]: {
2973
- value: Judge.JV_UMSA,
2974
- label: 'Juez Virtual UMSA',
2975
- logo: 'https://images.juki.pub/c/codeforces-logo-horizontal-color.svg',
2976
- logoSize: [1232.75, 145.12],
2977
- url: 'https://jv.umsa.bo',
2978
- // getLoginUrl: () => 'https://jv.umsa.bo/oj/login.php',
2979
- // getProfileUrl: () => 'https://jv.umsa.bo/oj/userInfo.php',
2980
- // getSubmitUrl: (problemKey: string) => {
2981
- // // single problem: '1019'
2982
- // // cib problem: '1019-A'
2983
- // const isContestProblem = problemKey.includes('-');
2984
- // // A -> 0, B -> 1, C -> 2, D -> 3, E -> 4, F -> 5, G -> 6, H -> 7, I -> 8, J -> 9
2985
- // const params = problemKey.split('-');
2986
- // return isContestProblem
2987
- // ? `https://jv.umsa.bo/oj/submitpage.php?cid=${params[0]}&pid=${params[1].charCodeAt(0) - 65}`
2988
- // : `https://jv.umsa.bo/oj/submitpage.php?id=${problemKey}`;
2989
- // },
2990
- // getSubmissionUrl: (problemKey: string, submissionId: string, username: string) => {
2991
- // // return `https://jv.umsa.bo/status.php?problem_id=&user_id=${username}&language=-1&jresult=-1`;
2992
- // return `https://jv.umsa.bo/oj/showsource.php?id=${submissionId}`;
2993
- // },
2994
- // getProblemUrl: (problemKey: string) => {
2995
- // const isContestProblem = problemKey.includes('-');
2996
- // const params = problemKey.split('-');
2997
- // return isContestProblem
2998
- // ? `https://jv.umsa.bo/oj/problem.php?cid=${params[0]}&pid=${params[1].charCodeAt(0) - 65}`
2999
- // : `https://jv.umsa.bo/oj/problem.php?id=${problemKey}`;
3000
- // },
3001
- // getUserSubmissionsUrl: (username: string) => `https://jv.umsa.bo/oj/status.php?user_id=${username}`,
3002
- },
3003
- [Judge.UVA_ONLINE_JUDGE]: {
3004
- value: Judge.UVA_ONLINE_JUDGE,
3005
- label: 'Uva Online Judge',
3006
- logo: 'https://images.juki.pub/c/uva-online-judge-logo-color.png',
3007
- logoSize: [150, 135.994],
3008
- url: 'https://onlinejudge.org',
3009
- },
3010
- [Judge.AT_CODER]: {
3011
- value: Judge.AT_CODER,
3012
- label: 'AtCoder',
3013
- logo: 'https://images.juki.pub/c/at-coder-logo-color.png',
3014
- logoSize: [762.997, 675],
3015
- url: 'https://atcoder.jp',
3016
- },
3017
- [Judge.CODECHEF]: {
3018
- value: Judge.CODECHEF,
3019
- label: 'Codechef',
3020
- logo: 'https://images.juki.pub/c/codechef-logo-color.svg',
3021
- logoSize: [1207.7, 453.17],
3022
- url: 'https://www.codechef.com',
3023
- },
3024
- [Judge.TOPCODER]: {
3025
- value: Judge.TOPCODER,
3026
- label: 'Topcoder',
3027
- logo: 'https://images.juki.pub/c/topcoder-logo-color.png',
3028
- logoSize: [971.99, 415.99],
3029
- url: 'https://www.topcoder.com',
3030
- },
3031
- [Judge.LEETCODE]: {
3032
- value: Judge.LEETCODE,
3033
- label: 'LeetCode',
3034
- logo: 'https://images.juki.pub/assets/leetcode-logo-color.svg',
3035
- logoSize: [95, 111],
3036
- url: 'https://leetcode.com',
3037
- // getProblemUrl: (problemKey: string) => {
3038
- // return `https://leetcode.com/problems/${problemKey.replace('PL-', '')}`;
3039
- // },
3040
- // getProfileUrl: (userNickname: string) => {
3041
- // return `https://leetcode.com/u/${userNickname}`;
3042
- // },
3043
- // getSubmissionUrl: (problemKey: string, submissionId: string, username: string, submissionRunId: string) => {
3044
- // return `https://leetcode.com/problems/${problemKey.replace('PL-', '')}/submissions/${submissionRunId}`;
3045
- // },
3046
- },
2966
+ const isWebsocketSubscription = (event) => {
2967
+ return (Object.values(WebSocketSubscriptionEvent).includes(event?.event) || Object.values(WebSocketMessageEvent).includes(event?.event))
2968
+ && typeof event?.clientId === 'string' && !!event.clientId;
3047
2969
  };
3048
- const RUNNER_ACCEPTED_PROBLEM_MODES = [
3049
- ProblemScoringMode.TOTAL,
3050
- ProblemScoringMode.SUBTASK,
3051
- ProblemScoringMode.PARTIAL,
3052
- ];
3053
- const RUNNER_ACCEPTED_PROBLEM_TYPES = [
3054
- ProblemType.STANDARD,
3055
- ProblemType.DYNAMIC,
3056
- ];
3057
- const RUNNER_ACCEPTED_PROGRAMMING_LANGUAGES = [
3058
- CodeLanguage.C_11,
3059
- CodeLanguage.CPP_11,
3060
- CodeLanguage.CPP_20,
3061
- CodeLanguage.JAVA_21,
3062
- CodeLanguage.PYTHON_3,
3063
- CodeLanguage.PYTHON_PYPY_3,
3064
- CodeLanguage.JAVASCRIPT_NODE_JS_22,
3065
- CodeLanguage.PSEUDOCODE_PSEINT,
3066
- ];
3067
- const ACCEPTED_PROGRAMMING_LANGUAGES = [
3068
- ...RUNNER_ACCEPTED_PROGRAMMING_LANGUAGES,
3069
- ];
3070
- const PROBLEM_VERDICT = {
3071
- [ProblemVerdict.NONE]: { value: ProblemVerdict.NONE, label: 'none', color: '#555555' },
3072
- [ProblemVerdict.PENDING]: { value: ProblemVerdict.PENDING, label: 'pending', color: '#79B6FD' },
3073
- [ProblemVerdict.HIDDEN]: { value: ProblemVerdict.HIDDEN, label: 'hidden', color: '#555555' },
3074
- [ProblemVerdict.AC]: { value: ProblemVerdict.AC, label: 'accepted', color: '#43D787' },
3075
- [ProblemVerdict.PE]: { value: ProblemVerdict.PE, label: 'presentation error', color: '#55db93' },
3076
- [ProblemVerdict.PA]: { value: ProblemVerdict.PA, label: 'partial accepted', color: '#55db93' },
3077
- [ProblemVerdict.CE]: { value: ProblemVerdict.CE, label: 'compilation error', color: '#FE9F9F' },
3078
- [ProblemVerdict.RE]: { value: ProblemVerdict.RE, label: 'runtime error', color: '#FE9F9F' },
3079
- [ProblemVerdict.TLE]: { value: ProblemVerdict.TLE, label: 'time limit exceed', color: '#FE9F9F' },
3080
- [ProblemVerdict.MLE]: { value: ProblemVerdict.MLE, label: 'memory limit exceed', color: '#FE9F9F' },
3081
- [ProblemVerdict.WA]: { value: ProblemVerdict.WA, label: 'wrong answer', color: '#FE9F9F' },
2970
+ // Custom CHANNEL_PUBLISH_MESSAGES
2971
+ const isPingWebSocketEventDTO = (event) => {
2972
+ return isWebsocketSubscription(event)
2973
+ && event?.event === WebSocketMessageEvent.PING;
2974
+ };
2975
+ const isClientTrackLocationWebSocketEventDTO = (event) => {
2976
+ return isWebsocketSubscription(event)
2977
+ && event?.event === WebSocketMessageEvent.CLIENT_TRACK_LOCATION;
2978
+ };
2979
+ const isClientTrackScreenshotWebSocketEventDTO = (event) => {
2980
+ return isWebsocketSubscription(event)
2981
+ && event?.event === WebSocketMessageEvent.CLIENT_TRACK_SCREENSHOT;
2982
+ };
2983
+ const isClientTrackDeviceWebSocketEventDTO = (event) => {
2984
+ return isWebsocketSubscription(event)
2985
+ && event?.event === WebSocketMessageEvent.CLIENT_TRACK_DEVICE;
2986
+ };
2987
+ const isChatCompletionsWebSocketEventDTO = (event) => {
2988
+ return isWebsocketSubscription(event)
2989
+ && event?.event === WebSocketMessageEvent.CHAT_COMPLETIONS;
2990
+ };
2991
+ // CHANNEL_PUBLISH_SUBSCRIPTIONS
2992
+ const isSubscribeCodeRunStatusWebSocketEventDTO = (event) => {
2993
+ return isWebsocketSubscription(event)
2994
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CODE_RUN_STATUS
2995
+ && typeof event?.runId === 'string' && !!event.runId;
2996
+ };
2997
+ const isUnsubscribeCodeRunStatusWebSocketEventDTO = (event) => {
2998
+ return isWebsocketSubscription(event)
2999
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CODE_RUN_STATUS
3000
+ && typeof event?.runId === 'string' && !!event.runId;
3001
+ };
3002
+ const isSubscribeSubmissionRunStatusWebSocketEventDTO = (event) => {
3003
+ return isWebsocketSubscription(event)
3004
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_SUBMISSION_RUN_STATUS
3005
+ && typeof event?.submitId === 'string' && !!event.submitId;
3006
+ };
3007
+ const isUnsubscribeSubmissionRunStatusWebSocketEventDTO = (event) => {
3008
+ return isWebsocketSubscription(event)
3009
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_SUBMISSION_RUN_STATUS
3010
+ && typeof event?.submitId === 'string' && !!event.submitId;
3011
+ };
3012
+ const isSubscribeGetDataWebSocketEventDTO = (event) => {
3013
+ return isWebsocketSubscription(event)
3014
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_GET_DATA;
3015
+ };
3016
+ const isUnsubscribeGetDataWebSocketEventDTO = (event) => {
3017
+ return isWebsocketSubscription(event)
3018
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_GET_DATA;
3019
+ };
3020
+ const isSubscribeProblemCrawledWebSocketEventDTO = (event) => {
3021
+ return isWebsocketSubscription(event)
3022
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_PROBLEM_CRAWLED;
3023
+ };
3024
+ const isUnsubscribeProblemCrawledWebSocketEventDTO = (event) => {
3025
+ return isWebsocketSubscription(event)
3026
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_PROBLEM_CRAWLED;
3027
+ };
3028
+ const isSubscribeSubmissionsCrawlWebSocketEventDTO = (event) => {
3029
+ return isWebsocketSubscription(event)
3030
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_SUBMISSIONS_CRAWL;
3031
+ };
3032
+ const isUnsubscribeSubmissionsCrawlWebSocketEventDTO = (event) => {
3033
+ return isWebsocketSubscription(event)
3034
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_SUBMISSIONS_CRAWL;
3035
+ };
3036
+ const isSubscribeContestChangesWebSocketEventDTO = (event) => {
3037
+ return isWebsocketSubscription(event)
3038
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CONTEST_CHANGES;
3039
+ };
3040
+ const isUnsubscribeContestChangesWebSocketEventDTO = (event) => {
3041
+ return isWebsocketSubscription(event)
3042
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CONTEST_CHANGES;
3043
+ };
3044
+ const isSubscribeClientTrackWebSocketEventDTO = (event) => {
3045
+ return isWebsocketSubscription(event)
3046
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CLIENT_TRACK;
3047
+ };
3048
+ const isUnsubscribeClientTrackWebSocketEventDTO = (event) => {
3049
+ return isWebsocketSubscription(event)
3050
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CLIENT_TRACK;
3051
+ };
3052
+ const isSubscribeUserNotificationWebSocketEventDTO = (event) => {
3053
+ return isWebsocketSubscription(event)
3054
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_USER_NOTIFICATION;
3055
+ };
3056
+ const isUnsubscribeUserNotificationWebSocketEventDTO = (event) => {
3057
+ return isWebsocketSubscription(event)
3058
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_USER_NOTIFICATION;
3059
+ };
3060
+ const isSubscribeClientTrackDataWebSocketEventDTO = (event) => {
3061
+ return isWebsocketSubscription(event)
3062
+ && event?.event === WebSocketSubscriptionEvent.SUBSCRIBE_CLIENT_TRACK_DATA
3063
+ && typeof event?.trackedClientId === 'string' && !!event.trackedClientId;
3064
+ };
3065
+ const isUnsubscribeClientTrackDataWebSocketEventDTO = (event) => {
3066
+ return isWebsocketSubscription(event)
3067
+ && event?.event === WebSocketSubscriptionEvent.UNSUBSCRIBE_CLIENT_TRACK_DATA
3068
+ && typeof event?.trackedClientId === 'string' && !!event.trackedClientId;
3069
+ };
3070
+ // is WebSocketResponseEventDTO, CHANNEL_SUBSCRIBE_CLIENT
3071
+ const isWebSocketResponseEventDTO = (event) => {
3072
+ return Object.values(WebSocketResponseEvent).includes(event?.event)
3073
+ && typeof event?.key === 'string'
3074
+ && typeof event?.connectionId === 'string'
3075
+ && typeof event?.messageTimestamp === 'number' && !!event.messageTimestamp;
3076
+ };
3077
+ const isPongWebSocketResponseEventDTO = (event) => {
3078
+ return isWebSocketResponseEventDTO(event)
3079
+ && event?.event === WebSocketResponseEvent.PONG
3080
+ && !!event?.data;
3081
+ };
3082
+ const isCodeRunStatusMessageWebSocketResponseEventDTO = (event) => {
3083
+ return isWebSocketResponseEventDTO(event)
3084
+ && event?.event === WebSocketResponseEvent.CODE_RUN_STATUS
3085
+ && typeof event?.runId === 'string' && !!event.runId
3086
+ && event?.status in SubmissionRunStatus;
3087
+ };
3088
+ const isSubmissionRunStatusMessageWebSocketResponseEventDTO = (event) => {
3089
+ return isWebSocketResponseEventDTO(event)
3090
+ && event?.event === WebSocketResponseEvent.SUBMISSION_RUN_STATUS
3091
+ && typeof event?.submitId === 'string' && !!event.submitId
3092
+ && event?.status in SubmissionRunStatus
3093
+ && event?.verdict in ProblemVerdict
3094
+ && typeof event?.points === 'number';
3095
+ };
3096
+ const isUserMessageWebSocketResponseEventDTO = (event) => {
3097
+ return isWebSocketResponseEventDTO(event)
3098
+ && event?.event === WebSocketResponseEvent.USER_MESSAGE
3099
+ && typeof event?.user?.nickname === 'string' && !!event.user?.nickname
3100
+ && typeof event?.user?.imageUrl === 'string' && !!event.user?.imageUrl
3101
+ && typeof event?.user?.company?.key === 'string' && !!event.user?.company?.key
3102
+ && !!event?.content;
3103
+ };
3104
+ const isSendDataWebSocketResponseEventDTO = (event) => {
3105
+ return [
3106
+ WebSocketResponseEvent.SEND_DATA_ECS_TASK_DEFINITIONS_LIST,
3107
+ WebSocketResponseEvent.SEND_DATA_EC2_INSTANCES_LIST,
3108
+ WebSocketResponseEvent.SEND_DATA_ECS_TASKS_LIST,
3109
+ WebSocketResponseEvent.SEND_DATA_SSM_SESSIONS_LIST,
3110
+ WebSocketResponseEvent.SEND_DATA_RUN_COMMAND,
3111
+ WebSocketResponseEvent.SEND_DATA_CLIENT_TRACK,
3112
+ WebSocketResponseEvent.SEND_DATA_CHAT_COMPLETIONS,
3113
+ ].includes(event?.event)
3114
+ && typeof event?.dataId === 'string' && !!event.dataId
3115
+ && !!event?.content;
3116
+ };
3117
+ const isSendDataEcsTaskDefinitionListWebSocketResponseEventDTO = (event) => {
3118
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3119
+ && event?.event === WebSocketResponseEvent.SEND_DATA_ECS_TASK_DEFINITIONS_LIST;
3120
+ };
3121
+ const isSendDataEc2InstancesListWebSocketResponseEventDTO = (event) => {
3122
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3123
+ && event?.event === WebSocketResponseEvent.SEND_DATA_EC2_INSTANCES_LIST;
3124
+ };
3125
+ const isSendDataEcsTasksListWebSocketResponseEventDTO = (event) => {
3126
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3127
+ && event?.event === WebSocketResponseEvent.SEND_DATA_ECS_TASKS_LIST;
3128
+ };
3129
+ const isSendDataSsmSessionsListWebSocketResponseEventDTO = (event) => {
3130
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3131
+ && event?.event === WebSocketResponseEvent.SEND_DATA_SSM_SESSIONS_LIST;
3132
+ };
3133
+ const isSendDataRunCommandWebSocketResponseEventDTO = (event) => {
3134
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3135
+ && event?.event === WebSocketResponseEvent.SEND_DATA_RUN_COMMAND;
3136
+ };
3137
+ const isSendDataClientTrackWebSocketResponseEventDTO = (event) => {
3138
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3139
+ && event?.event === WebSocketResponseEvent.SEND_DATA_CLIENT_TRACK;
3140
+ };
3141
+ const isSenDataChatCompletionsWebSocketResponseEventDTO = (event) => {
3142
+ return isWebSocketResponseEventDTO(event) && isSendDataWebSocketResponseEventDTO(event)
3143
+ && event?.event === WebSocketResponseEvent.SEND_DATA_CHAT_COMPLETIONS;
3082
3144
  };
3083
- const PROBLEM_VERDICTS = [
3084
- ProblemVerdict.NONE,
3085
- ProblemVerdict.PENDING,
3086
- ProblemVerdict.AC,
3087
- ProblemVerdict.PE,
3088
- ProblemVerdict.PA,
3089
- ProblemVerdict.CE,
3090
- ProblemVerdict.RE,
3091
- ProblemVerdict.TLE,
3092
- ProblemVerdict.MLE,
3093
- ProblemVerdict.WA,
3094
- ];
3095
- const SUBMISSION_RUN_STATUS = {
3096
- [SubmissionRunStatus.NONE]: { value: SubmissionRunStatus.NONE, label: 'none' }, // status
3097
- [SubmissionRunStatus.RECEIVED]: { value: SubmissionRunStatus.RECEIVED, label: 'received' }, // state
3098
- [SubmissionRunStatus.COMPILING]: { value: SubmissionRunStatus.COMPILING, label: 'compiling' }, // state
3099
- [SubmissionRunStatus.COMPILED]: { value: SubmissionRunStatus.COMPILED, label: 'compiled' }, // status
3100
- [SubmissionRunStatus.COMPILATION_ERROR]: { value: SubmissionRunStatus.COMPILATION_ERROR, label: 'compilation error' }, // status
3101
- [SubmissionRunStatus.FETCHING_TEST_CASES]: {
3102
- value: SubmissionRunStatus.FETCHING_TEST_CASES,
3103
- label: 'fetching test cases',
3104
- }, // state
3105
- [SubmissionRunStatus.RUNNING_TEST_CASE]: { value: SubmissionRunStatus.RUNNING_TEST_CASE, label: 'running test case' }, // state
3106
- [SubmissionRunStatus.RUNNING_TEST_CASES]: {
3107
- value: SubmissionRunStatus.RUNNING_TEST_CASES,
3108
- label: 'running test cases',
3109
- }, // state
3110
- [SubmissionRunStatus.RUNNING_SAMPLE_TEST_CASES]: {
3111
- value: SubmissionRunStatus.RUNNING_SAMPLE_TEST_CASES,
3112
- label: 'running sample cases',
3113
- }, // state
3114
- [SubmissionRunStatus.EXECUTED_TEST_CASE]: {
3115
- value: SubmissionRunStatus.EXECUTED_TEST_CASE,
3116
- label: 'executed test case',
3117
- }, // status
3118
- [SubmissionRunStatus.FAILED_TEST_CASE]: { value: SubmissionRunStatus.FAILED_TEST_CASE, label: 'failed test case' }, // status
3119
- [SubmissionRunStatus.JUDGING_TEST_CASE]: { value: SubmissionRunStatus.JUDGING_TEST_CASE, label: 'judging test case' }, // state
3120
- [SubmissionRunStatus.GRADING]: { value: SubmissionRunStatus.GRADING, label: 'grading' }, // status
3121
- [SubmissionRunStatus.FAILED]: { value: SubmissionRunStatus.FAILED, label: 'failed' }, // status
3122
- [SubmissionRunStatus.COMPLETED]: { value: SubmissionRunStatus.COMPLETED, label: 'completed' }, // status
3145
+ const isProblemCrawledWebSocketResponseEventDTO = (event) => {
3146
+ return isWebSocketResponseEventDTO(event)
3147
+ && event?.event === WebSocketResponseEvent.PROBLEM_CRAWLED
3148
+ && !!event?.content;
3123
3149
  };
3124
- const RUNNER_TYPE = {
3125
- [RunnerType.HIGH_PERFORMANCE]: { value: RunnerType.HIGH_PERFORMANCE, label: 'high performance' },
3126
- [RunnerType.LOW_PERFORMANCE]: { value: RunnerType.LOW_PERFORMANCE, label: 'low performance' },
3150
+ const isSubmissionsCrawlWebSocketResponseEventDTO = (event) => {
3151
+ return isWebSocketResponseEventDTO(event)
3152
+ && event?.event === WebSocketResponseEvent.SUBMISSIONS_CRAWL
3153
+ && !!event?.content;
3127
3154
  };
3128
-
3129
- const PROBLEM_INPUT = {
3130
- [ProblemInput.STANDARD]: { value: ProblemInput.STANDARD, label: 'standard' },
3131
- [ProblemInput.INTERACTIVE]: { value: ProblemInput.INTERACTIVE, label: 'interactive' },
3155
+ const isContestChangesWebSocketResponseEventDTO = (event) => {
3156
+ return isWebSocketResponseEventDTO(event)
3157
+ && event?.event === WebSocketResponseEvent.CONTEST_CHANGES
3158
+ && !!event?.content;
3132
3159
  };
3133
- const PROBLEM_OUTPUT = {
3134
- [ProblemOutput.STANDARD]: { value: ProblemOutput.STANDARD, label: 'standard' },
3135
- [ProblemOutput.DYNAMIC]: { value: ProblemOutput.DYNAMIC, label: 'dynamic' },
3136
- [ProblemOutput.INTERACTIVE]: { value: ProblemOutput.INTERACTIVE, label: 'interactive' },
3160
+ const isClientTrackWebSocketResponseEventDTO = (event) => {
3161
+ return isWebSocketResponseEventDTO(event)
3162
+ && event?.event === WebSocketResponseEvent.CLIENT_TRACK;
3137
3163
  };
3138
- const PROBLEM_MODES = [ProblemScoringMode.TOTAL, ProblemScoringMode.SUBTASK, ProblemScoringMode.PARTIAL];
3139
- const PROBLEM_MODE = {
3140
- [ProblemScoringMode.TOTAL]: {
3141
- value: ProblemScoringMode.TOTAL,
3142
- label: 'total',
3143
- description: 'if all test cases are Accepted the result is Accepted '
3144
- + 'otherwise it will be Runtime Error, Time Limited Exceeded, Memory Limited Exceeded, Wrong Answer or Presentation Error in that order.',
3145
- },
3146
- [ProblemScoringMode.SUBTASK]: {
3147
- value: ProblemScoringMode.SUBTASK,
3148
- label: 'subtask',
3149
- description: 'the test cases are grouped and each group of test cases is assigned a score, '
3150
- + 'if all test cases in a group are Accepted then the score assigned to that group of test cases is added to total score, '
3151
- + 'if total score is equal to the sum of the assigned scores of all groups of test cases then the result is Accepted, '
3152
- + 'otherwise if the total score is greater than zero the result is Partial Accepted with the total accumulated score, '
3153
- + 'otherwise it will be Runtime Error, Time Limited Exceeded, Memory Limited Exceeded, Wrong Answer or Presentation Error in that order.',
3154
- },
3155
- [ProblemScoringMode.PARTIAL]: {
3156
- value: ProblemScoringMode.PARTIAL,
3157
- label: 'partial',
3158
- description: 'the test cases are grouped and each group is associated with X points, '
3159
- + 'and each test case in a group scores X points ',
3160
- },
3164
+ const isUserNotificationWebSocketResponseEventDTO = (event) => {
3165
+ return [
3166
+ WebSocketResponseEvent.USER_NOTIFICATION_SUBMISSION,
3167
+ WebSocketResponseEvent.USER_NOTIFICATION_CONTEST_CLARIFICATION,
3168
+ ].includes(event?.event)
3169
+ && !!event?.content;
3161
3170
  };
3162
- const PROBLEM_TYPES = [ProblemType.STANDARD, ProblemType.DYNAMIC, ProblemType.INTERACTIVE];
3163
- const PROBLEM_TYPE = {
3164
- [ProblemType.STANDARD]: {
3165
- value: ProblemType.STANDARD,
3166
- label: 'standard',
3167
- description: 'The contestant submit a single source code in one of the allowed programming languages. '
3168
- + 'The source code is either standalone or to be compiled. '
3169
- + 'The resulting user\'s executable does I/O standard input and output. '
3170
- + 'The output produced by the contestant\'s program is then compared to the correct output using a simple diff algorithm.',
3171
- },
3172
- [ProblemType.INTERACTIVE]: {
3173
- value: ProblemType.INTERACTIVE, label: 'interactive', description: 'developing..',
3174
- },
3175
- [ProblemType.DYNAMIC]: {
3176
- value: ProblemType.DYNAMIC,
3177
- label: 'dynamic',
3178
- description: 'The contestant submit a single source code in one of the allowed programming languages. '
3179
- + 'The user\'s source code is either standalone or to be compiled. '
3180
- + 'The resulting user\'s executable does I/O standard input and output. '
3181
- + 'The output produced by the contestant\'s program is saved. '
3182
- + 'The problem editor save a single source code in C++ 17. '
3183
- + 'The editor\'s source code can read judge input filepath argv[1], judge output filepath argv[2], user\'s output filepath argv[3], user\'s error filepath argv[4], user\'s log filepath argv[5], user\'s source filepath argv[6] and submission information filepath argv[7] (companyId, submitId, runId, userId, contestId, problemId, language, userNickname, timestamp). '
3184
- + 'The resulting editor\'s executable should be "AC" or a number between 1 and 100 for partial accepted',
3185
- },
3171
+ const isUserNotificationSubmissionWebSocketResponseEventDTO = (event) => {
3172
+ return isWebSocketResponseEventDTO(event) && isUserNotificationWebSocketResponseEventDTO(event)
3173
+ && event?.event === WebSocketResponseEvent.USER_NOTIFICATION_SUBMISSION;
3186
3174
  };
3187
- const PROBLEM_ROLE = {
3188
- [Role.RESTRICTED]: { value: Role.RESTRICTED, label: 'restricted', level: 7 },
3189
- [Role.GUEST]: { value: Role.GUEST, label: 'guest', level: 6 },
3190
- [Role.REGULAR]: { value: Role.REGULAR, label: 'regular', level: 5 },
3191
- [Role.CREATOR]: { value: Role.CREATOR, label: 'creator', level: 4 },
3192
- [Role.MANAGER]: { value: Role.MANAGER, label: 'manager', level: 3 },
3193
- [Role.MASTER]: { value: Role.MASTER, label: 'master', level: 2 },
3194
- [Role.ADMIN]: { value: Role.ADMIN, label: 'admin', level: 1 },
3195
- [Role.SUPER_ADMIN]: { value: Role.SUPER_ADMIN, label: 'super admin', level: 0 },
3175
+ const isUserNotificationContestClarificationWebSocketResponseEventDTO = (event) => {
3176
+ return isWebSocketResponseEventDTO(event) && isUserNotificationWebSocketResponseEventDTO(event)
3177
+ && event?.event === WebSocketResponseEvent.USER_NOTIFICATION_CONTEST_CLARIFICATION;
3178
+ };
3179
+ // generic
3180
+ const getWebSocketResponseEventKey = (event, clientId, id) => {
3181
+ return `${event}-${clientId}-${id}`;
3182
+ };
3183
+ const isWebSocketChannelsMessageDTO = (message) => {
3184
+ return Array.isArray(message?.channels)
3185
+ && message.channels.every((channel) => typeof channel === 'string' && !!channel)
3186
+ && Object.values(WebSocketResponseEvent).includes(message?.event?.event);
3187
+ };
3188
+ /**
3189
+ * Key used by the client to dispatch a response received on a TOPIC channel to its subscribers.
3190
+ * It is the same key that `getKeyWebSocketEventDTO` (base-ui) computes for the subscription.
3191
+ * Returns null when the response is not addressed to this client.
3192
+ */
3193
+ const getWebSocketResponseEventKeyOfResponse = (response, clientId) => {
3194
+ if (isCodeRunStatusMessageWebSocketResponseEventDTO(response)) {
3195
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.CODE_RUN_STATUS, clientId, response.runId);
3196
+ }
3197
+ if (isSubmissionRunStatusMessageWebSocketResponseEventDTO(response)) {
3198
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.SUBMISSION_RUN_STATUS, clientId, response.submitId);
3199
+ }
3200
+ if (isSendDataWebSocketResponseEventDTO(response)) {
3201
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.SEND_DATA_, clientId, response.dataId);
3202
+ }
3203
+ if (isContestChangesWebSocketResponseEventDTO(response)) {
3204
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.CONTEST_CHANGES, clientId, response.content.contestKey);
3205
+ }
3206
+ if (isProblemCrawledWebSocketResponseEventDTO(response)) {
3207
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.PROBLEM_CRAWLED, clientId, response.content.problemKey);
3208
+ }
3209
+ if (isSubmissionsCrawlWebSocketResponseEventDTO(response)) {
3210
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.SUBMISSIONS_CRAWL, clientId, join([response.content.contestKey, response.content.problemKeys]));
3211
+ }
3212
+ if (isClientTrackWebSocketResponseEventDTO(response)) {
3213
+ // the command is sent to the session channel, `key` holds the targeted client
3214
+ return response.key === clientId ? getWebSocketResponseEventKey(WebSocketResponseEvent.CLIENT_TRACK, clientId, '*') : null;
3215
+ }
3216
+ if (isUserNotificationWebSocketResponseEventDTO(response)) {
3217
+ return getWebSocketResponseEventKey(WebSocketResponseEvent.USER_NOTIFICATION_, clientId, '*');
3218
+ }
3219
+ return null;
3220
+ };
3221
+ /**
3222
+ * TOPIC channel that the client has to attach to receive the events of a subscription,
3223
+ * or null when the events arrive by the private channels (session / user) the client is always attached to.
3224
+ * Ably rejects the attach if the token has no capability for the channel.
3225
+ */
3226
+ const getChannelOfWebSocketSubscribeEvent = (event) => {
3227
+ if (isSubscribeSubmissionRunStatusWebSocketEventDTO(event)) {
3228
+ return CHANNEL_SUBMISSION(event.submitId);
3229
+ }
3230
+ if (isSubscribeProblemCrawledWebSocketEventDTO(event)) {
3231
+ return CHANNEL_PROBLEM(event.problemKey);
3232
+ }
3233
+ if (isSubscribeContestChangesWebSocketEventDTO(event) || isSubscribeSubmissionsCrawlWebSocketEventDTO(event)) {
3234
+ return CHANNEL_CONTEST(event.contestKey, ContestChannelRole.SPECTATORS);
3235
+ }
3236
+ if (isSubscribeClientTrackDataWebSocketEventDTO(event)) {
3237
+ return CHANNEL_CLIENT_TRACK(event.trackedClientId);
3238
+ }
3239
+ return null;
3240
+ };
3241
+ /**
3242
+ * Contest whose role channels the client needs (the API grants them when the token is requested with this contest).
3243
+ */
3244
+ const getContestKeyOfWebSocketSubscribeEvent = (event) => {
3245
+ if (isSubscribeContestChangesWebSocketEventDTO(event) || isSubscribeSubmissionsCrawlWebSocketEventDTO(event)) {
3246
+ return event.contestKey;
3247
+ }
3248
+ return null;
3249
+ };
3250
+
3251
+ function splitTime(timeRemaining) {
3252
+ const remaining = [];
3253
+ // const aYearMilliseconds = 1000 * 60 * 60 * 24 * 365;
3254
+ // const remainingYears = Math.floor(timeRemaining / aYearMilliseconds);
3255
+ // remaining.push({ remaining: remainingYears, label: 'years', milliseconds: aYearMilliseconds });
3256
+ // const aWeekMilliseconds = 1000 * 60 * 60 * 24 * 7;
3257
+ // const remainingWeeks = Math.floor((timeRemaining % aYearMilliseconds) / aWeekMilliseconds);
3258
+ // remaining.push({ remaining: remainingWeeks, label: 'weeks', milliseconds: aWeekMilliseconds });
3259
+ const aSecondMilliseconds = 1000;
3260
+ const aMinuteMilliseconds = aSecondMilliseconds * 60;
3261
+ const aHourMilliseconds = aMinuteMilliseconds * 60;
3262
+ const aDayMilliseconds = aHourMilliseconds * 24;
3263
+ const aWeekMilliseconds = aDayMilliseconds * 7;
3264
+ const remainingWeeks = Math.floor(timeRemaining / aWeekMilliseconds);
3265
+ remaining.push({
3266
+ remaining: remainingWeeks,
3267
+ label: remainingWeeks === 1 ? 'week' : 'weeks',
3268
+ abbreviatedLabel: 'w',
3269
+ milliseconds: aWeekMilliseconds,
3270
+ digits: 2,
3271
+ });
3272
+ const remainingDays = Math.floor((timeRemaining % aWeekMilliseconds) / aDayMilliseconds);
3273
+ remaining.push({
3274
+ remaining: remainingDays,
3275
+ label: remainingDays === 1 ? 'day' : 'days',
3276
+ abbreviatedLabel: 'd',
3277
+ milliseconds: aDayMilliseconds,
3278
+ digits: 2,
3279
+ });
3280
+ const remainingHours = Math.floor((timeRemaining % aDayMilliseconds) / aHourMilliseconds);
3281
+ remaining.push({
3282
+ remaining: remainingHours,
3283
+ label: remainingHours === 1 ? 'hour' : 'hours',
3284
+ abbreviatedLabel: 'h',
3285
+ milliseconds: aHourMilliseconds,
3286
+ digits: 2,
3287
+ });
3288
+ const remainingMinutes = Math.floor((timeRemaining % aHourMilliseconds) / aMinuteMilliseconds);
3289
+ remaining.push({
3290
+ remaining: remainingMinutes,
3291
+ label: remainingMinutes === 1 ? 'minute' : 'minutes',
3292
+ abbreviatedLabel: 'm',
3293
+ milliseconds: aMinuteMilliseconds,
3294
+ digits: 2,
3295
+ });
3296
+ const remainingSeconds = Math.floor((timeRemaining % aMinuteMilliseconds) / aSecondMilliseconds);
3297
+ remaining.push({
3298
+ remaining: remainingSeconds,
3299
+ label: remainingSeconds === 1 ? 'second' : 'seconds',
3300
+ abbreviatedLabel: 's',
3301
+ milliseconds: aSecondMilliseconds,
3302
+ digits: 2,
3303
+ });
3304
+ const remainingMilliseconds = Math.floor(timeRemaining % aSecondMilliseconds);
3305
+ remaining.push({
3306
+ remaining: remainingMilliseconds,
3307
+ label: remainingMilliseconds === 1 ? 'millisecond' : 'milliseconds',
3308
+ abbreviatedLabel: 'ms',
3309
+ milliseconds: 1,
3310
+ digits: 3,
3311
+ });
3312
+ // while (remaining[0].remaining <= 0) {
3313
+ // remaining.shift();
3314
+ // if (remaining.length === 3) {
3315
+ // break;
3316
+ // }
3317
+ // }
3318
+ return remaining;
3319
+ }
3320
+ function normalizeToLocalStartOfDay(timestamp) {
3321
+ const date = new Date(timestamp);
3322
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
3323
+ }
3324
+ function normalizeToLocalStartOfHour(timestamp) {
3325
+ const date = new Date(timestamp);
3326
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours());
3327
+ }
3328
+ function normalizeToLocalStartOfMinutes(timestamp) {
3329
+ const date = new Date(timestamp);
3330
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes());
3331
+ }
3332
+ function normalizeToLocalStartOfSeconds(timestamp) {
3333
+ const date = new Date(timestamp);
3334
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes());
3335
+ }
3336
+ const getYears = (d) => d.getFullYear();
3337
+ const getMonths = (d) => d.getFullYear() * 12 + d.getMonth();
3338
+ const getDays = (d) => {
3339
+ return Math.floor(normalizeToLocalStartOfDay(d).getTime() / ONE_DAY);
3196
3340
  };
3341
+ const getHours = (d) => {
3342
+ return Math.floor(normalizeToLocalStartOfHour(d).getTime() / ONE_HOUR);
3343
+ };
3344
+ const getMinutes = (d) => {
3345
+ return Math.floor(normalizeToLocalStartOfMinutes(d).getTime() / ONE_MINUTE);
3346
+ };
3347
+ const getSeconds = (d) => {
3348
+ return Math.floor(normalizeToLocalStartOfSeconds(d).getTime() / 1000);
3349
+ };
3350
+ const getMilliseconds = (d) => d.getTime();
3197
3351
 
3198
- const _TYPE = ':type';
3199
- const _KEY = ':key';
3200
- const _TAB = ':tab';
3201
- const _SUB_TAB = ':subTab?';
3202
- const _SUB_SUB_TAB = ':subSubTab?';
3203
- const PAGE = 'page';
3204
- const PAGE_SIZE = 'size';
3205
-
3206
- const FILE_TYPE = {
3207
- [FileType.FILE]: { value: FileType.FILE, label: 'file' },
3208
- [FileType.FOLDER]: { value: FileType.FOLDER, label: 'folder' },
3352
+ const getUserKey = (userNickname, userCompanyKey) => {
3353
+ return userNickname + '|' + userCompanyKey;
3209
3354
  };
3210
- const FILE_ROLE = {
3211
- [Role.RESTRICTED]: { value: Role.RESTRICTED, label: 'restricted', level: 5 },
3212
- [Role.GUEST]: { value: Role.GUEST, label: 'guest', level: 4 },
3213
- [Role.REGULAR]: { value: Role.REGULAR, label: 'regular', level: 3 },
3214
- [Role.MASTER]: { value: Role.MASTER, label: 'master', level: 2 },
3215
- [Role.ADMIN]: { value: Role.ADMIN, label: 'admin', level: 1 },
3216
- [Role.SUPER_ADMIN]: { value: Role.SUPER_ADMIN, label: 'super admin', level: 0 },
3355
+ const getParamsOfUserKey = (userKey) => {
3356
+ const [userNickname, userCompanyKey] = userKey.split('|');
3357
+ return { userNickname, userCompanyKey };
3217
3358
  };
3218
- const ENTITY_STATE = {
3219
- [EntityState.RELEASED]: {
3220
- value: EntityState.RELEASED,
3221
- label: 'released',
3222
- },
3223
- [EntityState.ARCHIVED]: {
3224
- value: EntityState.ARCHIVED,
3225
- label: 'archived',
3226
- },
3359
+ const getClientId = (sessionId, uiId) => {
3360
+ return `${sessionId}|${uiId}`;
3227
3361
  };
3228
- const ENTITY_ACCESS = {
3229
- [EntityAccess.PRIVATE]: {
3230
- value: EntityAccess.PRIVATE,
3231
- label: 'private',
3232
- description: 'the record will be visible and editable only to the owner',
3233
- },
3234
- [EntityAccess.RESTRICTED]: {
3235
- value: EntityAccess.RESTRICTED,
3236
- label: 'restricted',
3237
- description: 'the record will be visible to viewers and the owner and editable to editors and the owner',
3238
- },
3239
- [EntityAccess.PUBLIC]: {
3240
- value: EntityAccess.PUBLIC,
3241
- label: 'public',
3242
- description: 'the record will be visible to anyone and editable to editors and the owner',
3243
- },
3244
- [EntityAccess.EXPOSED]: {
3245
- value: EntityAccess.EXPOSED,
3246
- label: 'exposed',
3247
- description: 'the record will be visible and editable to anyone',
3248
- },
3362
+ const getParamsOfClientId = (clientId) => {
3363
+ const [sessionId, uiId] = clientId.split('|');
3364
+ return { sessionId, uiId };
3249
3365
  };
3250
3366
 
3251
- const SYSTEM_ROLE = {
3252
- [SystemRole.GUEST]: { value: SystemRole.GUEST, label: 'guest', level: 5 },
3253
- [SystemRole.REGULAR]: { value: SystemRole.REGULAR, label: 'regular', level: 4 },
3254
- [SystemRole.MANAGER]: { value: SystemRole.MANAGER, label: 'manager', level: 3 },
3255
- [SystemRole.MASTER]: { value: SystemRole.MASTER, label: 'master', level: 2 },
3256
- [SystemRole.ADMIN]: { value: SystemRole.ADMIN, label: 'admin', level: 1 },
3257
- [SystemRole.SUPER_ADMIN]: { value: SystemRole.SUPER_ADMIN, label: 'super admin', level: 0 },
3367
+ const getWorksheetsInPages = (initialSheets) => {
3368
+ const sheets = [...initialSheets];
3369
+ if (sheets[0]?.type !== WorksheetType.NEW_PAGE) {
3370
+ sheets.unshift(NEW_PAGE_SHEET());
3371
+ }
3372
+ let newPage = sheets[0];
3373
+ let content = [];
3374
+ const sheetsByPages = [];
3375
+ for (let i = 1; i < sheets.length; i++) {
3376
+ const sheet = sheets[i];
3377
+ if (sheet.type === WorksheetType.NEW_PAGE) {
3378
+ sheetsByPages.push({
3379
+ header: newPage,
3380
+ content: [...content],
3381
+ });
3382
+ newPage = sheet;
3383
+ content = [];
3384
+ }
3385
+ else {
3386
+ content.push(sheet);
3387
+ }
3388
+ }
3389
+ sheetsByPages.push({
3390
+ header: newPage,
3391
+ content: [...content],
3392
+ });
3393
+ return sheetsByPages;
3258
3394
  };
3259
-
3260
- const MEMBER_ROLE = {
3261
- [MemberRole.COACH]: { value: MemberRole.COACH, label: 'coach' },
3262
- [MemberRole.CO_COACH]: { value: MemberRole.CO_COACH, label: 'co-coach' },
3263
- [MemberRole.STAFF]: { value: MemberRole.STAFF, label: 'staff' },
3264
- [MemberRole.ATTENDEE]: { value: MemberRole.ATTENDEE, label: 'attendee' },
3265
- [MemberRole.RESERVE]: { value: MemberRole.RESERVE, label: 'reserve' },
3266
- [MemberRole.CONTESTANT]: { value: MemberRole.CONTESTANT, label: 'contestant' },
3395
+ const getSummaryWorksheetsInPages = (initialSheets) => {
3396
+ const sheets = [...initialSheets];
3397
+ if (sheets[0]?.type !== WorksheetType.NEW_PAGE) {
3398
+ sheets.unshift(NEW_PAGE_SHEET());
3399
+ }
3400
+ let newPage = sheets[0];
3401
+ let content = [];
3402
+ const sheetsByPages = [];
3403
+ for (let i = 1; i < sheets.length; i++) {
3404
+ const sheet = sheets[i];
3405
+ if (sheet.type === WorksheetType.NEW_PAGE) {
3406
+ sheetsByPages.push({
3407
+ header: newPage,
3408
+ content: content.map(c => ({
3409
+ id: c.id,
3410
+ type: c.type,
3411
+ title: c.title,
3412
+ points: c.points,
3413
+ })),
3414
+ });
3415
+ newPage = sheet;
3416
+ content = [];
3417
+ }
3418
+ else {
3419
+ content.push(sheet);
3420
+ }
3421
+ }
3422
+ sheetsByPages.push({
3423
+ header: newPage,
3424
+ content: [...content],
3425
+ });
3426
+ return sheetsByPages;
3267
3427
  };
3268
- const TEAM_ROLE = {
3269
- [TeamRole.RESTRICTED]: { value: TeamRole.RESTRICTED, label: 'restricted', level: 5 },
3270
- [TeamRole.GUEST]: { value: TeamRole.GUEST, label: 'guest', level: 4 },
3271
- [TeamRole.REGULAR]: { value: TeamRole.REGULAR, label: 'regular', level: 3 },
3272
- [TeamRole.MANAGER]: { value: TeamRole.MANAGER, label: 'manager', level: 2 },
3273
- [TeamRole.ADMIN]: { value: TeamRole.ADMIN, label: 'admin', level: 1 },
3274
- [TeamRole.SUPER_ADMIN]: { value: TeamRole.SUPER_ADMIN, label: 'super admin', level: 0 },
3428
+ const getTotalExercisesOfSummaryWorksheetsInPages = (content) => content.reduce((sum, { content }) => sum + content.reduce((sum, { type }) => sum + +(type === WorksheetType.QUIZ_OPTIONS || type === WorksheetType.QUIZ_PROBLEM || type === WorksheetType.QUIZ_TEXT), 0), 0);
3429
+ const isBasicWorksheet = (value) => {
3430
+ return typeof value?.id == 'string' && value.id
3431
+ && Object.values(WorksheetType).includes(value?.type)
3432
+ && typeof value?.title == 'string'
3433
+ && typeof value?.points == 'number';
3275
3434
  };
3276
-
3277
- const ONE_SECOND = 1000;
3278
- const SEC_30 = ONE_SECOND * 30;
3279
- const SEC_60 = ONE_SECOND * 60;
3280
- const SEC_90 = ONE_SECOND * 90;
3281
- const SEC_120 = ONE_SECOND * 120;
3282
- const ONE_MINUTE = ONE_SECOND * 60;
3283
- const ONE_HOUR = ONE_MINUTE * 60;
3284
- const ONE_DAY = ONE_HOUR * 24;
3285
- const ONE_WEEK = ONE_DAY * 7;
3286
-
3287
- const USER_STATUS = {
3288
- [UserStatus.ACTIVE]: { value: UserStatus.ACTIVE, label: 'active' },
3289
- [UserStatus.REPORTED]: { value: UserStatus.REPORTED, label: 'reported' },
3290
- [UserStatus.ARCHIVED]: { value: UserStatus.ARCHIVED, label: 'archived' },
3435
+ const isJkmdSheet = (value) => {
3436
+ return isBasicWorksheet(value)
3437
+ && value?.type === WorksheetType.JK_MD
3438
+ && typeof value?.content == 'string';
3291
3439
  };
3292
- const USER_ROLE = {
3293
- [UserRole.RESTRICTED]: { value: UserRole.RESTRICTED, label: 'restricted', level: 6 },
3294
- [UserRole.GUEST]: { value: UserRole.GUEST, label: 'guest', level: 5 },
3295
- [UserRole.LIMITED]: { value: UserRole.LIMITED, label: 'limited', level: 4 },
3296
- [UserRole.REGULAR]: { value: UserRole.REGULAR, label: 'regular', level: 3 },
3297
- [UserRole.MANAGER]: { value: UserRole.MANAGER, label: 'manager', level: 2 },
3298
- [UserRole.ADMIN]: { value: UserRole.ADMIN, label: 'admin', level: 1 },
3299
- [UserRole.SUPER_ADMIN]: { value: UserRole.SUPER_ADMIN, label: 'super admin', level: 0 },
3440
+ const isCodeEditorSheet = (value) => {
3441
+ return isBasicWorksheet(value)
3442
+ && value?.type === WorksheetType.CODE_EDITOR
3443
+ && typeof value?.sourceCode === 'object' && value?.sourceCode !== null
3444
+ && value?.testCases === 'object' && value?.testCases !== null
3445
+ && Array.isArray(value?.languages)
3446
+ && typeof value?.height == 'number';
3300
3447
  };
3301
- const EMPTY_USER_PERMISSIONS = {
3302
- users: {
3303
- create: false,
3304
- manage: false,
3305
- administrate: false,
3306
- },
3307
- problems: {
3308
- create: false,
3309
- manage: false,
3310
- },
3311
- submissions: {
3312
- manage: false,
3313
- },
3314
- contests: {
3315
- create: false,
3316
- manage: false,
3317
- },
3318
- company: {
3319
- manage: false,
3320
- administrate: false,
3321
- },
3322
- services: {
3323
- administrate: false,
3324
- },
3448
+ const isQuizProblemSheet = (value) => {
3449
+ return isBasicWorksheet(value)
3450
+ && value?.type === WorksheetType.QUIZ_PROBLEM
3451
+ && Object.values(Judge).includes(value?.problemJudge) || typeof value?.problemJudge === 'string'
3452
+ && typeof value?.problemKey == 'string'
3453
+ && Array.isArray(value?.languages)
3454
+ && typeof value?.height == 'number';
3455
+ };
3456
+ const isQuizOptionsSheet = (value) => {
3457
+ return isBasicWorksheet(value)
3458
+ && value?.type === WorksheetType.QUIZ_OPTIONS
3459
+ && typeof value?.description == 'string'
3460
+ && Array.isArray(value?.options)
3461
+ && value?.options.every((option) => typeof option?.label == 'string' && typeof option?.correct == 'boolean' && typeof option?.id == 'string')
3462
+ && typeof value?.multiple == 'boolean'
3463
+ && (value?.scoringMode === 'TOTAL' || value?.scoringMode === 'PARTIAL');
3464
+ };
3465
+ const isQuizTextSheet = (value) => {
3466
+ return isBasicWorksheet(value)
3467
+ && value?.type === WorksheetType.QUIZ_TEXT
3468
+ && typeof value?.description == 'string'
3469
+ && typeof value?.answer == 'string'
3470
+ && ['text', 'number', 'textarea'].includes(value?.inputType);
3325
3471
  };
3326
3472
 
3327
- const CHANNEL_PUBLISH_SUBSCRIPTIONS = 'pub:subscriptions';
3328
- const CHANNEL_SUBSCRIBE_NOTIFICATIONS = 'sub:notifications';
3329
- const CHANNEL_SUBSCRIBE_CLIENT = (clientId) => `sub:client:${clientId}`;
3330
- const CHANNEL_PUBLISH_MESSAGES = 'pub:messages';
3331
- const CHANNEL_PRESENCE_CLIENT = 'pre:client';
3332
-
3333
- var ContestProblemBlockedByType;
3334
- (function (ContestProblemBlockedByType) {
3335
- ContestProblemBlockedByType["UNMET_PREREQUISITES"] = "UNMET_PREREQUISITES";
3336
- ContestProblemBlockedByType["MAX_ACCEPTED_SUBMISSIONS_ACHIEVED"] = "MAX_ACCEPTED_SUBMISSIONS_ACHIEVED";
3337
- ContestProblemBlockedByType["START_TIME_IN_THE_FUTURE"] = "START_TIME_IN_THE_FUTURE";
3338
- ContestProblemBlockedByType["END_TIME_IN_THE_PAST"] = "END_TIME_IN_THE_PAST";
3339
- })(ContestProblemBlockedByType || (ContestProblemBlockedByType = {}));
3340
-
3341
- var MemberType;
3342
- (function (MemberType) {
3343
- MemberType["USER"] = "USER";
3344
- MemberType["TEAM"] = "TEAM";
3345
- })(MemberType || (MemberType = {}));
3346
-
3347
- export { ACCEPTED_PROGRAMMING_LANGUAGES, ASPECT_RATIO, AspectRatio, AssignmentClass, AssignmentState, AssignmentType, CHANNEL_PRESENCE_CLIENT, CHANNEL_PUBLISH_MESSAGES, CHANNEL_PUBLISH_SUBSCRIPTIONS, CHANNEL_SUBSCRIBE_CLIENT, CHANNEL_SUBSCRIBE_NOTIFICATIONS, CODE_LANGUAGE, COMPANY_PLAN, CONTEST_ROLE, CONTEST_STATUS, COOKIE_JUKI_SESSION_ID, COURSE_ROLE, CodeLanguage, CollectionKey, CompanyLogoType, CompanyPlan, ContestEventAction, ContestProblemBlockedByType, ContestProblemPrerequisiteType, ContestStatus, ContestTimeStatus, CourseRole, CourseStatus, CourseType, DAY_NAMES, DEFAULT_JUKI_PROFILE_IMAGE, DataViewMode, EMPTY_DOCUMENT_MEMBERS, EMPTY_ENTITY_MEMBERS, EMPTY_USER_PERMISSIONS, ENTITY_ACCESS, ENTITY_STATE, ERROR, EmailSubscription, EmailValidationState, EntityAccess, EntityCollection, EntityMembersRank, EntityState, EntityStatus, ErrorCode, FILE_ROLE, FILE_TYPE, FileMemberRole, FileType, FilesJukiPub, GroupType, HEADER_JUKI_FORWARDED_HOST, HEADER_JUKI_INTERNAL_API_KEY, HEADER_JUKI_METADATA, HEADER_JUKI_SECRET_TOKEN, HEADER_JUKI_VISITOR_SESSION_ID, HOURS, HTTPMethod, JUDGE, JUKI_APP_COMPANY_KEY, JUKI_APP_EMAIL_TEMPLATE, JkError, Judge, LANGUAGE, LOWERCASE_LETTERS, Language, LogLevel, LogOperation, MAX_DATE, MEMBER_ROLE, MILLISECONDS, MINUTES, MIN_DATE, MONTH_NAMES, MemberRole, MemberType, MenuViewMode, NEW_PAGE_SHEET, NUMBERS, NotificationType, ONE_DAY, ONE_HOUR, ONE_MINUTE, ONE_SECOND, ONE_WEEK, PAGE, PAGE_SIZE, PAGE_SIZES, PALLETE, PROBLEM_INPUT, PROBLEM_MODE, PROBLEM_MODES, PROBLEM_OUTPUT, PROBLEM_ROLE, PROBLEM_TYPE, PROBLEM_TYPES, PROBLEM_VERDICT, PROBLEM_VERDICTS, ProblemInput, ProblemOutput, ProblemScoringMode, ProblemType, ProblemVerdict, ProfileSetting, QuizScoringMode, RUNNER_ACCEPTED_PROBLEM_MODES, RUNNER_ACCEPTED_PROBLEM_TYPES, RUNNER_ACCEPTED_PROGRAMMING_LANGUAGES, RUNNER_TYPE, Role, RunnerType, SECONDS, SEC_120, SEC_30, SEC_60, SEC_90, SEPARATOR_TOKEN, SUBMISSION_RUN_STATUS, SUPPORT_EMAIL, SYSTEM_ROLE, ScopeData, Status, SubmissionRunStatus, SystemRole, TEAM_ROLE, THEME, TeamRole, TeamStatus, Theme, TypeTestCase, UPPERCASE_LETTERS, USER_ROLE, USER_STATUS, UserRole, UserStatus, UserTeamStatus, WebSocketMessageEvent, WebSocketResponseEvent, WebSocketSubscriptionEvent, WorkingIn, WorksheetType, YEARS, _KEY, _SUB_SUB_TAB, _SUB_TAB, _TAB, _TYPE, areArraysDifferent, chunkString, cleanRequest, clearAsyncInterval, consoleError, consoleInfo, consoleWarn, contentResponse, contentsResponse, errorsResponse, getAssignmentCommentKey, getAssignmentUserCommentKey, getClientId, getContestCommentKey, getDataLog, getDataOfTestCase, getDays, getDefaultMeta, getDocumentAccess, getHours, getMilliseconds, getMinutes, getMonths, getParamsOfClientId, getParamsOfUserKey, getPlainText, getProblemCommentKey, getProblemJudgeKey, getRandomString, getSeconds, getSummaryWorksheetsInPages, getTotalExercisesOfSummaryWorksheetsInPages, getUserKey, getVerdictFromTestCase, getWebSocketResponseEventKey, getWorksheetsInPages, getYears, humanFileSize, indexToLetters, isBasicWorksheet, isChatCompletionsWebSocketEventDTO, isClientTrackDeviceWebSocketEventDTO, isClientTrackLocationWebSocketEventDTO, isClientTrackScreenshotWebSocketEventDTO, isClientTrackWebSocketResponseEventDTO, isCodeEditorSheet, isCodeRunStatusMessageWebSocketResponseEventDTO, isContestAssignment, isContestChangesWebSocketResponseEventDTO, isCourseAssignment, isEndlessContest, isFutureContest, isGlobalContest, isJkmdSheet, isObjectJson, isPastContest, isPingWebSocketEventDTO, isPongWebSocketResponseEventDTO, isProblemCrawledWebSocketResponseEventDTO, isQuizOptionsSheet, isQuizProblemSheet, isQuizTextSheet, isSenDataChatCompletionsWebSocketResponseEventDTO, isSendDataClientTrackWebSocketResponseEventDTO, isSendDataEc2InstancesListWebSocketResponseEventDTO, isSendDataEcsTaskDefinitionListWebSocketResponseEventDTO, isSendDataEcsTasksListWebSocketResponseEventDTO, isSendDataRunCommandWebSocketResponseEventDTO, isSendDataSsmSessionsListWebSocketResponseEventDTO, isSendDataWebSocketResponseEventDTO, isStringJson, isSubmissionRunStatusMessageWebSocketResponseEventDTO, isSubmissionsCrawlWebSocketResponseEventDTO, isSubscribeClientTrackWebSocketEventDTO, isSubscribeCodeRunStatusWebSocketEventDTO, isSubscribeContestChangesWebSocketEventDTO, isSubscribeGetDataWebSocketEventDTO, isSubscribeProblemCrawledWebSocketEventDTO, isSubscribeSubmissionRunStatusWebSocketEventDTO, isSubscribeSubmissionsCrawlWebSocketEventDTO, isSubscribeUserNotificationWebSocketEventDTO, isTeamMember, isUnsubscribeClientTrackWebSocketEventDTO, isUnsubscribeCodeRunStatusWebSocketEventDTO, isUnsubscribeContestChangesWebSocketEventDTO, isUnsubscribeGetDataWebSocketEventDTO, isUnsubscribeProblemCrawledWebSocketEventDTO, isUnsubscribeSubmissionRunStatusWebSocketEventDTO, isUnsubscribeSubmissionsCrawlWebSocketEventDTO, isUnsubscribeUserNotificationWebSocketEventDTO, isUserMember, isUserMessageWebSocketResponseEventDTO, isUserNotificationContestClarificationWebSocketResponseEventDTO, isUserNotificationSubmissionWebSocketResponseEventDTO, isUserNotificationWebSocketResponseEventDTO, isWebSocketResponseEventDTO, isWebsocketSubscription, isWorksheetAssignment, join, lettersToIndex, memorySizeOf, mergeVerdicts, mex, normalizeToLocalStartOfDay, normalizeToLocalStartOfHour, normalizeToLocalStartOfMinutes, normalizeToLocalStartOfSeconds, objectUpdate, objectsUpdate, range, removeExtension, safeJsonParse, setAsyncInterval, split, splitTime, stringToArrayBuffer, toEntityMembersDTO, toJkError };
3473
+ export { ACCEPTED_PROGRAMMING_LANGUAGES, ASPECT_RATIO, AspectRatio, AssignmentClass, AssignmentState, AssignmentType, CHANNEL_CLIENT_TRACK, CHANNEL_CLIENT_TRACK_ALL, CHANNEL_CONTEST, CHANNEL_PRESENCE_CLIENT, CHANNEL_PROBLEM, CHANNEL_PROBLEM_ALL, CHANNEL_PUBLISH_MESSAGES, CHANNEL_PUBLISH_SUBSCRIPTIONS, CHANNEL_SESSION, CHANNEL_SUBMISSION, CHANNEL_SUBMISSION_ALL, CHANNEL_SUBSCRIBE_CLIENT, CHANNEL_SUBSCRIBE_NOTIFICATIONS, CHANNEL_USER, CODE_LANGUAGE, COMPANY_PLAN, CONTEST_ROLE, CONTEST_STATUS, COOKIE_JUKI_SESSION_ID, COURSE_ROLE, CodeLanguage, CollectionKey, CompanyLogoType, CompanyPlan, ContestChannelRole, ContestEventAction, ContestProblemBlockedByType, ContestProblemPrerequisiteType, ContestStatus, ContestTimeStatus, CourseRole, CourseStatus, CourseType, DAY_NAMES, DEFAULT_JUKI_PROFILE_IMAGE, DataViewMode, EMPTY_DOCUMENT_MEMBERS, EMPTY_ENTITY_MEMBERS, EMPTY_USER_PERMISSIONS, ENTITY_ACCESS, ENTITY_STATE, ERROR, EmailSubscription, EmailValidationState, EntityAccess, EntityCollection, EntityMembersRank, EntityState, EntityStatus, ErrorCode, FILE_ROLE, FILE_TYPE, FileMemberRole, FileType, FilesJukiPub, GroupType, HEADER_JUKI_FORWARDED_HOST, HEADER_JUKI_INTERNAL_API_KEY, HEADER_JUKI_METADATA, HEADER_JUKI_SECRET_TOKEN, HEADER_JUKI_VISITOR_SESSION_ID, HOURS, HTTPMethod, JUDGE, JUKI_APP_COMPANY_KEY, JUKI_APP_EMAIL_TEMPLATE, JkError, Judge, LANGUAGE, LOWERCASE_LETTERS, Language, LogLevel, LogOperation, MAX_DATE, MEMBER_ROLE, MILLISECONDS, MINUTES, MIN_DATE, MONTH_NAMES, MemberRole, MemberType, MenuViewMode, NEW_PAGE_SHEET, NUMBERS, NotificationType, ONE_DAY, ONE_HOUR, ONE_MINUTE, ONE_SECOND, ONE_WEEK, PAGE, PAGE_SIZE, PAGE_SIZES, PALLETE, PROBLEM_INPUT, PROBLEM_MODE, PROBLEM_MODES, PROBLEM_OUTPUT, PROBLEM_ROLE, PROBLEM_TYPE, PROBLEM_TYPES, PROBLEM_VERDICT, PROBLEM_VERDICTS, ProblemInput, ProblemOutput, ProblemScoringMode, ProblemType, ProblemVerdict, ProfileSetting, QuizScoringMode, RUNNER_ACCEPTED_PROBLEM_MODES, RUNNER_ACCEPTED_PROBLEM_TYPES, RUNNER_ACCEPTED_PROGRAMMING_LANGUAGES, RUNNER_TYPE, Role, RunnerType, SECONDS, SEC_120, SEC_30, SEC_60, SEC_90, SEPARATOR_TOKEN, SUBMISSION_RUN_STATUS, SUPPORT_EMAIL, SYSTEM_ROLE, ScopeData, Status, SubmissionRunStatus, SystemRole, TEAM_ROLE, THEME, TeamRole, TeamStatus, Theme, TypeTestCase, UPPERCASE_LETTERS, USER_ROLE, USER_STATUS, UserRole, UserStatus, UserTeamStatus, WebSocketMessageEvent, WebSocketResponseEvent, WebSocketSubscriptionEvent, WorkingIn, WorksheetType, YEARS, _KEY, _SUB_SUB_TAB, _SUB_TAB, _TAB, _TYPE, areArraysDifferent, chunkString, cleanRequest, clearAsyncInterval, consoleError, consoleInfo, consoleWarn, contentResponse, contentsResponse, errorsResponse, getAssignmentCommentKey, getAssignmentUserCommentKey, getChannelOfWebSocketSubscribeEvent, getClientId, getContestChannelParams, getContestCommentKey, getContestKeyOfWebSocketSubscribeEvent, getDataLog, getDataOfTestCase, getDays, getDefaultMeta, getDocumentAccess, getHours, getMilliseconds, getMinutes, getMonths, getParamsOfClientId, getParamsOfUserKey, getPlainText, getProblemCommentKey, getProblemJudgeKey, getRandomString, getSeconds, getSummaryWorksheetsInPages, getTotalExercisesOfSummaryWorksheetsInPages, getUserKey, getVerdictFromTestCase, getWebSocketResponseEventKey, getWebSocketResponseEventKeyOfResponse, getWorksheetsInPages, getYears, humanFileSize, indexToLetters, isBasicWorksheet, isChatCompletionsWebSocketEventDTO, isClientTrackDeviceWebSocketEventDTO, isClientTrackLocationWebSocketEventDTO, isClientTrackScreenshotWebSocketEventDTO, isClientTrackWebSocketResponseEventDTO, isCodeEditorSheet, isCodeRunStatusMessageWebSocketResponseEventDTO, isContestAssignment, isContestChangesWebSocketResponseEventDTO, isCourseAssignment, isEndlessContest, isFutureContest, isGlobalContest, isJkmdSheet, isObjectJson, isPastContest, isPingWebSocketEventDTO, isPongWebSocketResponseEventDTO, isProblemCrawledWebSocketResponseEventDTO, isQuizOptionsSheet, isQuizProblemSheet, isQuizTextSheet, isSenDataChatCompletionsWebSocketResponseEventDTO, isSendDataClientTrackWebSocketResponseEventDTO, isSendDataEc2InstancesListWebSocketResponseEventDTO, isSendDataEcsTaskDefinitionListWebSocketResponseEventDTO, isSendDataEcsTasksListWebSocketResponseEventDTO, isSendDataRunCommandWebSocketResponseEventDTO, isSendDataSsmSessionsListWebSocketResponseEventDTO, isSendDataWebSocketResponseEventDTO, isStringJson, isSubmissionRunStatusMessageWebSocketResponseEventDTO, isSubmissionsCrawlWebSocketResponseEventDTO, isSubscribeClientTrackDataWebSocketEventDTO, isSubscribeClientTrackWebSocketEventDTO, isSubscribeCodeRunStatusWebSocketEventDTO, isSubscribeContestChangesWebSocketEventDTO, isSubscribeGetDataWebSocketEventDTO, isSubscribeProblemCrawledWebSocketEventDTO, isSubscribeSubmissionRunStatusWebSocketEventDTO, isSubscribeSubmissionsCrawlWebSocketEventDTO, isSubscribeUserNotificationWebSocketEventDTO, isTeamMember, isUnsubscribeClientTrackDataWebSocketEventDTO, isUnsubscribeClientTrackWebSocketEventDTO, isUnsubscribeCodeRunStatusWebSocketEventDTO, isUnsubscribeContestChangesWebSocketEventDTO, isUnsubscribeGetDataWebSocketEventDTO, isUnsubscribeProblemCrawledWebSocketEventDTO, isUnsubscribeSubmissionRunStatusWebSocketEventDTO, isUnsubscribeSubmissionsCrawlWebSocketEventDTO, isUnsubscribeUserNotificationWebSocketEventDTO, isUserMember, isUserMessageWebSocketResponseEventDTO, isUserNotificationContestClarificationWebSocketResponseEventDTO, isUserNotificationSubmissionWebSocketResponseEventDTO, isUserNotificationWebSocketResponseEventDTO, isWebSocketChannelsMessageDTO, isWebSocketResponseEventDTO, isWebsocketSubscription, isWorksheetAssignment, join, lettersToIndex, memorySizeOf, mergeVerdicts, mex, normalizeToLocalStartOfDay, normalizeToLocalStartOfHour, normalizeToLocalStartOfMinutes, normalizeToLocalStartOfSeconds, objectUpdate, objectsUpdate, range, removeExtension, safeJsonParse, setAsyncInterval, split, splitTime, stringToArrayBuffer, toEntityMembersDTO, toJkError };