Permalink
Browse files

Resistor color code calculator.

Type in a query like "1.58m ohms" and get back the color codes in
an electronics resistor "brown green gray yellow".
  • Loading branch information...
Joe Walnes authored and majuscule committed Nov 2, 2012
1 parent 67ef3d5 commit 4bb042849434a25e60917197d33b1721d5fbcf6c
Showing with 241 additions and 0 deletions.
  1. +139 −0 lib/DDG/Goodie/ResistorColors.pm
  2. +102 −0 t/ResistorColors.t
@@ -0,0 +1,139 @@
+package DDG::Goodie::ResistorColors;
+# ABSTRACT: Convert a resistor value into color codes.
+# e.g. "4.7K ohms" -> "yellow purple black brown"
+
+# Ideas for future improvements
+# - reverse query (e.g. "yellow purple black brown" -> "4.7K ohms"
+# - show surface mount resistor markings
+
+use DDG::Goodie;
+use Math::Round;
+use POSIX qw(abs floor log10 pow);
+
+attribution twitter => 'joewalnes',
+ web => ['http://joewalnes.com', 'joewalnes.com'],
+ email => ['joe@walnes.com', 'Joe Walnes'];
+
+# \x{2126} is the unicode ohm symbol
+triggers query_nowhitespace => qr/^(.*)(ohm|ohms|\x{2126})/i;
+
+zci is_cached => 1;
+zci answer_type => 'resistor_colors';
+
+# These hex codes came from
+# http://en.wikipedia.org/wiki/Electronic_color_code
+my %digits_to_colors = (
+ -1 => { hex => '#cfb53b', label => '#000', name => 'gold' },
+ -2 => { hex => '#c0c0c0', label => '#000', name => 'silver' },
+ 0 => { hex => '#000000', label => '#fff', name => 'black' },
+ 1 => { hex => '#964b00', label => '#fff', name => 'brown' },
+ 2 => { hex => '#ff0000', label => '#fff', name => 'red' },
+ 3 => { hex => '#ffa500', label => '#000', name => 'orange' },
+ 4 => { hex => '#ffff00', label => '#000', name => 'yellow' },
+ 5 => { hex => '#9acd32', label => '#000', name => 'green' },
+ 6 => { hex => '#6495ed', label => '#000', name => 'blue' },
+ 7 => { hex => '#ee82ee', label => '#000', name => 'purple' },
+ 8 => { hex => '#a0a0a0', label => '#000', name => 'gray' },
+ 9 => { hex => '#ffffff', label => '#000', name => 'white' },
+);
+
+handle matches => sub {
+ my $input = shift;
+ my $value = parse_value($input);
+ if (defined $value) {
+ $value = round_to_significant_places($value, 3);
+ my @digits = number_to_color_digits($value);
+ return render($value, \@digits);
+ }
+ return;
+};
+
+# Given ohm rating as string (e.g. 3.2m or 3M2), return
+# integer value (e.g. 3200000).
+sub parse_value {
+ my $input = shift;
+ if ($input =~ m/^(\d+)(\.(\d+))?([km])?$/i) {
+ # e.g. 123, 1.23, 1M, 1.23M
+ my $multiplier = 1;
+ if ($4) {
+ $multiplier = 1000 if $4 eq 'k' || $4 eq 'K';
+ $multiplier = 1000000 if $4 eq 'm' || $4 eq 'M';
+ }
+ return ("$1." . ($3 || 0)) * $multiplier;
+ } elsif ($input =~ m/^(\d+)([km])(\d+)$/i) {
+ # e.g. 12K3
+ my $multiplier = 1;
+ $multiplier = 1000 if $2 eq 'k' || $2 eq 'K';
+ $multiplier = 1000000 if $2 eq 'm' || $2 eq 'M';
+ return ("$1." . ($3 || 0)) * $multiplier;
+ } else {
+ return;
+ }
+};
+
+# Round a value to significant places.
+# e.g. (123456789, 3) -> 123000000)
+# (0.0045678, 3) -> 0.00457)
+sub round_to_significant_places {
+ my $value = shift;
+ my $significant = shift;
+ if ($value == 0) {
+ return 0;
+ }
+ return nearest(pow(10, int(floor(log10(abs($value))) - ($significant - 1))), $value);
+}
+
+# Given ohm rating as integer (e.g. 470000), return
+# array of color digits (e.g. 4, 7, 0, 3). See %digits_to_colors.
+sub number_to_color_digits {
+ my $value = shift;
+ return (0, 0, 0, 0) if $value == 0; # special case
+ my @value_digits = split(//, $value * 100);
+ return (
+ $value_digits[0] || 0,
+ $value_digits[1] || 0,
+ $value_digits[2] || 0,
+ scalar(@value_digits) - 5);
+};
+
+# Given a numeric value, format it like '3.2M' etc.
+sub format_value {
+ my $value = shift;
+ if ($value >= 1000000) {
+ return ($value / 1000000) . 'M';
+ } elsif ($value >= 1000) {
+ return ($value / 1000) . 'K';
+ } else {
+ return $value;
+ }
+};
+
+# Given array of color digits (e.g. 3, 3, 1, 4),
+# return text and html representation of colors.
+sub render {
+ my ($value, $digits) = @_;
+ my $formatted_value = format_value($value);
+ my $text = "$formatted_value\x{2126} resistor colors:";
+ my $html = "<b>$formatted_value&#x2126; resistor colors:</b>";
+
+ foreach my $digit (@$digits) {
+ if (exists $digits_to_colors{$digit}) {
+ my $name = $digits_to_colors{$digit}{name};
+ my $hex = $digits_to_colors{$digit}{hex};
+ my $label = $digits_to_colors{$digit}{label};
+ my $style = "display:inline-block;background-color:$hex;color:$label;"
+ . "border:1px solid #c8c8c8;margin-top:-1px;padding:0px 4px;"
+ . "border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;";
+ $text .= " $name";
+ $html .= " <span style='$style'>$name</span>";
+ } else {
+ return;
+ }
+ }
+ $html .= "<br/><span style='font-size:92.8%;color:#333'>Followed by a gap and tolerance color "
+ . "[<a href='http://resisto.rs/#$formatted_value'>more at resisto.rs</a>]</span>";
+
+ return $text, html => $html;
+};
+
+1;
View
@@ -0,0 +1,102 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Test::More;
+use DDG::Test::Goodie;
+
+zci answer_type => "resistor_colors";
+zci is_cached => 1;
+
+ddg_goodie_test(
+ [qw(
+ DDG::Goodie::ResistorColors
+ )],
+
+ # Check trigger kicks in.
+ "330 ohms" => test_zci("330\x{2126} resistor colors: orange orange black black", html => qr/./),
+ "330 ohm" => test_zci("330\x{2126} resistor colors: orange orange black black", html => qr/./),
+ "330 \x{2126}" => test_zci("330\x{2126} resistor colors: orange orange black black", html => qr/./),
+ "330ohms" => test_zci("330\x{2126} resistor colors: orange orange black black", html => qr/./),
+ "330ohm" => test_zci("330\x{2126} resistor colors: orange orange black black", html => qr/./),
+ "330\x{2126}" => test_zci("330\x{2126} resistor colors: orange orange black black", html => qr/./),
+
+ # Various multipliers
+ "472000 ohms" => test_zci("472K\x{2126} resistor colors: yellow purple red orange", html => qr/./),
+ "400000 ohms" => test_zci("400K\x{2126} resistor colors: yellow black black orange", html => qr/./),
+ "12300 ohms" => test_zci("12.3K\x{2126} resistor colors: brown red orange red", html => qr/./),
+
+ # Rounding
+ "1.2345 ohms" => test_zci("1.23\x{2126} resistor colors: brown red orange silver", html => qr/./),
+ "1.2355 ohms" => test_zci("1.24\x{2126} resistor colors: brown red yellow silver", html => qr/./),
+ "12.345 ohms" => test_zci("12.3\x{2126} resistor colors: brown red orange gold", html => qr/./),
+ "12.355 ohms" => test_zci("12.4\x{2126} resistor colors: brown red yellow gold", html => qr/./),
+ "123.45 ohms" => test_zci("123\x{2126} resistor colors: brown red orange black", html => qr/./),
+ "123.55 ohms" => test_zci("124\x{2126} resistor colors: brown red yellow black", html => qr/./),
+ "1234.5 ohms" => test_zci("1.23K\x{2126} resistor colors: brown red orange brown", html => qr/./),
+ "1235.5 ohms" => test_zci("1.24K\x{2126} resistor colors: brown red yellow brown", html => qr/./),
+ "12345 ohms" => test_zci("12.3K\x{2126} resistor colors: brown red orange red", html => qr/./),
+ "12355 ohms" => test_zci("12.4K\x{2126} resistor colors: brown red yellow red", html => qr/./),
+ "123450 ohms" => test_zci("123K\x{2126} resistor colors: brown red orange orange", html => qr/./),
+ "123550 ohms" => test_zci("124K\x{2126} resistor colors: brown red yellow orange", html => qr/./),
+ "1234500 ohms" => test_zci("1.23M\x{2126} resistor colors: brown red orange yellow", html => qr/./),
+ "1235500 ohms" => test_zci("1.24M\x{2126} resistor colors: brown red yellow yellow", html => qr/./),
+ "12345000 ohms" => test_zci("12.3M\x{2126} resistor colors: brown red orange green", html => qr/./),
+ "12355000 ohms" => test_zci("12.4M\x{2126} resistor colors: brown red yellow green", html => qr/./),
+ "123450000 ohms" => test_zci("123M\x{2126} resistor colors: brown red orange blue", html => qr/./),
+ "123550000 ohms" => test_zci("124M\x{2126} resistor colors: brown red yellow blue", html => qr/./),
+ "1234500000 ohms" => test_zci("1230M\x{2126} resistor colors: brown red orange purple", html => qr/./),
+ "1235500000 ohms" => test_zci("1240M\x{2126} resistor colors: brown red yellow purple", html => qr/./),
+
+ # kilo and mega multipliers
+ "27kohm" => test_zci("27K\x{2126} resistor colors: red purple black red", html => qr/./),
+ "27Kohm" => test_zci("27K\x{2126} resistor colors: red purple black red", html => qr/./),
+ "27 K ohm" => test_zci("27K\x{2126} resistor colors: red purple black red", html => qr/./),
+ "4K2 ohm" => test_zci("4.2K\x{2126} resistor colors: yellow red black brown", html => qr/./),
+ "4.2K ohm" => test_zci("4.2K\x{2126} resistor colors: yellow red black brown", html => qr/./),
+
+ # Decimal points
+ "2.9ohm" => test_zci("2.9\x{2126} resistor colors: red white black silver", html => qr/./),
+
+ # Negative multipliers
+ "1 ohm" => test_zci("1\x{2126} resistor colors: brown black black silver", html => qr/./),
+ "29 ohms" => test_zci("29\x{2126} resistor colors: red white black gold", html => qr/./),
+
+ # Zero special case
+ "0 ohms" => test_zci("0\x{2126} resistor colors: black black black black", html => qr/./),
+
+ # Range
+ "999000M ohms" => test_zci("999000M\x{2126} resistor colors: white white white white", html => qr/./),
+ "999500M ohms" => undef,
+ "1.1 ohms" => test_zci("1.1\x{2126} resistor colors: brown brown black silver", html => qr/./),
+ "1 ohms" => test_zci("1\x{2126} resistor colors: brown black black silver", html => qr/./),
+ "0.9 ohms" => undef,
+ "-10 ohms" => undef,
+
+ # Don't trigger
+ "343.3.3.3 ohms" => undef,
+ "chicken ohms" => undef,
+ "what is ohms law" => undef,
+ "ohm ma darling" => undef,
+
+ # Check the HTML. Just once.
+ "1.58m ohm" => test_zci("1.58M\x{2126} resistor colors: brown green gray yellow", html =>
+ "<b>1.58M&#x2126; resistor colors:</b> "
+ . "<span style='display:inline-block;background-color:#964b00;"
+ . "color:#fff;border:1px solid #c8c8c8;margin-top:-1px;padding:0px 4px;border-radius:4px;"
+ . "-webkit-border-radius:4px;-moz-border-radius:4px;'>brown</span> "
+ . "<span style='display:inline-block;background-color:#9acd32;"
+ . "color:#000;border:1px solid #c8c8c8;margin-top:-1px;padding:0px 4px;border-radius:4px;"
+ . "-webkit-border-radius:4px;-moz-border-radius:4px;'>green</span> "
+ . "<span style='display:inline-block;background-color:#a0a0a0;"
+ . "color:#000;border:1px solid #c8c8c8;margin-top:-1px;padding:0px 4px;border-radius:4px;"
+ . "-webkit-border-radius:4px;-moz-border-radius:4px;'>gray</span> "
+ . "<span style='display:inline-block;background-color:#ffff00;"
+ . "color:#000;border:1px solid #c8c8c8;margin-top:-1px;padding:0px 4px;border-radius:4px;"
+ . "-webkit-border-radius:4px;-moz-border-radius:4px;'>yellow</span>"
+ . "<br/><span style='font-size:92.8%;color:#333'>Followed by a gap and tolerance color "
+ . "[<a href='http://resisto.rs/#1.58M'>more at resisto.rs</a>]</span>"),
+
+);
+
+done_testing;

0 comments on commit 4bb0428

Please sign in to comment.