addons/roller: A capable die roller

This commit is contained in:
Bill Niblock 2021-02-06 22:24:07 -05:00
parent 1a7b4bb970
commit 5938547e05

108
lib/addons/roller.rb Normal file
View file

@ -0,0 +1,108 @@
# frozen_string_literal: true
module Chronicle
module Matrix
# Roll dice and get the results
#
# @param message [hash] The message data from Matrix
def handle_roll(client, message)
msgstr = message.content[:body]
.gsub(/!roll\s*/, '')
.strip
room = client.ensure_room(message.room_id)
res = Roller.roll(msgstr)
final_msg = res.reduce("") { |x,y| x+y+"\n" }
room.send_notice(final_msg)
end
module Roller
# Solve an arithmatic forumla from a string
#
# @param string [String] The string representation of the formula
# @return Integer of the solution
def self.solve(string)
formatted = string.gsub(/\s+/, '')
formatted = formatted.gsub(/\[[\d,]*\]/) do |a|
a.scan(/\d*/).reduce(0) { |x, y| x + y.to_i }
end
if formatted.match(/\(.*\)/)
formatted = formatted.sub(/\(.*\)/) do |m|
solve(m[1..-2])
end
solve(formatted)
elsif formatted.match(/\d+\*\d+/)
formatted = formatted.sub(/\d+\*\d+/) do |m|
m.split('*').reduce(1) { |x, y| x * y.to_i }
end
solve(formatted)
elsif formatted.match(/\d+\/\d+/)
formatted = formatted.sub(/\d*\/\d*/) do |m|
m.split('/').reduce { |x, y| x.to_i / y.to_i }
end
solve(formatted)
elsif formatted.match(/\d+\+\d+/)
formatted = formatted.sub(/\d+\+\d+/) do |m|
m.split('+').reduce(0) { |x, y| x + y.to_i }
end
solve(formatted)
elsif formatted.match(/\d+\-\d+/)
formatted = formatted.sub(/\d+\-\d+/) do |m|
m.split('-').reduce { |x, y| x.to_i + -(y.to_i) }
end
solve(formatted)
else
formatted.to_i
end
end
# Pretty-print a result
#
# @param func [String] The name of the function
# @param orig [String] The original request
# @param string [String] The processed request
# @param res [String] The result of the process
# @return String re-formatted
def self.pretty(func, orig, string, res)
orig.gsub!(/[\+\-*\/]/) { |s| " #{s} " }
string.gsub!(/[\+\-*\/]/) { |s| " #{s} " }
"#{func.capitalize}: #{orig} (#{string}) ==> #{res}"
end
# Roll dice
#
# @param string [String] The string representation of the dice roll
# example: 2d4+6
# @return Array of the message and the result
def self.roll(string)
results = []
string.gsub(/\s+/,'').split(',').each do |roll|
orig = roll
res = roll.gsub(/[0-9]*d[0-9]*/) do |d|
num,sides = d.split('d')
num = num.empty? ? '1' : num
Array.new(num.to_i.abs) { Random.new.rand(sides.to_i) + 1 }
end
results << pretty("Roll", orig, res, solve(res))
end
results
end
end
end
end