Example #1
0
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]}})
Example #2
0
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()