def test_insert(): D = Donors() rec = Record("C00629618|||||||PEREZ, JOHN A|||90017|||01032017|40||||||") D.insert(rec) assert(D._donors == {'90017': {'PEREZ, JOHN A': [2017]}}) rec = Record("C00629618|||||||PEREZ, JOHN A|||90017|||01022012|40||||||") D.insert(rec) assert (D._donors == {'90017': {'PEREZ, JOHN A': [2017, 2012]}}) rec = Record("xyz|||||||CHANDAN, DEEPAK|||90017|||01022011|40||||||") D.insert(rec) assert (D._donors == {'90017': {'PEREZ, JOHN A': [2017, 2012], 'CHANDAN, DEEPAK': [2011]}}) rec = Record("xyz|||||||someone|||34567|||01022018|40||||||") D.insert(rec) assert (D._donors == {'90017': {'PEREZ, JOHN A': [2017, 2012], 'CHANDAN, DEEPAK': [2011]}, '34567': {'someone': [2018]}})
class AnalyticsApp(object): def __init__(self, ofname, perc, verbosity=1): """ Constructor :param ofname: output file name :param perc: percentile value (> 0 and <= 100) :param verbosity: how much diagnostics to produce """ self._ofname = ofname self._perc = perc if (self._perc <= 0) or (self._perc > 100): raise ValueError("Invalid percentile value") if not isinstance(ofname, str): raise ValueError("Output filename must be a string") # A data structure containing (some) information about all donors self._all_donors = Donors() # A data structure containing (some) information about all repeat donations self._repeats = RepeatDonations() if not isinstance(verbosity, int): raise ValueError("Verbosity must be an integer") self._verbosity = verbosity if self._verbosity >= 1: print("Configuration:") print(" Output file: ", self._ofname) print(" Percentile : ", self._perc) print(" Verbosity : ", self._verbosity) self._ofile = open(self._ofname, "w") # to count how many records processed self._ctr = 0 @property def perc(self): """ Get the percentile value this app is configured with :return: percentile """ return self._perc @property def ofname(self): return self._ofname def update(self, recstr): """ Updates its internal state with new donation information. :param recstr: the record in string format :return: None """ self._ctr += 1 if self._verbosity > 3: print(recstr) try: rec = Record(recstr) except BadRecord: return if self._all_donors.is_repeat_donor(rec): """ This is a repeat donor. """ if self._verbosity > 1: print("[AnalyticsApp.update] Repeat donor {0:30s} {1:5s} {2:4d} {3:d}".format(rec.NAME, rec.ZIP_CODE, rec.TRANSACTION_DT.year, self._ctr)) self._repeats.insert(rec) self._print(rec) else: """ We have not seen any previous instance of this donor donating. So, we insert this new information into the donors database. """ self._all_donors.insert(rec) def _print(self, rec): """ Write data to output file :param rec: obejct of class Record :return: None """ self._ofile.write("{0}|{1}|{2}|{3}|{4}|{5}\n".format( rec.CMTE_ID, rec.ZIP_CODE, rec.TRANSACTION_DT.year, self._repeats[rec].percentile(self._perc), self._repeats[rec].total_amount, self._repeats[rec].num_donations(), )) def finalize(self): """ Called by the user at the end of the app. :return: None """ self._ofile.close()