Prashikshak / API /src /model /userStats.model.ts
Abhisingh-18's picture
Initial commit: Prashikshak - disaster management training platform
9a92a42
Raw
History Blame Contribute Delete
3.88 kB
import { Schema, model, Document, Types } from 'mongoose';
// Aggregated statistics for each user (updated periodically)
export interface IUserStats extends Document {
user: Types.ObjectId;
// Time metrics
totalOnlineTime: number; // minutes
lastOnlineTime: Date;
averageSessionDuration: number; // minutes
totalSessions: number;
// Activity counts
eventsCreated: number;
eventsJoined: number;
eventsCompleted: number;
formsCreated: number;
formsSubmitted: number;
// Verification metrics (for organizations)
trainersVerified?: number;
trainersRejected?: number;
// Verification metrics (for admins)
organizationsVerified?: number;
organizationsRejected?: number;
// Engagement metrics
loginCount: number;
lastLoginDate: Date;
consecutiveLoginDays: number;
longestLoginStreak: number;
// Content interaction
profileUpdates: number;
locationUpdates: number;
documentsUploaded: number;
// Performance metrics (for trainers)
averageEventAttendance?: number;
totalEventParticipants?: number;
formResponsesReceived?: number;
// Last activity
lastActivityDate: Date;
lastActivityType: string;
// Period tracking
periodStart: Date; // Start of current tracking period
periodEnd: Date; // End of current tracking period
createdAt: Date;
updatedAt: Date;
}
const UserStatsSchema = new Schema<IUserStats>({
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
unique: true,
index: true
},
// Time metrics
totalOnlineTime: {
type: Number,
default: 0
},
lastOnlineTime: {
type: Date,
default: Date.now
},
averageSessionDuration: {
type: Number,
default: 0
},
totalSessions: {
type: Number,
default: 0
},
// Activity counts
eventsCreated: {
type: Number,
default: 0,
index: true
},
eventsJoined: {
type: Number,
default: 0,
index: true
},
eventsCompleted: {
type: Number,
default: 0
},
formsCreated: {
type: Number,
default: 0
},
formsSubmitted: {
type: Number,
default: 0
},
// Verification metrics
trainersVerified: {
type: Number,
default: 0
},
trainersRejected: {
type: Number,
default: 0
},
organizationsVerified: {
type: Number,
default: 0
},
organizationsRejected: {
type: Number,
default: 0
},
// Engagement metrics
loginCount: {
type: Number,
default: 0,
index: true
},
lastLoginDate: {
type: Date,
default: Date.now,
index: true
},
consecutiveLoginDays: {
type: Number,
default: 0
},
longestLoginStreak: {
type: Number,
default: 0
},
// Content interaction
profileUpdates: {
type: Number,
default: 0
},
locationUpdates: {
type: Number,
default: 0
},
documentsUploaded: {
type: Number,
default: 0
},
// Performance metrics
averageEventAttendance: {
type: Number,
default: 0
},
totalEventParticipants: {
type: Number,
default: 0
},
formResponsesReceived: {
type: Number,
default: 0
},
// Last activity
lastActivityDate: {
type: Date,
default: Date.now,
index: true
},
lastActivityType: {
type: String,
default: ''
},
// Period tracking
periodStart: {
type: Date,
default: Date.now
},
periodEnd: {
type: Date,
default: () => new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // 30 days
}
}, {
timestamps: true
});
// Indexes for leaderboards and rankings
UserStatsSchema.index({ eventsCreated: -1 });
UserStatsSchema.index({ eventsJoined: -1 });
UserStatsSchema.index({ totalOnlineTime: -1 });
UserStatsSchema.index({ loginCount: -1 });
UserStatsSchema.index({ longestLoginStreak: -1 });
export default model<IUserStats>('UserStats', UserStatsSchema);