probably_alive and CalcEstDates now share same codebase; rewritten probably_alive
svn: r14102
This commit is contained in:
		| @@ -48,7 +48,7 @@ from ReportBase import ReportUtils | ||||
| from docgen import TextBufDoc | ||||
| from Simple import make_basic_stylesheet, SimpleAccess, SimpleDoc, SimpleTable | ||||
| from QuestionDialog import QuestionDialog | ||||
| from Utils import create_id | ||||
| from Utils import create_id, probably_alive_range | ||||
| import DateHandler | ||||
|  | ||||
| #------------------------------------------------------------------------ | ||||
| @@ -509,317 +509,9 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch): | ||||
|         self.db.add_event(event, self.trans) | ||||
|         return event | ||||
|  | ||||
|     def calc_estimates(self, person, is_spouse=False): | ||||
|         if person is None: | ||||
|             return (None, None, "", None) | ||||
|         birth_ref = person.get_birth_ref() | ||||
|         death_ref = person.get_death_ref() | ||||
|         death_date = None | ||||
|         birth_date = None | ||||
|         explain = "" | ||||
|         # If the recorded death year is before current year then | ||||
|         # things are simple. | ||||
|         if death_ref and death_ref.get_role().is_primary(): | ||||
|             death = self.db.get_event_from_handle(death_ref.ref) | ||||
|             if death and death.get_date_object().get_start_date() != gen.lib.Date.EMPTY: | ||||
|                 death_date = death.get_date_object() | ||||
|     def calc_estimates(self, person): | ||||
|         return probably_alive_range(person, self.db, | ||||
|                          self.MAX_SIB_AGE_DIFF,  | ||||
|                          self.MAX_AGE_PROB_ALIVE,  | ||||
|                          self.AVG_GENERATION_GAP) | ||||
|  | ||||
|         # Look for Cause Of Death, Burial or Cremation events. | ||||
|         # These are fairly good indications that someone's not alive. | ||||
|         if not death_date: | ||||
|             for ev_ref in person.get_primary_event_ref_list(): | ||||
|                 ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                 if ev and ev.type.is_death_fallback(): | ||||
|                     death_date = ev.get_date_object() | ||||
|                     explain = _("death-related evidence") | ||||
|  | ||||
|         # If they were born within X years before current year then | ||||
|         # assume they are alive (we already know they are not dead). | ||||
|         if not birth_date: | ||||
|             if birth_ref and birth_ref.get_role().is_primary(): | ||||
|                 birth = self.db.get_event_from_handle(birth_ref.ref) | ||||
|                 if birth and birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY: | ||||
|                     birth_date = birth.get_date_object() | ||||
|  | ||||
|         # Look for Baptism, etc events. | ||||
|         # These are fairly good indications that someone's birth. | ||||
|         if not birth_date: | ||||
|             for ev_ref in person.get_primary_event_ref_list(): | ||||
|                 ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                 if ev and ev.type.is_birth_fallback(): | ||||
|                     birth_date = ev.get_date_object() | ||||
|                     explain = _("birth-related evidence") | ||||
|  | ||||
|         if not birth_date and death_date: | ||||
|             # person died more than MAX after current year | ||||
|             birth_date = death_date.copy_offset_ymd(year=-self.MAX_AGE_PROB_ALIVE) | ||||
|             explain = _("death date") | ||||
|          | ||||
|         if not death_date and birth_date: | ||||
|             # person died more than MAX after current year | ||||
|             death_date = birth_date.copy_offset_ymd(year=self.MAX_AGE_PROB_ALIVE) | ||||
|             explain = _("birth date") | ||||
|          | ||||
|         if death_date and birth_date: | ||||
|             return (birth_date, death_date, explain, "") # direct self evidence | ||||
|          | ||||
|         # Neither birth nor death events are available. Try looking | ||||
|         # at siblings. If a sibling was born more than X years past,  | ||||
|         # or more than Z future, then probably this person is | ||||
|         # not alive. If the sibling died more than X years | ||||
|         # past, or more than X years future, then probably not alive. | ||||
|  | ||||
|         family_list = person.get_parent_family_handle_list() | ||||
|         for family_handle in family_list: | ||||
|             family = self.db.get_family_from_handle(family_handle) | ||||
|             for child_ref in family.get_child_ref_list(): | ||||
|                 child_handle = child_ref.ref | ||||
|                 child = self.db.get_person_from_handle(child_handle) | ||||
|                 # Go through once looking for direct evidence: | ||||
|                 for ev_ref in child.get_primary_event_ref_list(): | ||||
|                     ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                     if ev and ev.type.is_birth(): | ||||
|                         dobj = ev.get_date_object()  | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             # if sibling birth date too far away, then not alive: | ||||
|                             year = dobj.get_year() | ||||
|                             if year != 0: | ||||
|                                 # sibling birth date | ||||
|                                 return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF), | ||||
|                                         gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("sibling birth date"), | ||||
|                                         child) | ||||
|                     elif ev and ev.type.is_death(): | ||||
|                         dobj = ev.get_date_object()  | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             # if sibling death date too far away, then not alive: | ||||
|                             year = dobj.get_year() | ||||
|                             if year != 0: | ||||
|                                 # sibling death date | ||||
|                                 return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE), | ||||
|                                         gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF), | ||||
|                                         _("sibling death date"), | ||||
|                                         child) | ||||
|                 # Go through again looking for fallback: | ||||
|                 for ev_ref in child.get_primary_event_ref_list(): | ||||
|                     ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                     if ev and ev.type.is_birth_fallback(): | ||||
|                         dobj = ev.get_date_object()  | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             # if sibling birth date too far away, then not alive: | ||||
|                             year = dobj.get_year() | ||||
|                             if year != 0: | ||||
|                                 # sibling birth date | ||||
|                                 return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF), | ||||
|                                         gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("sibling birth-related date"), | ||||
|                                         child) | ||||
|                     elif ev and ev.type.is_death_fallback(): | ||||
|                         dobj = ev.get_date_object()  | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             # if sibling death date too far away, then not alive: | ||||
|                             year = dobj.get_year() | ||||
|                             if year != 0: | ||||
|                                 # sibling death date | ||||
|                                 return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE), | ||||
|                                         gen.lib.Date().copy_ymd(year + self.MAX_SIB_AGE_DIFF), | ||||
|                                         _("sibling death-related date"), | ||||
|                                         child) | ||||
|  | ||||
|         if not is_spouse: # if you are not in recursion, let's recurse: | ||||
|             for family_handle in person.get_family_handle_list(): | ||||
|                 family = self.db.get_family_from_handle(family_handle) | ||||
|                 if family: | ||||
|                     mother_handle = family.get_mother_handle() | ||||
|                     father_handle = family.get_father_handle() | ||||
|                     if mother_handle == person.handle and father_handle: | ||||
|                         father = self.db.get_person_from_handle(father_handle) | ||||
|                         date1, date2, explain, other = self.calc_estimates(father, is_spouse=True) | ||||
|                         if date1 and date2: | ||||
|                             return date1, date2, _("a spouse, ") + explain, other | ||||
|                     elif father_handle == person.handle and mother_handle: | ||||
|                         mother = self.db.get_person_from_handle(mother_handle) | ||||
|                         date1, date2, explain, other = self.calc_estimates(mother, is_spouse=True) | ||||
|                         if date1 and date2: | ||||
|                             return date1, date2, _("a spouse, ") + explain, other | ||||
|  | ||||
|         # Try looking for descendants that were born more than a lifespan | ||||
|         # ago. | ||||
|  | ||||
|         def descendants_too_old (person, years): | ||||
|             for family_handle in person.get_family_handle_list(): | ||||
|                 family = self.db.get_family_from_handle(family_handle) | ||||
|                 for child_ref in family.get_child_ref_list(): | ||||
|                     child_handle = child_ref.ref | ||||
|                     child = self.db.get_person_from_handle(child_handle) | ||||
|                     child_birth_ref = child.get_birth_ref() | ||||
|                     if child_birth_ref: | ||||
|                         child_birth = self.db.get_event_from_handle(child_birth_ref.ref) | ||||
|                         dobj = child_birth.get_date_object() | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             d = gen.lib.Date(dobj) | ||||
|                             val = d.get_start_date() | ||||
|                             val = d.get_year() - years | ||||
|                             d.set_year(val) | ||||
|                             return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE), | ||||
|                                     _("descendent birth date"), | ||||
|                                     child) | ||||
|                     child_death_ref = child.get_death_ref() | ||||
|                     if child_death_ref: | ||||
|                         child_death = self.db.get_event_from_handle(child_death_ref.ref) | ||||
|                         dobj = child_death.get_date_object() | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             return (dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP),  | ||||
|                                     dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE), | ||||
|                                     _("descendent death date"), | ||||
|                                     child) | ||||
|                     date1, date2, explain, other = descendants_too_old (child, years + self.AVG_GENERATION_GAP) | ||||
|                     if date1 and date2: | ||||
|                         return date1, date2, explain, other | ||||
|                     # Check fallback data: | ||||
|                     for ev_ref in child.get_primary_event_ref_list(): | ||||
|                         ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                         if ev and ev.type.is_birth_fallback(): | ||||
|                             dobj = ev.get_date_object()  | ||||
|                             if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                                 d = gen.lib.Date(dobj) | ||||
|                                 val = d.get_start_date() | ||||
|                                 val = d.get_year() - years | ||||
|                                 d.set_year(val) | ||||
|                                 return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("descendent birth-related date"), | ||||
|                                         child) | ||||
|  | ||||
|                         elif ev and ev.type.is_death_fallback(): | ||||
|                             dobj = ev.get_date_object()  | ||||
|                             if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                                 return (dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP),  | ||||
|                                         dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("descendent death-related date"), | ||||
|                                         child) | ||||
|  | ||||
|             return (None, None, "", None) | ||||
|  | ||||
|         # If there are descendants that are too old for the person to have | ||||
|         # been alive in the current year then they must be dead. | ||||
|  | ||||
|         date1, date2, explain, other = None, None, "", None | ||||
|         try: | ||||
|             date1, date2, explain, other = descendants_too_old(person, self.AVG_GENERATION_GAP) | ||||
|         except RuntimeError: | ||||
|             raise Errors.DatabaseError( | ||||
|                 _("Database error: %s is defined as his or her own ancestor") % | ||||
|                 name_displayer.display(person)) | ||||
|  | ||||
|         if date1 and date2: | ||||
|             return (date1, date2, explain, other) | ||||
|  | ||||
|         def ancestors_too_old(person, year): | ||||
|             family_handle = person.get_main_parents_family_handle() | ||||
|             if family_handle:                 | ||||
|                 family = self.db.get_family_from_handle(family_handle) | ||||
|                 father_handle = family.get_father_handle() | ||||
|                 if father_handle: | ||||
|                     father = self.db.get_person_from_handle(father_handle) | ||||
|                     father_birth_ref = father.get_birth_ref() | ||||
|                     if father_birth_ref and father_birth_ref.get_role().is_primary(): | ||||
|                         father_birth = self.db.get_event_from_handle( | ||||
|                             father_birth_ref.ref) | ||||
|                         dobj = father_birth.get_date_object() | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             return (dobj.copy_offset_ymd(- year),  | ||||
|                                     dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), | ||||
|                                     _("ancestor birth date"), | ||||
|                                     father) | ||||
|                     father_death_ref = father.get_death_ref() | ||||
|                     if father_death_ref and father_death_ref.get_role().is_primary(): | ||||
|                         father_death = self.db.get_event_from_handle( | ||||
|                             father_death_ref.ref) | ||||
|                         dobj = father_death.get_date_object() | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE),  | ||||
|                                     dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), | ||||
|                                     _("ancestor death date"), | ||||
|                                     father) | ||||
|  | ||||
|                     # Check fallback data: | ||||
|                     for ev_ref in father.get_primary_event_ref_list(): | ||||
|                         ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                         if ev and ev.type.is_birth_fallback(): | ||||
|                             dobj = ev.get_date_object()  | ||||
|                             if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                                 return (dobj.copy_offset_ymd(- year),  | ||||
|                                         dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("ancestor birth-related date"), | ||||
|                                         father) | ||||
|  | ||||
|                         elif ev and ev.type.is_death_fallback(): | ||||
|                             dobj = ev.get_date_object()  | ||||
|                             if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                                 return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE),  | ||||
|                                         dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("ancestor death-related date"), | ||||
|                                         father) | ||||
|  | ||||
|                     date1, date2, explain, other = ancestors_too_old (father, year - self.AVG_GENERATION_GAP) | ||||
|                     if date1 and date2: | ||||
|                         return date1, date2, explain, other | ||||
|  | ||||
|                 mother_handle = family.get_mother_handle() | ||||
|                 if mother_handle: | ||||
|                     mother = self.db.get_person_from_handle(mother_handle) | ||||
|                     mother_birth_ref = mother.get_birth_ref() | ||||
|                     if mother_birth_ref and mother_birth_ref.get_role().is_primary(): | ||||
|                         mother_birth = self.db.get_event_from_handle(mother_birth_ref.ref) | ||||
|                         dobj = mother_birth.get_date_object() | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             return (dobj.copy_offset_ymd(- year),  | ||||
|                                     dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), | ||||
|                                     _("ancestor birth date"), | ||||
|                                     mother) | ||||
|                     mother_death_ref = mother.get_death_ref() | ||||
|                     if mother_death_ref and mother_death_ref.get_role().is_primary(): | ||||
|                         mother_death = self.db.get_event_from_handle( | ||||
|                             mother_death_ref.ref) | ||||
|                         dobj = mother_death.get_date_object() | ||||
|                         if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                             return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE),  | ||||
|                                     dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), | ||||
|                                     _("ancestor death date"), | ||||
|                                     mother) | ||||
|  | ||||
|                     # Check fallback data: | ||||
|                     for ev_ref in mother.get_primary_event_ref_list(): | ||||
|                         ev = self.db.get_event_from_handle(ev_ref.ref) | ||||
|                         if ev and ev.type.is_birth_fallback(): | ||||
|                             dobj = ev.get_date_object()  | ||||
|                             if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                                 return (dobj.copy_offset_ymd(- year),  | ||||
|                                         dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("ancestor birth-related date"), | ||||
|                                         mother) | ||||
|  | ||||
|                         elif ev and ev.type.is_death_fallback(): | ||||
|                             dobj = ev.get_date_object()  | ||||
|                             if dobj.get_start_date() != gen.lib.Date.EMPTY: | ||||
|                                 return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE),  | ||||
|                                         dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), | ||||
|                                         _("ancestor death-related date"), | ||||
|                                         mother) | ||||
|  | ||||
|                     date1, date2, explain, other = ancestors_too_old (mother, year - self.AVG_GENERATION_GAP) | ||||
|                     if date1 and date2: | ||||
|                         return (date1, date2, explain, other) | ||||
|  | ||||
|             return (None, None, "", None) | ||||
|  | ||||
|         # If there are ancestors that would be too old in the current year | ||||
|         # then assume our person must be dead too. | ||||
|         date1, date2, explain, other = ancestors_too_old (person, - self.AVG_GENERATION_GAP) | ||||
|         if date1 and date2: | ||||
|             return (date1, date2, explain, other) | ||||
|  | ||||
|         # If we can't find any reason to believe that they are dead we | ||||
|         # must assume they are alive. | ||||
|  | ||||
|         return (None, None, "", None) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user