ballrush-core 0.5.0 → 0.5.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.
@@ -7,3 +7,5 @@ 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";
@@ -23,3 +23,5 @@ __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);
@@ -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
+ }
@@ -7,3 +7,5 @@ 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";
@@ -23,3 +23,5 @@ __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);
@@ -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,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -7,3 +7,5 @@ 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";
@@ -23,3 +23,5 @@ __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);
@@ -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;
@@ -3,3 +3,5 @@ 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";
@@ -19,3 +19,5 @@ __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);
@@ -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,6 @@
1
+ "use strict";
2
+ /**
3
+ * Statistics: User Match History Types
4
+ * Pre-aggregated user match history data for ballrush-api
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Statistics: User Profile Types
4
+ * Pre-aggregated user profile data for ballrush-api
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ballrush-core",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",