module QuakeRoulette
Constants
- DEFAULT_BET
- PAYOUT_MULTIPLIER
- PLUGIN
- STYLE_LOSE
- STYLE_TITLE
- STYLE_WIN
Public Instance Methods
Source
# File lib/quake_roulette.rb, line 67 def clear_bets(network:, channel:, store: RabbotDb) GameStore.clear(plugin: PLUGIN, network: network, channel: channel, store: store) end
Source
# File lib/quake_roulette.rb, line 132 def find_settling_event(events, known_ids) known = Array(known_ids) events.find { |event| !known.include?(event[:id]) } end
Source
# File lib/quake_roulette.rb, line 115 def format_status(network:, channel:, store: RabbotDb) state = load_bets(network: network, channel: channel, store: store) bets = state["bets"] || {} lines = [ IrcFormat.report_header(tag: "QUAKE", title: "Richter Roulette", style: STYLE_TITLE) ] if bets.empty? lines << "No pending bets." else bets.each_value do |bet| lines << "#{bet['user']} โ #{bet['band']} #{bet['amount']} credits" end end lines << IrcFormat.report_footer("USGS ยท AU region") lines.join("\n") end
Source
# File lib/quake_roulette.rb, line 59 def load_bets(network:, channel:, store: RabbotDb) GameStore.load(plugin: PLUGIN, network: network, channel: channel, store: store) || { "bets" => {} } end
Source
# File lib/quake_roulette.rb, line 39 def parse_args(parts) tokens = Array(parts).map(&:to_s) return { error: usage_message } if tokens.empty? if tokens[0].casecmp("status").zero? return { action: :status } end range = parse_band(tokens[0]) return { error: usage_message } unless range amount = DEFAULT_BET amount = tokens[1].to_i if tokens[1]&.match?(/\A\d+\z/) unless Game.valid_amount?(amount) return { error: "Bet must be between #{Game::MIN_BET} and #{Game::MAX_BET} credits." } end { action: :bet, band: tokens[0], range: range, amount: amount } end
Source
# File lib/quake_roulette.rb, line 23 def parse_band(text) band = text.to_s.strip.downcase case band when "2-3", "2", "3" (2.0...3.0) when "3-4", "4" (3.0...4.0) when "4-5", "5" (4.0...5.0) when "5+", "5plus", "6+" (5.0..Float::INFINITY) else nil end end
Source
# File lib/quake_roulette.rb, line 71 def place_bet(user:, band:, range:, amount:, network:, channel:, events:, store: Game.default_store, db_store: RabbotDb) state = load_bets(network: network, channel: channel, store: db_store) key = GameStore.norm_nick(user) return { error: "#{user}, you already have a pending Richter Roulette bet." } if state["bets"][key] balance = Game.balance_for(user, store: store) if balance < amount return { error: "#{user}, you need #{amount} credits (balance: #{balance})." } end Game.deduct_bet(user, amount, store: store) state = state.dup state["bets"] = state["bets"].dup state["bets"][key] = { "user" => user, "band" => band, "range_min" => range.begin, "range_end" => range.end == Float::INFINITY ? nil : range.end, "range_exclude_end" => range.exclude_end?, "amount" => amount, "known_ids" => events.map { |event| event[:id] } } save_bets(network: network, channel: channel, state: state, store: db_store) { message: [ IrcFormat.report_header(tag: "QUAKE", title: "Richter Roulette", style: STYLE_TITLE), "#{user} bet #{band} #{amount} โ waiting for next AU quake", IrcFormat.report_footer("auto-settles on next event") ].join("\n") } end
Source
# File lib/quake_roulette.rb, line 170 def poll_settle(bot, fetch: nil, store: Game.default_store, db_store: RabbotDb) return [] unless bot events = QuakeFeed.fetch_recent(fetch: fetch) messages = [] bot.config.channels.each do |channel_name| network = bot.config.server messages.concat( settle_pending( network: network, channel: channel_name, events: events, store: store, db_store: db_store ) ) end messages rescue StandardError [] end
Source
# File lib/quake_roulette.rb, line 104 def restore_range(bet) min = bet["range_min"].to_f if bet["range_end"].nil? (min..Float::INFINITY) elsif bet["range_exclude_end"] (min...bet["range_end"].to_f) else (min..bet["range_end"].to_f) end end
Source
# File lib/quake_roulette.rb, line 63 def save_bets(network:, channel:, state:, store: RabbotDb) GameStore.save(plugin: PLUGIN, network: network, channel: channel, game: state, store: store) end
Source
# File lib/quake_roulette.rb, line 137 def settle_pending(network:, channel:, events:, store: Game.default_store, db_store: RabbotDb) state = load_bets(network: network, channel: channel, store: db_store) bets = state["bets"] || {} return [] if bets.empty? all_known = bets.values.flat_map { |bet| Array(bet["known_ids"]) }.uniq event = find_settling_event(events, all_known) return [] unless event mag = event[:magnitude].to_f lines = [ IrcFormat.report_header(tag: "QUAKE", title: "Richter Roulette settled", style: STYLE_TITLE), "M#{event[:magnitude]} โ #{event[:place]} โ #{QuakeFeed.format_time(event[:time])}" ] bets.each_value do |bet| range = restore_range(bet) won = range.cover?(mag) user = bet["user"] amount = bet["amount"].to_i winnings = won ? amount * PAYOUT_MULTIPLIER : 0 Game.credit_winnings(user, winnings, store: store) if winnings.positive? balance = Game.balance_for(user, store: store) outcome_style = won ? STYLE_WIN : STYLE_LOSE outcome_word = won ? "WIN" : "LOSS" lines << "#{user} bet #{bet['band']} #{amount} โ #{IrcFormat.decorate(outcome_word, outcome_style)} (balance #{balance})" end clear_bets(network: network, channel: channel, store: db_store) lines << IrcFormat.report_footer("USGS ยท AU region") [{ channel: channel, text: lines.join("\n") }] end
Source
# File lib/quake_roulette.rb, line 19 def usage_message "Usage: !quake roulette <band> [amount] | status โ bands: 2-3, 3-4, 4-5, 5+" end