forked from danielstricoff/Calculator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
calculator.py
304 lines (265 loc) · 11.9 KB
/
calculator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# On my honor:
#
# - I have not discussed the Python code in my program with
# anyone other than my instructor or the teaching assistants
# assigned to this course.
#
# - I have not used Python code obtained from another student,
# or any other unauthorized source, either modified or
# unmodified.
#
# - If any Python code or documentation used in my program
# was obtained from another source, such as a text book or
# course notes, that has been clearly noted with a proper
# citation in the comments of my program.
import matplotlib.pyplot as plot
import matplotlib.patches as patches
from scipy import math
import os
import platform
import subprocess as sub
import math
newFileCounter = 0
fileList = []
#writes the py outline that the user will be able to edit
def writePy():
global newFileCounter
fileName = "pythonTemp" + str(newFileCounter) + ".py"
command = "touch " + fileName
os.system(command)
with open(fileName, "w") as newFile:
newFile.write("#Keep in mind, any line with a \"#\" leading it is a comment which means it does not impact the code.\n\n")
newFile.write("#These are import statements which import modules and allow the python code to access more functions\nimport sys\n")
newFile.write("import matplotlib.pyplot as plot\t#pyplot provides plot for images, run these functions using \"plot\"\n")
newFile.write("import matplotlib.patches as patches\t#2D images with color, run these functions with patches\n\n")
newFile.write("#\"def\" is a keyword to declare a function in python. \n")
newFile.write("#\"firstFunction\" is the name of the function and \"arg1\" is the parameter passed into the function.\n")
newFile.write("def firstFunction(arg1):\n\n\t#Creates a plot to hold created shape\n\tfig = plot.figure()\n")
newFile.write("\tsub = fig.add_subplot(111, aspect= 'equal')\n\n")
newFile.write("\t#Creates a new shape using Polygon function and stores in variable \"shape\". Try out others at https://matplotlib.org/api/patches_api.html\n")
newFile.write("\tshape = patches.Polygon([[0,0], [0,arg1], [arg1,0]], closed=True,fill=True,color ='b', )\n\n")
newFile.write("\t#Adds shape to the plot\n\tsub.add_patch(shape)\n\n")
newFile.write("\t#The following lines sets the y and x axis limits for the pyplot.These values can be adjusted to change the size of your plot\n")
newFile.write("\tplot.ylim(0, 10)\n\tplot.xlim(0, 10)\n\n")
newFile.write("\t#This line displays the pyplot, do not remove this line. \n\tplot.show()\n\n")
newFile.write("#Below calls the function using the function name \"firstFunction\". Remember if you change the function name change it here too!\n")
newFile.write("#The function is called with one argument. If you change the number of parameters the function call changes as well.")
newFile.write("\n#\tExample of function call w/ two param: firstfunction(sys.argv[1], sys.argv[2])\n\n")
newFile.write("firstFunction(sys.argv[1])\n")
newFileCounter+=1
return fileName
# Introduction info about the Calculator
# Prompts the user to pick a shape
def parser():
global fileList
print("Welcome to the Geometry Calculator.")
print("CALC -> Would you like to enable developer mode? (Y/N)")
answer = input('CALC -> ')
if answer == "Y":
developerMode()
while True:
print("CALC -> Select a shape: rectangle, triangle, circle, rhombus:")
shape = input('CALC -> ')
if shape == "rectangle":
rectangle()
elif shape == "dev":
developerMode()
elif shape == "myFiles":
for i in fileList:
print("CALC -> " + i)
elif shape == "triangle":
triangle()
elif shape == "circle":
circle()
elif shape == "rhombus":
rhombus()
else:
calcDev(shape)
print("CALC -> Do you want to exit the calculator? (Y/N)")
v = input('CALC -> ')
if v == 'Y':
break
#Asks for the needed measurements
#Print the area
#Call graph
#prints the perimeter and area as well as plots the rectangle with the appropriate length and height
def rectangle():
print("CALC -> Enter the length: ")
length = int(input('CALC -> '))
print("CALC -> Enter the height: ")
height = int(input('CALC -> '))
perim = 2 * length + 2 * height
area = length*height
print("CALC -> Perimeter = 2 * (length + width) = %.3f" %perim)
print("CALC -> Area = length * width = %.3f" %area)
fig = plot.figure()
ax1 = fig.add_subplot(111, aspect='equal')
ax1.add_patch(patches.Rectangle((3, 3), length, height))
plot.ylim(0, height + 5)
plot.xlim(0, length + 5)
plot.show()
#Asks for the needed measurements
#Assumed Right Triangle
def triangle():
print("CALC -> Please enter the base length: ")
b = int(input("CALC -> "))
print("CALC -> Please enter the height: ")
h = int(input("CALC -> "))
fig = plot.figure()
area = (1/2)* b * h
perimeter = b + h + math.sqrt(h**2 + b**2)
print("CALC -> Area = 1/2 * base * height = %.3f" %area)
print("CALC -> Perimeter = base + height + sqrt(base^2 + height^2) = %.3f" %perimeter)
p1 = (0, h)
p2 = (0, 0)
p3 = (b, 0)
tri = patches.Polygon([p1,p2,p3], closed=True,fill=True)
sub = fig.add_subplot(111, aspect= 'equal')
sub.add_patch(tri)
plot.ylim(0, h + 5)
plot.xlim(0, b+ 5)
plot.show()
#Asks for the needed measurements
#Print the area
#Call graph
#plots the circle based on the radius
def circle():
print("CALC -> Enter the radius: ")
radius = int(input('CALC -> '))
area = math.pi*(int(radius)**2)
perim = 2 * int(radius) * math.pi
print("CALC -> Area = pi * radius * radius = %.3f" %area)
print("CALC -> Circumference = 2 * pi * radius = %.3f" %perim)
fig = plot.figure()
circle1 = patches.Circle((int(radius), int(radius)), radius, color = 'r')
sub = fig.add_subplot(111, aspect= 'equal')
sub.add_patch(circle1)
plot.ylim(0, int(radius)*2)
plot.xlim(0, int(radius)*2)
plot.show()
#Asks for the needed measurements
#Print the area
#Call graph
def rhombus():
fig = plot.figure()
p = int(input("CALC -> Please enter the first diagonal length: "))
q = int(input("CALC -> Please enter the second diagonal length: "))
area = (p*q) / 2
perimeter = 2 * math.sqrt(p**2 + q**2)
print("CALC -> Area = 1/2 * (diagonal 1) * (diagonal 2) = %.3f" %area)
print("CALC -> Perimeter = 2 * sqrt((diagonal 1)^2 + (diagonal 2)^2) = %.3f" %perimeter)
p1 = (0, p/2)
p2 = (q/2, p)
p3 = (q, p/2)
p4 = (q/2, 0)
tri = patches.Polygon([p1,p2,p3,p4], closed=True,fill=True)
sub = fig.add_subplot(111, aspect= 'equal')
sub.add_patch(tri)
plot.ylim(0, p + 5)
plot.xlim(0, q + 5)
plot.show()
#Calls files that were created in developer mode
def calcDev(fileName):
global fileList
fileInfo = fileName.split()
inList = False
for files in fileList:
if (fileInfo[0] == files):
inList =True;
if (not inList):
print("CALC -> That input is not available")
return
command = ['python']
command.extend(fileInfo)
try:
sub.check_call(command)
except sub.CalledProcessError:
print("CALC -> That input is not available")
#Checks if they are finished
def finishedDev():
while (True):
inp = input("DEV -> Would you like to continue editing your script or are you finished in Dev mode? (quit/cont): ")
if (inp == "quit"):
return True
elif (inp == "cont"):
return False
else:
print("DEV -> That is not a valid answer")
#Adds to global list
def addToList(fileName):
global fileList
inList = False
for i in fileList:
if (fileName == i):
inList = True
if (not inList):
fileList.append(fileName)
#Removes from global list
def removeFromList(fileName):
global fileList
try:
fileList.remove(fileName)
except ValueError:
pass
#Gives the user to develop their own functions through python scripts
#Provides the user an outline and walks them through the script and lets them play around
#with the code to make their own calculator functions
def developerMode():
#filename is the name of the written outline which is written in writePy()
fileName = writePy()
commandArr = ['python', fileName, '1']
#runs the outline code to show the user what the code originially displays
print("DEV -> This image is what the current code script plots, have fun developing!")
sub.call(commandArr)
#Opens the outline code in the notepad and allows the user to edit the code
print("DEV -> Please close and save file when you are finished editing")
if (platform.system() == "Darwin"): #Opens a text editer on a mac
sub.run(['open', fileName], check = True)
elif (platform.system() == "Windows"): #Opens notepad on windows
sub.call(['notepad', filename])
# if user saved file under a new name, prompts user for name and saves it
newFile = input("DEV -> If you have saved the file under a new name please enter here, otherwise press ENTER: ")
if (len(newFile) > 0):
fileName = newFile
#gets user to input arguments and adds them to the command list
paramNum = int(input("DEV -> How many arguments does you function have? "))
commandArr = ['python', fileName]
if (paramNum > 0):
params = input("DEV -> Please enter your function arguments seperated by spaces: ")
params = params.split()
commandArr.extend(params)
#Loops through the developing process until the user wants to exit developer mode
while(True):
try:
print("DEV -> Your code will now run and check for errors. If it is error free your graph will be displayed!")
print("DEV -> If there are any errors in your code, they will be printed below and your plot will not display")
sub.check_call(commandArr)
addToList(fileName)
if (finishedDev()):
break
except sub.CalledProcessError:
removeFromList(fileName)
print("\nDEV -> There was an error in your code, please try again.")
#prompts user if they would like to fix their code
inp = input("DEV -> Would you like to try to fix your code? (Y/N): ")
#If no then prompts user if they would like to stay in dev mode
if (inp == "N" and finishedDev()):
break
#Opens the outline code in the notepad and allows the user to edit the code
print("DEV -> Please save file before you are finished editing and the code is run")
if (platform.system() == "Darwin"): #Opens a text editer on a mac
sub.run(['open', fileName], check = True)
elif (platform.system() == "Windows"): #Opens notepad on windows
sub.call(['notepad', filename])
#If user saved file under a new name, prompts user for name and saves it
newFile = input("DEV -> If you have saved the file under a new name please enter here, otherwise press ENTER: ")
if (len(newFile) > 0):
fileName = newFile
#gets user to input arguments and adds them to the command list
paramNum = int(input("DEV -> How many arguments does you function have? "))
commandArr = ['python', fileName]
if (paramNum > 0):
params = input("DEV -> Please enter your function arguments seperated by spaces: ")
params = params.split()
commandArr.extend(params)
parser()