Annotation of loncom/cgi/graph.png, revision 1.29
1.1 minaeibi 1: #!/usr/bin/perl
2: #
1.29 ! matthew 3: # $Id: graph.png,v 1.28 2003/10/21 15:19:25 matthew Exp $
1.5 minaeibi 4: #
5: # Copyright Michigan State University Board of Trustees
6: #
7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: #
9: # LON-CAPA is free software; you can redistribute it and/or modify
10: # it under the terms of the GNU General Public License as published by
11: # the Free Software Foundation; either version 2 of the License, or
12: # (at your option) any later version.
13: #
14: # LON-CAPA is distributed in the hope that it will be useful,
15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: # GNU General Public License for more details.
18: #
19: # You should have received a copy of the GNU General Public License
20: # along with LON-CAPA; if not, write to the Free Software
21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # /home/httpd/cgi-bin/graph.gif
24: #
25: # http://www.lon-capa.org/
26: #
1.1 minaeibi 27: # The LearningOnline Network with CAPA
1.22 matthew 28: #
1.1 minaeibi 29: # A CGI script that dynamically outputs a graphical chart for lonstatistics.
1.5 minaeibi 30: #
31: ####
1.22 matthew 32:
33: =pod
34:
35: =head1 NAME
36:
37: graph.png
38:
39: =head1 SYNOPSIS
40:
41: produces plots based on input
42:
43: =head1 DESCRIPTION
44:
45: graph.png is a cgi-bin script which produces plots based on input data.
46:
47: The query string is expected to be as follows (without whitespace):
48:
49: escape(Plot title) & escape(X label)& escape(Y label) & Maximum Y value &
50: Number of bars & $data1 & $data2
51:
52: $data1 and $data2 are expected to be comma seperated lists of numbers.
53: escape( value ) means the values must be run through lonnet::escape.
54:
55: =cut
1.1 minaeibi 56:
57: use strict;
1.24 matthew 58: use lib '/home/httpd/lib/perl';
1.9 minaeibi 59: use GD::Graph::bars;
1.29 ! matthew 60: use GD::Graph::lines;
1.1 minaeibi 61: use GD::Graph::colour;
62: use GD::Graph::Data;
1.24 matthew 63: use LONCAPA::loncgi();
1.1 minaeibi 64:
1.21 matthew 65: sub unescape {
66: my $str=shift;
67: $str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
68: return $str;
69: }
70:
1.29 ! matthew 71: sub error {
! 72: my ($error) = @_;
! 73: my $Str = <<"END";
! 74: Content-type: text/html
! 75:
! 76: <html>
! 77: <head><title>Bad Graph</title></head>
! 78: <body>
! 79: <p>
! 80: There was an error producing the graph you requested.
! 81: </p><p>
! 82: $error
! 83: </p>
! 84: </body>
! 85: </html>
! 86: END
! 87: return $Str;
! 88: }
! 89:
! 90: my $id = $ENV{'QUERY_STRING'};
! 91:
! 92: #
! 93: # &get_env($name,$default)
! 94: sub get_env {
! 95: my $key = 'cgi.'.$id.'.'.(shift());
! 96: return shift if (! exists($ENV{$key}));
! 97: return $ENV{$key};
! 98: }
! 99:
1.24 matthew 100: if (! &LONCAPA::loncgi::check_cookie_and_load_env()) {
101: print <<END;
102: Content-type: text/html
103:
104: <html>
105: <head><title>Bad Cookie</title></head>
106: <body>
1.28 matthew 107: Your cookie information is incorrect.
1.24 matthew 108: </body>
109: </html>
110: END
1.26 albertel 111: exit;
1.24 matthew 112: }
113:
1.4 matthew 114: $|=1; # Autoflush after each print/write
1.1 minaeibi 115:
1.29 ! matthew 116: my $colordefaults = join(',',
! 117: ('#33ff00',
! 118: '#0033cc','#990000','#aaaa66','#663399','#ff9933',
! 119: '#66ccff','#ff9999','#cccc33','#660000','#33cc66',
! 120: ));
! 121:
! 122: my $height = &get_env('height',300);
! 123: my $width = &get_env('width', 400);
! 124: my $PlotType = &get_env('PlotType','bar');
! 125:
! 126: my %GraphSettings = (
! 127: title => &unescape(&get_env('title','')),
! 128: x_label => &unescape(&get_env('xlabel','')),
! 129: y_label => &unescape(&get_env('ylabel','')),
1.24 matthew 130: x_label_position => 0.5,
1.29 ! matthew 131: dclrs => [split(',',&get_env('Colors',
! 132: $colordefaults))],
1.24 matthew 133: fgclr => 'black',
134: boxclr => 'white',
135: accentclr => 'dblue',
136: valuesclr => '#ffff77',
137: l_margin => 10,
138: b_margin => 10,
139: r_margin => 10,
140: t_margin => 10,
141: transparent => 0,
1.29 ! matthew 142: );
1.24 matthew 143:
1.29 ! matthew 144: $GraphSettings{'x_label_skip'} = &get_env('xskip',1);
! 145: $GraphSettings{'x_tick_offset'} = &get_env('x_tick_offset',0);
! 146: $GraphSettings{'y_max_value'} = &get_env('Max',undef);
! 147:
! 148: my $MyGraph;
! 149: if ($PlotType eq 'bar') {
! 150: # Pick up bar graph settings
! 151: $GraphSettings{'bar_width'} = &get_env('bar_width',undef);
! 152: $GraphSettings{'long_ticks'} = 1;
! 153: $GraphSettings{'tick_length'} = 0;
! 154: $GraphSettings{'x_ticks'} = 0;
! 155: $GraphSettings{'cumulate'} = 2;
! 156: $GraphSettings{'zero_axis'} = 1;
! 157: } else {
! 158: #
! 159: # X label skip setup
! 160: my $skip_x = &get_env('xskip',1);
! 161: my $x_tick_offset = &get_env('x_tick_offset',$skip_x-1);
! 162: my $zero_axis = &get_env('zero_axis',1);
! 163: #
! 164: # Fill up %GraphSettings
! 165: $GraphSettings{'long_ticks'} = 1;
! 166: $GraphSettings{'tick_length'} = 0;
! 167: $GraphSettings{'x_ticks'} = &get_env('x_ticks',0),;
! 168: $GraphSettings{'x_label_skip'} = $skip_x;
! 169: $GraphSettings{'x_tick_offset'} = $x_tick_offset;
! 170: $GraphSettings{'zero_axis'} = 1;
! 171: }
! 172: #
! 173: # Pick up miscellanious values passed in by the user
! 174: #
! 175: # Create the plot and check it out
! 176: if ($PlotType eq 'bar') {
! 177: $MyGraph = GD::Graph::bars->new($width,$height);
! 178: } else {
! 179: $MyGraph = GD::Graph::lines->new($width,$height);
! 180: }
! 181: if (! defined($MyGraph)) {
! 182: print &error('Unable to create initial graph');
1.24 matthew 183: return;
184: }
1.1 minaeibi 185:
1.29 ! matthew 186: ##
! 187: ## Build the @Data array
! 188: my $NumSets = &get_env('NumSets');
! 189: my @Data; # stores the data for the graph
! 190: my @xlabels = split(',',&get_env('labels'));
! 191: push(@Data,\@xlabels);
! 192: for (my $i=1;$i<=$NumSets;$i++) {
! 193: push(@Data,[split(',',&get_env('data.'.$i))]);
! 194: }
1.24 matthew 195:
1.29 ! matthew 196: my $error = '';
! 197: if (! $MyGraph->set(%GraphSettings)) {
! 198: print &error($MyGraph->error);
1.24 matthew 199: return;
200: }
1.1 minaeibi 201:
1.29 ! matthew 202: my $plot = $MyGraph->plot(\@Data);
! 203: if (! defined($plot)) {
! 204: my $error = 'Unable to plot the data provided.';
! 205: $error .= '<pre>'.join(',',@{$Data[0]}).'</pre>';
! 206: $error .= '<pre>'.join(',',@{$Data[1]}).'</pre>';
! 207: $error .= '<pre>'.join(',',@{$Data[2]}).'</pre>';
! 208: print &error($error);
! 209: exit;
! 210: }
! 211:
1.24 matthew 212: my $BinaryData=$plot->png;
213: undef($MyGraph);
214: undef($plot);
215:
216: if (! defined($BinaryData)) {
1.29 ! matthew 217: print &error('Unable to render graph as image');
! 218: exit;
1.24 matthew 219: }
1.12 minaeibi 220:
1.16 albertel 221: # Tell the server we are sending a png graphic
1.1 minaeibi 222: print <<END;
1.16 albertel 223: Content-type: image/png
1.1 minaeibi 224:
225: END
226:
227: binmode(STDOUT);
1.16 albertel 228: #open IMG,"|pngtopnm|ppmtogif 2>/dev/null"; # convert into a gif image
229: #print IMG $BinaryData; # output image
230: #$|=1; # be sure to flush before closing
231: #close IMG;
232: print $BinaryData;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>