# -*- coding: utf-8 -*-
"""
Created on Fri Jan 15 12:28:40 2021

####Explanation of parameters used in exercise 2:#####
Type of variable used:
name: A string, used in text output

effort: A double in range (.6, .7, .8, .9, 1)
Has a significant effect on scores

luck: Either 1 or -1
Applied for EACH exercise. Internally, each exercise is done twice, and 
either the best or worst result is taken. Bad luck DOUBLES the chance to
fail each exercise. 

charisma: A double in range (.8, .85, .9, .95, 1)
Has the smallest effect on scores

IQ: A double in range (.2, .5, .7, .8, .9, 1)
Can have a very large effect on the scores, which makes sense. An IQ
below 70 would make it hard to succeed in any class, and thus uses a 
.2 multiplier. 

####The formulas:####
Each exercise score is a boolean array of size 10 generated by a skewed  
coin flip (true probability = std.effort * std.IQ). Simulate twice, take
the better or worse result being taken depending on luck, charisma isn't 
factored in because we only have whole numbers, no rounding.

The test is simply 10.0 * std.IQ * std.effort, rounded using charisma,
luck is not involved
     
#### The plots ####
After considering venn diagrams, line graphs, and 3D plots, I finally
settled on bar graphs. Basically, I take the data for all students with
a specific letter grade, count how many of them had a specific attribute score, 
then plot. This same procedure could be done for the exercise/test 
scores, with minor code modifications.

#### note##### 
see line 78 if you'd like plots for different letter grades

### interpretation ####
IQ and effort clearly have the largest effects on grades. A students 
only have a 5 or 6 rating for IQ and effort, but the charisma distribution
is relatively uniform, they are more lucky, but the effect is small.
Likewise, F students are slightly more unlucky, with a much larger
proportion of the having low effort and IQ. 

@author: Daniel Broderick
"""


import exercise2 
import matplotlib.pyplot as plt
import numpy as np
import math




data = []

def main(): 
    # store the results of every all 300 variable combinations 
    for effort in range(1,6):
        for luck in ['y','n']:
            for charisma in range(1,6):
                for IQ in [50, 75, 90, 105, 120, 135]:
                    data.append(exercise2.main('test', 
                                               str(effort), 
                                               str(luck),
                                               str(charisma), 
                                               str(IQ)))
    
    # change this for a different set of plots
    plots('F')
    
        
        
    

def plots(grade_req):
    """provide the grade you want data for
        
    """
    
    # take all the A students and record their results
    # counts are stored in order for the following values:
    c_effort = [0,0,0,0,0] 
    v_effort = [.6, .7, .8, .9, 1]
    c_luck = [0,0] # [lucky, not lucky]
    v_luck = [1,-1]
    c_charisma = [0,0,0,0,0] 
    v_charisma = [.8, .85, .9, .95, 1]
    c_IQ = [0,0,0,0,0,0] # [50, 75, 90, 105, 120, 135]
    v_IQ = [.2, .5, .7,.8,.9, 1] # internal values
    
    
    for x in data: 
        if x['grade'] == grade_req:
            # record everything
            # yes this looks disgusting but its actually good practice
            c_effort[v_effort.index(x['student'].effort)] += 1
            c_luck[v_luck.index(x['student'].luck)] += 1
            c_charisma[v_charisma.index(x['student'].charisma)] += 1
            c_IQ[v_IQ.index(x['student'].IQ)] += 1
                
            
    # now we have the variables in list form and can plot
    fig = plt.figure()
    ax = fig.add_axes([0,0,1,1])
    ax.set_xticks([0,.1,.2,.3,.4, .8, 1.1, 1.5,1.6,1.7,1.8,1.9,
                   2.3,2.4,2.5,2.6,2.7,2.8])
    ax.set_xticklabels(['1','2','3','4','5','lucky', 'unlucky',
                        '1','2','3','4','5','1','2','3','4','5','6'])
    ## yes I looked into major and minor ticks but this was easier
    ax.set_xlabel('effort                                 \
                  charisma     \
                      IQ')
    ax.set_title('Attribute Scores of Students With Letter Grade ' + 
                 grade_req)
    ax.set_ylabel('Number of Students')
    #use integers on the y axis
    yint = range(2, 
                 math.ceil(max(c_effort+c_luck+c_charisma+c_IQ))+1, 4)
    plt.yticks(yint)
    
    
    # definitely a better way to do all this
    # the .05+ is just so a tiny bit of the bar is visible
    ####effort ### 
    ax.bar(0, .05+ c_effort[0], color = 'green', width = 0.1)
    ax.bar(.1, .05+c_effort[1], color = 'red', width = 0.1)
    ax.bar(.2, .05+c_effort[2], color = 'blue', width = 0.1)
    ax.bar(.3, .05+c_effort[3], color = 'orange', width = 0.1)
    ax.bar(.4, .05+c_effort[4], color = 'black', width = 0.1)
    
    #### luck ####
    ax.bar(.8, .05+c_luck[0], color = 'g', width = 0.3)
    ax.bar(1.1, .05+c_luck[1], color = 'blue', width = 0.3)
    
    ###charisma###
    ax.bar(1.5, .05+c_charisma[0], color = 'g', width = 0.1)
    ax.bar(1.6, .05+c_charisma[1], color = 'r', width = 0.1)
    ax.bar(1.7, .05+c_charisma[2], color = 'blue', width = 0.1)
    ax.bar(1.8, .05+c_charisma[3], color = 'orange', width = 0.1)
    ax.bar(1.9, .05+c_charisma[4], color = 'black', width = 0.1)
    
    ### iq ###
    ax.bar(2.3, .05+c_IQ[0], color = 'g', width = 0.1) 
    ax.bar(2.4, .05+c_IQ[1], color = 'r', width = 0.1) 
    ax.bar(2.5, .05+c_IQ[2], color = 'blue', width = 0.1) 
    ax.bar(2.6, .05+c_IQ[3], color = 'orange', width = 0.1) 
    ax.bar(2.7, .05+c_IQ[4], color = 'black', width = 0.1) 
    ax.bar(2.8, .05+c_IQ[5], color = 'gold', width = 0.1) 
    
    
    
                  
                  
                  
if __name__ == "__main__":
    main()