# Ryan Martin
# macid: abcd123
# student number: #######
# November 7, 2011
#
#
# This is a solution for Major Assignment 4 (Lab 09) on Thursday.

import time


#Constants for Database Entries.
#Not required in the assignment specification,
#but improves module flexibility by allowing
#the user to configure the module in the event
#that the database specification changes.

#Extra Study Topic: This set of values could be 
#elegantly implemented using an Enumeration type.

GENDER_INDEX = 0
BIRTH_YEAR_INDEX = 1
GRAD_YEAR_INDEX = 2
SESSIONAL_AVG_INDEX = 3

def isGraduated(row):
        '''Returns True if the student has graduated, False otherwise'''

        gradYear = row[GRAD_YEAR_INDEX]
        currentYear = time.localtime().tm_year

        #If the grad year is before or equal to this year,
        #the student has graduated.
        if gradYear <= currentYear:
                return True
        else:
                return False

def isGender(row, gender):
        '''Returns True if the student is of the specified gender, False otherwise'''

        rowGender = row[GENDER_INDEX]

        if rowGender == gender:
                return True
        else:
                return False

def isBirthDateBefore(row, year):
        '''Returns True if the student was born before the specified year, False otherwise'''

        birthYear = row[BIRTH_YEAR_INDEX]

        if birthYear < year:
                return True
        else:
                return False

def query(data, gender, year):
        '''Returns the ratio: average of first-year sessional averages for students of gender born before year
                                                        / average of first-year sessional averages for students of gender born after or in year'''

        numeratorList = []
        denominatorList = []
        
        #The first row of data contains headings.
        #Only loop through the following rows.
        #Can also use: for i in range(1, len(data))
        for row in data[1:]:
                if isGraduated(row) and isGender(row, gender):
                        sessionalAvgList = row[SESSIONAL_AVG_INDEX]
                        firstYearAvg = sessionalAvgList[0]
                        
                        if isBirthDateBefore(row, year):
                                numeratorList.append(firstYearAvg)
                        else:
                                denominatorList.append(firstYearAvg)

        numerator = float(sum(numeratorList)) / len(numeratorList)
        print numerator
        denominator = float(sum(denominatorList)) / len(denominatorList)
        print denominator
        result = numerator / denominator
        return result
'''
Design Question

Making this module operate independently of the order in the database can be
approached in different ways.

Likely it would be easiest to add an additional argument to isGraduated, isGender,
and isBirthDateBefore that takes the row index of of the item to be compared.
Then, the query function could determine the index of each heading, and pass
the required index to each function as it is called. 

Alternatively, isGraduated, isGender, and isBirthDataBefore could take in a 
list of headings, which would be provided to them by the query function
by passing the first row in the database.

Many solutions are possible. The best solutions would avoid changing the 
specification of as many functions as possible.

'''
##Note: This format is used by our automated marking system.
##You will see that, for inputs, the function name is
##given with the corresponding inputs to that function
##listed right after it. Our automated marking system uses
##the variable data you see here.
'''

Testing Report

data = [ ["GENDER","BIRTH_YEAR","GRAD_YEAR","SESSIONAL_AVERAGES"],
		['F', 1988, 2010, [1.5,2.4,3.3,4.2,5.1] ],	#3.3
		['F', 1989, 2011, [1.4,2.3,3.2,4.1] ],		#2.75
		['F', 1990, 2012, [1.3,2.2,3.1] ],			#2.2
		['F', 1991, 2013, [1.2,2.1] ],				#1.65
		['M', 1988, 2010, [2.5,3.4,4.3,5.2,6.1] ],	#4.3
		['M', 1989, 2011, [2.4,3.3,4.2,5.1] ],		#3.75
		['M', 1990, 2012, [2.3,3.2,4.1] ],			#3.2
		['M', 1991, 2013, [2.2,3.1] ] ]				#2.65

THU = {'test1': 
       {'inputs': ['isGraduated',[data[1]]],
       'outputs': [True]},
       'test2':
       {'inputs': ['isGraduated',[data[3]]],
       'outputs': [False]},
       'test3':
       {'inputs': ['isGender',[data[1], 'F']],
       'outputs': [True]},
       'test4':
       {'inputs': ['isGender',[data[1], 'M']],
       'outputs': [False]},
       'test5':
       {'inputs': ['isBirthDateBefore',[data[1], 1989]],
       'outputs': [True]},
       'test6':
       {'inputs': ['isBirthDateBefore',[data[1], 1988]],
       'outputs': [False]},
       'test7':
       {'inputs': ['query',[data, 'M', 1989]],
       'outputs': [1.0416666666666667]}}
'''