Missed some warn -> warning conversion
[rbot] / data / rbot / plugins / math.rb
1 class MathPlugin < Plugin
2   @@digits = {
3      "first" => "1",
4      "second" => "2",
5      "third" => "3",
6      "fourth" => "4",
7      "fifth" => "5",
8      "sixth" => "6",
9      "seventh" => "7",
10      "eighth" => "8",
11      "ninth" => "9",
12      "tenth" => "10",
13      "one" => "1",
14      "two" => "2",
15      "three" => "3",
16      "four" => "4",
17      "five" => "5",
18      "six" => "6",
19      "seven" => "7",
20      "eight" => "8",
21      "nine" => "9",
22      "ten" => "10"
23   };
24
25   def name
26     "math"
27   end
28   def help(plugin, topic="")
29     "math <expression>, evaluate mathematical expression"
30   end
31   def privmsg(m)
32     unless(m.params)
33       m.reply "incorrect usage: " + help(m.plugin)
34       return
35     end
36
37     expr = m.params.dup
38     @@digits.each {|k,v|
39       expr.gsub!(/\b#{k}\b/, v)
40     }
41
42     while expr =~ /(exp ([\w\d]+))/
43       exp = $1
44       val = Math.exp($2).to_s
45       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
46     end
47     
48     while expr =~ /^\s*(dec2hex\s*(\d+))\s*\?*/
49       exp = $1
50       val = sprintf("%x", $2)
51       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
52     end
53
54     expr.gsub(/\be\b/, Math.exp(1).to_s)
55
56     while expr =~ /(log\s*((\d+\.?\d*)|\d*\.?\d+))\s*/
57       exp = $1
58       res = $2
59       
60       if res == 0
61         val = "Infinity"
62       else
63         val = Math.log(res).to_s
64       end
65       
66       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
67     end
68
69     while expr =~ /(bin2dec ([01]+))/
70       exp = $1
71       val = join('', unpack('B*', pack('N', $2)))
72       val.gsub!(/^0+/, "")
73       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
74     end
75
76     expr.gsub!(/ to the power of /, " ** ")
77     expr.gsub!(/ to the /, " ** ")
78     expr.gsub!(/\btimes\b/, "*")
79     expr.gsub!(/\bdiv(ided by)? /, "/ ")
80     expr.gsub!(/\bover /, "/ ")
81     expr.gsub!(/\bsquared/, "**2 ")
82     expr.gsub!(/\bcubed/, "**3 ")
83     expr.gsub!(/\bto\s+(\d+)(r?st|nd|rd|th)?( power)?/, "**\1 ")
84     expr.gsub!(/\bpercent of/, "*0.01*")
85     expr.gsub!(/\bpercent/, "*0.01")
86     expr.gsub!(/\% of\b/, "*0.01*")
87     expr.gsub!(/\%/, "*0.01")
88     expr.gsub!(/\bsquare root of (\d+)/, "\1 ** 0.5 ")
89     expr.gsub!(/\bcubed? root of (\d+)/, "\1 **(1.0/3.0) ")
90     expr.gsub!(/ of /, " * ")
91     expr.gsub!(/(bit(-| )?)?xor(\'?e?d( with))?/, "^")
92     expr.gsub!(/(bit(-| )?)?or(\'?e?d( with))?/, "|")
93     expr.gsub!(/bit(-| )?and(\'?e?d( with))?/, "& ")
94     expr.gsub!(/(plus|and)/, "+")
95
96     if (expr =~ /^\s*[-\d*+\s()\/^\.\|\&\*\!]+\s*$/ &&
97        expr !~ /^\s*\(?\d+\.?\d*\)?\s*$/ &&
98        expr !~ /^\s*$/ &&
99        expr !~ /^\s*[( )]+\s*$/)
100
101        begin
102          debug "evaluating expression \"#{expr}\""
103          answer = eval(expr)
104          if answer =~ /^[-+\de\.]+$/
105            answer = sprintf("%1.12f", answer)
106            answer.gsub!(/\.?0+$/, "")
107            answer.gsub!(/(\.\d+)000\d+/, '\1')
108            if (answer.length > 30)
109              answer = "a number with >30 digits..."
110            end
111          end
112          m.reply answer
113        rescue Exception => e
114          error "couldn't evaluate expression \"#{m.params}\": #{e.inspect}"
115          m.reply "illegal expression \"#{m.params}\""
116          return
117        end
118     else
119       m.reply "illegal expression \"#{m.params}\""
120       return
121     end
122   end
123 end
124 plugin = MathPlugin.new
125 plugin.register("math")
126 plugin.register("maths")