Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # NEA
- # Andrew Howell Candidate No. 0082
- # St. John Payne School Centre No. 16331
- runProgram = True
- ##### Importing Python Modules needed for program #####
- # Defensive programming - catching exceptions in code where python modules are not present
- try:
- import tkinter as tk
- from tkinter import messagebox
- from tkinter import *
- except:
- print("Python's Tkinter module not installed, Program cannot run")
- runProgram = False
- try:
- import pickle
- except:
- messagebox.showinfo("Error","Python's Pickle module not installed, Program cannot run")
- runProgram = False
- try:
- import datetime
- except:
- messagebox.showinfo("Error","Python's Datetime module not installed, Program cannot run")
- runProgram = False
- try:
- import math
- except:
- messagebox.showinfo("Error","Python's Datetime module not installed, Program cannot run")
- runProgram = False
- try:
- import random
- except:
- messagebox.showinfo("Error","Python's Random module not installed, Program cannot run")
- runProgram = False
- try:
- import passlib
- from passlib.hash import pbkdf2_sha256
- except:
- messagebox.showinfo("Error","Python's Passlib module not installed, Program cannot run")
- runProgram = False
- #######################################################
- ##### Constant Declaration #####
- # Using passlib's hashing algorithm, password is securely encrypted
- HASHEDADMINPASSWORD = "$pbkdf2-sha256$29000$COH8X8sZQ6j1PkeoFUIIQQ$64MnDDlriVWgZGjjXEHP/HnlweMr/OkbAmAvgUGYDoA"
- ADMIN = ["Admin", HASHEDADMINPASSWORD] # Admin details
- LARGEFONT = ("Verdana", 22) # Font format for titles on each page
- MEDIUMFONT = ("Verdana", 16)
- LABELFONT = ("Verdana", 13)
- SMALLFONT = ("Verdana", 11)
- # Dimensions of the Tkinter window
- WIDTH = 800
- HEIGHT = 600
- FILENAME = "NEADatabase.dat" # Constant database name
- ################################
- ##### File Handling #####
- #Username Format: USERNAMES[Username] = [Password, Score, LastSession]
- USERNAMES = {} # Dictionary where student details will be stored whilst the program runs
- try:
- try:
- USERNAMES = pickle.load(open(FILENAME, "rb")) # Retrieves dictionary of user details stored in database
- except:
- pickle.dump({},open(FILENAME, "wb")) # If database not present in directory, create file
- except EOFError:
- pass
- def saveUsers(): # Writes the current dictionary of user details to the database
- pickle.dump(USERNAMES, open(FILENAME, "wb"))
- #########################
- ##### Mathematical Operational Functions #####
- def Modulus(a):
- if a < 0:
- a = -a
- return a
- def mergeSort(alist):
- if len(alist) > 1:
- mid = len(alist)//2
- lefthalf = alist[:mid]
- righthalf = alist[mid:]
- mergeSort(lefthalf)
- mergeSort(righthalf)
- leftHalfPosition = 0
- rightHalfPosition = 0
- originalListPosition = 0
- while leftHalfPosition < len(lefthalf) and rightHalfPosition < len(righthalf):
- if lefthalf[leftHalfPosition] < righthalf[rightHalfPosition]:
- alist[originalListPosition] = lefthalf[leftHalfPosition]
- leftHalfPosition += 1
- else:
- alist[originalListPosition] = righthalf[rightHalfPosition]
- rightHalfPosition += 1
- originalListPosition += 1
- while leftHalfPosition < len(lefthalf):
- alist[originalListPosition] = lefthalf[leftHalfPosition]
- leftHalfPosition += 1
- originalListPosition += 1
- while rightHalfPosition < len(righthalf):
- alist[originalListPosition]=righthalf[rightHalfPosition]
- rightHalfPosition += 1
- originalListPosition += 1
- return alist
- def getCurrentDate(): # Returns array of current day, month and year
- day = datetime.date.today().day
- month = datetime.date.today().month
- year = datetime.date.today().year
- date = [day, month, year]
- return date
- ##############################################
- ##### SUVAT Equation Solving Algorithm #####
- class SUVAT():
- def __init__(self,s,u,v,a,t,shortAnswer):
- # Passes parameters from user as attributes
- self.s = s
- self.u = u
- self.v = v
- self.a = a
- self.t = t
- self.sA = shortAnswer # Boolean - determines whether object returns worded answer or just numeric answer
- try:
- def initiate(self):
- if self.s == "x":
- return self.SUVAT1()
- elif self.u == "x":
- return self.SUVAT2()
- elif self.v == "x":
- return self.SUVAT3()
- elif self.a == "x":
- return self.SUVAT4()
- elif self.t == "x":
- return self.SUVAT5()
- except:
- messagebox.showinfo("Error","Invalid details inputted, try again", icon = "warning")
- def SUVAT1(self): # v = u + at (s = 'X')
- if self.u == "a":
- self.u = float(self.v) - float(self.a)*float(self.t) # Converts string parameters given by user to a float value
- if self.sA: # If the user wants a short answer -> using Checker not Solver
- return [self.u,0] # Some calculations return two values so a 2 element array is returned
- else:
- return("Initial Velocity is {0:.2f} ms^-1".format(self.u))
- elif self.v == "a":
- self.v = float(self.u) + float(self.a)*float(self.t)
- if self.sA:
- return [self.v,0]
- else:
- return("Final Velocity is {0:.2f} ms^-1".format(self.v))
- elif self.a == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.a = (float(self.v) - float(self.u))/float(self.t)
- if self.sA:
- return [self.a,0]
- else:
- return("Acceleration is {0:.2f} ms^-2".format(self.a))
- elif self.t == "a":
- if float(self.a) == 0:
- return "zeroDivision error" # Calculation would include a division by zero which creates an error and so
- # validation will inform the user that the question cannot include a division by zero
- else:
- self.t = (float(self.v) - float(self.u))/float(self.a)
- if self.sA:
- return [self.t,0]
- else:
- return("Time Taken is {0:.2f} s".format(self.t))
- def SUVAT2(self): # s = vt - 0.5at^2 (u = 'X')
- if self.s == "a":
- self.s = float(self.v)*float(self.t) - 0.5*float(self.a)*float(self.t)**2
- if self.sA:
- return [self.s,0]
- else:
- return("Displacement is {0:.2f} m".format(self.s))
- elif self.v == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.v = float(self.s)/float(self.t) + 0.5*float(self.a)*float(self.t)
- if self.sA:
- return [self.v,0]
- else:
- return("Final Velocity is {0:.2f} ms^-1".format(self.v))
- elif self.a == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.a = (float(self.v)*float(self.t) - float(self.s))/(0.5*float(self.t)**2)
- if self.sA:
- return [self.a,0]
- else:
- return("Acceleration is {0:.2f} ms^-2".format(self.a))
- elif self.t == "a":
- if float(self.a) == 0:
- return "zeroDivision error"
- else:
- x = float(self.v)**2 - 2*float(self.a)*float(self.s)
- x = Modulus(x)
- x = math.sqrt(x)
- t1 = ((float(self.v) + (x))/float(self.a))
- t2 = ((float(self.v) - (x))/float(self.a))
- if self.sA:
- return [t1,t2] # Two values of t
- else:
- return("Time Taken is {0:.2f} s and {1:.2f} s".format(t1, t2))
- def SUVAT3(self): # s = ut + 0.5at^2 (v = 'X')
- if self.s == "a":
- self.s = float(self.u)*float(self.t) + 0.5*float(self.a)*float(self.t)**2
- if self.sA:
- return [self.s,0]
- else:
- return("Displacement is {0:.2f} m".format(self.s))
- elif self.u == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.u = float(self.s)/float(self.t) - 0.5*float(self.a)*float(self.t)
- if self.sA:
- return [self.u,0]
- else:
- return("Initial Velocity is {0:.2f} ms^-1".format(self.u))
- elif self.a == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.a = (float(self.s) - float(self.u)*float(self.t))/(0.5*float(self.t)**2)
- if self.sA:
- return [self.a,0]
- else:
- return("Acceleration is {0:.2f} ms^-2".format(self.a))
- elif self.t == "a":
- if float(self.a) == 0:
- return "zeroDivision error"
- else: # Using quadratic equation - returns two values of t
- x = float(self.u)**2 + 2*float(self.a)*float(self.s)
- x = Modulus(x)
- x = math.sqrt(x)
- t1 = ((-float(self.u) + (x))/float(self.a))
- t2 = ((-float(self.u) - (x))/float(self.a))
- if self.sA:
- return [t1,t2]
- else:
- return("Time Taken is {0:.2f} s and {1:.2f} s".format(t1, t2))
- def SUVAT4(self): # s = 0.5(u + v)t (a = 'X')
- if self.s == "a":
- self.s = 0.5*(float(self.u) + float(self.v))*float(self.t)
- if self.sA:
- return [self.s,0]
- else:
- return("Displacement is {0:.2f} m".format(self.s))
- elif self.u == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.u = (2*float(self.s))/float(self.t) - float(self.v)
- if self.sA:
- return [self.u,0]
- else:
- return("Initial Velocity is {0:.2f} ms^-1".format(float(self.u)))
- elif self.v == "a":
- if float(self.t) == 0:
- return "zeroDivision error"
- else:
- self.v = (2*float(self.s))/float(self.t) - float(self.u)
- if self.sA:
- return [self.v,0]
- else:
- return("Final Velocity is {0:.2f} ms^-1".format(self.v))
- elif self.t == "a":
- if (float(self.u) + float(self.v)) == 0:
- return "zeroDivision error"
- else:
- self.t = (2*float(self.s))/(float(self.u) + float(self.v))
- if self.sA:
- return [self.t,0]
- else:
- return("Time Taken is {0:.2f} s".format(self.t))
- def SUVAT5(self): # v^2 = u^2 + 2as (t = 'X')
- if self.s == "a":
- if float(self.a) == 0:
- return "zeroDivision error"
- else:
- self.s = (float(self.v)**2 - float(self.u)**2)/2*float(self.a)
- if self.sA:
- return [self.s,0]
- else:
- return("Displacement is {0:.2f} m".format(self.s))
- elif self.u == "a":
- uSquared = float(self.v)**2 - 2*float(self.a)*float(self.s)
- self.u = math.sqrt(Modulus(uSquared)) # If self.u is negative,
- # square rooting it will cause
- # an error, so we square root the modulus
- if self.sA:
- return [self.u,0]
- else:
- return("Initial Velocity is {0:.2f} ms^-1".format(self.u))
- elif self.v == "a":
- vSquared = float(self.u)**2 + 2*float(self.a)*float(self.s)
- self.v = math.sqrt(Modulus(vSquared))
- if self.sA:
- return [self.v,0]
- else:
- return("Final Velocity is {0:.2f} ms^-1".format(self.v))
- elif self.a == "a":
- if float(self.s) == 0:
- return "zeroDivision error"
- else:
- self.a = (float(self.v)**2 - float(self.u)**2)/2*float(self.s)
- if self.sA:
- return [self.a,0]
- else:
- return("Acceleration is {0:.2f} ms^-2".format(self.a))
- ############################################
- ##### GUI Classes #####
- # Parent class which hosts the structure of the GUI interface, subsequent pages are frames displayed on this GUI interface
- class GUI(tk.Tk):
- def __init__(self, *args, **kwargs): # Allows a variable amount of keyworded and non-keyworded arguements to be passed into the object
- self.activeUser = "" # Stores the Username of a current user
- tk.Tk.__init__(self, *args, **kwargs)
- tk.Tk.iconbitmap(self, default="NEALogo.ico") # Displays telescope icon to be displayed in left-hand corner of the GUI window
- tk.Tk.wm_title(self, "Physics Learning Aid") # Displays on the header of th GUI window
- container = tk.Frame(self) # Container holds all elements of the frames and the toolbar
- container.pack(side="top", fill="both", expand = True)
- container.grid_rowconfigure(0, weight=1) # Weight attribute added to allow the rows and colunmns to display properly
- container.grid_columnconfigure(0, weight=1)
- menubar = tk.Menu(container) # Creates the toolbar where students can easily access different pages
- self.filemenu = tk.Menu(menubar, tearoff=0)
- self.filemenu.add_command(label="Home", state="disable", command = lambda: self.show_frame(homePage)) # Pages disabled until a user logs in
- self.filemenu.add_command(label="1: Forces", state="disable", command = lambda: self.show_frame(forcesPage))
- self.filemenu.add_command(label="2: Time Graphs", state="disable", command = lambda: self.show_frame(timeGraphsPage))
- self.filemenu.add_command(label="3. SUVAT Revision", state="disable", command = lambda: self.show_frame(SUVATRevisionPage))
- self.filemenu.add_command(label="Account", command = lambda: self.show_frame(accountPage))
- helpmenu = tk.Menu(self.filemenu, tearoff=0) # Dropdown menu
- helpmenu.add_command(label="General Help", command=self.helpme)
- helpmenu.add_command(label="Application Help", command=self.helpme)
- helpmenu.add_command(label="SUVAT Solver Help", command=self.helpme)
- self.filemenu.add_cascade(label="Help", menu=helpmenu)
- tk.Tk.config(self, menu=self.filemenu)
- self.frames = {}
- # Creates each individual page as an object is instanciated from the page classes
- for page in (startPage, accountPage, changePasswordPage, loginPage, signupPage, adminLoginPage, adminPage, homePage, forcesPage, ScalarsVectorsPage, AdditionVectorsCalculationPage,
- AdditionVectorsScaleDrawingPage, ResolutionOfVectorsPage, InclinedPlaneVectorsPage, VectorsInEquilibriumPage, timeGraphsPage, GradientsPage, AreaUnderCurvePage, BouncingBallPage,
- SUVATRevisionPage, SUVATCheckerPage, SUVATSolverPage):
- frame = page(container, self)
- self.frames[page] = frame
- frame.grid(row=0, column=0, sticky="nsew")
- self.centreScreen(WIDTH, HEIGHT)
- def helpme(self):
- helpList = ["Please seek help from your teacher", "Ask your teacher for help, they're right behind you!", "Help Bot Open Hours -> 11:59PM SUN - 00:00AM MON\nPlease come back then", "Tough, help yourself, I'M BUSY",
- "I'm in the Bahamas on holiday right now\n\nLEAVE\n\nME\n\nALONE"]
- helpChoice = random.randrange(len(helpList))
- helpComment = helpList[helpChoice-1]
- messagebox.showinfo("Help Bot","Hi, you have requested help\n\n{}".format(helpComment), icon="info")
- def enableWidgets(self):
- self.filemenu.entryconfig("Home", state="normal")
- self.filemenu.entryconfig("1: Forces", state="normal")
- self.filemenu.entryconfig("2: Time Graphs", state="normal")
- self.filemenu.entryconfig("3. SUVAT Revision", state="normal")
- def disableWidgets(self):
- self.filemenu.entryconfig("Home", state="disable")
- self.filemenu.entryconfig("1: Forces", state="disable")
- self.filemenu.entryconfig("2: Time Graphs", state="disable")
- self.filemenu.entryconfig("3. SUVAT Revision", state="disable")
- def addScore(self, score):
- if window.activeUser != "Admin" and window.activeUser != "":
- USERNAMES[self.activeUser][1] += score
- def centreScreen(self, w, h): # Uses screen dimensions to centre the GUI window
- ws = self.winfo_screenwidth()
- hs = self.winfo_screenheight()
- # Finds the top left coordinate that the GUI will be in order to be centered
- x = (ws / 2) - (w / 2)
- y = (hs / 2) - (w / 2)
- # Align window with the top left coordinate
- self.geometry("%dx%d+%d+%d" % (w, h, x, y)) # takes parameters as 'wxh+x+y'
- self.show_frame(startPage)
- def logout(self):
- if self.activeUser != "" and self.activeUser != ADMIN[0]:
- date = getCurrentDate()
- USERNAMES[self.activeUser][2] = date
- self.activeUser = ""
- self.disableWidgets()
- messagebox.showinfo("Logged out", "You have been logged out successfully")
- saveUsers()
- self.show_frame(startPage)
- def show_frame(self, cont):
- frame = self.frames[cont]
- frame.tkraise() # When called it raises the given page to the top of the GUI
- ### Start of Page Classes ###
- class startPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Start Page", font=LARGEFONT)
- self.title.pack(side="top", fill="x", pady=30)
- self.welcomeMsg = tk.Label(self, text = "Welcome to the Physics Learning Aid!")
- self.label1 = tk.Label(self, text = "Are you a")
- self.student = tk.Button(self, text = "Student", command=lambda: controller.show_frame(accountPage),height=2,width=20)
- self.label2 = tk.Label(self, text = "or ")
- self.teacher = tk.Button(self, text = "Teacher", command=lambda: controller.show_frame(adminLoginPage),height=2,width=20)
- self.welcomeMsg.pack(side="top", fill="x", padx=5, pady=20)
- self.label1.pack(side="top", fill="x", pady=5)
- self.student.pack(side="top", pady=5)
- self.label2.pack(side="top", fill="x", pady=5)
- self.teacher.pack(side="top", pady=5)
- class accountPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Account Page", font=LARGEFONT)
- self.title.pack(side="top", fill="x", pady=30)
- self.login = tk.Button(self, text = "Existing User - Log in", command=lambda: controller.show_frame(loginPage),height=2,width=20)
- self.signUp = tk.Button(self, text = "New User - Sign Up", command=lambda: controller.show_frame(signupPage),height=2,width=20)
- self.logoutButton = tk.Button(self, text = "Log out", command=lambda: window.logout())
- self.selectButton = tk.Button(self,text = "Score", command=lambda: showScore())
- self.changePasswordButton = tk.Button(self, text = "Change Password", command=lambda: changePassword())
- self.login.pack(side="top", fill="x", padx=300, pady=20)
- self.signUp.pack(side="top", fill="x", padx=300, pady=5)
- self.selectButton.pack(side="top", pady=20)
- self.logoutButton.pack(side="bottom", pady=10)
- self.changePasswordButton.pack(side="bottom")
- # Displays the user's details, their username, current score and the date they last were on the program
- def showScore():
- if window.activeUser != "" and window.activeUser != "Admin":
- score = USERNAMES[window.activeUser][1]
- messagebox.showinfo("Your Details","Username : {0}\n\nScore : {1}".format(window.activeUser,score), icon="info")
- else:
- messagebox.showinfo("Error","Cannot display score\n\nYou are not logged in as a student", icon="warning")
- def changePassword():
- if window.activeUser != "" or window.activeUser != "Admin":
- controller.show_frame(changePasswordPage)
- else:
- messagebox.showinfo("Error","Please login before trying to change your password", icon="warning")
- self.login.focus()
- class changePasswordPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Change Password", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.originalPasswordText = tk.Label(self, text = "Original Password:")
- self.originalPasswordInput = tk.Entry(self, justify="center", show="*", width=30)
- self.newPasswordText = tk.Label(self, text = "New Password:")
- self.newPasswordInput = tk.Entry(self, justify="center", show="*", width=30)
- self.confirmPasswordText = tk.Label(self, text = "Confirm Password:")
- self.confirmPasswordInput = tk.Entry(self, justify="center", show="*", width=30)
- self.changePasswordButton = tk.Button(self,text = "Change Password", command=lambda: changePassword())
- self.originalPasswordText.pack(side="top", fill="x", padx=20, pady=5)
- self.originalPasswordInput.pack(side="top")
- self.originalPasswordInput.focus()
- self.newPasswordText.pack(side="top", fill="x", padx=20, pady=5)
- self.newPasswordInput.pack(side="top")
- self.confirmPasswordText.pack(side="top", fill="x", padx=20, pady=5)
- self.confirmPasswordInput.pack(side="top")
- self.changePasswordButton.pack(side="top", fill="y", padx=20, pady=10)
- def changePassword():
- if self.originalPasswordInput.get() == USERNAMES[window.activeUser][0]:
- if self.newPasswordInput.get() == self.confirmPasswordInput.get():
- USERNAMES[window.activeUser][0] = self.newPasswordInput.get()
- messagebox.showinfo("Password Changed","Your password has been changed successfully!", icon="info")
- controller.show_frame(accountPage)
- else:
- messagebox.showinfo("Error","Your new and confirmation password do not match\nPlease try again", icon="warning")
- self.newPasswordInput.delete(0,"end")
- self.confirmPasswordInput.delete(0,"end")
- self.newPasswordInput.focus()
- else:
- messagebox.showinfo("Error","Incorrect original password\nPlease try again", icon="warning")
- self.originalPasswordInput.delete(0,"end")
- self.newPasswordInput.delete(0,"end")
- self.confirmPasswordInput.delete(0,"end")
- self.newPasswordInput.focus()
- class loginPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Login", font=LARGEFONT)
- self.title.pack(side="top", fill="x", pady=30)
- # User details entry boxes
- self.usernameText = tk.Label(self, text = "Username:")
- self.usernameInput = tk.Entry(self, justify="center", width=30)
- self.passwordText = tk.Label(self, text = "Password:")
- self.passwordInput = tk.Entry(self, show="*", justify="center", width=30)
- self.loginButton = tk.Button(self,text = "Login", command=lambda: login())
- self.usernameText.pack(side="top", fill="x", padx=20, pady=5)
- self.usernameInput.pack(side="top", pady=5)
- self.usernameInput.focus()
- self.passwordText.pack(side="top", fill="x", padx=20, pady=5)
- self.passwordInput.pack(side="top", pady=5)
- self.loginButton.pack(side="top", pady="10")
- def login(): # Validation ensuring username exists, and that the password given matches the saved password
- if self.usernameInput.get() in USERNAMES:
- if self.passwordInput.get() == USERNAMES[self.usernameInput.get()][0]:
- window.activeUser = self.usernameInput.get()
- messagebox.showinfo("Login Successful","Welcome back {0}".format(self.usernameInput.get()), icon = "info")
- self.usernameInput.delete(0,"end") # Deletes value in entry box as it will not be removed automatically when a new frame is raised
- self.passwordInput.delete(0,"end")
- controller.show_frame(homePage)
- window.enableWidgets()
- else:
- self.passwordInput.delete(0,"end")
- messagebox.showinfo("Login Failed", "Incorrect Password", icon = "warning")
- self.passwordInput.focus()
- else:
- self.usernameInput.delete(0,"end")
- self.passwordInput.delete(0,"end")
- messagebox.showinfo("Login Failed", "Username not found, please try again if you are an existing user\nIf not, register by clicking on the account tab at the top", icon = "warning")
- self.usernameInput.focus()
- class signupPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- title = tk.Label(self, text="Sign Up", font=LARGEFONT)
- title.pack(padx=10, pady=10)
- self.firstNameText = tk.Label(self, text = "First Name:")
- self.firstNameInput = tk.Entry(self, justify="center", width=30)
- self.secondNameText = tk.Label(self, text = "Second Name:")
- self.secondNameInput = tk.Entry(self, justify="center", width=30)
- self.yearOfEntryText = tk.Label(self, text = "Year of Entry to SJP (YYYY):")
- self.yearOfEntryInput = tk.Entry(self, justify="center", width=30)
- self.passwordText = tk.Label(self, text = "New Password:")
- self.passwordInput = tk.Entry(self, show="*", justify="center", width=30)
- self.passwordText2 = tk.Label(self, text = "Confirm Password:")
- self.passwordInput2 = tk.Entry(self, show="*", justify="center", width=30)
- self.signupButton = tk.Button(self,text = "Register", command=lambda: signup())
- # Pack the elements onto the GUI window
- self.firstNameText.pack(side="top", fill="x", padx=20, pady=5)
- self.firstNameInput.pack(side="top")
- self.firstNameInput.focus()
- self.secondNameText.pack(side="top", fill="x", padx=20, pady=5)
- self.secondNameInput.pack(side="top")
- self.yearOfEntryText.pack(side="top", fill="x", padx=20, pady=5)
- self.yearOfEntryInput.pack(side="top")
- self.passwordText.pack(side="top", fill="x", padx=20, pady=5)
- self.passwordInput.pack(side="top")
- self.passwordText2.pack(side="top", fill="x", padx=20, pady=5)
- self.passwordInput2.pack(side="top")
- self.signupButton.pack(side="top", fill="y", padx=20, pady=10)
- def signup():
- # Create local variables that are easier to manipulate inside the function
- firstName = self.firstNameInput.get()
- secondName = self.secondNameInput.get()
- yearOfEntry = self.yearOfEntryInput.get()
- password = self.passwordInput.get()
- if firstName == "" or secondName == "" or yearOfEntry == "" or password == "":
- messagebox.showinfo("Error!","Please do not leave any fields blank", icon = "warning")
- else:
- if yearOfEntry.isdigit() == False:
- messagebox.showinfo("Invalid Year of Entry", "Please enter a valid 4 digit year", icon = "warning")
- self.yearOfEntryInput.delete(0,"end")
- self.yearOfEntryInput.focus()
- else:
- if self.passwordInput.get() != self.passwordInput2.get():
- messagebox.showinfo("Passwords do not match", "The passwords you entered did not match\n\nPlease ensure they match", icon = "warning")
- self.passwordInput.delete(0,"end")
- self.passwordInput2.delete(0,"end")
- self.passwordInput.focus()
- else:
- newUsername = yearOfEntry[2:] + secondName.lower() + firstName[0].lower() # Creates a username, compiled from the student's year of entry, their surname and the first initial of their forename
- if newUsername in USERNAMES:
- messagebox.showinfo("Error!","That user already exists\n\nIf someone in your year shares your name, add a space on the end of your surname", icon = "warning")
- self.firstNameInput.delete(0,"end")
- self.secondNameInput.delete(0,"end")
- self.yearOfEntryInput.delete(0,"end")
- self.passwordInput.delete(0,"end")
- self.passwordInput2.delete(0,"end")
- self.firstNameInput.focus() # Resets the form and focuses the keyboard onto the first entry field
- else:
- revisionScore = 0 # Each students starts with a score of 0, this will be added to and subtracted from when they perform tasks on the program
- lastSession = [] # This will hold the date which the student last logged out on, it is overwritten when the user logs out of the program
- USERNAMES[newUsername] = [password, revisionScore, lastSession] # Creates entry in the USERNAMES dictionary holding all the usernames, will later be pickled to the database when logging out
- window.activeUser = newUsername # Assigns the active user as the newly registered user
- messagebox.showinfo("Registered","Welcome {0}".format(newUsername), icon = "info")
- self.firstNameInput.delete(0,"end")
- self.secondNameInput.delete(0,"end")
- self.yearOfEntryInput.delete(0,"end")
- self.passwordInput.delete(0,"end")
- self.passwordInput2.delete(0,"end")
- window.enableWidgets()
- controller.show_frame(homePage)
- class adminLoginPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Admin Login Page", font=LARGEFONT)
- self.title.pack(side="top", fill="x", pady=30)
- self.usernameText = tk.Label(self, text = "Admin Username:")
- self.usernameInput = tk.Entry(self, justify="center", width=30)
- self.passwordText = tk.Label(self, text = "Admin Password:")
- self.passwordInput = tk.Entry(self, show="*", justify="center", width=30)
- self.loginButton = tk.Button(self,text = "Login", command=lambda: adminLogin())
- self.usernameText.pack(side="top", fill="x", padx=20, pady=5)
- self.usernameInput.pack(side="top", pady=5)
- self.usernameInput.focus()
- self.passwordText.pack(side="top", fill="x", padx=20, pady=5)
- self.passwordInput.pack(side="top", pady=5)
- self.loginButton.pack(side="top", pady="10")
- def adminLogin():
- if self.usernameInput.get() == ADMIN[0]:
- if pbkdf2_sha256.verify(self.passwordInput.get(), ADMIN[1]):
- window.activeUser = self.usernameInput.get()
- messagebox.showinfo("Login Successful","Continue to Admin Page".format(self.usernameInput.get()), icon = "info")
- self.usernameInput.delete(0,"end")
- self.passwordInput.delete(0,"end")
- controller.show_frame(adminPage)
- window.enableWidgets()
- else:
- self.usernameInput.delete(0,"end")
- self.passwordInput.delete(0,"end")
- messagebox.showinfo("Login Failed", "Incorrect details", icon = "warning")
- self.usernameInput.focus()
- else:
- self.usernameInput.delete(0,"end")
- self.passwordInput.delete(0,"end")
- messagebox.showinfo("Login Failed", "Incorrect details", icon = "warning")
- self.usernameInput.focus()
- class adminPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Admin Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- username = StringVar()
- username.set("Usernames")
- self.usernameText = tk.Label(self, text = "Select students to review details:")
- self.usernamesList = list(USERNAMES) # Creates an array, holding all the key values from the dictionary USERNAMES
- self.dropdown = OptionMenu(self, username, *self.usernamesList)
- self.updateButton = tk.Button(self,text = "Update and Sort (Alphabetically)", command=lambda: updateUsernames())
- self.selectButton = tk.Button(self,text = "Search", command=lambda: searchUsername())
- self.usernameText.pack(side="top", padx=20, pady=5)
- self.dropdown.pack(side="top", padx=20, pady=5)
- self.updateButton.pack(side="top", pady=10)
- self.selectButton.pack(side="top")
- # Displays the user's details, their username, current score and the date they last were on the program
- def searchUsername():
- if username.get() in USERNAMES:
- score = USERNAMES[username.get()][1]
- lastSession = USERNAMES[username.get()][2]
- messagebox.showinfo("User Details","Username : {0}\n\nScore : {1}\n\nLast Session : {2}/{3}/{4}".format(username.get(),score,lastSession[0],lastSession[1],lastSession[2]))
- username.set("Usernames")
- # Updates the usernames list, sorting them into alphabetical order of their username, allowing the teacher to easily search for a student
- def updateUsernames():
- username.set("Usernames")
- self.dropdown["menu"].delete(0,"end")
- self.usernamesList = list(USERNAMES) # Takes into account any new users
- self.usernamesList = mergeSort(self.usernamesList) # Calls global function to merge sort the list of
- for each in self.usernamesList:
- self.dropdown["menu"].add_command(label=each, command=tk._setit(username, each))
- class homePage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Learning Options Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.welcomeMsg = tk.Label(self, text = "Welcome to the Physics Learning Aid!")
- self.forcesButton = tk.Button(self, text = "1. Forces", command=lambda: controller.show_frame(forcesPage),height=2,width=20)
- self.label1 = tk.Label(self, text = "or ")
- self.timeGraphsButton = tk.Button(self, text = "2. Time Graphs", command=lambda: controller.show_frame(timeGraphsPage),height=2,width=20)
- self.label2 = tk.Label(self, text = "or ")
- self.SUVATRevisionButton = tk.Button(self, text = "3. SUVAT Revision", command=lambda: controller.show_frame(SUVATRevisionPage),height=2,width=20)
- self.welcomeMsg.pack(side="top", fill="x", padx=5, pady=20)
- self.forcesButton.pack(side="top", pady=5)
- self.label1.pack(side="top", fill="x", pady=5)
- self.timeGraphsButton.pack(side="top", pady=5)
- self.label2.pack(side="top", fill="x", pady=5)
- self.SUVATRevisionButton.pack(side="top", pady=5)
- # Forces Pages #
- class forcesPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Forces Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.label = tk.Label(self, text = "Forces Topics:", font = MEDIUMFONT)
- self.ScalarsVectorsButton = tk.Button(self, text = "Scalars and Vectors", command=lambda: controller.show_frame(ScalarsVectorsPage))
- self.AdditionVectorsCalculationButton = tk.Button(self, text = "Addition of Vectors - Calculation", command=lambda: controller.show_frame(AdditionVectorsCalculationPage))
- self.AdditionVectorsScaleDrawingButton = tk.Button(self, text = "Addition of Vectors - Scale Drawing", command=lambda: controller.show_frame(AdditionVectorsScaleDrawingPage))
- self.ResolutionOfVectorsButton = tk.Button(self, text = "Resolution of Vectors", command=lambda: controller.show_frame(ResolutionOfVectorsPage))
- self.VectorsInEquilibriumButton = tk.Button(self, text = "Vectors in Equilibrium", command=lambda: controller.show_frame(VectorsInEquilibriumPage))
- self.InclinedPlaneVectorsButton = tk.Button(self, text = "Inclined Plane Vectors", command=lambda: controller.show_frame(InclinedPlaneVectorsPage))
- self.label.pack(side="top", fill="x", pady=10)
- self.ScalarsVectorsButton.pack(side="top", pady=15, ipadx=10)
- self.AdditionVectorsCalculationButton.pack(side="top", pady=15, ipadx=10)
- self.AdditionVectorsScaleDrawingButton.pack(side="top", pady=15, ipadx=10)
- self.ResolutionOfVectorsButton.pack(side="top", pady=15, ipadx=10)
- self.VectorsInEquilibriumButton.pack(side="top", pady=15, ipadx=10)
- self.InclinedPlaneVectorsButton.pack(side="top", pady=15, ipadx=10)
- class ScalarsVectorsPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Scalars and Vectors Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.canvas = Canvas(self, width=800, height=500, bd=2)
- self.canvas.pack()
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.pack(ipadx=10)
- self.canvas.create_line(400, 0, 400, 350)
- self.canvas.create_line(400, 400, 400, 500)
- self.canvas.create_line(20, 375, 325, 375)
- self.canvas.create_line(475, 375, 780, 375)
- self.canvas.create_text(200, 15, text = "Scalars", font = MEDIUMFONT)
- self.canvas.create_line(100, 175, 300, 75, arrow=BOTH, arrowshape="2 1 10")
- self.canvas.create_text(160, 100, text = "2 metres", font = LABELFONT)
- self.canvas.create_text(200, 250, text = "Scalars have size / length / magnitude", font = LABELFONT)
- self.canvas.create_text(200, 300, text = "They have no direction", font = MEDIUMFONT)
- self.canvas.create_text(600, 15, text = "Vectors", font = MEDIUMFONT)
- self.canvas.create_text(500, 60, text = "North", font = LABELFONT)
- self.canvas.create_line(500, 175, 500, 75, arrow=LAST) # North arrow
- self.canvas.create_line(500, 175, 700, 75, arrow=LAST) # Scalar arrow
- self.canvas.create_arc(475, 150, 525, 200, start = 90.0, extent = -63.44)
- self.canvas.create_text(660, 135, text = "2 metres", font = LABELFONT)
- self.canvas.create_text(520, 140, text = "Θ", font = LABELFONT)
- self.canvas.create_text(600, 250, text = "Vectors have size / length / magnitude", font = LABELFONT)
- self.canvas.create_text(600, 300, text = "They also have a direction / bearing", font = LABELFONT)
- self.canvas.create_text(400, 375, text = "Examples", font = MEDIUMFONT)
- self.canvas.create_text(120, 435, text = "Speed", font = MEDIUMFONT)
- self.canvas.create_text(200, 470, text = "Mass", font = MEDIUMFONT)
- self.canvas.create_text(280, 435, text = "Distance", font = MEDIUMFONT)
- self.canvas.create_text(465, 435, text = "Velocity", font = MEDIUMFONT)
- self.canvas.create_text(515, 470, text = "Force", font = MEDIUMFONT)
- self.canvas.create_text(565, 435, text = "Weight", font = MEDIUMFONT)
- self.canvas.create_text(650, 470, text = "Acceleration", font = MEDIUMFONT)
- self.canvas.create_text(700, 435, text = "Displacement", font = MEDIUMFONT)
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(forcesPage)
- class AdditionVectorsCalculationPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Addition of Vectors - Calculation Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.canvas = Canvas(self, width=800, height=500, bd=2)
- self.canvas.pack()
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.pack(ipadx=10)
- self.canvas.create_line(25, 150, 425, 20, arrow=LAST, arrowshape="16 20 6")
- self.canvas.create_rectangle(400, 125, 425, 150)
- self.canvas.create_arc(-50, 100, 100, 200, extent = 25.5)
- self.canvas.create_text(110, 135, text = "Θ", font = LABELFONT)
- self.canvas.create_line(425, 150, 425,50, arrow=LAST, arrowshape="12 16 4", fill="red")
- self.canvas.create_line(425, 50, 425, 20, fill="red")
- self.canvas.create_line(25, 150, 375, 150, arrow=LAST, arrowshape="12 16 4", fill="blue")
- self.canvas.create_line(375, 150, 425, 150, fill="blue")
- self.canvas.create_text(450, 75, text = "a", font = LABELFONT, fill="red")
- self.canvas.create_text(225, 170, text = "b", font = LABELFONT, fill="blue")
- self.canvas.create_text(225, 50, text = "c", font = LABELFONT)
- self.canvas.create_text(625, 75, text = """You will only ever be asked
- to add vectors by calculation
- with vectors at right angles
- Therefore, addition of vectors
- by calculation simply requires
- Pythagoras's Theorem""", font = LABELFONT)
- self.canvas.create_text(175, 225, text = "PYTHAGORAS", font = LARGEFONT)
- self.canvas.create_text(175, 275, text = "a^2 + b^2 = c^2", font = LARGEFONT)
- self.canvas.create_text(175, 375, text = "TRIGONOMETRY", font = LARGEFONT)
- self.canvas.create_text(175, 425, text = "tan Θ = a / b", font = LARGEFONT)
- self.canvas.create_text(550, 325, text = """You may be asked to find the final vector
- after travelling along two vectors
- In which case, substitute in 'a' and 'b'
- and rearrange to find 'c'
- which will be your vector's magnitude
- Use trigonometry to find
- the angle of the vector""", font = LABELFONT)
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(forcesPage)
- class AdditionVectorsScaleDrawingPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Addition of Vectors - Scale Drawing Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.canvas = Canvas(self, width=800, height=500, bd=2)
- self.canvas.pack()
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.pack(ipadx=10)
- self.canvas.create_text(50, 10, text = "North", font = LABELFONT)
- self.canvas.create_line(50, 200, 50, 20, dash=True, arrow=LAST, arrowshape="12 16 4") # North Arrow
- self.canvas.create_arc(25, 175, 75, 225, start = 90.0, extent = -45.0)
- self.canvas.create_text(175, 10, text = "North", font = LABELFONT)
- self.canvas.create_line(175, 75, 175, 20, dash=True, arrow=LAST, arrowshape="12 16 4") # North Arrow
- self.canvas.create_rectangle(175, 75, 190, 60)
- self.canvas.create_line(50, 200, 175, 75, arrow=LAST, arrowshape="16 20 6", fill="red")
- self.canvas.create_line(175, 75, 425, 75, arrow=LAST, arrowshape="16 20 6", fill="blue")
- self.canvas.create_text(160, 155, text = "10 KM\nVector a", font = LABELFONT, fill="red")
- self.canvas.create_text(300, 100, text = "20 KM\nVector b", font = LABELFONT, fill="blue")
- self.canvas.create_text(75, 145, text = "45°", font = LABELFONT)
- self.canvas.create_text(620, 125, text = """You can be asked to add two vectors
- by scale drawing
- The angle between these vectors is
- NOT limited to right angles
- You must draw the vectors
- to scale""", font = LABELFONT)
- self.canvas.create_text(400, 240, text = "DRAW TO SCALE - DECLARE YOUR SCALE", font = LARGEFONT)
- self.canvas.create_rectangle(15, 285, 145, 315)
- self.canvas.create_text(80, 300, text = "1 KM = 1 CM", font = LABELFONT)
- self.canvas.create_text(50, 340, text = "North", font = LABELFONT)
- self.canvas.create_line(50, 460, 50, 350, dash=True, arrow=LAST, arrowshape="12 16 4") # North Arrow
- self.canvas.create_arc(25, 435, 75, 485, start = 90.0, extent = -72.5)
- self.canvas.create_text(65, 425, text = "Θ", font = LABELFONT)
- self.canvas.create_line(50, 460, 175, 335, arrow=LAST, arrowshape="16 20 6", fill="red")
- self.canvas.create_line(175, 335, 425, 335, arrow=LAST, arrowshape="16 20 6", fill="blue")
- self.canvas.create_text(120, 370, text = "a", font = LABELFONT, fill="red")
- self.canvas.create_text(280, 320, text = "b", font = LABELFONT, fill="blue")
- self.canvas.create_text(150, 400, text = "10 CM", font = LABELFONT, fill="red")
- self.canvas.create_text(280, 355, text = "20 CM", font = LABELFONT, fill="blue")
- self.canvas.create_line(50, 460, 425, 335, fill="red")
- self.canvas.create_line(50, 460, 425, 335, dash=True, fill="blue")
- self.canvas.create_text(300, 420, text = "Resultant Vector", font = MEDIUMFONT, fill="red")
- self.canvas.create_text(620, 375, text = "For the magnitude, measure\nthe resultant vector using\na ruler\n\nFor the angle, measure\nΘ with a protractor", font = LABELFONT)
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(forcesPage)
- class ResolutionOfVectorsPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Resolution of Vectors Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.canvas = Canvas(self, width=800, height=500, bd=2)
- self.canvas.pack()
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.pack(ipadx=10)
- self.canvas.create_line(50, 150, 450, 20, arrow=LAST, arrowshape="16 20 6")
- self.canvas.create_line(50, 150, 50, 20, dash=True, arrow=LAST, arrowshape="12 16 4", fill="red")
- self.canvas.create_line(50, 150, 450, 150, dash=True, arrow=LAST, arrowshape="12 16 4", fill="blue")
- self.canvas.create_text(250, 50, text = "? ms^-1", font = LABELFONT)
- self.canvas.create_text(100, 75, text = "3 ms^-1", font = LABELFONT, fill="red")
- self.canvas.create_text(250, 175, text = "4 ms^-1", font = LABELFONT, fill="blue")
- self.canvas.create_text(625, 100, text = """Similar to addition of vectors
- by calculation
- Every vector has a vertical
- and horizontal component
- Simply add the two components
- in order to find the vector's
- magnitude""", font = LABELFONT)
- self.canvas.create_line(350, 390, 750, 240, arrow=LAST, arrowshape="16 20 6")
- self.canvas.create_rectangle(725, 365, 750, 390)
- self.canvas.create_arc(300, 340, 400, 440, extent = 20.5)
- self.canvas.create_text(420, 377, text = "Θ", font = LABELFONT)
- self.canvas.create_line(750, 390, 750, 290, arrow=LAST, arrowshape="12 16 4", fill="red")
- self.canvas.create_line(750, 290, 750, 240, fill="red")
- self.canvas.create_line(350, 390, 700, 390, arrow=LAST, arrowshape="12 16 4", fill="blue")
- self.canvas.create_line(700, 390, 750, 390, fill="blue")
- self.canvas.create_text(775, 315, text = "a", font = LABELFONT, fill="red")
- self.canvas.create_text(550, 410, text = "b", font = LABELFONT, fill="blue")
- self.canvas.create_text(550, 290, text = "c", font = LABELFONT)
- self.canvas.create_text(100, 245, text = "a^2 + b^2 = c^2", font = LABELFONT)
- self.canvas.create_text(100, 295, text = "3^2 + 4^2 = c^2", font = LABELFONT)
- self.canvas.create_text(100, 345, text = "c^2 = 25", font = LABELFONT)
- self.canvas.create_text(100, 395, text = "c = 5", font = LABELFONT)
- self.canvas.create_text(310, 245, text = "arg Θ = 3 / 4", font = LABELFONT)
- self.canvas.create_text(310, 295, text = "Θ = tan^-1( 0.75 )", font = LABELFONT)
- self.canvas.create_text(310, 345, text = "Θ ≈ 53°", font = LABELFONT)
- self.canvas.create_text(475, 465, text = "Vector Magnitude is 5 ms^-1, Vector Angle is 53°", font = LABELFONT)
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(forcesPage)
- class VectorsInEquilibriumPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Vectors In Equilibrium Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.canvas = Canvas(self, width=800, height=500, bd=2)
- self.canvas.pack()
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.pack(ipadx=10)
- self.canvas.create_text(400, 20, text = "F = ma", font = LARGEFONT)
- self.canvas.create_text(400, 50, text = "When an object is in equilibrium, the resultant force acting on it is 0", font = LABELFONT)
- self.canvas.create_text(400, 70, text = "If F = 0, ma = 0. Assuming the object has mass, when in equilibrium, acceleration = 0", font = LABELFONT)
- self.canvas.create_text(400, 90, text = "When acceleration = 0, the object has constant velocity", font = LABELFONT)
- # Underline
- self.canvas.create_line(160, 102, 640, 102)
- # Page divider
- self.canvas.create_line(400, 110, 400, 490)
- # At rest
- self.canvas.create_text(200, 135, text = "Objects in equilibrium - at rest", font = MEDIUMFONT)
- self.canvas.create_line(20, 260, 380, 260)
- self.canvas.create_rectangle(175, 210, 225, 260)
- self.canvas.create_oval(198, 233, 202, 237, fill="black")
- self.canvas.create_text(50, 250, text = "Table", font = SMALLFONT)
- self.canvas.create_line(200, 160, 200, 235, fill="blue", arrow=FIRST)
- self.canvas.create_text(280, 185, text = "Reaction Force", font = LABELFONT, fill="blue")
- self.canvas.create_line(200, 235, 200, 310, fill="red", arrow=LAST)
- self.canvas.create_text(165, 285, text = "Weight ", font = LABELFONT, fill="red")
- self.canvas.create_text(200, 350, text = "The table supports the block by exerting a", font = LABELFONT)
- self.canvas.create_text(200, 390, text = "reaction force equal to the blocks weight", font = LABELFONT)
- self.canvas.create_text(200, 430, text = "Resultant force is 0 and so its acceleration", font = LABELFONT)
- self.canvas.create_text(200, 470, text = "is 0. Therefore it stays at rest", font = LABELFONT)
- # Moving
- self.canvas.create_text(600, 135, text = "Objects in equilibrium - moving", font = MEDIUMFONT)
- self.canvas.create_text(600, 180, text = "Velocity = 30 ms^-1", font = LABELFONT)
- self.canvas.create_line(420, 290, 780, 290)
- try:
- self.Car = tk.PhotoImage(file = "NEACar1.png")
- self.canvas.create_image(600, 260, image=self.Car)
- except:
- self.canvas.create_text(600, 260, text = "Car Image not found")
- self.canvas.create_line(537, 260, 450, 260, fill="red", arrow=LAST)
- self.canvas.create_text(490, 240, text = "Thrust ", font = LABELFONT, fill="red")
- self.canvas.create_line(663, 260, 750, 260, fill="blue", arrow=LAST)
- self.canvas.create_text(710, 230, text = "Air Resistance", font = LABELFONT, fill="blue")
- self.canvas.create_line(635, 290, 750, 290, fill="blue", arrow=LAST)
- self.canvas.create_text(690, 305, text = "Friction", font = LABELFONT, fill="blue")
- self.canvas.create_text(600, 345, text = "If in equilibrium,", font = LABELFONT)
- self.canvas.create_text(600, 375, text = "Thrust = Air Resistance + Friction,", font = LABELFONT)
- self.canvas.create_text(600, 405, text = "so the overall force on the car is 0", font = LABELFONT)
- self.canvas.create_text(600, 435, text = "So its acceleration is 0", font = LABELFONT)
- self.canvas.create_text(600, 465, text = "Therefore it stays at its current velocity", font = LABELFONT)
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(forcesPage)
- class InclinedPlaneVectorsPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Inclined Plane Vectors Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.canvas = Canvas(self, width=800, height=500, bd=2)
- self.canvas.pack()
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.pack(ipadx=10)
- self.canvas.create_text(400, 25, text = "When an object is stationary on an inclined plane, 3 forces are acting on it", font = MEDIUMFONT)
- self.canvas.create_text(400, 50, text = "1. Weight of the object, acting vertically downwards", font = SMALLFONT)
- self.canvas.create_text(400, 75, text = "2. The Support / Reaction force, acting perpendicular to where the weight acts on the plane", font = SMALLFONT)
- self.canvas.create_text(400, 100, text = "3. Friction, acting parallel to the plane", font = SMALLFONT)
- # Box
- self.canvas.create_polygon(120, 225, 160, 215, 150, 175, 110, 185, fill="white", outline="black")
- self.canvas.create_oval(133, 198, 137, 202, fill="black")
- # Weight arrow
- self.canvas.create_line(135, 125, 135, 220, fill="green", arrow=LAST)
- self.canvas.create_text(160, 150, text = "Weight", fill="green")
- # Support Arrow
- self.canvas.create_line(135, 220, 90, 135, fill="blue", arrow=LAST)
- self.canvas.create_text(70, 160, text = "Support", fill="blue")
- # Friction Arrows
- self.canvas.create_line(90, 135, 135, 125, fill="red", arrow=LAST)
- self.canvas.create_text(105, 115, text = "Friction", fill="red")
- self.canvas.create_line(135, 220, 175, 210, fill="red", arrow=LAST)
- # Triangle
- self.canvas.create_arc(-40, 190, 80, 310, extent = 14.0)
- self.canvas.create_line(20, 250, 500, 250, fill="green")
- self.canvas.create_line(500, 250, 420, 150, fill="red")
- self.canvas.create_line(20, 250, 420, 150, fill="blue")
- self.canvas.create_text(100, 240, text = "Θ", font = SMALLFONT)
- self.canvas.create_text(650, 200, text = "As colour coordinated, one can see\nthat the rules of similar triangles\ncan be used\n\nThis allows us to form this triangle ↓", font = SMALLFONT)
- # New Triangle
- self.canvas.create_arc(210, 390, 330, 510, extent = 14.0)
- self.canvas.create_line(270, 450, 750, 450, fill="green", arrow=FIRST)
- self.canvas.create_line(750, 450, 670, 350, fill="red", arrow=FIRST)
- self.canvas.create_line(270, 450, 670, 350, fill="blue", arrow=LAST)
- self.canvas.create_text(350, 440, text = "Θ", font = SMALLFONT)
- self.canvas.create_text(550, 465, text = "Weight", fill="green")
- self.canvas.create_text(470, 380, text = "Support", fill="blue")
- self.canvas.create_text(740, 390, text = "Friction", fill="red")
- self.canvas.create_text(320, 350, text = """If asked to find out the angle of the inclined plane, use trigonometry
- and your values of weight, support and friction to find Θ
- As the triangle's overall displacement is zero,
- an unknown weight, support or friction force
- will be equal to the negative sum of the
- known values
- e.g. W = -(S + F)""", font = LABELFONT)
- self.canvas.create_text(125, 475, text = "W + S + F = 0", font = MEDIUMFONT)
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(forcesPage)
- # Time Graoh Pages #
- class timeGraphsPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Time Graphs Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.label = tk.Label(self, text = "Time Graphs:", font = MEDIUMFONT)
- self.GradientsButton = tk.Button(self, text = "Gradients", command=lambda: controller.show_frame(GradientsPage))
- self.AreaUnderCurveButton = tk.Button(self, text = "Area Under Curve", command=lambda: controller.show_frame(AreaUnderCurvePage))
- self.BouncingBallbutton = tk.Button(self, text = "Experiment - Bouncing Ball", command=lambda: controller.show_frame(BouncingBallPage))
- self.label.pack(side="top", fill="x", pady=10)
- self.GradientsButton.pack(side="top", pady=15, ipadx=10)
- self.AreaUnderCurveButton.pack(side="top", pady=15, ipadx=10)
- self.BouncingBallbutton.pack(side="top", pady=15, ipadx=10)
- class GradientsPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Gradients Of Time Graphs Page", font=LARGEFONT)
- self.title.grid(row=0 , column=0, columnspan=2, padx=10, pady=10)
- self.distanceCanvas = Canvas(self, width=400, height=160, bd=2)
- self.distanceCanvas.grid(row=1, column=0)
- self.displacementCanvas = Canvas(self, width=400, height=160, bd=2)
- self.displacementCanvas.grid(row=1, column=1)
- self.speedCanvas = Canvas(self, width=400, height=160, bd=2)
- self.speedCanvas.grid(row=2, column=0)
- self.velocityCanvas = Canvas(self, width=400, height=160, bd=2)
- self.velocityCanvas.grid(row=2, column=1)
- self.accelerationCanvas = Canvas(self, width=400, height=160, bd=2)
- self.accelerationCanvas.grid(row=3, column=0, columnspan=2)
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.grid(row=4, column=0, ipadx=10)
- self.scalarVectorLabel = tk.Label(self, text = "Blue = Scalar , Red = Vector")
- self.scalarVectorLabel.grid(row=4, column=1, padx=5)
- self.distanceCanvas.create_text(200, 15, text = "Distance - Time Graph",font = MEDIUMFONT, fill="blue")
- self.distanceCanvas.create_line(50, 135, 50, 35, width = 3, fill="blue")
- self.distanceCanvas.create_line(50, 135, 200, 135, width = 3, fill="blue")
- self.distanceCanvas.create_line(50, 135, 195, 40, fill="blue")
- self.distanceCanvas.create_text(25, 85, text = "d",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(300, 55, text = "Gradient",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(300, 85, text = "= d / t",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(300, 115, text = "= Speed",font = LABELFONT, fill="blue")
- self.displacementCanvas.create_text(200, 15, text = "Displacement - Time Graph",font = MEDIUMFONT, fill="red")
- self.displacementCanvas.create_line(50, 135, 50, 35, width = 3, fill="red")
- self.displacementCanvas.create_line(50, 135, 200, 135, width = 3, fill="red")
- self.displacementCanvas.create_line(50, 135, 195, 40, fill="red")
- self.displacementCanvas.create_text(25, 85, text = "s",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(300, 55, text = "Gradient",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(300, 85, text = "= s / t",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(300, 115, text = "= Velocity",font = LABELFONT, fill="red")
- self.speedCanvas.create_text(200, 15, text = "Speed - Time Graph",font = MEDIUMFONT, fill="blue")
- self.speedCanvas.create_line(50, 135, 50, 35, width = 3, fill="blue")
- self.speedCanvas.create_line(50, 135, 200, 135, width = 3, fill="blue")
- self.speedCanvas.create_line(50, 135, 195, 40, fill="blue")
- self.speedCanvas.create_text(25, 85, text = "s",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(300, 55, text = "Gradient",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(300, 85, text = "= s / t",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(300, 115, text = "Not needed for exam",font = LABELFONT, fill="blue")
- self.velocityCanvas.create_text(200, 15, text = "Velocity - Time Graph",font = MEDIUMFONT, fill="red")
- self.velocityCanvas.create_line(50, 135, 50, 35, width = 3, fill="red")
- self.velocityCanvas.create_line(50, 135, 200, 135, width = 3, fill="red")
- self.velocityCanvas.create_line(50, 135, 195, 40, fill="red")
- self.velocityCanvas.create_text(25, 85, text = "v",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(300, 55, text = "Gradient",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(300, 85, text = "= v / t",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(300, 115, text = "Acceleration",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(200, 15, text = "Acceleration - Time Graph",font = MEDIUMFONT, fill="red")
- self.accelerationCanvas.create_line(50, 135, 50, 35, width = 3, fill="red")
- self.accelerationCanvas.create_line(50, 135, 200, 135, width = 3, fill="red")
- self.accelerationCanvas.create_line(50, 135, 195, 40, fill="red")
- self.accelerationCanvas.create_text(25, 85, text = "a",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(300, 55, text = "Gradient",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(300, 85, text = "= a / t",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(300, 115, text = "Not needed for exam",font = LABELFONT, fill="red")
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(timeGraphsPage)
- class AreaUnderCurvePage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Area Under Curves Of Time Graphs Page", font=LARGEFONT)
- self.title.grid(row=0, column=0, columnspan=2, padx=10, pady=10)
- self.distanceCanvas = Canvas(self, width=400, height=160, bd=2)
- self.distanceCanvas.grid(row=1, column=0)
- self.displacementCanvas = Canvas(self, width=400, height=160, bd=2)
- self.displacementCanvas.grid(row=1, column=1)
- self.speedCanvas = Canvas(self, width=400, height=160, bd=2)
- self.speedCanvas.grid(row=2, column=0)
- self.velocityCanvas = Canvas(self, width=400, height=160, bd=2)
- self.velocityCanvas.grid(row=2, column=1)
- self.accelerationCanvas = Canvas(self, width=400, height=160, bd=2)
- self.accelerationCanvas.grid(row=3, column=0, columnspan=2)
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.grid(row=4, column=0, ipadx=10)
- self.scalarVectorLabel = tk.Label(self, text = "Blue = Scalar , Red = Vector")
- self.scalarVectorLabel.grid(row=4, column=1, padx=5)
- self.distanceCanvas.create_text(200, 15, text = "Distance - Time Graph",font = MEDIUMFONT, fill="blue")
- self.distanceCanvas.create_line(50, 135, 50, 35, width = 3, fill="blue")
- self.distanceCanvas.create_line(50, 135, 200, 135, width = 3, fill="blue")
- self.distanceCanvas.create_line(50, 135, 195, 40, fill="blue")
- self.distanceCanvas.create_text(25, 85, text = "d",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(300, 55, text = "Area Under Curve",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(300, 85, text = "= d x t",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(300, 115, text = "Not needed for exam",font = LABELFONT, fill="blue")
- self.displacementCanvas.create_text(200, 15, text = "Displacement - Time Graph",font = MEDIUMFONT, fill="red")
- self.displacementCanvas.create_line(50, 135, 50, 35, width = 3, fill="red")
- self.displacementCanvas.create_line(50, 135, 200, 135, width = 3, fill="red")
- self.displacementCanvas.create_line(50, 135, 195, 40, fill="red")
- self.displacementCanvas.create_text(25, 85, text = "s",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(300, 55, text = "Area Under Curve",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(300, 85, text = "= s x t",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(300, 115, text = "Not needed for exam",font = LABELFONT, fill="red")
- self.speedCanvas.create_text(200, 15, text = "Speed - Time Graph",font = MEDIUMFONT, fill="blue")
- self.speedCanvas.create_line(50, 135, 50, 35, width = 3, fill="blue")
- self.speedCanvas.create_line(50, 135, 200, 135, width = 3, fill="blue")
- self.speedCanvas.create_line(50, 135, 195, 40, fill="blue")
- self.speedCanvas.create_text(25, 85, text = "s",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(300, 55, text = "Area Under Curve",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(300, 85, text = "= s x t",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(300, 115, text = "= Distance",font = LABELFONT, fill="blue")
- self.velocityCanvas.create_text(200, 15, text = "Velocity - Time Graph",font = MEDIUMFONT, fill="red")
- self.velocityCanvas.create_line(50, 135, 50, 35, width = 3, fill="red")
- self.velocityCanvas.create_line(50, 135, 200, 135, width = 3, fill="red")
- self.velocityCanvas.create_line(50, 135, 195, 40, fill="red")
- self.velocityCanvas.create_text(25, 85, text = "v",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(300, 55, text = "Area Under Curve",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(300, 85, text = "= v x t",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(300, 115, text = "Displacement",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(200, 15, text = "Acceleration - Time Graph",font = MEDIUMFONT, fill="red")
- self.accelerationCanvas.create_line(50, 135, 50, 35, width = 3, fill="red")
- self.accelerationCanvas.create_line(50, 135, 200, 135, width = 3, fill="red")
- self.accelerationCanvas.create_line(50, 135, 195, 40, fill="red")
- self.accelerationCanvas.create_text(25, 85, text = "a",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(125, 153, text = "t",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(300, 55, text = "Area Under Curve",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(300, 85, text = "= a x t",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(300, 115, text = "Velocity",font = LABELFONT, fill="red")
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(timeGraphsPage)
- class BouncingBallPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="Bouncing Ball Example Page", font=LARGEFONT)
- self.title.grid(row=0, column=0, columnspan=2, padx=10, pady=10)
- self.bouncingBallCanvas = Canvas(self, width=400, height=160, bd=2)
- self.bouncingBallCanvas.grid(row=1, column=0)
- self.distanceCanvas = Canvas(self, width=400, height=160, bd=2)
- self.distanceCanvas.grid(row=1, column=1)
- self.displacementCanvas = Canvas(self, width=400, height=160, bd=2)
- self.displacementCanvas.grid(row=2, column=0)
- self.speedCanvas = Canvas(self, width=400, height=160, bd=2)
- self.speedCanvas.grid(row=2, column=1)
- self.velocityCanvas = Canvas(self, width=400, height=160, bd=2)
- self.velocityCanvas.grid(row=3, column=0)
- self.accelerationCanvas = Canvas(self, width=400, height=160, bd=2)
- self.accelerationCanvas.grid(row=3, column=1)
- self.returnButton = tk.Button(self, text = "Return - Click to earn points for visiting this revision page", command=lambda: returnForces())
- self.returnButton.grid(row=4, column=0, ipadx=10)
- self.scalarVectorLabel = tk.Label(self, text = "Blue = Scalar , Red = Vector")
- self.scalarVectorLabel.grid(row=4, column=1, padx=5)
- self.bouncingBallCanvas.create_oval(50, 10, 90, 50, fill="gray40", outline="gray40")
- self.bouncingBallCanvas.create_oval(50, 150, 90, 110, fill="gray40", outline="gray40")
- self.bouncingBallCanvas.create_line(60, 50, 60, 110, width=2)
- self.bouncingBallCanvas.create_line(80, 50, 80, 110, width=2)
- self.bouncingBallCanvas.create_line(60, 50, 45, 65, width=2)
- self.bouncingBallCanvas.create_line(80, 110, 95, 95, width=2)
- self.bouncingBallCanvas.create_line(20, 152, 130, 152, width = 3)
- self.bouncingBallCanvas.create_text(265, 30, text = "Common Exam Question", font = MEDIUMFONT)
- self.bouncingBallCanvas.create_text(265, 70, text = "Ball projected upward, whilst", font = SMALLFONT)
- self.bouncingBallCanvas.create_text(265, 100, text = "in the air, it is acted on", font = SMALLFONT)
- self.bouncingBallCanvas.create_text(265, 130, text = "by gravity only", font = SMALLFONT)
- self.distanceCanvas.create_text(200, 15, text = "Distance - Time Graph", font = MEDIUMFONT, fill="blue")
- self.distanceCanvas.create_line(125, 135, 125, 35, width = 3, fill="blue")
- self.distanceCanvas.create_line(125, 135, 275, 135, width = 3, fill="blue")
- self.distanceCanvas.create_arc(127, 85, 275, 185, start=90, extent=90, style="arc", outline="blue")
- self.distanceCanvas.create_arc(127, -15, 275, 85, start=-90, extent=90, style="arc", outline="blue")
- self.distanceCanvas.create_text(100, 85, text = "d",font = LABELFONT, fill="blue")
- self.distanceCanvas.create_text(200, 153, text = "t",font = LABELFONT, fill="blue")
- self.displacementCanvas.create_text(200, 15, text = "Displacement - Time Graph",font = MEDIUMFONT, fill="red")
- self.displacementCanvas.create_line(125, 135, 125, 35, width = 3, fill="red")
- self.displacementCanvas.create_line(125, 135, 275, 135, width = 3, fill="red")
- self.displacementCanvas.create_arc(127, 35, 275, 235, extent=180, style="arc", outline="red")
- self.displacementCanvas.create_text(100, 85, text = "s",font = LABELFONT, fill="red")
- self.displacementCanvas.create_text(200, 153, text = "t",font = LABELFONT, fill="red")
- self.speedCanvas.create_text(200, 15, text = "Speed - Time Graph",font = MEDIUMFONT, fill="blue")
- self.speedCanvas.create_line(125, 135, 125, 35, width = 3, fill="blue")
- self.speedCanvas.create_line(125, 135, 275, 135, width = 3, fill="blue")
- self.speedCanvas.create_arc(127, -60, 275, 133, extent=-180, style="arc", outline="blue")
- self.speedCanvas.create_text(100, 85, text = "s",font = LABELFONT, fill="blue")
- self.speedCanvas.create_text(200, 153, text = "t",font = LABELFONT, fill="blue")
- self.velocityCanvas.create_text(200, 15, text = "Velocity - Time Graph",font = MEDIUMFONT, fill="red")
- self.velocityCanvas.create_line(125, 135, 125, 35, width = 3, fill="red")
- self.velocityCanvas.create_line(125, 85, 275, 85, width = 3, fill="red")
- self.velocityCanvas.create_line(125, 35, 275, 135, fill="red")
- self.velocityCanvas.create_text(100, 85, text = "v",font = LABELFONT, fill="red")
- self.velocityCanvas.create_text(295, 85, text = "t",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(200, 15, text = "Acceleration - Time Graph",font = MEDIUMFONT, fill="red")
- self.accelerationCanvas.create_line(125, 135, 125, 35, width = 3, fill="red")
- self.accelerationCanvas.create_line(125, 85, 275, 85, width = 3, fill="red")
- self.accelerationCanvas.create_line(125, 50, 275, 50, fill="red")
- self.accelerationCanvas.create_text(100, 85, text = "a",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(295, 85, text = "t",font = LABELFONT, fill="red")
- self.accelerationCanvas.create_text(329, 49, text = "= 9.8 ms^-1",font = SMALLFONT, fill="red")
- def returnForces():
- window.addScore(2)
- messagebox.showinfo("Score Updated","You earned 2 points for visiting this page", icon = "info")
- controller.show_frame(timeGraphsPage)
- # SUVAT Revision Pages #
- class SUVATRevisionPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="SUVAT Revision Page", font=LARGEFONT)
- self.title.pack(side="top", fill="x", pady=30)
- self.SUVATCheckerButton = tk.Button(self, text = "SUVAT Checker", command=lambda: controller.show_frame(SUVATCheckerPage),height=2,width=20)
- self.label1 = tk.Label(self, text = "or ")
- self.SUVATSolverButton = tk.Button(self, text = "SUVAT Solver", command=lambda: controller.show_frame(SUVATSolverPage),height=2,width=20)
- self.SUVATCheckerButton.pack(side="top", pady=5)
- self.label1.pack(side="top", fill="x", pady=5)
- self.SUVATSolverButton.pack(side="top", pady=5)
- class SUVATCheckerPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="SUVAT Checker Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- # Instructions explaining to the user what to enter into each entry field
- self.instructions = tk.Label(self, text = """You should have 3 known values, and an unknown value that you want to find
- For each of the boxes below, either:
- 1. The value is known so type it into the box
- 2. The value is unknown and the value you want to find, type in 'A'
- 3. The value is unknown and not the value you want to find, type in 'X'
- Enter your answer in the box by the check button (Please enter your answer to 2 decimal places. No units!)
- A correct answer will earn you 10 points
- An incorrect answer will lose you 1 point
- """)
- self.displacementText = tk.Label(self, text = "Displacement:")
- self.displacementInput = tk.Entry(self, justify="center", width=30)
- self.initialVelocityText = tk.Label(self, text = "Initial Velocity:")
- self.initialVelocityInput = tk.Entry(self, justify="center", width=30)
- self.finalVelocityText = tk.Label(self, text = "Final Velocity:")
- self.finalVelocityInput = tk.Entry(self, justify="center", width=30)
- self.accelerationText = tk.Label(self, text = "Acceleration:")
- self.accelerationInput = tk.Entry(self, justify="center", width=30)
- self.timeTakenText = tk.Label(self, text = "Time Taken:")
- self.timeTakenInput = tk.Entry(self, justify="center", width=30)
- self.userAnswerText = tk.Label(self, text = "Your Answer: (Please enter your answer to 2 decimal places. No units!)\nSeparate dual answers with a single comma, no spaces!")
- self.userAnswerInput = tk.Entry(self, justify="center", width=30)
- self.submitButton = tk.Button(self,text = "Check", command=lambda: Solve())
- self.instructions.pack(side="top", fill="x")
- self.displacementText.pack(side="top", fill="x", padx=20, pady=5)
- self.displacementInput.pack(side="top")
- self.displacementInput.focus()
- self.initialVelocityText.pack(side="top", fill="x", padx=20, pady=5)
- self.initialVelocityInput.pack(side="top")
- self.finalVelocityText.pack(side="top", fill="x", padx=20, pady=5)
- self.finalVelocityInput.pack(side="top")
- self.accelerationText.pack(side="top", fill="x", padx=20, pady=5)
- self.accelerationInput.pack(side="top")
- self.timeTakenText.pack(side="top", fill="x", padx=20, pady=5)
- self.timeTakenInput.pack(side="top")
- self.userAnswerText.pack(side="top", fill="x", padx=20, pady=5)
- self.userAnswerInput.pack(side="top", pady=5)
- self.submitButton.pack(side="bottom", fill="y", padx=20, pady=5)
- def Solve():
- def deleteEntryFields():
- self.displacementInput.delete(0,"end")
- self.initialVelocityInput.delete(0,"end")
- self.finalVelocityInput.delete(0,"end")
- self.accelerationInput.delete(0,"end")
- self.timeTakenInput.delete(0,"end")
- def response(message1, message2, score, add):
- messagebox.showinfo("{0}".format(message1),"{0}".format(message2), icon = "info")
- if add:
- window.addScore(score)
- messagebox.showinfo("Score Updated","You earnt {0} points for beating PHYSICS".format(score), icon = "info")
- else:
- window.addScore(-score)
- messagebox.showinfo("Score Updated","You lost {0} points for losing to PHYSICS".format(score), icon = "info")
- try:
- s = self.displacementInput.get().lower()
- except:
- s = self.displacementInput.get()
- try:
- u = self.initialVelocityInput.get().lower()
- except:
- u = self.initialVelocityInput.get()
- try:
- v = self.finalVelocityInput.get().lower()
- except:
- v = self.finalVelocityInput.get()
- try:
- a = self.accelerationInput.get().lower()
- except:
- a = self.accelerationInput.get()
- try:
- t = self.timeTakenInput.get().lower()
- except:
- t = self.timeTakenInput.get()
- suvat = [s,u,v,a,t]
- Xcount = 0
- Acount = 0
- numberCount = 0
- for each in suvat:
- if each.lower() == "x": # Increments
- Xcount += 1
- elif each.lower() == "a":
- Acount += 1
- if each.isdigit(): # Used to ensure 3 values are numbers and stops the program crashing from attempting to convert letters into float numbers
- numberCount += 1
- elif "-" in each or "." in each:
- numberCount += 1
- if "" in suvat:
- messagebox.showinfo("Error!","Leave no fields blank", icon="warning")
- elif Acount == 0:
- messagebox.showinfo("Error!","No value given as 'A'", icon="warning")
- elif Acount > 1:
- messagebox.showinfo("Error!","Only one value can be given as 'A'", icon="warning")
- elif Xcount == 0:
- messagebox.showinfo("Error!","No value given as 'X'", icon="warning")
- elif Xcount > 1:
- messagebox.showinfo("Error!","Only one value can be given as 'X'", icon="warning")
- elif numberCount != 3:
- messagebox.showinfo("Error!","Three values entered must be numbers", icon="warning")
- else:
- Solver = SUVAT(s,u,v,a,t,shortAnswer=True) # Calls the Solving algorithm, passing through the parameters given by the user
- # shortAnswer is True, so only the value is returned, no text
- answer = Solver.initiate() # Returns the answer(s) from the SUVAT equations
- if answer == "None": # If an error occurs in the mathematics, 'None' is returned and this stops an error occuring
- messagebox.showinfo("Error","Invalid details inputted, try again", icon = "warning")
- else:
- if answer == "zeroDivision error":
- messagebox.showinfo("Error","Invalid details inputted, resulting in a calculation involving a division by 0\n\nCheck your numbers", icon = "warning")
- else:
- userAnswer = self.userAnswerInput.get()
- if "," in userAnswer: # Comma suggests the answer has two parts, and so continues onto code that compares two answers
- userAnswer1, userAnswer2 = userAnswer.split(",") # Splits the answers into two variables
- answer1, answer2 = "{:.2f}".format(answer[0]), "{:.2f}".format(answer[1]) # Converts answers from SUVAT() into 2 decimal place variables
- userAnswer1, userAnswer2 = "{:.2f}".format(float(userAnswer1)), "{:.2f}".format(float(userAnswer2))
- if userAnswer1 == answer1:
- if userAnswer2 == answer2:
- response("Correct!!", "You got both answers correct", 15, True)
- deleteEntryFields()
- else: # First correct, second incorrect
- response("Incorrect!!", "Your second answer was wrong, try again", 1, False)
- self.userAnswerInput.delete(",","end")
- else: # First answer is incorrect
- if userAnswer2 == answer2: #
- response("Incorrect!!", "Your first answer was wrong, try again", 1, False)
- self.userAnswerInput.delete(0,",")
- else:
- if userAnswer1 == answer2:# If user enters dual answers in wrong order, compare opposite answers
- if userAnswer2 == answer1:
- response("Correct!!", "You got both answers correct", 15, True)
- deleteEntryFields()
- else: # First answer correct, second incorrect
- response("Incorrect!!", "Your second answer was wrong, try again", 1, False)
- self.userAnswerInput.delete(0,",")
- elif userAnswer2 == answer1:
- response("Incorrect!!", "Your first answer was wrong, try again", 1, False)
- self.userAnswerInput.delete(",","end")
- else:
- response("Incorrect!!", "You got both answers wrong, try again", 2, False)
- self.userAnswerInput.delete(0,"end")
- else: # No comma so only one part, so only us the first element in array 'answer'
- answer = "{0:.2f}".format(answer1)
- if userAnswer == answer:
- response("Correct!!", "You got the right answer!!", 10, True)
- deleteEntryFields()
- else:
- response("Incorrect!!", "You entered the wrong answer", 1, False)
- self.userAnswerInput.delete(0,"end")
- class SUVATSolverPage(tk.Frame):
- def __init__(self, parent, controller):
- tk.Frame.__init__(self, parent)
- self.title = tk.Label(self, text="SUVAT Solver Page", font=LARGEFONT)
- self.title.pack(padx=10, pady=10)
- self.instructions = tk.Label(self, text = """You should have 3 known values, and an unknown value that you want to find
- For each of the boxes below, either:
- 1. The value is known so type it into the box
- 2. The value is unknown and the value you want to find, type in 'A'
- 3. The value is unknown and not the value you want to find, type in 'X'
- Warning!!! Every answer you seek from this tool with remove 5 points from your account!
- """)
- self.displacementText = tk.Label(self, text = "Displacement:")
- self.displacementInput = tk.Entry(self, justify="center", width=30)
- self.initialVelocityText = tk.Label(self, text = "Initial Velocity:")
- self.initialVelocityInput = tk.Entry(self, justify="center", width=30)
- self.finalVelocityText = tk.Label(self, text = "Final Velocity:")
- self.finalVelocityInput = tk.Entry(self, justify="center", width=30)
- self.accelerationText = tk.Label(self, text = "Acceleration:")
- self.accelerationInput = tk.Entry(self, justify="center", width=30)
- self.timeTakenText = tk.Label(self, text = "Time Taken:")
- self.timeTakenInput = tk.Entry(self, justify="center", width=30)
- self.submitButton = tk.Button(self,text = "Solve", command=lambda: Solve())
- self.instructions.pack(side="top", fill="x", pady=15)
- self.displacementText.pack(side="top", fill="x", padx=20, pady=5)
- self.displacementInput.pack(side="top")
- self.displacementInput.focus()
- self.initialVelocityText.pack(side="top", fill="x", padx=20, pady=5)
- self.initialVelocityInput.pack(side="top")
- self.finalVelocityText.pack(side="top", fill="x", padx=20, pady=5)
- self.finalVelocityInput.pack(side="top")
- self.accelerationText.pack(side="top", fill="x", padx=20, pady=5)
- self.accelerationInput.pack(side="top")
- self.timeTakenText.pack(side="top", fill="x", padx=20, pady=5)
- self.timeTakenInput.pack(side="top")
- self.submitButton.pack(side="top", fill="y", padx=20, pady=10)
- def Solve():
- # Validation Statements
- try:
- s = self.displacementInput.get().lower()
- except:
- s = self.displacementInput.get()
- try:
- u = self.initialVelocityInput.get().lower()
- except:
- u = self.initialVelocityInput.get()
- try:
- v = self.finalVelocityInput.get().lower()
- except:
- v = self.finalVelocityInput.get()
- try:
- a = self.accelerationInput.get().lower()
- except:
- a = self.accelerationInput.get()
- try:
- t = self.timeTakenInput.get().lower()
- except:
- t = self.timeTakenInput.get()
- suvat = [s,u,v,a,t]
- Xcount = 0
- Acount = 0
- numberCount = 0
- for each in suvat:
- if each.lower() == "x":
- Xcount += 1
- elif each.lower() == "a":
- Acount += 1
- if each.isdigit(): # Used to ensure 3 values are numbers and stops the program crashing from attempting to convert letters into float numbers
- numberCount += 1
- elif "-" in each or "." in each:
- numberCount += 1
- if "" in suvat:
- messagebox.showinfo("Error!","Leave no fields blank", icon="warning")
- elif Acount == 0:
- messagebox.showinfo("Error!","No value given as 'A'", icon="warning")
- elif Acount > 1:
- messagebox.showinfo("Error!","Only one value can be given as 'A'", icon="warning")
- elif Xcount == 0:
- messagebox.showinfo("Error!","No value given as 'X'", icon="warning")
- elif Xcount > 1:
- messagebox.showinfo("Error!","Only one value can be given as 'X'", icon="warning")
- elif numberCount != 3:
- messagebox.showinfo("Error!","Three values entered must be numbers", icon="warning")
- else:
- Solver = SUVAT(s,u,v,a,t,shortAnswer=False) # Calls the Solving algorithm, passing through the parameters given by the user, shortAnswer=False means worded solution returned
- answer = Solver.initiate()
- if answer == "None":
- messagebox.showinfo("Error","Invalid values inputted, try again", icon = "warning")
- else:
- if answer == "zeroDivision error":
- messagebox.showinfo("Error","Invalid details inputted, resulting in a calculation involving a division by 0\n\nCheck your numbers", icon = "warning")
- else:
- messagebox.showinfo("Answer","{0}".format(answer), icon = "info")
- window.addScore(-5)
- messagebox.showinfo("Score Updated","You lost 5 points for cheating PHYSICS by just wanting an answer", icon = "info")
- deleteEntryFields()
- def deleteEntryFields():
- self.displacementInput.delete(0,"end")
- self.initialVelocityInput.delete(0,"end")
- self.finalVelocityInput.delete(0,"end")
- self.accelerationInput.delete(0,"end")
- self.timeTakenInput.delete(0,"end")
- #############################
- ##### Tkinter Runtime #####
- def exitProgram():
- if messagebox.askokcancel("Quit", "Do you wish to quit?"):
- window.logout()
- window.destroy()
- if runProgram: # If any python modules are missing, the Tkinter window will not be called and the program will cease
- window = GUI()
- window.protocol("WM_DELETE_WINDOW", exitProgram) # If 'x' in top right corner of GUI window pressed, call exitProgram()
- window.mainloop()
- ###########################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement