Drill baby drill

This commit is contained in:
Bill Rossi 2025-08-28 21:02:26 -04:00
parent 4edb1381e6
commit 5970841784
5 changed files with 171 additions and 31 deletions

View File

@ -1,48 +1,129 @@
require "rufus-scheduler"
class Drill class Drill
COMMANDS = %w[ attr_reader :responder, :current_question, :scheduler
init attr_accessor :length, :participants, :timer_job_id
start
end
]
attr_reader :channel def initialize(responder: nil, scheduler: Rufus::Scheduler.new)
@responder = responder
def initialize(channel) @participants = []
@channel = channel @length = "10m"
@exists = false @running = false
@started = false @scheduler = scheduler
@time_is_up = false
end end
def init! def respond(response)
@exists = true responder.call response
end end
def start! def can_handle_message?(message)
@started = true true
end end
def end! ACTIONS = %w[join leave start stop]
@started = false CUSTOMIZATIONS = %w[length]
end
def handle_message(message) def handle_message(message)
message.command_message ? handle_command(message) : handle_normal_message(message) if ACTIONS.include? message.content
return send("handle_#{message.content.downcase}", message)
elsif customization = CUSTOMIZATIONS.find { |c| message.content.start_with?("#{c} ") }
return send("handle_customize_#{customization}", message)
end
return unless running?
return unless message.author == current_question_target
handle_question_response(message)
end end
def handle_command(message) def handle_join(message)
command = message.command if participants.include? message.author
if COMMANDS.includes?(command) respond "You've already joined"
send("handle_#{command}", message)
else else
puts "[Drill] Unknown command #{command}" self.participants << message.author
respond "#{message.author.display_name} has joined"
end end
end end
def started? def handle_leave(message)
@started if participants.include? message.author
self.participants -= [message.author]
respond "#{message.author.display_name} has left"
else
respond "You aren't a participant"
end
end end
def exists? def handle_start(message)
@exists return respond "The drill's already started!" if running?
@running = true
@time_is_up = false
self.timer_job_id = scheduler.in(length){ @time_is_up = true }
respond "Drill started!"
participants.shuffle!
next_question!
end
def handle_stop(message)
return respond "The drill's not running yet" unless running?
@running = false
scheduler.unschedule(timer_job_id) if timer_job_id
respond "Drill stopped!"
end
def handle_customize_length(message)
return respond "The drill's already started!" if running?
cmd, desired_length = message.content.split
return respond "Please specify a length" unless desired_length
self.length = desired_length
respond "Drill length set to #{desired_length}"
end
def handle_question_response(message)
if current_question.correct_answer == message.content
respond "Correct!"
else
respond "Incorrect: #{current_question.correct_answer}"
end
next_question!
end
def next_question!
return end_drill! if time_is_up?
self.participants = participants.rotate
generate_question
respond "#{current_question_target.display_name}: #{current_question.question_text}"
end
def end_drill!
respond "Time's up! Everyone did great!"
@running = false
end
def generate_question
value = (1..100).to_a.sample
@current_question = OpenStruct.new(
question_text: "Type the number #{value}",
correct_answer: value.to_s
)
end
def current_question_target
participants.first
end
def running?
@running
end
def time_is_up?
@time_is_up
end end
end end

View File

@ -1,6 +1,5 @@
require_relative './session' require_relative './session'
require_relative './message' require_relative './message'
require_relative './drill_plugin'
require_relative './ika/plugin' require_relative './ika/plugin'
class Ika class Ika
@ -8,7 +7,8 @@ class Ika
PLUGIN_TYPES = [ PLUGIN_TYPES = [
Plugin::HelpPlugin, Plugin::HelpPlugin,
Plugin::LessonPlugin Plugin::LessonPlugin,
Plugin::DrillPlugin
] ]
def self.for(type:, **kwargs) def self.for(type:, **kwargs)

View File

@ -1,3 +1,4 @@
require_relative "./plugin/drill_plugin"
require_relative "./plugin/help_plugin" require_relative "./plugin/help_plugin"
require_relative "./plugin/lesson_plugin" require_relative "./plugin/lesson_plugin"

View File

@ -0,0 +1,57 @@
require_relative "../../drill"
class Plugin
class DrillPlugin < Plugin
attr_reader :drills
def initialize(ika)
super
@drills = {}
end
def handle_message(message)
return false unless super
Message.new(self, message).handle
end
def can_handle_message?(message)
return true if message.content == "!drill"
drills[message.channel.id]&.can_handle_message?(message)
end
class Message
attr_reader :plugin, :message
def initialize(plugin, message)
@plugin = plugin
@message = message
end
def content
message.content
end
def responder
message.responder
end
def respond(response)
responder.call response
end
def handle
drill.handle_message(message)
end
def drill
drl = plugin.drills[message.channel.id]
return drl if drl
drl = Drill.new responder: responder
plugin.drills[message.channel.id] = drl
end
end
end
end

View File

@ -10,7 +10,8 @@ class Plugin
end end
def handle_message(message) def handle_message(message)
super return false unless super
Message.new(self, message).handle Message.new(self, message).handle
end end