import { MODULES } from "@/constants/ielts"; import { app } from "@/firebase"; import { Module } from "@/interfaces"; import { Stat, User } from "@/interfaces/user"; import { sessionOptions } from "@/lib/session"; import { calculateAverageLevel, calculateBandScore } from "@/utils/score"; import { groupByModule, groupBySession } from "@/utils/stats"; import { MODULE_ARRAY } from "@/utils/moduleUtils"; import client from "@/lib/mongodb"; import { withIronSessionApiRoute } from "iron-session/next"; import { groupBy } from "lodash"; import { NextApiRequest, NextApiResponse } from "next"; import { requestUser } from "@/utils/api"; const db = client.db(process.env.MONGODB_DB); export default withIronSessionApiRoute(update, sessionOptions); async function update(req: NextApiRequest, res: NextApiResponse) { const user = await requestUser(req, res) if (user) { const docUser = await db.collection("users").findOne({ id: user.id }); if (!docUser) { res.status(401).json(undefined); return; } const stats = await db.collection("stats").find({ user: user.id }).toArray(); const groupedStats = groupBySession(stats); const sessionLevels: { [key in Module]: { correct: number; total: number } }[] = Object.keys(groupedStats).map((key) => { const sessionStats = groupedStats[key].map((stat) => ({ module: stat.module, correct: stat.score.correct, total: stat.score.total })); const sessionLevels = { reading: { correct: 0, total: 0, }, listening: { correct: 0, total: 0, }, writing: { correct: 0, total: 0, }, speaking: { correct: 0, total: 0, }, level: { correct: 0, total: 0, }, }; MODULE_ARRAY.forEach((module: Module) => { const moduleStats = sessionStats.filter((x) => x.module === module); if (moduleStats.length === 0) return; const moduleScore = moduleStats.reduce( (accumulator, current) => ({ correct: accumulator.correct + current.correct, total: accumulator.total + current.total }), { correct: 0, total: 0 }, ); sessionLevels[module] = moduleScore; }); return sessionLevels; }); const readingLevel = sessionLevels .map((x) => x.reading) .filter((x) => x.total > 0) .reduce((acc, cur) => ({ total: acc.total + cur.total, correct: acc.correct + cur.correct }), { total: 0, correct: 0 }); const listeningLevel = sessionLevels .map((x) => x.listening) .filter((x) => x.total > 0) .reduce((acc, cur) => ({ total: acc.total + cur.total, correct: acc.correct + cur.correct }), { total: 0, correct: 0 }); const writingLevel = sessionLevels .map((x) => x.writing) .filter((x) => x.total > 0) .reduce((acc, cur) => ({ total: acc.total + cur.total, correct: acc.correct + cur.correct }), { total: 0, correct: 0 }); const speakingLevel = sessionLevels .map((x) => x.speaking) .filter((x) => x.total > 0) .reduce((acc, cur) => ({ total: acc.total + cur.total, correct: acc.correct + cur.correct }), { total: 0, correct: 0 }); const levelLevel = sessionLevels .map((x) => x.level) .filter((x) => x.total > 0) .reduce((acc, cur) => ({ total: acc.total + cur.total, correct: acc.correct + cur.correct }), { total: 0, correct: 0 }); const levels = { reading: calculateBandScore(readingLevel.correct, readingLevel.total, "reading", user.focus), listening: calculateBandScore(listeningLevel.correct, listeningLevel.total, "listening", user.focus), writing: calculateBandScore(writingLevel.correct, writingLevel.total, "writing", user.focus), speaking: calculateBandScore(speakingLevel.correct, speakingLevel.total, "speaking", user.focus), level: calculateBandScore(levelLevel.correct, levelLevel.total, "level", user.focus), }; const averageLevel = calculateAverageLevel(levels) await db.collection("users").updateOne( { id: user.id }, { $set: { levels, averageLevel } } ); res.status(200).json({ ok: true }); } else { res.status(401).json(undefined); } }