#!/usr/bin/env python
"""
Takes the database from the output of integrate.py (e.g. after the disambiguated
inventors have been merged into the database) and computes statistics on top of it
"""

import uuid
from datetime import datetime
from lib import alchemy
from collections import Counter, defaultdict

def compute_future_citation_rank():
    """
    Ranks each patent by number of future citations in a given year
    Returns nested dictionary:
        years[YEAR][PATENT_ID] = list of Citation.number that cited PATENT_ID in YEAR
    """
    citations = (c for c in alchemy.session.query(alchemy.USPatentCitation).yield_per(1))
    years = defaultdict(lambda: defaultdict(list))
    print "Counting citations...", datetime.now()
    for cit in citations:
      if cit.date:
        year = cit.date.year
        patid = cit.patent_id
        years[year][patid].append(cit.number)
    print "Finished counting citations", datetime.now()
    return years

def insert_future_citation_rank(years):
    """
    Accepts as input the dictionary returned from compute_future_citation_rank:
        years[YEAR][PATENT_ID] = number of times PATENT_ID was cited in YEAR
    Inserts rows into the correct table:
    """
    # remove old rows to make way for new rankings
    deleted = alchemy.session.query(alchemy.FutureCitationRank).delete()
    print 'Removed {0} rows from FutureCitationRank'.format(deleted)
    print 'Inserting records in order...', datetime.now()
    for year in years.iterkeys():
        rank = 0
        prev_num_cits = float('inf')
        commit_counter = 0
        for i, record in enumerate(years[year].iteritems()):
            if record[1] < prev_num_cits:
                prev_num_cits = len(record[1])
                rank += 1
            row = {'uuid': str(uuid.uuid1()),
                   'patent_id': record[0],
                   'num_citations': len(record[1]),
                   'year': year,
                   'rank': rank}
            dbrow = alchemy.FutureCitationRank(**row)
            alchemy.session.merge(dbrow)
            if (i+1) % 1000 == 0:
                alchemy.commit()
    alchemy.commit()
    print 'Finished inserting records', datetime.now()


def compute_inventor_rank():
    """
    Ranks each inventor by number of granted patents in a given year
    Returns nested dictionary:
        years[YEAR][INVENTOR_ID] = number of patents granted in YEAR to INVENTOR_ID
    """
    patents = (p for p in alchemy.session.query(alchemy.Patent).yield_per(1))
    years = defaultdict(Counter)
    print 'Counting granted patents...', datetime.now()
    for pat in patents:
        year = pat.date.year
        inventors = pat.inventors
        for inventor in inventors:
            years[year][inventor.id] += 1
    print 'Finished counting', datetime.now()
    return years

def insert_inventor_rank(years):
    """
    Accepts as input the dictionary returned from compute_inventor_rank:
        years[YEAR][INVENTOR_ID] = number of patents granted in YEAR to INVENTOR_ID
    Inserts rows into the correct table:
    """
    deleted = alchemy.session.query(alchemy.InventorRank).delete()
    print 'removed {0} rows'.format(deleted)
    print 'Inserting records in order...', datetime.now()
    for year in years.iterkeys():
        rank = 0
        prev_num_cits = float('inf')
        commit_counter = 0
        for i, record in enumerate(years[year].most_common()):
            if record[1] < prev_num_cits:
                prev_num_cits = record[1]
                rank += 1
            row = {'uuid': str(uuid.uuid1()),
                   'inventor_id': record[0],
                   'num_patents': record[1],
                   'patent_year': year,
                   'rank': rank}
            dbrow = alchemy.InventorRank(**row)
            alchemy.session.merge(dbrow)
            if (i+1) % 1000 == 0:
                alchemy.commit()
    alchemy.commit()
    print 'Finished inserting records', datetime.now()


if __name__=='__main__':
    years = compute_future_citation_rank()
    insert_future_citation_rank(years)

    years = compute_inventor_rank()
    insert_inventor_rank(years)

@@ -2194,16 +2194,992 @@
 .now()%0A%0A
+def insert_cited_by(years):%0A    %22%22%22%0A    Accepts as input the dictionary returned from compute_future_citation_rank:%0A        years%5BYEAR%5D%5BPATENT_ID%5D = number of times PATENT_ID was cited in YEAR%0A    Inserts records into CitedBy table%0A    %22%22%22%0A    deleted = alchemy.session.query(alchemy.CitedBy).delete()%0A    print 'Removed %7B0%7D rows from FutureCitationRank'.format(deleted)%0A    print 'Inserting records in order...', datetime.now()%0A    for year in years.iterkeys():%0A        for i, record in enumerate(years%5Byear%5D.iteritems()):%0A            row = %7B'uuid': str(uuid.uuid1()),%0A                   'patent_id': record%5B0%5D,%0A                   'year': year%7D%0A            for citation in record%5B1%5D:%0A                row.update(%7B'citation_id': citation%7D)%0A                dbrow = alchemy.CitedBy(**row)%0A                alchemy.session.merge(dbrow)%0A            if (i+1) %25 1000 == 0:%0A                alchemy.commit()%0A    alchemy.commit()%0A    print 'Finished inserting records', datetime.now()%0A%0A%0A
 %0Adef com
@@ -5049,16 +5049,43 @@
 k(years)
+%0A    insert_cited_by(years)
 %0A%0A    ye

add insertion for citedby table