ballrush-core 0.5.0 → 0.5.2
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/mongo/index.d.ts +3 -0
- package/dist/mongo/index.js +3 -0
- package/dist/mongo/schemas/stat-event.schema.d.ts +96 -0
- package/dist/mongo/schemas/stat-event.schema.js +80 -0
- package/dist/mongo/schemas/stat-user-match-history.schema.d.ts +24 -0
- package/dist/mongo/schemas/stat-user-match-history.schema.js +29 -0
- package/dist/mongo/schemas/stat-user-profile.schema.d.ts +51 -0
- package/dist/mongo/schemas/stat-user-profile.schema.js +48 -0
- package/dist/ports/index.d.ts +3 -0
- package/dist/ports/index.js +3 -0
- package/dist/ports/stat-event.repository.d.ts +14 -0
- package/dist/ports/stat-event.repository.js +2 -0
- package/dist/ports/stat-user-match-history.repository.d.ts +19 -0
- package/dist/ports/stat-user-match-history.repository.js +2 -0
- package/dist/ports/stat-user-profile.repository.d.ts +20 -0
- package/dist/ports/stat-user-profile.repository.js +2 -0
- package/dist/repositories/index.d.ts +3 -0
- package/dist/repositories/index.js +3 -0
- package/dist/repositories/mongo/stat-event.repository.d.ts +13 -0
- package/dist/repositories/mongo/stat-event.repository.js +91 -0
- package/dist/repositories/mongo/stat-user-match-history.repository.d.ts +14 -0
- package/dist/repositories/mongo/stat-user-match-history.repository.js +108 -0
- package/dist/repositories/mongo/stat-user-profile.repository.d.ts +14 -0
- package/dist/repositories/mongo/stat-user-profile.repository.js +105 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/types/stat-event.types.d.ts +66 -0
- package/dist/types/stat-event.types.js +6 -0
- package/dist/types/stat-user-match-history.types.d.ts +39 -0
- package/dist/types/stat-user-match-history.types.js +6 -0
- package/dist/types/stat-user-profile.types.d.ts +36 -0
- package/dist/types/stat-user-profile.types.js +6 -0
- package/package.json +1 -1
package/dist/mongo/index.d.ts
CHANGED
|
@@ -7,3 +7,6 @@ export * from "./schemas/stat-group-profile.schema";
|
|
|
7
7
|
export * from "./schemas/stat-group-season.schema";
|
|
8
8
|
export * from "./schemas/stat-group-last-100-games.schema";
|
|
9
9
|
export * from "./schemas/stat-group-activity-chart.schema";
|
|
10
|
+
export * from "./schemas/stat-user-profile.schema";
|
|
11
|
+
export * from "./schemas/stat-user-match-history.schema";
|
|
12
|
+
export * from "./schemas/stat-event.schema";
|
package/dist/mongo/index.js
CHANGED
|
@@ -23,3 +23,6 @@ __exportStar(require("./schemas/stat-group-profile.schema"), exports);
|
|
|
23
23
|
__exportStar(require("./schemas/stat-group-season.schema"), exports);
|
|
24
24
|
__exportStar(require("./schemas/stat-group-last-100-games.schema"), exports);
|
|
25
25
|
__exportStar(require("./schemas/stat-group-activity-chart.schema"), exports);
|
|
26
|
+
__exportStar(require("./schemas/stat-user-profile.schema"), exports);
|
|
27
|
+
__exportStar(require("./schemas/stat-user-match-history.schema"), exports);
|
|
28
|
+
__exportStar(require("./schemas/stat-event.schema"), exports);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Schema } from "mongoose";
|
|
2
|
+
/**
|
|
3
|
+
* Mongoose document interface for StatEventPlayer
|
|
4
|
+
*/
|
|
5
|
+
export interface StatEventPlayerDoc {
|
|
6
|
+
userId: number;
|
|
7
|
+
playerName: string;
|
|
8
|
+
avatarUrl: string;
|
|
9
|
+
position: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Mongoose document interface for StatEventTeam
|
|
13
|
+
*/
|
|
14
|
+
export interface StatEventTeamDoc {
|
|
15
|
+
teamId: number;
|
|
16
|
+
teamName: string;
|
|
17
|
+
totalPoints: number;
|
|
18
|
+
avgTeamRating: number;
|
|
19
|
+
players: StatEventPlayerDoc[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Mongoose document interface for StatEventStandingsRow
|
|
23
|
+
*/
|
|
24
|
+
export interface StatEventStandingsRowDoc {
|
|
25
|
+
rank: number;
|
|
26
|
+
teamName: string;
|
|
27
|
+
played: number;
|
|
28
|
+
wins: number;
|
|
29
|
+
draws: number;
|
|
30
|
+
losses: number;
|
|
31
|
+
goalsFor: number;
|
|
32
|
+
goalsAgainst: number;
|
|
33
|
+
goalDifference: number;
|
|
34
|
+
points: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Mongoose document interface for StatEventMatch
|
|
38
|
+
*/
|
|
39
|
+
export interface StatEventMatchDoc {
|
|
40
|
+
matchId: number;
|
|
41
|
+
matchNumber: number;
|
|
42
|
+
time: string;
|
|
43
|
+
status: string;
|
|
44
|
+
team1Name: string;
|
|
45
|
+
team1Score: number;
|
|
46
|
+
team2Name: string;
|
|
47
|
+
team2Score: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Mongoose document interface for StatEventHeader
|
|
51
|
+
*/
|
|
52
|
+
export interface StatEventHeaderDoc {
|
|
53
|
+
status: 'Finished' | 'In Progress' | 'Upcoming';
|
|
54
|
+
seasonName: string;
|
|
55
|
+
groupName: string;
|
|
56
|
+
eventName: string;
|
|
57
|
+
date: Date;
|
|
58
|
+
timeRange: string;
|
|
59
|
+
location: string;
|
|
60
|
+
winnerName: string | null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Mongoose document interface for StatEventOverviewStats
|
|
64
|
+
*/
|
|
65
|
+
export interface StatEventOverviewStatsDoc {
|
|
66
|
+
totalGoals: number;
|
|
67
|
+
goalsPerMatch: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Mongoose document interface for StatEventOverview
|
|
71
|
+
*/
|
|
72
|
+
export interface StatEventOverviewDoc {
|
|
73
|
+
stats: StatEventOverviewStatsDoc;
|
|
74
|
+
standings: StatEventStandingsRowDoc[];
|
|
75
|
+
teams: StatEventTeamDoc[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Mongoose document interface for StatEvent
|
|
79
|
+
*/
|
|
80
|
+
export interface StatEventDoc {
|
|
81
|
+
eventId: number;
|
|
82
|
+
header: StatEventHeaderDoc;
|
|
83
|
+
overview: StatEventOverviewDoc;
|
|
84
|
+
matches: StatEventMatchDoc[];
|
|
85
|
+
calculatedAt: Date;
|
|
86
|
+
version: number;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Factory function to create StatEvent schema
|
|
90
|
+
* Collection: stat_events
|
|
91
|
+
*/
|
|
92
|
+
export declare function createStatEventSchema(): Schema<StatEventDoc, import("mongoose").Model<StatEventDoc, any, any, any, import("mongoose").Document<unknown, any, StatEventDoc> & StatEventDoc & {
|
|
93
|
+
_id: import("mongoose").Types.ObjectId;
|
|
94
|
+
}, any>, {}, {}, {}, {}, import("mongoose").DefaultSchemaOptions, StatEventDoc, import("mongoose").Document<unknown, {}, import("mongoose").FlatRecord<StatEventDoc>> & import("mongoose").FlatRecord<StatEventDoc> & {
|
|
95
|
+
_id: import("mongoose").Types.ObjectId;
|
|
96
|
+
}>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createStatEventSchema = createStatEventSchema;
|
|
4
|
+
const mongoose_1 = require("mongoose");
|
|
5
|
+
/**
|
|
6
|
+
* Factory function to create StatEvent schema
|
|
7
|
+
* Collection: stat_events
|
|
8
|
+
*/
|
|
9
|
+
function createStatEventSchema() {
|
|
10
|
+
const PlayerSchema = new mongoose_1.Schema({
|
|
11
|
+
userId: { type: Number, required: true },
|
|
12
|
+
playerName: { type: String, required: true },
|
|
13
|
+
avatarUrl: { type: String, required: true },
|
|
14
|
+
position: { type: String, required: true },
|
|
15
|
+
}, { _id: false });
|
|
16
|
+
const TeamSchema = new mongoose_1.Schema({
|
|
17
|
+
teamId: { type: Number, required: true },
|
|
18
|
+
teamName: { type: String, required: true },
|
|
19
|
+
totalPoints: { type: Number, required: true, min: 0, default: 0 },
|
|
20
|
+
avgTeamRating: { type: Number, required: true, min: 0, default: 0 },
|
|
21
|
+
players: { type: [PlayerSchema], default: [] },
|
|
22
|
+
}, { _id: false });
|
|
23
|
+
const StandingsRowSchema = new mongoose_1.Schema({
|
|
24
|
+
rank: { type: Number, required: true, min: 1 },
|
|
25
|
+
teamName: { type: String, required: true },
|
|
26
|
+
played: { type: Number, required: true, min: 0, default: 0 },
|
|
27
|
+
wins: { type: Number, required: true, min: 0, default: 0 },
|
|
28
|
+
draws: { type: Number, required: true, min: 0, default: 0 },
|
|
29
|
+
losses: { type: Number, required: true, min: 0, default: 0 },
|
|
30
|
+
goalsFor: { type: Number, required: true, min: 0, default: 0 },
|
|
31
|
+
goalsAgainst: { type: Number, required: true, min: 0, default: 0 },
|
|
32
|
+
goalDifference: { type: Number, required: true, default: 0 },
|
|
33
|
+
points: { type: Number, required: true, min: 0, default: 0 },
|
|
34
|
+
}, { _id: false });
|
|
35
|
+
const MatchSchema = new mongoose_1.Schema({
|
|
36
|
+
matchId: { type: Number, required: true },
|
|
37
|
+
matchNumber: { type: Number, required: true, min: 1 },
|
|
38
|
+
time: { type: String, required: true },
|
|
39
|
+
status: { type: String, required: true },
|
|
40
|
+
team1Name: { type: String, required: true },
|
|
41
|
+
team1Score: { type: Number, required: true, min: 0, default: 0 },
|
|
42
|
+
team2Name: { type: String, required: true },
|
|
43
|
+
team2Score: { type: Number, required: true, min: 0, default: 0 },
|
|
44
|
+
}, { _id: false });
|
|
45
|
+
const HeaderSchema = new mongoose_1.Schema({
|
|
46
|
+
status: { type: String, enum: ['Finished', 'In Progress', 'Upcoming'], required: true },
|
|
47
|
+
seasonName: { type: String, required: true },
|
|
48
|
+
groupName: { type: String, required: true },
|
|
49
|
+
eventName: { type: String, required: true },
|
|
50
|
+
date: { type: Date, required: true },
|
|
51
|
+
timeRange: { type: String, required: true },
|
|
52
|
+
location: { type: String, required: true },
|
|
53
|
+
winnerName: { type: String, default: null },
|
|
54
|
+
}, { _id: false });
|
|
55
|
+
const OverviewStatsSchema = new mongoose_1.Schema({
|
|
56
|
+
totalGoals: { type: Number, required: true, min: 0, default: 0 },
|
|
57
|
+
goalsPerMatch: { type: Number, required: true, min: 0, default: 0 },
|
|
58
|
+
}, { _id: false });
|
|
59
|
+
const OverviewSchema = new mongoose_1.Schema({
|
|
60
|
+
stats: { type: OverviewStatsSchema, required: true },
|
|
61
|
+
standings: { type: [StandingsRowSchema], default: [] },
|
|
62
|
+
teams: { type: [TeamSchema], default: [] },
|
|
63
|
+
}, { _id: false });
|
|
64
|
+
const StatEventSchema = new mongoose_1.Schema({
|
|
65
|
+
eventId: { type: Number, required: true, unique: true, index: true },
|
|
66
|
+
header: { type: HeaderSchema, required: true },
|
|
67
|
+
overview: { type: OverviewSchema, required: true },
|
|
68
|
+
matches: { type: [MatchSchema], default: [] },
|
|
69
|
+
calculatedAt: { type: Date, default: Date.now },
|
|
70
|
+
version: { type: Number, required: true, default: 1, min: 1 },
|
|
71
|
+
}, {
|
|
72
|
+
collection: 'stat_events',
|
|
73
|
+
versionKey: false,
|
|
74
|
+
});
|
|
75
|
+
// Index for fast lookup by eventId
|
|
76
|
+
StatEventSchema.index({ eventId: 1 }, { unique: true });
|
|
77
|
+
// Index for cache invalidation by calculatedAt
|
|
78
|
+
StatEventSchema.index({ calculatedAt: -1 });
|
|
79
|
+
return StatEventSchema;
|
|
80
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Schema } from "mongoose";
|
|
2
|
+
/**
|
|
3
|
+
* Mongoose document interface for StatUserMatchHistory
|
|
4
|
+
*/
|
|
5
|
+
export interface StatUserMatchHistoryDoc {
|
|
6
|
+
userId: number;
|
|
7
|
+
groupId: number;
|
|
8
|
+
eventId: number;
|
|
9
|
+
result: 'Win' | 'Loss' | 'Draw';
|
|
10
|
+
matchup: string;
|
|
11
|
+
score: string;
|
|
12
|
+
date: Date;
|
|
13
|
+
seasonName: string;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Factory function to create StatUserMatchHistory schema
|
|
18
|
+
* Collection: stat_user_match_history
|
|
19
|
+
*/
|
|
20
|
+
export declare function createStatUserMatchHistorySchema(): Schema<StatUserMatchHistoryDoc, import("mongoose").Model<StatUserMatchHistoryDoc, any, any, any, import("mongoose").Document<unknown, any, StatUserMatchHistoryDoc> & StatUserMatchHistoryDoc & {
|
|
21
|
+
_id: import("mongoose").Types.ObjectId;
|
|
22
|
+
}, any>, {}, {}, {}, {}, import("mongoose").DefaultSchemaOptions, StatUserMatchHistoryDoc, import("mongoose").Document<unknown, {}, import("mongoose").FlatRecord<StatUserMatchHistoryDoc>> & import("mongoose").FlatRecord<StatUserMatchHistoryDoc> & {
|
|
23
|
+
_id: import("mongoose").Types.ObjectId;
|
|
24
|
+
}>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createStatUserMatchHistorySchema = createStatUserMatchHistorySchema;
|
|
4
|
+
const mongoose_1 = require("mongoose");
|
|
5
|
+
/**
|
|
6
|
+
* Factory function to create StatUserMatchHistory schema
|
|
7
|
+
* Collection: stat_user_match_history
|
|
8
|
+
*/
|
|
9
|
+
function createStatUserMatchHistorySchema() {
|
|
10
|
+
const StatUserMatchHistorySchema = new mongoose_1.Schema({
|
|
11
|
+
userId: { type: Number, required: true, index: true },
|
|
12
|
+
groupId: { type: Number, required: true, index: true },
|
|
13
|
+
eventId: { type: Number, required: true },
|
|
14
|
+
result: { type: String, enum: ['Win', 'Loss', 'Draw'], required: true },
|
|
15
|
+
matchup: { type: String, required: true },
|
|
16
|
+
score: { type: String, required: true },
|
|
17
|
+
date: { type: Date, required: true },
|
|
18
|
+
seasonName: { type: String, required: true },
|
|
19
|
+
createdAt: { type: Date, default: Date.now },
|
|
20
|
+
}, {
|
|
21
|
+
collection: 'stat_user_match_history',
|
|
22
|
+
versionKey: false,
|
|
23
|
+
});
|
|
24
|
+
// Compound index for efficient queries (userId + groupId + date DESC)
|
|
25
|
+
StatUserMatchHistorySchema.index({ userId: 1, groupId: 1, date: -1 });
|
|
26
|
+
// Compound index for season filtering (userId + groupId + seasonName + date DESC)
|
|
27
|
+
StatUserMatchHistorySchema.index({ userId: 1, groupId: 1, seasonName: 1, date: -1 });
|
|
28
|
+
return StatUserMatchHistorySchema;
|
|
29
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Schema } from "mongoose";
|
|
2
|
+
/**
|
|
3
|
+
* Mongoose sub-schema for SkillHistoryPoint
|
|
4
|
+
*/
|
|
5
|
+
export interface SkillHistoryPointDoc {
|
|
6
|
+
date: Date;
|
|
7
|
+
earnedRating: number | null;
|
|
8
|
+
manualAdjustment: number | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Mongoose sub-schema for ProfileAchievement
|
|
12
|
+
*/
|
|
13
|
+
export interface ProfileAchievementDoc {
|
|
14
|
+
icon: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
count: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Mongoose document interface for StatUserProfile
|
|
21
|
+
*/
|
|
22
|
+
export interface StatUserProfileDoc {
|
|
23
|
+
userId: number;
|
|
24
|
+
groupId: number;
|
|
25
|
+
username: string;
|
|
26
|
+
fullName: string;
|
|
27
|
+
avatarUrl: string;
|
|
28
|
+
position: string;
|
|
29
|
+
currentSkillRating: number;
|
|
30
|
+
groupName: string;
|
|
31
|
+
gamesCount: number;
|
|
32
|
+
wins: number;
|
|
33
|
+
losses: number;
|
|
34
|
+
draws: number;
|
|
35
|
+
winPercentage: number;
|
|
36
|
+
goalsFor: number;
|
|
37
|
+
goalsAgainst: number;
|
|
38
|
+
eventsCount: number;
|
|
39
|
+
skillHistory: SkillHistoryPointDoc[];
|
|
40
|
+
achievements: ProfileAchievementDoc[];
|
|
41
|
+
lastUpdated: Date;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Factory function to create StatUserProfile schema
|
|
45
|
+
* Collection: stat_user_profile
|
|
46
|
+
*/
|
|
47
|
+
export declare function createStatUserProfileSchema(): Schema<StatUserProfileDoc, import("mongoose").Model<StatUserProfileDoc, any, any, any, import("mongoose").Document<unknown, any, StatUserProfileDoc> & StatUserProfileDoc & {
|
|
48
|
+
_id: import("mongoose").Types.ObjectId;
|
|
49
|
+
}, any>, {}, {}, {}, {}, import("mongoose").DefaultSchemaOptions, StatUserProfileDoc, import("mongoose").Document<unknown, {}, import("mongoose").FlatRecord<StatUserProfileDoc>> & import("mongoose").FlatRecord<StatUserProfileDoc> & {
|
|
50
|
+
_id: import("mongoose").Types.ObjectId;
|
|
51
|
+
}>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createStatUserProfileSchema = createStatUserProfileSchema;
|
|
4
|
+
const mongoose_1 = require("mongoose");
|
|
5
|
+
/**
|
|
6
|
+
* Factory function to create StatUserProfile schema
|
|
7
|
+
* Collection: stat_user_profile
|
|
8
|
+
*/
|
|
9
|
+
function createStatUserProfileSchema() {
|
|
10
|
+
const SkillHistoryPointSchema = new mongoose_1.Schema({
|
|
11
|
+
date: { type: Date, required: true },
|
|
12
|
+
earnedRating: { type: Number, default: null },
|
|
13
|
+
manualAdjustment: { type: Number, default: null },
|
|
14
|
+
}, { _id: false });
|
|
15
|
+
const ProfileAchievementSchema = new mongoose_1.Schema({
|
|
16
|
+
icon: { type: String, required: true },
|
|
17
|
+
name: { type: String, required: true },
|
|
18
|
+
description: { type: String, required: true },
|
|
19
|
+
count: { type: Number, required: true, min: 0, default: 0 },
|
|
20
|
+
}, { _id: false });
|
|
21
|
+
const StatUserProfileSchema = new mongoose_1.Schema({
|
|
22
|
+
userId: { type: Number, required: true, index: true },
|
|
23
|
+
groupId: { type: Number, required: true, index: true },
|
|
24
|
+
username: { type: String, required: true },
|
|
25
|
+
fullName: { type: String, required: true },
|
|
26
|
+
avatarUrl: { type: String, default: '' },
|
|
27
|
+
position: { type: String, default: '' },
|
|
28
|
+
currentSkillRating: { type: Number, required: true, default: 0 },
|
|
29
|
+
groupName: { type: String, required: true },
|
|
30
|
+
gamesCount: { type: Number, required: true, min: 0, default: 0 },
|
|
31
|
+
wins: { type: Number, required: true, min: 0, default: 0 },
|
|
32
|
+
losses: { type: Number, required: true, min: 0, default: 0 },
|
|
33
|
+
draws: { type: Number, required: true, min: 0, default: 0 },
|
|
34
|
+
winPercentage: { type: Number, required: true, min: 0, max: 100, default: 0 },
|
|
35
|
+
goalsFor: { type: Number, required: true, min: 0, default: 0 },
|
|
36
|
+
goalsAgainst: { type: Number, required: true, min: 0, default: 0 },
|
|
37
|
+
eventsCount: { type: Number, required: true, min: 0, default: 0 },
|
|
38
|
+
skillHistory: { type: [SkillHistoryPointSchema], default: [] },
|
|
39
|
+
achievements: { type: [ProfileAchievementSchema], default: [] },
|
|
40
|
+
lastUpdated: { type: Date, default: Date.now },
|
|
41
|
+
}, {
|
|
42
|
+
collection: 'stat_user_profile',
|
|
43
|
+
versionKey: false,
|
|
44
|
+
});
|
|
45
|
+
// Create compound unique index for userId + groupId
|
|
46
|
+
StatUserProfileSchema.index({ userId: 1, groupId: 1 }, { unique: true });
|
|
47
|
+
return StatUserProfileSchema;
|
|
48
|
+
}
|
package/dist/ports/index.d.ts
CHANGED
|
@@ -7,3 +7,6 @@ export * from "./stat-group-profile.repository";
|
|
|
7
7
|
export * from "./stat-group-season.repository";
|
|
8
8
|
export * from "./stat-group-last-100-games.repository";
|
|
9
9
|
export * from "./stat-group-activity-chart.repository";
|
|
10
|
+
export * from "./stat-user-profile.repository";
|
|
11
|
+
export * from "./stat-user-match-history.repository";
|
|
12
|
+
export * from "./stat-event.repository";
|
package/dist/ports/index.js
CHANGED
|
@@ -23,3 +23,6 @@ __exportStar(require("./stat-group-profile.repository"), exports);
|
|
|
23
23
|
__exportStar(require("./stat-group-season.repository"), exports);
|
|
24
24
|
__exportStar(require("./stat-group-last-100-games.repository"), exports);
|
|
25
25
|
__exportStar(require("./stat-group-activity-chart.repository"), exports);
|
|
26
|
+
__exportStar(require("./stat-user-profile.repository"), exports);
|
|
27
|
+
__exportStar(require("./stat-user-match-history.repository"), exports);
|
|
28
|
+
__exportStar(require("./stat-event.repository"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StatEvent } from "../types/stat-event.types";
|
|
2
|
+
/**
|
|
3
|
+
* Repository interface for StatEvent
|
|
4
|
+
* Provides pre-aggregated event data including standings, statistics,
|
|
5
|
+
* and enriched rosters/matches for the Event Page
|
|
6
|
+
*/
|
|
7
|
+
export interface StatEventRepository {
|
|
8
|
+
/**
|
|
9
|
+
* Finds complete event data by event ID
|
|
10
|
+
* @param eventId - The event ID
|
|
11
|
+
* @returns Complete event data or null if not found
|
|
12
|
+
*/
|
|
13
|
+
findEventById(eventId: number): Promise<StatEvent | null>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { StatUserMatchHistory, MatchHistoryFilter, MatchHistoryOptions, MatchHistoryResult } from "../types/stat-user-match-history.types";
|
|
2
|
+
/**
|
|
3
|
+
* Repository interface for StatUserMatchHistory
|
|
4
|
+
* Provides paginated and filterable match history data
|
|
5
|
+
*/
|
|
6
|
+
export interface StatUserMatchHistoryRepository {
|
|
7
|
+
/**
|
|
8
|
+
* Find paginated match history for a user in a group
|
|
9
|
+
* @param filter - User ID, group ID, and optional season filter
|
|
10
|
+
* @param options - Pagination options
|
|
11
|
+
* @returns Paginated match history with metadata
|
|
12
|
+
*/
|
|
13
|
+
find(filter: MatchHistoryFilter, options: MatchHistoryOptions): Promise<MatchHistoryResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new match history item
|
|
16
|
+
* @param item - Match history item to save
|
|
17
|
+
*/
|
|
18
|
+
create(item: StatUserMatchHistory): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StatUserProfile } from "../types/stat-user-profile.types";
|
|
2
|
+
/**
|
|
3
|
+
* Repository interface for StatUserProfile
|
|
4
|
+
* Provides pre-aggregated user profile data including basic info,
|
|
5
|
+
* statistics, skill history, and achievements
|
|
6
|
+
*/
|
|
7
|
+
export interface StatUserProfileRepository {
|
|
8
|
+
/**
|
|
9
|
+
* Find user profile data for a specific user in a specific group
|
|
10
|
+
* @param userId - User ID
|
|
11
|
+
* @param groupId - Group ID
|
|
12
|
+
* @returns User profile data or null if not found
|
|
13
|
+
*/
|
|
14
|
+
findByUserAndGroup(userId: number, groupId: number): Promise<StatUserProfile | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Create or update user profile data
|
|
17
|
+
* @param profile - User profile data to save
|
|
18
|
+
*/
|
|
19
|
+
save(profile: StatUserProfile): Promise<void>;
|
|
20
|
+
}
|
|
@@ -7,3 +7,6 @@ export * from "./mongo/stat-group-profile.repository";
|
|
|
7
7
|
export * from "./mongo/stat-group-season.repository";
|
|
8
8
|
export * from "./mongo/stat-group-last-100-games.repository";
|
|
9
9
|
export * from "./mongo/stat-group-activity-chart.repository";
|
|
10
|
+
export * from "./mongo/stat-user-profile.repository";
|
|
11
|
+
export * from "./mongo/stat-user-match-history.repository";
|
|
12
|
+
export * from "./mongo/stat-event.repository";
|
|
@@ -23,3 +23,6 @@ __exportStar(require("./mongo/stat-group-profile.repository"), exports);
|
|
|
23
23
|
__exportStar(require("./mongo/stat-group-season.repository"), exports);
|
|
24
24
|
__exportStar(require("./mongo/stat-group-last-100-games.repository"), exports);
|
|
25
25
|
__exportStar(require("./mongo/stat-group-activity-chart.repository"), exports);
|
|
26
|
+
__exportStar(require("./mongo/stat-user-profile.repository"), exports);
|
|
27
|
+
__exportStar(require("./mongo/stat-user-match-history.repository"), exports);
|
|
28
|
+
__exportStar(require("./mongo/stat-event.repository"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Model } from "mongoose";
|
|
2
|
+
import type { StatEventRepository } from "../../ports/stat-event.repository";
|
|
3
|
+
import type { StatEventDoc } from "../../mongo/schemas/stat-event.schema";
|
|
4
|
+
import type { StatEvent } from "../../types/stat-event.types";
|
|
5
|
+
/**
|
|
6
|
+
* MongoDB implementation of StatEventRepository
|
|
7
|
+
* Provides read-only access to pre-aggregated event data
|
|
8
|
+
*/
|
|
9
|
+
export declare class MongoStatEventRepository implements StatEventRepository {
|
|
10
|
+
private readonly model;
|
|
11
|
+
constructor(model: Model<StatEventDoc>);
|
|
12
|
+
findEventById(eventId: number): Promise<StatEvent | null>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoStatEventRepository = void 0;
|
|
4
|
+
const errors_1 = require("../../errors");
|
|
5
|
+
/**
|
|
6
|
+
* MongoDB implementation of StatEventRepository
|
|
7
|
+
* Provides read-only access to pre-aggregated event data
|
|
8
|
+
*/
|
|
9
|
+
class MongoStatEventRepository {
|
|
10
|
+
constructor(model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
}
|
|
13
|
+
async findEventById(eventId) {
|
|
14
|
+
try {
|
|
15
|
+
// Validate input
|
|
16
|
+
if (!eventId || eventId === 0) {
|
|
17
|
+
throw new errors_1.ValidationError('StatEvent', 'eventId', eventId, 'must be a non-zero number');
|
|
18
|
+
}
|
|
19
|
+
// Find event by ID
|
|
20
|
+
const doc = await this.model
|
|
21
|
+
.findOne({ eventId })
|
|
22
|
+
.lean();
|
|
23
|
+
if (!doc) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
// Map document to domain type
|
|
27
|
+
return {
|
|
28
|
+
eventId: doc.eventId,
|
|
29
|
+
header: {
|
|
30
|
+
status: doc.header.status,
|
|
31
|
+
seasonName: doc.header.seasonName,
|
|
32
|
+
groupName: doc.header.groupName,
|
|
33
|
+
eventName: doc.header.eventName,
|
|
34
|
+
date: doc.header.date,
|
|
35
|
+
timeRange: doc.header.timeRange,
|
|
36
|
+
location: doc.header.location,
|
|
37
|
+
winnerName: doc.header.winnerName,
|
|
38
|
+
},
|
|
39
|
+
overview: {
|
|
40
|
+
stats: {
|
|
41
|
+
totalGoals: doc.overview.stats.totalGoals,
|
|
42
|
+
goalsPerMatch: doc.overview.stats.goalsPerMatch,
|
|
43
|
+
},
|
|
44
|
+
standings: doc.overview.standings.map(s => ({
|
|
45
|
+
rank: s.rank,
|
|
46
|
+
teamName: s.teamName,
|
|
47
|
+
played: s.played,
|
|
48
|
+
wins: s.wins,
|
|
49
|
+
draws: s.draws,
|
|
50
|
+
losses: s.losses,
|
|
51
|
+
goalsFor: s.goalsFor,
|
|
52
|
+
goalsAgainst: s.goalsAgainst,
|
|
53
|
+
goalDifference: s.goalDifference,
|
|
54
|
+
points: s.points,
|
|
55
|
+
})),
|
|
56
|
+
teams: doc.overview.teams.map(t => ({
|
|
57
|
+
teamId: t.teamId,
|
|
58
|
+
teamName: t.teamName,
|
|
59
|
+
totalPoints: t.totalPoints,
|
|
60
|
+
avgTeamRating: t.avgTeamRating,
|
|
61
|
+
players: t.players.map(p => ({
|
|
62
|
+
userId: p.userId,
|
|
63
|
+
playerName: p.playerName,
|
|
64
|
+
avatarUrl: p.avatarUrl,
|
|
65
|
+
position: p.position,
|
|
66
|
+
})),
|
|
67
|
+
})),
|
|
68
|
+
},
|
|
69
|
+
matches: doc.matches.map(m => ({
|
|
70
|
+
matchId: m.matchId,
|
|
71
|
+
matchNumber: m.matchNumber,
|
|
72
|
+
time: m.time,
|
|
73
|
+
status: m.status,
|
|
74
|
+
team1Name: m.team1Name,
|
|
75
|
+
team1Score: m.team1Score,
|
|
76
|
+
team2Name: m.team2Name,
|
|
77
|
+
team2Score: m.team2Score,
|
|
78
|
+
})),
|
|
79
|
+
calculatedAt: doc.calculatedAt,
|
|
80
|
+
version: doc.version,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof errors_1.ValidationError) {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
throw new errors_1.QueryError('findEventById', 'StatEvent', eventId, error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.MongoStatEventRepository = MongoStatEventRepository;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Model } from "mongoose";
|
|
2
|
+
import type { StatUserMatchHistoryRepository } from "../../ports/stat-user-match-history.repository";
|
|
3
|
+
import type { StatUserMatchHistoryDoc } from "../../mongo/schemas/stat-user-match-history.schema";
|
|
4
|
+
import type { StatUserMatchHistory, MatchHistoryFilter, MatchHistoryOptions, MatchHistoryResult } from "../../types/stat-user-match-history.types";
|
|
5
|
+
/**
|
|
6
|
+
* MongoDB implementation of StatUserMatchHistoryRepository
|
|
7
|
+
* Provides paginated and filterable match history data
|
|
8
|
+
*/
|
|
9
|
+
export declare class MongoStatUserMatchHistoryRepository implements StatUserMatchHistoryRepository {
|
|
10
|
+
private readonly model;
|
|
11
|
+
constructor(model: Model<StatUserMatchHistoryDoc>);
|
|
12
|
+
find(filter: MatchHistoryFilter, options: MatchHistoryOptions): Promise<MatchHistoryResult>;
|
|
13
|
+
create(item: StatUserMatchHistory): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoStatUserMatchHistoryRepository = void 0;
|
|
4
|
+
const errors_1 = require("../../errors");
|
|
5
|
+
/**
|
|
6
|
+
* MongoDB implementation of StatUserMatchHistoryRepository
|
|
7
|
+
* Provides paginated and filterable match history data
|
|
8
|
+
*/
|
|
9
|
+
class MongoStatUserMatchHistoryRepository {
|
|
10
|
+
constructor(model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
}
|
|
13
|
+
async find(filter, options) {
|
|
14
|
+
try {
|
|
15
|
+
// Validate input
|
|
16
|
+
if (!filter.userId || filter.userId === 0) {
|
|
17
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'userId', filter.userId, 'must be a non-zero number');
|
|
18
|
+
}
|
|
19
|
+
if (!filter.groupId || filter.groupId === 0) {
|
|
20
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'groupId', filter.groupId, 'must be a non-zero number');
|
|
21
|
+
}
|
|
22
|
+
if (!options.page || options.page < 1) {
|
|
23
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'page', options.page, 'must be at least 1');
|
|
24
|
+
}
|
|
25
|
+
if (!options.limit || options.limit < 1) {
|
|
26
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'limit', options.limit, 'must be at least 1');
|
|
27
|
+
}
|
|
28
|
+
// Build query
|
|
29
|
+
const query = {
|
|
30
|
+
userId: filter.userId,
|
|
31
|
+
groupId: filter.groupId,
|
|
32
|
+
};
|
|
33
|
+
// Add season filter if not "All Seasons"
|
|
34
|
+
if (filter.season && filter.season !== 'All Seasons') {
|
|
35
|
+
query.seasonName = filter.season;
|
|
36
|
+
}
|
|
37
|
+
// Count total matches
|
|
38
|
+
const totalMatches = await this.model.countDocuments(query);
|
|
39
|
+
// Calculate pagination
|
|
40
|
+
const totalPages = Math.ceil(totalMatches / options.limit);
|
|
41
|
+
const skip = (options.page - 1) * options.limit;
|
|
42
|
+
// Fetch paginated results (sorted by date DESC)
|
|
43
|
+
const docs = await this.model
|
|
44
|
+
.find(query)
|
|
45
|
+
.sort({ date: -1 })
|
|
46
|
+
.skip(skip)
|
|
47
|
+
.limit(options.limit)
|
|
48
|
+
.lean();
|
|
49
|
+
// Map documents to domain types
|
|
50
|
+
const matches = docs.map(doc => ({
|
|
51
|
+
userId: doc.userId,
|
|
52
|
+
groupId: doc.groupId,
|
|
53
|
+
eventId: doc.eventId,
|
|
54
|
+
result: doc.result,
|
|
55
|
+
matchup: doc.matchup,
|
|
56
|
+
score: doc.score,
|
|
57
|
+
date: doc.date,
|
|
58
|
+
seasonName: doc.seasonName,
|
|
59
|
+
createdAt: doc.createdAt,
|
|
60
|
+
}));
|
|
61
|
+
return {
|
|
62
|
+
matches,
|
|
63
|
+
totalMatches,
|
|
64
|
+
totalPages,
|
|
65
|
+
currentPage: options.page,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error instanceof errors_1.ValidationError) {
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
throw new errors_1.QueryError('find', 'StatUserMatchHistory', `${filter.userId}:${filter.groupId}`, error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async create(item) {
|
|
76
|
+
try {
|
|
77
|
+
// Validate input
|
|
78
|
+
if (!item.userId || item.userId === 0) {
|
|
79
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'userId', item.userId, 'must be a non-zero number');
|
|
80
|
+
}
|
|
81
|
+
if (!item.groupId || item.groupId === 0) {
|
|
82
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'groupId', item.groupId, 'must be a non-zero number');
|
|
83
|
+
}
|
|
84
|
+
if (!item.eventId || item.eventId === 0) {
|
|
85
|
+
throw new errors_1.ValidationError('StatUserMatchHistory', 'eventId', item.eventId, 'must be a non-zero number');
|
|
86
|
+
}
|
|
87
|
+
// Create new match history item
|
|
88
|
+
await this.model.create({
|
|
89
|
+
userId: item.userId,
|
|
90
|
+
groupId: item.groupId,
|
|
91
|
+
eventId: item.eventId,
|
|
92
|
+
result: item.result,
|
|
93
|
+
matchup: item.matchup,
|
|
94
|
+
score: item.score,
|
|
95
|
+
date: item.date,
|
|
96
|
+
seasonName: item.seasonName,
|
|
97
|
+
createdAt: item.createdAt,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error instanceof errors_1.ValidationError) {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
throw new errors_1.QueryError('create', 'StatUserMatchHistory', `${item.userId}:${item.groupId}:${item.eventId}`, error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.MongoStatUserMatchHistoryRepository = MongoStatUserMatchHistoryRepository;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Model } from "mongoose";
|
|
2
|
+
import type { StatUserProfileRepository } from "../../ports/stat-user-profile.repository";
|
|
3
|
+
import type { StatUserProfileDoc } from "../../mongo/schemas/stat-user-profile.schema";
|
|
4
|
+
import type { StatUserProfile } from "../../types/stat-user-profile.types";
|
|
5
|
+
/**
|
|
6
|
+
* MongoDB implementation of StatUserProfileRepository
|
|
7
|
+
* Provides read and write access to pre-aggregated user profile data
|
|
8
|
+
*/
|
|
9
|
+
export declare class MongoStatUserProfileRepository implements StatUserProfileRepository {
|
|
10
|
+
private readonly model;
|
|
11
|
+
constructor(model: Model<StatUserProfileDoc>);
|
|
12
|
+
findByUserAndGroup(userId: number, groupId: number): Promise<StatUserProfile | null>;
|
|
13
|
+
save(profile: StatUserProfile): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MongoStatUserProfileRepository = void 0;
|
|
4
|
+
const errors_1 = require("../../errors");
|
|
5
|
+
/**
|
|
6
|
+
* MongoDB implementation of StatUserProfileRepository
|
|
7
|
+
* Provides read and write access to pre-aggregated user profile data
|
|
8
|
+
*/
|
|
9
|
+
class MongoStatUserProfileRepository {
|
|
10
|
+
constructor(model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
}
|
|
13
|
+
async findByUserAndGroup(userId, groupId) {
|
|
14
|
+
try {
|
|
15
|
+
// Validate input
|
|
16
|
+
if (!userId || userId === 0) {
|
|
17
|
+
throw new errors_1.ValidationError('StatUserProfile', 'userId', userId, 'must be a non-zero number');
|
|
18
|
+
}
|
|
19
|
+
if (!groupId || groupId === 0) {
|
|
20
|
+
throw new errors_1.ValidationError('StatUserProfile', 'groupId', groupId, 'must be a non-zero number');
|
|
21
|
+
}
|
|
22
|
+
const doc = await this.model.findOne({ userId, groupId }).lean();
|
|
23
|
+
if (!doc) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
// Map document to domain type
|
|
27
|
+
return {
|
|
28
|
+
userId: doc.userId,
|
|
29
|
+
groupId: doc.groupId,
|
|
30
|
+
username: doc.username,
|
|
31
|
+
fullName: doc.fullName,
|
|
32
|
+
avatarUrl: doc.avatarUrl,
|
|
33
|
+
position: doc.position,
|
|
34
|
+
currentSkillRating: doc.currentSkillRating,
|
|
35
|
+
groupName: doc.groupName,
|
|
36
|
+
gamesCount: doc.gamesCount,
|
|
37
|
+
wins: doc.wins,
|
|
38
|
+
losses: doc.losses,
|
|
39
|
+
draws: doc.draws,
|
|
40
|
+
winPercentage: doc.winPercentage,
|
|
41
|
+
goalsFor: doc.goalsFor,
|
|
42
|
+
goalsAgainst: doc.goalsAgainst,
|
|
43
|
+
eventsCount: doc.eventsCount,
|
|
44
|
+
skillHistory: doc.skillHistory.map(point => ({
|
|
45
|
+
date: point.date,
|
|
46
|
+
earnedRating: point.earnedRating,
|
|
47
|
+
manualAdjustment: point.manualAdjustment,
|
|
48
|
+
})),
|
|
49
|
+
achievements: doc.achievements.map(achievement => ({
|
|
50
|
+
icon: achievement.icon,
|
|
51
|
+
name: achievement.name,
|
|
52
|
+
description: achievement.description,
|
|
53
|
+
count: achievement.count,
|
|
54
|
+
})),
|
|
55
|
+
lastUpdated: doc.lastUpdated,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof errors_1.ValidationError) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
throw new errors_1.QueryError('findByUserAndGroup', 'StatUserProfile', `${userId}:${groupId}`, error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async save(profile) {
|
|
66
|
+
try {
|
|
67
|
+
// Validate input
|
|
68
|
+
if (!profile.userId || profile.userId === 0) {
|
|
69
|
+
throw new errors_1.ValidationError('StatUserProfile', 'userId', profile.userId, 'must be a non-zero number');
|
|
70
|
+
}
|
|
71
|
+
if (!profile.groupId || profile.groupId === 0) {
|
|
72
|
+
throw new errors_1.ValidationError('StatUserProfile', 'groupId', profile.groupId, 'must be a non-zero number');
|
|
73
|
+
}
|
|
74
|
+
// Upsert the profile (create or update)
|
|
75
|
+
await this.model.updateOne({ userId: profile.userId, groupId: profile.groupId }, {
|
|
76
|
+
$set: {
|
|
77
|
+
username: profile.username,
|
|
78
|
+
fullName: profile.fullName,
|
|
79
|
+
avatarUrl: profile.avatarUrl,
|
|
80
|
+
position: profile.position,
|
|
81
|
+
currentSkillRating: profile.currentSkillRating,
|
|
82
|
+
groupName: profile.groupName,
|
|
83
|
+
gamesCount: profile.gamesCount,
|
|
84
|
+
wins: profile.wins,
|
|
85
|
+
losses: profile.losses,
|
|
86
|
+
draws: profile.draws,
|
|
87
|
+
winPercentage: profile.winPercentage,
|
|
88
|
+
goalsFor: profile.goalsFor,
|
|
89
|
+
goalsAgainst: profile.goalsAgainst,
|
|
90
|
+
eventsCount: profile.eventsCount,
|
|
91
|
+
skillHistory: profile.skillHistory,
|
|
92
|
+
achievements: profile.achievements,
|
|
93
|
+
lastUpdated: profile.lastUpdated,
|
|
94
|
+
},
|
|
95
|
+
}, { upsert: true });
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (error instanceof errors_1.ValidationError) {
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
throw new errors_1.QueryError('save', 'StatUserProfile', `${profile.userId}:${profile.groupId}`, error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.MongoStatUserProfileRepository = MongoStatUserProfileRepository;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,3 +3,6 @@ export * from "./stat-group-profile.types";
|
|
|
3
3
|
export * from "./stat-group-season.types";
|
|
4
4
|
export * from "./stat-group-last-100-games.types";
|
|
5
5
|
export * from "./stat-group-activity-chart.types";
|
|
6
|
+
export * from "./stat-user-profile.types";
|
|
7
|
+
export * from "./stat-user-match-history.types";
|
|
8
|
+
export * from "./stat-event.types";
|
package/dist/types/index.js
CHANGED
|
@@ -19,3 +19,6 @@ __exportStar(require("./stat-group-profile.types"), exports);
|
|
|
19
19
|
__exportStar(require("./stat-group-season.types"), exports);
|
|
20
20
|
__exportStar(require("./stat-group-last-100-games.types"), exports);
|
|
21
21
|
__exportStar(require("./stat-group-activity-chart.types"), exports);
|
|
22
|
+
__exportStar(require("./stat-user-profile.types"), exports);
|
|
23
|
+
__exportStar(require("./stat-user-match-history.types"), exports);
|
|
24
|
+
__exportStar(require("./stat-event.types"), exports);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistics: Event Page Types
|
|
3
|
+
* Pre-aggregated event data with standings, statistics, and enriched rosters/matches
|
|
4
|
+
*/
|
|
5
|
+
export interface StatEventPlayer {
|
|
6
|
+
userId: number;
|
|
7
|
+
playerName: string;
|
|
8
|
+
avatarUrl: string;
|
|
9
|
+
position: string;
|
|
10
|
+
}
|
|
11
|
+
export interface StatEventTeam {
|
|
12
|
+
teamId: number;
|
|
13
|
+
teamName: string;
|
|
14
|
+
totalPoints: number;
|
|
15
|
+
avgTeamRating: number;
|
|
16
|
+
players: StatEventPlayer[];
|
|
17
|
+
}
|
|
18
|
+
export interface StatEventStandingsRow {
|
|
19
|
+
rank: number;
|
|
20
|
+
teamName: string;
|
|
21
|
+
played: number;
|
|
22
|
+
wins: number;
|
|
23
|
+
draws: number;
|
|
24
|
+
losses: number;
|
|
25
|
+
goalsFor: number;
|
|
26
|
+
goalsAgainst: number;
|
|
27
|
+
goalDifference: number;
|
|
28
|
+
points: number;
|
|
29
|
+
}
|
|
30
|
+
export interface StatEventMatch {
|
|
31
|
+
matchId: number;
|
|
32
|
+
matchNumber: number;
|
|
33
|
+
time: string;
|
|
34
|
+
status: string;
|
|
35
|
+
team1Name: string;
|
|
36
|
+
team1Score: number;
|
|
37
|
+
team2Name: string;
|
|
38
|
+
team2Score: number;
|
|
39
|
+
}
|
|
40
|
+
export interface StatEventHeader {
|
|
41
|
+
status: 'Finished' | 'In Progress' | 'Upcoming';
|
|
42
|
+
seasonName: string;
|
|
43
|
+
groupName: string;
|
|
44
|
+
eventName: string;
|
|
45
|
+
date: Date;
|
|
46
|
+
timeRange: string;
|
|
47
|
+
location: string;
|
|
48
|
+
winnerName: string | null;
|
|
49
|
+
}
|
|
50
|
+
export interface StatEventOverviewStats {
|
|
51
|
+
totalGoals: number;
|
|
52
|
+
goalsPerMatch: number;
|
|
53
|
+
}
|
|
54
|
+
export interface StatEventOverview {
|
|
55
|
+
stats: StatEventOverviewStats;
|
|
56
|
+
standings: StatEventStandingsRow[];
|
|
57
|
+
teams: StatEventTeam[];
|
|
58
|
+
}
|
|
59
|
+
export interface StatEvent {
|
|
60
|
+
eventId: number;
|
|
61
|
+
header: StatEventHeader;
|
|
62
|
+
overview: StatEventOverview;
|
|
63
|
+
matches: StatEventMatch[];
|
|
64
|
+
calculatedAt: Date;
|
|
65
|
+
version: number;
|
|
66
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistics: User Match History Types
|
|
3
|
+
* Pre-aggregated user match history data for ballrush-api
|
|
4
|
+
*/
|
|
5
|
+
export interface StatUserMatchHistory {
|
|
6
|
+
userId: number;
|
|
7
|
+
groupId: number;
|
|
8
|
+
eventId: number;
|
|
9
|
+
result: 'Win' | 'Loss' | 'Draw';
|
|
10
|
+
matchup: string;
|
|
11
|
+
score: string;
|
|
12
|
+
date: Date;
|
|
13
|
+
seasonName: string;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Filter options for match history queries
|
|
18
|
+
*/
|
|
19
|
+
export interface MatchHistoryFilter {
|
|
20
|
+
userId: number;
|
|
21
|
+
groupId: number;
|
|
22
|
+
season?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Pagination options for match history queries
|
|
26
|
+
*/
|
|
27
|
+
export interface MatchHistoryOptions {
|
|
28
|
+
page: number;
|
|
29
|
+
limit: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Result type for paginated match history queries
|
|
33
|
+
*/
|
|
34
|
+
export interface MatchHistoryResult {
|
|
35
|
+
matches: StatUserMatchHistory[];
|
|
36
|
+
totalMatches: number;
|
|
37
|
+
totalPages: number;
|
|
38
|
+
currentPage: number;
|
|
39
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistics: User Profile Types
|
|
3
|
+
* Pre-aggregated user profile data for ballrush-api
|
|
4
|
+
*/
|
|
5
|
+
export interface SkillHistoryPoint {
|
|
6
|
+
date: Date;
|
|
7
|
+
earnedRating: number | null;
|
|
8
|
+
manualAdjustment: number | null;
|
|
9
|
+
}
|
|
10
|
+
export interface ProfileAchievement {
|
|
11
|
+
icon: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
count: number;
|
|
15
|
+
}
|
|
16
|
+
export interface StatUserProfile {
|
|
17
|
+
userId: number;
|
|
18
|
+
groupId: number;
|
|
19
|
+
username: string;
|
|
20
|
+
fullName: string;
|
|
21
|
+
avatarUrl: string;
|
|
22
|
+
position: string;
|
|
23
|
+
currentSkillRating: number;
|
|
24
|
+
groupName: string;
|
|
25
|
+
gamesCount: number;
|
|
26
|
+
wins: number;
|
|
27
|
+
losses: number;
|
|
28
|
+
draws: number;
|
|
29
|
+
winPercentage: number;
|
|
30
|
+
goalsFor: number;
|
|
31
|
+
goalsAgainst: number;
|
|
32
|
+
eventsCount: number;
|
|
33
|
+
skillHistory: SkillHistoryPoint[];
|
|
34
|
+
achievements: ProfileAchievement[];
|
|
35
|
+
lastUpdated: Date;
|
|
36
|
+
}
|