Skip to content
This repository was archived by the owner on Oct 15, 2022. It is now read-only.

Commit 98fbd94

Browse files
author
Jag Talon
committed
Merge pull request #488 from mwmiller/calc_updates
Calc updates
2 parents ddba2e8 + 300cba4 commit 98fbd94

File tree

3 files changed

+124
-96
lines changed

3 files changed

+124
-96
lines changed

lib/DDG/Goodie/Calculator.pm

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package DDG::Goodie::Calculator;
22
# ABSTRACT: do simple arthimetical calculations
33

4+
use feature 'state';
5+
46
use DDG::Goodie;
57

68
use List::Util qw( all first max );
@@ -21,27 +23,6 @@ attribution
2123
github => ['https://github.com/duckduckgo', 'duckduckgo'],
2224
twitter => ['http://twitter.com/duckduckgo', 'duckduckgo'];
2325

24-
triggers query_nowhitespace => qr<
25-
^
26-
( what is | calculate | solve | math )? !?
27-
28-
[\( \) x X * % + / \^ \$ -]*
29-
30-
(?: [0-9 \. ,]* )
31-
(?: gross | dozen | pi | e | c |)
32-
[\( \) x X * % + / \^ 0-9 \. , \$ -]*
33-
34-
(?(1) (?: -? [0-9 \. ,]+ |) |)
35-
(?: [\( \) x X * % + / \^ \$ -] | times | divided by | plus | minus | cos | sin | tan | cotan | log | ln | log[_]?\d{1,3} | exp | tanh | sec | csc)+
36-
37-
(?: [0-9 \. ,]* )
38-
(?: gross | dozen | pi | e | c |)
39-
40-
[\( \) x X * % + / \^ 0-9 \. , \$ -]* =?
41-
42-
$
43-
>xi;
44-
4526
# This is probably YAGNI territory, but since I have to reference it in two places
4627
# and there are a multitude of other notation systems (although some break the
4728
# 'thousands' assumption) I am going to pretend that I do need it.
@@ -74,7 +55,7 @@ foreach my $style (@known_styles) {
7455
# Luckily it will someday be able to be tokenized so this won't apply.
7556
my $all_seps = join('', map { $_->{decimal} . $_->{thousands} } @known_styles);
7657

77-
my $numbery = qr/^[\d$all_seps]+$/;
58+
my $numbery = qr/[\d$all_seps]+/;
7859
my $funcy = qr/[[a-z]+\(|log[_]?\d{1,3}\(|\^/; # Stuff that looks like functions.
7960

8061
my %named_operations = (
@@ -85,8 +66,11 @@ my %named_operations = (
8566
'plus' => '+',
8667
'divided\sby' => '/',
8768
'ln' => 'log', # perl log() is natural log.
69+
'squared' => '**2',
8870
);
8971

72+
my $ored_operations = join('|', keys %named_operations);
73+
9074
my %named_constants = (
9175
dozen => 12,
9276
e => 2.71828182845904523536028747135266249, # This should be computed.
@@ -96,12 +80,19 @@ my %named_constants = (
9680

9781
my $ored_constants = join('|', keys %named_constants); # For later substitutions
9882

83+
my $extra_trigger_words = qr/^(?:whatis|calculate|solve|math)/;
84+
triggers query_nowhitespace => qr<
85+
$extra_trigger_words?
86+
(\s|$funcy|$ored_constants|$ored_operations|$numbery)*
87+
$
88+
>xi;
89+
9990
handle query_nowhitespace => sub {
10091
my $results_html;
10192
my $results_no_html;
10293
my $query = $_;
10394

104-
$query =~ s/^(?:whatis|calculate|solve|math)//;
95+
$query =~ s/$extra_trigger_words//;
10596

10697
if ($query !~ /[xX]\s*[\*\%\+\-\/\^]/ && $query !~ /^-?[\d]{2,3}\.\d+,\s?-?[\d]{2,3}\.\d+$/) {
10798
my $tmp_result = '';
@@ -125,7 +116,7 @@ handle query_nowhitespace => sub {
125116
$tmp_expr =~ s#\b$name\b# $constant #ig;
126117
}
127118

128-
my @numbers = grep { $_ =~ $numbery } (split /\s+/, $tmp_expr);
119+
my @numbers = grep { $_ =~ /^$numbery$/ } (split /\s+/, $tmp_expr);
129120
my $style = display_style(@numbers);
130121
return unless $style;
131122

@@ -137,6 +128,7 @@ handle query_nowhitespace => sub {
137128
# e.g. sin(100000)/100000 completely makes this go haywire.
138129
alarm(1);
139130
$tmp_result = eval($tmp_expr);
131+
alarm(0); # Assume the string processing will be "fast enough"
140132
};
141133

142134
# Guard against non-result results
@@ -165,8 +157,7 @@ handle query_nowhitespace => sub {
165157
$results_no_html = $results_html = $tmp_q;
166158

167159
# Superscript (before spacing).
168-
$results_html =~ s/\^([^\)]+)/<sup>$1<\/sup>/g;
169-
$results_html =~ s/\^(\d+|\b(?:$ored_constants)\b)/<sup>$1<\/sup>/g;
160+
$results_html =~ s/\^($numbery|\b$ored_constants\b)/<sup>$1<\/sup>/g;
170161

171162
($results_no_html, $results_html) = map { spacing($_) } ($results_no_html, $results_html);
172163
return if $results_no_html =~ /^\s/;
@@ -176,26 +167,37 @@ handle query_nowhitespace => sub {
176167

177168
# Now add = back.
178169
$results_no_html .= ' = ';
179-
$results_html .= ' = ';
180170

181-
$results_html =
182-
qq(<div>$results_html<a href="javascript:;" onClick="document.x.q.value='$tmp_result';document.x.q.focus();">$tmp_result</a></div>);
183171
return $results_no_html . $tmp_result,
184-
html => $results_html,
172+
html => wrap_html($results_html, $tmp_result),
185173
heading => "Calculator";
186174
}
187175

188176
return;
189177
};
190178

179+
# Add some HTML and styling to our output
180+
# so that we can make it prettier (unabashedly stolen from
181+
# the ReverseComplement goodie.)
182+
sub append_css {
183+
my $html = shift;
184+
state $css = share("style.css")->slurp;
185+
return "<style type='text/css'>$css</style>$html";
186+
}
187+
188+
sub wrap_html {
189+
my ($entered, $result) = @_;
190+
return append_css("<div class='zci--calculator'>$entered = $result</div>");
191+
}
192+
191193
#separates symbols with a space
192194
#spacing '1+1' -> '1 + 1'
193195
sub spacing {
194196
my ($text, $space_for_parse) = @_;
195197

196198
$text =~ s/(\s*(?<!<)(?:[\+\-\^xX\*\/\%]|times|plus|minus|dividedby)+\s*)/ $1 /ig;
197199
$text =~ s/\s*dividedby\s*/ divided by /ig;
198-
$text =~ s/(\d+?)((?:dozen|pi|gross))/$1 $2/ig;
200+
$text =~ s/(\d+?)((?:dozen|pi|gross|squared))/$1 $2/ig;
199201
$text =~ s/(\d+?)e/$1 e/g; # E == *10^n
200202
$text =~ s/([\(\)\$])/ $1 /g if ($space_for_parse);
201203

share/goodie/calculator/style.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.zci--answer .zci--calculator {
2+
font-size: 1.5em;
3+
font-weight: 300;
4+
padding-top: .25em;
5+
padding-bottom: .25em;
6+
/* color: #393939; */
7+
}

0 commit comments

Comments
 (0)