]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/math.rb
plugin(points): new message parser, see #34
[user/henk/code/ruby/rbot.git] / 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     # ruby doesn't like floating-point values without a 0
43     # in front of them, so find any non-digit followed by
44     # a .<digits> and insert a 0 before the .
45     expr.gsub!(/(\D|^)(\.\d+)/,'\10\2')
46
47     while expr =~ /(exp ([\w\d]+))/
48       exp = $1
49       val = Math.exp($2).to_s
50       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
51     end
52
53     while expr =~ /^\s*(dec2hex\s*(\d+))\s*\?*/
54       exp = $1
55       val = sprintf("%x", $2)
56       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
57     end
58
59     expr.gsub(/\be\b/, Math.exp(1).to_s)
60
61     while expr =~ /(log\s*((\d+\.?\d*)|\d*\.?\d+))\s*/
62       exp = $1
63       res = $2
64
65       if res == 0
66         val = "Infinity"
67       else
68         val = Math.log(res).to_s
69       end
70
71       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
72     end
73
74     while expr =~ /(bin2dec ([01]+))/
75       exp = $1
76       val = join('', unpack('B*', pack('N', $2)))
77       val.gsub!(/^0+/, "")
78       expr.gsub!(/#{Regexp.escape exp}/, "+#{val}")
79     end
80
81     expr.gsub!(/ to the power of /, " ** ")
82     expr.gsub!(/ to the /, " ** ")
83     expr.gsub!(/\btimes\b/, "*")
84     expr.gsub!(/\bdiv(ided by)? /, "/ ")
85     expr.gsub!(/\bover /, "/ ")
86     expr.gsub!(/\bsquared/, "**2 ")
87     expr.gsub!(/\bcubed/, "**3 ")
88     expr.gsub!(/\bto\s+(\d+)(r?st|nd|rd|th)?( power)?/, '**\1 ')
89     expr.gsub!(/\bpercent of/, "*0.01*")
90     expr.gsub!(/\bpercent/, "*0.01")
91     expr.gsub!(/\% of\b/, "*0.01*")
92     expr.gsub!(/\%/, "*0.01")
93     expr.gsub!(/\bsquare root of (\d+(\.\d+)?)/, '\1 ** 0.5 ')
94     expr.gsub!(/\bcubed? root of (\d+(\.\d+)?)/, '\1 **(1.0/3.0) ')
95     expr.gsub!(/ of /, " * ")
96     expr.gsub!(/(bit(-| )?)?xor(\'?e?d( with))?/, "^")
97     expr.gsub!(/(bit(-| )?)?or(\'?e?d( with))?/, "|")
98     expr.gsub!(/bit(-| )?and(\'?e?d( with))?/, "& ")
99     expr.gsub!(/(plus|and)/, "+")
100
101     debug expr
102     if (expr =~ /^\s*[-\d*+\s()\/^\.\|\&\*\!]+\s*$/ &&
103        expr !~ /^\s*\(?\d+\.?\d*\)?\s*$/ &&
104        expr !~ /^\s*$/ &&
105        expr !~ /^\s*[( )]+\s*$/)
106
107        begin
108          debug "evaluating expression \"#{expr}\""
109          answer = eval(expr)
110          if answer =~ /^[-+\de\.]+$/
111            answer = sprintf("%1.12f", answer)
112            answer.gsub!(/\.?0+$/, "")
113            answer.gsub!(/(\.\d+)000\d+/, '\1')
114            if (answer.length > 30)
115              answer = "a number with >30 digits..."
116            end
117          end
118          m.reply answer.to_s
119        rescue Exception => e
120          error e
121          m.reply "illegal expression \"#{m.params}\""
122          return
123        end
124     else
125       m.reply "illegal expression \"#{m.params}\""
126       return
127     end
128   end
129 end
130 plugin = MathPlugin.new
131 plugin.register("math")
132 plugin.register("maths")