def birth_before_death_of_parents(self): if not self._husband or not self._wife: raise AttributeError("Missing husband/wife") if not self._husband.get_deathDate() and not self._wife.get_deathDate( ): return True if len(self._children) == 0: return True death = self._wife.get_deathDate() hDeath = self._husband.get_deathDate() if not hDeath: for c in self._children: if c.get_birthDate() > death: #return False raise Error( 'ERROR', 'FAMILY', 'US09', c.get_lineNum()["BIRT"], f"Child birthday {c.get_birthDate()} is after death date of mother {death}" ) return True # hDeath = hDeath + (0, 9, 0) # if hDeath[1] > 12: # hDeath[1] = hDeath[1] % 12 # hDeath[0] = hDeath[0] + 1 # if not death: # for c in self._children: # if c.get_birthDate() > hDeath: # # return False # raise Error('ERROR', 'FAMILY', 'US09', c.get_lineNum()['BIRT'], # f"Child birthday {c.get_birthDate()} is after 9 month of death date of father {hDeath}") # return True # if hDeath < death: # if not death and not hDeath: # return True if hDeath: hDeath = list(map(sum, zip(hDeath, (0, 9, 0)))) if hDeath[1] > 12: hDeath[1] = hDeath[1] % 12 hDeath[0] = hDeath[0] + 1 hDeath = tuple(hDeath) if death is None or hDeath < death: death = hDeath death = tuple(death) for c in self._children: if c.get_birthDate() > death: # return False raise Error( 'ERROR', 'FAMILY', 'US09', c.get_lineNum()['BIRT'], f"Child birthday {c.get_birthDate()} is after 9 month of death date of father {hDeath}" ) return True
def update_name(self, name): if len(name) < 3: return Error("Name must be at least 3 characters long.", "Name parameter must be at least 3 characters long.", 400, "https://en.wikipedia.org/wiki/HTTP_400") elif len(name) > 255: return Error( "Name cannot be longer than 255 characters.", "Name parameter cannot be longer than 255 characters.", 400, "https://en.wikipedia.org/wiki/HTTP_400") self.name = name db.session.commit() return self
def unique_families_by_spouses(self): check_list = [] for _, family in self._families: if not family.get_husband() or not family.get_wife(): raise AttributeError("no husband or wife") if not family.get_husband().get_name() or not family.get_wife( ).get_name(): raise AttributeError("no husband or wife name") if not family.get_marriedDate(): raise AttributeError("no marriage date") this_fam_info = [ family.get_husband().get_name(), family.get_wife.get_name(), family.get_marriedDate() ] if this_fam_info in check_list: # return False raise Error( 'ANOMALY', 'GEDCOM', 'US024', family.get_lineNum()['FAM ID'], f"Family{family.get_id()} has repeated marriage date{family.get_marriedDate()} or spouse name{family._wife.get_name()}" ) check_list.append(this_fam_info) return True
def patch(self, usage_id, new_value): usage = UsageModel.find_by_id(usage_id) new_value = float(new_value) if usage.min_value > new_value or usage.max_value < new_value: return { "errors": Error( "New value does not fall within the expected range. ({} - {})" .format(usage.min_value, usage.max_value), "{} is outside of ({} - {})".format( new_value, usage.min_value, usage.max_value), 422, "").to_json() }, 422 print("url is: " + "{}/{}/{}".format( app.config['HOMELYNK_URI'], usage.external_item_id, new_value)) response = requests.get( url="{}/{}/{}".format(app.config['HOMELYNK_URI'], usage.external_item_id, int(new_value))) home_response = response.json() item = ItemModel.find_by_id(usage.item_id) item_in_json = item.to_json() fake_event = { 'last_use_timestamp': datetime.now().timestamp(), 'data_type': usage.unit.value, 'data': float(home_response["current_value"]), 'usage_id': usage.id } item_in_json['last_use'] = fake_event return item_in_json, 200
def less_then_150_years_old(self): if self.get_age() < 150: return True else: raise Error( 'ANOMALY', 'INDIVIDUAL', 'US07', self.get_lineNum()['BIRT'], f" Individual's Age {self.get_age()} is greater than 150")
def multiple_births_lessOrEqual_than_5( self): # cannot catch multi multiples; not sure if need to from datetime import date today = date.today() try: births = sorted( list( map(lambda i: abs((date(*i) - today).days), [x.get_birthDate() for x in self.get_children()]))) except AttributeError: raise AttributeError("Missing birthdate for children") if len(births) <= 5: return True multi, sameDay, pre = 0, 0, births[0] for i in range(len(births)): if pre == births[i]: multi += 1 sameDay += 1 elif births[i] - pre == 1: multi, sameDay = sameDay + 1, 1 else: multi, sameDay = 1, 1 pre = births[i] if multi >= 5: raise Error( 'ANOMALY', 'FAMILY', 'US14', self.get_lineNum()["CHIL"], f'Family has more than five children with the same birthday' ) #return False return True
def marriage_before_death(self): from datetime import date if not self._husband or not self._wife or not self.get_marriedDate(): raise AttributeError("Missing husband/wife/marriedDate") if not self._husband.get_deathDate() and not self._wife.get_deathDate( ): return True death = None if not self._husband.get_deathDate(): death = self._wife.get_deathDate() elif not self._wife.get_deathDate(): death = self._husband.get_deathDate() else: if self._husband.get_deathDate() > self._wife.get_deathDate(): death = self._wife.get_deathDate() else: death = self._husband.get_deathDate() marriage = self._marriedDate timedelta = date(*marriage) - date(*death) if timedelta.days <= 0: return True else: raise Error( 'ERROR', 'FAMILY', 'US05', self.get_lineNum()["MARR"], f"Family marriage date {marriage} is after death date of husband{self._husband.get_deathDate()} or wife{self._wife.get_deathDate()}" )
def marriage_after_14(self) -> bool: from datetime import date if not self._husband or not self._wife or not self._marriedDate: raise AttributeError("Missing husband/wife/marriedDate") if not self._husband.get_birthDate() or not self._wife.get_birthDate(): raise AttributeError("Missing birthdate for husband/wife") if not self._husband or not self._wife or not self._marriedDate: raise AttributeError("Missing husband/wife/marriedDate") if not self._husband.get_birthDate() or not self._wife.get_birthDate(): raise AttributeError("Missing birthdate for husband/wife") husbandMarryAge = (date(*self._marriedDate) - date(*self._husband.get_birthDate())).days // 365 wifeMarryAge = (date(*self._marriedDate) - date(*self._wife.get_birthDate())).days // 365 if (husbandMarryAge > 14 and wifeMarryAge > 14): return True else: raise Error( 'ERROR', 'FAMILY', 'US10', self.get_lineNum()["MARR"], f"Family marriage date {self.get_marriedDate()} is not 14 years after" f"Husband birthday {self._husband.get_birthDate()} or Wife birthday {self._wife.get_birthDate()}" )
def siblings_should_not_marry(self): if not self._husband or not self._wife: raise AttributeError("Missing husband or wife") if not self._husband.get_parent_family() and not self._wife.get_parent_family(): raise AttributeError( "Missing husband and wife parent") if not self._husband.get_parent_family().get_id() == self._wife.get_parent_family().get_id(): return True else:raise Error('ERROR', 'FAMILY', 'US18', self.get_lineNum()['FAM ID'], f"Siblings in family {self.get_id()} are married.")
def divorce_before_death(self) -> bool: from datetime import date if not self._husband or not self._wife: raise AttributeError("Missing husband/wife") if not self._husband.get_deathDate() and not self._wife.get_deathDate( ): return True if not self._divorced: return True deathdays = None if self._husband.get_deathDate() and self._wife.get_deathDate(): deathdays = (date(*self._divorced) - date(*self._husband.get_deathDate())).days if deathdays > (date(*self._divorced) - date(*self._wife.get_deathDate())).days: deathdays = (date(*self._divorced) - date(*self._wife.get_deathDate())).days elif not self._husband.get_deathDate(): deathdays = (date(*self._divorced) - date(*self._wife.get_deathDate())).days elif not self._wife.get_deathDate(): deathdays = (date(*self._divorced) - date(*self._husband.get_deathDate())).days if deathdays < 0: return True else: raise Error( 'ERROR', 'FAMILY', 'US05', self.get_lineNum()["DIV"], f"Family divorce date {self.get_divorcedDate()} is after death date of husband{self._husband.get_deathDate()} or wife{self._wife.get_deathDate()}" )
def order_siblings_by_age(self): """ Need one extra step which filters out the Nones. Not sure if necessary. :return: list of references in the order of descending age """ res = sorted(self.get_children(), key=lambda x: x.get_age(days=True), reverse=True) if list(filter(lambda x: x.get_birthDate() != None, res)): return True else: raise Error('ERROR', 'FAMILY', 'US28', self.get_lineNum()['FAM ID'], f"Family {self.get_id()} Siblings not ordered by age")
def fewer_than_15_siblings(self): """ if self._children is empty, it is a empty list which the length is 0 :return: boolean if the length of self._children is less then 15 """ if len(self._children) < 15: return True else: raise Error('ERROR', 'FAMILY', 'US15', self.get_lineNum()["FAM ID"], f"The siblings of the family is more than 15.")
def first_cousins_should_not_marry(self): if not self.get_parent_family(): raise AttributeError("missing parent family") if not self.get_parent_family().get_husband( ) or not self.get_parent_family().get_wife(): raise AttributeError("missing husband or wife") if not self.get_parent_family().get_husband().get_parent_family( ) or not self.get_parent_family().get_wife().get_parent_family(): raise AttributeError("missing husband/wife's parent family") daddy = self.get_parent_family().get_husband() daddy_siblings = self.get_parent_family().get_husband( ).get_parent_family().get_children()[:] daddy_siblings.remove(daddy) # if singleton, this loop does nothing for daddy_sibling in daddy_siblings: daddy_sibling_families = daddy_sibling.get_family( ) # consider past families for child_fam in daddy_sibling_families: for first_cousin in child_fam.get_children(): if first_cousin == self: #return False raise Error( 'ANOMALY', 'INDIVIDUAL', 'US19', first_cousin.get_lineNum()['INDI ID'], f"first_cousin {first_cousin.get_id()} is married to each other" ) mummy = self.get_parent_family().get_wife() mummy_siblings = self.get_parent_family().get_wife().get_parent_family( ).get_children()[:] mummy_siblings.remove(mummy) # if singleton, this loop does nothing for mummy_sibling in mummy_siblings: mummy_sibling_families = mummy_sibling.get_family( ) # consider past families for mummy_sibling_fam in mummy_sibling_families: for first_cousin in mummy_sibling_fam.get_children(): if first_cousin == self: #return False raise Error( 'ANOMALY', 'INDIVIDUAL', 'US19', first_cousin.get_lineNum()['INDI ID'], f"first_cousin {first_cousin.get_id()} is married to each other" ) return True
def post(self): errors = [] if 'usage_id' in request.form.keys(): usage_id = request.form['usage_id'] data_type = request.form['data_type'] data = request.form['data'] else: request_data = json.loads(request.data) usage_id = request_data['usage_id'] data_type = request_data['data_type'] data = request_data['data'] usage = UsageModel.find_by_id(usage_id) if usage is None: errors.append( Error( "Cannot find usage with id: {}".format(usage_id), "UsageModel.find_by_id({}) returns None".format(usage_id), 404, "https://en.wikipedia.org/wiki/HTTP_404")) if UnitEnum.has_value(data_type): data_type = UnitEnum(data_type) else: errors.append( Error( '"{}" is not a valid unit type.'.format(data_type), "UnitEnum.has_value({}) returned False".format(data_type), 400, "https://en.wikipedia.org/wiki/HTTP_400")) if len(errors) > 0: all_errors_in_json = [error.to_json() for error in errors] return {"errors": all_errors_in_json}, 422 if usage.unit != data_type: error = Error( 'The unit type of the usage with id "{}" does not match the given "{}".' .format(usage_id, data_type), "usage.unit does not equal data_type.", 422, "https://en.wikipedia.org/wiki/HTTP_422") return {"errors": error.to_json()}, 422 event = EventModel(usage_id, data, round(datetime.now().timestamp())) event.save_to_db() return event.to_json(), 201
def dates_before_current_date(self): from datetime import date today = date.today() for _, indi in self._individuals: if not indi.get_birthDate(): raise AttributeError("missing birthdate for individual") if not (today - date(indi.get_birthDate())).days < 0: #return False raise Error( 'ERROR', 'GEDCOM', 'US01', indi.get_lineNum()['INDI ID'], f"Individual{indi.get_id()}'s birthday {indi.get_birthDate()} is after today's date {today}" ) if not indi.get_deathDate() == None: if not (today - date(indi.get_deathDate())).days < 0: # return False raise Error( 'ERROR', 'GEDCOM', 'US01', indi.get_lineNum()['INDI ID'], f"Individual{indi.get_id()}'s death date {indi.get_deathDate()} is after today's date {today}" ) for _, fam in self._families: if not fam.get_marriedDate(): raise AttributeError("missing marriedDate for family") if not (today - date(fam.get_marriedDate())).days < 0: #return False raise Error( 'ERROR', 'GEDCOM', 'US01', fam.get_lineNum()['FAM ID'], f"Family{fam.get_id()}'s marriage date {fam.get_marriedDate()} is after today's date {today}" ) if not fam.get_divorcedDate() == None: if not (today - date(fam.get_divorcedDate())).days < 0: #return False raise Error( 'ERROR', 'GEDCOM', 'US01', fam.get_lineNum()['INDI ID'], f"Individual{fam.get_id()}'s divorce date {fam.get_divorcedDate()} is after today's date {today}" ) return True
def birth_before_marriage_of_parents(self): if not self._husband or not self._wife: raise AttributeError("Missing husband/wife") if not self.get_marriedDate(): raise AttributeError("Missing marrageDate") for c in self._children: if not c.get_birthDate(): raise AttributeError("Missing child birthDate") if c.get_birthDate() <= self.get_marriedDate(): # return False raise Error('ANOMALY', 'FAMILY', 'US08', c.get_lineNum()["BIRT"], f"Child birthday {c.get_birthDate()} is after marriage date of Family {self.get_marriedDate()}") return True
def marriage_before_divorce(self): from datetime import date marriage = self.get_marriedDate() divorce = self.get_divorcedDate() if not marriage: raise AttributeError("Missing marriage date") if not divorce: return True timedelta = date(*marriage) - date(*divorce) if timedelta.days < 0: return True else: raise Error('ERROR', 'FAMILY', 'US04', self.get_lineNum()["MARR"], f"Family marriage date {marriage} is after divorce date {divorce}")
def get(self): results_array = analyze_fake_event_data() if results_array is None: print('here', 30, 'error') error = Error( "The analysis did not complete correctly." "The analysis went HAM and broke everything.", 500, "https://en.wikipedia.org/wiki/HTTP_500") return {"errors": error.to_json()}, 500 else: return {"results": results_array}, 200
def birth_before_death(self): from datetime import date if not self._birthDate or not self._deathDate: raise AttributeError("Missing attribute") if (date(*self._deathDate) - date(*self._birthDate)).days > 0: return True else: raise Error( 'ERROR', 'INDIVIDUAL', 'US03', self.get_lineNum()['BIRT'], f" Individual's Birthday {self.get_birthDate()} is after individual's death date {self.get_deathDate()}" )
def correct_gender_for_role(self): """ throw error when missing husband/wife or missing gender of husband/wife :return: boolean from compare the string of husband and wife gender """ if (not self._husband or not self._wife): raise AttributeError("missing husband or wife") if (not self._husband.get_gender() or not self._wife.get_gender()): raise AttributeError( "missing gender of husband or wife") if self._husband.get_gender() == "M" and self._wife.get_gender() == "F": return True else:raise Error ('ERROR', 'FAMILY', 'US21', self.get_lineNum()["FAM ID"], f"Family {self.get_id()} 's husband {self.get_husband().get_id()} 's gender {self.get_husband().get_gender()} is incorrect " f"or wife {self.get_wife().get_id()} 's gender {self.get_wife().get_gender()} is incorrect.")
def dfs(family, last_name): flag = True for child in family.get_children(): if child.get_gender() == None: raise AttributeError("child's gender is not set yet") if child.get_gender() == "F": continue if not child.get_name(): raise AttributeError("Child's name is missing") if child.get_name().split('/')[1] != last_name: #return False raise Error('ERROR', 'FAMILY', 'US16', child.get_lineNum()['NAME'], f"Male Child's last name {child.get_name().split('/')[1]} doesn't match family last name {last_name}") for fam in child.get_family(): flag = dfs(fam, check_last_name) and flag return flag
def dfs(indi): # print(indi.get_id()) result = True for family in indi.get_family(): for child in family.get_children(): if child in spouse: #return False raise Error( 'ERROR', 'INDIVIDUAL', 'US17', child.get_lineNum()['INDI ID'], f"Parent is married to a descendant{child.get_id()}" ) result = dfs(child) and result return result
def siblings_spacing(self): from datetime import date threshold = [1, 240] # 8 month is ambiguous, let's just assume 8*30=240 days n = len(self.get_children()) if n < 2: return True sumOfDifference = 0 for i in range(n - 1): timedelta = date(*self.get_children()[i].get_birthDate()) - date( *self.get_children()[i + 1].get_birthDate()) sumOfDifference += abs(timedelta.days) if not (threshold[0] < sumOfDifference // (n - 1) < threshold[1]): return True else: raise Error('ERROR', 'FAMILY', 'US13', self.get_lineNum()["FAM ID"], f"The birth date spacing of siblings is greater than 2 days and less than 8 month")
def unique_name_and_birth_date(self): dic = set() for indi in self._individuals.values(): if indi.get_birthDate(): key = indi.get_name().replace("/", "") + "a".join( list(map(str, indi.get_birthDate()))) # print(key) if key not in dic: dic.add(indi) else: #return False raise Error( 'ANOMALY', 'GEDCOM', 'US023', indi.get_lineNum()['INDI ID'], f"Individual{indi.get_id()} appears multiple times in the GEDCOM file" ) return True
def unique_first_names_in_families(self): for _, family in self._families: check_list = [] for child in family.get_children(): if not child.get_name() or not child.get_birthDate(): raise AttributeError("no name or birthdate for child") child_info = [child.get_name(), child.get_birthDate()] if child_info in check_list: # return False raise Error( 'ERROR', 'GEDCOM', 'US025', child.get_lineNum()['INDI ID'], f"Child{child.get_id()}'s birthday{child.get_birthDate()}or name{child.get_name()} is repeated in a family" ) check_list.append(child_info) return True
def delete(self, group_id, item_id): errors = validate(group_id=group_id, item_id=item_id, method="GroupItemResource.delete") if len(errors) > 0: all_errors_in_json = [error.to_json() for error in errors] return {'errors': all_errors_in_json}, 500 item_group = ItemGroupModel.find_by_item_id_and_group_id(item_id, group_id) item_group.delete_from_db() item_group = ItemGroupModel.find_by_item_id_and_group_id(item_id, group_id) if item_group is not None: errors.append(Error("An unexpected error occurred item was not removed from group.", "ItemGroupModel.find_by_item_id_and_group_id({}, {}) did not return None".format(item_id, group_id), 500, "https://en.wikipedia.org/wiki/HTTP_500")) else: group = GroupModel.find_by_id(group_id) return group.to_json(), 200
def birth_before_marriage(self): from datetime import date if not self._birthDate or not self._family: raise AttributeError( "Missing self birthday or family marriage date") # if not self._parentFamily.get_marriedDate(): raise AttributeError("Missing attribute") for family in self.get_family(): if not family.get_marriedDate(): raise AttributeError("Missing attribute") timedelta = date(*family.get_marriedDate()) - date( *self._birthDate) if (timedelta.days <= 0): #return False raise Error( 'ERROR', 'INDIVIDUAL', 'US02', self.get_lineNum()['BIRT'], f" Individual's Birthday {self.get_birthDate()} is after marriage date of Family {family.get_marriedDate()}" ) return True
def parents_not_too_old(self): if not self._husband or not self._wife: raise AttributeError("missing husband or wife") if not self._husband.get_age() or not self._wife.get_age(): raise AttributeError( "missing age for husband or wife") if not self._husband.get_age() or not self._wife.get_age(): raise AttributeError( "missing age for husband or wife") wife_age = self._wife.get_age() husband_age = self._husband.get_age() for child in self._children: if not child.get_age(): raise AttributeError("missing child age") wife_diff = wife_age - child.get_age() husband_diff = husband_age - child.get_age() if wife_diff >= 60 or husband_diff >= 80: raise Error('ANOMALY', 'FAMILY', 'US12', self.get_lineNum()["FAM ID"], f"Family Mother's age {wife_age} exceeds child's age {child.get_age()} by 60 or Father's age {husband_age} exceeds child's age by 80") # return False return True
def test_error(self): raise Error("123", 1, 2, 3, 4)
def aunts_and_uncles(self): if (not self._parentFamily): raise AttributeError("missing value") if (not self._parentFamily.get_husband() or not self._parentFamily.get_wife()): raise AttributeError("missing value") if (not self._parentFamily.get_husband().get_parent_family() or not self._parentFamily.get_wife().get_parent_family()): raise AttributeError("missing value") dad_grand_family = self._parentFamily.get_husband().get_parent_family() mom_grand_family = self._parentFamily.get_wife().get_parent_family() for dad_side_aunt_uncle in dad_grand_family.get_children(): if (dad_side_aunt_uncle == self.get_parent_family().get_husband()): continue check_id = dad_side_aunt_uncle.get_id() for dad_side_family in dad_side_aunt_uncle.get_family(): if (not dad_side_family.get_husband() or not dad_side_family.get_wife()): raise AttributeError("missing value") uncle_id = dad_side_family.get_husband().get_id() aunt_id = dad_side_family.get_wife().get_id() if (uncle_id == aunt_id): #return False raise Error( 'ERROR', 'INDIVIDUAL', 'US20', dad_side_family.get_husband().get_lineNum()['INDI ID'], f" Individual's Aunt{aunt_id} and Uncle{uncle_id} has the same ID" ) for each_child in dad_side_family.get_children(): if (uncle_id == each_child.get_id() or aunt_id == each_child.get_id()): #return False raise Error( 'ERROR', 'INDIVIDUAL', 'US20', dad_side_family.get_husband().get_lineNum() ['INDI ID'], f" Individual's Aunt{aunt_id} or Uncle{uncle_id} is married to their child {each_child.get_id()}" ) for mom_side_aunt_uncle in mom_grand_family.get_children(): if (mom_side_aunt_uncle == self.get_parent_family().get_wife()): continue for mom_side_family in mom_side_aunt_uncle.get_family(): if (not mom_side_family.get_husband() or not mom_side_family.get_wife()): raise AttributeError("missing value") uncle_id = mom_side_family.get_husband().get_id() aunt_id = mom_side_family.get_wife().get_id() if (uncle_id == aunt_id): #return False raise Error( 'ERROR', 'INDIVIDUAL', 'US20', mom_side_family.get_husband().get_lineNum()['INDI ID'], f" Individual's Aunt{aunt_id} and Uncle{uncle_id} has the same ID" ) for each_child in mom_side_family.get_children(): if (uncle_id == each_child.get_id() or aunt_id == each_child.get_id()): #return False raise Error( 'ERROR', 'INDIVIDUAL', 'US20', mom_side_family.get_husband().get_lineNum() ['INDI ID'], f" Individual's Aunt{aunt_id} or Uncle{uncle_id} is married to their child {each_child.get_id()}" ) return True