from time import time
from sys import argv
TIME = time()
def checkpoint ():
    """ A stopwatch. Prints seconds elapsed since last call to checkpoint. """
    global TIME
    if TIME > 0:
        elapsed_time = time() - TIME
        print ('............. Elapsed time : ' + str(elapsed_time) )
    TIME = time()

class Arbalet:
    """ Primitive key-value store "Arbalet v1".
        See https://kirgizov.link/teaching/esirem/information-systems-2021/TD-1-2.pdf
    """
    
    def __init__(self):
        """ Creates a new empty key-value store """
        # Initialize the set of tuples (key, value)
        self.data = []
        
    def search (self, key):
        """ Find a corresponding set of values.
            Return empty list if key does not exists.
        """
        r = []
        for d in self.data:
            if d[0] == key:
                r.append (d[1])
        return r
    
    def insert (self, key, value):
        """ Associate value to the key.
            To accelerate data insertion we insert a new tuple in the end of the list.
            But Exercice 2.5 would take some time to finish. """
        tulpa = (key, value)
        self.data.append(tulpa)
    
    def delete_one (self, key, value):
        """ Delete a value associated to the key. """
        # Reverse order is important here !
        # Otherwise we should juggle with indices.
        for i in reversed (range (len (self.data))):
            if self.data[i][0] == key and self.data[i][1] == value:
                del self.data[i]
    
    def delete_all (self, key):
        """ Delete all values associated to the key. """
        for i in reversed (range (len (self.data))):
            if self.data[i][0] == key:
                del self.data[i]

def test_arbalet():
    print ('We test...')
    a = Arbalet()
    b = Arbalet()
    a.insert ("test", 0)
    a.insert ("hzhh", 1)
    a.insert ("test", 1)
    b.insert ("test", 0)
    assert a.search('hei') == []
    assert a.search('test') == [0,1]
    assert b.search('test') == [0]
    a.delete_one ('test', 1)
    assert a.search('test') == [0]
    a.delete_one ('test', 0)
    assert a.search('test') == []
    a.insert ("test", 0)
    a.insert ("test", 1)
    a.insert ("test", 3)
    assert a.search('test') == [0,1,3]
    a.delete_all ('test')
    assert a.search('test') == []
    assert len (b.search ('test')) == 1
    print ('Tests are OK!')

def load_data (name, arbalet):
    """ Exercice 2.1 """
    print ('Loading data from', name)
    with open(name) as f:
        for line in f:
            t = line.rstrip('\n').split(';')
            arbalet.insert (t[0], int(t[1]))
    print ('Done')
            
if __name__ == "__main__":
    test_arbalet()
    a = Arbalet()

    if len (argv) < 2:
        print ("Usage : python {} file-with-notes.txt".format(argv[0]))
        exit (1)
    fname = argv[1]
    checkpoint()
    # Exercice 2.1
    load_data (argv[1], a)
    
    checkpoint()
    
    # Exercice 2.2
    # cat notes-med.txt | awk -F ';' '{print $1}' | grep '^Mary ' | wc -l 
    r = 0
    s = 0
    for kv in a.data:
        if kv[0] == 'Margaret Smith':
            s = s + kv[1]
            r = r + 1
    print ('Mean note is', s/r, 'for Margaret Smith')
    
    checkpoint()
    # Exercice 2.3 ?
    prsn = []
    for kv in a.data:
        if kv[1] > 18 and kv[0] not in prsn:
            prsn.append (kv[0])
    print ('There are', len (prsn), ' persons with bons notes (> 18)')

    checkpoint()
    # Exercice 2.4 ?
    # grep ';0$' notes.txt | awk -F ';' '{print $1}'  | sort -n |uniq
    prsn = []
    for kv in a.data:
        if kv[1] == 0 and kv[0] not in prsn:
            prsn.append (kv[0])
    print ('There are', len (prsn), ' persons with note 0')

    checkpoint()
    # Exercice 2.5
    # cat notes.txt | awk -F ';' '{print $1}' | sort | uniq -c | sort -nr |  less
    pl = []
    for i in range (len (a.data)):
        for j in range (i + 1, len (a.data)):
            if a.data[i][0] == a.data[j][0]:
                if a.data[i][0] not in pl:
                    pl.append (a.data[i][0])
                break
    print (len(pl), ' people have more than one note')
    
    checkpoint()
    print ('A+')
