mirror of
https://framagit.org/enfance-libre/statistiques
synced 2025-12-07 07:23:44 +00:00
fix: améliore la gestion des données manquante
This commit is contained in:
parent
998714105b
commit
456cb3279d
17 changed files with 65 additions and 28 deletions
|
|
@ -1,9 +1,13 @@
|
||||||
|
import { StatsValue } from "../statistiques/v2/desc/StatsDesc";
|
||||||
import { ValueFormatOptions } from "./ValueFormatOptions";
|
import { ValueFormatOptions } from "./ValueFormatOptions";
|
||||||
|
|
||||||
export function formatValue(
|
export function formatValue(
|
||||||
value: number,
|
value: StatsValue,
|
||||||
valueFormatOptions: ValueFormatOptions
|
valueFormatOptions: ValueFormatOptions
|
||||||
) {
|
) {
|
||||||
|
if (value === undefined) {
|
||||||
|
return "Pas de données";
|
||||||
|
}
|
||||||
const valueStr = value.toLocaleString("fr-FR", {
|
const valueStr = value.toLocaleString("fr-FR", {
|
||||||
useGrouping: false,
|
useGrouping: false,
|
||||||
maximumFractionDigits:
|
maximumFractionDigits:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { formatValue } from "../../../format/formatValue";
|
import { formatValue } from "../../../format/formatValue";
|
||||||
import { ValueFormatOptions } from "../../../format/ValueFormatOptions";
|
import { ValueFormatOptions } from "../../../format/ValueFormatOptions";
|
||||||
import { StatsData } from "../../../statistiques/v2/desc/StatsDesc";
|
import { StatsData, StatsValue } from "../../../statistiques/v2/desc/StatsDesc";
|
||||||
import { chunk, isNumber } from "lodash";
|
import { chunk, isObject } from "lodash";
|
||||||
import { BlockObjectRequest } from "@notionhq/client/build/src/api-endpoints";
|
import { BlockObjectRequest } from "@notionhq/client/build/src/api-endpoints";
|
||||||
|
|
||||||
export function createSingleValueStatListItemBlock(
|
export function createSingleValueStatListItemBlock(
|
||||||
|
|
@ -9,7 +9,7 @@ export function createSingleValueStatListItemBlock(
|
||||||
formatOptions: ValueFormatOptions,
|
formatOptions: ValueFormatOptions,
|
||||||
data: StatsData
|
data: StatsData
|
||||||
): BlockObjectRequest {
|
): BlockObjectRequest {
|
||||||
if (isNumber(data)) {
|
if (!isObject(data)) {
|
||||||
return bulletedListNumberData(label, data, formatOptions);
|
return bulletedListNumberData(label, data, formatOptions);
|
||||||
} else if (data.relatedPageIds.length === 0) {
|
} else if (data.relatedPageIds.length === 0) {
|
||||||
return bulletedListNumberData(label, data.value, formatOptions);
|
return bulletedListNumberData(label, data.value, formatOptions);
|
||||||
|
|
@ -50,7 +50,7 @@ export function createSingleValueStatListItemBlock(
|
||||||
|
|
||||||
function bulletedListNumberData(
|
function bulletedListNumberData(
|
||||||
label: string,
|
label: string,
|
||||||
data: number,
|
data: StatsValue,
|
||||||
formatOptions: ValueFormatOptions
|
formatOptions: ValueFormatOptions
|
||||||
): BlockObjectRequest {
|
): BlockObjectRequest {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,11 @@ export function isMultiValueStatDesc(x: StatDesc): x is MultiValueStatDesc {
|
||||||
return "type" in x && x.type === "multi";
|
return "type" in x && x.type === "multi";
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StatsData = number | { value: number; relatedPageIds: string[] };
|
export type StatsValue = number | undefined;
|
||||||
|
|
||||||
|
export type StatsData =
|
||||||
|
| StatsValue
|
||||||
|
| { value: StatsValue; relatedPageIds: string[] };
|
||||||
|
|
||||||
export type StatType<T extends StatDesc> = T extends StatGroupListDesc
|
export type StatType<T extends StatDesc> = T extends StatGroupListDesc
|
||||||
? Record<
|
? Record<
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import {
|
||||||
isExResistant,
|
isExResistant,
|
||||||
isResistant,
|
isResistant,
|
||||||
} from "../../../data/Famille";
|
} from "../../../data/Famille";
|
||||||
import { average } from "../../../utils/math/average";
|
import { average } from "../math/average";
|
||||||
import { median } from "../../../utils/math/median";
|
import { median } from "../math/median";
|
||||||
import { StatsGenerales } from "./StatsGenerales";
|
import { StatsGenerales } from "./StatsGenerales";
|
||||||
import _, { countBy, uniq } from "lodash";
|
import _, { countBy, uniq } from "lodash";
|
||||||
import { isIntegrationEnCours } from "../../../data/StatutFamille";
|
import { isIntegrationEnCours } from "../../../data/StatutFamille";
|
||||||
|
|
|
||||||
7
src/statistiques/v2/math/average.ts
Normal file
7
src/statistiques/v2/math/average.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { StatsValue } from "../desc/StatsDesc";
|
||||||
|
|
||||||
|
export function average(values: number[]): StatsValue {
|
||||||
|
if (values.length === 0) return undefined;
|
||||||
|
|
||||||
|
return values.reduce((a, b) => a + b) / values.length;
|
||||||
|
}
|
||||||
7
src/statistiques/v2/math/max.ts
Normal file
7
src/statistiques/v2/math/max.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { StatsValue } from "../desc/StatsDesc";
|
||||||
|
|
||||||
|
export function max(values: number[]): StatsValue {
|
||||||
|
if (values.length === 0) return undefined;
|
||||||
|
|
||||||
|
return Math.max(...values);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
export function median(values: number[]): number {
|
import { StatsValue } from "../desc/StatsDesc";
|
||||||
if (values.length === 0) return NaN;
|
|
||||||
|
export function median(values: number[]): StatsValue {
|
||||||
|
if (values.length === 0) return undefined;
|
||||||
|
|
||||||
const sorted = [...values].sort((a, b) => a - b);
|
const sorted = [...values].sort((a, b) => a - b);
|
||||||
|
|
||||||
7
src/statistiques/v2/math/min.ts
Normal file
7
src/statistiques/v2/math/min.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { StatsValue } from "../desc/StatsDesc";
|
||||||
|
|
||||||
|
export function min(values: number[]): StatsValue {
|
||||||
|
if (values.length === 0) return undefined;
|
||||||
|
|
||||||
|
return Math.min(...values);
|
||||||
|
}
|
||||||
8
src/statistiques/v2/math/percent.ts
Normal file
8
src/statistiques/v2/math/percent.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { StatsValue } from "../desc/StatsDesc";
|
||||||
|
|
||||||
|
export function percent(value: StatsValue, total: StatsValue): StatsValue {
|
||||||
|
if (value === undefined || total === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return (100 * value) / total;
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ import { Famille } from "../../../data/Famille";
|
||||||
import { NamedStatsType } from "../desc/StatsDesc";
|
import { NamedStatsType } from "../desc/StatsDesc";
|
||||||
import { statsAmendesDesc } from "./StatsPenales";
|
import { statsAmendesDesc } from "./StatsPenales";
|
||||||
import { isEvtProcedurePenale } from "../../../data/EvenementFamille";
|
import { isEvtProcedurePenale } from "../../../data/EvenementFamille";
|
||||||
|
import { max } from "../math/max";
|
||||||
|
import { min } from "../math/min";
|
||||||
|
|
||||||
export function computeStatsAmendes(
|
export function computeStatsAmendes(
|
||||||
familles: Famille[]
|
familles: Famille[]
|
||||||
|
|
@ -38,10 +40,10 @@ export function computeStatsAmendes(
|
||||||
.map((a) => a.Montant);
|
.map((a) => a.Montant);
|
||||||
|
|
||||||
const stats = {
|
const stats = {
|
||||||
amendeMinAvecSursi: Math.min(...montantsAvecSursi),
|
amendeMinAvecSursi: min(montantsAvecSursi),
|
||||||
amendeMaxAvecSursi: Math.max(...montantsAvecSursi),
|
amendeMaxAvecSursi: max(montantsAvecSursi),
|
||||||
amendeMinFerme: Math.min(...montantsFerme),
|
amendeMinFerme: min(montantsFerme),
|
||||||
amendeMaxFerme: Math.max(...montantsFerme),
|
amendeMaxFerme: max(montantsFerme),
|
||||||
};
|
};
|
||||||
return [evtType, stats];
|
return [evtType, stats];
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import {
|
||||||
} from "./computeFamilleAvecInfosProceduresPenales";
|
} from "./computeFamilleAvecInfosProceduresPenales";
|
||||||
import { computeIntervalMedGendarmerieOuProcureur } from "./intervals/computeIntervalMedGendarmerieOuProcureur";
|
import { computeIntervalMedGendarmerieOuProcureur } from "./intervals/computeIntervalMedGendarmerieOuProcureur";
|
||||||
import { groupBy } from "lodash";
|
import { groupBy } from "lodash";
|
||||||
import { percent } from "../../../utils/math/percent";
|
import { percent } from "../math/percent";
|
||||||
import { isEvtTypeProcedurePenaleHorsGendarmerie } from "../../../data/TypeEvenementsPenal";
|
import { isEvtTypeProcedurePenaleHorsGendarmerie } from "../../../data/TypeEvenementsPenal";
|
||||||
import { computeStatsAmendes } from "./computeStatsAmendes";
|
import { computeStatsAmendes } from "./computeStatsAmendes";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import {
|
||||||
FamilleAvecInfosProceduresPenales,
|
FamilleAvecInfosProceduresPenales,
|
||||||
InfosProcedurePenale,
|
InfosProcedurePenale,
|
||||||
} from "../computeFamilleAvecInfosProceduresPenales";
|
} from "../computeFamilleAvecInfosProceduresPenales";
|
||||||
|
import { StatsValue } from "../../desc/StatsDesc";
|
||||||
|
|
||||||
export function computeIntervalGendarmerieProcureur(
|
export function computeIntervalGendarmerieProcureur(
|
||||||
familles: FamilleAvecInfosProceduresPenales[]
|
familles: FamilleAvecInfosProceduresPenales[]
|
||||||
): number {
|
): StatsValue {
|
||||||
return computeIntervalProcedurePenale(
|
return computeIntervalProcedurePenale(
|
||||||
familles,
|
familles,
|
||||||
(procPenal: InfosProcedurePenale): number | undefined => {
|
(procPenal: InfosProcedurePenale): number | undefined => {
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@ import {
|
||||||
} from "../computeFamilleAvecInfosProceduresPenales";
|
} from "../computeFamilleAvecInfosProceduresPenales";
|
||||||
import { computeIntervalProcedurePenale } from "./computeIntervalProcedurePenale";
|
import { computeIntervalProcedurePenale } from "./computeIntervalProcedurePenale";
|
||||||
import { min } from "lodash";
|
import { min } from "lodash";
|
||||||
|
import { StatsValue } from "../../desc/StatsDesc";
|
||||||
|
|
||||||
export function computeIntervalMedGendarmerieOuProcureur(
|
export function computeIntervalMedGendarmerieOuProcureur(
|
||||||
familles: FamilleAvecInfoProceduresPenales[]
|
familles: FamilleAvecInfoProceduresPenales[]
|
||||||
): number {
|
): StatsValue {
|
||||||
return computeIntervalProcedurePenale(
|
return computeIntervalProcedurePenale(
|
||||||
familles,
|
familles,
|
||||||
(procPenal: InfosProcedurePenale): number | undefined => {
|
(procPenal: InfosProcedurePenale): number | undefined => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Famille } from "../../../../data/Famille";
|
import { Famille } from "../../../../data/Famille";
|
||||||
import { average } from "../../../../utils/math/average";
|
import { StatsValue } from "../../desc/StatsDesc";
|
||||||
|
import { average } from "../../math/average";
|
||||||
import {
|
import {
|
||||||
FamilleAvecInfosProceduresPenales as FamilleAvecInfoProceduresPenales,
|
FamilleAvecInfosProceduresPenales as FamilleAvecInfoProceduresPenales,
|
||||||
InfosProcedurePenale,
|
InfosProcedurePenale,
|
||||||
|
|
@ -13,7 +14,7 @@ export function computeIntervalProcedurePenale(
|
||||||
famille: Famille
|
famille: Famille
|
||||||
) => number | undefined,
|
) => number | undefined,
|
||||||
intervalName: string
|
intervalName: string
|
||||||
): number {
|
): StatsValue {
|
||||||
const intervals: number[] = famillesAvecInfoProceduresPenales.flatMap((f) => {
|
const intervals: number[] = famillesAvecInfoProceduresPenales.flatMap((f) => {
|
||||||
return f.proceduresPenales
|
return f.proceduresPenales
|
||||||
.map((pp) => {
|
.map((pp) => {
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import {
|
||||||
FamilleAvecInfosProceduresPenales,
|
FamilleAvecInfosProceduresPenales,
|
||||||
InfosProcedurePenale,
|
InfosProcedurePenale,
|
||||||
} from "../computeFamilleAvecInfosProceduresPenales";
|
} from "../computeFamilleAvecInfosProceduresPenales";
|
||||||
|
import { StatsValue } from "../../desc/StatsDesc";
|
||||||
|
|
||||||
export function computeIntervalProcureurTribunalCorrectionnel(
|
export function computeIntervalProcureurTribunalCorrectionnel(
|
||||||
familles: FamilleAvecInfosProceduresPenales[]
|
familles: FamilleAvecInfosProceduresPenales[]
|
||||||
): number {
|
): StatsValue {
|
||||||
return computeIntervalProcedurePenale(
|
return computeIntervalProcedurePenale(
|
||||||
familles,
|
familles,
|
||||||
(procPenal: InfosProcedurePenale): number | undefined => {
|
(procPenal: InfosProcedurePenale): number | undefined => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
export function average(values: number[]): number {
|
|
||||||
if (values.length === 0) return NaN;
|
|
||||||
|
|
||||||
return values.reduce((a, b) => a + b) / values.length;
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export function percent(value: number, total: number): number {
|
|
||||||
return (100 * value) / total;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue