Solved a bug with calculations of the stats page
This commit is contained in:
@@ -139,9 +139,9 @@ export default function Stats() {
|
|||||||
}
|
}
|
||||||
}, [startDate, endDate]);
|
}, [startDate, endDate]);
|
||||||
|
|
||||||
const calculateTotalScore = (stats: Stat[]) => {
|
const calculateTotalScore = (stats: Stat[], divisionFactor: number) => {
|
||||||
const moduleScores = calculateModuleScore(stats);
|
const moduleScores = calculateModuleScore(stats);
|
||||||
return moduleScores.reduce((acc, curr) => acc + curr.score, 0) / 4;
|
return moduleScores.reduce((acc, curr) => acc + curr.score, 0) / divisionFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateScorePerModule = (stats: Stat[], module: Module) => {
|
const calculateScorePerModule = (stats: Stat[], module: Module) => {
|
||||||
@@ -278,7 +278,10 @@ export default function Stats() {
|
|||||||
</span>
|
</span>
|
||||||
<span className="px-2">
|
<span className="px-2">
|
||||||
Level{" "}
|
Level{" "}
|
||||||
{calculateTotalScore(stats.filter((s) => timestampToMoment(s).isBefore(date))).toFixed(1)}
|
{calculateTotalScore(
|
||||||
|
stats.filter((s) => timestampToMoment(s).isBefore(date)),
|
||||||
|
5,
|
||||||
|
).toFixed(1)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
@@ -364,6 +367,7 @@ export default function Stats() {
|
|||||||
return date.isValid()
|
return date.isValid()
|
||||||
? calculateTotalScore(
|
? calculateTotalScore(
|
||||||
stats.filter((s) => timestampToMoment(s).isBefore(date)),
|
stats.filter((s) => timestampToMoment(s).isBefore(date)),
|
||||||
|
5,
|
||||||
).toFixed(1)
|
).toFixed(1)
|
||||||
: undefined;
|
: undefined;
|
||||||
})
|
})
|
||||||
@@ -599,9 +603,12 @@ export default function Stats() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="flex -md:flex-col -md:items-center gap-4 flex-wrap">
|
<div className="flex -md:flex-col -md:items-center gap-4 flex-wrap">
|
||||||
{/* Reading Score Band in Interval */}
|
{/* Module Score Band in Interval */}
|
||||||
<div className="w-full md:max-w-2xl border border-mti-gray-platinum p-4 pb-12 rounded-xl h-fit md:h-96">
|
{MODULE_ARRAY.map((module, index) => (
|
||||||
<span className="text-sm font-bold">Reading Score Band in Interval</span>
|
<div
|
||||||
|
className="w-full md:max-w-2xl border border-mti-gray-platinum p-4 pb-12 rounded-xl h-fit md:h-96"
|
||||||
|
key={module}>
|
||||||
|
<span className="text-sm font-bold">{capitalize(module)} Score Band in Interval</span>
|
||||||
<Chart
|
<Chart
|
||||||
options={{
|
options={{
|
||||||
scales: {
|
scales: {
|
||||||
@@ -617,17 +624,18 @@ export default function Stats() {
|
|||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
type: "line",
|
type: "line",
|
||||||
label: "Reading",
|
label: capitalize(module),
|
||||||
fill: false,
|
fill: false,
|
||||||
borderColor: COLORS[0],
|
borderColor: COLORS[index],
|
||||||
backgroundColor: COLORS[0],
|
backgroundColor: COLORS[index],
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
spanGaps: true,
|
spanGaps: true,
|
||||||
data: intervalDates.map((date) => {
|
data: intervalDates.map((date) => {
|
||||||
return calculateTotalScore(
|
return calculateTotalScore(
|
||||||
stats.filter(
|
stats.filter(
|
||||||
(s) => timestampToMoment(s).isBefore(date) && s.module === "reading",
|
(s) => timestampToMoment(s).isBefore(date) && s.module === module,
|
||||||
),
|
),
|
||||||
|
1,
|
||||||
).toFixed(1);
|
).toFixed(1);
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -635,152 +643,7 @@ export default function Stats() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
{/* Listening Score Band in Interval */}
|
|
||||||
<div className="w-full md:max-w-2xl border border-mti-gray-platinum p-4 pb-12 rounded-xl h-fit md:h-96">
|
|
||||||
<span className="text-sm font-bold">Listening Score Band in Interval</span>
|
|
||||||
<Chart
|
|
||||||
options={{
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
min: 0,
|
|
||||||
max: 9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
type="line"
|
|
||||||
data={{
|
|
||||||
labels: intervalDates.map((date) => moment(date).format("DD/MM/YYYY")),
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
type: "line",
|
|
||||||
label: "Listening",
|
|
||||||
fill: false,
|
|
||||||
borderColor: COLORS[1],
|
|
||||||
backgroundColor: COLORS[1],
|
|
||||||
borderWidth: 2,
|
|
||||||
spanGaps: true,
|
|
||||||
data: intervalDates.map((date) => {
|
|
||||||
return calculateTotalScore(
|
|
||||||
stats.filter(
|
|
||||||
(s) => timestampToMoment(s).isBefore(date) && s.module === "listening",
|
|
||||||
),
|
|
||||||
).toFixed(1);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Writing Score Band in Interval */}
|
|
||||||
<div className="w-full md:max-w-2xl border border-mti-gray-platinum p-4 pb-12 rounded-xl h-fit md:h-96">
|
|
||||||
<span className="text-sm font-bold">Writing Score Band in Interval</span>
|
|
||||||
<Chart
|
|
||||||
options={{
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
min: 0,
|
|
||||||
max: 9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
type="line"
|
|
||||||
data={{
|
|
||||||
labels: intervalDates.map((date) => moment(date).format("DD/MM/YYYY")),
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
type: "line",
|
|
||||||
label: "Writing",
|
|
||||||
fill: false,
|
|
||||||
borderColor: COLORS[2],
|
|
||||||
backgroundColor: COLORS[2],
|
|
||||||
borderWidth: 2,
|
|
||||||
spanGaps: true,
|
|
||||||
data: intervalDates.map((date) => {
|
|
||||||
return calculateTotalScore(
|
|
||||||
stats.filter(
|
|
||||||
(s) => timestampToMoment(s).isBefore(date) && s.module === "writing",
|
|
||||||
),
|
|
||||||
).toFixed(1);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Speaking Score Band in Interval */}
|
|
||||||
<div className="w-full md:max-w-2xl border border-mti-gray-platinum p-4 pb-12 rounded-xl h-fit md:h-96">
|
|
||||||
<span className="text-sm font-bold">Speaking Score Band in Interval</span>
|
|
||||||
<Chart
|
|
||||||
options={{
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
min: 0,
|
|
||||||
max: 9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
type="line"
|
|
||||||
data={{
|
|
||||||
labels: intervalDates.map((date) => moment(date).format("DD/MM/YYYY")),
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
type: "line",
|
|
||||||
label: "Speaking",
|
|
||||||
fill: false,
|
|
||||||
borderColor: COLORS[3],
|
|
||||||
backgroundColor: COLORS[3],
|
|
||||||
borderWidth: 2,
|
|
||||||
spanGaps: true,
|
|
||||||
data: intervalDates.map((date) => {
|
|
||||||
return calculateTotalScore(
|
|
||||||
stats.filter(
|
|
||||||
(s) => timestampToMoment(s).isBefore(date) && s.module === "speaking",
|
|
||||||
),
|
|
||||||
).toFixed(1);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Level Score Band in Interval */}
|
|
||||||
<div className="w-full md:max-w-2xl border border-mti-gray-platinum p-4 pb-12 rounded-xl h-fit md:h-96">
|
|
||||||
<span className="text-sm font-bold">Level Score Band in Interval</span>
|
|
||||||
<Chart
|
|
||||||
options={{
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
min: 0,
|
|
||||||
max: 9,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
type="line"
|
|
||||||
data={{
|
|
||||||
labels: intervalDates.map((date) => moment(date).format("DD/MM/YYYY")),
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
type: "line",
|
|
||||||
label: "Level",
|
|
||||||
fill: false,
|
|
||||||
borderColor: COLORS[4],
|
|
||||||
backgroundColor: COLORS[4],
|
|
||||||
borderWidth: 2,
|
|
||||||
spanGaps: true,
|
|
||||||
data: intervalDates.map((date) => {
|
|
||||||
return calculateTotalScore(
|
|
||||||
stats.filter((s) => timestampToMoment(s).isBefore(date) && s.module === "level"),
|
|
||||||
).toFixed(1);
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -142,23 +142,24 @@ export const calculateBandScore = (correct: number, total: number, module: Modul
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const calculateAverageLevel = (levels: {[key in Module]: number}) => {
|
export const calculateAverageLevel = (levels: {[key in Module]: number}) => {
|
||||||
return Object.keys(levels).reduce((accumulator, current) => levels[current as Module] + accumulator, 0) / 4;
|
return Object.keys(levels).reduce((accumulator, current) => levels[current as Module] + accumulator, 0) / 5;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLevelScore = (level: number) => {
|
export const getLevelScore = (level: number) => {
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case 0:
|
case 0:
|
||||||
return ['Beginner', 'Low A1'];
|
return ["Beginner", "Low A1"];
|
||||||
case 2:
|
case 2:
|
||||||
return ['Elementary', 'High A1/Low A2'];
|
return ["Elementary", "High A1/Low A2"];
|
||||||
case 4:
|
case 4:
|
||||||
return ['Pre-Intermediate', 'High A2/Low B1'];
|
return ["Pre-Intermediate", "High A2/Low B1"];
|
||||||
case 6:
|
case 6:
|
||||||
return ['Intermediate', 'High B1/Low B2'];
|
return ["Intermediate", "High B1/Low B2"];
|
||||||
case 8:
|
case 8:
|
||||||
return ['Upper-Intermediate', 'High B2/Low C1'];
|
return ["Upper-Intermediate", "High B2/Low C1"];
|
||||||
case 9:
|
case 9:
|
||||||
return ['Advanced', 'C1'];
|
return ["Advanced", "C1"];
|
||||||
default: return [];
|
default:
|
||||||
}
|
return [];
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user