"""
This scripts stores a dictionary with the most important terminology
we encountered in the course.  The keys in the dictionary are the
lectures in which the terms were explained.
"""
TERMS = \
{ \
  '1':['computer science', 'algorithm', 'pseudocode', 'flowchart'] ,
  '2':['hardware', 'software', 'processor', 'memory', 'storage', \
       'volatile', 'persistent', 'peripherals', 'system bus', \
       'editor', 'compiler', 'interpreter', 'linker', 'debugger', 'IDE', \
       'assembler', 'machine code'] , \
  '3':['system clock', 'byte', 'ASCII', 'Unicode', 'CPU', 'ALU', \
       'control unit', 'register', 'RAM', 'ROM', 'cache', 'hard drive'] ,
  '4':['memory allocation', 'garbage collection', 'dynamic typing', \
       'floating-point number', 'machine precision', 'precision', \
       'accuracy', 'specification', 'implementation'] , \
  '5':['OS', 'PC', 'workstation', 'mainframe', 'virtual machine', \
       'shell', 'kernel of OS', 'interrupt', 'pagination' , \
       'segmentation', 'virtual memory', 'swap space', \
       'directory', 'UNIX', 'Linux', 'Cygwin', 'portable code' ], \
  '6':['language generation', 'syntax', 'semantics', 'BNF' ] , \
  '7':['mass storage', 'sequential access', 'direct access' , \
       'kilobyte', 'megabyte', 'gigabyte', 'terabyte', \
       'kilohertz', 'megahertz', 'gigahertz', 'terahertz', \
       'disk sector', 'cylinder on disk', 'latency time', 'seek time' , \
       'hash function', 'rule based programming' ], \
  '8':['logical expression', 'truth table'], \
  '9':['transistor', 'electronic circuit', 'logic gate'], \
  '10':['flip flop', 'latch', 'FIFO', 'FILO', 'queue', 'stack'], \
  '11':['bitwise operator'], \
  '12':['Monte Carlo method'], \
  '13':['top down design'], \
  '14':['call by value', 'call by reference', 'functional programming'], \
  '15':['trapdoor function'], \
  '16':['binary file', 'soft link', 'bottom up design'], \
  '17':['data compression', 'lossless data compression', \
        'lossy data compression', 'dictionary encoding compression'], \
  '18':['IP address', 'WAN', 'LAN', 'URL', 'TCP/IP', 'HTTP', 'XML', \
        'HTML', 'CGI'],  \
  '21':['modular design', 'information hiding', \
        'low coupling and high cohesion', 'design for change'], \
  '22':['software quality criteria', 'waterfall model' , \
        'spiral model'], \
  '23':['GNU', 'GPL', 'IPR', 'copyright', 'copyleft', 'open source'], \
  '24':['OOP', 'UML', 'class diagram', 'use case diagram'], \
  '25':['object-oriented programming', 'procedure-oriented programming', \
        'flop'], \
  '26':['procedure-oriented language', 'object-oriented language', \
        'framework language', 'encapsulation', 'polymorphism', \
        'wrapping', 'inheritance', 'method overriding'], \
  '27':['software bug', 'white-box testing', 'black-box testing', \
        'static testing', 'dynamic testing', 'verification', \
        'validation', 'beta testing', 'test to pass', 'test to fail', \
        'unit testing', 'integration testing', 'programming by contract', \
        'precondition', 'postcondition', 'loop invariant'], \
  '28':['robust', 'exception', 'raise exception', 'handle exception', \
        'anytime algorithm' ], \
  '29':['complexity', 'cost', 'complexity class', 'P complexity class', \
        'NP complexity class', '#P complexity class' ], \
  '30':['GUI', 'event driven interface', 'command line interface'], \
  '31':['callback function'], \
  '32':['RGB'], \
  '33':['multiple inheritance'], \
  '34':['cellular automaton'], \
  '35':['concurrency', 'parallelism', 'process', 'thread'], \
  '36':['time sharing','thread safe', \
        'critical section', 'lock', 'semaphore', 'deadlock'],  \
  '39':['bps', 'star network', 'ring network', 'bus network', \
        'client/server architecture', 'application layer', \
        'transport layer', 'network layer', 'link layer', 'TCP', 'UDP', \
        'socket', 'localhost'], \
  '40':['fork a process', 'speedup', 'quality up'], \
  '41':['generator', 'recursive algorithm', 'iterative algorithm'], \
}

def choose_term(nbr):
    """
    Generates a number in range(nbr)
    and returns the lecture key string
    and a term from the list as a tuple.
    """
    from random import choice
    trm = choice(list(range(nbr)))
    kys = list(TERMS.keys())
    cnt = 0
    for key in kys:
        lgt = len(TERMS[key])
        cnt = cnt + lgt
        if cnt > trm:
            qst = choice(list(range(lgt)))
            return (key, TERMS[key][qst])

def main():
    """
    Generates a random number from the range
    of the total number of terms.
    """
    keys = list(TERMS.keys())
    numb = sum([len(TERMS[k]) for k in keys])
    print('We have', numb, 'terms to choose from ...')
    (lec, term) = choose_term(numb)
    print('Explain the term : \"%s\".' % term)
    print('Hint: see lecture %s.' % lec)

if __name__ == "__main__":
    main()
