From 08ba76352474969492bce1331a7bf50cebf7a869 Mon Sep 17 00:00:00 2001 From: dJonaitis <55477640+dJonaitis@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:00:19 +0100 Subject: [PATCH] Added a button that exports the trip table to a CSV file. (#1153) * Added a button that exports the trip table to a CSV file. * Fixed minor type issue in function --- .../game/src/sandbox/dashboards/trip_table.rs | 51 +++++++++++++++++++ widgetry_demo/src/lib.rs | 3 +- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/apps/game/src/sandbox/dashboards/trip_table.rs b/apps/game/src/sandbox/dashboards/trip_table.rs index 3748dd5ab2..d38ba4171a 100644 --- a/apps/game/src/sandbox/dashboards/trip_table.rs +++ b/apps/game/src/sandbox/dashboards/trip_table.rs @@ -1,4 +1,5 @@ use std::collections::{BTreeSet, HashMap}; +use std::io::Write; use abstutil::prettyprint_usize; use geom::{Duration, Polygon, Time}; @@ -6,6 +7,7 @@ use map_gui::tools::{checkbox_per_mode, color_for_mode}; use sim::TripID; use synthpop::{TripEndpoint, TripMode}; use widgetry::table::{Col, Filter, Table}; +use widgetry::tools::PopupMsg; use widgetry::{ Color, EventCtx, Filler, GeomBatch, GfxCtx, Line, Outcome, Panel, Stash, State, TabController, Text, Toggle, Widget, @@ -62,6 +64,11 @@ impl TripTable { let finished_trips_table = make_table_finished_trips(app); let finished_trips_content = Widget::col(vec![ finished_trips_table.render(ctx, app), + ctx.style() + .btn_plain + .text("Export to CSV") + .build_def(ctx) + .align_bottom(), Filler::square_width(ctx, 0.15) .named("preview") .centered_horiz(), @@ -123,6 +130,18 @@ impl State for TripTable { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { match self.panel.event(ctx) { Outcome::Clicked(x) => { + if x == "Export to CSV" { + return Transition::Push(match export_trip_table(app) { + Ok(path) => PopupMsg::new_state( + ctx, + "Data exported", + vec![format!("Data exported to {}", path)], + ), + Err(err) => { + PopupMsg::new_state(ctx, "Export failed", vec![err.to_string()]) + } + }); + } if self.table_tabs.active_tab_idx() == 0 && self.finished_trips_table.clicked(&x) { self.finished_trips_table .replace_render(ctx, app, &mut self.panel); @@ -698,3 +717,35 @@ fn make_table_unfinished_trips(app: &App) -> Table table } + +fn export_trip_table(app: &App) -> anyhow::Result { + let (finished, _) = produce_raw_data(app); + let path = format!( + "trip_table_{}_{}.csv", + app.primary.map.get_name().as_filename(), + app.primary.sim.time().as_filename() + ); + + let mut out = std::io::Cursor::new(Vec::new()); + writeln!( + out, + "id,mode,modified,departure,duration,waiting_time,percent_waiting,duration_before" + )?; + + for trip in finished { + writeln!( + out, + "{},{:?},{},{},{},{},{},{}", + trip.id.0, + trip.mode, + trip.modified, + trip.departure, + trip.duration_after.inner_seconds(), + trip.waiting.inner_seconds(), + trip.percent_waiting, + trip.duration_before.inner_seconds() + )?; + } + + abstio::write_file(path, String::from_utf8(out.into_inner())?).map_err(anyhow::Error::from) +} diff --git a/widgetry_demo/src/lib.rs b/widgetry_demo/src/lib.rs index 875709aa8f..b68e7081ee 100644 --- a/widgetry_demo/src/lib.rs +++ b/widgetry_demo/src/lib.rs @@ -14,7 +14,6 @@ pub fn main() { run(settings); } - fn run(mut settings: Settings) { abstutil::logger::setup(); settings = settings.read_svg(Box::new(abstio::slurp_bytes)); @@ -60,7 +59,7 @@ impl Demo { where F: Fn(usize) -> usize, { - Series{ + Series { label: label.to_string(), color, pts: (0..(self.elapsed.inner_seconds() as usize))