Skip to content

Commit

Permalink
🔧 Merge statistics dashboard.
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasGilg committed Dec 11, 2024
1 parent b461d20 commit d8c01ed
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 51 deletions.
162 changes: 127 additions & 35 deletions frontend/src/components/InspireGridComponents/BaseLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import 'leaflet/dist/leaflet.css';
import {getGridNew, getCellFromPosition} from './inspire';
import {PandemosContext} from '../../data_sockets/PandemosContext';
import {susceptibleStates, infectionStates} from './Constants';
import {useAppSelector} from '../../store/hooks';
import {KeyInfo} from '../../types/pandemos';
import age_group = KeyInfo.age_group;

type MapBounds = [[number, number], [number, number]];
type MapCenter = [number, number];
Expand Down Expand Up @@ -97,6 +100,8 @@ export default function BaseLayer({
setMapCenter,
}: BaseLayerProps): JSX.Element {
const context = useContext(PandemosContext);
const selectedTab = useAppSelector((state) => state.userPreference.selectedSidebarTab ?? '1');
const filter = useAppSelector((state) => state.pandemosFilter);

const gridResolution = useMemo(() => getResolutionFromZoom(mapZoom), [mapZoom]);

Expand Down Expand Up @@ -182,44 +187,131 @@ export default function BaseLayer({

const trips = useMemo(() => {
const trips: {pos: [number, number]; color: string}[] = [];
context.filteredTripChains?.forEach((tripChains) => {
tripChains.forEach((tripChainId) => {
if (context.tripChains) {
const tripChain = context.tripChains.get(tripChainId);
tripChain?.forEach((trip) => {
let color: string;
switch (trip.transport_mode) {
case 0:
color = 'green'; // Bike
break;
case 1:
color = 'brown'; // Car (Driver)
break;
case 2:
color = 'brown'; // Car (Passenger)
break;
case 3:
color = 'blue'; // Bus
break;
case 4:
color = 'white'; // Walking
break;
case 5:
color = 'grey'; // Other
break;
default:
color = 'red'; // Unknown
}
trips.push({
pos: [getLocationPos(trip.start_location), getLocationPos(trip.end_location)],
color: color,

if (selectedTab === '3') {
context.filteredTripChains?.forEach((tripChains) => {
tripChains.forEach((tripChainId) => {
if (context.tripChains) {
const tripChain = context.tripChains.get(tripChainId);
tripChain?.forEach((trip) => {
let color: string;
switch (trip.transport_mode) {
case 0:
color = 'green'; // Bike
break;
case 1:
color = 'brown'; // Car (Driver)
break;
case 2:
color = 'brown'; // Car (Passenger)
break;
case 3:
color = 'blue'; // Bus
break;
case 4:
color = 'white'; // Walking
break;
case 5:
color = 'grey'; // Other
break;
default:
color = 'red'; // Unknown
}
trips.push({
pos: [getLocationPos(trip.start_location), getLocationPos(trip.end_location)],
color: color,
});
});
});
}
});
});
} else if (selectedTab === '2') {
context.trips?.forEach((trip) => {
const duration = trip.end_time - trip.start_time;
const agent = context.agents?.find((agent) => agent.agent_id === trip.agent_id);
const start = context.locations?.find((loc) => loc.location_id === trip.start_location);
const end = context.locations?.find((loc) => loc.location_id === trip.end_location);
if (
agent &&
duration >= (filter.tripDurationMin ?? 0) &&
duration < (filter.tripDurationMax ?? Number.MAX_SAFE_INTEGER)
) {
if (!filter.ageGroups || filter.ageGroups.length === 0 || filter.ageGroups.includes(agent.age_group)) {
if (
!filter.transportationModes ||
filter.transportationModes.length === 0 ||
filter.transportationModes.includes(trip.transport_mode)
) {
if (!filter.activities || filter.activities.length === 0 || filter.activities.includes(trip.activity)) {
if (
!filter.originTypes ||
filter.originTypes.length === 0 ||
filter.originTypes.includes(start?.location_type ?? -1)
) {
if (
!filter.destinationTypes ||
filter.destinationTypes.length === 0 ||
filter.destinationTypes.includes(end?.location_type ?? -1)
) {
if (
!filter.infectionStates ||
filter.infectionStates.length === 0 ||
filter.infectionStates.includes(trip.infection_state)
) {
let color: string;
switch (trip.transport_mode) {
case 0:
color = 'green'; // Bike
break;
case 1:
color = 'brown'; // Car (Driver)
break;
case 2:
color = 'brown'; // Car (Passenger)
break;
case 3:
color = 'blue'; // Bus
break;
case 4:
color = 'white'; // Walking
break;
case 5:
color = 'grey'; // Other
break;
default:
color = 'red'; // Unknown
}
trips.push({
pos: [getLocationPos(trip.start_location), getLocationPos(trip.end_location)],
color: color,
});
}
}
}
}
}
}
}
});
});
}
return trips;
}, [context.filteredTripChains, context.tripChains, getLocationPos]);
}, [
context.agents,
context.filteredTripChains,
context.locations,
context.tripChains,
context.trips,
filter.activities,
filter.ageGroups,
filter.destinationTypes,
filter.infectionStates,
filter.originTypes,
filter.transportationModes,
filter.tripDurationMax,
filter.tripDurationMin,
getLocationPos,
selectedTab,
]);

return (
<MapContainer
Expand Down Expand Up @@ -260,7 +352,7 @@ export default function BaseLayer({
<LayersControl.Overlay checked name='Trips'>
<LayerGroup>
{trips.map((line, index) => (
<Polyline key={index} pathOptions={{weight: 1, color: line.color}} positions={line.pos} />
<Polyline key={index} pathOptions={{weight: 1, color: line.color}} positions={line.pos} zIndex={1000} />
))}
</LayerGroup>
</LayersControl.Overlay>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ export default function StatisticsDashboard(props: any): JSX.Element {
odInfectionChart.controlsUseVisibility(true);

odInfectionChart.on('filtered', function (_chart: any, filter: any) {
const selectedFilters = _chart.filters();
dispatch(
selectDestinationTypes({
destinationTypes: filter,
destinationTypes: selectedFilters,
})
);
});
Expand Down Expand Up @@ -169,9 +170,10 @@ export default function StatisticsDashboard(props: any): JSX.Element {
})

.on('filtered', function (_chart: any, filter: any) {
const selectedFilters = _chart.filters();
dispatch(
selectTransportationModes({
transportationModes: filter,
transportationModes: selectedFilters,
})
);
});
Expand Down Expand Up @@ -206,9 +208,10 @@ export default function StatisticsDashboard(props: any): JSX.Element {
return 'Activity:' + '' + KeyInfo.activity[d.key] + '\nvalue: ' + d.value;
})
.on('filtered', function (_chart: any, filter: any) {
const selectedFilters = _chart.filters();
dispatch(
selectActivities({
activities: filter,
activities: selectedFilters,
})
);
});
Expand Down Expand Up @@ -278,7 +281,7 @@ export default function StatisticsDashboard(props: any): JSX.Element {
.keyAccessor((d: any) => KeyInfo.age_group[d.key].icon)
.on('filtered', function (_chart: any) {
// Get all selected filters
const selectedFilters = _chart.filters();
const selectedFilters = _chart.filters().map((d: any) => Object.values(KeyInfo.age_group).findIndex((e: any) => e.icon === d));
dispatch(
selectAgeGroups({
ageGroups: selectedFilters,
Expand All @@ -290,7 +293,7 @@ export default function StatisticsDashboard(props: any): JSX.Element {

// *********************************************************************************//
}
}, [context.expandedTrips, chartGroup]);
}, [context.expandedTrips, chartGroup, dispatch]);

return (
<Box sx={{p: 1}} id='dashboard'>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/TripChainView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default function TripChainView(): JSX.Element {
if (
filterInfections &&
!tripChain.find(
(trip, index) =>
(trip) =>
infectionStates.includes(trip.infection_state)
)
) {
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/data_sockets/PandemosContext.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
// SPDX-License-Identifier: Apache-2.0

import React, {createContext, useEffect, useMemo, useState} from 'react';
import React, {createContext, useCallback, useEffect, useMemo, useState} from 'react';
import crossfilter, {Crossfilter} from 'crossfilter2';
import agentList from '../../assets/pandemos/agents_lookup.json?url';
import locationList from '../../assets/pandemos/locations_lookup.json?url';
import trajectories from '../../assets/pandemos/trajectories.json?url';
import {Agent, Location, Trip, TripExpanded, TripChain} from 'types/pandemos';
import {Agent, Location, Trip, TripExpanded} from 'types/pandemos';
/**
* Data context for the pandemos data.
*/
Expand Down Expand Up @@ -136,7 +136,7 @@ export const PandemosProvider = ({children}: {children: React.ReactNode}) => {
return crossfilter([]);
}
}, [agents, locations, trips]);

/*
// Preprocess trip chains
const tripChains = useMemo<Array<TripChain>>(() => {
const agentTrips = new Map<number, Array<Trip>>();
Expand All @@ -158,7 +158,7 @@ export const PandemosProvider = ({children}: {children: React.ReactNode}) => {
}
return tripChains;
}, [trips, locations]);

*/
return (
<PandemosContext.Provider
value={useMemo(
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/store/PandemosFilterSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const PandemosFilterSlice = createSlice({
selectAgeGroups(state, action: PayloadAction<{ageGroups?: number | number[]}>) {
if (action.payload.ageGroups) {
state.ageGroups = [];
state.ageGroups.concat(action.payload.ageGroups);
state.ageGroups = state.ageGroups.concat(action.payload.ageGroups);
} else {
// reset filter if parameter is undefined
state.ageGroups = undefined;
Expand All @@ -53,7 +53,7 @@ export const PandemosFilterSlice = createSlice({
selectTransportationModes(state, action: PayloadAction<{transportationModes?: number | number[]}>) {
if (action.payload.transportationModes) {
state.transportationModes = [];
state.transportationModes.concat(action.payload.transportationModes);
state.transportationModes = state.transportationModes.concat(action.payload.transportationModes);
} else {
// reset filter if parameter is undefined
state.transportationModes = undefined;
Expand All @@ -67,7 +67,7 @@ export const PandemosFilterSlice = createSlice({
selectActivities(state, action: PayloadAction<{activities?: number | number[]}>) {
if (action.payload.activities) {
state.activities = [];
state.activities.concat(action.payload.activities);
state.activities = state.activities.concat(action.payload.activities);
} else {
// reset filter if parameter is undefined
state.activities = undefined;
Expand All @@ -81,7 +81,7 @@ export const PandemosFilterSlice = createSlice({
selectOriginTypes(state, action: PayloadAction<{originTypes?: number | number[]}>) {
if (action.payload.originTypes) {
state.originTypes = [];
state.originTypes.concat(action.payload.originTypes);
state.originTypes = state.originTypes.concat(action.payload.originTypes);
} else {
// reset filter if parameter is undefined
state.originTypes = undefined;
Expand All @@ -95,7 +95,7 @@ export const PandemosFilterSlice = createSlice({
selectDestinationTypes(state, action: PayloadAction<{destinationTypes?: number | number[]}>) {
if (action.payload.destinationTypes) {
state.destinationTypes = [];
state.destinationTypes.concat(action.payload.destinationTypes);
state.destinationTypes = state.destinationTypes.concat(action.payload.destinationTypes);
} else {
// reset filter if parameter is undefined
state.destinationTypes = undefined;
Expand All @@ -109,7 +109,7 @@ export const PandemosFilterSlice = createSlice({
selectInfectionStates(state, action: PayloadAction<{infectionStates?: number | number[]}>) {
if (action.payload.infectionStates) {
state.infectionStates = [];
state.infectionStates.concat(action.payload.infectionStates);
state.infectionStates = state.infectionStates.concat(action.payload.infectionStates);
} else {
// reset filter if parameter is undefined
state.infectionStates = undefined;
Expand Down

0 comments on commit d8c01ed

Please sign in to comment.