diff options
| author | Szymon Szukalski <szymon@skas.io> | 2024-10-25 01:19:25 +1100 |
|---|---|---|
| committer | Szymon Szukalski <szymon@skas.io> | 2024-10-25 01:19:25 +1100 |
| commit | fa50df797d8fcb1e3636683cf2ff1582f35bc181 (patch) | |
| tree | d5a68c46854fcfecf548e0f13a438bc01f8e490c /lib/family_tree.rb | |
| parent | a89fa6a27bb0e2b9797dd01052aaf22b38296821 (diff) | |
Implement extended relationships
- Support uncle, aunt, in-law, son, daughter relationships
Diffstat (limited to 'lib/family_tree.rb')
| -rw-r--r-- | lib/family_tree.rb | 207 |
1 files changed, 179 insertions, 28 deletions
diff --git a/lib/family_tree.rb b/lib/family_tree.rb index 66af748..09f367f 100644 --- a/lib/family_tree.rb +++ b/lib/family_tree.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'singleton' - require_relative 'person' require_relative 'family_factory' @@ -18,53 +17,205 @@ class FamilyTree @families << family unless @families.include?(family) end - def add_child(*params) - puts "Adding Child with params: #{params.join(', ')}" + def add_child(mothers_name, name, gender) + result = find_person_in_families(mothers_name) + parent_of_family = result[:parent_of_family] + + return 'CHILD_ADDITION_FAILED' if parent_of_family.nil? || parent_of_family.mother.is_a?(NilPerson) + + return 'CHILD_ADDITION_FAILED' if parent_of_family.children.any? { |child| child.name.casecmp(name).zero? } + + child = Person.new(name, gender) + parent_of_family.add_child(child) + 'CHILD_ADDED' end def get_relationship(name, relationship) - result = find_person_and_family(name) + result = find_person_in_families(name) person = result[:person] - family = result[:family] + parent_of_family = result[:parent_of_family] + child_of_family = result[:child_of_family] - return 'PERSON_NOT_FOUND' if family.nil? || person.is_a?(NilPerson) + return 'PERSON_NOT_FOUND' if person.is_a?(NilPerson) case relationship.downcase - when 'mother' - mother = find_mother(family) - return 'PERSON_NOT_FOUND' if mother.is_a?(NilPerson) + when 'mother', 'father' + handle_parent_relationship(child_of_family, relationship) + when 'siblings' + handle_siblings_relationship(child_of_family, name) + when 'child', 'daughter', 'son' + handle_children_relationship(parent_of_family, relationship) + when 'paternal-uncle' + handle_uncle_relationship(child_of_family, 'paternal') + when 'maternal-uncle' + handle_uncle_relationship(child_of_family, 'maternal') + when 'paternal-aunt' + handle_aunt_relationship(child_of_family, 'paternal') + when 'maternal-aunt' + handle_aunt_relationship(child_of_family, 'maternal') + when 'sister-in-law' + handle_sister_in_law_relationship(person, child_of_family) + when 'brother-in-law' + handle_brother_in_law_relationship(person, child_of_family) + else + 'UNSUPPORTED_RELATIONSHIP' + end + end - mother.name - when 'father' - father = find_father(family) - return 'PERSON_NOT_FOUND' if father.is_a?(NilPerson) + private - father.name - when 'siblings' - siblings = find_siblings(family, name) - siblings.empty? ? 'NONE' : siblings.map(&:name).join(' ') + def handle_parent_relationship(child_of_family, relationship) + parent = relationship == 'mother' ? child_of_family&.mother : child_of_family&.father + return 'PERSON_NOT_FOUND' if parent.nil? || parent.is_a?(NilPerson) + + parent.name + end + + def handle_siblings_relationship(child_of_family, name) + siblings = find_siblings(child_of_family, name) + siblings.empty? ? 'NONE' : siblings.map(&:name).join(' ') + end + + def handle_children_relationship(parent_of_family, relationship) + return 'NONE' if parent_of_family.nil? + + children = parent_of_family.children + + case relationship.downcase + when 'child' + children.map(&:name).join(' ') + when 'son' + sons = children.select { |child| child.gender == Gender::MALE } + sons.empty? ? 'NONE' : sons.map(&:name).join(' ') + when 'daughter' + daughters = children.select { |child| child.gender == Gender::FEMALE } + daughters.empty? ? 'NONE' : daughters.map(&:name).join(' ') else 'UNSUPPORTED_RELATIONSHIP' end end - def find_person_and_family(name) - families.each do |family| - family.children.each do |child| - return { person: child, family: family } if child.name.casecmp(name).zero? + def handle_uncle_relationship(child_of_family, type) + return 'NONE' if child_of_family.nil? + + parent = type == 'paternal' ? child_of_family.father : child_of_family.mother + return 'NONE' if parent.nil? || parent.is_a?(NilPerson) + + # Find the family where the parent is a child + parent_result = find_person_in_families(parent.name) + parent_family = parent_result[:child_of_family] + + return 'NONE' if parent_family.nil? + + # Find the siblings of the parent + siblings = find_siblings(parent_family, parent.name) + + # Select male siblings (uncles) + uncles = siblings.select { |sibling| sibling.gender == Gender::MALE } + uncles.empty? ? 'NONE' : uncles.map(&:name).join(' ') + end + + def handle_aunt_relationship(child_of_family, type) + return 'NONE' if child_of_family.nil? + + parent = type == 'paternal' ? child_of_family.father : child_of_family.mother + return 'NONE' if parent.nil? || parent.is_a?(NilPerson) + + # Find the family where the parent is a child + parent_result = find_person_in_families(parent.name) + parent_family = parent_result[:child_of_family] + + return 'NONE' if parent_family.nil? + + # Find the siblings of the parent + siblings = find_siblings(parent_family, parent.name) + + # Select female siblings (aunts) + aunts = siblings.select { |sibling| sibling.gender == Gender::FEMALE } + aunts.empty? ? 'NONE' : aunts.map(&:name).join(' ') + end + + def handle_sister_in_law_relationship(person, child_of_family) + sisters_in_law = [] + + # Check for female siblings of the spouse + if person.spouse.is_a?(Person) + spouse_result = find_person_in_families(person.spouse.name) + spouse_family = spouse_result[:child_of_family] + + if spouse_family + spouse_siblings = find_siblings(spouse_family, person.spouse.name) + sisters_in_law.concat(spouse_siblings.select { |sibling| sibling.gender == Gender::FEMALE }.map(&:name)) end end - { person: NilPerson.new, family: nil } + + unless child_of_family.nil? + # Check for female spouses of siblings of the person + siblings = find_siblings(child_of_family, person.name) + + siblings.each do |sibling| + sisters_in_law << sibling.spouse.name if sibling.spouse && sibling.spouse.gender == Gender::FEMALE + end + end + + sisters_in_law.uniq! + sisters_in_law.empty? ? 'NONE' : sisters_in_law.join(' ') end - def find_mother(family) - mother = family.mother - mother || NilPerson.new + def handle_brother_in_law_relationship(person, child_of_family) + brothers_in_law = [] + + # Check for male siblings of the spouse + if person.spouse.is_a?(Person) + spouse_result = find_person_in_families(person.spouse.name) + spouse_family = spouse_result[:child_of_family] + + if spouse_family + spouse_siblings = find_siblings(spouse_family, person.spouse.name) + brothers_in_law.concat(spouse_siblings.select { |sibling| sibling.gender == Gender::MALE }.map(&:name)) + end + end + + unless child_of_family.nil? + # Check for male spouses of siblings of the person + siblings = find_siblings(child_of_family, person.name) + + siblings.each do |sibling| + brothers_in_law << sibling.spouse.name if sibling.spouse && sibling.spouse.gender == Gender::MALE + end + end + + brothers_in_law.uniq! + brothers_in_law.empty? ? 'NONE' : brothers_in_law.join(' ') end - def find_father(family) - father = family.father - father || NilPerson.new + def find_person_in_families(name) + result = { person: NilPerson.new, parent_of_family: nil, child_of_family: nil } + + families.each do |family| + # Check for mother + if family.mother&.name&.casecmp(name)&.zero? + result[:person] = family.mother + result[:parent_of_family] = family + end + + # Check for father + if family.father&.name&.casecmp(name)&.zero? + result[:person] = family.father + result[:parent_of_family] = family + end + + family.children.each do |child| + next if child.nil? || child.name.nil? + + if child.name.casecmp(name).zero? && family != result[:parent_of_family] + result[:person] = child + result[:child_of_family] = family + end + end + end + + result end def find_siblings(family, name) |
