lib/laser-cutter/configuration.rb
require 'hashie/mash'
require 'hashie/extensions/symbolize_keys'
require 'hashie/extensions/mash/symbolize_keys'
require 'prawn/measurement_extensions'
require 'pdf/core/page_geometry'
module Laser
module Cutter
class MissingOption < RuntimeError; end
class ZeroValueNotAllowed < MissingOption; end
class UnitsConverter
def self.mm2in(value)
0.039370079 * value
end
def self.in2mm(value)
25.4 * value
end
end
class Configuration < Hashie::Mash
include ::Hashie::Extensions::Mash::SymbolizeKeys
DEFAULTS = {
units: :in,
page_layout: 'portrait',
metadata: true
}
UNIT_SPECIFIC_DEFAULTS = {
in: {
kerf: 0.0024, # smallest kerf for thin material, usually it's more than that.
margin: 0.125,
padding: 0.1,
stroke: 0.001,
}
}
UNIT_SPECIFIC_DEFAULTS[:mm] = UNIT_SPECIFIC_DEFAULTS[:in].map{|k, v| [k, UnitsConverter.in2mm(v)] }.to_h
SIZE_REGEXP = /[\d.]+x[\d.]+x[\d.]+\/[\d.]+(\/[\d.]+)?/
FLOATS = %i(width height depth thickness notch margin padding stroke kerf)
NON_ZERO = %i(width height depth thickness stroke)
REQUIRED = %i(width height depth thickness notch file)
def initialize(options = {})
::Hashie::Extensions::SymbolizeKeys.symbolize_keys!(options)
options.delete_if { |k, v| v.nil? }
if options[:units] && !UNIT_SPECIFIC_DEFAULTS.keys.include?(options[:units].to_sym)
options.delete(:units)
end
super(DEFAULTS.merge(options))
if self.box =~ SIZE_REGEXP
dim, self[:thickness], self[:notch] = self[:box].split('/')
self[:width], self[:height], self[:depth] = dim.split('x')
delete(:box)
end
FLOATS.each do |k|
self[k] = self[k].to_f if (self[k] && self[k].is_a?(String))
end
self.merge!(UNIT_SPECIFIC_DEFAULTS[self[:units].to_sym].merge(self))
self[:notch] = (self[:thickness] * 3.0).round(5) if self[:thickness] && self[:notch].nil?
end
def validate!
missing = []
REQUIRED.each { |k| missing << k if self[k].nil? }
raise MissingOption.new("#{missing.join(', ')} #{missing.size > 1 ? 'are' : 'is'} required, but missing.") unless missing.empty?
zeros = []
NON_ZERO.each { |k| zeros << k if self[k] == 0 }
raise ZeroValueNotAllowed.new("#{zeros.join(', ')} #{zeros.size > 1 ? 'are' : 'is'} required, but is zero.") unless zeros.empty?
end
def change_units(new_units)
return if new_units.to_sym == units.to_sym
return if (units.to_sym.eql?(new_units) || !UNIT_SPECIFIC_DEFAULTS.keys.include?(new_units.to_sym))
k = (units.to_sym == :in) ? UnitsConverter.in2mm(1.0) : UnitsConverter.mm2in(1.0)
FLOATS.each do |field|
next if send(field).nil?
send("#{field}=", (send(field) * k).round(5))
end
self.units = new_units.to_sym
end
end
end
end