diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000000000000000000000000000000000000..266880429dcb61bd439e6f833b2d98f52f8ee52d --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,79 @@ +import React, { useState, useEffect } from "react"; +import { useDispatch } from "react-redux"; +import { fetchPoiRequest } from "./redux/actions/poiActions"; +import { poiList } from "./data/data"; +import { Poi } from "./redux/types/Poi"; + +import DropDown from "./components/generalInformation/dropdown/DropDown"; +import DemographicsSection from "./sections/demographics"; +import FootfallSection from "./sections/footfall"; +import ModeSection from "./sections/mode"; +import DescriptionSection from "./sections/description"; +import InformationSection from "./sections/information"; +import DrawerSection from "./sections/drawer"; +import TraficSection from "./sections/trafic"; +import MapSection from "./sections/map"; +import GraphSections from "./components/main/GraphSections"; + +import "./styles/global/App.css"; +import "./styles/global/customScrollBar.css"; + +const App = () => { + const [selectedPoi, setSelectedPoi] = useState(poiList.items[0]); + const [isFootfallSection, setFootfallSection] = useState(true); + const [isModeSection, setModeSection] = useState(true); + const [isDemographicsSection, setDemographicsSection] = useState(true); + const [isInformationSection, setInformationSection] = useState(true); + const [isTraficSection, setTraficSection] = useState(true); + const [isMapView, setIsMapView] = useState(false); + + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(fetchPoiRequest()); + }, [dispatch]); + + return ( +
+ + + {isMapView ? ( + + ) : ( +
+

+ + +
+ )} +
+ ); +}; + +export default App; diff --git a/src/algorithm/DemographicsPieByGender.ts b/src/algorithm/DemographicsPieByGender.ts new file mode 100644 index 0000000000000000000000000000000000000000..6de0cdf66f37b05f7caaee2f6f5d730a16848b05 --- /dev/null +++ b/src/algorithm/DemographicsPieByGender.ts @@ -0,0 +1,39 @@ +interface SocioDemographyItem { + age: string; + gender: string; + percentage: number; + social_group: string; +} + +export interface SummaryItem { + label: string; + usage: number; +} + +export function generateSummary(data: SocioDemographyItem[]): SummaryItem[] { + const summaryData: SummaryItem[] = []; + + function calculateUsage(age: string, gender: string): number { + const filteredData = data.filter( + (item) => item.age === age && item.gender.toUpperCase() === gender + ); + const totalPercentage = filteredData.reduce( + (total, item) => total + item.percentage, + 0 + ); + return totalPercentage; + } + + const ageGroups = ["15-24", "25-34", "35-49", "50-64", "65-PLUS"]; + const genders = ["MALE", "FEMALE"]; + + for (const gender of genders) { + for (const age of ageGroups) { + const label = `${gender} ${age}`; + const usage = calculateUsage(age, gender); + summaryData.push({ label, usage }); + } + } + + return summaryData; +} diff --git a/src/algorithm/DemographicsPieBySocialGroup.ts b/src/algorithm/DemographicsPieBySocialGroup.ts new file mode 100644 index 0000000000000000000000000000000000000000..8d72f6e4262ff3aca95f588b5b791acd4e609512 --- /dev/null +++ b/src/algorithm/DemographicsPieBySocialGroup.ts @@ -0,0 +1,24 @@ +export interface SummaryItemSocial { + label: string; + usage: number; +} + +export function summarizeSocialGroups(data: any[]): SummaryItemSocial[] { + const summary: { [key: string]: number } = {}; + + data.forEach((item) => { + const socialGroup = item.social_group; + const percentage = item.percentage; + summary[socialGroup] = (summary[socialGroup] || 0) + percentage; + }); + + const summaryArray: SummaryItemSocial[] = []; + for (const socialGroup in summary) { + summaryArray.push({ + label: `${socialGroup}`, + usage: summary[socialGroup], + }); + } + + return summaryArray; +} diff --git a/src/algorithm/WordCloud.ts b/src/algorithm/WordCloud.ts new file mode 100644 index 0000000000000000000000000000000000000000..92f15232f4b4a73e9548fe66a32f367c5335b1b5 --- /dev/null +++ b/src/algorithm/WordCloud.ts @@ -0,0 +1,98 @@ +interface SocioDemographicData { + age: string; + gender: string; + percentage: number; + social_group: string; +} + +type SynonymsMap = Record; + +export function characterizeSocioDemographicData( + data: SocioDemographicData[] +): string { + const result: string[] = []; + + const ageSynonyms: SynonymsMap = { + "15-24": ["young", "youthful", "adolescent", "teenage", "juvenile"], + "25-34": ["young adult", "early adult", "youthful", "prime of life"], + "35-49": ["middle-aged", "adult", "mature", "grown-up"], + "50-64": ["senior", "elderly", "aged", "mature", "golden-aged"], + "65-PLUS": ["elderly", "senior", "aged", "retired", "elder"], + }; + + const socialGroupSynonyms: SynonymsMap = { + "1": ["poorest", "impoverished", "deprived", "underprivileged", "needy"], + "2": [ + "poor", + "low-income", + "economically challenged", + "struggling", + "disadvantaged", + ], + "3": ["poor", "struggling", "disadvantaged", "less fortunate", "in need"], + "4": ["middle-income", "average", "moderate", "ordinary", "typical"], + "5": ["middle-income", "average", "moderate", "ordinary", "typical"], + "6": ["middle-income", "average", "moderate", "ordinary", "typical"], + "7": ["rich", "affluent", "well-off", "prosperous", "wealthy"], + "8": ["rich", "wealthy", "opulent", "affluent", "privileged"], + "9": ["richest", "privileged", "wealthiest", "affluent", "opulent"], + "10": ["richest", "wealthiest", "opulent", "affluent", "privileged"], + }; + + const crowdedSynonyms = [ + "crowded", + "dense", + "populated", + "teeming", + "packed", + ]; + const notCrowdedSynonyms = [ + "not that crowded", + "sparsely populated", + "unpopulated", + "deserted", + "vacant", + ]; + + const groupedData = data.reduce((groups, item) => { + const key = `${item.age}-${item.gender}-${item.social_group}`; + if (!groups[key]) { + groups[key] = []; + } + groups[key].push(item.percentage); + return groups; + }, {} as Record); + + for (const key in groupedData) { + if (groupedData.hasOwnProperty(key)) { + const percentages = groupedData[key]; + const averagePercentage = + percentages.reduce((sum, percentage) => sum + percentage, 0) / + percentages.length; + + if (averagePercentage > 0.1) { + result.push(...crowdedSynonyms); + } else { + result.push(...notCrowdedSynonyms); + } + + const age = key.split("-")[0]; + const randomAgeSynonym = ageSynonyms[age] + ? ageSynonyms[age][Math.floor(Math.random() * ageSynonyms[age].length)] + : age; + result.push(randomAgeSynonym); + + const socialGroup = key.split("-")[2]; + const randomSocialGroupSynonym = socialGroupSynonyms[socialGroup] + ? socialGroupSynonyms[socialGroup][ + Math.floor(Math.random() * socialGroupSynonyms[socialGroup].length) + ] + : "social group " + socialGroup; + result.push(randomSocialGroupSynonym); + } + } + + const finalString = result.filter((word) => isNaN(Number(word))).join(" "); + + return finalString; +} diff --git a/src/assets/fonts/AirbnbCereal_W_Bd.otf b/src/assets/fonts/AirbnbCereal_W_Bd.otf new file mode 100644 index 0000000000000000000000000000000000000000..17534ca3ea66e2fc2466e34dd6e3cfbf5e0e75b3 Binary files /dev/null and b/src/assets/fonts/AirbnbCereal_W_Bd.otf differ diff --git a/src/assets/fonts/AirbnbCereal_W_Bk.otf b/src/assets/fonts/AirbnbCereal_W_Bk.otf new file mode 100644 index 0000000000000000000000000000000000000000..aec995fe09c7589338cf2cfb1bbf79c4ae7f2239 Binary files /dev/null and b/src/assets/fonts/AirbnbCereal_W_Bk.otf differ diff --git a/src/assets/fonts/AirbnbCereal_W_Blk.otf b/src/assets/fonts/AirbnbCereal_W_Blk.otf new file mode 100644 index 0000000000000000000000000000000000000000..ad53abb877e35e5dfd4f9ea767f7522ea23cd083 Binary files /dev/null and b/src/assets/fonts/AirbnbCereal_W_Blk.otf differ diff --git a/src/assets/fonts/AirbnbCereal_W_Lt.otf b/src/assets/fonts/AirbnbCereal_W_Lt.otf new file mode 100644 index 0000000000000000000000000000000000000000..a2e76b66c4d11ed58506b389bcc581971d525bd5 Binary files /dev/null and b/src/assets/fonts/AirbnbCereal_W_Lt.otf differ diff --git a/src/assets/fonts/AirbnbCereal_W_Md.otf b/src/assets/fonts/AirbnbCereal_W_Md.otf new file mode 100644 index 0000000000000000000000000000000000000000..44474a04ebc6cb2140e4c7c44bb21d731a0cd77d Binary files /dev/null and b/src/assets/fonts/AirbnbCereal_W_Md.otf differ diff --git a/src/assets/fonts/AirbnbCereal_W_XBd.otf b/src/assets/fonts/AirbnbCereal_W_XBd.otf new file mode 100644 index 0000000000000000000000000000000000000000..34ceae4bd5ab9bc50fffed36c50dd085c9a88da8 Binary files /dev/null and b/src/assets/fonts/AirbnbCereal_W_XBd.otf differ diff --git a/src/assets/fonts/fonts.css b/src/assets/fonts/fonts.css new file mode 100644 index 0000000000000000000000000000000000000000..b2f4df5f0d1c2792a5fdbd21946e2a172b0327aa --- /dev/null +++ b/src/assets/fonts/fonts.css @@ -0,0 +1,29 @@ +@font-face { + font-family: "airbnb_extra_bold"; + src: url("./AirbnbCereal_W_Blk.otf") format("opentype"); +} + +@font-face { + font-family: "airbnb_bold"; + src: url("./AirbnbCereal_W_XBd.otf") format("opentype"); +} + +@font-face { + font-family: "airbnb_semi_bold"; + src: url("./AirbnbCereal_W_Bd.otf") format("opentype"); +} + +@font-face { + font-family: "airbnb_regular"; + src: url("./AirbnbCereal_W_Md.otf") format("opentype"); +} + +@font-face { + font-family: "airbnb_light"; + src: url("./AirbnbCereal_W_Bk.otf") format("opentype"); +} + +@font-face { + font-family: "airbnb_extra_light"; + src: url("./AirbnbCereal_W_Lt.otf") format("opentype"); +} diff --git a/src/assets/images/pin.png b/src/assets/images/pin.png new file mode 100644 index 0000000000000000000000000000000000000000..ec45b2165303246aa8bba3584440cd06c31cf3e2 Binary files /dev/null and b/src/assets/images/pin.png differ diff --git a/src/assets/images/seiki.png b/src/assets/images/seiki.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd5440805b48e06904485bde9ca8933ed0b06cf Binary files /dev/null and b/src/assets/images/seiki.png differ diff --git a/src/components/charts/brushChart/Area.tsx b/src/components/charts/brushChart/Area.tsx new file mode 100644 index 0000000000000000000000000000000000000000..8bc9007f1ae7589ac7c014d7daa3d89ed9a54056 --- /dev/null +++ b/src/components/charts/brushChart/Area.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { Group } from "@visx/group"; +import { AreaClosed } from "@visx/shape"; +import { AxisLeft, AxisBottom, AxisScale } from "@visx/axis"; +import { LinearGradient } from "@visx/gradient"; +import { curveMonotoneX } from "@visx/curve"; +import { week_distribution } from "./AreaChart"; + +const axisColor = "#fff"; +const axisBottomTickLabelProps = { + textAnchor: "middle" as const, + fontFamily: "Arial", + fontSize: 10, + fill: axisColor, +}; +const axisLeftTickLabelProps = { + dx: "-0.25em", + dy: "0.25em", + fontFamily: "Arial", + fontSize: 10, + textAnchor: "end" as const, + fill: axisColor, +}; + +export default function AreaChart({ + data, + gradientColor, + width, + yMax, + margin, + xScale, + yScale, + hideBottomAxis = false, + hideLeftAxis = false, + top, + left, + children, +}: { + data: week_distribution[]; + gradientColor: string; + xScale: AxisScale; + yScale: AxisScale; + width: number; + yMax: number; + margin: { top: number; right: number; bottom: number; left: number }; + hideBottomAxis?: boolean; + hideLeftAxis?: boolean; + top?: number; + left?: number; + children?: React.ReactNode; +}) { + if (width < 10) return null; + return ( + + + + data={data} + x={(d) => xScale(d.week) || 0} + y={(d) => yScale(d.indice_base_100) || 0} + yScale={yScale} + strokeWidth={1} + stroke="url(#gradient)" + fill="url(#gradient)" + curve={curveMonotoneX} + /> + {!hideBottomAxis && ( + 520 ? 10 : 5} + stroke={axisColor} + tickStroke={axisColor} + tickLabelProps={axisBottomTickLabelProps} + /> + )} + {!hideLeftAxis && ( + + )} + {children} + + ); +} diff --git a/src/components/charts/brushChart/AreaChart.tsx b/src/components/charts/brushChart/AreaChart.tsx new file mode 100644 index 0000000000000000000000000000000000000000..012f34b111cdae6217cf13e4b24c683399eb8b30 --- /dev/null +++ b/src/components/charts/brushChart/AreaChart.tsx @@ -0,0 +1,245 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import React, { useRef, useState, useMemo } from "react"; +import { scaleLinear } from "@visx/scale"; +import { Brush } from "@visx/brush"; +import { Bounds } from "@visx/brush/lib/types"; +import BaseBrush, { + BaseBrushState, + UpdateBrush, +} from "@visx/brush/lib/BaseBrush"; +import { PatternLines } from "@visx/pattern"; +import { Group } from "@visx/group"; +import { LinearGradient } from "@visx/gradient"; +import { extent } from "@visx/vendor/d3-array"; +import { BrushHandleRenderProps } from "@visx/brush/lib/BrushHandle"; +import AreaChart from "./Area"; + +const brushMargin = { top: 0, bottom: 15, left: 50, right: 20 }; +const chartSeparation = 30; +const PATTERN_ID = "brush_pattern"; +const GRADIENT_ID = "brush_gradient"; +export const accentColor = "#f6acc8"; +export const background = "#584153"; +export const background2 = "#af8baf"; + +const getWeek = (d: any) => d.week; +const getIndice = (d: any) => d.indice_base_100; + +export interface week_distribution { + indice_base_100: number; + week: number; +} + +export type BrushProps = { + data: week_distribution[]; + width: number; + height: number; + margin?: { top: number; right: number; bottom: number; left: number }; + compact?: boolean; +}; + +function BrushChart({ + data, + compact = false, + width, + height, + margin = { + top: 20, + left: 50, + bottom: 20, + right: 20, + }, +}: BrushProps) { + const brushRef = useRef(null); + + const [filteredData, setFilteredData] = useState(data); + + const onBrushChange = (domain: Bounds | null) => { + if (!domain) return; + const { x0, x1, y0, y1 } = domain; + const dataCopy = data.filter((d) => { + const x = getWeek(d); + const y = getIndice(d); + return x > x0 && x < x1 && y > y0 && y < y1; + }); + setFilteredData(dataCopy); + }; + + const innerHeight = height - margin.top - margin.bottom; + const topChartBottomMargin = compact + ? chartSeparation / 2 + : chartSeparation + 10; + const topChartHeight = 0.8 * innerHeight - topChartBottomMargin; + const bottomChartHeight = innerHeight - topChartHeight - chartSeparation; + + const xMax = Math.max(width - margin.left - margin.right, 0); + const yMax = Math.max(topChartHeight, 0); + const xBrushMax = Math.max(width - brushMargin.left - brushMargin.right, 0); + const yBrushMax = Math.max( + bottomChartHeight - brushMargin.top - brushMargin.bottom, + 0 + ); + + const weekScale = useMemo( + () => + scaleLinear({ + range: [0, xMax], + domain: extent(data, getWeek) as [number, number], + }), + [xMax, data] + ); + + const brushWeekScale = useMemo( + () => + scaleLinear({ + range: [0, xBrushMax], + domain: extent(data, getWeek) as [number, number], + }), + [xBrushMax, data] + ); + + const indiceScale = useMemo( + () => + scaleLinear({ + range: [topChartHeight, 0], + domain: [70, 105], + }), + [topChartHeight, data] + ); + + const initialBrushPosition = useMemo( + () => ({ + start: { x: brushWeekScale(data[0].week) }, + end: { x: brushWeekScale(data[10].week) }, + }), + [brushWeekScale] + ); + + const handleClearClick = () => { + if (brushRef?.current) { + setFilteredData(data); + brushRef.current.reset(); + } + }; + + const handleResetClick = () => { + if (brushRef?.current) { + const updater: UpdateBrush = (prevBrush) => { + const newExtent = brushRef.current!.getExtent( + initialBrushPosition.start, + initialBrushPosition.end + ); + + const newState: BaseBrushState = { + ...prevBrush, + start: { y: newExtent.y0, x: newExtent.x0 }, + end: { y: newExtent.y1, x: newExtent.x1 }, + extent: newExtent, + }; + + return newState; + }; + brushRef.current.updateBrush(updater); + } + }; + + return ( +
+ + + + + + + setFilteredData(data)} + selectedBoxStyle={{ + fill: `url(#${PATTERN_ID})`, + stroke: "white", + }} + useWindowMoveEvents + renderBrushHandle={(props) => } + /> + + +
+ ); +} + +function BrushHandle({ x, height, isBrushActive }: BrushHandleRenderProps) { + const pathWidth = 8; + const pathHeight = 15; + if (!isBrushActive) { + return null; + } + return ( + + + + ); +} + +export default BrushChart; diff --git a/src/components/charts/pieChart/Pie.tsx b/src/components/charts/pieChart/Pie.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e5ed8d41791c056f03c3ac8e2773e373162b48e1 --- /dev/null +++ b/src/components/charts/pieChart/Pie.tsx @@ -0,0 +1,278 @@ +/* eslint-disable @typescript-eslint/no-use-before-define */ +import React, { useState } from "react"; +import Pie, { ProvidedProps, PieArcDatum } from "@visx/shape/lib/shapes/Pie"; +import { scaleOrdinal } from "@visx/scale"; +import { Group } from "@visx/group"; +import { + GradientPinkBlue, + GradientOrangeRed, + LinearGradient, +} from "@visx/gradient"; +import { animated, useTransition, interpolate } from "@react-spring/web"; +import { + generateSummary, + SummaryItem, +} from "../../../algorithm/DemographicsPieByGender"; +import { + summarizeSocialGroups, + SummaryItemSocial, +} from "../../../algorithm/DemographicsPieBySocialGroup"; + +interface demographics { + age: string; + gender: string; + percentage: number; + social_group: string; +} + +const defaultMargin = { top: 20, right: 20, bottom: 20, left: 20 }; + +export type PieProps = { + data: demographics[]; + width: number; + height: number; + margin?: typeof defaultMargin; + animate?: boolean; + flag?: number; +}; + +export default function PieChart({ + data, + width, + height, + margin = defaultMargin, + animate = true, + flag = 0, +}: PieProps) { + const [selectedDemographic, setSelectedDemographic] = useState( + null + ); + const [selectedSocialGroup, setSelectedSocialGroup] = useState( + null + ); + + const proccessedData = generateSummary(data); + const proccessedSocialGroupData = summarizeSocialGroups(data); + if (width < 10) return null; + + const innerWidth = width - margin.left - margin.right; + const innerHeight = height - margin.top - margin.bottom; + const radius = Math.min(innerWidth, innerHeight) / 2; + const centerY = innerHeight / 2; + const centerX = innerWidth / 2; + const donutThickness = 50; + + const backgroundDefined = () => { + switch (flag) { + case 0: + return ( + <> + + + + ); + case 1: + return ( + <> + + + + ); + case 2: + return ( + <> + + + + ); + } + }; + // accessor functions + const usage = (d: SummaryItem) => d.usage; + const frequency = (d: SummaryItemSocial) => d.usage; + + // color scales + const getBrowserColor = scaleOrdinal({ + domain: proccessedData.map((d) => d.label), + range: [ + "rgba(255,255,255,0.7)", + "rgba(255,255,255,0.6)", + "rgba(255,255,255,0.5)", + "rgba(255,255,255,0.4)", + "rgba(255,255,255,0.3)", + "rgba(255,255,255,0.2)", + "rgba(255,255,255,0.1)", + ], + }); + + const getLetterFrequencyColor = scaleOrdinal({ + domain: proccessedSocialGroupData.map((l) => l.label), + range: [ + "rgba(93,30,91,1)", + "rgba(93,30,91,0.8)", + "rgba(93,30,91,0.6)", + "rgba(93,30,91,0.4)", + ], + }); + + return ( + + {backgroundDefined()} + + label === selectedDemographic + ) + : proccessedData + } + pieValue={usage} + outerRadius={radius} + innerRadius={radius - donutThickness} + cornerRadius={3} + padAngle={0.005} + > + {(pie) => ( + + {...pie} + animate={animate} + getKey={(arc) => arc.data.label} + onClickDatum={({ data: { label } }) => + animate && + setSelectedDemographic( + selectedDemographic && selectedDemographic === label + ? null + : label + ) + } + getColor={(arc) => getBrowserColor(arc.data.label)} + /> + )} + + label === selectedSocialGroup + ) + : proccessedSocialGroupData + } + pieValue={frequency} + pieSortValues={() => -1} + outerRadius={radius - donutThickness * 1.3} + > + {(pie) => ( + + {...pie} + animate={animate} + getKey={({ data: { label } }) => label} + onClickDatum={({ data: { label } }) => + animate && + setSelectedSocialGroup( + selectedSocialGroup && selectedSocialGroup === label + ? null + : label + ) + } + getColor={({ data: { label } }) => getLetterFrequencyColor(label)} + /> + )} + + + + ); +} + +type AnimatedStyles = { startAngle: number; endAngle: number; opacity: number }; + +const fromLeaveTransition = ({ endAngle }: PieArcDatum) => ({ + startAngle: endAngle > Math.PI ? 2 * Math.PI : 0, + endAngle: endAngle > Math.PI ? 2 * Math.PI : 0, + opacity: 0, +}); +const enterUpdateTransition = ({ startAngle, endAngle }: PieArcDatum) => ({ + startAngle, + endAngle, + opacity: 1, +}); + +type AnimatedPieProps = ProvidedProps & { + animate?: boolean; + getKey: (d: PieArcDatum) => string; + getColor: (d: PieArcDatum) => string; + onClickDatum: (d: PieArcDatum) => void; + delay?: number; +}; + +function AnimatedPie({ + animate, + arcs, + path, + getKey, + getColor, + onClickDatum, +}: AnimatedPieProps) { + const transitions = useTransition, AnimatedStyles>(arcs, { + from: animate ? fromLeaveTransition : enterUpdateTransition, + enter: enterUpdateTransition, + update: enterUpdateTransition, + leave: animate ? fromLeaveTransition : enterUpdateTransition, + keys: getKey, + }); + return transitions((props: any, arc: PieArcDatum, { key }: any) => { + const [centroidX, centroidY] = path.centroid(arc); + const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.1; + + return ( + + + path({ + ...arc, + startAngle, + endAngle, + }) + )} + fill={getColor(arc)} + onClick={() => onClickDatum(arc)} + onTouchStart={() => onClickDatum(arc)} + /> + {hasSpaceForLabel && ( + + + {getKey(arc)} + + + )} + + ); + }); +} diff --git a/src/components/charts/singleChart/SimpleChart.tsx b/src/components/charts/singleChart/SimpleChart.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a03ee78a5d82b68382e4cf80fb2845c76e9899c0 --- /dev/null +++ b/src/components/charts/singleChart/SimpleChart.tsx @@ -0,0 +1,141 @@ +import React, { useMemo, useState } from "react"; +import { Bar } from "@visx/shape"; +import { Group } from "@visx/group"; +import { LinearGradient } from "@visx/gradient"; +import { AxisBottom, AxisLeft } from "@visx/axis"; +import { scaleBand, scaleLinear } from "@visx/scale"; + +const verticalMargin = 20; +const leftMargin = 50; +const barPadding = 4; + +interface originTopTen { + commune: string; + percentage: number; +} +export type BarsProps = { + data: originTopTen[]; + width: number; + height: number; + events?: boolean; +}; + +const getCommuneValue = (d: originTopTen) => Number(d.percentage); + +export default function SimpleChart({ + data, + width, + height, + events = false, +}: BarsProps) { + const xMax = width - leftMargin; + const yMax = height - verticalMargin - 20; + + const xScale = useMemo( + () => + scaleBand({ + range: [0, xMax], + round: true, + domain: data.map((d: any) => d.commune), + paddingInner: 0.2, + paddingOuter: 0.1, + }), + [xMax] + ); + const yScale = useMemo( + () => + scaleLinear({ + range: [yMax, 0], + round: true, + domain: [0, Math.max(...data.map(getCommuneValue))], + }), + [yMax] + ); + + const [isHover, setIsHover] = useState(Array(data.length).fill(false)); + + return width < 10 ? null : ( + + + + + {data.map((d: any, index: any) => { + const barWidth = xScale.bandwidth(); + const barHeight = yMax - (yScale(d.percentage) ?? 0); + const barX = xScale(d.commune) ?? 0; + const barY = yMax - barHeight; + return ( + { + if (events) alert(`clicked: ${JSON.stringify(d)}`); + }} + onMouseMove={() => { + const updatedHover = [...isHover]; + updatedHover[index] = true; + setIsHover(updatedHover); + }} + onMouseLeave={() => { + const updatedHover = [...isHover]; + updatedHover[index] = false; + setIsHover(updatedHover); + }} + /> + ); + })} + ({ + fill: "white", + fontSize: 12, + textAnchor: "middle", + fontWeight: "bold", + })} + /> + value.toString()} + tickStroke="white" + strokeWidth={2} + stroke="white" + tickLabelProps={() => ({ + fill: "white", + fontSize: 11, + textAnchor: "end", + dy: "0.3em", + dx: "-0.25em", + fontWeight: "bold", + })} + /> + + + ); +} diff --git a/src/components/charts/singleChart/SimpleChartTripPurpose.tsx b/src/components/charts/singleChart/SimpleChartTripPurpose.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1ef0144bfdfd409acdba0502885ec3f5ddf7f3c0 --- /dev/null +++ b/src/components/charts/singleChart/SimpleChartTripPurpose.tsx @@ -0,0 +1,141 @@ +import React, { useMemo, useState } from "react"; +import { Bar } from "@visx/shape"; +import { Group } from "@visx/group"; +import { LinearGradient } from "@visx/gradient"; +import { AxisBottom, AxisLeft } from "@visx/axis"; +import { scaleBand, scaleLinear } from "@visx/scale"; + +const verticalMargin = 20; +const leftMargin = 50; +const barPadding = 4; + +interface tripPurpose { + trip_purpose_group: string; + percentage: number; +} +export type BarsProps = { + data: tripPurpose[]; + width: number; + height: number; + events?: boolean; +}; + +const getTripPurposeValue = (d: tripPurpose) => Number(d.percentage); + +export default function SimpleChartTripPurpose({ + data, + width, + height, + events = false, +}: BarsProps) { + const xMax = width - leftMargin; + const yMax = height - verticalMargin - 20; + + const xScale = useMemo( + () => + scaleBand({ + range: [0, xMax], + round: true, + domain: data.map((d: any) => d.trip_purpose_group), + paddingInner: 0.2, + paddingOuter: 0.1, + }), + [xMax] + ); + const yScale = useMemo( + () => + scaleLinear({ + range: [yMax, 0], + round: true, + domain: [0, Math.max(...data.map(getTripPurposeValue))], + }), + [yMax] + ); + + const [isHover, setIsHover] = useState(Array(data.length).fill(false)); + + return width < 10 ? null : ( + + + + + {data.map((d: any, index: any) => { + const barWidth = xScale.bandwidth(); + const barHeight = yMax - (yScale(d.percentage) ?? 0); + const barX = xScale(d.trip_purpose_group) ?? 0; + const barY = yMax - barHeight; + return ( + { + if (events) alert(`clicked: ${JSON.stringify(d)}`); + }} + onMouseMove={() => { + const updatedHover = [...isHover]; + updatedHover[index] = true; + setIsHover(updatedHover); + }} + onMouseLeave={() => { + const updatedHover = [...isHover]; + updatedHover[index] = false; + setIsHover(updatedHover); + }} + /> + ); + })} + ({ + fill: "white", + fontSize: 10, + textAnchor: "middle", + fontWeight: "bold", + })} + /> + value.toString()} + tickStroke="white" + strokeWidth={2} + stroke="white" + tickLabelProps={() => ({ + fill: "white", + fontSize: 11, + textAnchor: "end", + dy: "0.3em", + dx: "-0.25em", + fontWeight: "bold", + })} + /> + + + ); +} diff --git a/src/components/charts/tripeChart/DayTypeGraph.tsx b/src/components/charts/tripeChart/DayTypeGraph.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3dd5fa18f3f6b90e7ed02e39bb71b6ec6c0182f0 --- /dev/null +++ b/src/components/charts/tripeChart/DayTypeGraph.tsx @@ -0,0 +1,204 @@ +import React, { useState } from "react"; +import { Group } from "@visx/group"; +import { BarGroup } from "@visx/shape"; +import { AxisBottom, AxisLeft } from "@visx/axis"; +import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale"; +import { LinearGradient } from "@visx/gradient"; + +const GRADIENT_ID = "brush_gradient"; + +export const green = "#ffffff"; +export const background = "#ff452f"; +export const background2 = "#ff8677"; + +export type BarGroupProps = { + data: + | { + day_type: string; + hour: number; + percentage: number; + }[] + | undefined; + width: number; + height: number; + margin?: { top: number; right: number; bottom: number; left: number }; + events?: boolean; +}; + +const defaultMargin = { top: 40, right: 0, bottom: 40, left: 60 }; + +export default function DayTypeGraph({ + data, + width, + height, + events = false, + margin = defaultMargin, +}: BarGroupProps) { + interface NewHourlyPercentage { + hour: number; + SATURDAY: number; + SUNDAY_PUBLIC_HOLIDAY: number; + WORKING_DAY: number; + } + + function processRawDataToGraphData( + data: + | { + day_type: string; + hour: number; + percentage: number; + }[] + | undefined + ): NewHourlyPercentage[] { + const transformedData: NewHourlyPercentage[] = []; + + if (!data || data === undefined) { + return transformedData; + } + for (let i = 0; i < 24; i++) { + const newObj: NewHourlyPercentage = { + hour: i, + SATURDAY: 0, + SUNDAY_PUBLIC_HOLIDAY: 0, + WORKING_DAY: 0, + }; + + transformedData.push(newObj); + } + + for (let index = 0; data[index]; index++) { + if (data[index].day_type === "SATURDAY") { + transformedData[data[index].hour].hour = data[index].hour; + transformedData[data[index].hour].SATURDAY = data[index].percentage; + } else if (data[index].day_type === "SUNDAY_&_PUBLIC_HOLIDAY") { + transformedData[data[index].hour].hour = data[index].hour; + transformedData[data[index].hour].SUNDAY_PUBLIC_HOLIDAY = + data[index].percentage; + } else { + transformedData[data[index].hour].hour = data[index].hour; + transformedData[data[index].hour].WORKING_DAY = data[index].percentage; + } + } + + return transformedData; + } + + const [currentData, setCurrentData] = useState( + processRawDataToGraphData(data) + ); + + const keys = ["SATURDAY", "SUNDAY_PUBLIC_HOLIDAY", "WORKING_DAY"]; + + const getDate = (d: any) => d.hour; + + const hourScale = scaleBand({ + domain: currentData.map((d) => d.hour), + padding: 0.2, + }); + const dayScale = scaleBand({ + domain: keys, + padding: 0.2, + }); + const percentageScale = scaleLinear({ + domain: [0, 0.12], + }); + + const colorScale = scaleOrdinal({ + domain: keys, + range: ["#AAB1FF", "#6A4CEE", "#FABA00"], + }); + + const xMax = width - margin.left - margin.right; + const yMax = height - margin.top - margin.bottom; + + hourScale.rangeRound([0, xMax]); + dayScale.rangeRound([0, hourScale.bandwidth()]); + percentageScale.range([yMax, 0]); + + return width < 10 ? null : ( + + + + + + {(barGroups) => + barGroups.map((barGroup) => ( + + {barGroup.bars.map((bar) => ( + { + if (!events) return; + const { key, value } = bar; + alert(JSON.stringify({ key, value })); + }} + /> + ))} + + )) + } + + + ({ + fill: "#ffffff", + fontSize: 11, + textAnchor: "end", + dy: "0.3em", + dx: "-0.25em", + fontWeight: "bold", + })} + /> + + + ); +} diff --git a/src/components/charts/wordCloudChart/CloudWord.tsx b/src/components/charts/wordCloudChart/CloudWord.tsx new file mode 100644 index 0000000000000000000000000000000000000000..df54d9423ceb1d15511c89ce3374df57ec334bf7 --- /dev/null +++ b/src/components/charts/wordCloudChart/CloudWord.tsx @@ -0,0 +1,114 @@ +import React, { useState } from "react"; +import { Text } from "@visx/text"; +import { scaleLog } from "@visx/scale"; +import Wordcloud from "@visx/wordcloud/lib/Wordcloud"; + +interface ExampleProps { + demographicWords: string; + width: number; + height: number; + showControls?: boolean; +} + +export interface WordData { + text: string; + value: number; +} + +export default function CloudWord({ + demographicWords, + width, + height, + showControls = true, +}: ExampleProps) { + function wordFreq(text: string): WordData[] { + const words: string[] = text.replace(/\./g, "").split(/\s/); + const freqMap: Record = {}; + + for (const w of words) { + if (!freqMap[w]) freqMap[w] = 0; + freqMap[w] += 1; + } + return Object.keys(freqMap).map((word) => ({ + text: word, + value: freqMap[word], + })); + } + + function getRotationDegree() { + const rand = Math.random(); + const degree = rand > 0.5 ? 60 : -60; + return rand * degree; + } + + const words = wordFreq(demographicWords); + + const fontScale = scaleLog({ + domain: [ + Math.min(...words.map((w) => w.value)), + Math.max(...words.map((w) => w.value)), + ], + range: [10, 100], + }); + const fontSizeSetter = (datum: WordData) => fontScale(datum.value); + + const fixedValueGenerator = () => 0.5; + + type SpiralType = "archimedean" | "rectangular"; + + // eslint-disable-next-line + const [spiralType, setSpiralType] = useState("archimedean"); + // eslint-disable-next-line + const [withRotation, setWithRotation] = useState(false); + + return ( +
+ + {(cloudWords) => + cloudWords.map((w, i) => ( + + {w.text} + + )) + } + + +
+ ); +} diff --git a/src/components/generalInformation/dropdown/DropDown.tsx b/src/components/generalInformation/dropdown/DropDown.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3d26baca231402d5a0aa4c26519617a6af2cbb90 --- /dev/null +++ b/src/components/generalInformation/dropdown/DropDown.tsx @@ -0,0 +1,78 @@ +import { Fragment } from "react"; +import { Listbox, Transition } from "@headlessui/react"; +import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid"; +import { Poi } from "../../../redux/types/Poi"; + +type DropDownProps = { + poiList: Poi[]; + selectedPoi: Poi; + setSelectedPoi: React.Dispatch>; +}; + +const DropDown: React.FC = ({ + poiList, + selectedPoi, + setSelectedPoi, +}) => { + return ( +
+ +
+ + {selectedPoi.address} + + + + + + {poiList.map((poi, index) => ( + + `relative cursor-pointer select-none py-2 pl-10 pr-4 ${ + active ? "bg-[#ECEEFF] text-[#00000]" : "text-gray-900" + }` + } + value={poi} + > + {({ selected }) => ( + <> + + {poi.address} + + {selected ? ( + + + ) : null} + + )} + + ))} + + +
+
+
+ ); +}; + +export default DropDown; diff --git a/src/components/generalInformation/legend/Legend.tsx b/src/components/generalInformation/legend/Legend.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d11819e0256d000b2afbf03217edeb7af2a68aa2 --- /dev/null +++ b/src/components/generalInformation/legend/Legend.tsx @@ -0,0 +1,343 @@ +import React from "react"; +import { format } from "@visx/vendor/d3-format"; +import { + scaleLinear, + scaleOrdinal, + scaleThreshold, + scaleQuantile, +} from "@visx/scale"; +import { GlyphStar, GlyphWye, GlyphTriangle, GlyphDiamond } from "@visx/glyph"; +import { + Legend, + LegendLinear, + LegendQuantile, + LegendOrdinal, + LegendSize, + LegendThreshold, + LegendItem, + LegendLabel, +} from "@visx/legend"; + +const oneDecimalFormat = format(".1f"); + +const sizeScale = scaleLinear({ + domain: [0, 10], + range: [5, 13], +}); + +const sizeColorScale = scaleLinear({ + domain: [0, 10], + range: ["#75fcfc", "#3236b8"], +}); + +const quantileScale = scaleQuantile({ + domain: [0, 0.15], + range: ["#eb4d70", "#f19938", "#6ce18b", "#78f6ef", "#9096f8"], +}); + +const linearScale = scaleLinear({ + domain: [0, 10], + range: ["#ed4fbb", "#e9a039"], +}); + +const thresholdScale = scaleThreshold({ + domain: [0.01, 0.02, 0.04, 0.06, 0.08], + range: ["#f2f0f7", "#dadaeb", "#bcbddc", "#9e9ac8", "#756bb1", "#54278f"], +}); + +const ordinalColorScale = scaleOrdinal({ + domain: ["a", "b", "c", "d"], + range: ["#66d981", "#71f5ef", "#4899f1", "#7d81f6"], +}); + +const ordinalColor2Scale = scaleOrdinal({ + domain: ["a", "b", "c", "d"], + range: ["#fae856", "#f29b38", "#e64357", "#8386f7"], +}); + +const shapeScale = scaleOrdinal({ + domain: ["a", "b", "c", "d", "e"], + range: [ + , + , + , + , + () => ( + + $ + + ), + ], +}); + +function LegendDemo({ + title, + children, +}: { + title: string; + children: React.ReactNode; +}) { + return ( +
+
{title}
+ {children} + +
+ ); +} + +const legendGlyphSize = 15; + +export default function LegendChart({ + width, + height, + events = false, +}: { + width?: number; + height?: number; + events?: boolean; +}) { + return ( +
+ + + {(labels) => + labels.map((label) => { + const size = sizeScale(label.datum) ?? 0; + const color = sizeColorScale(label.datum); + return ( + { + if (events) alert(`clicked: ${JSON.stringify(label)}`); + }} + > + + + + + {label.text} + + + ); + }) + } + + + + + {(labels) => + labels.map((label, i) => ( + { + if (events) alert(`clicked: ${JSON.stringify(label)}`); + }} + > + + + + + {label.text} + + + )) + } + + + + (i % 2 === 0 ? oneDecimalFormat(d) : "")} + > + {(labels) => + labels.map((label, i) => ( + { + if (events) alert(`clicked: ${JSON.stringify(label)}`); + }} + > + + + + + {label.text} + + + )) + } + + + + + {(labels) => + labels.reverse().map((label, i) => ( + { + if (events) alert(`clicked: ${JSON.stringify(label)}`); + }} + > + + + + + {label.text} + + + )) + } + + + + `${label.toUpperCase()}`} + > + {(labels) => ( +
+ {labels.map((label, i) => ( + { + if (events) alert(`clicked: ${JSON.stringify(label)}`); + }} + > + + + + + {label.text} + + + ))} +
+ )} +
+
+ + + {(labels) => ( +
+ {labels.map((label, i) => { + const color = ordinalColor2Scale(label.datum); + const shape = shapeScale(label.datum); + const isValidElement = React.isValidElement(shape); + return ( + { + const { datum, index } = label; + if (events) + alert( + `clicked: ${JSON.stringify({ datum, color, index })}` + ); + }} + > + + {isValidElement + ? React.cloneElement(shape as React.ReactElement) + : React.createElement( + shape as React.ComponentType<{ fill: string }>, + { + fill: color, + } + )} + + + {label.text} + + + ); + })} +
+ )} +
+
+ + +
+ ); +} diff --git a/src/components/main/GraphSections.tsx b/src/components/main/GraphSections.tsx new file mode 100644 index 0000000000000000000000000000000000000000..472d8e34897dd61db511331f72303e3734a00090 --- /dev/null +++ b/src/components/main/GraphSections.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import { Poi } from "../../redux/types/Poi"; +import DemographicsSection from "../../sections/demographics"; +import DescriptionSection from "../../sections/description"; +import FootfallSection from "../../sections/footfall"; +import ModeSection from "../../sections/mode"; +import InformationSection from "../../sections/information"; +import TraficSection from "../../sections/trafic"; + +type GraphSectionsProps = { + selectedPoi: Poi; + isDemographicsSection: boolean; + isFootfallSection: boolean; + isModeSection: boolean; + isInformationSection: boolean; + isTraficSection: boolean; +}; + +const GraphSections = ({ + selectedPoi, + isDemographicsSection, + isFootfallSection, + isModeSection, + isInformationSection, + isTraficSection, +}: GraphSectionsProps) => { + const renderSection = (state: boolean, section: JSX.Element) => { + return state ? section : null; + }; + + return ( + <> + + {renderSection( + isDemographicsSection, + + )} + {renderSection( + isFootfallSection, + + )} + {renderSection(isModeSection, )} + {renderSection( + isInformationSection, + + )} + {renderSection( + isTraficSection, + + )} + + ); +}; + +export default GraphSections; diff --git a/src/constants/main.ts b/src/constants/main.ts new file mode 100644 index 0000000000000000000000000000000000000000..67742cd054d82a7ea3de96f7068e6e06ff93f59b --- /dev/null +++ b/src/constants/main.ts @@ -0,0 +1 @@ +export const DEMOGRAPHICS_SECTION = 1; diff --git a/src/data/data.ts b/src/data/data.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e95fd502dffcecf4bb2d9f93f4adf7d3d4ecacc --- /dev/null +++ b/src/data/data.ts @@ -0,0 +1,5311 @@ +export const poiList = { + items: [ + { + id: "37869532-0308-4e7f-9409-8e59d7dfca65", + lat: 48.877034599999988, + lng: 2.3086978, + address: "31 Rue de Monceau", + ts_created: "2023-09-01T08:35:17.833286Z", + ts_updated: "2023-09-01T08:35:17.833286Z", + error: null, + state: null, + data: { + footfall: { + avg_daily_number: 17440.6985157266, + daytype_hour_distribution: [ + { + day_type: "SATURDAY", + hour: 0, + percentage: 0.006973303463104283, + }, + { + day_type: "SATURDAY", + hour: 1, + percentage: 0.0033327818586582963, + }, + { + day_type: "SATURDAY", + hour: 2, + percentage: 0.005864831291242033, + }, + { + day_type: "SATURDAY", + hour: 3, + percentage: 0, + }, + { + day_type: "SATURDAY", + hour: 4, + percentage: 0.00019839324028980595, + }, + { + day_type: "SATURDAY", + hour: 5, + percentage: 0.0015598351372808799, + }, + { + day_type: "SATURDAY", + hour: 6, + percentage: 0.006425470378479962, + }, + { + day_type: "SATURDAY", + hour: 7, + percentage: 0.002648477379501913, + }, + { + day_type: "SATURDAY", + hour: 8, + percentage: 0.018573437027597374, + }, + { + day_type: "SATURDAY", + hour: 9, + percentage: 0.030000085395931582, + }, + { + day_type: "SATURDAY", + hour: 10, + percentage: 0.0691902263159834, + }, + { + day_type: "SATURDAY", + hour: 11, + percentage: 0.04773574499959904, + }, + { + day_type: "SATURDAY", + hour: 12, + percentage: 0.05612483403744246, + }, + { + day_type: "SATURDAY", + hour: 13, + percentage: 0.10615910262517095, + }, + { + day_type: "SATURDAY", + hour: 14, + percentage: 0.05509225695966259, + }, + { + day_type: "SATURDAY", + hour: 15, + percentage: 0.0718086142287727, + }, + { + day_type: "SATURDAY", + hour: 16, + percentage: 0.07301615230676632, + }, + { + day_type: "SATURDAY", + hour: 17, + percentage: 0.07129803788984171, + }, + { + day_type: "SATURDAY", + hour: 18, + percentage: 0.05205365791987274, + }, + { + day_type: "SATURDAY", + hour: 19, + percentage: 0.05505912475529792, + }, + { + day_type: "SATURDAY", + hour: 20, + percentage: 0.037291005876552756, + }, + { + day_type: "SATURDAY", + hour: 21, + percentage: 0.018361348497472535, + }, + { + day_type: "SATURDAY", + hour: 22, + percentage: 0.011899747949488886, + }, + { + day_type: "SATURDAY", + hour: 23, + percentage: 0.009915541095251288, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 0, + percentage: 0.0016144004059411312, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 1, + percentage: 0.0005697525684024935, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 2, + percentage: 0.0006571122390810425, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 3, + percentage: 0, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 4, + percentage: 2.1054673605622763e-5, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 5, + percentage: 0.00027105406052476864, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 6, + percentage: 0.0011615460704465451, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 7, + percentage: 0.00376288270220158, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 8, + percentage: 0.018385158942663758, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 9, + percentage: 0.027917941246039454, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 10, + percentage: 0.04577147774527055, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 11, + percentage: 0.10709217792755978, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 12, + percentage: 0.05413888099857277, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 13, + percentage: 0.05912294790661425, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 14, + percentage: 0.03055861273321946, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 15, + percentage: 0.07345304181486333, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 16, + percentage: 0.0992030512564054, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 17, + percentage: 0.054451953778994325, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 18, + percentage: 0.028245334471392106, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 19, + percentage: 0.02146546552250561, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 20, + percentage: 0.01772127244621056, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 21, + percentage: 0.007641846080805942, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 22, + percentage: 0.0038716772415063228, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 23, + percentage: 0.002810011373309249, + }, + { + day_type: "WORKING_DAY", + hour: 0, + percentage: 0.003795602808138099, + }, + { + day_type: "WORKING_DAY", + hour: 1, + percentage: 0.0012501010131612637, + }, + { + day_type: "WORKING_DAY", + hour: 2, + percentage: 0.0007875003197658717, + }, + { + day_type: "WORKING_DAY", + hour: 3, + percentage: 0.00043983148772072374, + }, + { + day_type: "WORKING_DAY", + hour: 4, + percentage: 0.0018708501958342142, + }, + { + day_type: "WORKING_DAY", + hour: 5, + percentage: 0.0030478109129679883, + }, + { + day_type: "WORKING_DAY", + hour: 6, + percentage: 0.013498834024890015, + }, + { + day_type: "WORKING_DAY", + hour: 7, + percentage: 0.03509253714694336, + }, + { + day_type: "WORKING_DAY", + hour: 8, + percentage: 0.08816389024805311, + }, + { + day_type: "WORKING_DAY", + hour: 9, + percentage: 0.08432800599486026, + }, + { + day_type: "WORKING_DAY", + hour: 10, + percentage: 0.06523230082944143, + }, + { + day_type: "WORKING_DAY", + hour: 11, + percentage: 0.0746643198039038, + }, + { + day_type: "WORKING_DAY", + hour: 12, + percentage: 0.08340120298782826, + }, + { + day_type: "WORKING_DAY", + hour: 13, + percentage: 0.05250668593060444, + }, + { + day_type: "WORKING_DAY", + hour: 14, + percentage: 0.05461695355349352, + }, + { + day_type: "WORKING_DAY", + hour: 15, + percentage: 0.05552072439170519, + }, + { + day_type: "WORKING_DAY", + hour: 16, + percentage: 0.08581355911539687, + }, + { + day_type: "WORKING_DAY", + hour: 17, + percentage: 0.08133995945895146, + }, + { + day_type: "WORKING_DAY", + hour: 18, + percentage: 0.09239905447492745, + }, + { + day_type: "WORKING_DAY", + hour: 19, + percentage: 0.06393868166874156, + }, + { + day_type: "WORKING_DAY", + hour: 20, + percentage: 0.02979329095910868, + }, + { + day_type: "WORKING_DAY", + hour: 21, + percentage: 0.008358977463025077, + }, + { + day_type: "WORKING_DAY", + hour: 22, + percentage: 0.013051755457953267, + }, + { + day_type: "WORKING_DAY", + hour: 23, + percentage: 0.007087569752583225, + }, + ], + week_distribution: [ + { + indice_base_100: 97.35366383067951, + week: 1, + }, + { + indice_base_100: 97.46223504613279, + week: 2, + }, + { + indice_base_100: 97.60880617966619, + week: 3, + }, + { + indice_base_100: 97.77709155791881, + week: 4, + }, + { + indice_base_100: 97.96980545842699, + week: 5, + }, + { + indice_base_100: 98.18016217513564, + week: 6, + }, + { + indice_base_100: 98.40137601013247, + week: 7, + }, + { + indice_base_100: 98.630732694024, + week: 8, + }, + { + indice_base_100: 98.86958936150698, + week: 9, + }, + { + indice_base_100: 99.10573173516795, + week: 10, + }, + { + indice_base_100: 99.34323125981132, + week: 11, + }, + { + indice_base_100: 99.58480220483064, + week: 12, + }, + { + indice_base_100: 99.82365886417077, + week: 13, + }, + { + indice_base_100: 100.279932673678, + week: 14, + }, + { + indice_base_100: 100.51200363510586, + week: 15, + }, + { + indice_base_100: 100.74543173937332, + week: 16, + }, + { + indice_base_100: 100.96800271720974, + week: 17, + }, + { + indice_base_100: 101.1770022910788, + week: 18, + }, + { + indice_base_100: 101.37514474665966, + week: 19, + }, + { + indice_base_100: 101.55293010850373, + week: 20, + }, + { + indice_base_100: 101.70900122562855, + week: 21, + }, + { + indice_base_100: 101.83114383690639, + week: 22, + }, + { + indice_base_100: 103.50594556951616, + week: 23, + }, + { + indice_base_100: 103.5615883200824, + week: 24, + }, + { + indice_base_100: 103.57515971590692, + week: 25, + }, + { + indice_base_100: 103.54801692425785, + week: 26, + }, + { + indice_base_100: 101.28545894323358, + week: 27, + }, + { + indice_base_100: 101.17960200531661, + week: 28, + }, + { + indice_base_100: 101.04660227575062, + week: 29, + }, + { + indice_base_100: 100.88645973824985, + week: 30, + }, + { + indice_base_100: 100.70460295602986, + week: 31, + }, + { + indice_base_100: 100.50646050044901, + week: 32, + }, + { + indice_base_100: 100.29474664090077, + week: 33, + }, + { + indice_base_100: 100.07488994060067, + week: 34, + }, + { + indice_base_100: 99.84960468522792, + week: 35, + }, + { + indice_base_100: 101.80952042373681, + week: 36, + }, + { + indice_base_100: 101.57744946230893, + week: 37, + }, + { + indice_base_100: 101.34130707236228, + week: 38, + }, + { + indice_base_100: 101.10380756400458, + week: 39, + }, + { + indice_base_100: 98.84387624194588, + week: 40, + }, + { + indice_base_100: 98.61180528051801, + week: 41, + }, + { + indice_base_100: 98.37837717625054, + week: 42, + }, + { + indice_base_100: 98.15309192087778, + week: 43, + }, + { + indice_base_100: 97.93459234713161, + week: 44, + }, + { + indice_base_100: 97.72830706708456, + week: 45, + }, + { + indice_base_100: 97.53966457880946, + week: 46, + }, + { + indice_base_100: 97.37137920869968, + week: 47, + }, + { + indice_base_100: 99.96645231114695, + week: 48, + }, + { + indice_base_100: 99.86059538137286, + week: 49, + }, + { + indice_base_100: 99.79138123498207, + week: 50, + }, + { + indice_base_100: 99.76695271272652, + week: 51, + }, + { + indice_base_100: 99.78730982274898, + week: 52, + }, + ], + }, + mode: { + soft_mode: 0.7697936345265611, + vehicle: 0.23020636547343876, + }, + origin_top_10: [ + { + commune: "AUTRES", + percentage: 0.4235183655872554, + }, + { + commune: "75108", + percentage: 0.2239349172369961, + }, + { + commune: "75117", + percentage: 0.0894728353150189, + }, + { + commune: "75118", + percentage: 0.06206194955599398, + }, + { + commune: "75115", + percentage: 0.053636552763222226, + }, + { + commune: "75116", + percentage: 0.04959252651345241, + }, + { + commune: "75119", + percentage: 0.026587809202334136, + }, + { + commune: "75109", + percentage: 0.024782826780727202, + }, + { + commune: "92044", + percentage: 0.02452448408240073, + }, + { + commune: "75110", + percentage: 0.02188773296259902, + }, + ], + section: { + avg_speed: 26.5, + commune: "75108", + department: "75", + geometry: + '{ "type": "LineString", "coordinates": [ [2.30925, 48.87703], [2.30859, 48.8767] ] } ', + iris: "751083210", + length: 61, + max_speed: 50, + name: "Rue de Monceau", + nbr_direction: 1, + region: "11", + }, + socio_demography: [ + { + age: "15-24", + gender: "FEMALE", + percentage: 0, + social_group: "1", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.00031158249542968846, + social_group: "2", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.006326316811562401, + social_group: "3", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.014105837757733301, + social_group: "4", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.012378319047769615, + social_group: "5", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.0011621578243690084, + social_group: "6", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0, + social_group: "7", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.020335685826673243, + social_group: "8", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 3.0879688139125164e-5, + social_group: "1", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.0022462841213032477, + social_group: "2", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.13312319197299213, + social_group: "3", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.020334716582723178, + social_group: "4", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.011524341471942923, + social_group: "5", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.003295812104837797, + social_group: "6", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0, + social_group: "7", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.0020731447535718957, + social_group: "8", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0, + social_group: "1", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.005248042055179452, + social_group: "2", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.05890777021381176, + social_group: "3", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.03170425020902112, + social_group: "4", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.026774694057559136, + social_group: "5", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.004204729826760328, + social_group: "6", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.00011505520723929448, + social_group: "7", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.01194157158108294, + social_group: "8", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 5.577940872629436e-5, + social_group: "1", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.007191628981974905, + social_group: "2", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.04441724496185934, + social_group: "3", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.018016792094362907, + social_group: "4", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.025638421620726215, + social_group: "5", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.0017335856961051476, + social_group: "6", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.002112488073830816, + social_group: "7", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.004906039099330483, + social_group: "8", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 4.574816740222358e-6, + social_group: "1", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0004824729798047382, + social_group: "2", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0019870275220699226, + social_group: "3", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0009800463490156884, + social_group: "4", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0009439222193821032, + social_group: "5", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0004914068895457441, + social_group: "6", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.016804847881444894, + social_group: "7", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.003293083493348743, + social_group: "8", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0, + social_group: "1", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.0008120328408777674, + social_group: "2", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.014154767642486422, + social_group: "3", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.005496624200710941, + social_group: "4", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.007783351757346492, + social_group: "5", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.0035314135627534126, + social_group: "6", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0, + social_group: "7", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.01828430847064519, + social_group: "8", + }, + { + age: "25-34", + gender: "MALE", + percentage: 4.533072032303482e-5, + social_group: "1", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.0069323911457518945, + social_group: "2", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.06466885640149915, + social_group: "3", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.028216730064238006, + social_group: "4", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.02932739990067367, + social_group: "5", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.009872378486019564, + social_group: "6", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0, + social_group: "7", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.0030008619623858035, + social_group: "8", + }, + { + age: "35-49", + gender: "MALE", + percentage: 4.846967839414946e-5, + social_group: "1", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.013191438192254908, + social_group: "2", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.09858055785716019, + social_group: "3", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.025900397250136115, + social_group: "4", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.03467377626418078, + social_group: "5", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.01246016241721313, + social_group: "6", + }, + { + age: "35-49", + gender: "MALE", + percentage: 8.147862933404878e-5, + social_group: "7", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.0008027166922112632, + social_group: "8", + }, + { + age: "50-64", + gender: "MALE", + percentage: 6.400646967448577e-5, + social_group: "1", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.008262541897000163, + social_group: "2", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.05438194993209146, + social_group: "3", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.011936349956925357, + social_group: "4", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.00920073832360114, + social_group: "5", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.007619434578803137, + social_group: "6", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.0016940404206729556, + social_group: "7", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.00598958129253543, + social_group: "8", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0, + social_group: "1", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0039366197548585885, + social_group: "2", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.004599546216674328, + social_group: "3", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0014314034317906613, + social_group: "4", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0005013437041491296, + social_group: "5", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0008714446665018286, + social_group: "6", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.016202124159625207, + social_group: "7", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.00023968536053025204, + social_group: "8", + }, + ], + traffic: { + avg_daily_flow: 4012, + daytype_hour_distribution: [ + { + day_type: "SATURDAY", + hour: 0, + percentage: 0.007446775951494883, + }, + { + day_type: "SATURDAY", + hour: 1, + percentage: 0.004675553029622485, + }, + { + day_type: "SATURDAY", + hour: 2, + percentage: 0.0032142509881956096, + }, + { + day_type: "SATURDAY", + hour: 3, + percentage: 0.002775259355895538, + }, + { + day_type: "SATURDAY", + hour: 4, + percentage: 0.00521026721410662, + }, + { + day_type: "SATURDAY", + hour: 5, + percentage: 0.009778720548322989, + }, + { + day_type: "SATURDAY", + hour: 6, + percentage: 0.012854318495076029, + }, + { + day_type: "SATURDAY", + hour: 7, + percentage: 0.029140303624479405, + }, + { + day_type: "SATURDAY", + hour: 8, + percentage: 0.05194055368893026, + }, + { + day_type: "SATURDAY", + hour: 9, + percentage: 0.0699984123515333, + }, + { + day_type: "SATURDAY", + hour: 10, + percentage: 0.07048935604979267, + }, + { + day_type: "SATURDAY", + hour: 11, + percentage: 0.06497170794473413, + }, + { + day_type: "SATURDAY", + hour: 12, + percentage: 0.05884679643200482, + }, + { + day_type: "SATURDAY", + hour: 13, + percentage: 0.05675606094125499, + }, + { + day_type: "SATURDAY", + hour: 14, + percentage: 0.06237486662051666, + }, + { + day_type: "SATURDAY", + hour: 15, + percentage: 0.0501878265376101, + }, + { + day_type: "SATURDAY", + hour: 16, + percentage: 0.053194300254852625, + }, + { + day_type: "SATURDAY", + hour: 17, + percentage: 0.05586204974612174, + }, + { + day_type: "SATURDAY", + hour: 18, + percentage: 0.054569390440313406, + }, + { + day_type: "SATURDAY", + hour: 19, + percentage: 0.04430493240357506, + }, + { + day_type: "SATURDAY", + hour: 20, + percentage: 0.037258025345000084, + }, + { + day_type: "SATURDAY", + hour: 21, + percentage: 0.025031868991651492, + }, + { + day_type: "SATURDAY", + hour: 22, + percentage: 0.017654979605927174, + }, + { + day_type: "SATURDAY", + hour: 23, + percentage: 0.01328086445124812, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 0, + percentage: 0.009986865539776462, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 1, + percentage: 0.006480831737692823, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 2, + percentage: 0.003771659670497158, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 3, + percentage: 0.0023673217639864847, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 4, + percentage: 0.0036556984603722045, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 5, + percentage: 0.007676753156362383, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 6, + percentage: 0.00944561525503771, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 7, + percentage: 0.014294900545309044, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 8, + percentage: 0.02694559646745666, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 9, + percentage: 0.0438202610714391, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 10, + percentage: 0.05603180533877073, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 11, + percentage: 0.06213884486822559, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 12, + percentage: 0.06005381758848549, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 13, + percentage: 0.056668055750833536, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 14, + percentage: 0.06549528905125342, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 15, + percentage: 0.06765723125779811, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 16, + percentage: 0.0799665732910172, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 17, + percentage: 0.08753691272031106, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 18, + percentage: 0.09377117947094675, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 19, + percentage: 0.08017902150758988, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 20, + percentage: 0.06553476183782903, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 21, + percentage: 0.05547471304467792, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 22, + percentage: 0.03785258350474419, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 23, + percentage: 0.019210689564251808, + }, + { + day_type: "WORKING_DAY", + hour: 0, + percentage: 0.006351581250785439, + }, + { + day_type: "WORKING_DAY", + hour: 1, + percentage: 0.002465559898784744, + }, + { + day_type: "WORKING_DAY", + hour: 2, + percentage: 0.0018087992701054801, + }, + { + day_type: "WORKING_DAY", + hour: 3, + percentage: 0.0021602619098388407, + }, + { + day_type: "WORKING_DAY", + hour: 4, + percentage: 0.0065518370097038614, + }, + { + day_type: "WORKING_DAY", + hour: 5, + percentage: 0.023020160875000428, + }, + { + day_type: "WORKING_DAY", + hour: 6, + percentage: 0.05519105536276142, + }, + { + day_type: "WORKING_DAY", + hour: 7, + percentage: 0.09398480943157017, + }, + { + day_type: "WORKING_DAY", + hour: 8, + percentage: 0.09815470392384296, + }, + { + day_type: "WORKING_DAY", + hour: 9, + percentage: 0.07406806929359531, + }, + { + day_type: "WORKING_DAY", + hour: 10, + percentage: 0.06528982256363337, + }, + { + day_type: "WORKING_DAY", + hour: 11, + percentage: 0.06015485739484406, + }, + { + day_type: "WORKING_DAY", + hour: 12, + percentage: 0.0551823821013851, + }, + { + day_type: "WORKING_DAY", + hour: 13, + percentage: 0.051350904732580714, + }, + { + day_type: "WORKING_DAY", + hour: 14, + percentage: 0.056023753847739687, + }, + { + day_type: "WORKING_DAY", + hour: 15, + percentage: 0.048930624895072314, + }, + { + day_type: "WORKING_DAY", + hour: 16, + percentage: 0.05491405271738931, + }, + { + day_type: "WORKING_DAY", + hour: 17, + percentage: 0.06274495000415033, + }, + { + day_type: "WORKING_DAY", + hour: 18, + percentage: 0.06278916910614217, + }, + { + day_type: "WORKING_DAY", + hour: 19, + percentage: 0.05059355998547924, + }, + { + day_type: "WORKING_DAY", + hour: 20, + percentage: 0.038656257683140065, + }, + { + day_type: "WORKING_DAY", + hour: 21, + percentage: 0.024552747172339195, + }, + { + day_type: "WORKING_DAY", + hour: 22, + percentage: 0.020796844217658785, + }, + { + day_type: "WORKING_DAY", + hour: 23, + percentage: 0.008696350657072133, + }, + ], + week_distribution: [ + { + indice_base_100: 94.57284734835793, + week: 1, + }, + { + indice_base_100: 96.73234721613305, + week: 2, + }, + { + indice_base_100: 88.28542195785047, + week: 3, + }, + { + indice_base_100: 90.40462466985775, + week: 4, + }, + { + indice_base_100: 91.57493214058783, + week: 5, + }, + { + indice_base_100: 96.95766819576606, + week: 6, + }, + { + indice_base_100: 108.54960785002913, + week: 7, + }, + { + indice_base_100: 99.32861255034979, + week: 8, + }, + { + indice_base_100: 99.4988779921889, + week: 9, + }, + { + indice_base_100: 125.79303470407265, + week: 10, + }, + { + indice_base_100: 101.90162966319427, + week: 11, + }, + { + indice_base_100: 101.7283074084746, + week: 12, + }, + { + indice_base_100: 100.94091976740805, + week: 13, + }, + { + indice_base_100: 103.56717392487924, + week: 14, + }, + { + indice_base_100: 101.58324133504534, + week: 15, + }, + { + indice_base_100: 114.09914033208246, + week: 16, + }, + { + indice_base_100: 91.5831983044842, + week: 17, + }, + { + indice_base_100: 99.18957433830974, + week: 18, + }, + { + indice_base_100: 97.6604705975341, + week: 19, + }, + { + indice_base_100: 103.30992638734845, + week: 20, + }, + { + indice_base_100: 87.76995185633749, + week: 21, + }, + { + indice_base_100: 96.55972265133698, + week: 22, + }, + { + indice_base_100: 107.00242765091275, + week: 23, + }, + { + indice_base_100: 89.17776183879855, + week: 24, + }, + { + indice_base_100: 100.1588700649956, + week: 25, + }, + { + indice_base_100: 99.29800359340916, + week: 26, + }, + { + indice_base_100: 90.61518445547273, + week: 27, + }, + { + indice_base_100: 81.3921824434114, + week: 28, + }, + { + indice_base_100: 92.28287025240155, + week: 29, + }, + { + indice_base_100: 82.07494844886622, + week: 30, + }, + { + indice_base_100: 72.47820678053719, + week: 31, + }, + { + indice_base_100: 65.14895598483295, + week: 32, + }, + { + indice_base_100: 77.8691578078028, + week: 33, + }, + { + indice_base_100: 90.66478586787552, + week: 34, + }, + { + indice_base_100: 94.38458896494704, + week: 35, + }, + { + indice_base_100: 95.65670240546986, + week: 36, + }, + { + indice_base_100: 105.04448439310077, + week: 37, + }, + { + indice_base_100: 112.95326993967758, + week: 38, + }, + { + indice_base_100: 110.97277041432696, + week: 39, + }, + { + indice_base_100: 103.89154766145145, + week: 40, + }, + { + indice_base_100: 110.31330641619171, + week: 41, + }, + { + indice_base_100: 111.74532354549629, + week: 42, + }, + { + indice_base_100: 109.70132585961679, + week: 43, + }, + { + indice_base_100: 143.80901446261788, + week: 44, + }, + { + indice_base_100: 111.26160181991254, + week: 45, + }, + { + indice_base_100: 123.08603056126137, + week: 46, + }, + { + indice_base_100: 113.90072767229287, + week: 47, + }, + { + indice_base_100: 111.93782470112568, + week: 48, + }, + { + indice_base_100: 107.31780216959872, + week: 49, + }, + { + indice_base_100: 101.42056912077287, + week: 50, + }, + { + indice_base_100: 88.11189911499892, + week: 51, + }, + { + indice_base_100: 104.73662439619646, + week: 52, + }, + ], + }, + trip_purpose: [ + { + percentage: 0.031076454484835158, + trip_purpose_group: "ACCOMPAGNEMENT", + }, + { + percentage: 0.0792646659288684, + trip_purpose_group: "ACHAT_GRAND", + }, + { + percentage: 0.06494964078158855, + trip_purpose_group: "ACHAT_PETIT", + }, + { + percentage: 0, + trip_purpose_group: "COLLEGE", + }, + { + percentage: 0.06609696269415305, + trip_purpose_group: "DEMARCHE", + }, + { + percentage: 0.1118546989745553, + trip_purpose_group: "DOMICILE", + }, + { + percentage: 0, + trip_purpose_group: "FORMATION_SUPERIEUR", + }, + { + percentage: 0, + trip_purpose_group: "LYCEE", + }, + { + percentage: 0.04054228183062124, + trip_purpose_group: "RESTAURATION", + }, + { + percentage: 0.018752331459940694, + trip_purpose_group: "SOIN", + }, + { + percentage: 0, + trip_purpose_group: "SPORT_CULTURE_LOISIR_RELIGION", + }, + { + percentage: 0.016676776457084982, + trip_purpose_group: "TOURISME_AUTRE", + }, + { + percentage: 0.0029793759645218372, + trip_purpose_group: "TOURISME_EXCEPTIONNEL", + }, + { + percentage: 0, + trip_purpose_group: "TOURISME_HEBERGEMENT", + }, + { + percentage: 0.5546159883071546, + trip_purpose_group: "TRAVAIL", + }, + { + percentage: 0.013190823116676112, + trip_purpose_group: "VISITE", + }, + ], + }, + }, + { + id: "d04ad07f-c5af-410e-a9ad-3614e2220ec1", + lat: 48.8751901, + lng: 2.3074241, + address: "178 bd haussmann", + ts_created: "2023-09-01T08:35:17.833286Z", + ts_updated: "2023-09-01T08:35:17.833286Z", + error: null, + state: null, + data: { + footfall: { + avg_daily_number: 33471.121737897876, + daytype_hour_distribution: [ + { + day_type: "SATURDAY", + hour: 0, + percentage: 0.006973303463104283, + }, + { + day_type: "SATURDAY", + hour: 1, + percentage: 0.0033327818586582963, + }, + { + day_type: "SATURDAY", + hour: 2, + percentage: 0.005864831291242033, + }, + { + day_type: "SATURDAY", + hour: 3, + percentage: 0, + }, + { + day_type: "SATURDAY", + hour: 4, + percentage: 0.00019839324028980595, + }, + { + day_type: "SATURDAY", + hour: 5, + percentage: 0.0015598351372808799, + }, + { + day_type: "SATURDAY", + hour: 6, + percentage: 0.006425470378479962, + }, + { + day_type: "SATURDAY", + hour: 7, + percentage: 0.002648477379501913, + }, + { + day_type: "SATURDAY", + hour: 8, + percentage: 0.018573437027597374, + }, + { + day_type: "SATURDAY", + hour: 9, + percentage: 0.030000085395931582, + }, + { + day_type: "SATURDAY", + hour: 10, + percentage: 0.0691902263159834, + }, + { + day_type: "SATURDAY", + hour: 11, + percentage: 0.04773574499959904, + }, + { + day_type: "SATURDAY", + hour: 12, + percentage: 0.05612483403744246, + }, + { + day_type: "SATURDAY", + hour: 13, + percentage: 0.10615910262517095, + }, + { + day_type: "SATURDAY", + hour: 14, + percentage: 0.05509225695966259, + }, + { + day_type: "SATURDAY", + hour: 15, + percentage: 0.0718086142287727, + }, + { + day_type: "SATURDAY", + hour: 16, + percentage: 0.07301615230676632, + }, + { + day_type: "SATURDAY", + hour: 17, + percentage: 0.07129803788984171, + }, + { + day_type: "SATURDAY", + hour: 18, + percentage: 0.05205365791987274, + }, + { + day_type: "SATURDAY", + hour: 19, + percentage: 0.05505912475529792, + }, + { + day_type: "SATURDAY", + hour: 20, + percentage: 0.037291005876552756, + }, + { + day_type: "SATURDAY", + hour: 21, + percentage: 0.018361348497472535, + }, + { + day_type: "SATURDAY", + hour: 22, + percentage: 0.011899747949488886, + }, + { + day_type: "SATURDAY", + hour: 23, + percentage: 0.009915541095251288, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 0, + percentage: 0.0016144004059411312, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 1, + percentage: 0.0005697525684024935, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 2, + percentage: 0.0006571122390810425, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 3, + percentage: 0, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 4, + percentage: 2.1054673605622763e-5, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 5, + percentage: 0.00027105406052476864, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 6, + percentage: 0.0011615460704465451, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 7, + percentage: 0.00376288270220158, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 8, + percentage: 0.018385158942663758, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 9, + percentage: 0.027917941246039454, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 10, + percentage: 0.04577147774527055, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 11, + percentage: 0.10709217792755978, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 12, + percentage: 0.05413888099857277, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 13, + percentage: 0.05912294790661425, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 14, + percentage: 0.03055861273321946, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 15, + percentage: 0.07345304181486333, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 16, + percentage: 0.0992030512564054, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 17, + percentage: 0.054451953778994325, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 18, + percentage: 0.028245334471392106, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 19, + percentage: 0.02146546552250561, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 20, + percentage: 0.01772127244621056, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 21, + percentage: 0.007641846080805942, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 22, + percentage: 0.0038716772415063228, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 23, + percentage: 0.002810011373309249, + }, + { + day_type: "WORKING_DAY", + hour: 0, + percentage: 0.003795602808138099, + }, + { + day_type: "WORKING_DAY", + hour: 1, + percentage: 0.0012501010131612637, + }, + { + day_type: "WORKING_DAY", + hour: 2, + percentage: 0.0007875003197658717, + }, + { + day_type: "WORKING_DAY", + hour: 3, + percentage: 0.00043983148772072374, + }, + { + day_type: "WORKING_DAY", + hour: 4, + percentage: 0.0018708501958342142, + }, + { + day_type: "WORKING_DAY", + hour: 5, + percentage: 0.0030478109129679883, + }, + { + day_type: "WORKING_DAY", + hour: 6, + percentage: 0.013498834024890015, + }, + { + day_type: "WORKING_DAY", + hour: 7, + percentage: 0.03509253714694336, + }, + { + day_type: "WORKING_DAY", + hour: 8, + percentage: 0.08816389024805311, + }, + { + day_type: "WORKING_DAY", + hour: 9, + percentage: 0.08432800599486026, + }, + { + day_type: "WORKING_DAY", + hour: 10, + percentage: 0.06523230082944143, + }, + { + day_type: "WORKING_DAY", + hour: 11, + percentage: 0.0746643198039038, + }, + { + day_type: "WORKING_DAY", + hour: 12, + percentage: 0.08340120298782826, + }, + { + day_type: "WORKING_DAY", + hour: 13, + percentage: 0.05250668593060444, + }, + { + day_type: "WORKING_DAY", + hour: 14, + percentage: 0.05461695355349352, + }, + { + day_type: "WORKING_DAY", + hour: 15, + percentage: 0.05552072439170519, + }, + { + day_type: "WORKING_DAY", + hour: 16, + percentage: 0.08581355911539687, + }, + { + day_type: "WORKING_DAY", + hour: 17, + percentage: 0.08133995945895146, + }, + { + day_type: "WORKING_DAY", + hour: 18, + percentage: 0.09239905447492745, + }, + { + day_type: "WORKING_DAY", + hour: 19, + percentage: 0.06393868166874156, + }, + { + day_type: "WORKING_DAY", + hour: 20, + percentage: 0.02979329095910868, + }, + { + day_type: "WORKING_DAY", + hour: 21, + percentage: 0.008358977463025077, + }, + { + day_type: "WORKING_DAY", + hour: 22, + percentage: 0.013051755457953267, + }, + { + day_type: "WORKING_DAY", + hour: 23, + percentage: 0.007087569752583225, + }, + ], + week_distribution: [ + { + indice_base_100: 96.41917967065841, + week: 1, + }, + { + indice_base_100: 96.61225291264441, + week: 2, + }, + { + indice_base_100: 96.87290177629306, + week: 3, + }, + { + indice_base_100: 97.17216529123505, + week: 4, + }, + { + indice_base_100: 97.5148702834518, + week: 5, + }, + { + indice_base_100: 97.88894966626889, + week: 6, + }, + { + indice_base_100: 98.28233636749239, + week: 7, + }, + { + indice_base_100: 97.38418120910481, + week: 8, + }, + { + indice_base_100: 97.80894232988963, + week: 9, + }, + { + indice_base_100: 99.53489896224846, + week: 10, + }, + { + indice_base_100: 99.95724666280232, + week: 11, + }, + { + indice_base_100: 100.38683460956861, + week: 12, + }, + { + indice_base_100: 100.81159571587293, + week: 13, + }, + { + indice_base_100: 101.57055058993348, + week: 14, + }, + { + indice_base_100: 101.98324462404386, + week: 15, + }, + { + indice_base_100: 102.39835207838523, + week: 16, + }, + { + indice_base_100: 101.48812983332324, + week: 17, + }, + { + indice_base_100: 101.85979579590936, + week: 18, + }, + { + indice_base_100: 103.51817680660554, + week: 19, + }, + { + indice_base_100: 103.83433423420342, + week: 20, + }, + { + indice_base_100: 104.111877010508, + week: 21, + }, + { + indice_base_100: 104.32908439688188, + week: 22, + }, + { + indice_base_100: 106.93072570783397, + week: 23, + }, + { + indice_base_100: 107.029675749058, + week: 24, + }, + { + indice_base_100: 107.05380989344586, + week: 25, + }, + { + indice_base_100: 107.00554160467009, + week: 26, + }, + { + indice_base_100: 101.67554528610982, + week: 27, + }, + { + indice_base_100: 98.87525413707233, + week: 28, + }, + { + indice_base_100: 98.63873943229206, + week: 29, + }, + { + indice_base_100: 98.35395640977501, + week: 30, + }, + { + indice_base_100: 98.03055873596466, + week: 31, + }, + { + indice_base_100: 97.67820009178497, + week: 32, + }, + { + indice_base_100: 97.30170728873688, + week: 33, + }, + { + indice_base_100: 96.91073399326388, + week: 34, + }, + { + indice_base_100: 96.51010704582792, + week: 35, + }, + { + indice_base_100: 103.91395647194838, + week: 36, + }, + { + indice_base_100: 103.501262437838, + week: 37, + }, + { + indice_base_100: 103.08132814303464, + week: 38, + }, + { + indice_base_100: 102.6589804714418, + week: 39, + }, + { + indice_base_100: 99.12224394388879, + week: 40, + }, + { + indice_base_100: 98.7095499097784, + week: 41, + }, + { + indice_base_100: 98.29444245543702, + week: 42, + }, + { + indice_base_100: 96.58779314148458, + week: 43, + }, + { + indice_base_100: 96.19923323728158, + week: 44, + }, + { + indice_base_100: 97.1384164961544, + week: 45, + }, + { + indice_base_100: 96.80295173566964, + week: 46, + }, + { + indice_base_100: 96.50368823520814, + week: 47, + }, + { + indice_base_100: 99.4722050787586, + week: 48, + }, + { + indice_base_100: 99.28395867723455, + week: 49, + }, + { + indice_base_100: 99.16087449162269, + week: 50, + }, + { + indice_base_100: 97.81141064783144, + week: 51, + }, + { + indice_base_100: 97.84761189337424, + week: 52, + }, + ], + }, + mode: { + soft_mode: 0.3348574889074485, + vehicle: 0.6651425110925515, + }, + origin_top_10: [ + { + commune: "AUTRES", + percentage: 0.42495190985518844, + }, + { + commune: "75108", + percentage: 0.22383831051128075, + }, + { + commune: "75117", + percentage: 0.08574217812679136, + }, + { + commune: "75118", + percentage: 0.05866324903235986, + }, + { + commune: "75115", + percentage: 0.0577058088454153, + }, + { + commune: "75116", + percentage: 0.052937343747125304, + }, + { + commune: "75119", + percentage: 0.025617454979350578, + }, + { + commune: "75109", + percentage: 0.0239805223159214, + }, + { + commune: "92044", + percentage: 0.023751907900199817, + }, + { + commune: "75114", + percentage: 0.02281131468636706, + }, + ], + section: { + avg_speed: 27.2, + commune: "75108", + department: "75", + geometry: + '{ "type": "LineString", "coordinates": [ [2.30811, 48.87501], [2.30644, 48.87494] ] } ', + iris: "751083002", + length: 122, + max_speed: 50, + name: "Boulevard Haussmann", + nbr_direction: 2, + region: "11", + }, + socio_demography: [ + { + age: "15-24", + gender: "FEMALE", + percentage: 0, + social_group: "1", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.00028915312416660674, + social_group: "2", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.0069749405279014316, + social_group: "3", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.010402473106331602, + social_group: "4", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.00982853329916726, + social_group: "5", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.0016339477163747334, + social_group: "6", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0, + social_group: "7", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.014478107526332235, + social_group: "8", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 2.085526112127998e-5, + social_group: "1", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.0014814696208555777, + social_group: "2", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.07186178026418912, + social_group: "3", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.02199682328094838, + social_group: "4", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.011234780971462096, + social_group: "5", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.002056147484274182, + social_group: "6", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0, + social_group: "7", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.001403882126766549, + social_group: "8", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0, + social_group: "1", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.0041898654073147254, + social_group: "2", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.05459856843784022, + social_group: "3", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.03856861606427487, + social_group: "4", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.026066774001763084, + social_group: "5", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.0043624947691602725, + social_group: "6", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.00010384031084987632, + social_group: "7", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.007384829002388531, + social_group: "8", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 5.448421334785772e-5, + social_group: "1", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.004738043391745396, + social_group: "2", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.04535875195600566, + social_group: "3", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.02010444892790976, + social_group: "4", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.025906279720096542, + social_group: "5", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.001958317556363143, + social_group: "6", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.001614644987802714, + social_group: "7", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.0062760830629551186, + social_group: "8", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 3.021947199614989e-6, + social_group: "1", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0003185579022612243, + social_group: "2", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0016698018166776702, + social_group: "3", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0006201899041369576, + social_group: "4", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0005472658899846496, + social_group: "5", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0002734020087385049, + social_group: "6", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.012843914025984338, + social_group: "7", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0021598049549529964, + social_group: "8", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0, + social_group: "1", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.0010610466329445494, + social_group: "2", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.019157093525288126, + social_group: "3", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.0034212444781205834, + social_group: "4", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.009372362973955457, + social_group: "5", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.009269295265585778, + social_group: "6", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0, + social_group: "7", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.014385211650457367, + social_group: "8", + }, + { + age: "25-34", + gender: "MALE", + percentage: 5.931569588904401e-5, + social_group: "1", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.007836043558356176, + social_group: "2", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.05712882204425855, + social_group: "3", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.031339631622747194, + social_group: "4", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.0486165772579201, + social_group: "5", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.016417312170049155, + social_group: "6", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0, + social_group: "7", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.004030555403601121, + social_group: "8", + }, + { + age: "35-49", + gender: "MALE", + percentage: 5.998137920472336e-5, + social_group: "1", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.021512723628058426, + social_group: "2", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.1105368441909941, + social_group: "3", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.02911042642685161, + social_group: "4", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.04199830534554602, + social_group: "5", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.014927573531075815, + social_group: "6", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.00010097078805972802, + social_group: "7", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.0007339222153547127, + social_group: "8", + }, + { + age: "50-64", + gender: "MALE", + percentage: 6.584583813584692e-5, + social_group: "1", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.01344617127255909, + social_group: "2", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.06813944218173429, + social_group: "3", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.01751972303568231, + social_group: "4", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.006972232767206465, + social_group: "5", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.006087459264453643, + social_group: "6", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.0020028663143826916, + social_group: "7", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.0042558667731062245, + social_group: "8", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0, + social_group: "1", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0031963821595106905, + social_group: "2", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0048990989509658306, + social_group: "3", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0014109784872932138, + social_group: "4", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0005973428689343417, + social_group: "5", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0008434566524294123, + social_group: "6", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.015848245599469717, + social_group: "7", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.000254733480172981, + social_group: "8", + }, + ], + traffic: { + avg_daily_flow: 61090, + daytype_hour_distribution: [ + { + day_type: "SATURDAY", + hour: 0, + percentage: 0.007446775951494883, + }, + { + day_type: "SATURDAY", + hour: 1, + percentage: 0.004675553029622485, + }, + { + day_type: "SATURDAY", + hour: 2, + percentage: 0.0032142509881956096, + }, + { + day_type: "SATURDAY", + hour: 3, + percentage: 0.002775259355895538, + }, + { + day_type: "SATURDAY", + hour: 4, + percentage: 0.00521026721410662, + }, + { + day_type: "SATURDAY", + hour: 5, + percentage: 0.009778720548322989, + }, + { + day_type: "SATURDAY", + hour: 6, + percentage: 0.012854318495076029, + }, + { + day_type: "SATURDAY", + hour: 7, + percentage: 0.029140303624479405, + }, + { + day_type: "SATURDAY", + hour: 8, + percentage: 0.05194055368893026, + }, + { + day_type: "SATURDAY", + hour: 9, + percentage: 0.0699984123515333, + }, + { + day_type: "SATURDAY", + hour: 10, + percentage: 0.07048935604979267, + }, + { + day_type: "SATURDAY", + hour: 11, + percentage: 0.06497170794473413, + }, + { + day_type: "SATURDAY", + hour: 12, + percentage: 0.05884679643200482, + }, + { + day_type: "SATURDAY", + hour: 13, + percentage: 0.05675606094125499, + }, + { + day_type: "SATURDAY", + hour: 14, + percentage: 0.06237486662051666, + }, + { + day_type: "SATURDAY", + hour: 15, + percentage: 0.0501878265376101, + }, + { + day_type: "SATURDAY", + hour: 16, + percentage: 0.053194300254852625, + }, + { + day_type: "SATURDAY", + hour: 17, + percentage: 0.05586204974612174, + }, + { + day_type: "SATURDAY", + hour: 18, + percentage: 0.054569390440313406, + }, + { + day_type: "SATURDAY", + hour: 19, + percentage: 0.04430493240357506, + }, + { + day_type: "SATURDAY", + hour: 20, + percentage: 0.037258025345000084, + }, + { + day_type: "SATURDAY", + hour: 21, + percentage: 0.025031868991651492, + }, + { + day_type: "SATURDAY", + hour: 22, + percentage: 0.017654979605927174, + }, + { + day_type: "SATURDAY", + hour: 23, + percentage: 0.01328086445124812, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 0, + percentage: 0.009986865539776462, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 1, + percentage: 0.006480831737692823, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 2, + percentage: 0.003771659670497158, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 3, + percentage: 0.0023673217639864847, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 4, + percentage: 0.0036556984603722045, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 5, + percentage: 0.007676753156362383, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 6, + percentage: 0.00944561525503771, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 7, + percentage: 0.014294900545309044, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 8, + percentage: 0.02694559646745666, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 9, + percentage: 0.0438202610714391, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 10, + percentage: 0.05603180533877073, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 11, + percentage: 0.06213884486822559, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 12, + percentage: 0.06005381758848549, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 13, + percentage: 0.056668055750833536, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 14, + percentage: 0.06549528905125342, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 15, + percentage: 0.06765723125779811, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 16, + percentage: 0.0799665732910172, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 17, + percentage: 0.08753691272031106, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 18, + percentage: 0.09377117947094675, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 19, + percentage: 0.08017902150758988, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 20, + percentage: 0.06553476183782903, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 21, + percentage: 0.05547471304467792, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 22, + percentage: 0.03785258350474419, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 23, + percentage: 0.019210689564251808, + }, + { + day_type: "WORKING_DAY", + hour: 0, + percentage: 0.006351581250785439, + }, + { + day_type: "WORKING_DAY", + hour: 1, + percentage: 0.002465559898784744, + }, + { + day_type: "WORKING_DAY", + hour: 2, + percentage: 0.0018087992701054801, + }, + { + day_type: "WORKING_DAY", + hour: 3, + percentage: 0.0021602619098388407, + }, + { + day_type: "WORKING_DAY", + hour: 4, + percentage: 0.0065518370097038614, + }, + { + day_type: "WORKING_DAY", + hour: 5, + percentage: 0.023020160875000428, + }, + { + day_type: "WORKING_DAY", + hour: 6, + percentage: 0.05519105536276142, + }, + { + day_type: "WORKING_DAY", + hour: 7, + percentage: 0.09398480943157017, + }, + { + day_type: "WORKING_DAY", + hour: 8, + percentage: 0.09815470392384296, + }, + { + day_type: "WORKING_DAY", + hour: 9, + percentage: 0.07406806929359531, + }, + { + day_type: "WORKING_DAY", + hour: 10, + percentage: 0.06528982256363337, + }, + { + day_type: "WORKING_DAY", + hour: 11, + percentage: 0.06015485739484406, + }, + { + day_type: "WORKING_DAY", + hour: 12, + percentage: 0.0551823821013851, + }, + { + day_type: "WORKING_DAY", + hour: 13, + percentage: 0.051350904732580714, + }, + { + day_type: "WORKING_DAY", + hour: 14, + percentage: 0.056023753847739687, + }, + { + day_type: "WORKING_DAY", + hour: 15, + percentage: 0.048930624895072314, + }, + { + day_type: "WORKING_DAY", + hour: 16, + percentage: 0.05491405271738931, + }, + { + day_type: "WORKING_DAY", + hour: 17, + percentage: 0.06274495000415033, + }, + { + day_type: "WORKING_DAY", + hour: 18, + percentage: 0.06278916910614217, + }, + { + day_type: "WORKING_DAY", + hour: 19, + percentage: 0.05059355998547924, + }, + { + day_type: "WORKING_DAY", + hour: 20, + percentage: 0.038656257683140065, + }, + { + day_type: "WORKING_DAY", + hour: 21, + percentage: 0.024552747172339195, + }, + { + day_type: "WORKING_DAY", + hour: 22, + percentage: 0.020796844217658785, + }, + { + day_type: "WORKING_DAY", + hour: 23, + percentage: 0.008696350657072133, + }, + ], + week_distribution: [ + { + indice_base_100: 94.57284734835793, + week: 1, + }, + { + indice_base_100: 96.73234721613305, + week: 2, + }, + { + indice_base_100: 88.28542195785047, + week: 3, + }, + { + indice_base_100: 90.40462466985775, + week: 4, + }, + { + indice_base_100: 91.57493214058783, + week: 5, + }, + { + indice_base_100: 96.95766819576606, + week: 6, + }, + { + indice_base_100: 108.54960785002913, + week: 7, + }, + { + indice_base_100: 99.32861255034979, + week: 8, + }, + { + indice_base_100: 99.4988779921889, + week: 9, + }, + { + indice_base_100: 125.79303470407265, + week: 10, + }, + { + indice_base_100: 101.90162966319427, + week: 11, + }, + { + indice_base_100: 101.7283074084746, + week: 12, + }, + { + indice_base_100: 100.94091976740805, + week: 13, + }, + { + indice_base_100: 103.56717392487924, + week: 14, + }, + { + indice_base_100: 101.58324133504534, + week: 15, + }, + { + indice_base_100: 114.09914033208246, + week: 16, + }, + { + indice_base_100: 91.5831983044842, + week: 17, + }, + { + indice_base_100: 99.18957433830974, + week: 18, + }, + { + indice_base_100: 97.6604705975341, + week: 19, + }, + { + indice_base_100: 103.30992638734845, + week: 20, + }, + { + indice_base_100: 87.76995185633749, + week: 21, + }, + { + indice_base_100: 96.55972265133698, + week: 22, + }, + { + indice_base_100: 107.00242765091275, + week: 23, + }, + { + indice_base_100: 89.17776183879855, + week: 24, + }, + { + indice_base_100: 100.1588700649956, + week: 25, + }, + { + indice_base_100: 99.29800359340916, + week: 26, + }, + { + indice_base_100: 90.61518445547273, + week: 27, + }, + { + indice_base_100: 81.3921824434114, + week: 28, + }, + { + indice_base_100: 92.28287025240155, + week: 29, + }, + { + indice_base_100: 82.07494844886622, + week: 30, + }, + { + indice_base_100: 72.47820678053719, + week: 31, + }, + { + indice_base_100: 65.14895598483295, + week: 32, + }, + { + indice_base_100: 77.8691578078028, + week: 33, + }, + { + indice_base_100: 90.66478586787552, + week: 34, + }, + { + indice_base_100: 94.38458896494704, + week: 35, + }, + { + indice_base_100: 95.65670240546986, + week: 36, + }, + { + indice_base_100: 105.04448439310077, + week: 37, + }, + { + indice_base_100: 112.95326993967758, + week: 38, + }, + { + indice_base_100: 110.97277041432696, + week: 39, + }, + { + indice_base_100: 103.89154766145145, + week: 40, + }, + { + indice_base_100: 110.31330641619171, + week: 41, + }, + { + indice_base_100: 111.74532354549629, + week: 42, + }, + { + indice_base_100: 109.70132585961679, + week: 43, + }, + { + indice_base_100: 143.80901446261788, + week: 44, + }, + { + indice_base_100: 111.26160181991254, + week: 45, + }, + { + indice_base_100: 123.08603056126137, + week: 46, + }, + { + indice_base_100: 113.90072767229287, + week: 47, + }, + { + indice_base_100: 111.93782470112568, + week: 48, + }, + { + indice_base_100: 107.31780216959872, + week: 49, + }, + { + indice_base_100: 101.42056912077287, + week: 50, + }, + { + indice_base_100: 88.11189911499892, + week: 51, + }, + { + indice_base_100: 104.73662439619646, + week: 52, + }, + ], + }, + trip_purpose: [ + { + percentage: 0.0737514037064592, + trip_purpose_group: "ACCOMPAGNEMENT", + }, + { + percentage: 0.09068801239568441, + trip_purpose_group: "ACHAT_GRAND", + }, + { + percentage: 0.06687896029516564, + trip_purpose_group: "ACHAT_PETIT", + }, + { + percentage: 0, + trip_purpose_group: "COLLEGE", + }, + { + percentage: 0.03595641831344528, + trip_purpose_group: "DEMARCHE", + }, + { + percentage: 0.16815577087501374, + trip_purpose_group: "DOMICILE", + }, + { + percentage: 0.020092651792561075, + trip_purpose_group: "FORMATION_SUPERIEUR", + }, + { + percentage: 0, + trip_purpose_group: "LYCEE", + }, + { + percentage: 0.038035776844292865, + trip_purpose_group: "RESTAURATION", + }, + { + percentage: 0.049188070972545454, + trip_purpose_group: "SOIN", + }, + { + percentage: 0.04889032686343849, + trip_purpose_group: "SPORT_CULTURE_LOISIR_RELIGION", + }, + { + percentage: 0.016115409482767986, + trip_purpose_group: "TOURISME_AUTRE", + }, + { + percentage: 0.006286784849383614, + trip_purpose_group: "TOURISME_EXCEPTIONNEL", + }, + { + percentage: 0.007869905086336093, + trip_purpose_group: "TOURISME_HEBERGEMENT", + }, + { + percentage: 0.3575524849390893, + trip_purpose_group: "TRAVAIL", + }, + { + percentage: 0.020538023583816952, + trip_purpose_group: "VISITE", + }, + ], + }, + }, + { + id: "7bac5d77-4016-42a0-8328-875547c71f5d", + lat: 48.8764054, + lng: 2.3027652, + address: "236 Rue du Faubourg Saint-Honoré", + ts_created: "2023-09-01T08:35:17.833286Z", + ts_updated: "2023-09-01T08:35:17.833286Z", + error: null, + state: null, + data: { + footfall: { + avg_daily_number: 50039.92317397153, + daytype_hour_distribution: [ + { + day_type: "SATURDAY", + hour: 0, + percentage: 0.006973303463104283, + }, + { + day_type: "SATURDAY", + hour: 1, + percentage: 0.0033327818586582963, + }, + { + day_type: "SATURDAY", + hour: 2, + percentage: 0.005864831291242033, + }, + { + day_type: "SATURDAY", + hour: 3, + percentage: 0, + }, + { + day_type: "SATURDAY", + hour: 4, + percentage: 0.00019839324028980595, + }, + { + day_type: "SATURDAY", + hour: 5, + percentage: 0.0015598351372808799, + }, + { + day_type: "SATURDAY", + hour: 6, + percentage: 0.006425470378479962, + }, + { + day_type: "SATURDAY", + hour: 7, + percentage: 0.002648477379501913, + }, + { + day_type: "SATURDAY", + hour: 8, + percentage: 0.018573437027597374, + }, + { + day_type: "SATURDAY", + hour: 9, + percentage: 0.030000085395931582, + }, + { + day_type: "SATURDAY", + hour: 10, + percentage: 0.0691902263159834, + }, + { + day_type: "SATURDAY", + hour: 11, + percentage: 0.04773574499959904, + }, + { + day_type: "SATURDAY", + hour: 12, + percentage: 0.05612483403744246, + }, + { + day_type: "SATURDAY", + hour: 13, + percentage: 0.10615910262517095, + }, + { + day_type: "SATURDAY", + hour: 14, + percentage: 0.05509225695966259, + }, + { + day_type: "SATURDAY", + hour: 15, + percentage: 0.0718086142287727, + }, + { + day_type: "SATURDAY", + hour: 16, + percentage: 0.07301615230676632, + }, + { + day_type: "SATURDAY", + hour: 17, + percentage: 0.07129803788984171, + }, + { + day_type: "SATURDAY", + hour: 18, + percentage: 0.05205365791987274, + }, + { + day_type: "SATURDAY", + hour: 19, + percentage: 0.05505912475529792, + }, + { + day_type: "SATURDAY", + hour: 20, + percentage: 0.037291005876552756, + }, + { + day_type: "SATURDAY", + hour: 21, + percentage: 0.018361348497472535, + }, + { + day_type: "SATURDAY", + hour: 22, + percentage: 0.011899747949488886, + }, + { + day_type: "SATURDAY", + hour: 23, + percentage: 0.009915541095251288, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 0, + percentage: 0.0016144004059411312, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 1, + percentage: 0.0005697525684024935, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 2, + percentage: 0.0006571122390810425, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 3, + percentage: 0, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 4, + percentage: 2.1054673605622763e-5, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 5, + percentage: 0.00027105406052476864, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 6, + percentage: 0.0011615460704465451, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 7, + percentage: 0.00376288270220158, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 8, + percentage: 0.018385158942663758, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 9, + percentage: 0.027917941246039454, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 10, + percentage: 0.04577147774527055, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 11, + percentage: 0.10709217792755978, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 12, + percentage: 0.05413888099857277, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 13, + percentage: 0.05912294790661425, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 14, + percentage: 0.03055861273321946, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 15, + percentage: 0.07345304181486333, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 16, + percentage: 0.0992030512564054, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 17, + percentage: 0.054451953778994325, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 18, + percentage: 0.028245334471392106, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 19, + percentage: 0.02146546552250561, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 20, + percentage: 0.01772127244621056, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 21, + percentage: 0.007641846080805942, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 22, + percentage: 0.0038716772415063228, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 23, + percentage: 0.002810011373309249, + }, + { + day_type: "WORKING_DAY", + hour: 0, + percentage: 0.003795602808138099, + }, + { + day_type: "WORKING_DAY", + hour: 1, + percentage: 0.0012501010131612637, + }, + { + day_type: "WORKING_DAY", + hour: 2, + percentage: 0.0007875003197658717, + }, + { + day_type: "WORKING_DAY", + hour: 3, + percentage: 0.00043983148772072374, + }, + { + day_type: "WORKING_DAY", + hour: 4, + percentage: 0.0018708501958342142, + }, + { + day_type: "WORKING_DAY", + hour: 5, + percentage: 0.0030478109129679883, + }, + { + day_type: "WORKING_DAY", + hour: 6, + percentage: 0.013498834024890015, + }, + { + day_type: "WORKING_DAY", + hour: 7, + percentage: 0.03509253714694336, + }, + { + day_type: "WORKING_DAY", + hour: 8, + percentage: 0.08816389024805311, + }, + { + day_type: "WORKING_DAY", + hour: 9, + percentage: 0.08432800599486026, + }, + { + day_type: "WORKING_DAY", + hour: 10, + percentage: 0.06523230082944143, + }, + { + day_type: "WORKING_DAY", + hour: 11, + percentage: 0.0746643198039038, + }, + { + day_type: "WORKING_DAY", + hour: 12, + percentage: 0.08340120298782826, + }, + { + day_type: "WORKING_DAY", + hour: 13, + percentage: 0.05250668593060444, + }, + { + day_type: "WORKING_DAY", + hour: 14, + percentage: 0.05461695355349352, + }, + { + day_type: "WORKING_DAY", + hour: 15, + percentage: 0.05552072439170519, + }, + { + day_type: "WORKING_DAY", + hour: 16, + percentage: 0.08581355911539687, + }, + { + day_type: "WORKING_DAY", + hour: 17, + percentage: 0.08133995945895146, + }, + { + day_type: "WORKING_DAY", + hour: 18, + percentage: 0.09239905447492745, + }, + { + day_type: "WORKING_DAY", + hour: 19, + percentage: 0.06393868166874156, + }, + { + day_type: "WORKING_DAY", + hour: 20, + percentage: 0.02979329095910868, + }, + { + day_type: "WORKING_DAY", + hour: 21, + percentage: 0.008358977463025077, + }, + { + day_type: "WORKING_DAY", + hour: 22, + percentage: 0.013051755457953267, + }, + { + day_type: "WORKING_DAY", + hour: 23, + percentage: 0.007087569752583225, + }, + ], + week_distribution: [ + { + indice_base_100: 96.41917967065841, + week: 1, + }, + { + indice_base_100: 96.61225291264441, + week: 2, + }, + { + indice_base_100: 96.87290177629306, + week: 3, + }, + { + indice_base_100: 97.17216529123505, + week: 4, + }, + { + indice_base_100: 97.5148702834518, + week: 5, + }, + { + indice_base_100: 97.88894966626889, + week: 6, + }, + { + indice_base_100: 98.28233636749239, + week: 7, + }, + { + indice_base_100: 97.38418120910481, + week: 8, + }, + { + indice_base_100: 97.80894232988963, + week: 9, + }, + { + indice_base_100: 99.53489896224846, + week: 10, + }, + { + indice_base_100: 99.95724666280232, + week: 11, + }, + { + indice_base_100: 100.38683460956861, + week: 12, + }, + { + indice_base_100: 100.81159571587293, + week: 13, + }, + { + indice_base_100: 101.57055058993348, + week: 14, + }, + { + indice_base_100: 101.98324462404386, + week: 15, + }, + { + indice_base_100: 102.39835207838523, + week: 16, + }, + { + indice_base_100: 101.48812983332324, + week: 17, + }, + { + indice_base_100: 101.85979579590936, + week: 18, + }, + { + indice_base_100: 103.51817680660554, + week: 19, + }, + { + indice_base_100: 103.83433423420342, + week: 20, + }, + { + indice_base_100: 104.111877010508, + week: 21, + }, + { + indice_base_100: 104.32908439688188, + week: 22, + }, + { + indice_base_100: 106.93072570783397, + week: 23, + }, + { + indice_base_100: 107.029675749058, + week: 24, + }, + { + indice_base_100: 107.05380989344586, + week: 25, + }, + { + indice_base_100: 107.00554160467009, + week: 26, + }, + { + indice_base_100: 101.67554528610982, + week: 27, + }, + { + indice_base_100: 98.87525413707233, + week: 28, + }, + { + indice_base_100: 98.63873943229206, + week: 29, + }, + { + indice_base_100: 98.35395640977501, + week: 30, + }, + { + indice_base_100: 98.03055873596466, + week: 31, + }, + { + indice_base_100: 97.67820009178497, + week: 32, + }, + { + indice_base_100: 97.30170728873688, + week: 33, + }, + { + indice_base_100: 96.91073399326388, + week: 34, + }, + { + indice_base_100: 96.51010704582792, + week: 35, + }, + { + indice_base_100: 103.91395647194838, + week: 36, + }, + { + indice_base_100: 103.501262437838, + week: 37, + }, + { + indice_base_100: 103.08132814303464, + week: 38, + }, + { + indice_base_100: 102.6589804714418, + week: 39, + }, + { + indice_base_100: 99.12224394388879, + week: 40, + }, + { + indice_base_100: 98.7095499097784, + week: 41, + }, + { + indice_base_100: 98.29444245543702, + week: 42, + }, + { + indice_base_100: 96.58779314148458, + week: 43, + }, + { + indice_base_100: 96.19923323728158, + week: 44, + }, + { + indice_base_100: 97.1384164961544, + week: 45, + }, + { + indice_base_100: 96.80295173566964, + week: 46, + }, + { + indice_base_100: 96.50368823520814, + week: 47, + }, + { + indice_base_100: 99.4722050787586, + week: 48, + }, + { + indice_base_100: 99.28395867723455, + week: 49, + }, + { + indice_base_100: 99.16087449162269, + week: 50, + }, + { + indice_base_100: 97.81141064783144, + week: 51, + }, + { + indice_base_100: 97.84761189337424, + week: 52, + }, + ], + }, + mode: { + soft_mode: 0.8746786668863812, + vehicle: 0.1253213331136188, + }, + origin_top_10: [ + { + commune: "AUTRES", + percentage: 0.42309150931015976, + }, + { + commune: "75108", + percentage: 0.22302296777868422, + }, + { + commune: "75117", + percentage: 0.09012271625140715, + }, + { + commune: "75115", + percentage: 0.05739619178700684, + }, + { + commune: "75116", + percentage: 0.0569390133196766, + }, + { + commune: "75118", + percentage: 0.055704935027732244, + }, + { + commune: "92044", + percentage: 0.026462529259257166, + }, + { + commune: "75119", + percentage: 0.023611353733168087, + }, + { + commune: "75109", + percentage: 0.022027621713256958, + }, + { + commune: "75114", + percentage: 0.021621161819651423, + }, + ], + section: { + avg_speed: 28.907932552531328, + commune: "75108", + department: "75", + geometry: + '{ "type": "LineString", "coordinates": [ [2.30171, 48.87656], [2.30179, 48.87652], [2.30195, 48.87645], [2.30234, 48.87627], [2.30276, 48.87609], [2.30314, 48.87592] ] } ', + iris: "751083002", + length: 126, + max_speed: 50, + name: "Rue du Faubourg Saint-Honoré", + nbr_direction: 2, + region: "11", + }, + socio_demography: [ + { + age: "15-24", + gender: "FEMALE", + percentage: 0, + social_group: "1", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.00031699134763577507, + social_group: "2", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.006169900932673497, + social_group: "3", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.014998905683255037, + social_group: "4", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.012993200941230286, + social_group: "5", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.001048385495744496, + social_group: "6", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0, + social_group: "7", + }, + { + age: "15-24", + gender: "FEMALE", + percentage: 0.021748243269345467, + social_group: "8", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 3.3297082882573556e-5, + social_group: "1", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.0024307194560913626, + social_group: "2", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.14789640687868771, + social_group: "3", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.01993389886135244, + social_group: "4", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.01159416910703135, + social_group: "5", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.0035947577435316283, + social_group: "6", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0, + social_group: "7", + }, + { + age: "25-34", + gender: "FEMALE", + percentage: 0.002234537714301284, + social_group: "8", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0, + social_group: "1", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.005503221793795365, + social_group: "2", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.05994693601382686, + social_group: "3", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.030048905528865636, + social_group: "4", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.02694540927336316, + social_group: "5", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.004166684745302889, + social_group: "6", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.00011775968416668755, + social_group: "7", + }, + { + age: "35-49", + gender: "FEMALE", + percentage: 0.0130404319486006, + social_group: "8", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 5.609174563033863e-5, + social_group: "1", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.007783312167244532, + social_group: "2", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.044190200158748145, + social_group: "3", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.01751335278091823, + social_group: "4", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.02557382752868932, + social_group: "5", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.0016793915145618087, + social_group: "6", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.0022325431410265824, + social_group: "7", + }, + { + age: "50-64", + gender: "FEMALE", + percentage: 0.00457565242784656, + social_group: "8", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 4.9492918756134175e-6, + social_group: "1", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0005220011689092366, + social_group: "2", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0020635266328257592, + social_group: "3", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0010668258803242878, + social_group: "4", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0010395760581435585, + social_group: "5", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0005439788571974969, + social_group: "6", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.017760028727621117, + social_group: "7", + }, + { + age: "65-PLUS", + gender: "FEMALE", + percentage: 0.0035663740840931146, + social_group: "8", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0, + social_group: "1", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.0007519830613824618, + social_group: "2", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.012948454675912496, + social_group: "3", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.005997102883743715, + social_group: "4", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.007400161041760163, + social_group: "5", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.0021477210043395105, + social_group: "6", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0, + social_group: "7", + }, + { + age: "15-24", + gender: "MALE", + percentage: 0.019224577290053932, + social_group: "8", + }, + { + age: "25-34", + gender: "MALE", + percentage: 4.1958237650424995e-5, + social_group: "1", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.006714474990719264, + social_group: "2", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.06648713882184758, + social_group: "3", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.027463641054920284, + social_group: "4", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.024675806760652536, + social_group: "5", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.008294065006772709, + social_group: "6", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0, + social_group: "7", + }, + { + age: "25-34", + gender: "MALE", + percentage: 0.002752550960896538, + social_group: "8", + }, + { + age: "35-49", + gender: "MALE", + percentage: 4.569362695718527e-5, + social_group: "1", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.01118475674947165, + social_group: "2", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.09569729443640591, + social_group: "3", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.025126297379460816, + social_group: "4", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.03290746303071546, + social_group: "5", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.0118651452011708, + social_group: "6", + }, + { + age: "35-49", + gender: "MALE", + percentage: 7.677808715263169e-5, + social_group: "7", + }, + { + age: "35-49", + gender: "MALE", + percentage: 0.0008193065089095403, + social_group: "8", + }, + { + age: "50-64", + gender: "MALE", + percentage: 6.356290520523046e-5, + social_group: "1", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.007012507517762957, + social_group: "2", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.051064324955809544, + social_group: "3", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.010589917217450978, + social_group: "4", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.009738143365124607, + social_group: "5", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.00798887106284442, + social_group: "6", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.001619566927996948, + social_group: "7", + }, + { + age: "50-64", + gender: "MALE", + percentage: 0.006407667269763604, + social_group: "8", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0, + social_group: "1", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.004115128358762968, + social_group: "2", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.00452730895024775, + social_group: "3", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.001436328915648787, + social_group: "4", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0004781934656453142, + social_group: "5", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0008781939877326359, + social_group: "6", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.016287462121547233, + social_group: "7", + }, + { + age: "65-PLUS", + gender: "MALE", + percentage: 0.0002360565002214925, + social_group: "8", + }, + ], + traffic: { + avg_daily_flow: 5515, + daytype_hour_distribution: [ + { + day_type: "SATURDAY", + hour: 0, + percentage: 0.007446775951494883, + }, + { + day_type: "SATURDAY", + hour: 1, + percentage: 0.004675553029622485, + }, + { + day_type: "SATURDAY", + hour: 2, + percentage: 0.0032142509881956096, + }, + { + day_type: "SATURDAY", + hour: 3, + percentage: 0.002775259355895538, + }, + { + day_type: "SATURDAY", + hour: 4, + percentage: 0.00521026721410662, + }, + { + day_type: "SATURDAY", + hour: 5, + percentage: 0.009778720548322989, + }, + { + day_type: "SATURDAY", + hour: 6, + percentage: 0.012854318495076029, + }, + { + day_type: "SATURDAY", + hour: 7, + percentage: 0.029140303624479405, + }, + { + day_type: "SATURDAY", + hour: 8, + percentage: 0.05194055368893026, + }, + { + day_type: "SATURDAY", + hour: 9, + percentage: 0.0699984123515333, + }, + { + day_type: "SATURDAY", + hour: 10, + percentage: 0.07048935604979267, + }, + { + day_type: "SATURDAY", + hour: 11, + percentage: 0.06497170794473413, + }, + { + day_type: "SATURDAY", + hour: 12, + percentage: 0.05884679643200482, + }, + { + day_type: "SATURDAY", + hour: 13, + percentage: 0.05675606094125499, + }, + { + day_type: "SATURDAY", + hour: 14, + percentage: 0.06237486662051666, + }, + { + day_type: "SATURDAY", + hour: 15, + percentage: 0.0501878265376101, + }, + { + day_type: "SATURDAY", + hour: 16, + percentage: 0.053194300254852625, + }, + { + day_type: "SATURDAY", + hour: 17, + percentage: 0.05586204974612174, + }, + { + day_type: "SATURDAY", + hour: 18, + percentage: 0.054569390440313406, + }, + { + day_type: "SATURDAY", + hour: 19, + percentage: 0.04430493240357506, + }, + { + day_type: "SATURDAY", + hour: 20, + percentage: 0.037258025345000084, + }, + { + day_type: "SATURDAY", + hour: 21, + percentage: 0.025031868991651492, + }, + { + day_type: "SATURDAY", + hour: 22, + percentage: 0.017654979605927174, + }, + { + day_type: "SATURDAY", + hour: 23, + percentage: 0.01328086445124812, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 0, + percentage: 0.009986865539776462, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 1, + percentage: 0.006480831737692823, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 2, + percentage: 0.003771659670497158, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 3, + percentage: 0.0023673217639864847, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 4, + percentage: 0.0036556984603722045, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 5, + percentage: 0.007676753156362383, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 6, + percentage: 0.00944561525503771, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 7, + percentage: 0.014294900545309044, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 8, + percentage: 0.02694559646745666, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 9, + percentage: 0.0438202610714391, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 10, + percentage: 0.05603180533877073, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 11, + percentage: 0.06213884486822559, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 12, + percentage: 0.06005381758848549, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 13, + percentage: 0.056668055750833536, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 14, + percentage: 0.06549528905125342, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 15, + percentage: 0.06765723125779811, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 16, + percentage: 0.0799665732910172, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 17, + percentage: 0.08753691272031106, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 18, + percentage: 0.09377117947094675, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 19, + percentage: 0.08017902150758988, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 20, + percentage: 0.06553476183782903, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 21, + percentage: 0.05547471304467792, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 22, + percentage: 0.03785258350474419, + }, + { + day_type: "SUNDAY_&_PUBLIC_HOLIDAY", + hour: 23, + percentage: 0.019210689564251808, + }, + { + day_type: "WORKING_DAY", + hour: 0, + percentage: 0.006351581250785439, + }, + { + day_type: "WORKING_DAY", + hour: 1, + percentage: 0.002465559898784744, + }, + { + day_type: "WORKING_DAY", + hour: 2, + percentage: 0.0018087992701054801, + }, + { + day_type: "WORKING_DAY", + hour: 3, + percentage: 0.0021602619098388407, + }, + { + day_type: "WORKING_DAY", + hour: 4, + percentage: 0.0065518370097038614, + }, + { + day_type: "WORKING_DAY", + hour: 5, + percentage: 0.023020160875000428, + }, + { + day_type: "WORKING_DAY", + hour: 6, + percentage: 0.05519105536276142, + }, + { + day_type: "WORKING_DAY", + hour: 7, + percentage: 0.09398480943157017, + }, + { + day_type: "WORKING_DAY", + hour: 8, + percentage: 0.09815470392384296, + }, + { + day_type: "WORKING_DAY", + hour: 9, + percentage: 0.07406806929359531, + }, + { + day_type: "WORKING_DAY", + hour: 10, + percentage: 0.06528982256363337, + }, + { + day_type: "WORKING_DAY", + hour: 11, + percentage: 0.06015485739484406, + }, + { + day_type: "WORKING_DAY", + hour: 12, + percentage: 0.0551823821013851, + }, + { + day_type: "WORKING_DAY", + hour: 13, + percentage: 0.051350904732580714, + }, + { + day_type: "WORKING_DAY", + hour: 14, + percentage: 0.056023753847739687, + }, + { + day_type: "WORKING_DAY", + hour: 15, + percentage: 0.048930624895072314, + }, + { + day_type: "WORKING_DAY", + hour: 16, + percentage: 0.05491405271738931, + }, + { + day_type: "WORKING_DAY", + hour: 17, + percentage: 0.06274495000415033, + }, + { + day_type: "WORKING_DAY", + hour: 18, + percentage: 0.06278916910614217, + }, + { + day_type: "WORKING_DAY", + hour: 19, + percentage: 0.05059355998547924, + }, + { + day_type: "WORKING_DAY", + hour: 20, + percentage: 0.038656257683140065, + }, + { + day_type: "WORKING_DAY", + hour: 21, + percentage: 0.024552747172339195, + }, + { + day_type: "WORKING_DAY", + hour: 22, + percentage: 0.020796844217658785, + }, + { + day_type: "WORKING_DAY", + hour: 23, + percentage: 0.008696350657072133, + }, + ], + week_distribution: [ + { + indice_base_100: 94.57284734835793, + week: 1, + }, + { + indice_base_100: 96.73234721613305, + week: 2, + }, + { + indice_base_100: 88.28542195785047, + week: 3, + }, + { + indice_base_100: 90.40462466985775, + week: 4, + }, + { + indice_base_100: 91.57493214058783, + week: 5, + }, + { + indice_base_100: 96.95766819576606, + week: 6, + }, + { + indice_base_100: 108.54960785002913, + week: 7, + }, + { + indice_base_100: 99.32861255034979, + week: 8, + }, + { + indice_base_100: 99.4988779921889, + week: 9, + }, + { + indice_base_100: 125.79303470407265, + week: 10, + }, + { + indice_base_100: 101.90162966319427, + week: 11, + }, + { + indice_base_100: 101.7283074084746, + week: 12, + }, + { + indice_base_100: 100.94091976740805, + week: 13, + }, + { + indice_base_100: 103.56717392487924, + week: 14, + }, + { + indice_base_100: 101.58324133504534, + week: 15, + }, + { + indice_base_100: 114.09914033208246, + week: 16, + }, + { + indice_base_100: 91.5831983044842, + week: 17, + }, + { + indice_base_100: 99.18957433830974, + week: 18, + }, + { + indice_base_100: 97.6604705975341, + week: 19, + }, + { + indice_base_100: 103.30992638734845, + week: 20, + }, + { + indice_base_100: 87.76995185633749, + week: 21, + }, + { + indice_base_100: 96.55972265133698, + week: 22, + }, + { + indice_base_100: 107.00242765091275, + week: 23, + }, + { + indice_base_100: 89.17776183879855, + week: 24, + }, + { + indice_base_100: 100.1588700649956, + week: 25, + }, + { + indice_base_100: 99.29800359340916, + week: 26, + }, + { + indice_base_100: 90.61518445547273, + week: 27, + }, + { + indice_base_100: 81.3921824434114, + week: 28, + }, + { + indice_base_100: 92.28287025240155, + week: 29, + }, + { + indice_base_100: 82.07494844886622, + week: 30, + }, + { + indice_base_100: 72.47820678053719, + week: 31, + }, + { + indice_base_100: 65.14895598483295, + week: 32, + }, + { + indice_base_100: 77.8691578078028, + week: 33, + }, + { + indice_base_100: 90.66478586787552, + week: 34, + }, + { + indice_base_100: 94.38458896494704, + week: 35, + }, + { + indice_base_100: 95.65670240546986, + week: 36, + }, + { + indice_base_100: 105.04448439310077, + week: 37, + }, + { + indice_base_100: 112.95326993967758, + week: 38, + }, + { + indice_base_100: 110.97277041432696, + week: 39, + }, + { + indice_base_100: 103.89154766145145, + week: 40, + }, + { + indice_base_100: 110.31330641619171, + week: 41, + }, + { + indice_base_100: 111.74532354549629, + week: 42, + }, + { + indice_base_100: 109.70132585961679, + week: 43, + }, + { + indice_base_100: 143.80901446261788, + week: 44, + }, + { + indice_base_100: 111.26160181991254, + week: 45, + }, + { + indice_base_100: 123.08603056126137, + week: 46, + }, + { + indice_base_100: 113.90072767229287, + week: 47, + }, + { + indice_base_100: 111.93782470112568, + week: 48, + }, + { + indice_base_100: 107.31780216959872, + week: 49, + }, + { + indice_base_100: 101.42056912077287, + week: 50, + }, + { + indice_base_100: 88.11189911499892, + week: 51, + }, + { + indice_base_100: 104.73662439619646, + week: 52, + }, + ], + }, + trip_purpose: [ + { + percentage: 0.0737514037064592, + trip_purpose_group: "ACCOMPAGNEMENT", + }, + { + percentage: 0.09068801239568441, + trip_purpose_group: "ACHAT_GRAND", + }, + { + percentage: 0.06687896029516564, + trip_purpose_group: "ACHAT_PETIT", + }, + { + percentage: 0, + trip_purpose_group: "COLLEGE", + }, + { + percentage: 0.03595641831344528, + trip_purpose_group: "DEMARCHE", + }, + { + percentage: 0.16815577087501374, + trip_purpose_group: "DOMICILE", + }, + { + percentage: 0.020092651792561075, + trip_purpose_group: "FORMATION_SUPERIEUR", + }, + { + percentage: 0, + trip_purpose_group: "LYCEE", + }, + { + percentage: 0.038035776844292865, + trip_purpose_group: "RESTAURATION", + }, + { + percentage: 0.049188070972545454, + trip_purpose_group: "SOIN", + }, + { + percentage: 0.04889032686343849, + trip_purpose_group: "SPORT_CULTURE_LOISIR_RELIGION", + }, + { + percentage: 0.016115409482767986, + trip_purpose_group: "TOURISME_AUTRE", + }, + { + percentage: 0.006286784849383614, + trip_purpose_group: "TOURISME_EXCEPTIONNEL", + }, + { + percentage: 0.007869905086336093, + trip_purpose_group: "TOURISME_HEBERGEMENT", + }, + { + percentage: 0.3575524849390893, + trip_purpose_group: "TRAVAIL", + }, + { + percentage: 0.020538023583816952, + trip_purpose_group: "VISITE", + }, + ], + }, + }, + ], +}; diff --git a/src/declarations.d.ts b/src/declarations.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..66b245666b60a501157d793a5d5d06311ec2a90a --- /dev/null +++ b/src/declarations.d.ts @@ -0,0 +1,4 @@ +declare module "*.png" { + const value: string; + export default value; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5f00164c996208a3771c9810c6772e213b5aa600 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import store from "./redux/store/store"; +import { Provider } from "react-redux"; +import "./styles/global/index.css"; +import "./assets/fonts/fonts.css"; +// import * as dotenv from "dotenv"; + +// dotenv.config(); + +const root = ReactDOM.createRoot( + document.getElementById("root") as HTMLElement +); +root.render( + + + +); diff --git a/src/redux/actions/poiActions.ts b/src/redux/actions/poiActions.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2b545d9d16e1b1d575af6b5c2bab7f9ff62ae2f --- /dev/null +++ b/src/redux/actions/poiActions.ts @@ -0,0 +1,6 @@ +import { createAction } from "@reduxjs/toolkit"; +import { Poi } from "../types/Poi"; + +export const fetchPoiRequest = createAction("poi/fetchPoiRequest"); +export const fetchPoiSuccess = createAction("poi/fetchPoiSuccess"); +export const fetchPoiFailure = createAction("poi/fetchPoiFailure"); diff --git a/src/redux/reducers/poiReducer.ts b/src/redux/reducers/poiReducer.ts new file mode 100644 index 0000000000000000000000000000000000000000..1a38ee00007fc4227bc93c984e8ae0c1fe938897 --- /dev/null +++ b/src/redux/reducers/poiReducer.ts @@ -0,0 +1,37 @@ +import { createReducer } from "@reduxjs/toolkit"; +import { Poi } from "../types/Poi"; +import { + fetchPoiRequest, + fetchPoiSuccess, + fetchPoiFailure, +} from "../actions/poiActions"; + +interface PoiState { + data: Poi[] | null; + loading: boolean; + error: string | null; +} + +const initialState: PoiState = { + data: null, + loading: false, + error: null, +}; + +const poiReducer = createReducer(initialState, (builder) => { + builder + .addCase(fetchPoiRequest, (state) => { + state.loading = true; + state.error = null; + }) + .addCase(fetchPoiSuccess, (state, action) => { + state.loading = false; + state.data = action.payload; + }) + .addCase(fetchPoiFailure, (state, action) => { + state.loading = false; + state.error = action.payload; + }); +}); + +export default poiReducer; diff --git a/src/redux/sagas/poiSaga.ts b/src/redux/sagas/poiSaga.ts new file mode 100644 index 0000000000000000000000000000000000000000..b107b1d809c42a557cfe2b3bad421524e7ba0982 --- /dev/null +++ b/src/redux/sagas/poiSaga.ts @@ -0,0 +1,31 @@ +import { put, takeLatest, call } from "redux-saga/effects"; +import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from "axios"; +import { + fetchPoiRequest, + fetchPoiSuccess, + fetchPoiFailure, +} from "../actions/poiActions"; +import { Poi } from "../types/Poi"; + +function* fetchPoiData() { + try { + const config: AxiosRequestConfig = { + headers: { + key: "", // no more credits + }, + }; + + const response: AxiosResponse = yield call(() => + axios.get("https://api.seiki.co/v1/pois", config) + ); + const data = response.data as Poi[]; + yield put(fetchPoiSuccess(data)); + } catch (error) { + const errorMessage = (error as AxiosError).message || "An error occurred."; + yield put(fetchPoiFailure(errorMessage)); + } +} + +export function* watchFetchPoi() { + yield takeLatest(fetchPoiRequest.type, fetchPoiData); +} diff --git a/src/redux/store/store.ts b/src/redux/store/store.ts new file mode 100644 index 0000000000000000000000000000000000000000..3db4d9a76be22beb703db9a9520f339df27897e3 --- /dev/null +++ b/src/redux/store/store.ts @@ -0,0 +1,19 @@ +import { configureStore } from "@reduxjs/toolkit"; +import createSagaMiddleware from "redux-saga"; +import poiReducer from "../reducers/poiReducer"; +import { watchFetchPoi } from "../sagas/poiSaga"; + +const sagaMiddleware = createSagaMiddleware(); + +const store = configureStore({ + reducer: { + poi: poiReducer, + }, + middleware: [sagaMiddleware], +}); + +sagaMiddleware.run(watchFetchPoi); + +export type RootState = ReturnType; + +export default store; diff --git a/src/redux/types/Poi.ts b/src/redux/types/Poi.ts new file mode 100644 index 0000000000000000000000000000000000000000..e8755d86f44bf3e575e6474305222c5c2c6e685b --- /dev/null +++ b/src/redux/types/Poi.ts @@ -0,0 +1,62 @@ +export interface Poi { + id: string; + lat: number; + lng: number; + address: string; + ts_created: string; + ts_updated: string; + error: string | null; + state: string | null; + data: { + footfall: { + avg_daily_number: number; + daytype_hour_distribution: { + day_type: string; + hour: number; + percentage: number; + }[]; + week_distribution: { + indice_base_100: number; + week: number; + }[]; + }; + mode: { + soft_mode: number; + vehicle: number; + }; + origin_top_10: { + commune: string; + percentage: number; + }[]; + section: { + avg_speed: number; + commune: string; + department: string; + geometry: string; + iris: string; + length: number; + max_speed: number; + name: string; + nbr_direction: number; + region: string; + }; + socio_demography: { + age: string; + gender: string; + percentage: number; + social_group: string; + }[]; + traffic: { + avg_daily_flow: number; + daytype_hour_distribution: { + day_type: string; + hour: number; + percentage: number; + }[]; + }; + trip_purpose: { + percentage: number; + trip_purpose_group: string; + }[]; + }; +} diff --git a/src/sections/demographics/index.tsx b/src/sections/demographics/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..840396e7576ee636f4eca9b407c0b8de8ce570ff --- /dev/null +++ b/src/sections/demographics/index.tsx @@ -0,0 +1,95 @@ +import { useState, useEffect } from "react"; +import ParentSize from "@visx/responsive/lib/components/ParentSize"; +import PieChart from "../../components/charts/pieChart/Pie"; +import { Poi } from "../../redux/types/Poi"; +import LegendChart from "../../components/generalInformation/legend/Legend"; +import CloudWord from "../../components/charts/wordCloudChart/CloudWord"; +import { characterizeSocioDemographicData } from "../../algorithm/WordCloud"; + +type DemographicsSectionProps = { + selectedPoi: Poi; +}; + +const DemographicsSection: React.FC = ({ + selectedPoi, +}) => { + return ( +
+
+
Total Socio Demographics
+ + {({ width, height }) => ( + + )} + +
+
+
+
+
+ Masculine Socio Demographics +
+ + {({ width, height }) => ( + item.gender.toUpperCase() === "MALE" + )} + width={width} + height={height} + flag={1} + /> + )} + +
+
+
+ Feminine Socio Demographics +
+ + {({ width, height }) => ( + item.gender.toUpperCase() === "FEMALE" + )} + width={width} + height={height} + flag={2} + /> + )} + +
+
+
+
+ + {({ width, height }) => ( + + )} + +
+
+ + {({ width, height }) => ( + + )} + +
+
+
+
+ ); +}; + +export default DemographicsSection; diff --git a/src/sections/description/index.tsx b/src/sections/description/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..fe07faca23650079d337b090ee1ab0bca0091098 --- /dev/null +++ b/src/sections/description/index.tsx @@ -0,0 +1,39 @@ +import { useState, useEffect } from "react"; +import { Poi } from "../../redux/types/Poi"; +import { convertModeObjectToArray } from "../../utils/convertModeObjectToArray"; +import { FaWalking } from "react-icons/fa"; +import { AiFillCar } from "react-icons/ai"; +import { formatDate } from "../../utils/formatDate"; +import { FaLocationDot } from "react-icons/fa6"; +import { TbWorldLatitude, TbWorldLongitude } from "react-icons/tb"; +import { BiTimeFive } from "react-icons/bi"; + +type DemographicsSectionProps = { + selectedPoi: Poi; +}; +const DescriptionSection: React.FC = ({ + selectedPoi, +}) => { + return ( +
+
+ + {selectedPoi ? selectedPoi?.address : "unknown"} +
+
+ + {selectedPoi ? selectedPoi?.lat : "unknown"} +
+
+ + {selectedPoi ? selectedPoi?.lng : "unknown"} +
+
+ + {selectedPoi ? formatDate(selectedPoi?.ts_updated) : "unknown"} +
+
+ ); +}; + +export default DescriptionSection; diff --git a/src/sections/drawer/index.tsx b/src/sections/drawer/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3c212d2c1c70f7689afd1d227159410a334d0c32 --- /dev/null +++ b/src/sections/drawer/index.tsx @@ -0,0 +1,303 @@ +import { useState, useEffect } from "react"; +import seiki from "../../assets/images/seiki.png"; +import { BsSearch, BsChevronDown } from "react-icons/bs"; +import { FaMapLocationDot, FaLocationDot } from "react-icons/fa6"; +import { AiFillCar, AiFillDatabase } from "react-icons/ai"; +import { RiDashboardFill } from "react-icons/ri"; +import { IoFootstepsSharp, IoStatsChartSharp } from "react-icons/io5"; +import { FaBusAlt, FaInfoCircle, FaMapMarkedAlt } from "react-icons/fa"; +import { Poi } from "../../redux/types/Poi"; +import FootfallSection from "../footfall"; + +type DrawerSectionProps = { + poiList: Poi[]; + setSelectedPoi: React.Dispatch>; + isFootfallSection: boolean; + setFootfallSection: React.Dispatch>; + isModeSection: boolean; + setModeSection: React.Dispatch>; + isDemographicsSection: boolean; + setDemographicsSection: React.Dispatch>; + isInformationSection: boolean; + setInformationSection: React.Dispatch>; + isTraficSection: boolean; + setTraficSection: React.Dispatch>; + isMapView: boolean; + setIsMapView: React.Dispatch>; +}; + +const DrawerSection: React.FC = ({ + poiList, + setSelectedPoi, + isFootfallSection, + setFootfallSection, + isModeSection, + setModeSection, + isDemographicsSection, + setDemographicsSection, + isInformationSection, + setInformationSection, + isTraficSection, + setTraficSection, + isMapView, + setIsMapView, +}) => { + const [open, setOpen] = useState(true); + const [submenuOpen, setSubmenuOpen] = useState(false); + + const Menus = [ + { + title: "Points of interest", + icon: , + submenu: true, + submenuItems: poiList, + }, + { + title: "Footfall", + icon: , + }, + { + title: "Mode", + icon: , + }, + { + title: "Demographics", + icon: , + }, + { + title: "Section info", + icon: , + }, + { + title: "Trafic data", + icon: , + }, + ]; + + return ( +
+
+ setOpen(!open)} + /> +

+ seiki +

+
+ +
+ + +
+ +
    +
  • + + + + + Points of interest + + {open && ( + { + setSubmenuOpen(!submenuOpen); + }} + /> + )} +
  • + {submenuOpen && open && ( +
      + {Menus[0].submenuItems ? ( + Menus[0].submenuItems.map((submenuItem, index) => ( +
    • { + setSelectedPoi(submenuItem); + }} + key={index} + className="text-gray-300 text-sm flex items-center gap-x-4 cursor-pointer p-2 px-5 + hover:bg-light-white rounded-md" + style={{ fontFamily: "airbnb_light" }} + > + {submenuItem.address} +
    • + )) + ) : ( + <> + )} +
    + )} +
  • { + setFootfallSection(!isFootfallSection); + }} + > + + + + + Footfall + +
  • + +
  • { + setModeSection(!isModeSection); + }} + > + + + + + Mode + +
  • + +
  • { + setDemographicsSection(!isDemographicsSection); + }} + > + + + + + Demographics + +
  • + +
  • { + setInformationSection(!isInformationSection); + }} + > + + + + + Section info + +
  • + +
  • { + setTraficSection(!isTraficSection); + }} + > + + + + + Trafic data + +
  • + +
  • { + setIsMapView(!isMapView); + }} + > + + + + + Map View + +
  • +
+
+ ); +}; + +export default DrawerSection; diff --git a/src/sections/footfall/index.tsx b/src/sections/footfall/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..055ec6b78b27c26e7e52cee596158807c99e0194 --- /dev/null +++ b/src/sections/footfall/index.tsx @@ -0,0 +1,60 @@ +import { useState, useEffect } from "react"; +import { Poi } from "../../redux/types/Poi"; +import { formatNumber } from "../../utils/formatNumber"; +import { IoFootstepsSharp } from "react-icons/io5"; +import ParentSize from "@visx/responsive/lib/components/ParentSize"; +import BrushChart from "../../components/charts/brushChart/AreaChart"; +import DayTypeGraph from "../../components/charts/tripeChart/DayTypeGraph"; + +type FootfallSectionProps = { + selectedPoi: Poi; +}; + +const FootfallSection: React.FC = ({ selectedPoi }) => { + return ( +
+
+
+
Average Footfall
+
+ {selectedPoi + ? formatNumber(selectedPoi?.data.footfall.avg_daily_number) + : "17 400"} + +
+
+
+
+ Footfall Week Distribution +
+ + {({ width, height }) => ( + + )} + +
+
+
+
+ Footfall Day Type Hour distribution +
+ + {({ width, height }) => ( + + )} + +
+
+ ); +}; + +export default FootfallSection; diff --git a/src/sections/information/index.tsx b/src/sections/information/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..133a48213e25a026b2b068dbb5ee2d0055e6bf21 --- /dev/null +++ b/src/sections/information/index.tsx @@ -0,0 +1,107 @@ +import { SiZenn } from "react-icons/si"; +import { FaDirections } from "react-icons/fa"; +import { BsSpeedometer2, BsSpeedometer, BsPinMapFill } from "react-icons/bs"; +import { BiSolidCity, BiSolidRename } from "react-icons/bi"; +import { FaMapLocationDot } from "react-icons/fa6"; +import { Poi } from "../../redux/types/Poi"; +import ParentSize from "@visx/responsive/lib/components/ParentSize"; +import SimpleChart from "../../components/charts/singleChart/SimpleChart"; + +type InformationSectionProps = { + selectedPoi: Poi; +}; + +const InformationSection: React.FC = ({ + selectedPoi, +}) => { + const streetSpecs = [ + { + label: "Average speed", + icon: , + value: selectedPoi + ? selectedPoi?.data.section?.avg_speed.toString().slice(0, 4) + : "n/a" + "km/h", + }, + { + label: "Commune", + icon: , + value: selectedPoi ? selectedPoi?.data.section?.commune : "n/a", + }, + { + label: "Department", + icon: , + value: selectedPoi ? selectedPoi?.data.section?.department : "n/a", + }, + { + label: "Length", + icon: , + value: selectedPoi ? selectedPoi?.data.section?.length : "n/a" + "m", + }, + { + label: "Max speed", + icon: , + value: selectedPoi + ? selectedPoi?.data.section?.max_speed + : "n/a" + "km/h", + }, + { + label: "Name", + icon: , + value: ( +

+ {selectedPoi ? selectedPoi?.data.section?.name : "n/a"} +

+ ), + }, + { + label: "Directions", + icon: , + value: selectedPoi ? selectedPoi?.data.section?.nbr_direction : "n/a", + }, + { + label: "Region", + icon: , + value: selectedPoi ? selectedPoi?.data.section?.region : "n/a", + }, + ]; + return ( +
+
+
Section Information
+ {streetSpecs.map((object, index) => ( +
+
+

+ {object.label} + {object.icon} +

+

{object.value}

+
+
+ ))} +
+
+
Top 10 Trafic Origin
+ + {({ width, height }) => ( + + )} + +
+
+ ); +}; + +export default InformationSection; diff --git a/src/sections/map/control-panel.tsx b/src/sections/map/control-panel.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b1a7b674074620b8cb448dce538555756faf1704 --- /dev/null +++ b/src/sections/map/control-panel.tsx @@ -0,0 +1,129 @@ +import React, { useState, useEffect } from "react"; +import { fromJS, Map } from "immutable"; +import MAP_STYLE from "./map-style-basic-v8.json"; + +const defaultMapStyle: Map = fromJS(MAP_STYLE); +const defaultLayers = defaultMapStyle.get("layers"); + +const categories: string[] = [ + "labels", + "roads", + "buildings", + "parks", + "water", + "background", +]; + +// Layer id patterns by category +const layerSelector: { [key: string]: RegExp } = { + background: /background/, + water: /water/, + parks: /park/, + buildings: /building/, + roads: /bridge|road|tunnel/, + labels: /label|place|poi/, +}; + +// Layer color class by type +const colorClass: { [key: string]: string } = { + line: "line-color", + fill: "fill-color", + background: "background-color", + symbol: "text-color", +}; + +function getMapStyle({ visibility, color }: MapStyleOptions): Map { + const layers = defaultLayers + .filter((layer: any) => { + const id = layer.get("id"); + return categories.every( + (name) => visibility[name] || !layerSelector[name].test(id) + ); + }) + .map((layer: any) => { + const id = layer.get("id"); + const type = layer.get("type"); + const category = categories.find((name) => layerSelector[name].test(id)); + if (category && colorClass[type]) { + return layer.setIn(["paint", colorClass[type]], color[category]); + } + return layer; + }); + + return defaultMapStyle.set("layers", layers); +} + +interface MapStyleOptions { + visibility: { [key: string]: boolean }; + color: { [key: string]: string }; +} + +interface StyleControlsProps { + onChange: (style: Map) => void; +} + +function StyleControls(props: StyleControlsProps) { + const [visibility, setVisibility] = useState({ + water: true, + parks: true, + buildings: true, + roads: true, + labels: true, + background: true, + }); + + const [color, setColor] = useState({ + water: "#DBE2E6", + parks: "#E6EAE9", + buildings: "#c0c0c8", + roads: "#ffffff", + labels: "#78888a", + background: "#EBF0F0", + }); + + useEffect(() => { + props.onChange(getMapStyle({ visibility, color })); + }, [visibility, color]); + + const onColorChange = (name: string, value: string) => { + setColor({ ...color, [name]: value }); + }; + + const onVisibilityChange = (name: string, value: boolean) => { + setVisibility({ ...visibility, [name]: value }); + }; + + return ( +
+

Dynamic Styling

+
+ {categories.map((name) => ( +
+ + onVisibilityChange(name, evt.target.checked)} + /> + onColorChange(name, evt.target.value)} + /> +
+ ))} +
+ ); +} + +export default React.memo(StyleControls); diff --git a/src/sections/map/index.tsx b/src/sections/map/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..33ceadb2df25c32d6b45e63058b1376efa93317b --- /dev/null +++ b/src/sections/map/index.tsx @@ -0,0 +1,64 @@ +import { useState, useEffect } from "react"; +import { Poi } from "../../redux/types/Poi"; +import { convertModeObjectToArray } from "../../utils/convertModeObjectToArray"; +import { FaWalking } from "react-icons/fa"; +import { AiFillCar } from "react-icons/ai"; +import { Map, Marker } from "react-map-gl"; +import ControlPanel from "./control-panel"; +import pin from "../../assets/images/pin.png"; + +type DemographicsSectionProps = { + selectedPoi: Poi; +}; +const MapSection: React.FC = ({ selectedPoi }) => { + const [mapStyle, setMapStyle] = useState(null); + + return ( +
+ + + {/* You can customize the pin marker here */} + Custom Marker + + +
+ +
+
+ ); +}; + +export default MapSection; diff --git a/src/sections/map/map-style-basic-v8.json b/src/sections/map/map-style-basic-v8.json new file mode 100644 index 0000000000000000000000000000000000000000..3178e2dd3f4211db058fee45bfceddd578d1e662 --- /dev/null +++ b/src/sections/map/map-style-basic-v8.json @@ -0,0 +1,866 @@ +{ + "version": 8, + "name": "Basic", + "metadata": { + "mapbox:autocomposite": true + }, + "sources": { + "mapbox": { + "url": "mapbox://mapbox.mapbox-streets-v7", + "type": "vector" + } + }, + "sprite": "mapbox://sprites/mapbox/basic-v8", + "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "#dedede" + }, + "interactive": true + }, + { + "id": "landuse_overlay_national_park", + "type": "fill", + "source": "mapbox", + "source-layer": "landuse_overlay", + "filter": [ + "==", + "class", + "national_park" + ], + "paint": { + "fill-color": "#d2edae", + "fill-opacity": 0.75 + }, + "interactive": true + }, + { + "id": "landuse_park", + "type": "fill", + "source": "mapbox", + "source-layer": "landuse", + "filter": [ + "==", + "class", + "park" + ], + "paint": { + "fill-color": "#d2edae" + }, + "interactive": true + }, + { + "id": "waterway", + "type": "line", + "source": "mapbox", + "source-layer": "waterway", + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "in", + "class", + "river", + "canal" + ] + ], + "paint": { + "line-color": "#a0cfdf", + "line-width": { + "base": 1.4, + "stops": [ + [ + 8, + 0.5 + ], + [ + 20, + 15 + ] + ] + } + }, + "interactive": true + }, + { + "id": "water", + "type": "fill", + "source": "mapbox", + "source-layer": "water", + "paint": { + "fill-color": "#a0cfdf" + }, + "interactive": true + }, + { + "id": "building", + "type": "fill", + "source": "mapbox", + "source-layer": "building", + "paint": { + "fill-color": "#d6d6d6" + }, + "interactive": true + }, + { + "interactive": true, + "layout": { + "line-cap": "butt", + "line-join": "miter" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway_link", + "street", + "street_limited", + "service", + "track", + "pedestrian", + "path", + "link" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "tunnel_minor", + "paint": { + "line-color": "#efefef", + "line-width": { + "base": 1.55, + "stops": [ + [ + 4, + 0.25 + ], + [ + 20, + 30 + ] + ] + }, + "line-dasharray": [ + 0.36, + 0.18 + ] + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "butt", + "line-join": "miter" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ], + [ + "==", + "structure", + "tunnel" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "tunnel_major", + "paint": { + "line-color": "#fff", + "line-width": { + "base": 1.4, + "stops": [ + [ + 6, + 0.5 + ], + [ + 20, + 30 + ] + ] + }, + "line-dasharray": [ + 0.28, + 0.14 + ] + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway_link", + "street", + "street_limited", + "service", + "track", + "pedestrian", + "path", + "link" + ], + [ + "in", + "structure", + "none", + "ford" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "road_minor", + "paint": { + "line-color": "#efefef", + "line-width": { + "base": 1.55, + "stops": [ + [ + 4, + 0.25 + ], + [ + 20, + 30 + ] + ] + } + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ], + [ + "in", + "structure", + "none", + "ford" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "road_major", + "paint": { + "line-color": "#fff", + "line-width": { + "base": 1.4, + "stops": [ + [ + 6, + 0.5 + ], + [ + 20, + 30 + ] + ] + } + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "butt", + "line-join": "miter" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway_link", + "street", + "street_limited", + "service", + "track", + "pedestrian", + "path", + "link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "bridge_minor case", + "paint": { + "line-color": "#dedede", + "line-width": { + "base": 1.6, + "stops": [ + [ + 12, + 0.5 + ], + [ + 20, + 10 + ] + ] + }, + "line-gap-width": { + "base": 1.55, + "stops": [ + [ + 4, + 0.25 + ], + [ + 20, + 30 + ] + ] + } + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "butt", + "line-join": "miter" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "bridge_major case", + "paint": { + "line-color": "#dedede", + "line-width": { + "base": 1.6, + "stops": [ + [ + 12, + 0.5 + ], + [ + 20, + 10 + ] + ] + }, + "line-gap-width": { + "base": 1.55, + "stops": [ + [ + 4, + 0.25 + ], + [ + 20, + 30 + ] + ] + } + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway_link", + "street", + "street_limited", + "service", + "track", + "pedestrian", + "path", + "link" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "bridge_minor", + "paint": { + "line-color": "#efefef", + "line-width": { + "base": 1.55, + "stops": [ + [ + 4, + 0.25 + ], + [ + 20, + 30 + ] + ] + } + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ], + [ + "==", + "structure", + "bridge" + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "bridge_major", + "paint": { + "line-color": "#fff", + "line-width": { + "base": 1.4, + "stops": [ + [ + 6, + 0.5 + ], + [ + 20, + 30 + ] + ] + } + }, + "source-layer": "road" + }, + { + "interactive": true, + "layout": { + "line-cap": "round", + "line-join": "round" + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "all", + [ + "<=", + "admin_level", + 2 + ], + [ + "==", + "maritime", + 0 + ] + ] + ], + "type": "line", + "source": "mapbox", + "id": "admin_country", + "paint": { + "line-color": "#8b8a8a", + "line-width": { + "base": 1.3, + "stops": [ + [ + 3, + 0.5 + ], + [ + 22, + 15 + ] + ] + } + }, + "source-layer": "admin" + }, + { + "interactive": true, + "minzoom": 5, + "layout": { + "icon-image": "{maki}-11", + "text-offset": [ + 0, + 0.5 + ], + "text-field": "{name_en}", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 8, + "text-anchor": "top", + "text-size": 11, + "icon-size": 1 + }, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "all", + [ + "==", + "scalerank", + 1 + ], + [ + "==", + "localrank", + 1 + ] + ] + ], + "type": "symbol", + "source": "mapbox", + "id": "poi_label", + "paint": { + "text-color": "#666", + "text-halo-width": 1, + "text-halo-color": "rgba(255,255,255,0.75)", + "text-halo-blur": 1 + }, + "source-layer": "poi_label" + }, + { + "interactive": true, + "layout": { + "symbol-placement": "line", + "text-field": "{name_en}", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-transform": "uppercase", + "text-letter-spacing": 0.1, + "text-size": { + "base": 1.4, + "stops": [ + [ + 10, + 8 + ], + [ + 20, + 14 + ] + ] + } + }, + "filter": [ + "all", + [ + "==", + "$type", + "LineString" + ], + [ + "in", + "class", + "motorway", + "primary", + "secondary", + "tertiary", + "trunk" + ] + ], + "type": "symbol", + "source": "mapbox", + "id": "road_major_label", + "paint": { + "text-color": "#666", + "text-halo-color": "rgba(255,255,255,0.75)", + "text-halo-width": 2 + }, + "source-layer": "road_label" + }, + { + "interactive": true, + "minzoom": 8, + "layout": { + "text-field": "{name_en}", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 6, + "text-size": { + "stops": [ + [ + 6, + 12 + ], + [ + 12, + 16 + ] + ] + } + }, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "in", + "type", + "town", + "village", + "hamlet", + "suburb", + "neighbourhood", + "island" + ] + ], + "type": "symbol", + "source": "mapbox", + "id": "place_label_other", + "paint": { + "text-color": "#666", + "text-halo-color": "rgba(255,255,255,0.75)", + "text-halo-width": 1, + "text-halo-blur": 1 + }, + "source-layer": "place_label" + }, + { + "interactive": true, + "layout": { + "text-field": "{name_en}", + "text-font": [ + "Open Sans Bold", + "Arial Unicode MS Bold" + ], + "text-max-width": 10, + "text-size": { + "stops": [ + [ + 3, + 12 + ], + [ + 8, + 16 + ] + ] + } + }, + "maxzoom": 16, + "filter": [ + "all", + [ + "==", + "$type", + "Point" + ], + [ + "==", + "type", + "city" + ] + ], + "type": "symbol", + "source": "mapbox", + "id": "place_label_city", + "paint": { + "text-color": "#666", + "text-halo-color": "rgba(255,255,255,0.75)", + "text-halo-width": 1, + "text-halo-blur": 1 + }, + "source-layer": "place_label" + }, + { + "interactive": true, + "layout": { + "text-field": "{name_en}", + "text-font": [ + "Open Sans Regular", + "Arial Unicode MS Regular" + ], + "text-max-width": 10, + "text-size": { + "stops": [ + [ + 3, + 14 + ], + [ + 8, + 22 + ] + ] + } + }, + "maxzoom": 12, + "filter": [ + "==", + "$type", + "Point" + ], + "type": "symbol", + "source": "mapbox", + "id": "country_label", + "paint": { + "text-color": "#666", + "text-halo-color": "rgba(255,255,255,0.75)", + "text-halo-width": 1, + "text-halo-blur": 1 + }, + "source-layer": "country_label" + } + ] +} \ No newline at end of file diff --git a/src/sections/mode/index.tsx b/src/sections/mode/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b6b3daf3c494d89ee6b984593f5e5fb8976086d8 --- /dev/null +++ b/src/sections/mode/index.tsx @@ -0,0 +1,37 @@ +import { useState, useEffect } from "react"; +import { Poi } from "../../redux/types/Poi"; +import { convertModeObjectToArray } from "../../utils/convertModeObjectToArray"; +import { FaWalking } from "react-icons/fa"; +import { AiFillCar } from "react-icons/ai"; + +type DemographicsSectionProps = { + selectedPoi: Poi; +}; +const ModeSection: React.FC = ({ selectedPoi }) => { + return ( + //isSelected ? +
+
+
People walking
+
+ {selectedPoi + ? convertModeObjectToArray(selectedPoi?.data.mode)[0] + : "20%"} + +
+
+
+
People using vehicles
+
+ {selectedPoi + ? convertModeObjectToArray(selectedPoi?.data.mode)[1] + : "20%"} + +
+
+
+ //) : ( <> + ); +}; + +export default ModeSection; diff --git a/src/sections/trafic/index.tsx b/src/sections/trafic/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d520bdde71614374c1ccc48f1a040c5e948cfe4c --- /dev/null +++ b/src/sections/trafic/index.tsx @@ -0,0 +1,79 @@ +import { useState, useEffect } from "react"; +import { Poi } from "../../redux/types/Poi"; +import { formatNumber } from "../../utils/formatNumber"; +import { FaBusAlt } from "react-icons/fa"; +import ParentSize from "@visx/responsive/lib/components/ParentSize"; +import DayTypeGraph from "../../components/charts/tripeChart/DayTypeGraph"; +import SimpleChartTripPurpose from "../../components/charts/singleChart/SimpleChartTripPurpose"; +import BrushChart from "../../components/charts/brushChart/AreaChart"; + +type TraficSectionProps = { + selectedPoi: Poi; +}; + +const TraficSection: React.FC = ({ selectedPoi }) => { + return ( + //) isSelected ? + <> +
+
+
+
+ Average Trafic Daily Flow +
+
+ {selectedPoi + ? formatNumber(selectedPoi?.data.traffic.avg_daily_flow) + : "17 400"} + +
+
+
+
+ Trafic Week Distribution +
+ + {({ width, height }) => ( + + )} + +
+
+
+
+ Trafic Day Type Hour distribution +
+ + {({ width, height }) => ( + + )} + +
+
+
+
Trip Purpose
+ + {({ width, height }) => ( + + )} + +
+ + //) : ( <> + ); +}; + +export default TraficSection; diff --git a/src/styles/global/App.css b/src/styles/global/App.css new file mode 100644 index 0000000000000000000000000000000000000000..e22f75ef6390f17a9fb10a18d8dc72b8ac19de99 --- /dev/null +++ b/src/styles/global/App.css @@ -0,0 +1,381 @@ +.rootContent { + display: flex; + height: 100vh; + width: 100vw; + overflow: hidden; +} +.mainContent { + flex: 1; + overflow-y: auto; + width: 100%; + display: flex; + justify-content: flex-start; + align-items: center; + flex-direction: column; +} + +.sectionBasicInfo { + width: 100%; + display: flex; + background-color: white; + flex-direction: row; + justify-content: space-between; + padding: 2%; + border-bottom: 1px solid #d1d1d1; +} + +.sectionTrafic { + width: 100%; + display: flex; + background-color: white; + flex-direction: row; + justify-content: space-between; + padding: 2%; +} + +.sectionBasicInfoOne { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 2%; + padding-left: 10%; + padding-right: 10%; + border-bottom: 1px solid #d1d1d1; /* Add a thin bottom border */ +} + +.basicInfoLabelsOne { + background-color: white; /* Change background color to white */ + font-family: "airbnb_semi_bold"; + color: #3e3e3e; + font-size: 20px; + width: auto; + height: 10vh; + padding: 2%; + display: flex; + justify-content: space-evenly; + align-items: center; + border-radius: 20px; /* Add rounded borders */ + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.footfallLeftWrapper { + display: flex; + flex-direction: column; + justify-content: space-between; + height: 70vh; + width: 49%; +} + +.averageFootfallWrapper { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: auto; + position: sticky; + color: white; + font-family: "airbnb_extra_bold"; + font-size: 60px; +} + +.averageModeWrapper { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: auto; + color: white; + font-family: "airbnb_extra_bold"; + font-size: 60px; +} + +.averageFootfallWrapperText { + font-family: "airbnb_light"; + margin-top: 15px; + margin-left: 10px; + font-size: 20px; +} + +.averageFootfall { + background: linear-gradient(to bottom, #858585, #000000); + width: 100%; + height: 14vh; + display: flex; + flex-direction: column; + border-radius: 20px; /* Add rounded borders */ + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.parentWidthFootfall { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 10vh; + border-bottom-left-radius: 14px; + border-bottom-right-radius: 14px; +} + +.blockInformationBackground { + background: linear-gradient(to bottom, #4b4b4b, #000000); + display: flex; + justify-content: center; + align-items: center; + width: 90%; + height: 6.5vh; + border-radius: 14px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.weekDistribution { + background-color: white; /* Change background color to white */ + width: 100%; + height: 53vh; + display: flex; + flex-direction: column; + border-radius: 20px; /* Add rounded borders */ + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.weekDistributionTitle { + width: 100%; + height: 4vh; + display: flex; + justify-content: center; + align-items: center; + font-family: "airbnb_extra_bold"; + font-size: 17px; + background-color: white; + color: #4b4b4b; + border-top-left-radius: 14px; + border-top-right-radius: 14px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.basicInfoMap { + background-color: white; /* Change background color to white */ + width: 49%; + height: 70vh; + display: flex; + flex-direction: column; + border-radius: 20px; /* Add rounded borders */ + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.modeSection { + width: 100%; + display: flex; + background-color: white; /* Change background color to white */ + flex-direction: row; + justify-content: space-between; + padding: 2%; + border-bottom: 1px solid #d1d1d1; /* Add a thin bottom border */ +} + +.sectionModeDivider { + background: linear-gradient(to bottom, #858585, #000000); + width: 49%; + height: 14vh; + display: flex; + flex-direction: column; + border-radius: 20px; /* Add rounded borders */ + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.sectionModeWrapper { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + position: absolute; + width: auto; + color: white; + font-family: "airbnb_extra_bold"; + left: 70%; + font-size: 60px; +} + +.demographicsSection { + width: 100%; + display: flex; + background-color: white; /* Change background color to white */ + flex-direction: row; + justify-content: space-between; + padding: 2%; + border-bottom: 1px solid #d1d1d1; /* Add a thin bottom border */ +} + +.mainDemoPie { + background-color: white; /* Change background color to white */ + width: 49%; + height: 73vh; + display: flex; + flex-direction: column; +} + +.mainDemoPieTitle { + width: 100%; + height: 7vh; + display: flex; + justify-content: center; + align-items: center; + font-family: "airbnb_extra_bold"; + font-size: 20px; + background-color: white; + color: #4b4b4b; + border-top-left-radius: 14px; + border-top-right-radius: 14px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.otherDemoPieWrapper { + width: 49%; + height: 73vh; + display: flex; + flex-direction: column; + justify-content: space-between; + border-radius: 20px; /* Add rounded borders */ +} + +.wordCloud { + width: 49%; + height: 32vh; + border-radius: 20px; /* Add rounded borders */ + background-color: white; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.menAndWomenPies { + display: flex; + flex-direction: row; + justify-content: space-between; + border-radius: 20px; /* Add rounded borders */ +} + +.LegendChart { + display: flex; + flex-direction: row; + justify-content: space-between; + border-radius: 20px; /* Add rounded borders */ +} + +.menPie { + width: 49%; + height: 33vh; + border-radius: 20px; /* Add rounded borders */ + background-color: white; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.womenPie { + width: 49%; + height: 33vh; + border-radius: 20px; /* Add rounded borders */ + background-color: white; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.blockSection { + width: 100%; + height: 80vh; + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 2%; + border-bottom: 1px solid #d1d1d1; /* Add a thin bottom border */ +} + +.blockInformation { + width: 25%; + height: 68vh; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + border-radius: 20px; /* Add rounded borders */ + background-color: white; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ + padding-bottom: 10px; +} + +.blockSimpleChart { + width: 73%; + height: 63vh; + border-radius: 20px; /* Add rounded borders */ + background-color: pink; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); /* Add shadow */ +} + +.tripPurposeChart { + width: 95%; + height: 63vh; + border-radius: 20px; /* Add rounded borders */ + padding-bottom: 5%; +} + +.blockInformationContent { + padding: 0.8%; + padding-right: 5%; + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; + font-family: "airbnb_semi_bold"; + font-size: 20px; + color: white; +} + +@media (max-width: 1200px) { + .sectionBasicInfoOne { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 2%; + padding-left: 10%; + padding-right: 10%; + border-bottom: 1px solid #d1d1d1; + } + .basicInfoLabelsOne { + background-color: white; + font-family: "airbnb_semi_bold"; + color: #3e3e3e; + font-size: 12px; + width: 20%; + height: 10vh; + padding: 2%; + display: flex; + justify-content: space-evenly; + align-items: center; + border-radius: 20px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); + } +} + +@media (min-width: 1200px) and (max-width: 1800px) { + .sectionBasicInfoOne { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 2%; + padding-left: 10%; + padding-right: 10%; + border-bottom: 1px solid #d1d1d1; + } + .basicInfoLabelsOne { + background-color: white; + font-family: "airbnb_semi_bold"; + color: #3e3e3e; + font-size: 14px; + width: 20%; + height: 10vh; + padding: 2%; + display: flex; + justify-content: space-evenly; + align-items: center; + border-radius: 20px; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); + } +} diff --git a/src/styles/global/customScrollBar.css b/src/styles/global/customScrollBar.css new file mode 100644 index 0000000000000000000000000000000000000000..aa5bf3b4be7511e0c8bf6d6b66400ec4767f0534 --- /dev/null +++ b/src/styles/global/customScrollBar.css @@ -0,0 +1,24 @@ +::-webkit-scrollbar { + width: 6px; /* Width of the scrollbar track */ +} + +/* Define the scrollbar thumb (the draggable part) */ +::-webkit-scrollbar-thumb { + background: #cfcfcf; /* Color of the thumb */ + border-radius: 6px; /* Rounded corners of the thumb */ +} + +/* Define the scrollbar track on hover */ +::-webkit-scrollbar-track:hover { + background: #aaa; /* Color of the track on hover */ +} + +/* Define the scrollbar thumb on hover */ +::-webkit-scrollbar-thumb:hover { + background: #555; /* Color of the thumb on hover */ +} + +/* Define the scrollbar corner (between vertical and horizontal scrollbars) */ +::-webkit-scrollbar-corner { + background: transparent; /* Color of the scrollbar corner */ +} diff --git a/src/styles/global/index.css b/src/styles/global/index.css new file mode 100644 index 0000000000000000000000000000000000000000..c08ca95a9ae5b0fdcda6b058c0b8859f87c2b3c6 --- /dev/null +++ b/src/styles/global/index.css @@ -0,0 +1,20 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, +body { + height: 100%; /* Ensure full viewport height */ + width: 100vw; + overflow: hidden; /* Prevent body scrolling */ + + /* Add your background color or other styles here */ +} + +/* Define a container for your React app */ +#root { + display: flex; + height: 100%; /* Ensure full viewport height */ + width: 100vw; + overflow: hidden; /* Prevent container scrolling */ +} diff --git a/src/styles/sections/demographics/index.css b/src/styles/sections/demographics/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/styles/sections/description/index.css b/src/styles/sections/description/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/styles/sections/drawer/index.css b/src/styles/sections/drawer/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/styles/sections/footfall/index.css b/src/styles/sections/footfall/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/styles/sections/information/index.css b/src/styles/sections/information/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/styles/sections/mode/index.css b/src/styles/sections/mode/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/styles/sections/trafic/index.css b/src/styles/sections/trafic/index.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/utils/convertModeObjectToArray.ts b/src/utils/convertModeObjectToArray.ts new file mode 100644 index 0000000000000000000000000000000000000000..dcb2b0d05484c1c7222192fcfbe2179ec263cde4 --- /dev/null +++ b/src/utils/convertModeObjectToArray.ts @@ -0,0 +1,9 @@ +export function convertModeObjectToArray(mode: { + soft_mode: number; + vehicle: number; +}) { + const softModePercentage = (mode.soft_mode * 100).toFixed(2) + "%"; + const vehiclePercentage = (mode.vehicle * 100).toFixed(2) + "%"; + + return [softModePercentage, vehiclePercentage]; +} diff --git a/src/utils/formatDate.ts b/src/utils/formatDate.ts new file mode 100644 index 0000000000000000000000000000000000000000..51507f5b31e60eb0b56d3556cf9cb5c8360d0b01 --- /dev/null +++ b/src/utils/formatDate.ts @@ -0,0 +1,15 @@ +export function formatDate(inputDate: string): string { + const date = new Date(inputDate); + + const options: Intl.DateTimeFormatOptions = { + year: "numeric", + month: "long", + day: "2-digit", + hour: "numeric", + minute: "numeric", + timeZoneName: "short", + }; + + const formattedDate = date.toLocaleDateString("en-US", options); + return formattedDate; +} diff --git a/src/utils/formatNumber.ts b/src/utils/formatNumber.ts new file mode 100644 index 0000000000000000000000000000000000000000..c42cdc6b1eb49521157471bd4de5f928f59462ee --- /dev/null +++ b/src/utils/formatNumber.ts @@ -0,0 +1,9 @@ +export function replaceCommaWithPeriod(input: string): string { + return input.replace(/,/g, "."); +} + +export function formatNumber(number: number): string { + return replaceCommaWithPeriod( + number.toLocaleString("en-US", { maximumFractionDigits: 0 }) + ); +}