probably_alive and CalcEstDates now share same codebase; rewritten probably_alive

svn: r14102
This commit is contained in:
Doug Blank 2010-01-20 13:39:37 +00:00
parent c689013025
commit 97c058af9b
2 changed files with 397 additions and 317 deletions

View File

@ -452,12 +452,401 @@ def create_uid(self, handle=None):
uid = uuid.uuid4() uid = uuid.uuid4()
return uid.hex.upper() 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 # 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. """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 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) (defaults to today)
:param limit: number of years to check beyond death_date :param limit: number of years to check beyond death_date
""" """
today = gen.lib.Date() today = gen.lib.date.Today()
today.set_yr_mon_day(*time.localtime(time.time())[0:3])
if current_date is None: if current_date is None:
current_date = today current_date = today
# Are we checking to see if they are alive right now? # Are we checking to see if they are alive right now?

View File

@ -48,7 +48,7 @@ from ReportBase import ReportUtils
from docgen import TextBufDoc from docgen import TextBufDoc
from Simple import make_basic_stylesheet, SimpleAccess, SimpleDoc, SimpleTable from Simple import make_basic_stylesheet, SimpleAccess, SimpleDoc, SimpleTable
from QuestionDialog import QuestionDialog from QuestionDialog import QuestionDialog
from Utils import create_id from Utils import create_id, probably_alive_range
import DateHandler import DateHandler
#------------------------------------------------------------------------ #------------------------------------------------------------------------
@ -509,317 +509,9 @@ class CalcToolManagedWindow(PluginWindows.ToolManagedWindowBatch):
self.db.add_event(event, self.trans) self.db.add_event(event, self.trans)
return event return event
def calc_estimates(self, person, is_spouse=False): def calc_estimates(self, person):
if person is None: return probably_alive_range(person, self.db,
return (None, None, "", None) self.MAX_SIB_AGE_DIFF,
birth_ref = person.get_birth_ref() self.MAX_AGE_PROB_ALIVE,
death_ref = person.get_death_ref() self.AVG_GENERATION_GAP)
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.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)