@xcpcio/core 0.71.1 → 0.73.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -131,6 +131,9 @@ class I18nText {
131
131
  }
132
132
  return result;
133
133
  }
134
+ valueOf() {
135
+ return this.getOrDefault();
136
+ }
134
137
  }
135
138
 
136
139
  function calcDirt(attemptedNum, solvedNum) {
@@ -659,14 +662,16 @@ class PlaceChartPointData {
659
662
  class Team {
660
663
  id;
661
664
  name;
665
+ organizationId;
666
+ organizationName;
662
667
  organization;
668
+ isFirstRankOfOrganization;
663
669
  group;
664
670
  tag;
665
671
  coaches;
666
672
  members;
667
673
  rank;
668
674
  originalRank;
669
- organizationRank;
670
675
  solvedProblemNum;
671
676
  attemptedProblemNum;
672
677
  lastSolvedProblem;
@@ -686,14 +691,13 @@ class Team {
686
691
  constructor() {
687
692
  this.id = "";
688
693
  this.name = new I18nText();
689
- this.organization = "";
694
+ this.isFirstRankOfOrganization = false;
690
695
  this.group = [];
691
696
  this.tag = [];
692
697
  this.coaches = [];
693
698
  this.members = [];
694
699
  this.rank = 0;
695
700
  this.originalRank = 0;
696
- this.organizationRank = -1;
697
701
  this.solvedProblemNum = 0;
698
702
  this.attemptedProblemNum = 0;
699
703
  this.lastSolvedProblem = null;
@@ -708,9 +712,9 @@ class Team {
708
712
  this.se = 0;
709
713
  }
710
714
  reset() {
715
+ this.isFirstRankOfOrganization = false;
711
716
  this.rank = 0;
712
717
  this.originalRank = 0;
713
- this.organizationRank = -1;
714
718
  this.solvedProblemNum = 0;
715
719
  this.attemptedProblemNum = 0;
716
720
  this.lastSolvedProblem = null;
@@ -834,11 +838,20 @@ function createTeam(teamJSON) {
834
838
  const t = new Team();
835
839
  t.id = teamJSON.id ?? teamJSON.team_id ?? "";
836
840
  t.name = I18nText.fromIText(teamJSON.name ?? teamJSON.team_name ?? "");
837
- t.organization = teamJSON.organization ?? "";
841
+ if (teamJSON.organization) {
842
+ t.organizationId = teamJSON.organization;
843
+ t.organizationName = teamJSON.organization;
844
+ } else {
845
+ t.organizationId = teamJSON.organization_id;
846
+ }
838
847
  t.group = ___default.cloneDeep(teamJSON.group ?? []);
839
848
  t.tag = ___default.cloneDeep(teamJSON.tag ?? []);
840
- t.coaches = createPersons(teamJSON.coach);
841
849
  t.members = createPersons(teamJSON.members);
850
+ if (teamJSON.coach) {
851
+ t.coaches = createPersons(teamJSON.coach);
852
+ } else {
853
+ t.coaches = createPersons(teamJSON.coaches);
854
+ }
842
855
  if (Boolean(teamJSON.official) === true) {
843
856
  t.group.push("official");
844
857
  }
@@ -1416,7 +1429,7 @@ class CodeforcesGymGhostDATConverter {
1416
1429
  rank.teams.forEach((team) => {
1417
1430
  let name = team.name.getOrDefault();
1418
1431
  if (team.organization) {
1419
- name = `${team.organization} - ${name}`;
1432
+ name = `${team.organization.name.getOrDefault()} - ${name}`;
1420
1433
  }
1421
1434
  if (team.members) {
1422
1435
  name = `${name} - ${team.membersToString()}`;
@@ -1617,12 +1630,12 @@ class GeneralExcelConverter {
1617
1630
  const arr = [];
1618
1631
  arr.push(team.rank.toString());
1619
1632
  if (team.organization) {
1620
- if (team.organizationRank !== -1) {
1621
- arr.push(team.organizationRank.toString());
1633
+ if (team.isFirstRankOfOrganization) {
1634
+ arr.push(team.organization.rank.toString());
1622
1635
  } else {
1623
1636
  arr.push("");
1624
1637
  }
1625
- arr.push(team.organization);
1638
+ arr.push(team.organization.name.getOrDefault());
1626
1639
  }
1627
1640
  arr.push(team.name.getOrDefault(), team.solvedProblemNum.toString(), team.penaltyToMinute.toString());
1628
1641
  for (const p of team.problemStatistics) {
@@ -1693,7 +1706,7 @@ class ICPCStandingsCsvConverter {
1693
1706
  siteCitation: rank.contest.name.getOrDefault(),
1694
1707
  citation: ordinal__default(team.rank),
1695
1708
  teamName: team.name.getOrDefault(),
1696
- institution: team.organization
1709
+ institution: team.organization?.name.getOrDefault() ?? ""
1697
1710
  };
1698
1711
  resList.push(res);
1699
1712
  }
@@ -1740,6 +1753,42 @@ function getImageSource(image, asset_host) {
1740
1753
  return "";
1741
1754
  }
1742
1755
 
1756
+ class Organization {
1757
+ id;
1758
+ name;
1759
+ logo;
1760
+ // Teams belonging to this organization
1761
+ teams;
1762
+ rank;
1763
+ constructor() {
1764
+ this.id = "";
1765
+ this.name = new I18nText();
1766
+ this.teams = [];
1767
+ this.rank = -1;
1768
+ }
1769
+ reset() {
1770
+ this.rank = -1;
1771
+ }
1772
+ static compare(lhs, rhs) {
1773
+ if (lhs.id < rhs.id) {
1774
+ return -1;
1775
+ } else if (lhs.id > rhs.id) {
1776
+ return 1;
1777
+ }
1778
+ return 0;
1779
+ }
1780
+ }
1781
+ function createOrganization(orgJSON) {
1782
+ const org = new Organization();
1783
+ org.id = orgJSON.id;
1784
+ org.name = I18nText.fromIText(orgJSON.name);
1785
+ org.logo = orgJSON.logo;
1786
+ return org;
1787
+ }
1788
+ function createOrganizations(orgsJSON) {
1789
+ return orgsJSON.map((org) => createOrganization(org));
1790
+ }
1791
+
1743
1792
  class RankStatistics {
1744
1793
  teamSolvedNum;
1745
1794
  teamSolvedNumIndex;
@@ -1864,6 +1913,7 @@ class Rank {
1864
1913
  submissions;
1865
1914
  submissionsMap;
1866
1915
  organizations;
1916
+ organizationsMap;
1867
1917
  originTeams;
1868
1918
  rankStatistics;
1869
1919
  options;
@@ -1889,7 +1939,9 @@ class Rank {
1889
1939
  });
1890
1940
  }
1891
1941
  this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
1892
- this.organizations = this.buildOrganizations();
1942
+ this.organizationsMap = this.buildOrganizationsMap();
1943
+ this.organizations = [...this.organizationsMap.values()];
1944
+ this.organizations.sort(Organization.compare);
1893
1945
  this.originTeams = this.teams.map((t) => t);
1894
1946
  this.originTeams.sort(Team.compare);
1895
1947
  this.rankStatistics = new RankStatistics();
@@ -1912,6 +1964,31 @@ class Rank {
1912
1964
  this.statuses = [...se].sort();
1913
1965
  }
1914
1966
  }
1967
+ buildOrganizationsMap() {
1968
+ if (!this.contest.organization) {
1969
+ return /* @__PURE__ */ new Map();
1970
+ }
1971
+ const res = /* @__PURE__ */ new Map();
1972
+ this.teams.forEach((t) => {
1973
+ if (!t.organizationId) {
1974
+ return;
1975
+ }
1976
+ if (res.has(t.organizationId)) {
1977
+ const org2 = res.get(t.organizationId);
1978
+ org2?.teams.push(t);
1979
+ t.organization = org2;
1980
+ return;
1981
+ }
1982
+ const org = new Organization();
1983
+ org.id = t.organizationId;
1984
+ org.name = new I18nText();
1985
+ org.name.fallback = t.organizationName;
1986
+ org.teams.push(t);
1987
+ t.organization = org;
1988
+ res.set(org.id, org);
1989
+ });
1990
+ return res;
1991
+ }
1915
1992
  cleanRank() {
1916
1993
  (() => {
1917
1994
  this.teams = [];
@@ -1922,6 +1999,9 @@ class Rank {
1922
1999
  this.teams.push(v);
1923
2000
  }
1924
2001
  })();
2002
+ for (const o of this.organizations) {
2003
+ o.reset();
2004
+ }
1925
2005
  for (const t of this.teams) {
1926
2006
  t.reset();
1927
2007
  t.problemStatistics = this.contest.problems.map((p) => {
@@ -2076,39 +2156,21 @@ class Rank {
2076
2156
  }
2077
2157
  let rank = 1;
2078
2158
  let preTeam = null;
2079
- const se = /* @__PURE__ */ new Set();
2080
2159
  for (const t of this.teams) {
2081
2160
  const org = t.organization;
2082
- if (se.has(org)) {
2161
+ if (!org || org.rank > -1) {
2083
2162
  continue;
2084
2163
  }
2085
- se.add(org);
2086
- t.organizationRank = rank++;
2087
- if (preTeam !== null) {
2164
+ org.rank = rank++;
2165
+ t.isFirstRankOfOrganization = true;
2166
+ if (preTeam) {
2088
2167
  if (t.isEqualRank(preTeam)) {
2089
- t.organizationRank = preTeam.organizationRank;
2168
+ org.rank = preTeam.organization.rank;
2090
2169
  }
2091
2170
  }
2092
2171
  preTeam = t;
2093
2172
  }
2094
2173
  }
2095
- buildOrganizations() {
2096
- if (!this.contest.organization) {
2097
- return [];
2098
- }
2099
- const res = new Array();
2100
- const se = /* @__PURE__ */ new Set();
2101
- this.teams.forEach((t) => {
2102
- const org = t.organization;
2103
- if (se.has(org)) {
2104
- return;
2105
- }
2106
- res.push(org);
2107
- se.add(org);
2108
- });
2109
- res.sort();
2110
- return res;
2111
- }
2112
2174
  buildAwards() {
2113
2175
  if (this.contest.medal === "ccpc") {
2114
2176
  this.contest.awards = /* @__PURE__ */ new Map();
@@ -2444,7 +2506,7 @@ class Rating {
2444
2506
  u = new RatingUser();
2445
2507
  u.id = id;
2446
2508
  u.name = t.name;
2447
- u.organization = t.organization;
2509
+ u.organization = t.organizationName ?? "";
2448
2510
  u.members = t.members;
2449
2511
  u.coaches = t.coaches;
2450
2512
  u.rank = t.rank;
@@ -2464,7 +2526,7 @@ class Rating {
2464
2526
  h.rank = t.rank;
2465
2527
  h.rating = u.rating;
2466
2528
  h.teamName = t.name;
2467
- h.organization = t.organization;
2529
+ h.organization = t.organizationName ?? "";
2468
2530
  h.members = t.members;
2469
2531
  h.coaches = t.coaches;
2470
2532
  h.contestID = rank.contest.id;
@@ -2485,7 +2547,7 @@ class Rating {
2485
2547
  if (persons.length > 0) {
2486
2548
  return persons.map((person) => person.name.getOrDefault().trim()).sort().join("|");
2487
2549
  }
2488
- return `${t.organization}-${t.name}`;
2550
+ return `${t.organizationName ?? ""}-${t.name}`;
2489
2551
  }
2490
2552
  toJSON() {
2491
2553
  return {
@@ -2848,6 +2910,7 @@ exports.GiantsType = GiantsType;
2848
2910
  exports.I18nText = I18nText;
2849
2911
  exports.ICPCStandingsCsvConverter = ICPCStandingsCsvConverter;
2850
2912
  exports.MedalType = MedalType;
2913
+ exports.Organization = Organization;
2851
2914
  exports.Person = Person;
2852
2915
  exports.PlaceChartPointData = PlaceChartPointData;
2853
2916
  exports.Problem = Problem;
@@ -2872,6 +2935,8 @@ exports.createContest = createContest;
2872
2935
  exports.createContestIndex = createContestIndex;
2873
2936
  exports.createContestIndexList = createContestIndexList;
2874
2937
  exports.createDayJS = createDayJS;
2938
+ exports.createOrganization = createOrganization;
2939
+ exports.createOrganizations = createOrganizations;
2875
2940
  exports.createPersons = createPersons;
2876
2941
  exports.createProblem = createProblem;
2877
2942
  exports.createProblems = createProblems;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Lang, I18NStringSet, Text, CalculationOfPenalty, TimeUnit, Image, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Person as Person$1, Persons as Persons$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
1
+ import { Lang, I18NStringSet, Text, CalculationOfPenalty, TimeUnit, Image, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Organization as Organization$1, Organizations as Organizations$1, Person as Person$1, Persons as Persons$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
2
2
  import dayjs from 'dayjs';
3
3
  export { default as dayjs } from 'dayjs';
4
4
  import * as XLSX from 'xlsx-js-style';
@@ -35,6 +35,7 @@ declare class I18nText {
35
35
  static fromI18NStringSet(stringSet: I18NStringSet): I18nText;
36
36
  static fromIText(text: Text): I18nText;
37
37
  toI18NStringSet(): I18NStringSet;
38
+ valueOf(): string;
38
39
  }
39
40
 
40
41
  declare class ContestOptions {
@@ -192,6 +193,20 @@ declare class TeamProblemStatistics {
192
193
  get penaltyInSecond(): number;
193
194
  }
194
195
 
196
+ declare class Organization {
197
+ id: string;
198
+ name: I18nText;
199
+ logo?: Image;
200
+ teams: Teams;
201
+ rank: number;
202
+ constructor();
203
+ reset(): void;
204
+ static compare(lhs: Organization, rhs: Organization): number;
205
+ }
206
+ type Organizations = Array<Organization>;
207
+ declare function createOrganization(orgJSON: Organization$1): Organization;
208
+ declare function createOrganizations(orgsJSON: Organizations$1): Organizations;
209
+
195
210
  declare class Person {
196
211
  name: I18nText;
197
212
  cfID?: string;
@@ -212,14 +227,16 @@ declare class PlaceChartPointData {
212
227
  declare class Team {
213
228
  id: string;
214
229
  name: I18nText;
215
- organization: string;
230
+ organizationId?: string;
231
+ organizationName?: string;
232
+ organization?: Organization;
233
+ isFirstRankOfOrganization: boolean;
216
234
  group: Array<string>;
217
235
  tag: Array<string>;
218
236
  coaches: Persons;
219
237
  members: Persons;
220
238
  rank: number;
221
239
  originalRank: number;
222
- organizationRank: number;
223
240
  solvedProblemNum: number;
224
241
  attemptedProblemNum: number;
225
242
  lastSolvedProblem: Problem | null;
@@ -363,7 +380,8 @@ declare class Rank {
363
380
  teamsMap: Map<string, Team>;
364
381
  submissions: Submissions;
365
382
  submissionsMap: Map<string, Submission>;
366
- organizations: Array<string>;
383
+ organizations: Organizations;
384
+ organizationsMap: Map<string, Organization>;
367
385
  originTeams: Teams;
368
386
  rankStatistics: RankStatistics;
369
387
  options: RankOptions;
@@ -371,11 +389,11 @@ declare class Rank {
371
389
  languages: Array<string>;
372
390
  statuses: Array<SubmissionStatus>;
373
391
  constructor(contest: Contest, teams: Teams, submissions: Submissions);
392
+ buildOrganizationsMap(): Map<string, Organization>;
374
393
  cleanRank(): void;
375
394
  buildRank(): this;
376
395
  buildTeamRank(): void;
377
396
  buildOrgRank(): void;
378
- buildOrganizations(): string[];
379
397
  buildAwards(): void;
380
398
  filterTeamByOrg(team: Team): boolean;
381
399
  getSubmissions(): Submissions;
@@ -535,5 +553,5 @@ declare function isRejected(status: SubmissionStatus): boolean;
535
553
  declare function isPending(status: SubmissionStatus): boolean;
536
554
  declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
537
555
 
538
- export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
539
- export type { Awards, Balloons, ContestIndexList, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
556
+ export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Organization, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createOrganization, createOrganizations, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
557
+ export type { Awards, Balloons, ContestIndexList, Organizations, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Lang, I18NStringSet, Text, CalculationOfPenalty, TimeUnit, Image, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Person as Person$1, Persons as Persons$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
1
+ import { Lang, I18NStringSet, Text, CalculationOfPenalty, TimeUnit, Image, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Organization as Organization$1, Organizations as Organizations$1, Person as Person$1, Persons as Persons$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
2
2
  import dayjs from 'dayjs';
3
3
  export { default as dayjs } from 'dayjs';
4
4
  import * as XLSX from 'xlsx-js-style';
@@ -35,6 +35,7 @@ declare class I18nText {
35
35
  static fromI18NStringSet(stringSet: I18NStringSet): I18nText;
36
36
  static fromIText(text: Text): I18nText;
37
37
  toI18NStringSet(): I18NStringSet;
38
+ valueOf(): string;
38
39
  }
39
40
 
40
41
  declare class ContestOptions {
@@ -192,6 +193,20 @@ declare class TeamProblemStatistics {
192
193
  get penaltyInSecond(): number;
193
194
  }
194
195
 
196
+ declare class Organization {
197
+ id: string;
198
+ name: I18nText;
199
+ logo?: Image;
200
+ teams: Teams;
201
+ rank: number;
202
+ constructor();
203
+ reset(): void;
204
+ static compare(lhs: Organization, rhs: Organization): number;
205
+ }
206
+ type Organizations = Array<Organization>;
207
+ declare function createOrganization(orgJSON: Organization$1): Organization;
208
+ declare function createOrganizations(orgsJSON: Organizations$1): Organizations;
209
+
195
210
  declare class Person {
196
211
  name: I18nText;
197
212
  cfID?: string;
@@ -212,14 +227,16 @@ declare class PlaceChartPointData {
212
227
  declare class Team {
213
228
  id: string;
214
229
  name: I18nText;
215
- organization: string;
230
+ organizationId?: string;
231
+ organizationName?: string;
232
+ organization?: Organization;
233
+ isFirstRankOfOrganization: boolean;
216
234
  group: Array<string>;
217
235
  tag: Array<string>;
218
236
  coaches: Persons;
219
237
  members: Persons;
220
238
  rank: number;
221
239
  originalRank: number;
222
- organizationRank: number;
223
240
  solvedProblemNum: number;
224
241
  attemptedProblemNum: number;
225
242
  lastSolvedProblem: Problem | null;
@@ -363,7 +380,8 @@ declare class Rank {
363
380
  teamsMap: Map<string, Team>;
364
381
  submissions: Submissions;
365
382
  submissionsMap: Map<string, Submission>;
366
- organizations: Array<string>;
383
+ organizations: Organizations;
384
+ organizationsMap: Map<string, Organization>;
367
385
  originTeams: Teams;
368
386
  rankStatistics: RankStatistics;
369
387
  options: RankOptions;
@@ -371,11 +389,11 @@ declare class Rank {
371
389
  languages: Array<string>;
372
390
  statuses: Array<SubmissionStatus>;
373
391
  constructor(contest: Contest, teams: Teams, submissions: Submissions);
392
+ buildOrganizationsMap(): Map<string, Organization>;
374
393
  cleanRank(): void;
375
394
  buildRank(): this;
376
395
  buildTeamRank(): void;
377
396
  buildOrgRank(): void;
378
- buildOrganizations(): string[];
379
397
  buildAwards(): void;
380
398
  filterTeamByOrg(team: Team): boolean;
381
399
  getSubmissions(): Submissions;
@@ -535,5 +553,5 @@ declare function isRejected(status: SubmissionStatus): boolean;
535
553
  declare function isPending(status: SubmissionStatus): boolean;
536
554
  declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
537
555
 
538
- export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
539
- export type { Awards, Balloons, ContestIndexList, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
556
+ export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Organization, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createOrganization, createOrganizations, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
557
+ export type { Awards, Balloons, ContestIndexList, Organizations, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Lang, I18NStringSet, Text, CalculationOfPenalty, TimeUnit, Image, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Person as Person$1, Persons as Persons$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
1
+ import { Lang, I18NStringSet, Text, CalculationOfPenalty, TimeUnit, Image, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Organization as Organization$1, Organizations as Organizations$1, Person as Person$1, Persons as Persons$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
2
2
  import dayjs from 'dayjs';
3
3
  export { default as dayjs } from 'dayjs';
4
4
  import * as XLSX from 'xlsx-js-style';
@@ -35,6 +35,7 @@ declare class I18nText {
35
35
  static fromI18NStringSet(stringSet: I18NStringSet): I18nText;
36
36
  static fromIText(text: Text): I18nText;
37
37
  toI18NStringSet(): I18NStringSet;
38
+ valueOf(): string;
38
39
  }
39
40
 
40
41
  declare class ContestOptions {
@@ -192,6 +193,20 @@ declare class TeamProblemStatistics {
192
193
  get penaltyInSecond(): number;
193
194
  }
194
195
 
196
+ declare class Organization {
197
+ id: string;
198
+ name: I18nText;
199
+ logo?: Image;
200
+ teams: Teams;
201
+ rank: number;
202
+ constructor();
203
+ reset(): void;
204
+ static compare(lhs: Organization, rhs: Organization): number;
205
+ }
206
+ type Organizations = Array<Organization>;
207
+ declare function createOrganization(orgJSON: Organization$1): Organization;
208
+ declare function createOrganizations(orgsJSON: Organizations$1): Organizations;
209
+
195
210
  declare class Person {
196
211
  name: I18nText;
197
212
  cfID?: string;
@@ -212,14 +227,16 @@ declare class PlaceChartPointData {
212
227
  declare class Team {
213
228
  id: string;
214
229
  name: I18nText;
215
- organization: string;
230
+ organizationId?: string;
231
+ organizationName?: string;
232
+ organization?: Organization;
233
+ isFirstRankOfOrganization: boolean;
216
234
  group: Array<string>;
217
235
  tag: Array<string>;
218
236
  coaches: Persons;
219
237
  members: Persons;
220
238
  rank: number;
221
239
  originalRank: number;
222
- organizationRank: number;
223
240
  solvedProblemNum: number;
224
241
  attemptedProblemNum: number;
225
242
  lastSolvedProblem: Problem | null;
@@ -363,7 +380,8 @@ declare class Rank {
363
380
  teamsMap: Map<string, Team>;
364
381
  submissions: Submissions;
365
382
  submissionsMap: Map<string, Submission>;
366
- organizations: Array<string>;
383
+ organizations: Organizations;
384
+ organizationsMap: Map<string, Organization>;
367
385
  originTeams: Teams;
368
386
  rankStatistics: RankStatistics;
369
387
  options: RankOptions;
@@ -371,11 +389,11 @@ declare class Rank {
371
389
  languages: Array<string>;
372
390
  statuses: Array<SubmissionStatus>;
373
391
  constructor(contest: Contest, teams: Teams, submissions: Submissions);
392
+ buildOrganizationsMap(): Map<string, Organization>;
374
393
  cleanRank(): void;
375
394
  buildRank(): this;
376
395
  buildTeamRank(): void;
377
396
  buildOrgRank(): void;
378
- buildOrganizations(): string[];
379
397
  buildAwards(): void;
380
398
  filterTeamByOrg(team: Team): boolean;
381
399
  getSubmissions(): Submissions;
@@ -535,5 +553,5 @@ declare function isRejected(status: SubmissionStatus): boolean;
535
553
  declare function isPending(status: SubmissionStatus): boolean;
536
554
  declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
537
555
 
538
- export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
539
- export type { Awards, Balloons, ContestIndexList, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
556
+ export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Organization, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createOrganization, createOrganizations, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
557
+ export type { Awards, Balloons, ContestIndexList, Organizations, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
package/dist/index.mjs CHANGED
@@ -100,6 +100,9 @@ class I18nText {
100
100
  }
101
101
  return result;
102
102
  }
103
+ valueOf() {
104
+ return this.getOrDefault();
105
+ }
103
106
  }
104
107
 
105
108
  function calcDirt(attemptedNum, solvedNum) {
@@ -628,14 +631,16 @@ class PlaceChartPointData {
628
631
  class Team {
629
632
  id;
630
633
  name;
634
+ organizationId;
635
+ organizationName;
631
636
  organization;
637
+ isFirstRankOfOrganization;
632
638
  group;
633
639
  tag;
634
640
  coaches;
635
641
  members;
636
642
  rank;
637
643
  originalRank;
638
- organizationRank;
639
644
  solvedProblemNum;
640
645
  attemptedProblemNum;
641
646
  lastSolvedProblem;
@@ -655,14 +660,13 @@ class Team {
655
660
  constructor() {
656
661
  this.id = "";
657
662
  this.name = new I18nText();
658
- this.organization = "";
663
+ this.isFirstRankOfOrganization = false;
659
664
  this.group = [];
660
665
  this.tag = [];
661
666
  this.coaches = [];
662
667
  this.members = [];
663
668
  this.rank = 0;
664
669
  this.originalRank = 0;
665
- this.organizationRank = -1;
666
670
  this.solvedProblemNum = 0;
667
671
  this.attemptedProblemNum = 0;
668
672
  this.lastSolvedProblem = null;
@@ -677,9 +681,9 @@ class Team {
677
681
  this.se = 0;
678
682
  }
679
683
  reset() {
684
+ this.isFirstRankOfOrganization = false;
680
685
  this.rank = 0;
681
686
  this.originalRank = 0;
682
- this.organizationRank = -1;
683
687
  this.solvedProblemNum = 0;
684
688
  this.attemptedProblemNum = 0;
685
689
  this.lastSolvedProblem = null;
@@ -803,11 +807,20 @@ function createTeam(teamJSON) {
803
807
  const t = new Team();
804
808
  t.id = teamJSON.id ?? teamJSON.team_id ?? "";
805
809
  t.name = I18nText.fromIText(teamJSON.name ?? teamJSON.team_name ?? "");
806
- t.organization = teamJSON.organization ?? "";
810
+ if (teamJSON.organization) {
811
+ t.organizationId = teamJSON.organization;
812
+ t.organizationName = teamJSON.organization;
813
+ } else {
814
+ t.organizationId = teamJSON.organization_id;
815
+ }
807
816
  t.group = _.cloneDeep(teamJSON.group ?? []);
808
817
  t.tag = _.cloneDeep(teamJSON.tag ?? []);
809
- t.coaches = createPersons(teamJSON.coach);
810
818
  t.members = createPersons(teamJSON.members);
819
+ if (teamJSON.coach) {
820
+ t.coaches = createPersons(teamJSON.coach);
821
+ } else {
822
+ t.coaches = createPersons(teamJSON.coaches);
823
+ }
811
824
  if (Boolean(teamJSON.official) === true) {
812
825
  t.group.push("official");
813
826
  }
@@ -1385,7 +1398,7 @@ class CodeforcesGymGhostDATConverter {
1385
1398
  rank.teams.forEach((team) => {
1386
1399
  let name = team.name.getOrDefault();
1387
1400
  if (team.organization) {
1388
- name = `${team.organization} - ${name}`;
1401
+ name = `${team.organization.name.getOrDefault()} - ${name}`;
1389
1402
  }
1390
1403
  if (team.members) {
1391
1404
  name = `${name} - ${team.membersToString()}`;
@@ -1586,12 +1599,12 @@ class GeneralExcelConverter {
1586
1599
  const arr = [];
1587
1600
  arr.push(team.rank.toString());
1588
1601
  if (team.organization) {
1589
- if (team.organizationRank !== -1) {
1590
- arr.push(team.organizationRank.toString());
1602
+ if (team.isFirstRankOfOrganization) {
1603
+ arr.push(team.organization.rank.toString());
1591
1604
  } else {
1592
1605
  arr.push("");
1593
1606
  }
1594
- arr.push(team.organization);
1607
+ arr.push(team.organization.name.getOrDefault());
1595
1608
  }
1596
1609
  arr.push(team.name.getOrDefault(), team.solvedProblemNum.toString(), team.penaltyToMinute.toString());
1597
1610
  for (const p of team.problemStatistics) {
@@ -1662,7 +1675,7 @@ class ICPCStandingsCsvConverter {
1662
1675
  siteCitation: rank.contest.name.getOrDefault(),
1663
1676
  citation: ordinal(team.rank),
1664
1677
  teamName: team.name.getOrDefault(),
1665
- institution: team.organization
1678
+ institution: team.organization?.name.getOrDefault() ?? ""
1666
1679
  };
1667
1680
  resList.push(res);
1668
1681
  }
@@ -1709,6 +1722,42 @@ function getImageSource(image, asset_host) {
1709
1722
  return "";
1710
1723
  }
1711
1724
 
1725
+ class Organization {
1726
+ id;
1727
+ name;
1728
+ logo;
1729
+ // Teams belonging to this organization
1730
+ teams;
1731
+ rank;
1732
+ constructor() {
1733
+ this.id = "";
1734
+ this.name = new I18nText();
1735
+ this.teams = [];
1736
+ this.rank = -1;
1737
+ }
1738
+ reset() {
1739
+ this.rank = -1;
1740
+ }
1741
+ static compare(lhs, rhs) {
1742
+ if (lhs.id < rhs.id) {
1743
+ return -1;
1744
+ } else if (lhs.id > rhs.id) {
1745
+ return 1;
1746
+ }
1747
+ return 0;
1748
+ }
1749
+ }
1750
+ function createOrganization(orgJSON) {
1751
+ const org = new Organization();
1752
+ org.id = orgJSON.id;
1753
+ org.name = I18nText.fromIText(orgJSON.name);
1754
+ org.logo = orgJSON.logo;
1755
+ return org;
1756
+ }
1757
+ function createOrganizations(orgsJSON) {
1758
+ return orgsJSON.map((org) => createOrganization(org));
1759
+ }
1760
+
1712
1761
  class RankStatistics {
1713
1762
  teamSolvedNum;
1714
1763
  teamSolvedNumIndex;
@@ -1833,6 +1882,7 @@ class Rank {
1833
1882
  submissions;
1834
1883
  submissionsMap;
1835
1884
  organizations;
1885
+ organizationsMap;
1836
1886
  originTeams;
1837
1887
  rankStatistics;
1838
1888
  options;
@@ -1858,7 +1908,9 @@ class Rank {
1858
1908
  });
1859
1909
  }
1860
1910
  this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
1861
- this.organizations = this.buildOrganizations();
1911
+ this.organizationsMap = this.buildOrganizationsMap();
1912
+ this.organizations = [...this.organizationsMap.values()];
1913
+ this.organizations.sort(Organization.compare);
1862
1914
  this.originTeams = this.teams.map((t) => t);
1863
1915
  this.originTeams.sort(Team.compare);
1864
1916
  this.rankStatistics = new RankStatistics();
@@ -1881,6 +1933,31 @@ class Rank {
1881
1933
  this.statuses = [...se].sort();
1882
1934
  }
1883
1935
  }
1936
+ buildOrganizationsMap() {
1937
+ if (!this.contest.organization) {
1938
+ return /* @__PURE__ */ new Map();
1939
+ }
1940
+ const res = /* @__PURE__ */ new Map();
1941
+ this.teams.forEach((t) => {
1942
+ if (!t.organizationId) {
1943
+ return;
1944
+ }
1945
+ if (res.has(t.organizationId)) {
1946
+ const org2 = res.get(t.organizationId);
1947
+ org2?.teams.push(t);
1948
+ t.organization = org2;
1949
+ return;
1950
+ }
1951
+ const org = new Organization();
1952
+ org.id = t.organizationId;
1953
+ org.name = new I18nText();
1954
+ org.name.fallback = t.organizationName;
1955
+ org.teams.push(t);
1956
+ t.organization = org;
1957
+ res.set(org.id, org);
1958
+ });
1959
+ return res;
1960
+ }
1884
1961
  cleanRank() {
1885
1962
  (() => {
1886
1963
  this.teams = [];
@@ -1891,6 +1968,9 @@ class Rank {
1891
1968
  this.teams.push(v);
1892
1969
  }
1893
1970
  })();
1971
+ for (const o of this.organizations) {
1972
+ o.reset();
1973
+ }
1894
1974
  for (const t of this.teams) {
1895
1975
  t.reset();
1896
1976
  t.problemStatistics = this.contest.problems.map((p) => {
@@ -2045,39 +2125,21 @@ class Rank {
2045
2125
  }
2046
2126
  let rank = 1;
2047
2127
  let preTeam = null;
2048
- const se = /* @__PURE__ */ new Set();
2049
2128
  for (const t of this.teams) {
2050
2129
  const org = t.organization;
2051
- if (se.has(org)) {
2130
+ if (!org || org.rank > -1) {
2052
2131
  continue;
2053
2132
  }
2054
- se.add(org);
2055
- t.organizationRank = rank++;
2056
- if (preTeam !== null) {
2133
+ org.rank = rank++;
2134
+ t.isFirstRankOfOrganization = true;
2135
+ if (preTeam) {
2057
2136
  if (t.isEqualRank(preTeam)) {
2058
- t.organizationRank = preTeam.organizationRank;
2137
+ org.rank = preTeam.organization.rank;
2059
2138
  }
2060
2139
  }
2061
2140
  preTeam = t;
2062
2141
  }
2063
2142
  }
2064
- buildOrganizations() {
2065
- if (!this.contest.organization) {
2066
- return [];
2067
- }
2068
- const res = new Array();
2069
- const se = /* @__PURE__ */ new Set();
2070
- this.teams.forEach((t) => {
2071
- const org = t.organization;
2072
- if (se.has(org)) {
2073
- return;
2074
- }
2075
- res.push(org);
2076
- se.add(org);
2077
- });
2078
- res.sort();
2079
- return res;
2080
- }
2081
2143
  buildAwards() {
2082
2144
  if (this.contest.medal === "ccpc") {
2083
2145
  this.contest.awards = /* @__PURE__ */ new Map();
@@ -2413,7 +2475,7 @@ class Rating {
2413
2475
  u = new RatingUser();
2414
2476
  u.id = id;
2415
2477
  u.name = t.name;
2416
- u.organization = t.organization;
2478
+ u.organization = t.organizationName ?? "";
2417
2479
  u.members = t.members;
2418
2480
  u.coaches = t.coaches;
2419
2481
  u.rank = t.rank;
@@ -2433,7 +2495,7 @@ class Rating {
2433
2495
  h.rank = t.rank;
2434
2496
  h.rating = u.rating;
2435
2497
  h.teamName = t.name;
2436
- h.organization = t.organization;
2498
+ h.organization = t.organizationName ?? "";
2437
2499
  h.members = t.members;
2438
2500
  h.coaches = t.coaches;
2439
2501
  h.contestID = rank.contest.id;
@@ -2454,7 +2516,7 @@ class Rating {
2454
2516
  if (persons.length > 0) {
2455
2517
  return persons.map((person) => person.name.getOrDefault().trim()).sort().join("|");
2456
2518
  }
2457
- return `${t.organization}-${t.name}`;
2519
+ return `${t.organizationName ?? ""}-${t.name}`;
2458
2520
  }
2459
2521
  toJSON() {
2460
2522
  return {
@@ -2802,4 +2864,4 @@ class ResolverVue extends Resolver {
2802
2864
  }
2803
2865
  }
2804
2866
 
2805
- export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
2867
+ export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, I18nText, ICPCStandingsCsvConverter, MedalType, Organization, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createOrganization, createOrganizations, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
3
  "type": "module",
4
- "version": "0.71.1",
4
+ "version": "0.73.1",
5
5
  "description": "The core library for XCPCIO",
6
6
  "author": "Dup4 <hi@dup4.com>",
7
7
  "license": "MIT",
@@ -42,7 +42,7 @@
42
42
  "papaparse": "^5.5.3",
43
43
  "string-width": "^8.1.0",
44
44
  "xlsx-js-style": "^1.2.0",
45
- "@xcpcio/types": "0.71.1"
45
+ "@xcpcio/types": "0.73.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@babel/types": "^7.28.5",