Team Ai
Apppublic

sanket3280/code-execution

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
Challenge.js173 linesDownload Raw Back to models
1const mongoose = require('mongoose');2const Schema = mongoose.Schema;3const bcrypt = require('bcryptjs');4 5const ChallengeSchema = new Schema({6  title: {7    type: String,8    required: true,9    trim: true10  },11  description: {12    type: String,13    required: true14  },15  startDate: {16    type: Date,17    required: true18  },19  endDate: {20    type: Date,21    required: true22  },23  problems: [{24    type: Schema.Types.ObjectId,25    ref: 'Problem'26  }],27  participants: [{28    user: {29      type: Schema.Types.ObjectId,30      ref: 'User'31    },32    joinedAt: {33      type: Date,34      default: Date.now35    },36    score: {37      type: Number,38      default: 039    },40    problemsSolved: {41      type: Number,42      default: 043    },44    lastSubmission: {45      type: Date46    },47    hasSpectatorAccess: {48      type: Boolean,49      default: false50    },51    spectatorAccessGrantedAt: {52      type: Date53    },54    spectatorAccessGrantedBy: {55      type: Schema.Types.ObjectId,56      ref: 'User'57    }58  }],59  isActive: {60    type: Boolean,61    default: true62  },63  maxParticipants: {64    type: Number,65    default: 0 // 0 means unlimited66  },67  difficulty: {68    type: String,69    enum: ['easy', 'medium', 'hard', 'mixed'],70    default: 'mixed'71  },72  tags: [{73    type: String,74    trim: true75  }],76  createdBy: {77    type: Schema.Types.ObjectId,78    ref: 'User',79    required: true80  },81  createdAt: {82    type: Date,83    default: Date.now84  },85  updatedAt: {86    type: Date,87    default: Date.now88  },89  visibility: {90    type: String,91    enum: ['public', 'private'],92    default: 'public'93  },94  password: {95    type: String,96    required: function() { return this.visibility === 'private'; }97  },98  invites: [{99    user: {100      type: Schema.Types.ObjectId,101      ref: 'User'102    },103    email: String,104    status: {105      type: String,106      enum: ['pending', 'accepted', 'revoked'],107      default: 'pending'108    },109    sentAt: {110      type: Date,111      default: Date.now112    }113  }]114});115 116// Update the updatedAt field on save117ChallengeSchema.pre('save', function(next) {118  this.updatedAt = Date.now();119  next();120});121 122// Virtual for challenge status123ChallengeSchema.virtual('status').get(function() {124  const now = new Date();125  if (now < this.startDate) {126    return 'upcoming';127  } else if (now >= this.startDate && now <= this.endDate) {128    return 'active';129  } else {130    return 'completed';131  }132});133 134// Virtual for remaining time135ChallengeSchema.virtual('remainingTime').get(function() {136  const now = new Date();137  if (now > this.endDate) {138    return 0;139  }140  return Math.max(0, this.endDate - now);141});142 143// Virtual for participation count144ChallengeSchema.virtual('participantCount').get(function() {145  return this.participants.length;146});147 148// Add method to compare password149ChallengeSchema.methods.comparePassword = async function(candidatePassword) {150  if (!this.password || !candidatePassword) {151    return false;152  }153  154  try {155    return await bcrypt.compare(candidatePassword, this.password);156  } catch (error) {157    console.error('Error in comparePassword:', error);158    return false;159  }160};161 162// Indexes for better query performance163ChallengeSchema.index({ createdBy: 1 });164ChallengeSchema.index({ startDate: 1, endDate: 1 });165ChallengeSchema.index({ visibility: 1 });166ChallengeSchema.index({ isActive: 1 });167ChallengeSchema.index({ 'participants.user': 1 });168ChallengeSchema.index({ createdAt: -1 });169 170// Compound index for common queries171ChallengeSchema.index({ visibility: 1, isActive: 1, startDate: 1 });172 173module.exports = mongoose.model('Challenge', ChallengeSchema);