def dates_before_current_date(parser): """Makes sure all dates are before current date""" individuals = parser.individuals families = parser.families errors = [] current_date = date.today() # check all individual dates: birth, death for individual in individuals.values(): if individual.birth is not None and individual.birth >= current_date: errorMessage = f'Birth date {individual.birth} occurs in the future' errors.append( GedcomError(ErrorType.error, 'US01', individual, errorMessage)) elif individual.death is not None and individual.death >= current_date: errorMessage = f'Death date {individual.death} occurs in the future' errors.append( GedcomError(ErrorType.error, 'US01', individual, errorMessage)) # check all family dates: marriage, divorce for family in families.values(): if family.married is not None and family.married >= current_date: errorMessage = f'Marriage date {family.married} occurs in the future' errors.append( GedcomError(ErrorType.error, 'US01', family, errorMessage)) elif family.divorced is not None and family.divorced >= current_date: errorMessage = f'Divorce date {family.divorced} occurs in the future' errors.append( GedcomError(ErrorType.error, 'US01', family, errorMessage)) return errors
def birth_before_parent_marriage(parser): """Makes sure birth happens after parent marriage""" individuals = parser.individuals families = parser.families errors = [] for fam in families.values(): if fam.child_ids != []: for childID in fam.child_ids: child = individuals.get(childID) if child.birth is not None and \ fam.married is not None and \ child.birth <= fam.married: errorMessage = f'Married {fam.married} after child was born {child.birth}' errors.append( GedcomError(ErrorType.error, 'US08', fam, errorMessage)) if child.birth is not None and \ fam.divorced is not None: allowableDiff = fam.divorced + relativedelta(months=+9) if allowableDiff <= child.birth: errorMessage = f'Divorced {fam.divorced} more than 9 months before child was born {child.birth}' errors.append( GedcomError(ErrorType.error, 'US08', fam, errorMessage)) return errors
def marriage_after_14(parser): """Returns errors for individuals married before the age of 14""" individuals = parser.individuals families = parser.families errors = [] for fam in families.values(): if fam.married: if fam.husband_id: husband = individuals.get(fam.husband_id) if husband and husband.birth and \ DateHelpers.dates_within(husband.birth, fam.married, 14, 'years'): errorMessage = f'Married {fam.married} before husband turned 14 {husband.birth}' errors.append( GedcomError(ErrorType.error, 'US10', fam, errorMessage)) if fam.wife_id: wife = individuals.get(fam.wife_id) if wife and wife.birth and \ DateHelpers.dates_within(wife.birth, fam.married, 14, 'years'): errorMessage = f'Married {fam.married} before wife turned 14 {wife.birth}' errors.append( GedcomError(ErrorType.error, 'US10', fam, errorMessage)) return errors
def parents_not_too_old(parser): """Mother should be less than 60 years older than her children and father should be less than 80 years older than his children""" individuals = parser.individuals families = parser.families errors = [] for fam in families.values(): if fam.child_ids != []: for childID in fam.child_ids: child = individuals.get(childID) if child.birth is not None: childBirthYear = (datetime.strptime( str(child.birth), '%Y-%m-%d')).year if fam.wife_id is not None and \ individuals.get(fam.wife_id).birth is not None: momBirthYear = (datetime.strptime( str(individuals.get(fam.wife_id).birth), '%Y-%m-%d')).year if childBirthYear - momBirthYear >= 60: errorMessage = f'Mother {individuals.get(fam.wife_id).name} born {momBirthYear}, 60+ years before child was born {child.birth}' errors.append( GedcomError(ErrorType.error, 'US12', fam, errorMessage)) if fam.husband_id is not None and \ individuals.get(fam.husband_id).birth is not None: dadBirthYear = (datetime.strptime( str(individuals.get(fam.husband_id).birth), '%Y-%m-%d')).year if childBirthYear - dadBirthYear >= 80: errorMessage = f'Father {individuals.get(fam.husband_id).name} born {dadBirthYear}, 80+ years before child was born {child.birth}' errors.append( GedcomError(ErrorType.error, 'US12', fam, errorMessage)) return errors
def birth_before_parent_death(parser): """Child should be born before death of mother and before 9 months after death of father""" individuals = parser.individuals families = parser.families errors = [] for fam in families.values(): if fam.child_ids != []: for childID in fam.child_ids: child = individuals.get(childID) if child.birth is not None: if fam.wife_id is not None and \ individuals.get(fam.wife_id).death is not None and \ individuals.get(fam.wife_id).death <= child.birth: errorMessage = f'Mother {individuals.get(fam.wife_id).name} died before child was born {child.birth}' errors.append( GedcomError(ErrorType.error, 'US09', fam, errorMessage)) if fam.husband_id is not None and \ individuals.get(fam.husband_id).death is not None: allowableDiff = individuals.get( fam.husband_id).death + relativedelta(months=+9) if allowableDiff <= child.birth: errorMessage = f'Father {individuals.get(fam.husband_id).name} died more than 9 months before child was born {child.birth}' errors.append( GedcomError(ErrorType.error, 'US09', fam, errorMessage)) return errors
def less_than_150_years_old(parser): """Makes sure nobody reaches 150 years old""" individuals = parser.individuals errors = [] for individual in individuals.values(): # print("---------------------------------------------------------") # if birth is true if individual.birth is not None: individual_birth_year=(datetime.strptime(str(individual.birth), '%Y-%m-%d')).year # print("individual_birth_year: ",individual_birth_year) # if death is true (dead) if individual.death is not None: individual_death_year=(datetime.strptime(str(individual.death), '%Y-%m-%d')).year # print("individual_death_year: ",individual_death_year) age = individual_death_year-individual_birth_year if (age >= 150): errorMessage = f'The person is more than 150 years old, at {age} years old' errors.append(GedcomError(ErrorType.error, 'US07', individual, errorMessage)) # if death is not true (still alive) else: current_date_year=datetime.today().year # print("current_date_year: ",current_date_year) age = current_date_year-individual_birth_year if (age >= 150): errorMessage = f'The person is more than 150 years old, at {age} years old' errors.append(GedcomError(ErrorType.error, 'US07', individual, errorMessage)) return errors
def correct_gender_for_role(parser): errors = [] for family in parser.families.values(): father = family.husband_id mother = family.wife_id for individual in parser.individuals.values(): if individual.id == father: #if individual.sex == "M": # print("FATHER IDENTIFIED AND CONFIRMED") if individual.sex =="U": errorMessage = f'Husband in {family} does not have the correct gender for role, has {individual.sex} instead.' errors.append(GedcomError(ErrorType.error, 'US21', family, errorMessage)) elif individual.sex != "M": errorMessage = f'Husband in {family} does not have the correct gender for role, has {individual.sex} instead.' errors.append(GedcomError(ErrorType.error, 'US21', family, errorMessage)) elif individual.id == mother: #if individual.sex == "F": # print("MOTHER IDENTIFIED AND CONFIRMED") if individual.sex =="U": errorMessage = f'Wife in {family} does not have the correct gender for role, has {individual.sex} instead.' errors.append(GedcomError(ErrorType.error, 'US21', family, errorMessage)) elif individual.sex != "F": errorMessage = f'Wife in {family} does not have the correct gender for role, has {individual.sex} instead.' errors.append(GedcomError(ErrorType.error, 'US21', family, errorMessage)) return errors
def unique_ids(parser): errors = [] for individual in parser.individuals.values(): if individual.duplicates > 0: errMessage = f'ID {individual.id} is non-unique and shared with {individual.duplicates} other individual(s).' errors.append( GedcomError(ErrorType.error, 'US22', individual, errMessage)) for family in parser.families.values(): if family.duplicates > 0: errMessage = f'ID {family.id} is non-unique and shared with {family.duplicates} other families.' errors.append( GedcomError(ErrorType.error, 'US22', family, errMessage)) return errors
def sibling_spacing(parser): """Returns errors for siblings who are not twins born less than 8 months apart""" individuals = parser.individuals families = parser.families errors = [] for fam in families.values(): if len(fam.child_ids) > 1: children = [ individuals.get(child_id) for child_id in fam.child_ids ] children.sort(key=lambda x: x.birth or date(1, 1, 1)) children = list(filter(lambda c: c.birth is not None, children)) for i in range(1, len(children)): twins = DateHelpers.dates_within(children[i - 1].birth, children[i].birth, 2, 'days') lessThan9Months = DateHelpers.dates_within( children[i - 1].birth, children[i].birth, 8, 'months') if lessThan9Months and not twins: errorMessage = f'Siblings {children[i-1]}, {children[i]} born less than 8 months apart {children[i-1].birth}, {children[i].birth}' errors.append( GedcomError(ErrorType.error, 'US13', fam, errorMessage)) return errors
def birth_before_death(parser): """Makes sure births are before death""" individuals = parser.individuals errors = [] for individual in individuals.values(): if individual.birth is not None and \ individual.death is not None and \ individual.birth >= individual.death: errorMessage = f'Birth date {individual.birth} occurs after death date {individual.death}' errors.append(GedcomError(ErrorType.error, 'US03', individual, errorMessage)) elif individual.birth is None and individual.death is not None: errorMessage = f'Birth is null while death date is not.' errors.append(GedcomError(ErrorType.error, 'US03', individual, errorMessage)) return errors
def male_last_name(parser): errors = [] for family in parser.families.values(): father = family.husband_id children = family.child_ids # obtain father last_name for individual in parser.individuals.values(): if individual.id == father: father_last_name = individual.name.split()[1] child_last_name = "" for individual in parser.individuals.values(): for i in range(len(children)): if individual.sex == "M": if individual.id == children[i]: child_last_name = individual.name.split()[1] if child_last_name != father_last_name: errorMessage = f'Males ({individual.name}) in {family} do not have the same last name' errors.append( GedcomError(ErrorType.error, 'US16', family, errorMessage)) return errors
def marriage_before_divorce(parser): """Makes sure marriage come before a divorce""" families = parser.families errors = [] for family in families.values(): if family.married is not None and \ family.divorced is not None and \ family.married >= family.divorced: errorMessage = f'Marriage date {family.married} is after divorce date {family.divorced}' errors.append( GedcomError(ErrorType.error, 'US04', family, errorMessage)) elif family.married is None and family.divorced is not None: errorMessage = f'Marriage date is None while divorce date is not.' errors.append( GedcomError(ErrorType.error, 'US04', family, errorMessage)) return errors
def dateArgsToDate(dateArgs, gedcom_object): dayInt = int(dateArgs[0]) monthInt = TagDefinition.month_strs.index(dateArgs[1]) + 1 yearInt = int(dateArgs[2]) try: return date(yearInt, monthInt, dayInt) except ValueError: error = GedcomError( ErrorType.error, "US42", gedcom_object, "Incorrect Date Given. Correct this error before running the program. Exiting." ) print(error) exit()
def poligamy_exists(intervals): for i, interval_outer in enumerate(intervals): ID_outer = interval_outer["ID"] for interval_inner in intervals[i + 1:]: if interval_inner["ID"] == ID_outer and intervals_intersect( interval_outer, interval_inner): individual = db.individuals[db.individuals.ID == ID_outer].iloc[0].reference family1 = interval_inner["reference"].id family2 = interval_outer["reference"].id errorMessage = f'Bigamy between Family {family1} and Family {family2}' errors.append( GedcomError(ErrorType.error, 'US11', individual, errorMessage))
def no_married_siblings(parser): """Returns errors for siblings who are married""" families = parser.families errors = [] for fam in families.values(): if fam.husband_id and fam.wife_id: sublist = [fam.husband_id, fam.wife_id] for check_fam in families.values(): if check_fam.child_ids: if all(x in check_fam.child_ids for x in sublist): errorMessage = f'Siblings {fam.husband_id} and {fam.wife_id} of {check_fam} are married in {fam}' errors.append( GedcomError(ErrorType.error, 'US18', fam, errorMessage)) return errors
def unique_names_and_birth_date(parser): """Returns errors for individuals sharing a name and a birth date""" individuals = parser.individuals errors = [] indivs_by_name_birthdate = {} for indi in individuals.values(): # If name or birth are not given for the individual, these keys will be None # This means two people with the same name and no birthday will give a warning name_birthdate = (indi.name, indi.birth) if name_birthdate in indivs_by_name_birthdate: other_indi = indivs_by_name_birthdate[name_birthdate] errorMessage = f'Individual {indi} has the same name and birth date as {other_indi}' errors.append( GedcomError(ErrorType.anomaly, 'US23', indi, errorMessage)) else: indivs_by_name_birthdate[name_birthdate] = indi return errors
def marriage_before_death(parser): """Makes sure mariages come before death""" individuals = parser.individuals families = parser.families errors = [] for individual in individuals.values(): if individual.fams is not None: fam = families.get(individual.fams) if fam is not None: if fam.married is not None and \ individual.death is not None and \ fam.married >= individual.death: errorMessage = f'Married {fam.married} after death {individual.death}' errors.append(GedcomError(ErrorType.error, 'US05', individual, errorMessage)) # elif fam.married is None and \ # individual.death is not None: # errorMessage = f'Not married but has died' # errors.append(GedcomError(ErrorType.error, 'US08', fam, errorMessage)) return errors
def no_marriages_to_children(parser, db): errors = [] for individual in parser.individuals.values(): famc = individual.famc if famc != None: family = parser.families[famc] mother = family.wife_id father = family.husband_id myself = individual.id married_to_parent = db.families.loc[ (db.families["wife_id"] == mother) & (db.families["husband_id"] == myself) | (db.families["wife_id"] == myself) & (db.families["husband_id"] == father) ] for family in married_to_parent.iterrows(): family = family[1] parent = "" if myself == family.husband_id: parent = family.wife_id else: parent = family.husband_id errorMessage = f'Parent {parent} married child {myself}' errors.append(GedcomError(ErrorType.error, 'US17', family.reference, errorMessage)) return errors
def divorce_before_death(parser): """Makes sure divorces come before death""" individuals = parser.individuals families = parser.families errors = [] for individual in individuals.values(): if individual.fams is not None: fam = families.get(individual.fams) # print(individual.name) # print(individual.death) # print(fam.divorced) if fam is not None: if fam.divorced is not None and \ individual.death is not None and \ fam.divorced >= individual.death: errorMessage = f'Divorced {fam.divorced} after death {individual.death}' errors.append(GedcomError(ErrorType.error, 'US06', individual, errorMessage)) # elif fam.divorced is None and \ # individual.death is not None: # errorMessage = f'' # errors.append(GedcomError(ErrorType.error, 'US06', individual, errorMessage)) return errors