@xcpcio/core 0.46.0 → 0.46.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
@@ -548,6 +548,36 @@ class ICPCStandingsCsvConverter {
548
548
  }
549
549
  }
550
550
 
551
+ class Person {
552
+ constructor(name = "") {
553
+ this.name = name;
554
+ }
555
+ toJSON() {
556
+ return {
557
+ name: this.name
558
+ };
559
+ }
560
+ static fromJSON(iPerson) {
561
+ if (typeof iPerson === "string") {
562
+ iPerson = JSON.parse(iPerson);
563
+ }
564
+ const person = new Person();
565
+ person.name = iPerson.name;
566
+ return person;
567
+ }
568
+ }
569
+ function createPersons(iPersons) {
570
+ if (typeof iPersons === "string") {
571
+ for (const c of " ,\u3001|") {
572
+ if (iPersons.includes(c)) {
573
+ return iPersons.split(c).map((name) => new Person(name));
574
+ }
575
+ }
576
+ return [new Person(iPersons)];
577
+ }
578
+ return iPersons.map((name) => new Person(name));
579
+ }
580
+
551
581
  function calcDirt(attemptedNum, solvedNum) {
552
582
  if (solvedNum === 0) {
553
583
  return 0;
@@ -580,6 +610,10 @@ class RatingHistory {
580
610
  constructor() {
581
611
  this.rank = 0;
582
612
  this.rating = 0;
613
+ this.teamName = "";
614
+ this.organization = "";
615
+ this.members = [];
616
+ this.coaches = [];
583
617
  this.contestID = "";
584
618
  this.contestName = "";
585
619
  this.contestLink = "";
@@ -589,6 +623,10 @@ class RatingHistory {
589
623
  return {
590
624
  rank: this.rank,
591
625
  rating: this.rating,
626
+ teamName: this.teamName,
627
+ organization: this.organization,
628
+ members: this.members.map((member) => member.toJSON()),
629
+ coaches: this.coaches.map((coach) => coach.toJSON()),
592
630
  contestID: this.contestID,
593
631
  contestName: this.contestName,
594
632
  contestLink: this.contestLink,
@@ -602,6 +640,10 @@ class RatingHistory {
602
640
  const ratingHistory = new RatingHistory();
603
641
  ratingHistory.rank = iRatingHistory.rank;
604
642
  ratingHistory.rating = iRatingHistory.rating;
643
+ ratingHistory.teamName = iRatingHistory.teamName;
644
+ ratingHistory.organization = iRatingHistory.organization;
645
+ ratingHistory.members = iRatingHistory.members.map((iMember) => Person.fromJSON(iMember));
646
+ ratingHistory.coaches = iRatingHistory.coaches.map((iCoach) => Person.fromJSON(iCoach));
605
647
  ratingHistory.contestID = iRatingHistory.contestID;
606
648
  ratingHistory.contestName = iRatingHistory.contestName;
607
649
  ratingHistory.contestLink = iRatingHistory.contestLink;
@@ -614,6 +656,9 @@ class RatingUser {
614
656
  constructor() {
615
657
  this.id = "";
616
658
  this.name = "";
659
+ this.organization = "";
660
+ this.members = [];
661
+ this.coaches = [];
617
662
  this.rating = 0;
618
663
  this.minRating = 1061109567;
619
664
  this.maxRating = -1061109567;
@@ -632,6 +677,9 @@ class RatingUser {
632
677
  return {
633
678
  id: this.id,
634
679
  name: this.name,
680
+ organization: this.organization,
681
+ members: this.members.map((member) => member.toJSON()),
682
+ coaches: this.coaches.map((coach) => coach.toJSON()),
635
683
  rating: this.rating,
636
684
  minRating: this.minRating,
637
685
  maxRating: this.maxRating,
@@ -645,6 +693,9 @@ class RatingUser {
645
693
  const ratingUser = new RatingUser();
646
694
  ratingUser.id = iRatingUser.id;
647
695
  ratingUser.name = iRatingUser.name;
696
+ ratingUser.organization = iRatingUser.organization;
697
+ ratingUser.members = iRatingUser.members.map((member) => Person.fromJSON(member));
698
+ ratingUser.coaches = iRatingUser.coaches.map((coach) => Person.fromJSON(coach));
648
699
  ratingUser.rating = iRatingUser.rating;
649
700
  ratingUser.minRating = iRatingUser.minRating;
650
701
  ratingUser.maxRating = iRatingUser.maxRating;
@@ -741,40 +792,54 @@ class Rating {
741
792
  buildRating() {
742
793
  for (const rank of this.ranks) {
743
794
  rank.buildRank();
744
- for (const u of this.users) {
745
- u.oldRating = u.rating;
746
- }
795
+ const ratingCalculator = new RatingCalculator();
747
796
  for (const t of rank.teams) {
748
797
  const id = this.generateTeamId(t);
798
+ let u = null;
749
799
  if (!this.userMap.has(id)) {
750
- const u = new RatingUser();
800
+ u = new RatingUser();
751
801
  u.id = id;
752
802
  u.name = t.name;
803
+ u.organization = t.organization;
804
+ u.members = createPersons(t.members ?? []);
805
+ u.coaches = createPersons(t.coach ?? []);
753
806
  u.rank = t.rank;
754
807
  u.oldRating = this.baseRating;
755
808
  u.UpdateRating(this.baseRating);
756
809
  this.userMap.set(id, u);
757
810
  this.users.push(u);
811
+ ratingCalculator.users.push(u);
812
+ } else {
813
+ u = this.userMap.get(id);
814
+ u.rank = t.rank;
815
+ u.oldRating = u.rating;
816
+ ratingCalculator.users.push(u);
817
+ }
818
+ {
819
+ const h = new RatingHistory();
820
+ h.rank = t.rank;
821
+ h.rating = u.rating;
822
+ h.teamName = t.name;
823
+ h.organization = t.organization;
824
+ h.members = createPersons(t.members ?? []);
825
+ h.coaches = createPersons(t.coach ?? []);
826
+ h.contestID = rank.contest.id;
827
+ h.contestLink = h.contestID;
828
+ h.contestName = rank.contest.name;
829
+ h.contestTime = rank.contest.startTime;
830
+ u.ratingHistories.push(h);
758
831
  }
759
832
  }
760
- const ratingCalculator = new RatingCalculator();
761
- ratingCalculator.users = this.users;
762
833
  ratingCalculator.calculate();
763
- for (const u of this.users) {
764
- const h = new RatingHistory();
765
- h.rank = u.rank;
766
- h.rating = u.rating;
767
- h.contestID = rank.contest.id;
768
- h.contestLink = h.contestID;
769
- h.contestName = rank.contest.name;
770
- h.contestTime = rank.contest.startTime;
771
- u.ratingHistories.push(h);
834
+ for (const u of ratingCalculator.users) {
835
+ u.ratingHistories.at(-1).rating = u.rating;
772
836
  }
773
837
  }
774
838
  }
775
839
  generateTeamId(t) {
776
- if (Array.isArray(t.members) && t.members.length > 0) {
777
- return t.members.join("|");
840
+ const persons = createPersons(t.members ?? []);
841
+ if (persons.length > 0) {
842
+ return persons.map((person) => person.name).join("|");
778
843
  }
779
844
  return `${t.organization}-${t.name}`;
780
845
  }
@@ -2264,6 +2329,7 @@ exports.Giants = Giants;
2264
2329
  exports.GiantsType = GiantsType;
2265
2330
  exports.ICPCStandingsCsvConverter = ICPCStandingsCsvConverter;
2266
2331
  exports.MedalType = MedalType;
2332
+ exports.Person = Person;
2267
2333
  exports.PlaceChartPointData = PlaceChartPointData;
2268
2334
  exports.Problem = Problem;
2269
2335
  exports.ProblemStatistics = ProblemStatistics;
@@ -2283,6 +2349,7 @@ exports.createContest = createContest;
2283
2349
  exports.createContestIndex = createContestIndex;
2284
2350
  exports.createContestIndexList = createContestIndexList;
2285
2351
  exports.createDayJS = createDayJS;
2352
+ exports.createPersons = createPersons;
2286
2353
  exports.createProblem = createProblem;
2287
2354
  exports.createProblems = createProblems;
2288
2355
  exports.createProblemsByProblemIds = createProblemsByProblemIds;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { TimeUnit, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Lang, CalculationOfPenalty, StatusTimeDisplay, MedalPreset, Image, BannerMode, ContestState, Contest as Contest$1, Team as Team$1, Teams as Teams$1, IRatingHistory, ContestIndex as ContestIndex$1 } from '@xcpcio/types';
1
+ import { TimeUnit, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Lang, CalculationOfPenalty, StatusTimeDisplay, MedalPreset, Image, BannerMode, ContestState, Contest as Contest$1, Team as Team$1, Teams as Teams$1, IPerson, IRatingHistory, IRatingUser, IRating, ContestIndex as ContestIndex$1 } 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';
5
- import { IRatingUser, IRating } from '@xcpcio/types/index';
6
5
 
7
6
  declare class Submission {
8
7
  id: string;
@@ -355,9 +354,22 @@ declare class ICPCStandingsCsvConverter {
355
354
  private getMedalCitation;
356
355
  }
357
356
 
357
+ declare class Person {
358
+ name: string;
359
+ constructor(name?: string);
360
+ toJSON(): IPerson;
361
+ static fromJSON(iPerson: IPerson | string): Person;
362
+ }
363
+ type Persons = Array<Person>;
364
+ declare function createPersons(iPersons: string | Array<string>): Persons;
365
+
358
366
  declare class RatingHistory {
359
367
  rank: number;
360
368
  rating: number;
369
+ teamName: string;
370
+ organization: string;
371
+ members: Persons;
372
+ coaches: Persons;
361
373
  contestID: string;
362
374
  contestName: string;
363
375
  contestLink: string;
@@ -371,6 +383,9 @@ type RatingHistories = Array<RatingHistory>;
371
383
  declare class RatingUser {
372
384
  id: string;
373
385
  name: string;
386
+ organization: string;
387
+ members: Persons;
388
+ coaches: Persons;
374
389
  rating: number;
375
390
  minRating: number;
376
391
  maxRating: number;
@@ -458,4 +473,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
458
473
  declare function isPending(status: SubmissionStatus): boolean;
459
474
  declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
460
475
 
461
- export { Award, Awards, Balloon, Balloons, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Ranks, Rating, RatingCalculator, RatingHistories, RatingHistory, RatingUser, RatingUserMap, RatingUsers, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
476
+ export { Award, Awards, Balloon, Balloons, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, Persons, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Ranks, Rating, RatingCalculator, RatingHistories, RatingHistory, RatingUser, RatingUserMap, RatingUsers, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
package/dist/index.mjs CHANGED
@@ -515,6 +515,36 @@ class ICPCStandingsCsvConverter {
515
515
  }
516
516
  }
517
517
 
518
+ class Person {
519
+ constructor(name = "") {
520
+ this.name = name;
521
+ }
522
+ toJSON() {
523
+ return {
524
+ name: this.name
525
+ };
526
+ }
527
+ static fromJSON(iPerson) {
528
+ if (typeof iPerson === "string") {
529
+ iPerson = JSON.parse(iPerson);
530
+ }
531
+ const person = new Person();
532
+ person.name = iPerson.name;
533
+ return person;
534
+ }
535
+ }
536
+ function createPersons(iPersons) {
537
+ if (typeof iPersons === "string") {
538
+ for (const c of " ,\u3001|") {
539
+ if (iPersons.includes(c)) {
540
+ return iPersons.split(c).map((name) => new Person(name));
541
+ }
542
+ }
543
+ return [new Person(iPersons)];
544
+ }
545
+ return iPersons.map((name) => new Person(name));
546
+ }
547
+
518
548
  function calcDirt(attemptedNum, solvedNum) {
519
549
  if (solvedNum === 0) {
520
550
  return 0;
@@ -547,6 +577,10 @@ class RatingHistory {
547
577
  constructor() {
548
578
  this.rank = 0;
549
579
  this.rating = 0;
580
+ this.teamName = "";
581
+ this.organization = "";
582
+ this.members = [];
583
+ this.coaches = [];
550
584
  this.contestID = "";
551
585
  this.contestName = "";
552
586
  this.contestLink = "";
@@ -556,6 +590,10 @@ class RatingHistory {
556
590
  return {
557
591
  rank: this.rank,
558
592
  rating: this.rating,
593
+ teamName: this.teamName,
594
+ organization: this.organization,
595
+ members: this.members.map((member) => member.toJSON()),
596
+ coaches: this.coaches.map((coach) => coach.toJSON()),
559
597
  contestID: this.contestID,
560
598
  contestName: this.contestName,
561
599
  contestLink: this.contestLink,
@@ -569,6 +607,10 @@ class RatingHistory {
569
607
  const ratingHistory = new RatingHistory();
570
608
  ratingHistory.rank = iRatingHistory.rank;
571
609
  ratingHistory.rating = iRatingHistory.rating;
610
+ ratingHistory.teamName = iRatingHistory.teamName;
611
+ ratingHistory.organization = iRatingHistory.organization;
612
+ ratingHistory.members = iRatingHistory.members.map((iMember) => Person.fromJSON(iMember));
613
+ ratingHistory.coaches = iRatingHistory.coaches.map((iCoach) => Person.fromJSON(iCoach));
572
614
  ratingHistory.contestID = iRatingHistory.contestID;
573
615
  ratingHistory.contestName = iRatingHistory.contestName;
574
616
  ratingHistory.contestLink = iRatingHistory.contestLink;
@@ -581,6 +623,9 @@ class RatingUser {
581
623
  constructor() {
582
624
  this.id = "";
583
625
  this.name = "";
626
+ this.organization = "";
627
+ this.members = [];
628
+ this.coaches = [];
584
629
  this.rating = 0;
585
630
  this.minRating = 1061109567;
586
631
  this.maxRating = -1061109567;
@@ -599,6 +644,9 @@ class RatingUser {
599
644
  return {
600
645
  id: this.id,
601
646
  name: this.name,
647
+ organization: this.organization,
648
+ members: this.members.map((member) => member.toJSON()),
649
+ coaches: this.coaches.map((coach) => coach.toJSON()),
602
650
  rating: this.rating,
603
651
  minRating: this.minRating,
604
652
  maxRating: this.maxRating,
@@ -612,6 +660,9 @@ class RatingUser {
612
660
  const ratingUser = new RatingUser();
613
661
  ratingUser.id = iRatingUser.id;
614
662
  ratingUser.name = iRatingUser.name;
663
+ ratingUser.organization = iRatingUser.organization;
664
+ ratingUser.members = iRatingUser.members.map((member) => Person.fromJSON(member));
665
+ ratingUser.coaches = iRatingUser.coaches.map((coach) => Person.fromJSON(coach));
615
666
  ratingUser.rating = iRatingUser.rating;
616
667
  ratingUser.minRating = iRatingUser.minRating;
617
668
  ratingUser.maxRating = iRatingUser.maxRating;
@@ -708,40 +759,54 @@ class Rating {
708
759
  buildRating() {
709
760
  for (const rank of this.ranks) {
710
761
  rank.buildRank();
711
- for (const u of this.users) {
712
- u.oldRating = u.rating;
713
- }
762
+ const ratingCalculator = new RatingCalculator();
714
763
  for (const t of rank.teams) {
715
764
  const id = this.generateTeamId(t);
765
+ let u = null;
716
766
  if (!this.userMap.has(id)) {
717
- const u = new RatingUser();
767
+ u = new RatingUser();
718
768
  u.id = id;
719
769
  u.name = t.name;
770
+ u.organization = t.organization;
771
+ u.members = createPersons(t.members ?? []);
772
+ u.coaches = createPersons(t.coach ?? []);
720
773
  u.rank = t.rank;
721
774
  u.oldRating = this.baseRating;
722
775
  u.UpdateRating(this.baseRating);
723
776
  this.userMap.set(id, u);
724
777
  this.users.push(u);
778
+ ratingCalculator.users.push(u);
779
+ } else {
780
+ u = this.userMap.get(id);
781
+ u.rank = t.rank;
782
+ u.oldRating = u.rating;
783
+ ratingCalculator.users.push(u);
784
+ }
785
+ {
786
+ const h = new RatingHistory();
787
+ h.rank = t.rank;
788
+ h.rating = u.rating;
789
+ h.teamName = t.name;
790
+ h.organization = t.organization;
791
+ h.members = createPersons(t.members ?? []);
792
+ h.coaches = createPersons(t.coach ?? []);
793
+ h.contestID = rank.contest.id;
794
+ h.contestLink = h.contestID;
795
+ h.contestName = rank.contest.name;
796
+ h.contestTime = rank.contest.startTime;
797
+ u.ratingHistories.push(h);
725
798
  }
726
799
  }
727
- const ratingCalculator = new RatingCalculator();
728
- ratingCalculator.users = this.users;
729
800
  ratingCalculator.calculate();
730
- for (const u of this.users) {
731
- const h = new RatingHistory();
732
- h.rank = u.rank;
733
- h.rating = u.rating;
734
- h.contestID = rank.contest.id;
735
- h.contestLink = h.contestID;
736
- h.contestName = rank.contest.name;
737
- h.contestTime = rank.contest.startTime;
738
- u.ratingHistories.push(h);
801
+ for (const u of ratingCalculator.users) {
802
+ u.ratingHistories.at(-1).rating = u.rating;
739
803
  }
740
804
  }
741
805
  }
742
806
  generateTeamId(t) {
743
- if (Array.isArray(t.members) && t.members.length > 0) {
744
- return t.members.join("|");
807
+ const persons = createPersons(t.members ?? []);
808
+ if (persons.length > 0) {
809
+ return persons.map((person) => person.name).join("|");
745
810
  }
746
811
  return `${t.organization}-${t.name}`;
747
812
  }
@@ -2217,4 +2282,4 @@ class Resolver extends Rank {
2217
2282
  }
2218
2283
  }
2219
2284
 
2220
- export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingUser, Resolver, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
2285
+ export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingUser, Resolver, 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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.46.0",
3
+ "version": "0.46.1",
4
4
  "description": "XCPCIO Core",
5
5
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
6
6
  "license": "MIT",
@@ -49,7 +49,7 @@
49
49
  "papaparse": "^5.4.1",
50
50
  "string-width": "^6.1.0",
51
51
  "xlsx-js-style": "^1.2.0",
52
- "@xcpcio/types": "0.46.0"
52
+ "@xcpcio/types": "0.46.1"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@babel/types": "^7.22.4",
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export * from "./battle-of-giants";
9
9
  export * from "./contest-index";
10
10
  export * from "./contest";
11
11
  export * from "./image";
12
+ export * from "./person";
12
13
  export * from "./problem";
13
14
  export * from "./rank-statistics";
14
15
  export * from "./rank";
package/src/person.ts ADDED
@@ -0,0 +1,42 @@
1
+ import type { IPerson } from "@xcpcio/types";
2
+
3
+ export class Person {
4
+ name: string;
5
+
6
+ constructor(name = "") {
7
+ this.name = name;
8
+ }
9
+
10
+ toJSON(): IPerson {
11
+ return {
12
+ name: this.name,
13
+ };
14
+ }
15
+
16
+ static fromJSON(iPerson: IPerson | string): Person {
17
+ if (typeof iPerson === "string") {
18
+ iPerson = JSON.parse(iPerson) as IPerson;
19
+ }
20
+
21
+ const person = new Person();
22
+ person.name = iPerson.name;
23
+
24
+ return person;
25
+ }
26
+ }
27
+
28
+ export type Persons = Array<Person>;
29
+
30
+ export function createPersons(iPersons: string | Array<string>): Persons {
31
+ if (typeof iPersons === "string") {
32
+ for (const c of " ,、|") {
33
+ if (iPersons.includes(c)) {
34
+ return iPersons.split(c).map(name => new Person(name));
35
+ }
36
+ }
37
+
38
+ return [new Person(iPersons)];
39
+ }
40
+
41
+ return iPersons.map(name => new Person(name));
42
+ }
@@ -2,11 +2,19 @@ import type { IRatingHistory } from "@xcpcio/types";
2
2
 
3
3
  import type { dayjs } from "../utils";
4
4
  import { createDayJS } from "../utils";
5
+ import { Person } from "../person";
6
+ import type { Persons } from "../person";
5
7
 
6
8
  export class RatingHistory {
7
9
  rank: number;
8
10
  rating: number;
9
11
 
12
+ teamName: string;
13
+ organization: string;
14
+
15
+ members: Persons;
16
+ coaches: Persons;
17
+
10
18
  contestID: string;
11
19
  contestName: string;
12
20
  contestLink: string;
@@ -16,6 +24,12 @@ export class RatingHistory {
16
24
  this.rank = 0;
17
25
  this.rating = 0;
18
26
 
27
+ this.teamName = "";
28
+ this.organization = "";
29
+
30
+ this.members = [];
31
+ this.coaches = [];
32
+
19
33
  this.contestID = "";
20
34
  this.contestName = "";
21
35
  this.contestLink = "";
@@ -27,6 +41,12 @@ export class RatingHistory {
27
41
  rank: this.rank,
28
42
  rating: this.rating,
29
43
 
44
+ teamName: this.teamName,
45
+ organization: this.organization,
46
+
47
+ members: this.members.map(member => member.toJSON()),
48
+ coaches: this.coaches.map(coach => coach.toJSON()),
49
+
30
50
  contestID: this.contestID,
31
51
  contestName: this.contestName,
32
52
  contestLink: this.contestLink,
@@ -43,6 +63,12 @@ export class RatingHistory {
43
63
  ratingHistory.rank = iRatingHistory.rank;
44
64
  ratingHistory.rating = iRatingHistory.rating;
45
65
 
66
+ ratingHistory.teamName = iRatingHistory.teamName;
67
+ ratingHistory.organization = iRatingHistory.organization;
68
+
69
+ ratingHistory.members = iRatingHistory.members.map(iMember => Person.fromJSON(iMember));
70
+ ratingHistory.coaches = iRatingHistory.coaches.map(iCoach => Person.fromJSON(iCoach));
71
+
46
72
  ratingHistory.contestID = iRatingHistory.contestID;
47
73
  ratingHistory.contestName = iRatingHistory.contestName;
48
74
  ratingHistory.contestLink = iRatingHistory.contestLink;
@@ -1,9 +1,16 @@
1
- import type { IRatingUser } from "@xcpcio/types/index";
1
+ import type { IRatingUser } from "@xcpcio/types";
2
+
3
+ import type { Persons } from "../person";
4
+ import { Person } from "../person";
2
5
  import { type RatingHistories, RatingHistory } from "./rating-history";
3
6
 
4
7
  export class RatingUser {
5
8
  id: string;
6
9
  name: string;
10
+ organization: string;
11
+
12
+ members: Persons;
13
+ coaches: Persons;
7
14
 
8
15
  rating: number;
9
16
  minRating: number;
@@ -20,6 +27,10 @@ export class RatingUser {
20
27
  constructor() {
21
28
  this.id = "";
22
29
  this.name = "";
30
+ this.organization = "";
31
+
32
+ this.members = [];
33
+ this.coaches = [];
23
34
 
24
35
  this.rating = 0;
25
36
  this.minRating = 0x3F3F3F3F;
@@ -44,6 +55,10 @@ export class RatingUser {
44
55
  return {
45
56
  id: this.id,
46
57
  name: this.name,
58
+ organization: this.organization,
59
+
60
+ members: this.members.map(member => member.toJSON()),
61
+ coaches: this.coaches.map(coach => coach.toJSON()),
47
62
 
48
63
  rating: this.rating,
49
64
  minRating: this.minRating,
@@ -62,6 +77,10 @@ export class RatingUser {
62
77
 
63
78
  ratingUser.id = iRatingUser.id;
64
79
  ratingUser.name = iRatingUser.name;
80
+ ratingUser.organization = iRatingUser.organization;
81
+
82
+ ratingUser.members = iRatingUser.members.map(member => Person.fromJSON(member));
83
+ ratingUser.coaches = iRatingUser.coaches.map(coach => Person.fromJSON(coach));
65
84
 
66
85
  ratingUser.rating = iRatingUser.rating;
67
86
  ratingUser.minRating = iRatingUser.minRating;
@@ -1,6 +1,8 @@
1
- import type { IRating } from "@xcpcio/types/index";
1
+ import type { IRating } from "@xcpcio/types";
2
+
2
3
  import type { Ranks } from "../rank";
3
4
  import type { Team } from "../team";
5
+ import { createPersons } from "../person";
4
6
 
5
7
  import { RatingCalculator } from "./rating-calculator";
6
8
  import { RatingHistory } from "./rating-history";
@@ -34,48 +36,69 @@ export class Rating {
34
36
  for (const rank of this.ranks) {
35
37
  rank.buildRank();
36
38
 
37
- for (const u of this.users) {
38
- u.oldRating = u.rating;
39
- }
39
+ const ratingCalculator = new RatingCalculator();
40
40
 
41
41
  for (const t of rank.teams) {
42
42
  const id = this.generateTeamId(t);
43
43
 
44
+ let u = null;
45
+
44
46
  if (!this.userMap.has(id)) {
45
- const u = new RatingUser();
47
+ u = new RatingUser();
46
48
  u.id = id;
47
49
  u.name = t.name;
50
+ u.organization = t.organization;
51
+
52
+ u.members = createPersons(t.members ?? []);
53
+ u.coaches = createPersons(t.coach ?? []);
54
+
48
55
  u.rank = t.rank;
49
56
  u.oldRating = this.baseRating;
50
57
  u.UpdateRating(this.baseRating);
51
58
 
52
59
  this.userMap.set(id, u);
53
60
  this.users.push(u);
61
+
62
+ ratingCalculator.users.push(u);
63
+ } else {
64
+ u = this.userMap.get(id)!;
65
+ u.rank = t.rank;
66
+ u.oldRating = u.rating;
67
+ ratingCalculator.users.push(u);
54
68
  }
55
- }
56
69
 
57
- const ratingCalculator = new RatingCalculator();
58
- ratingCalculator.users = this.users;
59
- ratingCalculator.calculate();
70
+ {
71
+ const h = new RatingHistory();
72
+ h.rank = t.rank;
73
+ h.rating = u.rating;
74
+
75
+ h.teamName = t.name;
76
+ h.organization = t.organization;
77
+
78
+ h.members = createPersons(t.members ?? []);
79
+ h.coaches = createPersons(t.coach ?? []);
60
80
 
61
- for (const u of this.users) {
62
- const h = new RatingHistory();
63
- h.rank = u.rank;
64
- h.rating = u.rating;
81
+ h.contestID = rank.contest.id;
82
+ h.contestLink = h.contestID;
83
+ h.contestName = rank.contest.name;
84
+ h.contestTime = rank.contest.startTime;
65
85
 
66
- h.contestID = rank.contest.id;
67
- h.contestLink = h.contestID;
68
- h.contestName = rank.contest.name;
69
- h.contestTime = rank.contest.startTime;
86
+ u.ratingHistories.push(h);
87
+ }
88
+ }
89
+
90
+ ratingCalculator.calculate();
70
91
 
71
- u.ratingHistories.push(h);
92
+ for (const u of ratingCalculator.users) {
93
+ u.ratingHistories.at(-1)!.rating = u.rating;
72
94
  }
73
95
  }
74
96
  }
75
97
 
76
98
  generateTeamId(t: Team) {
77
- if (Array.isArray(t.members) && t.members.length > 0) {
78
- return t.members.join("|");
99
+ const persons = createPersons(t.members ?? []);
100
+ if (persons.length > 0) {
101
+ return persons.map(person => person.name).join("|");
79
102
  }
80
103
 
81
104
  return `${t.organization}-${t.name}`;