commit 12f8b86185da0490b9b3d9ae49f2f6bf88615457
parent 1faf71c063e2e721f2669952510849bb82389add
Author: Kyle Milz <kyle@getaddrinfo.net>
Date: Fri, 17 Apr 2015 21:48:10 -0600
gen_svg: split svg render from data gathering
Diffstat:
M | gen_svg | | | 136 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 80 insertions(+), 56 deletions(-)
diff --git a/gen_svg b/gen_svg
@@ -45,19 +45,86 @@ $sql = "update products set svg_stale = 0 where manufacturer = ? and part_num =
my $success_sth = $dbh->prepare($sql);
$parts_sth->execute();
-print "info: generating " if ($args{v});
+print "info: svg: " if ($args{v});
my ($raw_total, $rendered_total, $points, $series) = (0, 0, 0, 0);
while (my ($manufacturer, $part_num) = $parts_sth->fetchrow_array()) {
$raw_total++;
spin() if ($args{v});
+ my %series;
- # make sure we have at least two prices to work with
- $sql = "select min(date), max(date), min(price), max(price) " .
- "from prices where part_num = ? and manufacturer = ?";
+ $sql = qq{select min(date), max(date), min(price), max(price)
+ from prices where manufacturer = ? and part_num = ?};
my ($x_min, $x_max, $y_min, $y_max) =
- $dbh->selectrow_array($sql, undef, $part_num, $manufacturer);
+ $dbh->selectrow_array($sql, undef, $manufacturer, $part_num);
next unless (defined $x_min);
+ # each series on the chart represents a retailers prices
+ $retailer_sth->execute($part_num, $manufacturer);
+ while (my ($retailer) = $retailer_sth->fetchrow_array()) {
+ $sql = "select url, color from retailers where name = ?";
+ my ($url, $color) = $dbh->selectrow_array($sql, undef, $retailer);
+
+ # xlink:href's don't like raw ampersands
+ $url =~ s/&/&/g;
+
+ $series{$retailer}{url} = $url;
+ $series{$retailer}{color} = $color;
+
+ $point_sth->execute($part_num, $retailer);
+ $series{$retailer}{data} = $point_sth->fetchall_arrayref();
+ $points += scalar @{$series{$retailer}{data}};
+ $series++;
+ }
+
+ my $svg = make_svg(\%series, $x_min, $x_max, $y_min, $y_max, $part_num);
+
+ next if ($args{n});
+
+ # all links lower case
+ my $part_num_cased = $part_num;
+ $part_num = lc($part_num);
+
+ # giant hack, if the part number has / in it, make some directories
+ if ($part_num =~ /\//) {
+ my $needed_dirs = substr($part_num, 0, rindex($part_num, '/'));
+ make_path("$svg_dir/$needed_dirs", { verbose => $args{v} });
+ }
+ open my $svg_fh, ">", "$svg_dir/$part_num.svg" or
+ die "couldn't open $svg_dir/$part_num: $!";
+
+ # XXX: not sure how to add this programatically, hack around for now
+ my @buf = split("\n", $svg->xmlify);
+ my $css_include = "<?xml-stylesheet href=\"/pricechart.css\" type=\"text/css\"?>";
+ # must be the second line
+ splice (@buf, 1, 0, ($css_include));
+
+ print $svg_fh "$_\n" for (@buf);
+ close $svg_fh;
+
+ # we outputted something to a file, set stale to 0
+ $success_sth->execute($manufacturer, $part_num_cased);
+ $rendered_total++;
+}
+
+if ($args{v}) {
+ printf "\b%i rendered (%i skipped), %i series (%i points)\n",
+ $rendered_total, $raw_total - $rendered_total, $series, $points;
+}
+
+$dbh->disconnect();
+
+#
+# make a new svg with provided coordinate and label data
+#
+sub make_svg
+{
+ my $series = shift;
+ my $x_min = shift;
+ my $x_max = shift;
+ my $y_min = shift;
+ my $y_max = shift;
+ my $part_num = shift;
+
$y_max = ceil($y_max / 100) * 100;
$y_min = floor($y_min / 100) * 100;
@@ -114,28 +181,20 @@ while (my ($manufacturer, $part_num) = $parts_sth->fetchrow_array()) {
);
}
- # each series on the chart represents a retailers prices
- $retailer_sth->execute($part_num, $manufacturer);
- while (my ($retailer) = $retailer_sth->fetchrow_array()) {
+ while (my ($retailer, $values) = each %$series) {
my $retailer_id = lc($retailer);
$retailer_id =~ s/ /_/;
- $sql = "select url, color from retailers where name = ?";
- my ($url, $color) = $dbh->selectrow_array($sql, undef, $retailer);
-
- # xlink:href's don't like raw ampersands
- $url =~ s/&/&/g;
+ my $url = $values->{url};
+ my $color = $values->{color};
- # get all prices that we've scraped per product per retailer
my (@xs, @ys, @pts);
- $point_sth->execute($part_num, $retailer);
- while (my ($date, $price) = $point_sth->fetchrow_array) {
- # transform and clamp real world coordinates
- push @xs, sprintf "%.3f", ($date - $x_min) * $x_scale + $left;
- push @ys, sprintf "%.3f", $height - $bottom - ($price - $y_min) * $y_scale;
+ for (@{$values->{data}}) {
+ my ($x, $y) = @$_;
+ push @xs, sprintf "%.3f", ($x - $x_min) * $x_scale + $left;
+ push @ys, sprintf "%.3f", $height - $bottom - ($y - $y_min) * $y_scale;
push @pts, $xs[-1];
push @pts, $ys[-1];
- $points++;
}
if (@pts < 6) {
@@ -171,8 +230,6 @@ while (my ($manufacturer, $part_num) = $parts_sth->fetchrow_array()) {
$anchor->text(class => "chart_series_text", fill => "#$color"
)->tag("textPath", -href => "#path_$retailer_id"
)->tag("tspan", "dy" => "-5")->cdata($retailer);
-
- $series++;
}
# when graph is loaded make a sliding motion show the graph lines
@@ -185,42 +242,9 @@ while (my ($manufacturer, $part_num) = $parts_sth->fetchrow_array()) {
# fill => "freeze", -method => ""
# );
- next if ($args{n});
-
- # all links lower case
- my $part_num_cased = $part_num;
- $part_num = lc($part_num);
-
- # giant hack, if the part number has / in it, make some directories
- if ($part_num =~ /\//) {
- my $needed_dirs = substr($part_num, 0, rindex($part_num, '/'));
- make_path("$svg_dir/$needed_dirs", { verbose => $args{v} });
- }
- open my $svg_fh, ">", "$svg_dir/$part_num.svg" or
- die "couldn't open $svg_dir/$part_num: $!";
-
- # XXX: not sure how to add this programatically, hack around for now
- my @buf = split("\n", $svg->xmlify);
- my $css_include = "<?xml-stylesheet href=\"/pricechart.css\" type=\"text/css\"?>";
- # must be the second line
- splice (@buf, 1, 0, ($css_include));
-
- print $svg_fh "$_\n" for (@buf);
- close $svg_fh;
-
- # we outputted something to a file, set stale to 0
- $success_sth->execute($manufacturer, $part_num_cased);
- $rendered_total++;
+ return $svg
}
-if ($args{v}) {
- print "\n";
- printf "info: %i rendered (%i skipped), %i series (%i points)\n",
- $rendered_total, $raw_total - $rendered_total, $series, $points;
-}
-
-$dbh->disconnect();
-
sub catmullrom_to_bezier
{
my $pts_ref = shift;