Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(Grades): changes + many fix #295

Merged
merged 17 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 48 additions & 22 deletions src/utils/grades/getAverages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Grade } from "@/services/shared/Grade";
// Définition de l'interface `GradeHistory` pour représenter l'historique des notes avec une valeur numérique et une date
export interface GradeHistory {
value: number; // La valeur de la note
date: string; // La date à laquelle la note a été enregistrée
date: string; // La date à laquelle la note a été enregistrée
}

// Définition du type `Target` qui indique quel type de moyenne ou note cibler
Expand All @@ -13,41 +13,60 @@ type Target = "student" | "average" | "min" | "max";
// Définition du type `AverageDiffGrade` pour calculer la différence entre les moyennes avec et sans certaines notes
export type AverageDiffGrade = {
difference?: number; // La différence de moyenne entre deux ensembles de notes
with: number; // La moyenne avec toutes les notes
without: number; // La moyenne sans certaines notes
with: number; // La moyenne avec toutes les notes
without: number; // La moyenne sans certaines notes
};

// Fonction pour calculer la moyenne des notes globales par matière, en fonction de la cible (par défaut, "student")
const getPronoteAverage = (grades: Grade[], target: Target = "student"): number => {
const getPronoteAverage = (
grades: Grade[],
target: Target = "student"
): number => {
// Si aucune note n'est fournie ou que la liste est vide, on retourne -1
if (!grades || grades.length === 0) return -1;

// Grouper les notes par matière
const groupedBySubject = grades.reduce((acc: Record<string, Grade[]>, grade) => {
(acc[grade.subjectName] ||= []).push(grade); // Ajouter la note à la liste des notes pour la matière correspondante
return acc;
}, {});
const groupedBySubject = grades.reduce(
(acc: Record<string, Grade[]>, grade) => {
(acc[grade.subjectName] ||= []).push(grade); // Ajouter la note à la liste des notes pour la matière correspondante
return acc;
},
{}
);

// Calculer la moyenne totale de toutes les matières
const totalAverage = Object.values(groupedBySubject).reduce((acc, subjectGrades) => {
return acc + getSubjectAverage(subjectGrades, target); // Additionner les moyennes de chaque matière
}, 0);
const totalAverage = Object.values(groupedBySubject).reduce(
(acc, subjectGrades) => {
return acc + getSubjectAverage(subjectGrades, target); // Additionner les moyennes de chaque matière
},
0
);

// Retourner la moyenne globale en divisant par le nombre de matières
return totalAverage / Object.keys(groupedBySubject).length;
};

// Fonction pour calculer la moyenne d'une matière spécifique, selon la cible choisie
export const getSubjectAverage = (subject: Grade[], target: Target = "student"): number => {
export const getSubjectAverage = (
subject: Grade[],
target: Target = "student"
): number => {
let calcGradesSum = 0; // Somme cumulée des notes pondérées
let calcOutOfSum = 0; // Somme cumulée des coefficients pondérés
let calcOutOfSum = 0; // Somme cumulée des coefficients pondérés

// Parcourir chaque note de la matière
for (const grade of subject) {
const targetGrade = grade[target]; // Sélectionner la note selon la cible choisie

// Vérifier si la note est invalide ou si le coefficient est nul, et passer à la suivante si c'est le cas
if (!targetGrade || targetGrade.disabled || targetGrade.value === null || targetGrade.value < 0 || grade.coefficient === 0) continue;
if (
!targetGrade ||
targetGrade.disabled ||
targetGrade.value === null ||
targetGrade.value < 0 ||
grade.coefficient === 0
)
continue;

const coefficient = grade.coefficient; // Coefficient de la note
const outOfValue = grade.outOf.value!; // Valeur maximale possible pour la note
Expand Down Expand Up @@ -82,9 +101,16 @@ export const getSubjectAverage = (subject: Grade[], target: Target = "student"):
};

// Fonction pour calculer la différence de moyenne avec et sans certaines notes
const getAverageDiffGrade = (grades: Grade[], list: Grade[], target: Target = "student"): AverageDiffGrade => {
const getAverageDiffGrade = (
grades: Grade[],
list: Grade[],
target: Target = "student"
): AverageDiffGrade => {
const baseAverage = getSubjectAverage(list, target); // Calculer la moyenne de base avec toutes les notes
const baseWithoutGradeAverage = getSubjectAverage(list.filter(grade => !grades.includes(grade)), target); // Calculer la moyenne sans certaines notes
const baseWithoutGradeAverage = getSubjectAverage(
list.filter((grade) => JSON.stringify(grades[0]) !== JSON.stringify(grade)),
target
); // Calculer la moyenne sans certaines notes

return {
difference: baseWithoutGradeAverage - baseAverage, // Calculer la différence entre les deux moyennes
Expand All @@ -94,7 +120,11 @@ const getAverageDiffGrade = (grades: Grade[], list: Grade[], target: Target = "s
};

// Fonction pour générer un historique des moyennes au fil du temps
const getAveragesHistory = (grades: Grade[], target: Target = "student", final?: number): GradeHistory[] => {
const getAveragesHistory = (
grades: Grade[],
target: Target = "student",
final?: number
): GradeHistory[] => {
// Générer l'historique des moyennes jusqu'à la date de chaque note
const history = grades.map((grade, index) => ({
value: getPronoteAverage(grades.slice(0, index + 1), target), // Moyenne jusqu'à ce point
Expand All @@ -114,8 +144,4 @@ const getAveragesHistory = (grades: Grade[], target: Target = "student", final?:
};

// Exportation des fonctions pour utilisation externe
export {
getPronoteAverage,
getAverageDiffGrade,
getAveragesHistory,
};
export { getPronoteAverage, getAverageDiffGrade, getAveragesHistory };
189 changes: 118 additions & 71 deletions src/views/account/Grades/Document.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import { NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents";
import {
NativeItem,
NativeList,
NativeListHeader,
NativeText,
} from "@/components/Global/NativeComponents";
import { getSubjectData } from "@/services/shared/Subject";
import { useTheme } from "@react-navigation/native";
import React, { useEffect, useLayoutEffect, useState } from "react";
import { ScrollView, View } from "react-native";
import { GradeTitle } from "./Atoms/GradeTitle";
import { Asterisk, Calculator, Scale, School, UserMinus, UserPlus, Users } from "lucide-react-native";
import {
Asterisk,
Calculator,
Scale,
School,
UserMinus,
UserPlus,
Users,
} from "lucide-react-native";
import { getAverageDiffGrade } from "@/utils/grades/getAverages";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import type { Grade } from "@/services/shared/Grade";
import type { AverageDiffGrade } from "@/utils/grades/getAverages";
import { Screen } from "@/router/helpers/types";
import InsetsBottomView from "@/components/Global/InsetsBottomView";

const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
const {
grade,
allGrades = []
} = route.params;
const { grade, allGrades = [] } = route.params;
const theme = useTheme();
const insets = useSafeAreaInsets();

const [subjectData, setSubjectData] = useState({
color: "#888888", pretty: "Matière inconnue", emoji: "❓",
color: "#888888",
pretty: "Matière inconnue",
emoji: "❓",
});

const fetchSubjectData = () => {
Expand All @@ -43,8 +52,16 @@ const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
const [classDiff, setClassDiff] = useState({} as AverageDiffGrade);

useEffect(() => {
const gD = getAverageDiffGrade([grade], allGrades, "student") as AverageDiffGrade;
const cD = getAverageDiffGrade([grade], allGrades, "average") as AverageDiffGrade;
const gD = getAverageDiffGrade(
[grade],
allGrades,
"student"
) as AverageDiffGrade;
const cD = getAverageDiffGrade(
[grade],
allGrades,
"average"
) as AverageDiffGrade;

setGradeDiff(gD);
setClassDiff(cD);
Expand All @@ -60,15 +77,18 @@ const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
description: "Coefficient de la note",
value: "x" + grade.coefficient.toFixed(2),
},
grade.outOf.value !== 20 && !grade.student.disabled && {
grade.outOf.value !== 20 &&
!grade.student.disabled && {
icon: <Calculator />,
title: "Remis sur /20",
description: "Valeur recalculée sur 20",
value: (typeof grade.student.value === "number" && typeof grade.outOf.value === "number")
? (grade.student.value / grade.outOf.value * 20).toFixed(2)
: "??",
value:
typeof grade.student.value === "number" &&
typeof grade.outOf.value === "number"
? ((grade.student.value / grade.outOf.value) * 20).toFixed(2)
: "??",
bareme: "/20",
}
},
],
},
{
Expand All @@ -92,10 +112,14 @@ const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
icon: <UserMinus />,
title: "Note minimale",
description: "Moins bonne note de la classe",
value: grade.min.value?.toFixed(2) ?? "??",
value:
grade.min.value?.toFixed(2) &&
grade.min.value.toFixed(2) !== "-1.00"
? grade.min.value?.toFixed(2)
: "??",
bareme: "/" + grade.outOf.value,
}
]
},
],
},
{
title: "Influence",
Expand All @@ -104,21 +128,42 @@ const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
icon: <Scale />,
title: "Moyenne générale",
description: "Impact de la note sur la moyenne générale",
value: gradeDiff.difference === undefined ? "???" :
(gradeDiff.difference > 0 ? "- " : "+ ") +
gradeDiff.difference.toFixed(2).replace("-", "") + " pts",
color: gradeDiff.difference === undefined ? void 0 : (gradeDiff.difference < 0 ? "#4CAF50" : "#F44336"),
value:
gradeDiff.difference === undefined
? "???"
: (gradeDiff.difference > 0
? "- "
: gradeDiff.difference === 0
? "+/- "
: "+ ") +
gradeDiff.difference.toFixed(2).replace("-", "") +
" pts",
color:
gradeDiff.difference === undefined
? void 0
: gradeDiff.difference < 0
? "#4CAF50"
: gradeDiff.difference === 0
? theme.colors.text
: "#F44336",
},
!grade.average.disabled && {
icon: <School />,
title: "Moyenne de la classe",
description: "Impact de la note sur la moyenne de la classe",
value: classDiff.difference === undefined ? "???" :
(classDiff.difference > 0 ? "- " : "+ ") +
classDiff.difference.toFixed(2).replace("-", "") + " pts",
}
]
}
value:
classDiff.difference === undefined
? "???"
: (classDiff.difference > 0
? "- "
: gradeDiff.difference === 0
? "+/- "
: "+ ") +
classDiff.difference.toFixed(2).replace("-", "") +
" pts",
},
],
},
];

return (
Expand All @@ -137,49 +182,51 @@ const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
<NativeListHeader label={list.title} />

<NativeList>
{list.items.map((item, index) => item && (
<NativeItem
key={index}
icon={item.icon}
trailing={
<View
style={{
marginRight: 10,
alignItems: "flex-end",
flexDirection: "row",
gap: 2,
}}
{list.items.map(
(item, index) =>
item && (
<NativeItem
key={index}
icon={item.icon}
trailing={
<View
style={{
marginRight: 10,
alignItems: "flex-end",
flexDirection: "row",
gap: 2,
}}
>
<NativeText
style={{
fontSize: 18,
lineHeight: 22,
fontFamily: "semibold",
color:
"color" in item ? item.color : theme.colors.text,
}}
>
{item.value}
</NativeText>

{"bareme" in item && (
<NativeText variant="subtitle">
{item.bareme}
</NativeText>
)}
</View>
}
>
<NativeText
style={{
fontSize: 18,
lineHeight: 22,
fontFamily: "semibold",
color: "color" in item ? item.color : theme.colors.text,
}}
>
{item.value}
</NativeText>

{"bareme" in item &&
<NativeText variant="overtitle">{item.title}</NativeText>

{item.description && (
<NativeText variant="subtitle">
{item.bareme}
{item.description}
</NativeText>
}
</View>
}
>
<NativeText variant="overtitle">
{item.title}
</NativeText>

{item.description &&
<NativeText variant="subtitle">
{item.description}
</NativeText>
}
</NativeItem>
))}
)}
</NativeItem>
)
)}
</NativeList>
</View>
))}
Expand All @@ -189,4 +236,4 @@ const GradeDocument: Screen<"GradeDocument"> = ({ route, navigation }) => {
);
};

export default GradeDocument;
export default GradeDocument;
Loading
Loading