class Wheel
Constants
- DEFAULT_SEGMENTS
- DISPLAY_SLICES
- MAX_LABEL_LENGTH
- MAX_SEGMENTS
- MIN_SEGMENTS
- PHRASE_BOX_WIDTH
- POINTER_MARK
- POINTER_SLOT
- SLICE_EMPTY
- SLICE_WINNER
Public Class Methods
Source
# File plugins/wheel.rb, line 90 def self.add_segment(channel, label, store: default_store) segments = segments_for(channel, store: store) if segments.map(&:downcase).include?(label.downcase) return { error: "That segment is already on the wheel." } end if segments.length >= MAX_SEGMENTS return { error: "The wheel is full (#{MAX_SEGMENTS} segments max)." } end updated = segments + [label] set_segments(channel, updated, store: store) { added: true, segments: updated, label: label } end
Source
# File plugins/wheel.rb, line 115 def self.build_slice_ring(index, segment_count, display_slices: DISPLAY_SLICES) winner_slot = winning_display_slice(index, segment_count, display_slices: display_slices) ring = Array.new(display_slices, SLICE_EMPTY) ring[winner_slot] = SLICE_WINNER ring end
Source
# File plugins/wheel.rb, line 15 def self.command_pattern /wheel(?: (.+))?$/i end
Source
# File plugins/wheel.rb, line 146 def self.format_phrase_box(phrase, width: PHRASE_BOX_WIDTH) label = truncate_label(phrase, max_length: width - 2) inner = label.center(width) border = "-" * width [ "+#{border}+", "|#{inner}|", "+#{border}+" ] end
Source
# File plugins/wheel.rb, line 134 def self.format_pointer_line pointer = "#{' ' * POINTER_SLOT}#{POINTER_MARK}" "#{STYLE_POINTER}#{pointer}#{IRC_RESET}" end
Source
# File plugins/wheel.rb, line 127 def self.format_rotated_ring(index, segment_count, display_slices: DISPLAY_SLICES) ring = build_slice_ring(index, segment_count, display_slices: display_slices) winner_slot = winning_display_slice(index, segment_count, display_slices: display_slices) ring.rotate!(winner_slot - POINTER_SLOT) "#{STYLE_WHEEL}#{ring.join}#{IRC_RESET}" end
Source
# File plugins/wheel.rb, line 171 def self.format_segment_list(segments) lines = ["#{STYLE_TITLE}♦ WHEEL SEGMENTS ♦#{IRC_RESET}"] segments.each_with_index do |segment, index| lines << "#{STYLE_LABEL}#{index + 1}.#{IRC_RESET} #{STYLE_VALUE}#{segment}#{IRC_RESET}" end lines.join("\n") end
Source
# File plugins/wheel.rb, line 122 def self.format_slice_ring(index, segment_count, display_slices: DISPLAY_SLICES) ring = build_slice_ring(index, segment_count, display_slices: display_slices) "#{STYLE_WHEEL}#{ring.join}#{IRC_RESET}" end
Source
# File plugins/wheel.rb, line 179 def self.format_spin_result(user:, segment:, index:, segments:) lines = [ format_wheel_art(segments, index), "#{STYLE_TITLE}══════ SPIN THE WHEEL ══════#{IRC_RESET}", "#{STYLE_LABEL}Player:#{IRC_RESET} #{STYLE_NICK}#{user}#{IRC_RESET}", "#{STYLE_LABEL}The wheel landed on#{IRC_RESET} #{STYLE_WIN}#{segment}#{IRC_RESET}", "#{STYLE_LABEL}Segment#{IRC_RESET} #{STYLE_VALUE}#{index + 1}#{IRC_RESET} " \ "#{STYLE_LABEL}of#{IRC_RESET} #{STYLE_VALUE}#{segments.length}#{IRC_RESET}" ] lines.join("\n") end
Source
# File plugins/wheel.rb, line 157 def self.format_wheel_art(segments, index) phrase = segment_at(segments, index) box_lines = format_phrase_box(phrase) [ format_pointer_line, format_rotated_ring(index, segments.length), "#{STYLE_WHEEL} #{box_lines[0]} #{IRC_RESET}", "#{STYLE_WHEEL} #{IRC_RESET}#{STYLE_VALUE}#{box_lines[1]}#{IRC_RESET} #{STYLE_WHEEL}#{IRC_RESET}", "#{STYLE_WHEEL} #{box_lines[2]} #{IRC_RESET}", "#{STYLE_TITLE}WHEEL OF FORTUNE#{IRC_RESET}", "#{STYLE_LABEL}SPIN SPIN THAT WHEEL!#{IRC_RESET}" ].join("\n") end
Source
# File plugins/wheel.rb, line 62 def self.parse_command(text) parts = text.to_s.strip.split(/\s+/) return { action: :spin } if parts.empty? case parts[0].downcase when "spin" { action: :spin } when "list", "segments" { action: :list } when "reset" { action: :reset } when "help" { action: :help } when "add" label = parts[1..].join(" ").strip return { error: usage_message } if label.empty? return { error: usage_message } if label.length > MAX_LABEL_LENGTH { action: :add, label: label } else { error: usage_message } end end
Source
# File plugins/wheel.rb, line 57 def self.reset_channel(channel, store: default_store) key = normalize_channel(channel) store.delete(key) end
Source
# File plugins/wheel.rb, line 104 def self.segment_at(segments, index) segments[index % segments.length] end
Source
# File plugins/wheel.rb, line 47 def self.segments_for(channel, store: default_store) key = normalize_channel(channel) store.fetch(key, DEFAULT_SEGMENTS.dup) end
Source
# File plugins/wheel.rb, line 52 def self.set_segments(channel, segments, store: default_store) key = normalize_channel(channel) store[key] = segments end
Source
# File plugins/wheel.rb, line 191 def self.spin(channel:, user:, store: default_store, rand: ->(max) { Random.rand(0..max) }) segments = segments_for(channel, store: store) index = spin_index(segments.length, rand: rand) segment = segment_at(segments, index) message = format_spin_result(user: user, segment: segment, index: index, segments: segments) { index: index, segment: segment, message: message } end
Source
# File plugins/wheel.rb, line 86 def self.spin_index(segment_count, rand: ->(max) { Random.rand(0..max) }) rand.call(segment_count - 1) end
Source
# File plugins/wheel.rb, line 139 def self.truncate_label(label, max_length: 18) text = label.to_s.strip return text if text.length <= max_length "#{text[0, max_length - 3]}..." end
Source
# File plugins/wheel.rb, line 42 def self.usage_message "Usage: !wheel — spin the wheel | !wheel spin | !wheel list | " \ "!wheel add <segment> | !wheel reset" end
Source
# File plugins/wheel.rb, line 200 def self.wheel(args_text, user:, channel:, store: default_store, rand: ->(max) { Random.rand(0..max) }) parsed = parse_command(args_text.to_s) return parsed[:error] if parsed[:error] return usage_message if parsed[:action] == :help case parsed[:action] when :spin spin(channel: channel, user: user, store: store, rand: rand)[:message] when :list format_segment_list(segments_for(channel, store: store)) when :reset reset_channel(channel, store: store) "#{STYLE_TITLE}Wheel reset#{IRC_RESET} #{STYLE_LABEL}to default segments.#{IRC_RESET}" when :add result = add_segment(channel, parsed[:label], store: store) return result[:error] if result[:error] "#{STYLE_TITLE}Added#{IRC_RESET} #{STYLE_VALUE}#{result[:label]}#{IRC_RESET} " \ "#{STYLE_LABEL}to the wheel (#{result[:segments].length} segments).#{IRC_RESET}" else usage_message end end
Source
# File plugins/wheel.rb, line 108 def self.winning_display_slice(index, segment_count, display_slices: DISPLAY_SLICES) return 0 if segment_count <= 0 normalized = index % segment_count (normalized * display_slices) / segment_count end
Public Instance Methods
Source
# File plugins/wheel.rb, line 228 def execute(m, args_text = nil) channel = m.channel ? m.channel.name : m.user.nick themed_flood_safe_reply(m, wheel(args_text, user: m.user.nick, channel: channel)) end
Source
# File plugins/wheel.rb, line 224 def wheel(args_text = nil, **options) self.class.wheel(args_text, **options) end