### Simulation - MVC

def makeModel(data):
    # Set up your simulation components here
    data["cx"] = 200
    data["cy"] = 200
    data["size"] = 50
    data["color"] = "cyan"
    data["dir"] = "right"
    data["moving"] = True
    
def makeView(data, canvas):
    # The simulation view is written here, using the Tkinter canvas
    canvas.create_oval(data["cx"] - data["size"], data["cy"] - data["size"], data["cx"] + data["size"], data["cy"] + data["size"], fill=data["color"])

def runRules(data, call):
    # You can update simulation rules here, by changing or using data
    if data["moving"]==True:
        if data["dir"] == "right":
            data["cx"] = data["cx"] + 10
            if data["cx"]>340: #we want to make sure the canvas does not go off the page, so 400-size-10=340
                data["dir"] = "left"
        else:
            data["cx"] = data["cx"] - 10
            if data["cx"]<60:
                data["dir"] = "right"

def keyPressed(data, event):
    # Use event.keysym to for "Return", "Up", and "Down"
    # (you could also use event.char to get other characters pressed)
    if event.keysym == "Return":
        data["moving"] = not data["moving"] 
        
    if event.keysym == "Up":
        if data["cy"]>50:
            data["cy"] = data["cy"] - 10
    
    if event.keysym == "Down":
        if data["cy"]<350:
            data["cy"] = data["cy"] + 10

 

def mousePressed(data, event):
    # You could additional elements to the simulation based on mouse clicks in this function!
    # Use event.x and event.y to get the (x,y) location of the clicked pixel
    pass

# You do not need to be able to write the following functions;
# just modify the five functions above.

from tkinter import *

def timeLoop(data, canvas, call):
    runRules(data, call)

    canvas.delete(ALL)
    makeView(data, canvas)
    canvas.update()

    canvas.after(data["timeRate"], timeLoop, data, canvas, call + 1)

def keyEventHandler(data, canvas, event):
    keyPressed(data, event)
    
    canvas.delete(ALL)
    makeView(data, canvas)
    canvas.update()
    
def mouseEventHandler(data, canvas, event):
    mousePressed(data, event)
    
    canvas.delete(ALL)
    makeView(data, canvas)
    canvas.update()
    
def runSimulation(w, h, timeRate):
    data = { }
    data["timeRate"] = int(timeRate * 1000) # call will be in ms
    makeModel(data)
    
    root = Tk()
    canvas = Canvas(root, width=w, height=h)
    canvas.configure(bd=0, highlightthickness=0)
    canvas.pack()
    makeView(data, canvas)
    
    canvas.after(data["timeRate"], timeLoop, data, canvas, 1)
    
    root.bind("<Key>", lambda event : keyEventHandler(data, canvas, event))
    root.bind("<Button-1>", lambda event : mouseEventHandler(data, canvas, event))
    
    root.mainloop()

def simulationMVC():
    runSimulation(400, 400, 0.1)

###############################################################################

### Simulation - Monte Carlo

import random

def runTrial(playlist):
    time = 0
    random.shuffle(playlist)
    for song in playlist:
        if song[0] != "Headlines":
            time += song[1]
        else:
            break
    return time

def getExpectedValue(numTrials):
    playlist =  [
                    ["Butterfly Effect", 190],
                    ["Off Deez", 213],
                    ["6 Foot 7 Foot", 248],
                    ["m.A.A.d city", 350],
                    ["Black and Yellow", 217],
                    ["do re mi", 233],
                    ["Headlines", 235],
                    ["Plain Jane", 173],
                    ["Going Bad", 180],
                    ["History", 207],
                    ["Big Fish", 198],
                    ["Vibez", 144],
                    ["Goosebumps", 243],
                    ["Faucet Failure", 145],
                    ["WHATS POPPIN", 227],
                    ["Come & Go", 205],
                    ["Shoota", 153],
                    ["Bonfire", 192],
                    ["Crooked Smile", 278],
                    ["Laugh Now Cry Later", 261],
                    ["Powerglide", 332],
                    ["Taste", 232]
                ]
    time = 0
    for trial in range(numTrials):
        time += runTrial(playlist)
    return time / numTrials

def simulationMonteCarlo():
    print("Expected Time Until Headlines:", getExpectedValue(100000))

###############################################################################

### Data Analysis

import matplotlib.pyplot as plt

def geneExpression(filename, sample):
    f = open(filename, "r")
    txt = f.read()
    table = []
    for line in txt.split("\n"):
        temp = []
        for percent in line.split("\t"):
            temp.append(float(percent))
        table.append(temp)
    xvalues = []
    yvalues = []
    for row in range(len(table)):
        xvalues.append("Gene " + str(row))
        yvalues.append(table[row][sample])
    plt.bar(xvalues, yvalues)
    plt.title("Gene Expression Levels for Sample " + str(sample))
    plt.show()

def dataAnalysis():
    geneExpression("gene_data.txt", 3)

###############################################################################

### Uncomment which of the following functions you want to test:

#simulationMVC()
#simulationMonteCarlo()
#dataAnalysis()