From c179d375375b2de24ee9b1a9872b82fa785913b2 Mon Sep 17 00:00:00 2001 From: Brice Maron Date: Sat, 30 Sep 2023 23:22:41 +0200 Subject: [PATCH] fix: add possibility to choose ISE if not defined --- src/AppContainer.tsx | 41 +++++++++++++++++++++++++++++++++-------- src/InputConfig.tsx | 25 ++++++++++++++++++++++--- src/SchoolDetail.tsx | 6 ++++-- src/compute.ts | 20 ++++++++++++++++---- 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/AppContainer.tsx b/src/AppContainer.tsx index ee5bc00..1538fcb 100644 --- a/src/AppContainer.tsx +++ b/src/AppContainer.tsx @@ -1,10 +1,10 @@ import { Alert, Container, Modal, Text } from "@mantine/core"; import { useMemo, useState } from "react"; -import { BooleanParam, JsonParam } from "use-query-params"; +import { BooleanParam, JsonParam, NumberParam, withDefault } from "use-query-params"; import { useQueryParam, StringParam } from "use-query-params"; import { useDisclosure, useLocalStorage } from "@mantine/hooks"; -import { ComputeResult, computeAll, primarySchools, secondarySchools } from "./compute"; +import { ComputeResult, UnexistingSchool, computeAll, primarySchools, secondarySchools } from "./compute"; import { NamedLoc } from "./GeoAutoComplete"; import { InputConfig } from "./InputConfig"; import ResultTable from "./ResultTable"; @@ -42,6 +42,7 @@ function useConfiguration() { const [immersion, setImmersion] = useQueryParam("immersion", BooleanParam); const [date, setDate] = useQueryParam("date", StringParam); + const [ise, setIse] = useQueryParam("ise", withDefault(NumberParam, 10)); return { idPrimaire, @@ -69,6 +70,11 @@ function useConfiguration() { setDate(v); refresh(); }, + ise, + setIse: (v: number) => { + setIse(v); + refresh(); + }, }; } function AppContainer() { @@ -83,20 +89,28 @@ function AppContainer() { setImmersion, date, setDate, + ise, + setIse, } = useConfiguration(); const [opened, { open, close }] = useDisclosure(false); const school_prim = primarySchools.find((school) => school.id === idPrimaire); const detailsSecondaire = secondarySchools.find((school) => school.id === idSecondaire); - const scores = useMemo(() => { + const scores = useMemo(() => { if (!school_prim || !locHome || !date) return null; - - const results = computeAll(secondarySchools, school_prim, locHome, date, immersion); - return results; + try { + const results = computeAll(secondarySchools, school_prim, locHome, date, immersion, ise); + return results; + } catch (e) { + console.error(e); + if (e instanceof UnexistingSchool) { + return e; + } + } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [school_prim?.id, locHome?.lat, locHome?.lon, immersion, date]); + }, [school_prim?.id, locHome?.lat, locHome?.lon, immersion, date, ise]); - if (!school_prim || !locHome || !date) { + if (!scores || scores instanceof UnexistingSchool) { return ( @@ -110,7 +124,15 @@ function AppContainer() { setImmersion={setImmersion} date={date} setDate={setDate} + ise={ise} + setIse={setIse} + isFaultyDate={scores instanceof UnexistingSchool} /> + {scores instanceof UnexistingSchool && ( + + Selon les informations que vous avez entrées, l'école primaire n'existait pas au moment de l'inscription. + + )} ); } @@ -128,6 +150,8 @@ function AppContainer() { setImmersion={setImmersion} date={date} setDate={setDate} + ise={ise} + setIse={setIse} />
)} diff --git a/src/InputConfig.tsx b/src/InputConfig.tsx index 323c5c1..cd0917c 100644 --- a/src/InputConfig.tsx +++ b/src/InputConfig.tsx @@ -1,8 +1,8 @@ import { Checkbox, Group, Select, Text } from "@mantine/core"; import GeoAutoComplete, { NamedLoc } from "./GeoAutoComplete"; import type { School } from "./compute"; -import { IconCalendar, IconSchool } from "@tabler/icons-react"; -import { forwardRef } from "react"; +import { IconCalendar, IconMoneybag, IconSchool } from "@tabler/icons-react"; +import { forwardRef, useMemo } from "react"; interface ItemProps extends React.ComponentPropsWithoutRef<"div"> { city: string; @@ -32,6 +32,9 @@ export function InputConfig({ setImmersion, date, setDate, + ise, + setIse, + isFaultyDate, }: { primarySchools: School[]; idPrimaire: string; @@ -42,6 +45,9 @@ export function InputConfig({ setImmersion: (v: boolean) => void; date: string; setDate: (v: string) => void; + ise: number; + setIse: (v: number) => void; + isFaultyDate: boolean; }) { const prim = primarySchools.map((school) => ({ value: school.id, @@ -49,6 +55,9 @@ export function InputConfig({ address: school.address, city: school.city, })); + const primSchool = useMemo(() => { + return idPrimaire ? primarySchools.find((p) => p.id === idPrimaire) : null; + }, [idPrimaire, primarySchools]); return ( <> @@ -70,11 +79,21 @@ export function InputConfig({ i + 1).map((i) => ({ label: `${i}`, value: `${i}` }))} + icon={} + value={`${ise}`} + onChange={(v) => setIse(parseInt(v, 10))} + mt={"md"} + /> + )} { let result: ComputeResult | undefined; const [gridOpened, handlers] = useDisclosure(false); @@ -190,8 +192,8 @@ const SchoolDetail = ({ const gridResult = useMemo(() => { if (!gridOpened) return null; console.log("compute"); - return getScoreGrid(school, result.primarySchool, locHome, date, immersion); - }, [school, result?.primarySchool, locHome, date, immersion, gridOpened]); + return getScoreGrid(school, result.primarySchool, locHome, date, immersion, ise); + }, [school, result?.primarySchool, locHome, date, immersion, gridOpened, ise]); return ( diff --git a/src/compute.ts b/src/compute.ts index 3961cee..054ddd3 100644 --- a/src/compute.ts +++ b/src/compute.ts @@ -164,6 +164,13 @@ export function hasBothSchoolsNetworkInCity(schools: School[], city: string) { return !!confessional && !!other; } +export class UnexistingSchool extends Error { + constructor(message) { + super(message); + this.name = "UnexistingSchool"; + } +} + export function compute( // note: for perf reasons, primary schools should already by filtered by network, newest removed, and ordered by distance primary: School[], @@ -172,11 +179,14 @@ export function compute( school_sec: School, locHome: GeoLoc, immersion: boolean, + ise?: number, ) { const coef_1 = rankCoef1[0]; // LA PRÉFÉRENCE 1.5 pour 1° const rank_2 = findNearestRank(primary, school_prim, locHome); - + if (rank_2 === 0) { + throw new UnexistingSchool(`Missing primary school ${school_prim.name}`); + } // const coef_2 = 1.3 // LA PROXIMITÉ ENTRE LE DOMICILE ET L’ÉCOLE PRIMAIRE (meme réseau) const coef_2 = rankCoef2[rank_2 - 1]; @@ -197,7 +207,7 @@ export function compute( const coef_7 = coef_6 == 1.51 || !school_prim.partenaria || school_prim.partenaria.id !== school_sec.id ? 1 : 1.51; // partenaria peda soit 1 soit 1.51 // LA CLASSE D'ENCADREMENT DE L'ÉCOLE PRIMAIRE (socio-économique) - const coef_8 = coef_8Table[school_prim.ise || 10]; // if not found, it's an average of students /o\ + const coef_8 = coef_8Table[school_prim.ise || ise || 10]; // if not found, it's an average of students /o\ return { coef_1, @@ -244,6 +254,7 @@ export function computeAll( locHome: GeoLoc, date: string, immersion: boolean, + ise?: number, ): ComputeResult[] { console.time("computeAll"); @@ -257,7 +268,7 @@ export function computeAll( school: school, primarySchools: prim, secondarySchools: sec, - score: compute(prim, sec, primarySchool, school, locHome, immersion), + score: compute(prim, sec, primarySchool, school, locHome, immersion, ise), home: locHome, distance: distance(school.geo, locHome), primarySchool: primarySchool, @@ -287,6 +298,7 @@ export function getScoreGrid( locHome: GeoLoc, date: string, immersion: boolean, + ise?: number, ): { grid: object; min: number; max: number; lines: object } { console.time("getScoreGrid"); @@ -314,7 +326,7 @@ export function getScoreGrid( const nLoc = { lon: currentFeature.geometry.coordinates[0], lat: currentFeature.geometry.coordinates[1] }; const prim = filterNewestAndOrderSchool(primarySchools, primarySchool.network, inscriptionDate, nLoc); const sec = Array.from(secondarySchools).sort(schoolSorter(nLoc)); - const score = compute(prim, sec, primarySchool, secondarySchool, nLoc, immersion); + const score = compute(prim, sec, primarySchool, secondarySchool, nLoc, immersion, ise); currentFeature.properties = { score: score.total, };