Simpact Cyan
Population based event driven simulation using mNRM
person.h
1 #ifndef PERSON_H
2 
3 #define PERSON_H
4 
5 #include "personbase.h"
6 #include <stdlib.h>
7 #include <iostream>
8 #include <vector>
9 #include <set>
10 
11 class Person;
12 class Man;
13 class Woman;
14 
15 Man *MAN(Person *pPerson);
16 Woman *WOMAN(Person *pPerson);
17 
18 class Person : public PersonBase
19 {
20 public:
21  enum InfectionType { None, Partner, Mother, Seed };
22 
23  Person(double dateOfBirth, Gender g);
24  ~Person();
25 
26  bool isMan() const { return getGender() == Male; }
27  bool isWoman() const { return getGender() == Female; }
28 
29  void setFather(Man *pFather) { assert(m_pFather == 0); assert(pFather != 0); m_pFather = pFather; }
30  void setMother(Woman *pMother) { assert(m_pMother == 0); assert(pMother != 0); m_pMother = pMother; }
31 
32  Man *getFather() const { return m_pFather; }
33  Woman *getMother() const { return m_pMother; }
34 
35  // This also resets the iterator for getNextRelationshipPartner
36  int getNumberOfRelationships() const { return m_relationshipsSet.size(); }
37  void startRelationshipIteration();
38  Person *getNextRelationshipPartner(double &formationTime);
39 
40  bool hasRelationshipWith(Person *pPerson) const;
41 
42  // WARNING: do not use these during relationship iteration
43  void addRelationship(Person *pPerson, double t);
44  void removeRelationship(Person *pPerson, double t);
45 
46  // result is negative if no relations formed yet
47  double getLastRelationshipChangeTime() const { return m_lastRelationChangeTime; }
48 
49  void setSexuallyActive() { m_sexuallyActive = true; }
50  bool isSexuallyActive() { return m_sexuallyActive; }
51 
52  void setInfected(double t, Person *pOrigin, InfectionType iType);
53  bool isInfected() const { return m_infected; }
54  double getInfectionTime() const { assert(m_infected); return m_infectionTime; }
55  bool inAcuteStage() const { assert(m_infected); return m_acuteStage; }
56  void setInChronicStage() { assert(m_infected); assert(m_acuteStage); m_acuteStage = false; }
57 
58  // TODO: currently, the death of a parent or the death of a child does
59  // not have any influence on this list. I don't think modifying the list
60  // on a mortality event is useful, will only complicate things
61  // TODO: what might be useful is a member function to retrieve the number
62  // of living children?
63  void addChild(Person *pPerson);
64  bool hasChild(Person *pPerson) const;
65  int getNumberOfChildren() const { return m_children.size(); }
66 
67  void setBreastFeeding() { assert(!m_breastFeeding); m_breastFeeding = true; }
68  bool isBreastFeeding() const { return m_breastFeeding; }
69  void stopBreastFeeding() { assert(m_breastFeeding); m_breastFeeding = false; }
70 private:
71  class Relationship
72  {
73  public:
74  // A negative time is used when not relevant, e.g. when
75  // searching for a relationship with a person
76  Relationship(Person *pPerson, double formationTime) { assert(pPerson != 0); assert(formationTime > 0); m_pPerson = pPerson; m_formationTime = formationTime; }
77  Relationship(Person *pPerson) { assert(pPerson != 0); m_pPerson = pPerson; m_formationTime = -1; }
78 
79  Person *getPartner() const { return m_pPerson; }
80  double getFormationTime() const { return m_formationTime; }
81 
82  bool operator<(const Relationship &rel) const
83  {
84  if (m_pPerson->getPersonID() < rel.m_pPerson->getPersonID())
85  return true;
86  return false;
87  }
88  private:
89  Person *m_pPerson;
90  double m_formationTime;
91  };
92 
93  std::set<Relationship> m_relationshipsSet;
94  std::set<Relationship>::const_iterator m_relationshipsIterator;
95  double m_lastRelationChangeTime;
96  bool m_sexuallyActive;
97 
98  double m_infectionTime;
99  bool m_infected;
100  Person *m_pInfectionOrigin;
101  InfectionType m_infectionType;
102  bool m_acuteStage;
103 
104  Man *m_pFather;
105  Woman *m_pMother;
106 
107  std::vector<Person *> m_children;
108 
109  bool m_breastFeeding;
110 
111 #ifndef NDEBUG
112  bool m_relIterationBusy;
113 #endif
114 };
115 
116 class Man : public Person
117 {
118 public:
119  Man(double dateOfBirth);
120  ~Man();
121 };
122 
123 class Woman : public Person
124 {
125 public:
126  Woman(double dateOfBirth);
127  ~Woman();
128 
129  void setPregnant(bool f) { m_pregnant = f; }
130  bool isPregnant() const { return m_pregnant; }
131 private:
132  bool m_pregnant;
133 };
134 
135 inline void Person::addRelationship(Person *pPerson, double t)
136 {
137  assert(!m_relIterationBusy);
138  assert(pPerson != 0);
139  assert(pPerson != this); // can't have a relationship with ourselves
140  assert(!hasDied() && !pPerson->hasDied());
141  // Check that the relationship doesn't exist yet (debug mode only)
142  assert(m_relationshipsSet.find(Person::Relationship(pPerson)) == m_relationshipsSet.end());
143 
144  Person::Relationship r(pPerson, t);
145 
146  m_relationshipsSet.insert(r);
147  m_relationshipsIterator = m_relationshipsSet.begin();
148 
149  assert(t >= m_lastRelationChangeTime);
150  m_lastRelationChangeTime = t;
151 }
152 
153 inline void Person::removeRelationship(Person *pPerson, double t)
154 {
155  assert(!m_relIterationBusy);
156  assert(pPerson != 0);
157 
158  std::set<Person::Relationship>::iterator it = m_relationshipsSet.find(pPerson);
159 
160  if (it == m_relationshipsSet.end())
161  {
162  std::cerr << "Consistency error: a person was not found exactly once in the relationship list" << std::endl;
163  exit(-1);
164  }
165 
166  m_relationshipsSet.erase(it);
167  m_relationshipsIterator = m_relationshipsSet.begin();
168 
169  assert(t >= m_lastRelationChangeTime);
170  m_lastRelationChangeTime = t;
171 }
172 
173 inline bool Person::hasRelationshipWith(Person *pPerson) const
174 {
175  return m_relationshipsSet.find(Person::Relationship(pPerson)) != m_relationshipsSet.end();
176 }
177 
178 inline void Person::addChild(Person *pPerson)
179 {
180  assert(pPerson != 0);
181  assert(!hasChild(pPerson));
182 
183  m_children.push_back(pPerson);
184 }
185 
186 // TODO: this is currently not fast for large number of children
187 // can always use a 'set' if this becomes a bottleneck
188 inline bool Person::hasChild(Person *pPerson) const
189 {
190  assert(pPerson != 0);
191 
192  for (int i = 0 ; i < m_children.size() ; i++)
193  {
194  assert(m_children[i] != 0);
195 
196  if (m_children[i] == pPerson)
197  return true;
198  }
199 
200  return false;
201 }
202 
203 inline void Person::setInfected(double t, Person *pOrigin, InfectionType iType)
204 {
205  assert(!m_infected);
206  m_infected = true;
207 
208  m_infectionTime = t;
209  m_pInfectionOrigin = pOrigin;
210  m_infectionType = iType;
211 
212  m_acuteStage = true;
213 
214  assert(iType != None);
215  assert(!(pOrigin == 0 && iType != Seed));
216 }
217 
218 inline void Person::startRelationshipIteration()
219 {
220  assert(!m_relIterationBusy);
221 
222  m_relationshipsIterator = m_relationshipsSet.begin();
223 #ifndef NDEBUG
224  if (m_relationshipsIterator != m_relationshipsSet.end())
225  m_relIterationBusy = true;
226 #endif
227 }
228 
229 inline Person *Person::getNextRelationshipPartner(double &formationTime)
230 {
231  if (m_relationshipsIterator == m_relationshipsSet.end())
232  {
233 #ifndef NDEBUG
234  m_relIterationBusy = false;
235 #endif
236  return 0;
237  }
238 
239  assert(m_relIterationBusy);
240 
241  const Person::Relationship &r = *m_relationshipsIterator;
242 
243  ++m_relationshipsIterator;
244 
245  formationTime = r.getFormationTime();
246  return r.getPartner();
247 }
248 
249 inline Man *MAN(Person *pPerson)
250 {
251  assert(pPerson != 0);
252  assert(pPerson->getGender() == PersonBase::Male);
253 
254  return static_cast<Man*>(pPerson);
255 }
256 
257 inline Woman *WOMAN(Person *pPerson)
258 {
259  assert(pPerson != 0);
260  assert(pPerson->getGender() == PersonBase::Female);
261 
262  return static_cast<Woman*>(pPerson);
263 }
264 
265 #endif // PERSON_H
266 
The person is a man.
Definition: personbase.h:30
Gender getGender() const
Returns the gender of the person as set at construction time.
Definition: personbase.h:48
The person is a woman.
Definition: personbase.h:32
This is the base class for a person in a population-based simulation that used the Population class...
Definition: personbase.h:23