From b68c1f63783c2b5bbbec4aa7796aca83fa860f90 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 13 Feb 2007 15:55:40 +0000 Subject: [PATCH] quiz plugin: QuizAnswer class to wrap quiz answers, including information about core, being numeric and whatnot --- data/rbot/plugins/quiz.rb | 87 ++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/data/rbot/plugins/quiz.rb b/data/rbot/plugins/quiz.rb index d14a40f1..9a550ea8 100644 --- a/data/rbot/plugins/quiz.rb +++ b/data/rbot/plugins/quiz.rb @@ -1,3 +1,6 @@ +#-- vim:sw=2:et +#++ +# # Plugin for the Ruby IRC bot (http://linuxbrit.co.uk/rbot/) # # A trivia quiz game. Fast paced, featureful and fun. @@ -38,13 +41,57 @@ Color = "\003" Bold = "\002" +####################################################################### +# CLASS QuizAnswer +# Abstract an answer to a quiz question, by providing self as a string +# and a core that can be answered as an alternative. It also provides +# a boolean that tells if the core is numeric or not +####################################################################### +class QuizAnswer + attr_writer :info + + def initialize(str) + @string = str.strip + @core = nil + if @string =~ /#(.+)#/ + @core = $1 + @string.gsub!('#', '') + end + raise ArgumentError, "empty string can't be a valid answer!" if @string.empty? + raise ArgumentError, "empty core can't be a valid answer!" if @core and @core.empty? + + @numeric = (core.to_i.to_s == core) || (core.to_f.to_s == core) + @info = nil + end + + def core + @core || @string + end + + def numeric? + @numeric + end + + def valid?(str) + str.downcase == core.downcase || str.downcase == @string.downcase + end + + def to_str + [@string, @info].join + end + alias :to_s :to_str + + +end + + ####################################################################### # CLASS Quiz # One Quiz instance per channel, contains channel specific data ####################################################################### class Quiz attr_accessor :registry, :registry_conf, :questions, - :question, :answers, :answer_cores, :canonical_answer, :answer_array, + :question, :answers, :canonical_answer, :answer_array, :first_try, :hint, :hintrange, :rank_table, :hinted, :has_errors def initialize( channel, registry ) @@ -84,7 +131,6 @@ class Quiz @questions = @registry_conf["questions"] @question = nil @answers = [] - @answer_cores = [] @canonical_answer = nil # FIXME 2.0 UTF-8 @answer_array = [] @@ -324,11 +370,11 @@ class QuizPlugin < Plugin nick = m.sourcenick.to_s # Support multiple alternate answers and cores - answer = (q.answers|q.answer_cores).find { |ans| message == ans.downcase} + answer = q.answers.find { |ans| ans.valid?(message) } if answer - answer += " (hints were for alternate answer #{q.canonical_answer})" if answer != q.canonical_answer - # List canonical answer which the hint was based on, to avoid confusion - # FIXME display this more friendly + # List canonical answer which the hint was based on, to avoid confusion + # FIXME display this more friendly + answer.info = " (hints were for alternate answer #{q.canonical_answer.core})" if answer != q.canonical_answer and q.hinted points = 1 if q.first_try @@ -433,43 +479,27 @@ class QuizPlugin < Plugin picked = q.questions.delete_at( rand(q.questions.length) ) q.question = picked.question - debug "Question: #{picked.question}" - debug "Answer: #{picked.answer}" - q.answers = picked.answer.split(/\s+\|\|\s+/).each { |ans| ans.strip } - - q.answer_cores.clear - q.answers.each do |answer| - if /#(.+)#/ =~ answer - q.answer_cores << $1 - answer.gsub!('#', '') - else - q.answer_cores << answer - end - end + q.answers = picked.answer.split(/\s+\|\|\s+/).map { |ans| QuizAnswer.new(ans) } - # Check if core answer is numerical and tell the players so, if that's the case + # Check if any core answer is numerical and tell the players so, if that's the case # The rather obscure statement is needed because to_i and to_f returns 99(.0) for "99 red balloons", and 0 for "balloon" - # Doing this if *any* core answer is numerical. Maybe only checking the first one is more appropriate, - # because hints are based on the first alternate # # The "canonical answer" is also determined here, defined to be the first found numerical answer, or # the first core. - numeric = q.answer_cores.find { |core| core.to_i.to_s == core or core.to_f.to_s == core } + numeric = q.answers.find { |ans| ans.numeric? } if numeric q.question += "#{Color}07 (Numerical answer)#{Color}" q.canonical_answer = numeric else - q.canonical_answer = q.answer_cores[0] + q.canonical_answer = q.answers.first end - debug "Canonical answer: #{q.canonical_answer}" - q.first_try = true # FIXME 2.0 UTF-8 q.hint = [] q.answer_array.clear - q.canonical_answer.scan(/./u) { |ch| + q.canonical_answer.core.scan(/./u) { |ch| if is_sep(ch) q.hint << ch else @@ -478,7 +508,6 @@ class QuizPlugin < Plugin q.answer_array << ch } q.hinted = false - debug "Initial hint: #{q.hint}" # Generate array of unique random range q.hintrange = (0..q.hint.length-1).sort_by{ rand } @@ -533,7 +562,7 @@ class QuizPlugin < Plugin q.hinted = true # FIXME 2.0 UTF-8 - if q.hint.to_s == q.canonical_answer + if q.hintrange.length == 0 m.reply "#{Bold}#{Color}04BUST!#{Color}#{Bold} This round is over. #{Color}04Minus one point for #{nick}#{Color}." stats = nil -- 2.39.5