diff --git a/ClassDesign.txt b/ClassDesign.txt new file mode 100644 index 0000000..b28365c --- /dev/null +++ b/ClassDesign.txt @@ -0,0 +1,11 @@ +- pygame display + - screen class + -draw screen + - piegraph class + - arcs + - input_menu class + - init_menu class + - main + + +- data parser \ No newline at end of file diff --git a/DINOT-Bold.otf b/DINOT-Bold.otf new file mode 100644 index 0000000..62ffe41 Binary files /dev/null and b/DINOT-Bold.otf differ diff --git a/DINOT.otf b/DINOT.otf new file mode 100644 index 0000000..9e9bf29 Binary files /dev/null and b/DINOT.otf differ diff --git a/Display.py b/Display.py new file mode 100644 index 0000000..d135a6d --- /dev/null +++ b/Display.py @@ -0,0 +1,330 @@ +""" +Carl Moser and Serena Chen + +Creates a GUI that allows you to make a pie graph with data that you'd like. +""" +import pygame +from pygame.locals import QUIT, KEYDOWN +from random import randrange +import time +from math import pi, sin, cos, hypot, atan2 +from numpy import arange +import doctest +import Tkinter as t +import tkMessageBox + + +class Screen(object): + """Has a screen, takes in models to draw, keyboard control, if applicable""" + def __init__(self, model, size): + self.model = model + self.screen = pygame.display.set_mode(size) + self.radius = 400 + self.base_rect = pygame.Rect(100,150,self.radius*2,self.radius*2) + self.raw=False + + def draw(self): + """This function redraws the screen and updates it""" + self.screen.fill((0,0,0)) + + #Creates the command label at the top of the screen + font = pygame.font.Font('DINOT-Bold.otf',30) + commands_line1 = font.render('Press \'ENTER\' to add a sdata entry',True,(255,255,255)) + commands_line2 = font.render('Click on a slice to modify it\'s existing value',True,(255,255,255)) + commands_line3 = font.render('Press \'S\' to save a screenshot',True,(255,255,255)) + commands_line4 = font.render('Press \'V\' to see data values',True,(255,255,255)) + + self.screen.blit(commands_line1,(10,10)) + self.screen.blit(commands_line2,(10,45)) + self.screen.blit(commands_line3,(10,80)) + self.screen.blit(commands_line4,(10,115)) + + #draw slices + for arc in self.model.get_arcs(): + col = arc['color'] + #draw an arc with thickness of the radius + pygame.draw.arc( + self.screen, + col, + self.base_rect, + arc['start_angle'], + arc['stop_angle'], + self.radius/2) + cx = self.base_rect.centerx + cy = self.base_rect.centery + #draw lines coming out of the center to make up for some of the bad graphics + for theta in arange(arc['start_angle'],arc['stop_angle'],.00005): + pygame.draw.line(self.screen, col, (cx,cy), (self.radius*cos(theta)+cx,-1*self.radius*sin(theta)+cy)) + + #draw slice label + font_slice = pygame.font.Font('DINOT-Bold.otf',30) + words = font_slice.render(arc['label'],True, (0,0,0)) + font_raw = pygame.font.Font('DINOT-Bold.otf',20) + data = font_raw.render(str(arc['val']),True, (0,0,0)) + + pos = (cx + int(self.radius*cos((arc['start_angle']+arc['stop_angle'])/2.0)/2) - words.get_width()/2, + cy - int(self.radius*sin((arc['start_angle']+arc['stop_angle'])/2.0)/2) - words.get_height()/2) + pygame.draw.rect(self.screen, (col[0]+20,col[1]+20,col[2]+20), (pos[0],pos[1],words.get_width(),words.get_height())) + self.screen.blit(words,pos) + + if self.raw: + pygame.draw.rect(self.screen, (col[0]+20,col[1]+20,col[2]+20), (pos[0],pos[1]+40,data.get_width(),data.get_height())) + self.screen.blit(data,(pos[0],pos[1]+40)) + + pygame.display.update() + + def set_raw(self,b): + self.raw=b + self.draw() + + def in_arc(self,x,y): + """Determines which slice the point is in, with x and y as coordinates in the screen. + Returns the label of the corresponding slice, or None is it doesn't correspond to any slice""" + dx = x-self.base_rect.centerx + dy = self.base_rect.centery-y + hypotenuse = hypot(dx, dy) + if hypotenuse<=self.radius: + angle = atan2(dx,dy) + #normalizing angle to weird pygame unit circles + if angle<0: + angle+=2*pi + angle = 5*pi/2 - angle + + for arc in self.model.get_arcs(): + if arc['start_angle']<=angle<=arc['stop_angle']: + return arc['label'] + + return None + +class PieGraph(object): + """Stores the data for the graph to display (as a dictionary)""" + def __init__(self): + self.data = {} + self.raw_total = 0 + self.arcs = [] + + def add_slice(self, label, value): + """Takes a label as String and a value as a float or int. Adds to + raw_total and data + >>> pg = PieGraph() + >>> pg.add_slice('one', 1) + >>> str(pg) + "[('one', 1.0)]" + >>> pg.add_slice('three', 3) + >>> str(pg) + "[('one', 0.25), ('three', 0.75)]" + """ + if value<=0: + raise ValueError('Data entry requires a positive value') + elif label in self.data.keys(): + raise KeyError('That entry already exists') + self.data[label]=value + self.raw_total+=value + + def modify_slice(self, label, dv): + """Takes a label as String and a value as a float or int. Adds to + existing data entry and raw_total + >>> pg = PieGraph() + >>> pg.add_slice('one', 1) + >>> pg.add_slice('three', 3) + >>> pg.modify_slice('one', 4) + >>> str(pg) + "[('three', 0.375), ('one', 0.625)]" + """ + if self.data[label] + dv<=0: + del self.data[label] + else: + self.data[label]+=dv + self.raw_total+=dv + + def has_slice(self, label): + return label in self.data.keys() + + def calculate_percent(self): + """Calculates what percentage of the graph each label is. Returns a list of tuples + in the format (label, percent), sorted from greatest to least. + No doctest; this function is called by other functions and is tested through + their doctests""" + perc = {} + for k in self.data.keys(): + perc[k]=(float(self.data[k])/self.raw_total) + return sorted(perc.items(),key=lambda x:x[1],) + + def update_arcs(self): + """makes a new list of dictionaries based on the current data in the PieGraph. + Stores a list of dictionaries. + keys: color, label, start_angle, stop_angle""" + self.arcs = [] + curr_angle = pi/2 + for t in self.calculate_percent(): + d = {} + #ensure darker colors + d['color'] = (randrange(40,210),randrange(40,210),randrange(40,210), 255) + d['label'] = t[0] + d['start_angle']=curr_angle + d['stop_angle']=curr_angle+(2*pi*t[1]) + d['val'] = self.data[t[0]] + curr_angle = d['stop_angle'] + self.arcs.append(d) + self.arcs[-1]['stop_angle']=5*pi/2 + + def get_arcs(self): + """Returns a list of dictionaries. + keys: color, label, start_angle, stop_angle,""" + return self.arcs + + def __str__(self): + """Returns the String representation of the graph""" + return str(self.calculate_percent()) + +class input_menu(object): + """Creates the menu for wither modifying a slice or addinga slice""" + def __init__(self, pg, view, modifylabel=None,repeat=1): + """Creates a new TK window. Depending on whether modifylabel has a value or not, it + will make a window for modification or adding""" + self.main_window = t.Tk() + self.main_window.title('Input Data') + x=480 if modifylabel==None else 350 + self.main_window.geometry('+{}+500'.format(x)) + + #attributes + res_func = self.add if modifylabel==None else self.modify + self.num_iter=repeat + self.pg = pg + self.view=view + + #variables gathered from window + self.frame = t.Frame(self.main_window) + if modifylabel==None: + self.name_var = t.StringVar() + else: + self.name_var = modifylabel + self.val_var = t.DoubleVar() + + #actaul containers + if modifylabel==None: + self.tbox = t.Entry(self.frame, width=10, textvariable=self.name_var, text = 'Name: ') + else: + self.tbox = t.Label(self.frame, text='Modifying \''+modifylabel+'\'\nInput amount to add to existing value (negative to subtract)\nIf the value becomes less than 0, the entry will be deleted') + self.val = t.Entry(self.frame, width = 8, textvariable=self.val_var, text = 'Value: ') + self.bt1 = t.Button(self.frame, text = 'Enter', command = res_func) + #self.main_window.bind('', res_func) + + #create window + self.tbox.pack(padx=10) + self.val.pack(padx=10) + self.bt1.pack(padx=10) + self.frame.pack(padx=40) + + t.mainloop() + + def add(self): + ''' Method for adding slices, repeats if there should be multiple in succession + + If the data is invalid or a variable is missing, it will display an error message + Eg: if the user enters nothing for the first data point, if the user enters a string for the value + ''' + try: + self.pg.add_slice(self.name_var.get(), self.val_var.get()) + self.pg.update_arcs() + self.main_window.destroy() + self.view.draw() + if self.num_iter>1: + input_menu(self.pg,self.view,repeat=self.num_iter-1) + except (ValueError, KeyError) as e: + tkMessageBox.showwarning( + "!!Error!!", + "Invalid Data\n"+str(e) + ) + def modify(self): + """Method for modifying a slice, will not repeat""" + try: + self.pg.modify_slice(self.name_var, self.val_var.get()) + self.pg.update_arcs() + self.main_window.destroy() + self.view.draw() + except (ValueError, KeyError) as e: + tkMessageBox.showwarning( + "!!Error!!", + "Invalid Data\n"+str(e) + ) + +class init_menu(object): + """Initial window for choosing how many initial data entries to input""" + def __init__(self, pg, view): + """Creates a new window that allows the user to input a number for the number of entries to put in initially + Calls the input_menu class with the repeat field filled in""" + self.main_window = t.Tk() + self.main_window.title('Input Data') + self.main_window.geometry('+380+500') + + #class attributes + self.pg = pg + self.view=view + + #one data point to get + self.frame = t.Frame(self.main_window) + self.val_var = t.IntVar() + + #creates containers + self.tbox = t.Label(self.frame, text='How many data entries would you like to input?') + self.val = t.Entry(self.frame, width = 8, textvariable=self.val_var, text = 'Value: ') + self.bt1 = t.Button(self.frame, text = 'Enter', command = self.enter_data) + #self.main_window.bind('', res_func) + + #creates frame layout + self.tbox.pack(padx=10) + self.val.pack(padx=10) + self.bt1.pack(padx=10) + self.frame.pack(padx=40) + + t.mainloop() + + def enter_data(self): + """Method that makes the initial call to input_menu""" + try: + self.main_window.destroy() + input_menu(self.pg, self.view,repeat=self.val_var.get()) + + except (ValueError) as e: + tkMessageBox.showwarning( + "!!Error!!", + "INITInvalid Data\n"+str(e) + ) +def deal_with_event(event,pie,screen): + """Handles events such as exiting, saving a screenshot, inputting a new entry, and modifying an existing entry""" + if event.type == QUIT: + return True + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_RETURN: + #input a new entry + input_menu(pie, screen) + elif event.key == pygame.K_s: + #remove the commands + pygame.draw.rect(screen.screen, (0,0,0), (0,0,1000,150)) + #screenshot + pygame.image.save(screen.screen, "screenshot.jpeg") + #redraw commands + screen.draw() + elif event.key == pygame.K_v: + screen.set_raw(not screen.raw) + if event.type == pygame.MOUSEBUTTONDOWN: + #modify a slice (if the user clicks in the right place, otherwise this doesn't do anything) + pos = pygame.mouse.get_pos() + label = screen.in_arc(pos[0],pos[1]) + if label != None: + input_menu(pie,screen,label) + +if __name__ == '__main__': + doctest.testmod() + #creates the main Pie Graph object + pg = PieGraph() + pygame.init() + view = Screen(pg, (1000, 1000)) + running = True + menu = init_menu(pg, view) + #run forever. or quit. if that's what you want. + while running: + for event in pygame.event.get(): + running = not deal_with_event(event,pg,view) + time.sleep(float(1/30)) diff --git a/Interactive_Programming.pdf b/Interactive_Programming.pdf new file mode 100644 index 0000000..4fec565 Binary files /dev/null and b/Interactive_Programming.pdf differ diff --git a/Main.png b/Main.png new file mode 100644 index 0000000..af0c2f1 Binary files /dev/null and b/Main.png differ diff --git a/ProjectProposal.txt b/ProjectProposal.txt new file mode 100644 index 0000000..45e9957 --- /dev/null +++ b/ProjectProposal.txt @@ -0,0 +1,19 @@ +Project Proposal +Carl Moser and Serena Chen + +Our idea is to make an iSpy or Where's Waldo type of game, where the user inputs what to look for and the progam uses OpenCV to find the object. Our (very) minimum viable product is a grid where there are a few pictures on white background, and the user chooses a word and the program marks the image. From there we will add: + +-Searching the word that the user inputs using Google Images, processing those images, and find the box in the main picture that most likely represents that word. + +-Having images of variable size with arbitrary spacing with respect to the other objects in the picture + +-Allowing the user to pick a language, and implementing with different languages (using Google Images of different languages) + +Our learning goals are to learn to use OpenCV. We haven't looked that much into it, so we don't know how black-boxed the algorithms behind our project will be, but we hope that we learn some of the machine learning algorithms. + +We are planning to use OpenCV and other libraries that will allow us to grab pictures from the internet and create a user interface. + +We plan to play around with the libraries and make good progress on our very MVP. + +One of our biggest risks is not being able to use Google Search for images. If we are not successful, we might go to the Where's Waldo idea, where we are only searching for a single image every time. + diff --git a/ProjectProposal.txt~ b/ProjectProposal.txt~ new file mode 100644 index 0000000..45e9957 --- /dev/null +++ b/ProjectProposal.txt~ @@ -0,0 +1,19 @@ +Project Proposal +Carl Moser and Serena Chen + +Our idea is to make an iSpy or Where's Waldo type of game, where the user inputs what to look for and the progam uses OpenCV to find the object. Our (very) minimum viable product is a grid where there are a few pictures on white background, and the user chooses a word and the program marks the image. From there we will add: + +-Searching the word that the user inputs using Google Images, processing those images, and find the box in the main picture that most likely represents that word. + +-Having images of variable size with arbitrary spacing with respect to the other objects in the picture + +-Allowing the user to pick a language, and implementing with different languages (using Google Images of different languages) + +Our learning goals are to learn to use OpenCV. We haven't looked that much into it, so we don't know how black-boxed the algorithms behind our project will be, but we hope that we learn some of the machine learning algorithms. + +We are planning to use OpenCV and other libraries that will allow us to grab pictures from the internet and create a user interface. + +We plan to play around with the libraries and make good progress on our very MVP. + +One of our biggest risks is not being able to use Google Search for images. If we are not successful, we might go to the Where's Waldo idea, where we are only searching for a single image every time. + diff --git a/README.md b/README.md index 61ec120..7abf575 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ # InteractiveProgramming This is the base repo for the interactive programming project for Software Design, Spring 2016 at Olin College. + +## Requirements +Pygame and Tkinter are required to run this code + +To install pygame run the following command in the terminal: + +``` +$ sudo apt-get install python-pygame +``` + +To install Tkinter run the following command in the terminal: +``` +$ sudo apt-get install python-tk +``` + +## Running the program +To run the code: + +``` +$ cd ~/InteractiveProgramming +$ python2 Display.py +``` +From there, the GUI will run through how to use the program \ No newline at end of file diff --git a/UML.eps b/UML.eps new file mode 100644 index 0000000..1d8304a --- /dev/null +++ b/UML.eps @@ -0,0 +1,417 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: graphviz version 2.36.0 (20140111.2315) +%%Title: classes_No_Name +%%Pages: 1 +%%BoundingBox: 36 36 638 280 +%%EndComments +save +%%BeginProlog +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval +EncodingVector 45 /hyphen put + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +%%BeginResource: procset graphviz 0 0 +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def +/tapered { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw text fitted to its expected width +/alignedtext { % width text + /text exch def + /width exch def + gsave + width 0 gt { + [] 0 setdash + text stringwidth pop width exch sub text length div 0 text ashow + } if + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +%%EndResource +%%EndProlog +%%BeginSetup +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +%%EndSetup +setupLatin1 +%%Page: 1 1 +%%PageBoundingBox: 36 36 638 280 +%%PageOrientation: Portrait +0 0 1 beginpage +gsave +36 36 602 244 boxprim clip newpath +1 1 set_scale 0 rotate 40 40 translate +% 0 +gsave +1 setlinewidth +0 0 0 nodecolor +newpath -1 16 moveto +-1 220 lineto +119 220 lineto +119 16 lineto +closepath stroke +0 0 0 nodecolor +14 /Times-Roman set_font +10.5 204.8 moveto 97 (Display.PieGraph) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath -1 197 moveto +119 197 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +7 181.8 moveto 77 (raw_total : int) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 166.8 moveto 55 (data : dict) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 151.8 moveto 50 (arcs : list) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath -1 144 moveto +119 144 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +7 128.8 moveto 74 (update_arcs\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 113.8 moveto 50 (__str__\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 98.8 moveto 59 (has_slice\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 83.8 moveto 61 (add_slice\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 68.8 moveto 81 (modify_slice\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 53.8 moveto 104 (calculate_percent\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 38.8 moveto 55 (get_arcs\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +7 23.8 moveto 55 (__init__\(\)) alignedtext +grestore +% 1 +gsave +1 setlinewidth +0 0 0 nodecolor +newpath 137.5 31 moveto +137.5 205 lineto +236.5 205 lineto +236.5 31 lineto +closepath stroke +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 189.8 moveto 83 (Display.Screen) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath 137.5 182 moveto +236.5 182 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 166.8 moveto 56 (raw : bool) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 151.8 moveto 35 (model) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 136.8 moveto 59 (radius : int) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 121.8 moveto 35 (screen) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 106.8 moveto 52 (base_rect) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath 137.5 99 moveto +236.5 99 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 83.8 moveto 37 (draw\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 68.8 moveto 52 (set_raw\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 53.8 moveto 43 (in_arc\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +145.5 38.8 moveto 55 (__init__\(\)) alignedtext +grestore +% 2 +gsave +1 setlinewidth +0 0 0 nodecolor +newpath 254.5 23.5 moveto +254.5 212.5 lineto +375.5 212.5 lineto +375.5 23.5 lineto +closepath stroke +0 0 0 nodecolor +14 /Times-Roman set_font +264 197.3 moveto 102 (Display.init_menu) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath 254.5 189.5 moveto +375.5 189.5 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 174.3 moveto 67 (tbox : Label) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 159.3 moveto 66 (bt1 : Button) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 144.3 moveto 58 (val : Entry) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 129.3 moveto 79 (frame : Frame) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 114.3 moveto 88 (val_var : IntVar) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 99.3 moveto 14 (pg) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 84.3 moveto 27 (view) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 69.3 moveto 105 (main_window : Tk) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath 254.5 61.5 moveto +375.5 61.5 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 46.3 moveto 66 (enter_data\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +262.5 31.3 moveto 55 (__init__\(\)) alignedtext +grestore +% 3 +gsave +1 setlinewidth +0 0 0 nodecolor +newpath 394 1 moveto +394 235 lineto +594 235 lineto +594 1 lineto +closepath stroke +0 0 0 nodecolor +14 /Times-Roman set_font +438 219.8 moveto 112 (Display.input_menu) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath 394 212 moveto +594 212 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +402 196.8 moveto 104 (tbox : Entry, Label) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 181.8 moveto 66 (bt1 : Button) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 166.8 moveto 58 (val : Entry) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 151.8 moveto 79 (frame : Frame) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 136.8 moveto 112 (val_var : DoubleVar) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 121.8 moveto 184 (name_var : StringVar, NoneType) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 106.8 moveto 105 (main_window : Tk) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 91.8 moveto 27 (view) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 76.8 moveto 76 (num_iter : int) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 61.8 moveto 14 (pg) alignedtext +1 setlinewidth +0 0 0 nodecolor +newpath 394 54 moveto +594 54 lineto +stroke +0 0 0 nodecolor +14 /Times-Roman set_font +402 38.8 moveto 29 (add\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 23.8 moveto 49 (modify\(\)) alignedtext +0 0 0 nodecolor +14 /Times-Roman set_font +402 8.8 moveto 55 (__init__\(\)) alignedtext +grestore +endpage +showpage +grestore +%%PageTrailer +%%EndPage: 1 +%%Trailer +end +restore +%%EOF diff --git a/__pycache__/Display.cpython-35.pyc b/__pycache__/Display.cpython-35.pyc new file mode 100644 index 0000000..10ce3d2 Binary files /dev/null and b/__pycache__/Display.cpython-35.pyc differ diff --git a/add.png b/add.png new file mode 100644 index 0000000..ddbf2ed Binary files /dev/null and b/add.png differ diff --git a/change.png b/change.png new file mode 100644 index 0000000..a20cfdd Binary files /dev/null and b/change.png differ diff --git a/screenshot.jpeg b/screenshot.jpeg new file mode 100644 index 0000000..4d18941 Binary files /dev/null and b/screenshot.jpeg differ diff --git a/wow.jpeg b/wow.jpeg new file mode 100644 index 0000000..53aa9e6 Binary files /dev/null and b/wow.jpeg differ