# Copyright (C) 2020-2021 Sutou Kouhei # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. require "rabbit/relative-size" require "rabbit/yaml-loader" module Rabbit class Properties include Enumerable def initialize(data) @data = normalize(data) end def [](key) @data[normalize_key(key)] end def []=(key, value) @data[normalize_key(key)] = value end def each(&block) @data.each(&block) end def get_boolean(key, default=nil) value = self[key] return default if value.nil? true_value?(value) end def get_integer(key, default=nil) integer_value(self[key] || default) end def get_float(key, default=nil) float_value(self[key] || default) end def get_size(key, filename, default=nil) size_value(self[key] || default, filename, key) end def get_relative_size(key, filename, default=nil) relative_size_value(self[key] || default, filename, key) end def draws targets = @data.select do |key, _| /\Adraw\d+\z/.match?(key) end targets = targets.sort_by do |key, _| Integer(key[/\d+/], 10) end targets.collect do |_, value| YAMLLoader.load(value) end end def respond_to_missing?(name, include_private) @data.key?(normalize_key(name.to_s.gsub(/\?\z/, ""))) end def method_missing(name, *args, &block) case args.size when 0 key = name.to_s if key.end_with?("?") key = key[0..-2] is_predict = true else is_predict = false end key = normalize_key(key) return super unless @data.key?(key) value = @data[key] if is_predict true_value?(value) else value end when 1 key = name.to_s return super unless key.end_with?("=") key = key[0..-2] @data[normalize_key(key)] = args[0] else super end end private def normalize(data) normalized_data = {} (data || {}).each do |key, value| normalized_data[normalize_key(key)] = value end normalized_data end def normalize_key(key) key.to_s.gsub(/-/, "_") end def true_value?(value) value == true or value == "true" end def integer_value(value) return nil if value.nil? Integer(value, 10) end def float_value(value) return nil if value.nil? Float(value) end def size_value(value, filename, name) return nil if value.nil? begin Integer(value, 10) rescue ArgumentError raise InvalidSizeError.new(filename, name, value) end end def relative_size_value(value, filename, name) return nil if value.nil? begin value = Float(value) rescue ArgumentError raise InvalidSizeError.new(filename, name, value) end RelativeSize.new(value) end end end