summaryrefslogtreecommitdiff
path: root/lib/family_factory.rb
blob: 8a3a4e82746d8ec0debff3ffe5a33c4ad3eb292c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# frozen_string_literal: true

require_relative 'family'
require_relative 'person'
require_relative 'gender'

# FamilyFactory class to create initial families for the FamilyTree.
# The primary purpose of this class is to create and initialize predefined families.
class FamilyFactory
  # Initializes a new FamilyFactory object.
  # Sets up a hash to store people and gets the singleton instance of RelationshipManager.
  def initialize
    @people = {}
  end

  # Creates and returns an array of predefined families.
  #
  # @return [Array<Family>] An array of predefined Family objects.
  def create_families
    [
      create_queen_margaret_and_king_arthur_family,
      create_flora_and_bill_family,
      create_victoire_and_ted_family,
      create_percy_and_audrey_family,
      create_ronald_and_helen_family,
      create_malfoy_and_rose_family,
      create_ginerva_and_harry_family,
      create_darcy_and_james_family,
      create_alice_and_albus_family
    ]
  end

  private

  # Finds or creates a person with the given name and gender.
  #
  # @param name [String] The name of the person.
  # @param gender [String] The gender of the person.
  # @return [Person] The found or created Person object.
  def find_or_create_person(name, gender)
    return @people[name] if @people.key?(name)

    person = Person.new(name, gender)
    @people[name] = person
    person
  end

  # Finds or creates a male person with the given name.
  #
  # @param name [String] The name of the male person.
  # @return [Person] The found or created male Person object.
  def find_or_create_male(name)
    find_or_create_person(name, Gender::MALE)
  end

  # Finds or creates a female person with the given name.
  #
  # @param name [String] The name of the female person.
  # @return [Person] The found or created female Person object.
  def find_or_create_female(name)
    find_or_create_person(name, Gender::FEMALE)
  end

  # Links two people as spouses.
  #
  # @param person1 [Person] The first person to link.
  # @param person2 [Person] The second person to link.
  # @raise [RuntimeError] if either person is already linked to someone else.
  # @return [void]
  def link_spouses(person1, person2)
    # Check if either person is already linked to someone else
    if person1.spouse != NilPerson.new && person1.spouse != person2
      raise "Cannot link #{person1.name} and #{person2.name}: #{person1.name} is already linked to #{person1.spouse.name}."
    end

    if person2.spouse != NilPerson.new && person2.spouse != person1
      raise "Cannot link #{person1.name} and #{person2.name}: #{person2.name} is already linked to #{person2.spouse.name}."
    end

    # Link the spouses
    person1.spouse = person2
    person2.spouse = person1 unless person2.is_a?(NilPerson)
  end

  # Creates the family of Queen Margaret and King Arthur.
  #
  # @return [Family] The created Family object.
  def create_queen_margaret_and_king_arthur_family
    queen_margaret = find_or_create_female('Queen Margaret')
    king_arthur = find_or_create_male('King Arthur')

    link_spouses(queen_margaret, king_arthur)

    bill = find_or_create_male('Bill')
    charlie = find_or_create_male('Charlie')
    percy = find_or_create_male('Percy')
    ronald = find_or_create_male('Ronald')
    ginerva = find_or_create_female('Ginerva')

    Family.new(queen_margaret, king_arthur, [bill, charlie, percy, ronald, ginerva])
  end

  # Creates the family of Flora and Bill.
  #
  # @return [Family] The created Family object.
  def create_flora_and_bill_family
    bill = find_or_create_male('Bill')
    flora = find_or_create_female('Flora')

    link_spouses(flora, bill)

    victoire = find_or_create_female('Victoire')
    dominique = find_or_create_female('Dominique')
    louis = find_or_create_male('Louis')

    Family.new(flora, bill, [victoire, dominique, louis])
  end

  # Creates the family of Victoire and Ted.
  #
  # @return [Family] The created Family object.
  def create_victoire_and_ted_family
    victoire = find_or_create_female('Victoire')
    ted = find_or_create_male('Ted')

    link_spouses(victoire, ted)

    remus = find_or_create_male('Remus')

    Family.new(victoire, ted, [remus])
  end

  # Creates the family of Percy and Audrey.
  #
  # @return [Family] The created Family object.
  def create_percy_and_audrey_family
    percy = find_or_create_male('Percy')
    audrey = find_or_create_female('Audrey')

    link_spouses(audrey, percy)

    molly = find_or_create_female('Molly')
    lucy = find_or_create_female('Lucy')

    Family.new(audrey, percy, [molly, lucy])
  end

  # Creates the family of Ronald and Helen.
  #
  # @return [Family] The created Family object.
  def create_ronald_and_helen_family
    ronald = find_or_create_male('Ronald')
    helen = find_or_create_female('Helen')

    link_spouses(helen, ronald)

    rose = find_or_create_female('Rose')
    hugo = find_or_create_male('Hugo')

    Family.new(helen, ronald, [rose, hugo])
  end

  # Creates the family of Malfoy and Rose.
  #
  # @return [Family] The created Family object.
  def create_malfoy_and_rose_family
    malfoy = find_or_create_male('Malfoy')
    rose = find_or_create_female('Rose')

    link_spouses(rose, malfoy)

    draco = find_or_create_male('Draco')
    aster = find_or_create_female('Aster')

    Family.new(rose, malfoy, [draco, aster])
  end

  # Creates the family of Ginerva and Harry.
  #
  # @return [Family] The created Family object.
  def create_ginerva_and_harry_family
    ginerva = find_or_create_female('Ginerva')
    harry = find_or_create_male('Harry')

    link_spouses(ginerva, harry)

    james = find_or_create_male('James')
    albus = find_or_create_male('Albus')
    lily = find_or_create_female('Lily')

    Family.new(ginerva, harry, [james, albus, lily])
  end

  # Creates the family of Darcy and James.
  #
  # @return [Family] The created Family object.
  def create_darcy_and_james_family
    darcy = find_or_create_female('Darcy')
    james = find_or_create_male('James')

    link_spouses(darcy, james)

    william = find_or_create_male('William')

    Family.new(darcy, james, [william])
  end

  # Creates the family of Alice and Albus.
  #
  # @return [Family] The created Family object.
  def create_alice_and_albus_family
    alice = find_or_create_female('Alice')
    albus = find_or_create_male('Albus')

    link_spouses(alice, albus)

    ron = find_or_create_male('Ron')
    ginny = find_or_create_female('Ginny')

    Family.new(alice, albus, [ron, ginny])
  end
end