module Genealogy::UtilMethods

Module UtilMethods provides methods to run utility methods. It's included by the genealogy enabled AR model

Public Class Methods

generate_method_parent_birth_range(parent) click to toggle source

@!macro [attach] generate

@method $1_birth_range
optimistic (longest) estimation of $1's birth date. Calculation is based on receiver's birth or #life_range, max life expectancy and min and max fertility procreation ages
@return [Range] longest possible $1's birth date interval or nil when is not computable that is when birth or life range are not available
# File lib/genealogy/util_methods.rb, line 78
def self.generate_method_parent_birth_range(parent)
  define_method "#{parent}_birth_range" do
    if birth
      (birth - gclass.send("max_#{gclass::PARENT2SEX[parent]}_procreation_age").years)..(birth - gclass.send("min_#{gclass::PARENT2SEX[parent]}_procreation_age").years)
    elsif life_range
      (life_range.begin - gclass.send("max_#{gclass::PARENT2SEX[parent]}_procreation_age").years)..(life_range.end - gclass.send("min_#{gclass::PARENT2SEX[parent]}_procreation_age").years)
    end
  end
end
generate_method_parent_fertility_range(parent) click to toggle source

@!macro [attach] generate

@method $1_fertility_range
optimistic (longest) estimation of $1's fertility range. Calculation is based on receiver's #$1_birth_range, min and max fertility procreation ages
@return [Range] longest possible $1's fertility period or nil when is not computable that is when $1_birth_range is not computable
# File lib/genealogy/util_methods.rb, line 94
def self.generate_method_parent_fertility_range(parent)
  define_method "#{parent}_fertility_range" do
    if parent_birth_range = send("#{parent}_birth_range")
      (parent_birth_range.begin + gclass.send("min_#{gclass::PARENT2SEX[parent]}_procreation_age").years)..(parent_birth_range.end + gclass.send("max_#{gclass::PARENT2SEX[parent]}_procreation_age").years)
    end
  end
end

Public Instance Methods

birth() click to toggle source

Genealogy thinks time in term of Date, not DateTime @return [Date]

# File lib/genealogy/util_methods.rb, line 8
def birth
  birth_date.try(:to_date)
end
birth_range() click to toggle source

optimistic (longest) estimation of birth date. Calculation is based on available dates and max life expectancy @return [Range] longest possible birth date interval or nil if cannot be computable

# File lib/genealogy/util_methods.rb, line 34
def birth_range
  if birth
    birth..birth # exact
  elsif death
    (death - max_le)..death # estimation based on death
  end
end
can_procreate_during?(period) click to toggle source

It tests whether fertility range overlaps specified period @param [Range] period @return [Boolean] or nil if cannot be computable (fertility_range returns nil)

# File lib/genealogy/util_methods.rb, line 70
def can_procreate_during?(period)
  fertility_range.overlaps? period if (period and fertility_range)
end
can_procreate_on?(date) click to toggle source

It tests whether fertility range covers specified date @param [Date] date @return [Boolean] or nil if cannot be computable (fertility_range returns nil)

# File lib/genealogy/util_methods.rb, line 63
def can_procreate_on?(date)
  fertility_range.cover? date if (date and fertility_range)
end
death() click to toggle source

Genealogy thinks time in term of Date, not DateTime @return [Date]

# File lib/genealogy/util_methods.rb, line 14
def death
  death_date.try(:to_date)
end
fertility_range() click to toggle source

optimistic (longest) estimation of fertility period. Calculation is based on available dates, max life expectancy and min and max fertility procreation ages @return [Range] fertility period, nil if cannot be computable, false if died before reaching min fertility age

# File lib/genealogy/util_methods.rb, line 44
def fertility_range
  if birth
    if death
      if death > birth + min_fpa
        (birth + min_fpa)..([(birth + max_fpa), death].min) # best estimation
      else
        false # died before reaching min fertility age
      end
    else
      (birth + min_fpa)..(birth + max_fpa) # estimation based on birth
    end
  elsif death
    (death - max_le + min_fpa)..death # estimation based on death
  end
end
is_female?() click to toggle source

@return [Boolean]

# File lib/genealogy/util_methods.rb, line 124
def is_female?
  return female? if respond_to?(:female?)
  sex_before_type_cast == gclass.sex_female_value
end
is_male?() click to toggle source

@return [Boolean]

# File lib/genealogy/util_methods.rb, line 130
def is_male?
  return male? if respond_to?(:male?)
  sex_before_type_cast == gclass.sex_male_value
end
life_range() click to toggle source

optimistic (longest) estimation of life period. Calculation is based on available dates and max life expectancy @return [Range] life period or nil if cannot be computable

# File lib/genealogy/util_methods.rb, line 20
def life_range
  if birth
    if death
      birth..death # exact
    else
      birth..(birth + max_le) # estimation based on birth
    end
  elsif death
    (death - max_le)..death # estimation based on death
  end
end
max_fpa() click to toggle source

max fertility procreation age in terms of years. It depends on sex @return [Integer]

# File lib/genealogy/util_methods.rb, line 143
def max_fpa
  gclass.send("max_#{ssex}_procreation_age").years
end
max_le() click to toggle source

max life expectancy in terms of years. It depends on sex @return [Integer]

# File lib/genealogy/util_methods.rb, line 137
def max_le
  gclass.send("max_#{ssex}_life_expectancy").years
end
min_fpa() click to toggle source

min fertility procreation age in terms of years. It depends on sex @return [Integer]

# File lib/genealogy/util_methods.rb, line 149
def min_fpa
  gclass.send("min_#{ssex}_procreation_age").years
end
opposite_ssex() click to toggle source

opposite sex in terms of :male or :female @return [Symbol]

# File lib/genealogy/util_methods.rb, line 119
def opposite_ssex
  gclass::OPPOSITESEX[ssex]
end
ssex() click to toggle source

sex in terms of :male or :female @return [Symbol]

# File lib/genealogy/util_methods.rb, line 106
def ssex
  case sex_before_type_cast
  when gclass.sex_male_value
    :male
  when gclass.sex_female_value
    :female
  else
    raise SexError, "Sex value not valid for #{self}"
  end
end

Private Instance Methods

check_incompatible_relationship(*args) click to toggle source
# File lib/genealogy/util_methods.rb, line 155
def check_incompatible_relationship(*args)
  relationship = args.shift
  args.each do |relative|
    # puts "[#{__method__}]: #{arg} class: #{arg.class}, #{self} class: #{self.class}"
    next if relative.nil?
    check_indiv(relative)
    if gclass.ineligibility_level >= gclass::PEDIGREE
      if ineligibles = self.send("ineligible_#{relationship.to_s.pluralize}")
        # puts "[#{__method__}]: checking if #{relative} can be #{relationship} of #{self}"
        raise IncompatibleRelationshipException, "#{relative} can't be #{relationship} of #{self}" if ineligibles.include? relative
      else
        raise IncompatibleRelationshipException, "#{self} already has #{relationship}"
      end
    end
  end
end
check_indiv(arg, arg_sex=nil) click to toggle source
# File lib/genealogy/util_methods.rb, line 172
def check_indiv(arg, arg_sex=nil)
  raise ArgumentError, "Expected #{self.gclass} object. Got #{arg.class}" unless arg.is_a? self.gclass
  raise SexError, "Expected a #{arg_sex} as argument. Got a #{arg.ssex}" if arg_sex and arg.ssex != arg_sex
end