Merged in feature-levelScoringTiers (pull request #4)

Changed approach to display level for Level Testing

Approved-by: Tiago Ribeiro
This commit is contained in:
João Ramos
2023-12-13 22:01:07 +00:00
committed by Tiago Ribeiro
4 changed files with 153 additions and 114 deletions

View File

@@ -1,5 +1,4 @@
import {infoButtonStyle} from "@/constants/buttonStyles";
import {BAND_SCORES} from "@/constants/ielts";
import {Module} from "@/interfaces";
import {User} from "@/interfaces/user";
import useExamStore from "@/stores/examStore";

View File

@@ -2,20 +2,20 @@ import {Module} from "@/interfaces";
export const MODULES: Module[] = ["reading", "listening", "writing", "speaking"];
export const BAND_SCORES: {[key in Module]: number[]} = {
reading: [0, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9],
listening: [0, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9],
writing: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
speaking: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
level: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
};
// BAND SCORES is not in use anymore and level scoring is made based on thresholds
// export const BAND_SCORES: {[key in Module]: number[]} = {
// reading: [0, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9],
// listening: [0, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9],
// writing: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
// speaking: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
// level: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
// };
export const moduleResultText = (level: number) => {
if (level === 9) {
return (
export type LevelScore = "Advanced" | "Upper-Intermediate" | "Intermediate" | "Pre-Intermediate" | "Elementary" | "Beginner";
const generateHighestScoreText = () : React.ReactNode => (
<>
Congratulations on your exam performance! You achieved an impressive <span className="font-bold">level {level}</span>, demonstrating
excellent mastery of the assessed knowledge.
<br />
<br />
If you disagree with the result, you can request a review by a qualified teacher. We are committed to the accuracy and transparency of
@@ -26,13 +26,9 @@ export const moduleResultText = (level: number) => {
academic journey.
</>
);
}
if (level >= 6) {
return (
const generateAverageScoreText = () : React.ReactNode => (
<>
Congratulations on your exam performance! You achieved a commendable <span className="font-bold">level {level}</span>, demonstrating a
good understanding of the assessed knowledge.
<br />
<br />
If you have any concerns about the result, you can request a review by a qualified teacher. We are committed to the accuracy and
@@ -43,29 +39,9 @@ export const moduleResultText = (level: number) => {
journey.
</>
);
}
if (level >= 3) {
return (
const generateLowestScoreText = () : React.ReactNode => (
<>
Congratulations on your exam performance! You achieved a <span className="font-bold">level of {level}</span>, demonstrating a
satisfactory understanding of the assessed knowledge.
<br />
<br />
If you have any concerns about the result, you can request a review by a qualified teacher. We are committed to the accuracy and
transparency of the results.
<br />
<br />
Please contact us for further information. Congratulations again on your achievement! We are here to support you on your academic
journey.
</>
);
}
return (
<>
Thank you for taking the exam. You achieved a <span className="font-bold">level {level}</span>, but unfortunately, it did not meet the
required standards.
<br />
<br />
If you have any concerns about the result, you can request a review by a qualified teacher. We are committed to the accuracy and
@@ -75,23 +51,70 @@ export const moduleResultText = (level: number) => {
Please contact us for further information. We encourage you to continue your studies and wish you the best of luck in your future
endeavors.
</>
);
};
)
export const levelResultText = (level: number) => {
if(level === 9) {
return (
<>
{"Outstanding! Your command of English is excellent. Focus on fine-tuning subtle language nuances and exploring sophisticated vocabulary. Keep up the excellent work!"}
{generateHighestScoreText()}
</>
);
}
if(level >= 8) {
return (
<>
{"Impressive! You're approaching fluency. Continue refining nuances in grammar and expanding your vocabulary to express ideas more precisely."}
{generateAverageScoreText()}
</>
);
}
if(level >= 6) {
return (
<>
{"Great job! You're navigating the complexities of English. Keep honing your grammar skills and exploring more advanced vocabulary."}
{generateAverageScoreText()}
</>
);
}
if(level >= 4) {
return (
<>
{"Well done! You're moving beyond the basics. Work on expanding your vocabulary and refining your understanding of grammar structures."}
{generateAverageScoreText()}
</>
);
}
if(level >= 2) {
return (
<>
{"Good effort! You're making progress. Continue studying and pay attention to common vocabulary and fundamental grammar rules."}
{generateAverageScoreText()}
</>
);
}
if(level >= 0) {
return (
<>
{"Keep practicing! You're just starting, and improvement takes time. Focus on building your vocabulary and basic grammar skills."}
{generateLowestScoreText()}
</>
);
}
return null;
};
export const moduleResultText = (module: Module, level: number) => {
if(module === 'level') return levelResultText(level);
if (level === 9) {
return (
<>
Congratulations on your exam performance! You achieved an impressive <span className="font-bold">level {level}</span>, demonstrating
excellent mastery of the assessed knowledge.
<br />
<br />
If you disagree with the result, you can request a review by a qualified teacher. We are committed to the accuracy and transparency of
the results.
<br />
<br />
Please contact us for further information. Congratulations again on your outstanding achievement! We are here to support you on your
academic journey.
{generateHighestScoreText()}
</>
);
}
@@ -101,14 +124,7 @@ export const levelResultText = (level: number) => {
<>
Congratulations on your exam performance! You achieved a commendable <span className="font-bold">level {level}</span>, demonstrating a
good understanding of the assessed knowledge.
<br />
<br />
If you have any concerns about the result, you can request a review by a qualified teacher. We are committed to the accuracy and
transparency of the results.
<br />
<br />
Please contact us for further information. Congratulations again on your achievement! We are here to support you on your academic
journey.
{generateAverageScoreText()}
</>
);
}
@@ -118,14 +134,7 @@ export const levelResultText = (level: number) => {
<>
Congratulations on your exam performance! You achieved a <span className="font-bold">level of {level}</span>, demonstrating a
satisfactory understanding of the assessed knowledge.
<br />
<br />
If you have any concerns about the result, you can request a review by a qualified teacher. We are committed to the accuracy and
transparency of the results.
<br />
<br />
Please contact us for further information. Congratulations again on your achievement! We are here to support you on your academic
journey.
{generateAverageScoreText()}
</>
);
}
@@ -134,14 +143,7 @@ export const levelResultText = (level: number) => {
<>
Thank you for taking the exam. You achieved a <span className="font-bold">level {level}</span>, but unfortunately, it did not meet the
required standards.
<br />
<br />
If you have any concerns about the result, you can request a review by a qualified teacher. We are committed to the accuracy and
transparency of the results.
<br />
<br />
Please contact us for further information. We encourage you to continue your studies and wish you the best of luck in your future
endeavors.
{generateLowestScoreText()}
</>
);
};

View File

@@ -10,6 +10,8 @@ import Link from "next/link";
import {useRouter} from "next/router";
import {Fragment, useEffect, useState} from "react";
import {BsArrowCounterclockwise, BsBook, BsClipboard, BsEyeFill, BsHeadphones, BsMegaphone, BsPen, BsShareFill} from "react-icons/bs";
import { LevelScore } from "@/constants/ielts";
import { getLevelScore } from "@/utils/score";
interface Score {
module: Module;
@@ -66,6 +68,24 @@ export default function Finish({user, scores, modules, isLoading, onViewResults}
return exam.exercises.length;
};
const bandScore: number = calculateBandScore(selectedScore.correct, selectedScore.total, selectedModule, user.focus);
const showLevel = (level: number) => {
if(selectedModule === "level") {
const [levelStr, grade] = getLevelScore(level);
return (
<div className="flex flex-col items-center justify-center gap-1">
<span className="text-xl font-bold">{levelStr}</span>
<span className="text-xl">{grade}</span>
</div>
)
}
return <span className="text-3xl font-bold">{level}</span>;
}
return (
<>
<div className="w-full min-h-full h-fit flex flex-col items-center justify-between gap-8">
@@ -142,7 +162,7 @@ export default function Finish({user, scores, modules, isLoading, onViewResults}
{!isLoading && (
<div className="w-full flex gap-9 mt-32 items-center justify-between mb-20">
<span className="max-w-3xl">
{moduleResultText(calculateBandScore(selectedScore.correct, selectedScore.total, selectedModule, user.focus))}
{moduleResultText(selectedModule, bandScore)}
</span>
<div className="flex gap-9 px-16">
<div
@@ -156,9 +176,7 @@ export default function Finish({user, scores, modules, isLoading, onViewResults}
moduleColors[selectedModule].inner,
)}>
<span className="text-xl">Level</span>
<span className="text-3xl font-bold">
{calculateBandScore(selectedScore.correct, selectedScore.total, selectedModule, user.focus)}
</span>
{showLevel(bandScore)}
</div>
</div>
<div className="flex flex-col gap-5">

View File

@@ -1,4 +1,5 @@
import {Module} from "@/interfaces";
import { LevelScore } from "@/constants/ielts";
type Type = "academic" | "general";
@@ -94,11 +95,12 @@ const academicMarking: {[key: number]: number} = {
};
const levelMarking: {[key: number]: number} = {
88: 9,
64: 8,
52: 6,
32: 4,
16: 2,
88: 9, // Advanced
64: 8 , // Upper-Intermediate
52: 6, // Intermediate
32: 4, // Pre-Intermediate
16: 2, // Elementary
0: 0, // Beginner
};
const moduleMarkings: {[key in Module]: {[key in Type]: {[key: number]: number}}} = {
@@ -142,3 +144,21 @@ export const calculateBandScore = (correct: number, total: number, module: Modul
export const calculateAverageLevel = (levels: {[key in Module]: number}) => {
return Object.keys(levels).reduce((accumulator, current) => levels[current as Module] + accumulator, 0) / 4;
};
export const getLevelScore = (level: number) => {
switch(level) {
case 0:
return ['Beginner', 'Low A1'];
case 2:
return ['Elementary', 'High A1/Low A2'];
case 4:
return ['Pre-Intermediate', 'High A2/Low B1'];
case 6:
return ['Intermediate', 'High B1/Low B2'];
case 8:
return ['Upper-Intermediate', 'High B2/Low C1'];
case 9:
return ['Advanced', 'C1'];
default: return [];
}
}