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 {calculateBandScore} from "@/utils/score"; import {groupByModule, groupBySession} from "@/utils/stats"; import { MODULE_ARRAY } from "@/utils/moduleUtils"; import {getAuth} from "firebase/auth"; import {collection, doc, getDoc, getDocs, getFirestore, query, updateDoc, where} from "firebase/firestore"; import {withIronSessionApiRoute} from "iron-session/next"; import {groupBy} from "lodash"; import {NextApiRequest, NextApiResponse} from "next"; const db = getFirestore(app); export default withIronSessionApiRoute(update, sessionOptions); async function update(req: NextApiRequest, res: NextApiResponse) { if (req.session.user) { const docUser = await getDoc(doc(db, "users", req.session.user.id)); if (!docUser.exists()) { res.status(401).json(undefined); return; } const q = query(collection(db, "stats"), where("user", "==", req.session.user.id)); const stats = (await getDocs(q)).docs.map((doc) => ({ ...(doc.data() as Stat), id: doc.id, })) as Stat[]; 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", req.session.user.focus), listening: calculateBandScore(listeningLevel.correct, listeningLevel.total, "listening", req.session.user.focus), writing: calculateBandScore(writingLevel.correct, writingLevel.total, "writing", req.session.user.focus), speaking: calculateBandScore(speakingLevel.correct, speakingLevel.total, "speaking", req.session.user.focus), level: calculateBandScore(levelLevel.correct, levelLevel.total, "level", req.session.user.focus), }; const userDoc = doc(db, "users", req.session.user.id); await updateDoc(userDoc, {levels}); res.status(200).json({ok: true}); } else { res.status(401).json(undefined); } }