From 97c058af9bfabe25e7d87bba344f0add3dc5de2f Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Wed, 20 Jan 2010 13:39:37 +0000 Subject: [PATCH] probably_alive and CalcEstDates now share same codebase; rewritten probably_alive svn: r14102 --- src/Utils.py | 394 +++++++++++++++++++- src/plugins/tool/CalculateEstimatedDates.py | 320 +--------------- 2 files changed, 397 insertions(+), 317 deletions(-) diff --git a/src/Utils.py b/src/Utils.py index eea2a387f..5ad72205a 100644 --- a/src/Utils.py +++ b/src/Utils.py @@ -452,12 +452,401 @@ def create_uid(self, handle=None): uid = uuid.uuid4() return uid.hex.upper() +class ProbablyAlive(object): + """ + An object to hold the parameters for considering someone alive. + """ + + def __init__(self, + db, + max_sib_age_diff, + max_age_prob_alive, + avg_generation_gap): + self.db = db + self.MAX_SIB_AGE_DIFF = max_sib_age_diff + self.MAX_AGE_PROB_ALIVE = max_age_prob_alive + self.AVG_GENERATION_GAP = avg_generation_gap + + def probably_alive_range(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() + + # 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.probably_alive_range(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.probably_alive_range(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) + #------------------------------------------------------------------------- # # probably_alive # #------------------------------------------------------------------------- -def probably_alive(person, db, current_date=None, limit=0): +def probably_alive(person, db, + current_date=None, + limit=0, + max_sib_age_diff=None, + max_age_prob_alive=None, + avg_generation_gap=None): + """ + Return true if the person may be alive on current_date. + + This works by a process of emlimination. If we can't find a good + reason to believe that someone is dead then we assume they must + be alive. + + :param current_date: a date object that is not estimated or modified + (defaults to today) + :param limit: number of years to check beyond death_date + :param max_sib_age_diff: maximum sibling age difference, in years + :param max_age_prob_alive: maximum age of a person, in years + :param avg_generation_gap: average generation gap, in years + """ + if max_sib_age_diff is None: + max_sib_age_diff = _MAX_SIB_AGE_DIFF + if max_age_prob_alive is None: + max_age_prob_alive = _MAX_AGE_PROB_ALIVE + if avg_generation_gap is None: + avg_generation_gap = _AVG_GENERATION_GAP + pb = ProbablyAlive(db, max_sib_age_diff, + max_age_prob_alive, avg_generation_gap) + birth, death, explain, relative = pb.probably_alive_range(person, db) + if death is None: # no evidence... can't say if alive/dead + return True + # must have est dates + if current_date: # date in which to consider alive + # SPECIAL CASE: Today: + if current_date.match(gen.lib.date.Today(), "=="): + if person.get_death_ref(): + return False + if limit: + death += limit # add these years to death + if death.match(gen.lib.date.Today(), ">"): + return True + result = (current_date.match(birth, ">=") and + current_date.match(death, "<=")) + return result + # else, they have a est death date, and no current_date give, thus dead + return False + +def probably_alive_range(person, db, + max_sib_age_diff=None, + max_age_prob_alive=None, + avg_generation_gap=None): + """ + Computes estimated birth and death dates. + Returns: (birth_date, death_date, explain_text, related_person) + """ + pb = ProbablyAlive(db, max_sib_age_diff, + max_age_prob_alive, avg_generation_gap) + return pb.probably_alive_range(person, db) + +def probably_alive_old(person, db, current_date=None, limit=0): """Return true if the person may be alive on current_date. This works by a process of emlimination. If we can't find a good @@ -468,8 +857,7 @@ def probably_alive(person, db, current_date=None, limit=0): (defaults to today) :param limit: number of years to check beyond death_date """ - today = gen.lib.Date() - today.set_yr_mon_day(*time.localtime(time.time())[0:3]) + today = gen.lib.date.Today() if current_date is None: current_date = today # Are we checking to see if they are alive right now? diff --git a/src/plugins/tool/CalculateEstimatedDates.py b/src/plugins/tool/CalculateEstimatedDates.py index 33bb47d95..907c57071 100644 --- a/src/plugins/tool/CalculateEstimatedDates.py +++ b/src/plugins/tool/CalculateEstimatedDates.py @@ -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)