// server/models/MinesweeperRecord.ts import mongoose, { Document, Schema } from 'mongoose'; // 扫雷难度级别 export type MinesweeperDifficulty = 'beginner' | 'intermediate' | 'expert' | 'brutal'; // 扫雷游戏记录接口 export interface IMinesweeperRecord extends Document { userId: mongoose.Types.ObjectId; username: string; fullname: string; difficulty: MinesweeperDifficulty; timeSeconds: number; // 完成时间(秒) won: boolean; // 是否获胜 createdAt: Date; updatedAt: Date; } // 排行榜聚合结果接口 export interface IMinesweeperLeaderboardRecord { userId: mongoose.Types.ObjectId; username: string; fullname: string; bestTime: number; // 最佳时间 totalGames: number; // 总游戏次数 wonGames: number; // 获胜次数 winRate: number; // 胜率 lastPlayed: Date; // 最后游玩时间 } // 创建 Schema const minesweeperRecordSchema = new Schema({ userId: { type: Schema.Types.ObjectId, ref: 'User', required: true }, username: { type: String, required: true }, fullname: { type: String, required: true }, difficulty: { type: String, enum: ['beginner', 'intermediate', 'expert', 'brutal'], required: true }, timeSeconds: { type: Number, required: true, min: 0 }, won: { type: Boolean, required: true } }, { timestamps: true }); // 创建索引以优化查询性能 minesweeperRecordSchema.index({ userId: 1, difficulty: 1 }); minesweeperRecordSchema.index({ difficulty: 1, won: 1, timeSeconds: 1 }); // 获取排行榜的静态方法 minesweeperRecordSchema.statics.getLeaderboard = function( difficulty: MinesweeperDifficulty, skipCount: number, pageSize: number ): mongoose.Aggregate { return this.aggregate([ { $match: { difficulty // 统计所有记录(包括获胜和失败) } }, { $group: { _id: '$userId', username: { $first: '$username' }, fullname: { $first: '$fullname' }, // 最佳时间只统计获胜的记录 bestTime: { $min: { $cond: [{ $eq: ['$won', true] }, '$timeSeconds', null] } }, totalGames: { $sum: 1 }, // 所有游戏次数(获胜+失败) wonGames: { $sum: { $cond: ['$won', 1, 0] } }, // 获胜次数 lastPlayed: { $max: '$createdAt' } } }, { // 过滤掉没有获胜记录的用户(因为排行榜需要最佳时间) $match: { bestTime: { $ne: null } } }, { $addFields: { userId: '$_id', winRate: { $multiply: [ { $divide: ['$wonGames', '$totalGames'] }, 100 ] } } }, { $sort: { bestTime: 1 } }, // 按最佳时间升序排序(时间越短越好) { $skip: skipCount }, { $limit: pageSize } ]); }; // 扩展模型的静态方法类型 interface MinesweeperRecordModel extends mongoose.Model { getLeaderboard( difficulty: MinesweeperDifficulty, skipCount: number, pageSize: number ): mongoose.Aggregate; } // 创建并导出模型 export const MinesweeperRecord = mongoose.model( 'MinesweeperRecord', minesweeperRecordSchema );