diff --git a/app/components/hub/average/AverageForm.tsx b/app/components/hub/average/AverageForm.tsx new file mode 100644 index 00000000..4aaa0b6a --- /dev/null +++ b/app/components/hub/average/AverageForm.tsx @@ -0,0 +1,179 @@ +import Select from '@mui/material/Select' +import MenuItem from '@mui/material/MenuItem' +import Typography from '@mui/material/Typography' +import InputLabel from '@mui/material/InputLabel' +import FormControl from '@mui/material/FormControl' +import { createContext, useEffect, useState } from 'react' + +import { Year } from 'global' +import AverageData from './data' + +import { + computeUEAverage, + computeSectorAverage, + computeSemesterAverage, + computeYearAverage, +} from './averageComputing' +import Semesters from './Semesters' +import { importAverageData, saveAverageData } from './averageStorage' + +export const AverageContext = createContext({ + data: AverageData, + updateData: ( + yearIndex: number, + semesterIndex: number, + sectorIndex: number, + ueIndex: number, + subjectIndex: number, + mark: number + ) => {}, +}) + +function AverageForm() { + const savedData = importAverageData() + + const [averageFormState, setAverageFormState] = useState({ + currentYearIndex: savedData.currentYearIndex, + currentSectorIndex: savedData.currentSectorIndex, + }) + + const [averageDataState, setAverageDataState] = useState(savedData.averageData) + + const updateSubjectMark = ( + yearIndex: number, + semesterIndex: number, + sectorIndex: number, + ueIndex: number, + subjectIndex: number, + mark: number + ) => { + let newState: Year[] = [...averageDataState] + + { + let year = newState[yearIndex] + + { + let semester = year.semesters[semesterIndex] + + { + let sector = semester.sectors[sectorIndex] + + { + let ue = sector.ues[ueIndex] + + ue.subjects[subjectIndex].mark = mark + + ue.average = computeUEAverage(ue) + sector.ues[ueIndex] = ue + } + + sector.average = computeSectorAverage(sector) + semester.sectors[sectorIndex] = sector + } + + semester.average = computeSemesterAverage(semester, averageFormState.currentSectorIndex) + year.semesters[semesterIndex] = semester + } + + year.average = computeYearAverage(year) + newState[yearIndex] = year + } + + setAverageDataState(newState) + } + + useEffect(() => { + saveAverageData( + averageDataState, + averageFormState.currentYearIndex, + averageFormState.currentSectorIndex + ) + }, [averageDataState, averageFormState]) + + const averageContextValue = { + data: averageDataState, + updateData: updateSubjectMark, + } + + const handleYearChange = (event) => { + setAverageFormState({ + ...averageFormState, + currentYearIndex: event.target.value, + }) + } + + const handleSectorChange = (event) => { + setAverageFormState({ + ...averageFormState, + currentSectorIndex: event.target.value, + }) + } + + const yearInput = ( + + Année + + + ) + + const currentYear = averageDataState[averageFormState.currentYearIndex] + + const sectorInput = (() => { + const sectors = averageDataState[averageFormState.currentYearIndex].semesters[0].sectors + + return ( + + Filière + + + ) + })() + + return ( + // @ts-ignore + +
+ {yearInput} + {sectorInput} + + + +
+ + Moyenne de {currentYear.name} : {currentYear.average ?? 'N/A'} + +
+
+ ) +} + +export default AverageForm diff --git a/app/components/hub/average/SectorTable.tsx b/app/components/hub/average/SectorTable.tsx new file mode 100644 index 00000000..64633883 --- /dev/null +++ b/app/components/hub/average/SectorTable.tsx @@ -0,0 +1,151 @@ +import Box from '@mui/material/Box' +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import { useState, useContext } from 'react' +import Collapse from '@mui/material/Collapse' +import TableRow from '@mui/material/TableRow' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import TableHead from '@mui/material/TableHead' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import TableContainer from '@mui/material/TableContainer' + +import KeyboardArrowUp from '@mui/icons-material/KeyboardArrowUpTwoTone' +import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDownTwoTone' + +import Subject from './Subject' +import { AverageContext } from './AverageForm' + +function UERow(props: { + yearIndex: number + semesterIndex: number + sectorIndex: number + ueIndex: number +}) { + const { yearIndex, semesterIndex, sectorIndex, ueIndex } = props + + const [open, setOpen] = useState(false) + const averageContext = useContext(AverageContext) + const ue = + averageContext.data[yearIndex].semesters[semesterIndex].sectors[sectorIndex].ues[ueIndex] + + return ( + <> + + + setOpen(!open)}> + {open ? : } + + + + {ue.name} + + {ue.average ?? 'N/A'} + {ue.ects} + + + + + + + + + Nom + Coefficient + Note + + + + {ue.subjects.map((subject, subjectIndex) => ( + + ))} + + + Moyenne + + + {ue.average ?? 'N/A'} + + + +
+
+
+
+
+ + ) +} + +export default function SectorTable(props: { + yearIndex: number + semesterIndex: number + sectorIndex: number +}) { + const { yearIndex, semesterIndex, sectorIndex } = props + + const averageContext = useContext(AverageContext) + const sector = averageContext.data[yearIndex].semesters[semesterIndex].sectors[sectorIndex] + + if (sector == null) { + return null + } + + return ( + <> + + {sector.name} + + + + + + + + Nom UE + Moyenne + ETC + + + + {sector.ues.map((ue, ueIndex) => ( + + ))} + + + + Moyenne de la filière + + + {sector.average ?? 'N/A'} + + + +
+
+ + ) +} diff --git a/app/components/hub/average/Semesters.tsx b/app/components/hub/average/Semesters.tsx new file mode 100644 index 00000000..9700f8be --- /dev/null +++ b/app/components/hub/average/Semesters.tsx @@ -0,0 +1,64 @@ +import { useContext } from 'react' +import Typography from '@mui/material/Typography' + +import SectorTable from './SectorTable' +import { AverageContext } from './AverageForm' + +function Semester(props: { yearIndex: number; semesterIndex: number; sectorIndex: number }) { + const { yearIndex, semesterIndex, sectorIndex } = props + + const averageContext = useContext(AverageContext) + const semester = averageContext.data[yearIndex].semesters[semesterIndex] + + return ( + <> +
+ + + Semestre {semesterIndex + 1} + + + + + {sectorIndex !== 0 ? ( + + ) : null} + +
+ + Moyenne du semestre {semesterIndex + 1} : {semester.average ?? 'N/A'} + + + ) +} + +export default function Semesters(props: { yearIndex: number; sectorIndex: number }) { + const { yearIndex, sectorIndex } = props + + const averageContext = useContext(AverageContext) + const year = averageContext.data[yearIndex] + + return ( + <> +
+ {year.semesters.map((semester, semesterIndex) => ( + + ))} + + ) +} diff --git a/app/components/hub/average/Subject.tsx b/app/components/hub/average/Subject.tsx new file mode 100644 index 00000000..290a0536 --- /dev/null +++ b/app/components/hub/average/Subject.tsx @@ -0,0 +1,65 @@ +import { useContext, useState } from 'react' +import TableRow from '@mui/material/TableRow' +import TableCell from '@mui/material/TableCell' +import TextField from '@mui/material/TextField' +import InputAdornment from '@mui/material/InputAdornment' + +import { AverageContext } from './AverageForm' + +function Subject(props: { + yearIndex: number + semesterIndex: number + sectorIndex: number + ueIndex: number + subjectIndex: number +}) { + const { yearIndex, semesterIndex, sectorIndex, ueIndex, subjectIndex } = props + + const averageContext = useContext(AverageContext) + const subject = + averageContext.data[yearIndex].semesters[semesterIndex].sectors[sectorIndex].ues[ueIndex] + .subjects[subjectIndex] + + const [mark, setMark] = useState(subject.mark) + + const handleMarkChange = (event) => { + if (event.target.valueAsNumber >= 0 && event.target.valueAsNumber <= 20) { + const newMark: number = event.target.valueAsNumber + + averageContext.updateData( + yearIndex, + semesterIndex, + sectorIndex, + ueIndex, + subjectIndex, + newMark + ) + setMark(newMark) + } else if (event.target.value == '') { + setMark(undefined) + } + } + + return ( + + + {subject.name} + + {subject.coef} + + / 20, + }} + /> + + + ) +} + +export default Subject diff --git a/app/components/hub/average/averageComputing.ts b/app/components/hub/average/averageComputing.ts new file mode 100644 index 00000000..002aa76e --- /dev/null +++ b/app/components/hub/average/averageComputing.ts @@ -0,0 +1,99 @@ +import { SectorData, SemesterData, UEData, Year } from 'global' + +export const computeUEAverage = (ue: UEData): number | undefined => { + let average = 0 + let coefSum = 0 + + for (let subjectIndex in ue.subjects) { + if (ue.subjects[subjectIndex].mark == null) { + continue + } + + // @ts-ignore + average += ue.subjects[subjectIndex].mark * subjects[subjectIndex].coef + coefSum += ue.subjects[subjectIndex].coef + } + + if (coefSum === 0) { + return undefined + } + + average /= coefSum + + return Math.round(average * 1000) / 1000 +} + +export const computeSectorAverage = (sector: SectorData): number | undefined => { + let average = 0 + let sum = 0 + + for (let ueIndex in sector.ues) { + if (sector.ues[ueIndex].average == null) { + continue + } + + // @ts-ignore + average += sector.ues[ueIndex].average + sum++ + } + + if (sum === 0) { + return undefined + } + + average /= sum + + return Math.round(average * 1000) / 1000 +} + +export const computeSemesterAverage = ( + semester: SemesterData, + currentSectorIndex: number +): number | undefined => { + let average = 0 + let count = 0 + + // Tronc commun + if (semester.sectors[0].average) { + // @ts-ignore + average += semester.sectors[0].average + count++ + } + + if (semester.sectors[currentSectorIndex].average) { + // @ts-ignore + average += semester.sectors[averageFormState.currentSector].average + count++ + } + + if (average === 0) { + return undefined + } + + average /= 2 + + return Math.round(average * 1000) / 1000 +} + +export const computeYearAverage = (year: Year): number | undefined => { + let average = 0 + let sum = 0 + + for (let semesterIndex in year.semesters) { + if (year.semesters[semesterIndex].average == null) { + continue + } + + // @ts-ignore + average += year.semesters[semesterIndex].average + sum++ + } + + if (sum === 0) { + return undefined + } + + average /= sum + + return Math.round(average * 1000) / 1000 +} diff --git a/app/components/hub/average/averageStorage.ts b/app/components/hub/average/averageStorage.ts new file mode 100644 index 00000000..80fcac3c --- /dev/null +++ b/app/components/hub/average/averageStorage.ts @@ -0,0 +1,37 @@ +import { Year } from 'global' +import averageData from './data' + +export const importAverageData = (): { + averageData: Year[] + currentYearIndex: number + currentSectorIndex: number +} => { + let data: any = localStorage.getItem('average_data') + if (data === null) { + data = { + averageData, + currentYearIndex: 0, + currentSectorIndex: 0, + } + } else { + data = JSON.parse(data) + } + + return data +} + +export const saveAverageData = ( + averageData: Year[], + currentYearIndex: number, + currentSectorIndex: number +) => { + const dataToStore = { + averageData: averageData, + currentYearIndex: currentYearIndex, + currentSectorIndex: currentSectorIndex, + } + + const dataToStoreStr = JSON.stringify(dataToStore) + + localStorage.setItem('average_data', dataToStoreStr) +} diff --git a/app/components/hub/average/data/index.ts b/app/components/hub/average/data/index.ts new file mode 100644 index 00000000..0516d94f --- /dev/null +++ b/app/components/hub/average/data/index.ts @@ -0,0 +1,7 @@ +import zz1 from './zz1' +import zz2 from './zz2' +import zz3 from './zz3' + +const data = [zz1, zz2, zz3] + +export default data diff --git a/app/components/hub/average/data/zz1.ts b/app/components/hub/average/data/zz1.ts new file mode 100644 index 00000000..e8f61569 --- /dev/null +++ b/app/components/hub/average/data/zz1.ts @@ -0,0 +1,210 @@ +import { SemesterData, Year } from 'global' + +const semester1: SemesterData = { + sectors: [ + { + name: 'Tronc commun', + ues: [ + { + name: 'Sciences Humaines et Sociales', + subjects: [ + { + name: 'Anglais', + coef: 1.0, + }, + { + name: 'LV2', + coef: 1.0, + }, + { + name: 'Management et organisation des entreprises', + coef: 1.0, + }, + ], + ects: 5, + }, + { + name: 'Informatique', + subjects: [ + { + name: 'C / Unix', + coef: 2.5, + }, + { + name: 'SDD', + coef: 2.5, + }, + { + name: 'Programmation fonctionnelle', + coef: 1.0, + }, + { + name: 'Automates', + coef: 1.0, + }, + ], + ects: 12, + }, + { + name: "Sciences de l'ingénieur", + subjects: [ + { + name: 'Physique', + coef: 1.0, + }, + { + name: 'Transmission de données', + coef: 1.0, + }, + { + name: 'Traitement du signal', + coef: 1.0, + }, + { + name: 'Conception de systèmes numériques', + coef: 1.5, + }, + ], + ects: 8, + }, + { + name: 'Maths', + subjects: [ + { + name: 'Graphes', + coef: 1.0, + }, + { + name: 'Probabilités', + coef: 1.0, + }, + { + name: 'Analyse numérique', + coef: 1.0, + }, + { + name: 'Soutien maths', + coef: 2.0, + }, + ], + ects: 5, + }, + ], + }, + ], +} + +const semester2: SemesterData = { + sectors: [ + { + name: 'Tronc commun', + ues: [ + { + name: 'Sciences Humaines et Sociales', + subjects: [ + { + name: 'Anglais', + coef: 1.0, + }, + { + name: 'LV2', + coef: 1.0, + }, + { + name: 'Communication', + coef: 1.0, + }, + ], + ects: 5, + }, + { + name: 'Informatique', + subjects: [ + { + name: 'SDD', + coef: 1.5, + }, + { + name: 'Bases de données', + coef: 1.0, + }, + { + name: 'Cybersécurité', + coef: 1.0, + }, + { + name: "Systèmes d'exploitation", + coef: 1.0, + }, + ], + ects: 9, + }, + { + name: "Sciences de l'ingénieur", + subjects: [ + { + name: 'TPs Physique', + coef: 3.0, + }, + { + name: 'TPs Transmission de données', + coef: 3.0, + }, + { + name: 'Automatique', + coef: 4.0, + }, + ], + ects: 5, + }, + { + name: 'Maths', + subjects: [ + { + name: 'Analyse numérique', + coef: 1.0, + }, + { + name: 'Calcul diff', + coef: 1.0, + }, + { + name: 'Programmation linéaire', + coef: 1.0, + }, + { + name: 'Analyse de données', + coef: 1.0, + }, + { + name: 'Probabilités', + coef: 1.0, + }, + { + name: 'Soutien maths', + coef: 1.0, + }, + ], + ects: 8, + }, + { + name: 'Professionalisation', + subjects: [ + { + name: 'Projet / Stage', + coef: 1.0, + }, + ], + ects: 2, + }, + ], + }, + ], +} + +const zz1: Year = { + name: 'ZZ1', + semesters: [semester1, semester2], +} + +export default zz1 diff --git a/app/components/hub/average/data/zz2.ts b/app/components/hub/average/data/zz2.ts new file mode 100644 index 00000000..1885a006 --- /dev/null +++ b/app/components/hub/average/data/zz2.ts @@ -0,0 +1,455 @@ +import { SemesterData, Year } from 'global' + +const semester1: SemesterData = { + sectors: [ + { + name: 'Tronc commun', + ues: [ + { + name: 'Sciences Humaines et Sociales', + subjects: [ + { + name: 'Anglais', + coef: 4.0, + }, + { + name: 'LV2', + coef: 4.0, + }, + { + name: 'Droit', + coef: 2.0, + }, + { + name: 'Communication', + coef: 2.0, + }, + { + name: 'Gestion', + coef: 2.0, + }, + { + name: 'Conduite de projets', + coef: 2.0, + }, + ], + ects: 8, + }, + { + name: 'Scientifique', + subjects: [ + { + name: 'C++', + coef: 4.0, + }, + { + name: 'UML', + coef: 2.0, + }, + { + name: 'Java', + coef: 2.0, + }, + { + name: 'Internet des Objets', + coef: 1.0, + }, + { + name: 'Réseaux', + coef: 2.0, + }, + ], + ects: 6, + }, + ], + }, + { + name: 'F1', + ues: [ + { + name: 'Systèmes embarqués et temps réel', + subjects: [ + { + name: 'Linux embarqué', + coef: 3.0, + }, + { + name: 'Architecture avancée', + coef: 2.0, + }, + { + name: 'Design', + coef: 2.0, + }, + { + name: 'Systèmes embarqués', + coef: 3.0, + }, + { + name: "Séminaire Systèmes d'Exploitation Embarqués", + coef: 2.0, + }, + ], + ects: 6, + }, + { + name: 'Traitement des informations', + subjects: [ + { + name: 'Traitement numérique du signal', + coef: 2.0, + }, + { + name: 'Transmission de données sécurisée', + coef: 2.0, + }, + { + name: 'Imagerie vision', + coef: 2.0, + }, + { + name: 'Capteurs', + coef: 2.0, + }, + ], + ects: 5, + }, + { + name: 'Systèmes intelligents', + subjects: [ + { + name: 'Robotique', + coef: 2.0, + }, + { + name: 'Réalité virtuelle', + coef: 2.0, + }, + { + name: 'Réalité immersive', + coef: 2.0, + }, + { + name: 'Cybernétique Automatique', + coef: 2.0, + }, + ], + ects: 4, + }, + ], + }, + { + name: 'F2', + ues: [ + { + name: 'Systèmes et réseaux', + subjects: [ + { + name: "Systèmes d'exploitation", + coef: 2.0, + }, + { + name: "Sécurité et systèmes d'information", + coef: 2.0, + }, + { + name: 'Services Web .NET C#', + coef: 3.0, + }, + ], + ects: 5, + }, + { + name: 'Génie logiciel et développement', + subjects: [ + { + name: 'Forges logicielles', + coef: 2.0, + }, + { + name: 'Développement .NET C#', + coef: 2.0, + }, + { + name: "Développement d'applications Web", + coef: 3.0, + }, + { + name: 'Architectures logicielles et qualité', + coef: 2.0, + }, + ], + ects: 5, + }, + { + name: 'Outils', + subjects: [ + { + name: 'Simulation', + coef: 2.0, + }, + { + name: 'Ergonomie des IHM', + coef: 2.0, + }, + { + name: 'Développement de bases de données', + coef: 2.0, + }, + { + name: "Outils d'aide à la décision", + coef: 3.0, + }, + ], + ects: 5, + }, + ], + }, + { + name: 'F3', + ues: [ + { + name: "Connaissances de l'entreprise", + subjects: [ + { + name: "Sécurité et systèmes d'Information", + coef: 2.0, + }, + { + name: "Outil de développement mobile pour le SI de l'entreprise", + coef: 2.0, + }, + { + name: 'Architectures logicielles et qualités', + coef: 2.0, + }, + { + name: 'Développement Web', + coef: 2.0, + }, + ], + ects: 4, + }, + { + name: "Systèmes d'information", + subjects: [ + { + name: 'Développement de Bases de Données', + coef: 2.0, + }, + { + name: 'Analyse et fouille de données', + coef: 4.0, + }, + { + name: 'Fondements des Bases de Données', + coef: 3.0, + }, + ], + ects: 5, + }, + { + name: 'RO et Aide à la décision', + subjects: [ + { + name: 'Simulation à flux discrets', + coef: 4.0, + }, + { + name: 'Modélisation des processus aléatoires', + coef: 2.0, + }, + { + name: "Outils d'aide à la décision", + coef: 3.0, + }, + { + name: 'Recherche Opérationnelle', + coef: 2.0, + }, + ], + ects: 6, + }, + ], + }, + { + name: 'F4', + ues: [ + { + name: 'Science des données', + subjects: [ + { + name: 'Bases de données et fouille de données', + coef: 2.0, + }, + { + name: 'Statistiques', + coef: 2.0, + }, + { + name: 'Matlab', + coef: 2.0, + }, + { + name: 'Imagerie Vision', + coef: 2.0, + }, + { + name: 'Apprentissage statistique', + coef: 2.5, + }, + ], + ects: 5, + }, + { + name: 'Calcul scientifique', + subjects: [ + { + name: 'Éléments finis', + coef: 4.0, + }, + { + name: 'Méthodes de différences finies', + coef: 1.5, + }, + { + name: 'Mécanique du solide', + coef: 2.0, + }, + { + name: 'Intégration et Distributions', + coef: 4.0, + }, + ], + ects: 6, + }, + { + name: 'Recherche opérationnelle et optimisation', + subjects: [ + { + name: 'Recherche Opérationnelle', + coef: 3.5, + }, + { + name: 'Modélisation des processus aléatoires', + coef: 2.0, + }, + { + name: 'Optimisation', + coef: 1.5, + }, + ], + ects: 4, + }, + ], + }, + { + name: 'F5', + ues: [ + { + name: 'Informatique avancée', + subjects: [ + { + name: 'Certification industrielle', + coef: 2.0, + }, + { + name: 'Services Web .NET C#', + coef: 3.0, + }, + { + name: 'Cloud', + coef: 2.0, + }, + { + name: 'Intégration continue pour le web', + coef: 2.0, + }, + ], + ects: 5, + }, + { + name: 'Sécurité des couches réseaux', + subjects: [ + { + name: 'Sécurisation des protocoles réseaux', + coef: 2.0, + }, + { + name: 'Sécurité des objets connectés', + coef: 2.0, + }, + { + name: 'Sécurisation active des systèmes en réseau', + coef: 2.0, + }, + { + name: 'Transmission de données sécurisée', + coef: 2.0, + }, + ], + ects: 5, + }, + { + name: 'Sécurité des couches applicatives', + subjects: [ + { + name: 'Sécurité Web', + coef: 2.0, + }, + { + name: "Systèmes d'exploitation", + coef: 2.0, + }, + { + name: 'Analyse de malware - Rétroingénierie', + coef: 2.0, + }, + { + name: "Tests d'intrusion (pentest)", + coef: 2.0, + }, + ], + ects: 5, + }, + ], + }, + ], +} + +const semester2: SemesterData = { + sectors: [ + { + name: 'Tronc commun', + ues: [ + { + name: 'Projet', + subjects: [ + { + name: 'Projet', + coef: 1.0, + }, + ], + ects: 3, + }, + { + name: 'Stage', + subjects: [ + { + name: 'Stage', + coef: 1.0, + }, + ], + ects: 27, + }, + ], + }, + ], +} + +const zz2: Year = { + name: 'ZZ2', + semesters: [semester1, semester2], +} + +export default zz2 diff --git a/app/components/hub/average/data/zz3.ts b/app/components/hub/average/data/zz3.ts new file mode 100644 index 00000000..87a94bb5 --- /dev/null +++ b/app/components/hub/average/data/zz3.ts @@ -0,0 +1,451 @@ +import { SemesterData, Year } from 'global' + +const semester1: SemesterData = { + sectors: [ + { + name: 'Tronc commun', + ues: [ + { + name: 'Langues', + subjects: [ + { + name: 'Anglais', + coef: 2.0, + }, + { + name: 'LV2', + coef: 2.0, + }, + ], + ects: 3, + }, + { + name: 'Tertiaire', + subjects: [ + { + name: 'Droit', + coef: 2.0, + }, + { + name: 'Communication', + coef: 3.0, + }, + { + name: 'Intelligence économique', + coef: 1.0, + }, + { + name: 'Ethique, déontologie et développement durable', + coef: 2.0, + }, + ], + ects: 4, + }, + { + name: 'Méthodes et outils de développement logiciel', + subjects: [ + { + name: 'Méthodes et outils de développement logiciel', + coef: 4.0, + }, + ], + ects: 3, + }, + { + name: 'Projet', + subjects: [ + { + name: 'Projet', + coef: 5.0, + }, + ], + ects: 5, + }, + ], + }, + { + name: 'F1', + ues: [ + { + name: 'Programmation avancée', + subjects: [ + { + name: "Programmation d'applications mobiles", + coef: 3.0, + }, + { + name: 'Sécurité des systèmes embarqués', + coef: 2.0, + }, + ], + ects: 3, + }, + { + name: 'Programmation embarquée', + subjects: [ + { + name: 'Programmation FPGA - VHDL', + coef: 3.0, + }, + { + name: 'Programmation temps réel', + coef: 3.0, + }, + ], + ects: 4, + }, + { + name: 'Outils et méthodes de réalité virtuelle', + subjects: [ + { + name: 'Programmation GPGPU', + coef: 2.0, + }, + { + name: 'Réalité augmentée et mixte', + coef: 3.0, + }, + { + name: 'Géométrie algorithmique', + coef: 2.0, + }, + ], + ects: 4, + }, + { + name: 'Systèmes interactifs', + subjects: [ + { + name: 'Intégration capteurs pour la robotique', + coef: 2.0, + }, + { + name: 'Objets connectés', + coef: 2.0, + }, + { + name: 'Robotique mobile', + coef: 3.0, + }, + ], + ects: 4, + }, + ], + }, + { + name: 'F2', + ues: [ + { + name: 'Systèmes et réseaux', + subjects: [ + { + name: 'Sécurité réseaux', + coef: 2.0, + }, + { + name: 'Ecosystèmes Javascript', + coef: 4.0, + }, + ], + ects: 3, + }, + { + name: 'Génie logiciel et développement', + subjects: [ + { + name: 'DevOps', + coef: 2.0, + }, + { + name: "Programmation d'applications mobiles (PAM)", + coef: 3.0, + }, + { + name: 'Ingénierie des Modèles et Simulation', + coef: 3.0, + }, + { + name: 'Algorithmique pour le calcul parallèle', + coef: 2.0, + }, + ], + ects: 5, + }, + { + name: 'Modélisation et calcul', + subjects: [ + { + name: 'Grilles de Calcul et Cloud', + coef: 2.0, + }, + { + name: 'Apprentissage profond', + coef: 2.0, + }, + { + name: "Algorithmique de l'aide à la décision", + coef: 2.0, + }, + ], + ects: 3, + }, + { + name: "Informatique pour l'entreprise", + subjects: [ + { + name: "Intégration d'applications", + coef: 3.0, + }, + { + name: 'Administration sécurisée des bases de données', + coef: 3.0, + }, + { + name: "Conception d'applications Java Professionnelles", + coef: 2.0, + }, + ], + ects: 4, + }, + ], + }, + { + name: 'F3', + ues: [ + { + name: 'Connaissances et modélisation des entreprises', + subjects: [ + { + name: 'Modélisation et Gestion intégrée de la chaîne logistique', + coef: 3.0, + }, + { + name: 'R.O. et I.A. pour la productique', + coef: 2.0, + }, + { + name: 'Business Intelligence', + coef: 4.0, + }, + ], + ects: 5, + }, + { + name: "Ingénierie des systèmes d'information", + subjects: [ + { + name: "Intégration d'applicationss", + coef: 2.0, + }, + { + name: 'Web Services', + coef: 2.0, + }, + { + name: "Systèmes d'information", + coef: 2.0, + }, + { + name: 'Administration des bases de données', + coef: 4.0, + }, + ], + ects: 6, + }, + { + name: "Modélisation pour l'aide à la décision", + subjects: [ + { + name: "Algorithmique de l'aide à la décision", + coef: 2.0, + }, + { + name: 'Big Data', + coef: 2.0, + }, + { + name: 'Evaluation et optimisation des systèmes', + coef: 2.0, + }, + ], + ects: 4, + }, + ], + }, + { + name: 'F4', + ues: [ + { + name: 'Science des données', + subjects: [ + { + name: 'Apprentissage profond', + coef: 2.0, + }, + { + name: 'Big mcc_data', + coef: 2.0, + }, + ], + ects: 3, + }, + { + name: 'Recherche opérationnelle et optimisation', + subjects: [ + { + name: 'Etude de cas en R.O.', + coef: 3.0, + }, + { + name: 'Optimisation des systèmes complexes', + coef: 2.0, + }, + { + name: 'Programmation Non Linéaire', + coef: 2.0, + }, + { + name: 'Optimisation Convexe', + coef: 1.5, + }, + ], + ects: 5, + }, + { + name: 'Calcul scientifique', + subjects: [ + { + name: 'Equations aux Dérivées Partielles', + coef: 4.0, + }, + { + name: 'Algorithmique pour le Calcul Parallèle', + coef: 2.5, + }, + { + name: 'Méthodes de décomposition de domaines', + coef: 1.0, + }, + ], + ects: 4, + }, + { + name: 'Langage et Applications', + subjects: [ + { + name: 'Compléments de Génie Logiciel (JAVA)', + coef: 1.5, + }, + { + name: 'Eléments de CAO', + coef: 1.5, + }, + { + name: 'Mécanique du solide', + coef: 2, + }, + ], + ects: 3, + }, + ], + }, + { + name: 'F5', + ues: [ + { + name: 'Réseaux', + subjects: [ + { + name: 'Certification industrielle', + coef: 2.0, + }, + { + name: 'Routage', + coef: 2.0, + }, + ], + ects: 3, + }, + { + name: 'Informatique des réseaux', + subjects: [ + { + name: 'Administration sécurisée des bases de données', + coef: 2.0, + }, + { + name: 'Développement web (JEE)', + coef: 2.0, + }, + { + name: 'Programmation objet avancée', + coef: 2.0, + }, + { + name: 'Technologie des conteneurs', + coef: 2.0, + }, + { + name: "Programmation d'applications mobiles", + coef: 3.0, + }, + ], + ects: 6, + }, + { + name: 'Sécurité', + subjects: [ + { + name: 'Théorie des codes et cryptographie', + coef: 3.0, + }, + { + name: 'Politique de sécurité', + coef: 2.0, + }, + { + name: 'Analyse post-mortem (Forensic)', + coef: 2.0, + }, + { + name: 'Sécurité réseaux', + coef: 2.0, + }, + { + name: "Architecture d'un réseau sécurisé", + coef: 2.0, + }, + ], + ects: 6, + }, + ], + }, + ], +} + +const semester2: SemesterData = { + sectors: [ + { + name: 'Tronc commun', + ues: [ + { + name: "Projet de fin d'étude", + subjects: [ + { + name: "Projet de fin d'étude", + coef: 1.0, + }, + ], + ects: 30, + }, + ], + }, + ], +} + +const zz3: Year = { + name: 'ZZ3', + semesters: [semester1, semester2], +} + +export default zz3 diff --git a/app/components/nav/hub/submenus/ModulesMenu.tsx b/app/components/nav/hub/submenus/ModulesMenu.tsx index f186238c..429d1a0c 100644 --- a/app/components/nav/hub/submenus/ModulesMenu.tsx +++ b/app/components/nav/hub/submenus/ModulesMenu.tsx @@ -8,6 +8,7 @@ import ListItemIcon from '@mui/material/ListItemIcon' import Apps from '@mui/icons-material/AppsTwoTone' import HowToVote from '@mui/icons-material/HowToVoteTwoTone' import Extension from '@mui/icons-material/ExtensionTwoTone' +import Calculate from '@mui/icons-material/CalculateTwoTone' import Menu from './Menu' import Link from 'app/core/lib/Link' @@ -40,6 +41,22 @@ export default function ModulesMenu() { + + + + + + + Calculateur de moyenne + + + + diff --git a/app/pages/hub/modules/average.tsx b/app/pages/hub/modules/average.tsx new file mode 100644 index 00000000..f32971ad --- /dev/null +++ b/app/pages/hub/modules/average.tsx @@ -0,0 +1,30 @@ +import Paper from '@mui/material/Paper' +import { BlitzPage, Routes } from 'blitz' +import Typography from '@mui/material/Typography' + +import getHubNav from 'app/components/nav/hub/getHubNav' +import AverageForm from 'app/components/hub/average/AverageForm' + +const Average: BlitzPage = () => { + return ( + + + Calculateur de moyenne + + + + Séléctionnez votre année, remplissez le tableau et votre moyenne sera calculée.
+ Les données saisies seront uniquement stockées sur votre navigateur et resteront strictement + personnelles. +
+ + +
+ ) +} + +Average.suppressFirstRenderFlicker = true +Average.authenticate = { redirectTo: Routes.Login() } +Average.getLayout = (page) => getHubNav(page, 'Calculateur de moyenne') + +export default Average diff --git a/db/seeds/users.ts b/db/seeds/users.ts index 4eadc67d..c1fe32a5 100644 --- a/db/seeds/users.ts +++ b/db/seeds/users.ts @@ -19,6 +19,20 @@ const users = async (db) => { }, }) + await db.user.create({ + data: { + lastname: 'VÉROT', + firstname: 'Corentin', + nickname: 'Corentin', + image: faker.image.imageUrl(100, 100, undefined, false, true), + email: 'corentin.verot@outlook.com', + card: 1511, + balance: 1000, + roles: '*', + promotionId: promotion.id, + }, + }) + for (let i = 0; i < 4; ++i) { await db.user.create({ data: { diff --git a/global.d.ts b/global.d.ts index 23c6b4bf..d9caf466 100644 --- a/global.d.ts +++ b/global.d.ts @@ -9,6 +9,9 @@ import { User, Event, EventSubscription } from 'db' import { DefaultCtx, SessionContext, SimpleRolesIsAuthorized } from 'blitz' +/** + * app.tsx related types + */ export type BDEAppProps = AppProps & { emotionCache?: EmotionCache Component: NextPage & { @@ -16,6 +19,9 @@ export type BDEAppProps = AppProps & { } } +/** + * Events and subscriptions related types + */ export interface Item { name: string description: string | null @@ -48,6 +54,44 @@ export interface EventSubscriptionWithTypedCart extends Omit