root/misc/unitconverter.cgi

Revision 2160 (checked in by miyagawa, 13 years ago)

add temperature

  • Property svn:executable set to *
Line 
1 #!/usr/bin/perl
2 use strict;
3 use warnings;
4 use CGI;
5 use HTML::Prototype;
6 use MIME::Base64;
7 use Template;
8
9 my $query = CGI->new;
10    $query->charset("utf-8");
11
12 dispatch($query);
13
14 sub dispatch {
15     my $query = shift;
16
17     if ($query->param('from')) {
18         do_convert($query);
19     } elsif ($query->param('spinner')) {
20         show_spinner($query);
21     } else {
22         show_form($query);
23     }
24 }
25
26 sub do_convert {
27     my $query = shift;
28
29     my $from = validate_unit($query->param('from'));
30     my $to   = validate_unit($query->param('to'));
31
32     my $func = "convert_${from}_${to}";
33     no strict 'refs';
34     my $value = eval { $func->(validate_number($query->param('value'))) };
35     if ($@) {
36         print $query->header, "ERR: Can't do $from to $to conversion: $@";
37         return;
38     }
39
40     my $format = $value > 0 ? '%.4f' : '%.8f';
41     $value = sprintf $format, $value;
42
43     print $query->header, $value;
44 }
45
46 sub validate_unit {
47     my $input = shift;
48     return ($input =~ /^(\w+)$/)[0];
49 }
50
51 sub validate_number {
52     my $input = shift;
53     return ($input =~ /^([\-\+\d\.]+)/)[0];
54 }
55
56 sub convert_usd_jpy {
57     require Finance::Currency::Convert::Yahoo;
58     Finance::Currency::Convert::Yahoo::convert($_[0], 'USD', 'JPY');
59 }
60
61 sub convert_jpy_usd {
62     require Finance::Currency::Convert::Yahoo;
63     Finance::Currency::Convert::Yahoo::convert($_[0], 'JPY', 'USD');
64 }
65
66 sub convert_inch_meter {
67     return 0.0254 * $_[0];
68 }
69
70 sub convert_meter_inch {
71     return $_[0] / 0.0254;
72 }
73
74 sub convert_inch_feet {
75     return $_[0] / 12;
76 }
77
78 sub convert_feet_inch {
79     return $_[0] * 12;
80 }
81
82 sub convert_feet_meter { convert_inch_meter(convert_feet_inch($_[0])) }
83 sub convert_meter_feet { convert_inch_feet(convert_meter_inch($_[0])) }
84
85 sub convert_oz_pound {
86     return $_[0] / 16;
87 }
88
89 sub convert_pound_oz {
90     return $_[0] * 16;
91 }
92
93 sub convert_g_pound {
94     return $_[0] / 453.59237;
95 }
96
97 sub convert_pound_g {
98     return $_[0] * 453.59237;
99 }
100
101 sub convert_oz_g { convert_pound_g(convert_oz_pound($_[0])) }
102 sub convert_g_oz { convert_pound_oz(convert_g_pound($_[0])) }
103
104 sub convert_sqf_sqm {
105     return $_[0] * 0.09290304;
106 }
107
108 sub convert_sqm_sqf {
109     return $_[0] / 0.09290304;
110 }
111
112 sub convert_celsius_fahrenheit {
113     (9 / 5) * $_[0] + 32;
114 }
115
116 sub convert_fahrenheit_celsius {
117     (5 / 9) * ($_[0] - 32);
118 }
119
120 sub show_form {
121     my $query = shift;
122
123     my $tt = Template->new;
124     my $template = show_form_template();
125
126     my $stash;
127     $stash->{prototype} = HTML::Prototype->new;
128     $stash->{cgi}       = $query;
129
130     print $query->header('text/html');
131     $tt->process(\$template, $stash);
132 }
133
134 sub show_form_template {
135     return <<'TEMPLATE';
136 [% SET title = "Unit Converter (Japan and United States)" -%]
137 <html>
138 <head>
139 <title>[% title %]</title>
140 <style>
141 body,input,td { font-size: 11px; font-family: trebuchet MS }
142 input { background: #fff }
143 h1 { font-size: 2em }
144 h2 { font-size: 1.6em }
145 </style>
146 [% prototype.define_javascript_functions %]
147 <script>
148 var url = "[% cgi.url %]";
149 function doConvert(from, to, unit) {
150   var spinner = unit + "-spinner";
151   $(to).value = ''; // clear
152   $(spinner).innerHTML = "<img src=\"[% cgi.url %]?spinner=1\" style=\"vertical-align:middle\" />";
153   var query = "value=" + encodeURIComponent($(from).value) + "&from=" + from + "&to=" + to;
154   new Ajax.Request(
155     url,
156     { method: 'get',
157       parameters: query,
158       onComplete: function(req) { $(to).value = req.responseText; $(spinner).innerHTML = ""; } }
159   );
160 }
161 </script>
162 </head>
163 <body>
164 <h1>[% title %]</h1>
165
166 <h2>Currency</h2>
167 <p>
168 <input type="text" size="12" id="usd" onchange="doConvert('usd', 'jpy', 'currency')" /> USD =
169 <input type="text" size="12" id="jpy" onchange="doConvert('jpy', 'usd', 'currency')" /> JPY
170 <span id="currency-spinner"></span>
171 </p>
172
173 <h2>Length</h2>
174 <p>
175 <input type="text" size="12" id="feet" onchange="doConvert('feet', 'inch', 'length');doConvert('feet', 'meter', 'length')" /> feet =
176 <input type="text" size="12" id="inch" onchange="doConvert('inch', 'meter', 'length');doConvert('inch', 'feet', 'length')" /> inches =
177 <input type="text" size="12" id="meter" onchange="doConvert('meter', 'inch', 'length');doConvert('meter', 'feet', 'length')" /> meters
178 <span id="length-spinner"></span>
179 </p>
180
181 <h2>Weight</h2>
182 <p>
183 <input type="text" size="12" id="pound" onchange="doConvert('pound', 'oz', 'weight');doConvert('pound', 'g', 'weight')" /> lb =
184 <input type="text" size="12" id="oz" onchange="doConvert('oz', 'pound', 'weight');doConvert('oz', 'g', 'weight')" /> oz =
185 <input type="text" size="12" id="g" onchange="doConvert('g', 'pound', 'weight');doConvert('g', 'oz', 'weight')" /> g
186 <span id="weight-spinner"></span>
187 </p>
188
189 <h2>Dimensions</h2>
190 <p>
191 <input type="text" size="12" id="sqf" onchange="doConvert('sqf', 'sqm', 'dimensions')" /> square feet =
192 <input type="text" size="12" id="sqm" onchange="doConvert('sqm', 'sqf', 'dimensions')" /> m<sup>2</sup>
193 <span id="dimensions-spinner"></span>
194 </p>
195
196 <h2>Temperature</h2>
197 <p>
198 <input type="text" size="12" id="fahrenheit" onchange="doConvert('fahrenheit', 'celsius', 'temperature')" /> °F =
199 <input type="text" size="12" id="celsius" onchange="doConvert('celsius', 'fahrenheit', 'temperature')" /> °C
200 <span id="temperature-spinner"></span>
201 </p>
202
203
204
205 TEMPLATE
206 }
207
208 sub show_spinner {
209     my $query = shift;
210     print $query->header('image/gif'), decode_base64(<<IMAGE);
211 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
255 ISADghsLBDEhIwRfGyMWGA8NXBEAOw==
256 IMAGE
257 }
Note: See TracBrowser for help on using the browser.