calc.rb 5.39 KB
Newer Older
Cool Fire's avatar
Cool Fire committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#!/usr/bin/env ruby

# Plugin to do some math
class Calc

	# This method is called when the plugin is first loaded
	def initialize( status, config, output, irc, timer )
		@status  = status
		@config  = config
		@output  = output
		@irc     = irc
		@timer   = timer
	end

	# Default method, called when no argument is given (optional, but highly recomended)
Cool Fire's avatar
Cool Fire committed
16
	def main( _nick, _user, _host, from, _msg, arguments, _con )
Cool Fire's avatar
Cool Fire committed
17 18

		# Check for invalid input
19
		if( arguments =~ /^([0-9]|\.|,|\+|-|\*|\^|\/|%|\(|\)|E|pi|acos|acosh|asin|asinh|atan|atanh|cbrt|cos|cosh|erf|erfc|exp|frexp|gamma|hypot|ldexp|lgamma|log|sin|sinh|sqrt|tan|tanh| )+$/i )
Cool Fire's avatar
Cool Fire committed
20 21

			# Check for stuff from the Math package
Cool Fire's avatar
Cool Fire committed
22
			arguments.gsub!(/\^/,           "**")
23
			arguments.gsub!(/E/,            "Math::E") # lowercase e clashes with function names
Cool Fire's avatar
Cool Fire committed
24 25 26 27 28 29 30 31 32 33 34 35 36
			arguments.gsub!(/pi/i,          "Math::PI")
			arguments.gsub!(/acos\(/i,      "Math.acos(")
			arguments.gsub!(/acosh\(/i,     "Math.acosh(")
			arguments.gsub!(/asin\(/i,      "Math.asin(")
			arguments.gsub!(/asinh\(/i,     "Math.asinh(")
			arguments.gsub!(/atan\(/i,      "Math.atan(")
			arguments.gsub!(/atan2\(/i,     "Math.atan2(")
			arguments.gsub!(/atanh\(/i,     "Math.atanh(")
			arguments.gsub!(/cbrt\(/i,      "Math.cbrt(")
			arguments.gsub!(/cos\(/i,       "Math.cos(")
			arguments.gsub!(/cosh\(/i,      "Math.cosh(")
			arguments.gsub!(/erfc\(/i,      "Math.erfc(")
			arguments.gsub!(/erf\(/i,       "Math.erf(")
37 38
			arguments.gsub!(/(exp|frexp)\(/i,    'exp(' => "Math.exp(", 'frexp(' => "Math.frexp(")
			arguments.gsub!(/(gamma|lgamma)\(/i, 'gamma(' => "Math.gamma(", 'lgamma(' => "Math.lgamma(")
Cool Fire's avatar
Cool Fire committed
39 40 41 42 43 44 45 46 47 48
			arguments.gsub!(/hypot\(/i,     "Math.hypot(")
			arguments.gsub!(/ldexp\(/i,     "Math.ldexp(")
			arguments.gsub!(/log\(/i,       "Math.log(")
			arguments.gsub!(/log10\(/i,     "Math.log10(")
			arguments.gsub!(/log2\(/i,      "Math.log2(")
			arguments.gsub!(/sin\(/i,       "Math.sin(")
			arguments.gsub!(/sinh\(/i,      "Math.sinh(")
			arguments.gsub!(/sqrt\(/i,      "Math.sqrt(")
			arguments.gsub!(/tan\(/i,       "Math.tan(")
			arguments.gsub!(/tanh\(/i,      "Math.tanh(")
Cool Fire's avatar
Cool Fire committed
49 50 51

			# Try the calculation
			begin
52 53 54 55 56 57
				# Drop thread priority in case the calculation takes really long
				if( @status.threads && @config.threads )
					Thread.current.priority = -2
				end

				# Do the actual calculation
Cool Fire's avatar
Cool Fire committed
58
				result = eval( arguments )
Cool Fire's avatar
Cool Fire committed
59
				result = result.to_s
60

61
				# Truncate results too long for IRC
Cool Fire's avatar
Cool Fire committed
62
				if( result.length > 360 )
63 64
					result = result[0,360]
					result[360] = "..."
65
				end
Cool Fire's avatar
Cool Fire committed
66
			rescue Exception => e
67 68
				e = e.to_s.split("\n")
				@irc.message( from, "Does not seem to be a valid expression. (#{e[0]})" )
Cool Fire's avatar
Cool Fire committed
69 70 71 72 73 74 75 76 77 78 79
				return
			end

			# Return result
			@irc.message( from, "Result: #{result}" )
		else
			@irc.message( from, "Expression contains illegal characters." )			
		end
	end

	# Function to send help about this plugin (Can also be called by the help plugin.)
Cool Fire's avatar
Cool Fire committed
80
	def help( nick, _user, _host, _from, _msg, _arguments, con )
Cool Fire's avatar
Cool Fire committed
81 82 83 84 85 86 87 88 89 90 91 92
		help = [
			"This plugin allows you to do some math.",
			"  calc 5*5         - Do some calculation.",
			"",
			" Allowed operators/functions/constants:",
			"  0..9              numbers. You'll need some.",
			"  .                 decimal point.",
			"  +                 add",
			"  -                 subtract",
			"  *                 multiply",
			"  /                 divide",
			"  %                 Modulo",
Cool Fire's avatar
Cool Fire committed
93
			"  ** or ^           Exponent",
Cool Fire's avatar
Cool Fire committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
			"  ()                parentheses",
			"  E                 e (constant)",
			"  PI                pi (constant)",
			"  acos(x)           arc cosine of x. Returns 0..PI.",
			"  acosh(x)          inverse hyperbolic cosine of x.",
			"  asin(x)           arc sine of x. Returns -{PI/2} .. {PI/2}.",
			"  asinh(x)          inverse hyperbolic sine of x.",
			"  atan(x)           arc tangent of x. Returns -{PI/2} .. {PI/2}.",
			"  atan2(y, x)       arc tangent given y and x. Returns -PI..PI.",
			"  atanh(x)          inverse hyperbolic tangent of x.",
			"  cbrt(numeric)     cube root of numeric.",
			"  cos(x)            cosine of x (expressed in radians). Returns -1..1.",
			"  cosh(x)           hyperbolic cosine of x (expressed in radians).",
			"  erf(x)            error function of x.",
			"  erfc(x)           complementary error function of x.",
			"  exp(x)            e**x.",
			"  frexp(numeric)    Returns a two-element array containing the normalized fraction (a Float) and exponent (a Fixnum) of numeric.",
			"  gamma(x)          gamma function of x.",
			"  hypot(x, y)       sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle with sides x and y.",
			"  ldexp(flt, int)   value of flt*(2**int).",
			"  lgamma(x)         logarithmic gamma of x and the sign of gamma of x.",
			"  log(numeric)      natural logarithm of numeric. If additional second argument is given, it will be the base of logarithm.",
			"  log(numeric,base) same as above.",
			"  log10(numeric)    base 10 logarithm of numeric.",
			"  log2(numeric)     base 2 logarithm of numeric.",
			"  sin(x)            sine of x (expressed in radians). Returns -1..1.",
			"  sinh(x)           hyperbolic sine of x (expressed in radians).",
			"  sqrt(x)           non-negative square root of numeric.",
			"  tan(x)            tangent of x (expressed in radians).",
			"  tanh(x)           hyperbolic tangent of x (expressed in radians)."
		]

		# Print out help
		help.each do |line|
			if( con )
				@output.c( line + "\n" )
			else
				@irc.notice( nick, line )
			end
		end
	end
end