# Copyright (c) 2006 "Gardiner" # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in # the Software without restriction, including without limitation the rights to # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # of the Software, and to permit persons to whom the Software is furnished to do # so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. class StatEvaluator attr_reader :scoring attr_reader :requirements def initialize @scoring = "" @requirements = "" @scoring_proc = nil @requirements_proc = nil end def evaluate_stats(stats, tends) acid, color, grapes, quality, skin, sugar, vigor = *stats req = 1 sc = 0 if @requirements_proc req = @requirements_proc.call(*(stats + [tends])) end if @scoring_proc sc = @scoring_proc.call(*(stats + [tends])) end sc * req end def scoring=(sc) #acid, color, grapes, quality, skin, sugar, vigor = 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 tends = 1 begin @scoring_proc = eval("Proc.new { |acid, color, grapes, quality, skin, sugar, vigor, tends| #{sc} }") val = @scoring_proc.call(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0) if !val.is_a?(Integer) && !val.is_a?(Float) @scoring_proc = nil @scoring = "" raise "Scoring formula did not evaluate to a number." end rescue SyntaxError => ex @scoring_proc = nil @scoring = "" raise "Syntax error in scoring: " + ex rescue NameError => ex @scoring_proc = nil @scoring = "" raise "Invalid name in scoring: " + ex rescue ZeroDivisionError => ex @scoring_proc = nil @scoring = "" raise "Potential divide by zero found in scoring." rescue StandardError => ex @scoring_proc = nil @scoring = "" raise "Error when testing scoring: " + ex end @scoring = sc end def requirements=(req) #acid, color, grapes, quality, skin, sugar, vigor = 0, 0, 1, 0, 0, 0, 1 tends = 1 fixed_req = "[" + req + "].product" begin @requirements_proc = eval("Proc.new { |acid, color, grapes, quality, skin, sugar, vigor, tends| #{fixed_req} }") @requirements_proc.call(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0) rescue SyntaxError => ex @requirements_proc = nil @requirements = "" raise "Syntax error in requirements: " + ex + "\nDid you forget a comma?" rescue NameError => ex @requirements_proc = nil @requirements = "" raise "Invalid name in requirements: " + ex rescue ZeroDivisionError => ex @requirements_proc = nil @requirements = "" raise "Potential divide by zero found in requirements." rescue StandardError => ex @requirements_proc = nil @requirements = "" raise "Error when testing requirements: " + ex end @requirements = req end private def self.make_comparator(name, func) module_eval("def #{name} (value, stat) stat.send(:#{func}, value) ? 1 : 0 end") end def between(low, high, stat) stat >= low && stat <= high ? 1 : 0 end make_comparator "at_least", :>= make_comparator "more_than", :> make_comparator "no_more_than", :<= make_comparator "less_than", :< make_comparator "exactly", :== end