Skip to content

Commit

Permalink
Merge pull request #318 from dataforgoodfr/chore/process-todo-in-code
Browse files Browse the repository at this point in the history
Chore/process todo in code
  • Loading branch information
Baboo7 authored Aug 29, 2023
2 parents 34d88ef + ea094b9 commit 68d9861
Show file tree
Hide file tree
Showing 38 changed files with 599 additions and 648 deletions.
10 changes: 1 addition & 9 deletions packages/client/src/lib/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { differenceInDays } from "date-fns";
import { ENERGY_SHIFT_TARGET_YEAR } from "../modules/common/constants";
import { userLocale } from "../modules/translations";

export { formatDate, getDaysTo2050, getDaysToEnergyShiftTargetYear };
export { formatDate, getDaysToEnergyShiftTargetYear };

type DateFormat = "date-at-time" | "full-date-at-time";

Expand Down Expand Up @@ -37,14 +37,6 @@ function formatDate(
).format(new Date(date));
}

// TODO: Replace use with getDaysToEnergyShiftTargetYear.
/**
* @deprecated Use getDaysToEnergyShiftTargetYear instead.
*/
function getDaysTo2050() {
return Math.round(differenceInDays(new Date("01/01/2050"), new Date()));
}

function getDaysToEnergyShiftTargetYear(refDate: Date = new Date()) {
return Math.round(
differenceInDays(new Date(`01/01/${ENERGY_SHIFT_TARGET_YEAR}`), refDate)
Expand Down
16 changes: 2 additions & 14 deletions packages/client/src/modules/charts/DetailsEnergyBars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ import {
Cell,
} from "recharts";
import { EnergyPalette, ProductionPalette } from "../../utils/theme";
import { hasNuclear, roundValue } from "../common/utils";
import { roundValue } from "../common/utils";
import { ConsumptionDatum } from "../persona/consumption";
import { Persona } from "../persona/persona";
import { ProductionDatum } from "../persona/production";
import { productionConstants } from "../play";
import { usePlay } from "../play/context/playContext";
import { translateName, useTranslation } from "../translations";
import { Typography } from "../common/components/Typography";

Expand Down Expand Up @@ -44,20 +42,10 @@ function DetailsEnergyProductionBars({
persona: Persona;
}) {
const theme = useTheme();
const { game } = usePlay();

const personaValues = persona.production.filter(
({ type }: ProductionDatum) => {
if (!hasNuclear(game) && type === productionConstants.NUCLEAR.name) {
return false;
}
return true;
}
);

return DetailsEnergyBars(
"production",
personaValues,
persona.productionDisplayed,
theme.palette.production,
title
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { useMemo } from "react";
import { Persona } from "../../persona/persona";
import { useTranslation } from "../../translations/useTranslation";
import {
DetailsEnergyConsumptionBars,
DetailsEnergyProductionBars,
} from "../DetailsEnergyBars";
import {
EnergyConsumptionButtons,
EnergyProductionButtons,
} from "../../common/components/EnergyButtons";
import { StepDatum } from "./types";
import { getStackName } from "./utils";

export { EnergyBalanceDetailsForPlayerGraph };

function EnergyBalanceDetailsForPlayerGraph({
stepDatum,
getPersonaAtStep,
}: {
stepDatum: StepDatum;
getPersonaAtStep: (step: number) => Persona;
}) {
const { t } = useTranslation();

const DetailsContent = useMemo(() => {
const persona = getPersonaAtStep(stepDatum.step);

const graphTitle = t(
"page.player.statistics.tabs.energy-balance.graphs.details.title",
{ stackName: getStackName({ stepDatum, t }) }
);

if (stepDatum.type === "consumption") {
return (
<>
<DetailsEnergyConsumptionBars title={graphTitle} persona={persona} />
<EnergyConsumptionButtons persona={persona} />
</>
);
} else if (stepDatum.type === "production") {
return (
<>
<DetailsEnergyProductionBars title={graphTitle} persona={persona} />
<EnergyProductionButtons persona={persona} />
</>
);
}
}, [stepDatum, getPersonaAtStep, t]);

return <>{DetailsContent}</>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Box } from "@mui/material";
import _ from "lodash";
import React, { useMemo, useState } from "react";
import {
StackedBars,
StackedBarsStackData,
StackedBarsStacks,
} from "../StackedBars";
import { Persona } from "../../persona/persona";
import { STEPS, getStepTypes } from "../../play";
import { formatProduction } from "../../../lib/formatter";
import { usePlay } from "../../play/context/playContext";
import { useTranslation } from "../../translations/useTranslation";
import { StepDatum } from "./types";
import {
computeConsumptionBarsForPersona,
computeProductionBarsForPersona,
getStackName,
} from "./utils";
import { EnergyBalanceDetailsForPlayerGraph } from "./EnergyBalanceDetailsForPlayerGraph";
import { buildStack } from "../utils";

export { EnergyBalanceForPlayerChart };

function EnergyBalanceForPlayerChart({
getPersonaAtStep,
}: {
getPersonaAtStep: (step: number) => Persona;
}) {
const { t } = useTranslation();
const { game } = usePlay();
const [selectedStepDatum, setSelectedStepDatum] = useState<StepDatum | null>(
null
);

const stepDataToDisplay = useMemo((): StepDatum[] => {
const maxStep = STEPS.findIndex((s) => s.id === "final-situation");
const endStep = Math.min(game.lastFinishedStep + 1, maxStep);

return _.range(0, endStep)
.map(getStepTypes)
.map((stepTypes, idx) =>
stepTypes.map((stepType) => ({ step: idx, type: stepType }))
)
.flat();
}, [game.lastFinishedStep]);

const MainGraph = useMemo(() => {
const data = stepDataToDisplay.map((stepDatum): StackedBarsStackData => {
const computeBars =
stepDatum.type === "consumption"
? computeConsumptionBarsForPersona
: computeProductionBarsForPersona;

return buildStack({
bars: computeBars({
persona: getPersonaAtStep(stepDatum.step),
t,
}),
label: getStackName({ stepDatum, t }),
});
});

const stacks: StackedBarsStacks = {
data,
yAxisUnitLabel: t("unit.watthour-per-day-bare.kilo"),
palettes: ["energy", "production"],
yAxisValueFormatter: (value) =>
formatProduction(value, { fractionDigits: 2 }),
yAxisTicksValueFormatter: (value) =>
formatProduction(value, { fractionDigits: 0 }),
};

return (
<StackedBars
title={t("graph.energy-balance-for-player-graph.title")}
stacks={stacks}
onClick={(chartState) => {
if (chartState?.activeTooltipIndex != null) {
const stepDatum = stepDataToDisplay[chartState.activeTooltipIndex];
setSelectedStepDatum(stepDatum);
}
}}
/>
);
}, [stepDataToDisplay, getPersonaAtStep, t]);

return (
<Box>
{MainGraph}
{selectedStepDatum && (
<EnergyBalanceDetailsForPlayerGraph
stepDatum={selectedStepDatum}
getPersonaAtStep={getPersonaAtStep}
/>
)}
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Box } from "@mui/material";
import React, { useMemo } from "react";
import {
StackedBars,
StackedBarsStackData,
StackedBarsStacks,
} from "../StackedBars";
import { formatProduction, formatUserName } from "../../../lib/formatter";
import { usePersonaByUserId, usePlay } from "../../play/context/playContext";
import { useTranslation } from "../../translations/useTranslation";
import {
computeConsumptionBarsForPersona,
computeProductionBarsForPersona,
} from "./utils";
import { ITeam } from "../../../utils/types";
import { buildStack } from "../utils";

export { EnergyBalanceForTeamChart };

function EnergyBalanceForTeamChart({ team }: { team: ITeam }) {
const { t } = useTranslation();
const { players } = usePlay();

const playersInTeam = useMemo(
() => players.filter((p) => p.teamId === team.id),
[players, team]
);
const userIds = useMemo(
() => playersInTeam.map((p) => p.userId),
[playersInTeam]
);
const personaByUserId = usePersonaByUserId(userIds);

const Graph = useMemo(() => {
const consumptionStacks: StackedBarsStackData[] = playersInTeam.map(
(player) =>
buildStack({
bars: computeConsumptionBarsForPersona({
persona: personaByUserId[player.userId].currentPersona,
t,
}),
label: formatUserName(player.user),
})
);

const productionStack: StackedBarsStackData = buildStack({
bars: computeProductionBarsForPersona({
persona: personaByUserId[playersInTeam[0].userId].currentPersona,
t,
}),
label: t("graph.common.production"),
});

const data = [...consumptionStacks, productionStack];

const stacks: StackedBarsStacks = {
data,
yAxisUnitLabel: t("unit.watthour-per-day-bare.kilo"),
palettes: ["energy", "production"],
yAxisValueFormatter: (value) =>
formatProduction(value, { fractionDigits: 2 }),
yAxisTicksValueFormatter: (value) =>
formatProduction(value, { fractionDigits: 0 }),
};

return (
<StackedBars
title={t("graph.energy-balance-for-team-graph.title")}
stacks={stacks}
/>
);
}, [personaByUserId, playersInTeam, t]);

return <Box>{Graph}</Box>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { EnergyBalanceForPlayerChart } from "./EnergyBalanceForPlayerChart";
export { EnergyBalanceForTeamChart } from "./EnergyBalanceForTeamChart";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { GameStepType } from "../../play";

export type { StepDatum };

type StepDatum = { step: number; type: GameStepType };
76 changes: 76 additions & 0 deletions packages/client/src/modules/charts/EnergyBalanceCharts/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { StackedBarsBar } from "../StackedBars";
import { Persona } from "../../persona/persona";
import { sumReducer } from "../../../lib/array";
import { filterOutDuplicates } from "../../common/utils";
import { I18nTranslateFunction } from "../../translations";
import { StepDatum } from "./types";

export {
computeConsumptionBarsForPersona,
computeProductionBarsForPersona,
getStackName,
};

function computeConsumptionBarsForPersona({
persona,
t,
}: {
persona: Persona;
t: I18nTranslateFunction;
}): StackedBarsBar[] {
const consumptionTypes = persona.consumption
.map((consumption) => consumption.type)
.filter(filterOutDuplicates)
.sort()
.reverse();

const bars: StackedBarsBar[] = consumptionTypes.map((type) => ({
key: type,
label: t(`energy.${type}`),
total: persona.consumption
.filter((datum) => datum.type === type)
.map((datum) => datum.value)
.reduce(sumReducer, 0),
}));

return bars;
}

function computeProductionBarsForPersona({
persona,
t,
}: {
persona: Persona;
t: I18nTranslateFunction;
}): StackedBarsBar[] {
const productionTypes = persona.productionDisplayed
.map((production) => production.type)
.filter(filterOutDuplicates)
.sort()
.reverse();

const bars: StackedBarsBar[] = productionTypes.map((type) => ({
key: type,
label: t(`graph.energy.${type}`),
total: persona.productionDisplayed
.filter((datum) => datum.type === type)
.map((datum) => datum.value)
.reduce(sumReducer, 0),
}));

return bars;
}

function getStackName({
stepDatum,
t,
}: {
stepDatum: StepDatum;
t: I18nTranslateFunction;
}) {
return stepDatum.step === 0
? stepDatum.type === "consumption"
? t("graph.step.first.consumption.name")
: t("graph.step.first.production.name")
: t("graph.step.other.name", { stepNumber: stepDatum.step });
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function ResourcesPerProductionTypeChart({

const graphStacks: StackedBarsStacks = useMemo(() => {
const data: StackedBarsStackData[] = pipe(
persona[resourceType],
persona[`${resourceType}Displayed`],
(resources: PhysicalResourceNeedDatum[]) =>
resources.reduce(
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function ResourcesPerStepChart({
const computeBarsForPersona = useCallback(
(persona: Persona): StackedBarsBar[] => {
const indexBarByResourceName = (persona: Persona) =>
persona[resourceType].reduce(
persona[`${resourceType}Displayed`].reduce(
(barIndexedByResourceName, resourceDatum) => {
if (
!barIndexedByResourceName[
Expand Down
Loading

0 comments on commit 68d9861

Please sign in to comment.