Files
encoach_frontend/src/utils/stats.ts

131 lines
4.1 KiB
TypeScript

import {Stat} from "@/interfaces/user";
import {capitalize, groupBy} from "lodash";
import {convertCamelCaseToReadable} from "@/utils/string";
import {UserSolution} from "@/interfaces/exam";
import {Module} from "@/interfaces";
export const totalExams = (stats: Stat[]): number => {
const moduleStats = formatModuleTotalStats(stats);
return moduleStats.reduce((previous, current) => previous + current.value, 0);
};
export const averageScore = (stats: Stat[]): number => {
const {correct, total} = stats.reduce(
(acc, current) => ({correct: acc.correct + current.score.correct, total: acc.total + current.score.total}),
{correct: 0, total: 0},
);
return parseFloat(((correct / total) * 100).toFixed(2));
};
export const formatModuleTotalStats = (stats: Stat[]): {label: string; value: number}[] => {
const moduleSessions: {[key: string]: string[]} = {};
stats.forEach((stat) => {
if (stat.module in moduleSessions) {
if (!moduleSessions[stat.module].includes(stat.session)) {
moduleSessions[stat.module] = [...moduleSessions[stat.module], stat.session];
}
} else {
moduleSessions[stat.module] = [stat.session];
}
});
return ["reading", "listening", "writing", "speaking"].map((module) => ({
label: capitalize(module),
value: moduleSessions[module]?.length || 0,
}));
};
export const totalExamsByModule = (stats: Stat[], module: Module): number => {
const moduleSessions: {[key: string]: string[]} = {};
stats.forEach((stat) => {
if (stat.module in moduleSessions) {
if (!moduleSessions[stat.module].includes(stat.session)) {
moduleSessions[stat.module] = [...moduleSessions[stat.module], stat.session];
}
} else {
moduleSessions[stat.module] = [stat.session];
}
});
return moduleSessions[module]?.length || 0;
};
export const formatModuleAverageScoreStats = (stats: Stat[]): {label: string; value: number}[] => {
const moduleScores: {[key: string]: {correct: number; total: number}} = {};
stats.forEach((stat) => {
if (stat.module in moduleScores) {
moduleScores[stat.module] = {
correct: moduleScores[stat.module].correct + stat.score.correct,
total: moduleScores[stat.module].total + stat.score.total,
};
} else {
moduleScores[stat.module] = stat.score;
}
});
return ["reading", "listening", "writing", "speaking"].map((x) => {
const score = moduleScores[x as keyof typeof moduleScores];
return {
label: capitalize(x),
value: score ? parseFloat(((score.correct / score.total) * 100).toFixed(2)) : 0,
};
});
};
export const formatExerciseTotalStats = (stats: Stat[]): {label: string; value: number}[] => {
const totalExercises = stats.map((stat) => ({
label: convertCamelCaseToReadable(stat.type),
value: stats.filter((x) => x.type === stat.type).length,
}));
return totalExercises.filter((ex, index) => totalExercises.findIndex((x) => x.label === ex.label) === index);
};
export const formatExerciseAverageScoreStats = (stats: Stat[]): {label: string; value: number}[] => {
const typeScores: {[key: string]: {correct: number; total: number}} = {};
stats.forEach((stat) => {
if (stat.type in typeScores) {
typeScores[stat.type] = {
correct: typeScores[stat.type].correct + stat.score.correct,
total: typeScores[stat.type].total + stat.score.total,
};
} else {
typeScores[stat.type] = stat.score;
}
});
return Object.keys(typeScores).map((x) => {
const {correct, total} = typeScores[x as keyof typeof typeScores];
return {
label: convertCamelCaseToReadable(x),
value: parseFloat(((correct / total) * 100).toFixed(2)),
};
});
};
export const getExamsBySession = (stats: Stat[], session: string) => {
const grouped = groupBySession(stats);
return grouped[session].map((exam) => exam.exam);
};
export const groupBySession = (stats: Stat[]) => groupBy(stats, "session");
export const groupByDate = (stats: Stat[]) => groupBy(stats, "date");
export const groupByModule = (stats: Stat[]) => groupBy(stats, "module");
export const convertToUserSolutions = (stats: Stat[]): UserSolution[] => {
return stats.map((stat) => ({
exercise: stat.exercise,
exam: stat.exam,
score: stat.score,
solutions: stat.solutions,
type: stat.type,
module: stat.module,
}));
};