diff --git a/lib/DDG/Goodie/Geometry.pm b/lib/DDG/Goodie/Geometry.pm new file mode 100644 index 000000000..66a480954 --- /dev/null +++ b/lib/DDG/Goodie/Geometry.pm @@ -0,0 +1,66 @@ +package DDG::Goodie::Geometry; +# ABSTRACT: Write an abstract here + +# Start at http://docs.duckduckhack.com/walkthroughs/calculation.html if +# you are new to instant answer development + +use DDG::Goodie; +use strict; + + +use YAML::XS 'LoadFile'; +use Data::Dumper; + +zci answer_type => 'geometry'; + +# Caching - http://docs.duckduckhack.com/backend-reference/api-reference.html#caching` +zci is_cached => 1; + +my @keyWords = ('geometry', 'formula', 'volume', 'area', 'surface area', 'perimeter', 'circumference', 'diagonal'); +my @finalWords; +foreach my $word (@keyWords) { + push(@finalWords, $word); + push(@finalWords, $word.' of'); + push(@finalWords, $word.' of a'); +} + +triggers any => @finalWords; + +my ($shapes, $formulas) = LoadFile(share('objectInfo.yml')); + +handle remainder => sub { + + return unless $_; + + my $remainder = lc($_); + + return unless my $shape = $shapes->{$remainder}; + + my %dataFormula; + # Fill dataFormula with values for handlebar to parse + foreach my $key (keys $shape) { + + $dataFormula{$key} = { + 'nameCaps' => ucfirst($key), + 'color' => $formulas->{$key}{'color'}, + 'symbol' => $formulas->{$key}{'symbol'}, + 'html' => $shape->{$key} + }; + + } + + return "plain text response", structured_answer => { + data => { + title => ucfirst($remainder), + formulas => \%dataFormula, + svg => LoadFile(share("svg/$remainder.svg")), + }, + templates => { + group => "text", + options => { + subtitle_content => 'DDH.geometry.subtitle' + } + } + }; +}; +1; diff --git a/share/goodie/geometry/geometry.css b/share/goodie/geometry/geometry.css new file mode 100644 index 000000000..8d8dd8f73 --- /dev/null +++ b/share/goodie/geometry/geometry.css @@ -0,0 +1,93 @@ +.geometry-svg { + fill: transparent; + margin-left: 40px; + max-width: 50%; + height: 175px; +} + +.geometry-svg .stroke { + stroke: black; + stroke-width: 2; + stroke-linejoin: round; +} + +.geometry-svg .stroke.backface { + stroke-width: 1.5; +} + +.geometry-svg .stroke.special { + stroke-dasharray: 5,5; +} + +.geometry-svg .stroke.special.hover { + stroke-dasharray: none; +} + + +.geometry-formulas { + float: left; + font-size: 1.5em; + margin-right: 10px; +} +.geometry-formulas .formula { + margin-bottom: 5px; + overflow: hidden; + clear: left; +} + +.geometry-formulas .formula div { + float: left; +} + +.geometry-formulas .dot{ + width: 14px; + height: 14px; + border-radius: 7px; + opacity: 0.5; + margin: 20px 10px; +} + +.geometry-formulas .hover .dot { + opacity: 1; +} + +.geometry-formulas h4 { + color: #999; + font-size: 12px; + padding-bottom: 0; + margin-bottom: -3px; +} + +.geometry-formulas sup { + font-size: 0.6em; +} + +.geometry-formulas small { + color: #808080; + font-size: 0.8em; +} + +#geometry--goodie .volume.hover { + fill: #DE5833; + opacity: 1; +} +#geometry--goodie .area.hover { + fill: #F1A031; + opacity: 1; +} +#geometry--goodie .surface.hover { + fill: #F1A031; + opacity: 1; +} +#geometry--goodie .perimeter.hover { + stroke: #5B9E4D; + opacity: 1; +} +#geometry--goodie .circumference.hover { + stroke: #5B9E4D; + opacity: 1; +} +#geometry--goodie .diagonal.hover { + stroke: #4495D4; + opacity: 1; +} \ No newline at end of file diff --git a/share/goodie/geometry/geometry.js b/share/goodie/geometry/geometry.js new file mode 100644 index 000000000..3a803cfa8 --- /dev/null +++ b/share/goodie/geometry/geometry.js @@ -0,0 +1,36 @@ +DDH.geometry_goodie = DDH.geometry_goodie || {}; + +(function(DDH) { + "use strict"; + + DDH.geometry_goodie.build = function(ops) { + return { + onShow: function() { + var formulaSelector = '.geometry-formulas .formula .dot'; + var svgSelector = '.geometry-svg *'; + + $(svgSelector + ',' + formulaSelector).hover( + function() { + // Get Current geoemetry type + var datatype = $( this ).data('type'); + // Add Hover to Dot + $('#geometry--goodie .'+ datatype).addClass( "hover" ); + // Add Hover to SVG + // JQuery 1.1 cant select SVGs by normal selectors + var svg = document.querySelector(".geometry-svg ." + datatype); + svg.classList.add("hover"); + + + }, function() { + // Remove hovers when not hovering + var datatype = $( this ).data('type'); + $('#geometry--goodie .' + datatype).removeClass( "hover" ); + + var svg = document.querySelector(".geometry-svg ." + datatype); + svg.classList.remove("hover"); + } + ); + } + }; + }; +})(DDH); \ No newline at end of file diff --git a/share/goodie/geometry/objectInfo.yml b/share/goodie/geometry/objectInfo.yml new file mode 100644 index 000000000..29bf59d19 --- /dev/null +++ b/share/goodie/geometry/objectInfo.yml @@ -0,0 +1,45 @@ +--- +square: + area: a2 + perimeter: 4a + diagonal: a√2 +rectangle: + area: ab + perimeter: 2(a+b) + diagonal: "√(a2+b2)" +equilateral triangle: + area: (a2*√3)/4 + perimeter: 3a +circle: + area: "πr2" + circumference: 2πr +sphere: + volume: 4/3πr3 + surface: 4πr2 +cube: + volume: a3 + surface: 6a2 + diagonal: a√3 +cuboid: + volume: abc + surface: 2(ab + ac + bc) + diagonal: "√(a2 + b2 + c2)" +--- +volume: + symbol: "V" + color: "#DE5833" +area: + symbol: "A" + color: "#F1A031" +surface: + symbol: "S" + color: "#F1A031" +perimeter: + symbol: "u" + color: "#5B9E4D" +circumference: + symbol: "u" + color: "#5B9E4D" +diagonal: + symbol: "e" + color: "#4495D4" \ No newline at end of file diff --git a/share/goodie/geometry/subtitle.handlebars b/share/goodie/geometry/subtitle.handlebars new file mode 100644 index 000000000..6b6f87b35 --- /dev/null +++ b/share/goodie/geometry/subtitle.handlebars @@ -0,0 +1,29 @@ +
+
+ {{#each formulas}} +
+
+
+

{{nameCaps}}

+ {{symbol}} = {{{html}}} + {{#if result}} + = {{result}} + {{/if}} +
+
+ {{/each}} + {{#if parameter}} + + Assuming + {{#each parameter}} + {{symbol}} = {{value}} + {{/each}} + + {{/if}} +
+ {{#if svg}} + + {{{svg}}} + + {{/if}} +
diff --git a/share/goodie/geometry/svg/circle.svg b/share/goodie/geometry/svg/circle.svg new file mode 100644 index 000000000..bf2f11446 --- /dev/null +++ b/share/goodie/geometry/svg/circle.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/goodie/geometry/svg/cube.svg b/share/goodie/geometry/svg/cube.svg new file mode 100644 index 000000000..fc426b8a4 --- /dev/null +++ b/share/goodie/geometry/svg/cube.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/share/goodie/geometry/svg/cuboid.svg b/share/goodie/geometry/svg/cuboid.svg new file mode 100644 index 000000000..fdef78e22 --- /dev/null +++ b/share/goodie/geometry/svg/cuboid.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/share/goodie/geometry/svg/equilateral triangle.svg b/share/goodie/geometry/svg/equilateral triangle.svg new file mode 100644 index 000000000..477b04cca --- /dev/null +++ b/share/goodie/geometry/svg/equilateral triangle.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/share/goodie/geometry/svg/rectangle.svg b/share/goodie/geometry/svg/rectangle.svg new file mode 100644 index 000000000..d1ec0cea0 --- /dev/null +++ b/share/goodie/geometry/svg/rectangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/share/goodie/geometry/svg/sphere.svg b/share/goodie/geometry/svg/sphere.svg new file mode 100644 index 000000000..f91889376 --- /dev/null +++ b/share/goodie/geometry/svg/sphere.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/share/goodie/geometry/svg/square.svg b/share/goodie/geometry/svg/square.svg new file mode 100644 index 000000000..a47693430 --- /dev/null +++ b/share/goodie/geometry/svg/square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/t/Geometry.t b/t/Geometry.t new file mode 100644 index 000000000..625550b60 --- /dev/null +++ b/t/Geometry.t @@ -0,0 +1,77 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Test::More; +use Test::Deep; +use DDG::Test::Goodie; +use utf8; + +zci answer_type => "geometry"; +zci is_cached => 1; + +# Build a structured answer that should match the response from the Perl file +sub build_structured_answer { + my ( $title, $formulas, $svg ) = @_; + + return "plain text response", structured_answer => { + data => { + title => ucfirst($title), + formulas => $formulas, + svg => $svg, + }, + + templates => { + group => "text", + options => { + subtitle_content => 'DDH.geometry.subtitle' + } + } + }; +} + +# Use this to build expected results for your tests. +sub build_test { test_zci( build_structured_answer(@_) ) } + +ddg_goodie_test( + [qw( DDG::Goodie::Geometry )], + + # First Param = Name of object + # Second Param = Array of formula objects for expected object + # Third Param = SVG of expected object + + 'calc square' => build_test( + 'square', + { + area => { color => "#F1A031", html => "a2", nameCaps => "Area", symbol => "A" }, + diagonal => { color => "#4495D4", html => "a√2", nameCaps => "Diagonal", symbol => "e" }, + perimeter => { color => "#5B9E4D", html => "4a", nameCaps => "Perimeter", symbol => "u" } + }, + ' ', + ), + + 'area of a square' => build_test( + 'square', + { + area => { color => "#F1A031", html => "a2", nameCaps => "Area", symbol => "A" }, + diagonal => { color => "#4495D4", html => "a√2", nameCaps => "Diagonal", symbol => "e" }, + perimeter => { color => "#5B9E4D", html => "4a", nameCaps => "Perimeter", symbol => "u" } + }, + ' ', + ), + 'volume of sphere' => build_test( + 'sphere', + { + volume => { color => "#DE5833", html => "4/3πr3", nameCaps => "Volume", symbol => "V" }, + surface => { color => "#F1A031", html => "4πr2", nameCaps => "Surface", symbol => "S" }, + }, + ' ', + ), + # Does Not match to + 'calc banana' => undef, + 'formula of shirt' => undef, + '' => undef, + ' ' => undef, +); + +done_testing; \ No newline at end of file