From d2b0aeee5e781b395b9d00573df8de6f80b41509 Mon Sep 17 00:00:00 2001 From: Alexander Klink Date: Sat, 12 May 2007 01:46:27 +0200 Subject: [PATCH] chart generation using Chart::Clicker works --- lib/KratosOrange/Dispatcher.pm | 7 +++ lib/KratosOrange/Model/WayPoint.pm | 102 +++++++++++++++++++++++++++++++++++++ lib/KratosOrange/View.pm | 16 ++++++ 3 files changed, 125 insertions(+) diff --git a/lib/KratosOrange/Dispatcher.pm b/lib/KratosOrange/Dispatcher.pm index 9f4f3d2..5c995ce 100644 --- a/lib/KratosOrange/Dispatcher.pm +++ b/lib/KratosOrange/Dispatcher.pm @@ -58,6 +58,13 @@ on '/' => run { show 'summary'; }; +on qr{ /workout/(\d+)/chart }xms => run { + my $workout_id = $1; + set 'workout_id' => $workout_id; + show 'chart'; +}; + + on '/prefs' => show 'preferences'; on '/import_synched' => show 'import_synched'; diff --git a/lib/KratosOrange/Model/WayPoint.pm b/lib/KratosOrange/Model/WayPoint.pm index 11f5bb0..3bcaa97 100644 --- a/lib/KratosOrange/Model/WayPoint.pm +++ b/lib/KratosOrange/Model/WayPoint.pm @@ -3,6 +3,20 @@ use warnings; package KratosOrange::Model::WayPoint; use Jifty::DBI::Schema; +use Chart::Clicker::Renderer::Area; +use Chart::Clicker; +use Chart::Clicker::Axis; +use Chart::Clicker::Axis::DateTime; +use Chart::Clicker::Data::DataSet; +use Chart::Clicker::Data::Series; +use Chart::Clicker::Decoration::Grid; +use Chart::Clicker::Decoration::Label; +use Chart::Clicker::Decoration::Legend; +use Chart::Clicker::Decoration::Plot; +use Chart::Clicker::Drawing qw(:positions); +use Chart::Clicker::Drawing::Insets; +use Chart::Clicker::Drawing::Color; +use Chart::Clicker::Drawing::ColorAllocator; use KratosOrange::Record schema { column workout_id => @@ -34,5 +48,93 @@ sub new_from_extended_data { return 1; } +sub chart_from_workout { + my $self = shift; + my $workout_id = shift; + my @values = (); + my @keys = (); + + my $workout = KratosOrange::Model::Workout->load($workout_id); + my $points = KratosOrange::Model::WayPointCollection->new(); + $points->limit( + column => 'workout_id', + value => $workout_id, + ); + + if ($workout->interval_unit() ne 's') { + die "Can not compute with non-seconds"; + } + + my $curr_key = 0; + my $old = $points->next(); + while (my $new = $points->next()) { + # compute average speed in km/h between two waypoints + my $delta_distance = $new->distance - $old->distance; + push @values, (3600 / $workout->interval_value) * $delta_distance; + push @keys, $curr_key; + + $curr_key += $workout->interval_value; + $old = $new; + } + my $renderer = Chart::Clicker::Renderer::Area->new(); + $renderer->options({ + opacity => .8, + }); + my $series = Chart::Clicker::Data::Series->new({ + keys => \@keys, + values => \@values, + }); + my $chart = Chart::Clicker->new({ + datasets => [ + Chart::Clicker::Data::DataSet->new({ + series => [ $series ], + }), + ], + width => 700, + height => 250, + }); + $chart->color_allocator( + Chart::Clicker::Drawing::ColorAllocator->new({ + colors => [ + Chart::Clicker::Drawing::Color->new({ + red => 0, + blue => 0.7, + green => 0, + }), + ], + }), + ); + my $daxis = Chart::Clicker::Axis->new({ + orientation => $CC_HORIZONTAL, + position => $CC_BOTTOM, + format => '%02d', + label => 'Time (s)', + }); + $chart->add($daxis, $CC_AXIS_BOTTOM); + + # Range axis + my $raxis = Chart::Clicker::Axis->new({ + orientation => $CC_VERTICAL, + position => $CC_LEFT, + format => '%0.2f', + label => 'Speed (km/h)', + }); + $chart->add($raxis, $CC_AXIS_LEFT); + + $chart->range_axes([ $raxis ]); + $chart->domain_axes([ $daxis ]); + + $chart->add(Chart::Clicker::Decoration::Grid->new(), $CC_CENTER, 0); + + my $plot = Chart::Clicker::Decoration::Plot->new(); + $plot->renderers([ $renderer ]); + $chart->add($plot, $CC_CENTER); + $plot->set_renderer_for_dataset(1, 1); + + $chart->prepare(); + $chart->draw(); + + return $chart->png(); +} 1; diff --git a/lib/KratosOrange/View.pm b/lib/KratosOrange/View.pm index f236cdd..4e830f8 100644 --- a/lib/KratosOrange/View.pm +++ b/lib/KratosOrange/View.pm @@ -112,5 +112,21 @@ private template pref_form => sub { } }; +template 'chart' => sub { + my $workout_id = get('workout_id'); + # TODO - possibly refactor to model completely + my $workout = KratosOrange::Model::Workout->load($workout_id); + if (! $workout->chart) { + # chart does not exist yet, we have to render it and save it + # the database to cache it + my $chart = + KratosOrange::Model::WayPoint->chart_from_workout($workout_id); + $workout->set_chart($chart); + } + # output chart with appropriate header + Jifty->handler->apache->content_type('image/png'); + Jifty->web->out($workout->chart); +}; + 1; -- 2.11.4.GIT