module ChatModeSession
Constants
- BREAK_REASONS
- BURST_DELAY_SEC
- BURST_SCHEDULE_CHANCE
- BURST_TURN_COUNT
- DEFAULT_MINUTES
- INITIAL_STAGGER_SEC
- LONG_BREAK_CHANCE
- LONG_BREAK_DELAY_SEC
- MAX_MINUTES
- MAX_OUTPUT_CHARS
- MIN_MINUTES
- NORMAL_DELAY_SEC
- TURN_MINUTES_DIVISOR
- USAGE
Public Instance Methods
Source
# File lib/chat_mode_session.rb, line 31 def clamp_minutes(minutes, max_minutes: MAX_MINUTES) [[minutes.to_i, MIN_MINUTES].max, max_minutes].min end
Source
# File lib/chat_mode_session.rb, line 125 def consume_burst_turn(state) remaining = state[:burst_remaining].to_i state[:burst_remaining] = [remaining - 1, 0].max state[:long_break_next] = false if state[:burst_remaining].zero? end
Source
# File lib/chat_mode_session.rb, line 131 def format_status(state, bot_nick:) return "Chat mode is off." unless state status = state[:paused] ? "paused" : "running" parts = ["Chat mode #{status} for #{bot_nick}."] parts << "Ends in #{remaining_minutes(state)}m." parts << "Mode: #{state[:mode]}." parts << "Topic: #{state[:topic]}." if state[:topic] && !state[:topic].empty? parts << "Episode: #{state[:episode_title]}." if state[:episode_title] && !state[:episode_title].empty? parts << "Turns left: #{state[:turns_left]}." parts.join(" ") end
Source
# File lib/chat_mode_session.rb, line 96 def initial_stagger_sec(bot_nick, random: Random) seed = bot_nick.to_s.bytes.sum rng = Random.new(seed + random.rand(1000)) rng.rand(INITIAL_STAGGER_SEC) end
Source
# File lib/chat_mode_session.rb, line 92 def max_turns_for_duration(minutes) [[(minutes.to_f / TURN_MINUTES_DIVISOR).ceil, 2].max, 40].min end
Source
# File lib/chat_mode_session.rb, line 102 def next_delay_sec(state, random: Random) remaining = [state[:ends_at] - Time.now, 0].max return 0 if remaining <= 0 if state[:burst_remaining].to_i.positive? delay = random.rand(BURST_DELAY_SEC) return [delay, remaining].min end if state[:long_break_next] delay = random.rand(LONG_BREAK_DELAY_SEC) return [delay, remaining].min end delay = random.rand(NORMAL_DELAY_SEC) [delay, remaining].min end
Source
# File lib/chat_mode_session.rb, line 35 def parse_command(args, max_minutes: MAX_MINUTES) text = args.to_s.strip return start_payload(minutes: DEFAULT_MINUTES) if text.empty? control = text.match(/\A(stop|pause|continue|status)\z/i) return { action: control[1].downcase.to_sym } if control unless text.match?(/\Astart\b/i) return { error: USAGE } if text.match?(/\A\d/) return { error: USAGE } end parse_start_args(text.sub(/\Astart\s*/i, ""), max_minutes: max_minutes) end
Source
# File lib/chat_mode_session.rb, line 51 def parse_start_args(args, max_minutes: MAX_MINUTES) text = args.to_s.strip return start_payload(minutes: DEFAULT_MINUTES) if text.empty? match = text.match(/\A(\d+)\s*(.*)\z/m) if match minutes = clamp_minutes(match[1].to_i, max_minutes: max_minutes) return parse_start_mode(minutes, match[2].to_s.strip) end parse_start_mode(DEFAULT_MINUTES, text) end
Source
# File lib/chat_mode_session.rb, line 64 def parse_start_mode(minutes, remainder) return start_payload(minutes: minutes) if remainder.empty? if remainder.match?(/\A(?:episode|ep)\s+/i) search = remainder.sub(/\A(?:episode|ep)\s+/i, "").strip return { error: "episode search required after episode" } if search.empty? return start_payload(minutes: minutes, mode: :episode, episode_search: search) end if remainder.match?(/\Ageneral\b/i) topic = remainder.sub(/\Ageneral\s*/i, "").strip return start_payload(minutes: minutes, topic: topic.empty? ? nil : topic) end start_payload(minutes: minutes, topic: remainder) end
Source
# File lib/chat_mode_session.rb, line 159 def pick_break_reason(random: Random) BREAK_REASONS.sample(random: random) end
Source
# File lib/chat_mode_session.rb, line 144 def remaining_minutes(state) return 0 unless state && state[:ends_at] [[(state[:ends_at] - Time.now) / 60.0, 0].max.ceil, 0].max end
Source
# File lib/chat_mode_session.rb, line 150 def sanitize_output(text, max_chars: MAX_OUTPUT_CHARS) line = text.to_s.gsub(/[\r\n]+/, " ").squeeze(" ").strip line = line.sub(/\A[!\/]+\s*/, "") line = line.gsub(/\A["']|["']\z/, "") return "" if line.empty? line.length <= max_chars ? line : "#{line[0, max_chars - 3].rstrip}..." end
Source
# File lib/chat_mode_session.rb, line 120 def schedule_burst(state, random: Random) state[:burst_remaining] = random.rand(BURST_TURN_COUNT) state[:long_break_next] = random.rand < LONG_BREAK_CHANCE end
Source
# File lib/chat_mode_session.rb, line 82 def start_payload(minutes:, mode: :general, topic: nil, episode_search: nil) { action: :start, minutes: minutes, mode: mode, topic: topic, episode_search: episode_search } end