diff --git a/scripts/compile.ts b/scripts/compile.ts
index 9bca98f..b1774e9 100644
--- a/scripts/compile.ts
+++ b/scripts/compile.ts
@@ -70,6 +70,35 @@ const targetStatisticsDaily = (inputs: ResponseActivityRide[]) =>
const targetStatisticsMonthly = (inputs: ResponseActivityRide[]) =>
groupStatistics(inputs, date => timestampToIso(date).split('-').slice(0, 2).join('-'));
+const WEEKDAYS = [
+ 'Monday',
+ 'Tuesday',
+ 'Wednesday',
+ 'Thursday',
+ 'Friday',
+ 'Saturday',
+ 'Sunday',
+];
+
+const targetStatisticsWeekly = (inputs: ResponseActivityRide[]) => {
+ const daily = groupStatistics(inputs, date => timestampToIso(date));
+ const dailyDistances: { count: number, distance: number }[][] = _.list(0, WEEKDAYS.length - 1, () => []);
+ Object.entries(daily).forEach(([isoDate, values]) => dailyDistances[(WEEKDAYS.length + new Date(isoDate).getDay() - 1) % WEEKDAYS.length].push(values));
+ const totalWeeks = _.max(dailyDistances.map(array => array.length)) || 0;
+ return Object.fromEntries(WEEKDAYS.map((label, i) => {
+ const countAndDistancesBase = dailyDistances[i];
+ // Correct for empty days
+ const countAndDistances = countAndDistancesBase.concat(_.list(0, totalWeeks - countAndDistancesBase.length - 1, () => ({ count: 0, distance: 0 })));
+ const count = computeMeanStdDev(countAndDistances.map(v => v.count)), distance = computeMeanStdDev(countAndDistances.map(v => v.distance));
+ return [label, {
+ meanCount: count.mean,
+ stdDevCount: count.stdDev,
+ meanDistance: distance.mean,
+ stdDevDistance: distance.stdDev,
+ }];
+ }));
+};
+
const targetCumulativeDistance = (inputs: ResponseActivityRide[]) => {
const daily = Object.entries(targetStatisticsDaily(inputs));
const array: [string, number][] = [];
@@ -268,6 +297,7 @@ const compile = () => {
const targets = {
statisticsDaily: targetStatisticsDaily(inputs),
statisticsMonthly: targetStatisticsMonthly(inputs),
+ statisticsWeekly: targetStatisticsWeekly(inputs),
records: targetRecords(inputs),
cumulativeDistance: targetCumulativeDistance(inputs),
cadence: targetCadence(inputs),
diff --git a/src/Visualizations.tsx b/src/Visualizations.tsx
index 13afa18..763bffb 100644
--- a/src/Visualizations.tsx
+++ b/src/Visualizations.tsx
@@ -10,6 +10,7 @@ import { Grid, GridItem } from '@chakra-ui/react';
import { SpeedDistribution } from './viz/SpeedDistribution';
import { PowerDistribution } from './viz/PowerDistribution';
import { SpeedAccelerationChart } from './viz/SpeedAccelerationChart';
+import { WeeklyChart } from './viz/WeeklyChart';
export const Visualizations: React.FC = () => {
const largeProps = { colSpan: 2 }
@@ -22,12 +23,15 @@ export const Visualizations: React.FC = () => {
-
+
+
+
+
diff --git a/src/types/types.ts b/src/types/types.ts
index 143b6d2..ae5972f 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -1,6 +1,7 @@
export interface Data {
statisticsDaily: TargetStatistics;
- statisticsMonthly: TargetStatistics;
+ statisticsMonthly: Record;
+ statisticsWeekly: Record;
records: TargetRecords;
cumulativeDistance: TargetCumulative;
cadence: TargetBuckets;
@@ -15,6 +16,13 @@ export interface TargetStatistics {
distance: number;
}
+export interface TargetStatisticsAggregated {
+ meanCount: number,
+ stdDevCount: number,
+ meanDistance: number,
+ stdDevDistance: number,
+}
+
export interface TargetRecords {
totalDistance: number;
maxSpeed: number;
diff --git a/src/utils.ts b/src/utils.ts
new file mode 100644
index 0000000..27149c0
--- /dev/null
+++ b/src/utils.ts
@@ -0,0 +1,5 @@
+// Percentile to Z-score mapping for some well-known values
+export const Z_SCORES = {
+ 50: 0.674,
+ 95: 1.96,
+} as const;
diff --git a/src/viz/MonthlyChart.tsx b/src/viz/MonthlyChart.tsx
index bc3871e..cd1feae 100644
--- a/src/viz/MonthlyChart.tsx
+++ b/src/viz/MonthlyChart.tsx
@@ -2,26 +2,31 @@ import { useDataQuery } from '../hooks/useDataQuery';
import React from 'react';
import { TargetStatistics } from '../types/types';
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from 'recharts';
-import { Box, Heading, useColorModeValue, useTheme } from '@chakra-ui/react';
+import { Box, Heading, Text, useColorModeValue, useTheme } from '@chakra-ui/react';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
interface MonthlyChartContentProps {
- data: TargetStatistics;
+ data: Record;
}
const MonthlyChartContent: React.FC = ({ data }) => {
const theme = useTheme();
const color = useColorModeValue(theme.colors.blue[500], theme.colors.blue[200]);
- const barData = Object.entries(data).map(([key, obj]) => ({ name: key, ...obj, distance: obj.distance / 1000 })).reverse().slice(0, 12).reverse();
+ const lastMonths = 12;
+
+ const barData = Object.entries(data).map(([key, obj]) => ({ name: key, ...obj, distance: obj.distance / 1000 })).reverse().slice(0, lastMonths).reverse();
return (
-
+
Monthly distance
+
+ Last {lastMonths} months
+
= ({ data }) => {
>
-
+
diff --git a/src/viz/SpeedAccelerationChart.tsx b/src/viz/SpeedAccelerationChart.tsx
index 468819c..c28239c 100644
--- a/src/viz/SpeedAccelerationChart.tsx
+++ b/src/viz/SpeedAccelerationChart.tsx
@@ -11,12 +11,7 @@ import {
XAxis,
YAxis,
} from 'recharts';
-
-// Percentile to Z-score mapping for some well-known values
-const Z_SCORES = {
- 50: 0.674,
- 95: 1.96,
-} as const;
+import { Z_SCORES } from '../utils';
interface SpeedAccelerationChartContentProps {
data: TargetAccelerations;
@@ -40,7 +35,7 @@ const SpeedAccelerationChartContent: React.FC
- With a {percentile}% confidence interval
+ {percentile}% confidence interval
;
+}
+
+const WeeklyChartContent: React.FC = ({ data }) => {
+ const theme = useTheme();
+ const color = useColorModeValue(theme.colors.blue[500], theme.colors.blue[200]);
+ const errorColor = useColorModeValue(theme.colors.blue[700], theme.colors.blue[50]);
+
+ const percentile = 50 as const;
+ const zScore = Z_SCORES[percentile];
+
+ const barData = Object.entries(data).map(([key, obj]) => ({ weekday: key.substring(0, 1), ...obj, meanDistance: obj.meanDistance / 1000, confidenceDistance: zScore * obj.stdDevDistance / 1000 }));
+
+ return (
+
+
+ Weekly distance
+
+
+ {percentile}% confidence interval
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export const WeeklyChart = () => {
+ const { data } = useDataQuery('statisticsWeekly');
+
+ if (!data) {
+ return null;
+ }
+ return (
+
+ )
+};