From efb2ae1c538110772e072e8e74567f7f2d0c809b Mon Sep 17 00:00:00 2001 From: Brendan Nee Date: Sun, 28 Apr 2024 21:12:48 -0700 Subject: [PATCH] Error graph by date in summary --- CHANGELOG.md | 6 ++++++ lib/formatters.js | 22 ++++++++++++++++++++++ lib/gtfs-ride.js | 14 +++++++++++++- views/layout.pug | 35 ++++++++++++++++++++++++++++++++++- views/summary.pug | 3 +++ 5 files changed, 78 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a8f212..c01f4c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Error graph by date in summary + ## [0.2.5] - 2024-03-13 ### Updated diff --git a/lib/formatters.js b/lib/formatters.js index 7ae4a92..21c1182 100644 --- a/lib/formatters.js +++ b/lib/formatters.js @@ -71,3 +71,25 @@ export function summarizeIssues(issues) { return sortBy(issueSummaries, 'count').reverse(); } + +export function countIssuesByDate(issues, oldestDate, newestDate) { + const dateGroups = groupBy(issues, 'date'); + + const dateGroupsInRange = {}; + + for (let date = oldestDate; date <= newestDate; date++) { + dateGroupsInRange[date] = dateGroups[date] ?? []; + } + + return Object.entries(dateGroupsInRange).map(([date, issues]) => { + return { + date, + count: issues.length, + boardings: issues.reduce((sum, issue) => sum + (issue.boardings ?? 0), 0), + alightings: issues.reduce( + (sum, issue) => sum + (issue.alightings ?? 0), + 0, + ), + }; + }); +} diff --git a/lib/gtfs-ride.js b/lib/gtfs-ride.js index 7e01c51..91e9018 100644 --- a/lib/gtfs-ride.js +++ b/lib/gtfs-ride.js @@ -13,7 +13,11 @@ import { log, logWarning, logError, logStats } from './log-utils.js'; import { setDefaultConfig } from './utils.js'; import importAPC from './import-apc.js'; import { generateSummaryHtml } from './summary.js'; -import { formatIssue, summarizeIssues } from './formatters.js'; +import { + countIssuesByDate, + formatIssue, + summarizeIssues, +} from './formatters.js'; /* * Generate GTFS-Ride data @@ -140,6 +144,7 @@ const gtfsRide = async (initialConfig) => { .all(...tripsWithData); let dateRange = ''; + let issueDateCounts = []; if (oldestDate && newestDate) { dateRange = `${DateTime.fromFormat( @@ -149,6 +154,12 @@ const gtfsRide = async (initialConfig) => { newestDate.service_date.toString(), 'yyyyMMdd', ).toLocaleString(DateTime.DATE_FULL)}`; + + issueDateCounts = countIssuesByDate( + issues, + oldestDate.service_date, + newestDate.service_date, + ); } const outputStats = { @@ -156,6 +167,7 @@ const gtfsRide = async (initialConfig) => { boardAlightCount: boardAlightCount['count(*)'], issues, issueSummaries: summarizeIssues(issues), + issueDateCounts, seconds, dateRange, stopsWithData, diff --git a/views/layout.pug b/views/layout.pug index dc1eb5c..7e6eec4 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -9,4 +9,37 @@ html body block content - script(src="/js/index.js") + script(src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js") + script + script. + (async function() { + const issueDateCounts = !{JSON.stringify(issueDateCounts) || '\'\''}; + + new Chart( + document.getElementById('issuechart'), + { + type: 'bar', + data: { + labels: issueDateCounts.map(row => row.date), + datasets: [ + { + label: 'Issues by date', + data: issueDateCounts.map(row => row.count) + } + ] + }, + options: { + plugins: { + tooltip: { + callbacks: { + label: function(context) { + const issueDateCount = issueDateCounts[context.dataIndex]; + return `${issueDateCount.count} Issues, ${issueDateCount.boardings} Boardings, ${issueDateCount.alightings} Alightings`; + } + } + } + } + } + } + ); + })(); diff --git a/views/summary.pug b/views/summary.pug index 7324003..5abebd5 100644 --- a/views/summary.pug +++ b/views/summary.pug @@ -98,6 +98,9 @@ block content .py-12#issues h2.text-3xl.font-extrabold.tracking-tight.text-gray-900.pb-4 #{issues.length.toLocaleString()} Issues + + div(style="height: 400px;") + canvas#issuechart h3.text-xl.font-bold.tracking-tight.text-gray-900.pb-2 Summary of Issues table.table-auto.mb-4 thead