class XLABaseTest(unittest.TestCase):
    """Provides the model and config of PolI"""

    def setUp(self, mPaths, cPath):
        mPath = xlinkanalyzer.__path__[0]
        xlaTestPath = path.join(path.split(mPath)[0], 'pytests/test_data')
        self.xlaTestMPaths = [path.join(xlaTestPath, _path) for _path in mPaths]
        self.xlaTestCPath = path.join(xlaTestPath, cPath)

        self.config = Assembly()
        self.rManager = ResourceManager(self.config)
        self.rManager.loadAssembly(None, self.xlaTestCPath)

        [chimera.openModels.open(_path) for _path in self.xlaTestMPaths]
        self.models = chimera.openModels.list()
        # self.xla_models = [Model(chimeraModel, self.config) for chimeraModel in self.models]

    def _createTestWindow(self):
        self.testWindow = Toplevel()
        w = self.testWindow.winfo_screenwidth()
        h = self.testWindow.winfo_screenheight()
        x = w/2
        y = h/2
        self.testWindow.geometry("+%d+%d" % (x, y))
        self.testWindow.geometry("400x200")

    def tearDown(self):
        chimera.openModels.close(chimera.openModels.list())
Exemple #2
0
class XLABaseTest(unittest.TestCase):
    """Provides the model and config of PolI"""
    def setUp(self, mPaths, cPath):
        mPath = xlinkanalyzer.__path__[0]
        xlaTestPath = path.join(path.split(mPath)[0], 'pytests/test_data')
        self.xlaTestMPaths = [
            path.join(xlaTestPath, _path) for _path in mPaths
        ]
        self.xlaTestCPath = path.join(xlaTestPath, cPath)

        self.config = Assembly()
        self.rManager = ResourceManager(self.config)
        self.rManager.loadAssembly(None, self.xlaTestCPath)

        [chimera.openModels.open(_path) for _path in self.xlaTestMPaths]
        self.models = chimera.openModels.list()
        # self.xla_models = [Model(chimeraModel, self.config) for chimeraModel in self.models]

    def _createTestWindow(self):
        self.testWindow = Toplevel()
        w = self.testWindow.winfo_screenwidth()
        h = self.testWindow.winfo_screenheight()
        x = w / 2
        y = h / 2
        self.testWindow.geometry("+%d+%d" % (x, y))
        self.testWindow.geometry("400x200")

    def tearDown(self):
        chimera.openModels.close(chimera.openModels.list())
Exemple #3
0
    def createUser(self, username, password, fname, lname):
        if self.gui.btd.database.newUser(username, password, fname, lname):
            popup = Toplevel()
            popup.title("Account created!")

            windowWidth = popup.winfo_screenwidth()
            windowHeight = popup.winfo_screenheight()

            width = .25 * windowWidth
            height = .1 * windowHeight
            x = (windowWidth - width) / 2
            y = (windowHeight - height) / 2

            popup.geometry("%dx%d+%d+%d" % (width, height, x, y))
            popup.update()

            Label(
                popup,
                text="Your new account has been successfully created!").pack()
            Button(popup, text="Dismiss", command=popup.destroy).pack()

            self.gui.screenChange(title.titlePage(self.root, self.gui))
        else:
            popup = Toplevel()
            popup.title("Username Exists!")

            windowWidth = popup.winfo_screenwidth()
            windowHeight = popup.winfo_screenheight()

            width = .25 * windowWidth
            height = .1 * windowHeight
            x = (windowWidth - width) / 2
            y = (windowHeight - height) / 2

            popup.geometry("%dx%d+%d+%d" % (width, height, x, y))
            popup.update()

            Label(popup,
                  text="A user account with that username already exists!"
                  ).pack()
            Button(popup, text="Dismiss", command=popup.destroy).pack()
Exemple #4
0
 def createUser(self, username, password, fname, lname):
     if self.gui.btd.database.newUser(username, password, fname, lname):
         popup = Toplevel()
         popup.title("Account created!")
         
         windowWidth = popup.winfo_screenwidth()
         windowHeight = popup.winfo_screenheight()
         
         width = .25 * windowWidth
         height = .1 * windowHeight
         x = (windowWidth - width) / 2
         y = (windowHeight - height) / 2
         
         popup.geometry("%dx%d+%d+%d" % (width, height, x, y))
         popup.update()
         
         Label(popup, text="Your new account has been successfully created!").pack()
         Button(popup, text="Dismiss", command=popup.destroy).pack()
         
         self.gui.screenChange(title.titlePage(self.root, self.gui))
     else:
         popup = Toplevel()
         popup.title("Username Exists!")
         
         windowWidth = popup.winfo_screenwidth()
         windowHeight = popup.winfo_screenheight()
         
         width = .25 * windowWidth
         height = .1 * windowHeight
         x = (windowWidth - width) / 2
         y = (windowHeight - height) / 2
         
         popup.geometry("%dx%d+%d+%d" % (width, height, x, y))
         popup.update()
         
         Label(popup, text="A user account with that username already exists!").pack()
         Button(popup, text="Dismiss", command=popup.destroy).pack()
Exemple #5
0
 def loginCommand(self, username, password):
     if self.gui.btd.database.login(username, password):
         self.gui.screenChange(welcomePage(self.root, self.gui))
     else:
         popup = Toplevel()
         popup.title("Incorrect")
         
         windowWidth = popup.winfo_screenwidth()
         windowHeight = popup.winfo_screenheight()
         
         width = .25 * windowWidth
         height = .1 * windowHeight
         x = (windowWidth - width) / 2
         y = (windowHeight - height) / 2
         
         popup.geometry("%dx%d+%d+%d" % (width, height, x, y))
         popup.update()
         
         Label(popup, text="Incorrect username or password!").pack()
         Button(popup, text="Dismiss", command=popup.destroy).pack()
Exemple #6
0
class ContinuousTMPViewer(object):
    def __init__(self,
                 suction_height,
                 regions,
                 tl_x=0,
                 tl_y=0,
                 width=500,
                 height=150,
                 title='Grid',
                 background='tan'):
        self.tk = Tk()
        # tk.geometry('%dx%d+%d+%d'%(width, height, 100, 0))
        self.tk.withdraw()
        self.top = Toplevel(self.tk)
        self.top.wm_title(title)
        self.top.protocol('WM_DELETE_WINDOW', self.top.destroy)

        self.suction_height = suction_height
        self.regions = regions
        self.tl_x = tl_x
        self.tl_y = tl_y
        self.width = width
        self.height = height
        self.canvas = Canvas(self.top,
                             width=self.width,
                             height=self.height,
                             background=background)
        self.canvas.pack()
        # self.center()
        self.move_frame(self.tl_x, self.tl_y)

        max_width = max(
            map(get_width,
                regions.values()))  # Really should take width of max minus min
        self.dist_to_pixel = (self.width - 2 * PIXEL_BUFFER
                              ) / max_width  # Maintains aspect ratio
        self.dist_width = self.width / self.dist_to_pixel
        self.dist_height = self.height / self.dist_to_pixel
        self.ground_height = self.height - self.dist_to_pixel * ENV_HEIGHT
        self.robot_dist = self.dist_height / 2.

        self.robot = []
        self.blocks = []
        self.holding = None
        self.environment = []
        self.draw_environment()

    def center(self):
        self.top.update_idletasks()
        w = self.top.winfo_screenwidth()
        h = self.top.winfo_screenheight()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        x = w / 2 - size[0] / 2
        y = h / 2 - size[1] / 2
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def move_frame(self, x, y):
        self.top.update_idletasks()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def scale_x(self, x):  # x \in [-self.dist_width/2, self.dist_width/2]
        return self.dist_to_pixel * (x + self.dist_width / 2.)

    def scale_y(self, y):  # y \in [0, self.dist_height]
        return self.ground_height - self.dist_to_pixel * y

    def draw_block(self, x, y, width, height, name='', color='blue'):
        self.blocks.extend([
            self.canvas.create_rectangle(self.scale_x(x - width / 2.),
                                         self.scale_y(y),
                                         self.scale_x(x + width / 2.),
                                         self.scale_y(y + height),
                                         fill=color,
                                         outline='black',
                                         width=2),
            self.canvas.create_text(self.scale_x(x),
                                    self.scale_y(y + height / 2),
                                    text=name),
        ])

    # def draw_holding(self, x, width, height, color='blue'):
    #     self.holding = self.canvas.create_rectangle(self.scale_x(x - width / 2.),
    #                                                 self.scale_y(self.robot_dist - SUCTION_HEIGHT / 2 - height),
    #                                                 self.scale_x(x + width / 2.),
    #                                                 self.scale_y(self.robot_dist - SUCTION_HEIGHT / 2),
    #                                                 fill=color, outline='black', width=2)

    def draw_region(self, region, name='', color='red'):
        x1, x2 = map(self.scale_x, region)
        y1, y2 = self.ground_height, self.height
        self.environment.extend([
            self.canvas.create_rectangle(x1,
                                         y1,
                                         x2,
                                         y2,
                                         fill=color,
                                         outline='black',
                                         width=2),
            self.canvas.create_text((x1 + x2) / 2, (y1 + y2) / 2, text=name),
        ])

    def draw_environment(self):
        # TODO: automatically draw in order
        self.environment = []
        for name, region in sorted(self.regions.items(),
                                   key=lambda pair: get_width(pair[1]),
                                   reverse=True):
            self.draw_region(region, name=name, color=name)

    def draw_robot(
        self,
        x,
        y,
        color='yellow'
    ):  # TODO - could also visualize as top grasps instead of side grasps
        #y = self.robot_dist
        self.robot = [
            self.canvas.create_rectangle(
                self.scale_x(x - SUCTION_WIDTH / 2.),
                self.scale_y(y - self.suction_height / 2.),
                self.scale_x(x + SUCTION_WIDTH / 2.),
                self.scale_y(y + self.suction_height / 2.),
                fill=color,
                outline='black',
                width=2),
            self.canvas.create_rectangle(
                self.scale_x(x - STEM_WIDTH / 2.),
                self.scale_y(y + self.suction_height / 2.),
                self.scale_x(x + STEM_WIDTH / 2.),
                self.scale_y(y + self.suction_height / 2. + STEM_HEIGHT),
                fill=color,
                outline='black',
                width=2),
        ]

    def clear_state(self):
        for block in self.blocks:
            self.canvas.delete(block)
        for part in self.robot:
            self.canvas.delete(part)
        if self.holding is not None:
            self.canvas.delete(self.holding)

    def clear_all(self):
        self.canvas.delete('all')

    def save(self, filename):
        # TODO: screen recording based on location like I did before
        # TODO: only works on windows
        # self.canvas.postscript(file='%s.ps'%filename, colormode='color')
        #from PIL import ImageGrab
        try:
            import pyscreenshot as ImageGrab
        except ImportError:
            return None
        x, y = self.top.winfo_x(), 2 * self.top.winfo_y()
        width, height = self.top.winfo_width(), self.top.winfo_height(
        )  # winfo_width, winfo_reqheight
        path = filename + '.png'
        ImageGrab.grab((x, y, x + width, y + height)).save(path)
        return path
Exemple #7
0
class ContinuousTMPViewer(object):
    def __init__(self,
                 regions,
                 tl_x=0,
                 tl_y=0,
                 width=500,
                 height=250,
                 title='Grid',
                 background='tan'):
        self.tk = Tk()
        # tk.geometry('%dx%d+%d+%d'%(width, height, 100, 0))
        self.tk.withdraw()
        self.top = Toplevel(self.tk)
        self.top.wm_title(title)
        self.top.protocol('WM_DELETE_WINDOW', self.top.destroy)

        self.regions = regions
        self.tl_x = tl_x
        self.tl_y = tl_y
        self.width = width
        self.height = height
        self.canvas = Canvas(self.top,
                             width=self.width,
                             height=self.height,
                             background=background)
        self.canvas.pack()
        # self.center()
        self.move_frame(self.tl_x, self.tl_y)

        self.dist_to_pixel = (self.width - 2 * PIXEL_BUFFER) / get_width(
            regions[GROUND])  # Maintains aspect ratio
        self.dist_width = self.width / self.dist_to_pixel
        self.dist_height = self.height / self.dist_to_pixel
        self.ground_height = self.height - self.dist_to_pixel * ENV_HEIGHT
        self.robot_dist = self.dist_height / 2.

        self.robot = []
        self.blocks = []
        self.holding = None
        self.environment = []
        self.draw_environment()

    def center(self):
        self.top.update_idletasks()
        w = self.top.winfo_screenwidth()
        h = self.top.winfo_screenheight()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        x = w / 2 - size[0] / 2
        y = h / 2 - size[1] / 2
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def move_frame(self, x, y):
        self.top.update_idletasks()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def scale_x(self, x):  # x \in [-self.dist_width/2, self.dist_width/2]
        return self.dist_to_pixel * (x + self.dist_width / 2.)

    def scale_y(self, y):  # y \in [0, self.dist_height]
        return self.ground_height - self.dist_to_pixel * y

    def draw_block(self, x, width, height, color='blue'):
        self.blocks.append(
            self.canvas.create_rectangle(self.scale_x(x - width / 2.),
                                         self.scale_y(0),
                                         self.scale_x(x + width / 2.),
                                         self.scale_y(height),
                                         fill=color,
                                         outline='black',
                                         width=2))

    # def draw_holding(self, x, width, height, color='blue'):
    #     self.holding = self.canvas.create_rectangle(self.scale_x(x - width / 2.),
    #                                                 self.scale_y(self.robot_dist - SUCTION_HEIGHT / 2 - height),
    #                                                 self.scale_x(x + width / 2.),
    #                                                 self.scale_y(self.robot_dist - SUCTION_HEIGHT / 2),
    #                                                 fill=color, outline='black', width=2)

    def draw_region(self, region, color='red'):
        x1, x2 = map(self.scale_x, region)
        self.environment.append(
            self.canvas.create_rectangle(x1,
                                         self.ground_height,
                                         x2,
                                         self.height,
                                         fill=color,
                                         outline='black',
                                         width=2))

    def draw_environment(self, table_color='lightgrey'):
        self.environment = []
        self.draw_region(self.regions[GROUND], color=table_color)
        for name, region in self.regions.items():
            if name != GROUND:
                self.draw_region(region)

    def draw_robot(
        self,
        x,
        y,
        color='yellow'
    ):  # TODO - could also visualize as top grasps instead of side grasps
        #y = self.robot_dist
        self.robot = [
            self.canvas.create_rectangle(self.scale_x(x - SUCTION_WIDTH / 2.),
                                         self.scale_y(y - SUCTION_HEIGHT / 2.),
                                         self.scale_x(x + SUCTION_WIDTH / 2.),
                                         self.scale_y(y + SUCTION_HEIGHT / 2.),
                                         fill=color,
                                         outline='black',
                                         width=2),
            self.canvas.create_rectangle(self.scale_x(x - STEM_WIDTH / 2.),
                                         self.scale_y(y + SUCTION_HEIGHT / 2.),
                                         self.scale_x(x + STEM_WIDTH / 2.),
                                         self.scale_y(y + SUCTION_HEIGHT / 2. +
                                                      STEM_HEIGHT),
                                         fill=color,
                                         outline='black',
                                         width=2),
        ]

    def clear_state(self):
        for block in self.blocks:
            self.canvas.delete(block)
        for part in self.robot:
            self.canvas.delete(part)
        if self.holding is not None:
            self.canvas.delete(self.holding)

    def clear_all(self):
        self.canvas.delete('all')

    def save(self, filename):
        # self.canvas.postscript(file='%s.ps'%filename, colormode='color')
        from PIL import ImageGrab
        ImageGrab.grab((0, 0, self.width, self.height)).save(filename + '.jpg')
Exemple #8
0
class ContinuousTMPViewer(object):
    def __init__(self,
                 env_region,
                 regions=[],
                 tl_x=0,
                 tl_y=0,
                 width=500,
                 height=250,
                 title='Grid',
                 background='tan'):
        self.tk = Tk()

        self.tk.withdraw()
        self.top = Toplevel(self.tk)
        self.top.wm_title(title)
        self.top.protocol('WM_DELETE_WINDOW', self.top.destroy)

        self.env_region = env_region
        self.regions = regions
        self.tl_x = tl_x
        self.tl_y = tl_y
        self.width = width
        self.height = height
        self.canvas = Canvas(self.top,
                             width=self.width,
                             height=self.height,
                             background=background)
        self.canvas.pack()

        self.move_frame(self.tl_x, self.tl_y)

        self.dist_to_pixel = (self.width -
                              2 * PIXEL_BUFFER) / (self.env_region.w)
        self.dist_width = self.width / self.dist_to_pixel
        self.dist_height = self.height / self.dist_to_pixel
        self.ground_height = self.height - self.dist_to_pixel * ENV_HEIGHT
        self.robot_dist = self.dist_height / 2.

        self.robot = []
        self.blocks = []
        self.holding = None
        self.draw_environment()

    def center(self):
        self.top.update_idletasks()
        w = self.top.winfo_screenwidth()
        h = self.top.winfo_screenheight()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        x = w / 2 - size[0] / 2
        y = h / 2 - size[1] / 2
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def move_frame(self, x, y):
        self.top.update_idletasks()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def t_x(self, x):
        return self.dist_to_pixel * (x + self.dist_width / 2.)

    def t_y(self, y):
        return self.ground_height - self.dist_to_pixel * y

    def draw_block(self, block, x):
        self.blocks.append(
            self.canvas.create_rectangle(self.t_x(x - block.w / 2.),
                                         self.t_y(0),
                                         self.t_x(x + block.w / 2.),
                                         self.t_y(block.h),
                                         fill=block.color,
                                         outline='black',
                                         width=2))

    def draw_holding(self, block, x):
        self.holding = self.canvas.create_rectangle(
            self.t_x(x - block.w / 2.),
            self.t_y(self.robot_dist - SUCTION_HEIGHT / 2 - block.h),
            self.t_x(x + block.w / 2.),
            self.t_y(self.robot_dist - SUCTION_HEIGHT / 2),
            fill=block.color,
            outline='black',
            width=2)

    def draw_region(self, region):
        self.environment.append(
            self.canvas.create_rectangle(self.t_x(region.x - region.w / 2.),
                                         self.ground_height,
                                         self.t_x(region.x + region.w / 2.),
                                         self.height,
                                         fill='red',
                                         outline='black',
                                         width=2))

    def draw_environment(self, table_color='lightgrey', bin_color='grey'):
        self.environment = [
            self.canvas.create_rectangle(self.t_x(-self.env_region.w / 2),
                                         self.ground_height,
                                         self.t_x(self.env_region.w / 2),
                                         self.height,
                                         fill=table_color,
                                         outline='black',
                                         width=2)
        ]
        for region in self.regions:
            self.draw_region(region)

    def draw_robot(self, x, color='yellow'):
        self.robot = [
            self.canvas.create_rectangle(
                self.t_x(x - SUCTION_WIDTH / 2.),
                self.t_y(self.robot_dist - SUCTION_HEIGHT / 2.),
                self.t_x(x + SUCTION_WIDTH / 2.),
                self.t_y(self.robot_dist + SUCTION_HEIGHT / 2.),
                fill=color,
                outline='black',
                width=2),
            self.canvas.create_rectangle(
                self.t_x(x - STEM_WIDTH / 2.),
                self.t_y(self.robot_dist + SUCTION_HEIGHT / 2.),
                self.t_x(x + STEM_WIDTH / 2.),
                self.t_y(self.robot_dist + SUCTION_HEIGHT / 2. + STEM_HEIGHT),
                fill=color,
                outline='black',
                width=2),
        ]

    def clear_state(self):
        for block in self.blocks:
            self.canvas.delete(block)
        for part in self.robot:
            self.canvas.delete(part)
        if self.holding is not None:
            self.canvas.delete(self.holding)

    def clear_all(self):
        self.canvas.delete('all')

    def save(self, filename):

        from PIL import ImageGrab
        ImageGrab.grab((0, 0, self.width, self.height)).save(filename + '.jpg')
Exemple #9
0
class GUIHandler:

    screenwidth = 0
    screenheight = 0
    windowwidth = 0
    windowheight = 0

    ## Initializes the GUI setup of the program.
    #
    def __init__(self,game):

        assert type(game) is Game
        self.root = Tk()
        self.root.title('SET')
        self.root.resizable(0,0)
        self.root.withdraw()
        GUIHandler.screenwidth = self.root.winfo_screenwidth()
        GUIHandler.screenheight = self.root.winfo_screenheight()
        if GUIHandler.screenwidth < 1024 or GUIHandler.screenheight < 768:
            showerror("Resolution Error","Your screen's resolution is likely not the best choice to run this game. Minimum resolution for this game is at least 1024x768.")
            raise ResolutionError(GUIHandler.screenwidth,GUIHandler.screenheight)
        GUIHandler.windowwidth = GUIHandler.screenwidth // 3
        GUIHandler.windowheight = GUIHandler.screenheight // 1.5
        self.buttonField = None
        self.checkButtonField = None
        self.Game = game
        self.Field = game.field
        assert self.Game
        assert self.Field

        self.root.geometry('%dx%d+%d+%d' % (GUIHandler.windowwidth,
                                          GUIHandler.windowheight,
                                          self.root.winfo_screenwidth()/8,
                                          self.root.winfo_screenheight()/8))

        menu = Menu(self.root)

        gamemenu = Menu(menu,tearoff=0)
        gamemenu.add_command(label='New Game',command=lambda:self.startNewGame(),accelerator="F2")
        gamemenu.add_command(label='Leaderboards',command=lambda:showinfo("Not implemented","Feature not implemented...yet."))
        gamemenu.add_command(label='Exit',command=lambda:self.root.destroy(),accelerator="Alt-F4")

        menu.add_cascade(label='Game',menu=gamemenu)

        settingmenu = Menu(menu,tearoff=0)

        gamedifficulty = Menu(settingmenu,tearoff=0)
        gamedifficulty.add_radiobutton(label='Beginner',command=lambda :self.changeGameDifficulty(Difficulty.BEGINNER),accelerator="B")
        gamedifficulty.add_radiobutton(label='Novice',command=lambda :self.changeGameDifficulty(Difficulty.NOVICE),accelerator="N")
        gamedifficulty.add_radiobutton(label='Advanced',command=lambda :self.changeGameDifficulty(Difficulty.ADVANCED),accelerator="A")

        settingmenu.add_cascade(label='Game Difficulty',menu=gamedifficulty)

        timedmode = Menu(settingmenu,tearoff=0)
        timedmode.add_radiobutton(label='On',command=lambda:showinfo("Not implemented","Feature not implemented...yet."))
        timedmode.add_radiobutton(label='Off',command=lambda:showinfo("Not implemented","Feature not implemented...yet."))
        
        settingmenu.add_cascade(label='Timed Mode',menu=timedmode)

        timeddifficulty = Menu(settingmenu,tearoff=0)
        timeddifficulty.add_radiobutton(label='Easy',accelerator="E")
        timeddifficulty.add_radiobutton(label='Medium',accelerator="M")
        timeddifficulty.add_radiobutton(label='Hard',accelerator="H")

        settingmenu.add_cascade(label='Timed Difficulty',menu=timeddifficulty)
        menu.add_cascade(label='Settings',menu=settingmenu)

        helpmenu = Menu(menu,tearoff=0)
        helpmenu.add_command(label='About SET',command=lambda:showinfo("Not implemented","Feature not implemented...yet."))

        menu.add_cascade(label='Help',menu=helpmenu)

        self.root.config(menu=menu)

        self.root.bind('<F2>',lambda e:gamemenu.invoke(0))
        self.root.bind('L',lambda e:gamemenu.invoke(1))
        self.root.bind('<Alt-F4>',lambda e:gamemenu.invoke(2))
        self.root.bind('b',lambda e:gamedifficulty.invoke(Difficulty.BEGINNER))
        self.root.bind('n',lambda e:gamedifficulty.invoke(Difficulty.NOVICE))
        self.root.bind('a',lambda e:gamedifficulty.invoke(Difficulty.ADVANCED))

        self.remainderLabel = Label(self.root,text="There are %d set(s) remaining on the board." % self.Game.numSetsRemaining(),bg="white",relief=Tkinter.RAISED,font=('Helvetica',12))
        self.remainderLabel.place(x=(GUIHandler.windowwidth-self.remainderLabel.winfo_reqwidth())//2,y=3*GUIHandler.windowheight//4)

        timer = Label(self.root,text="Untimed Mode",bg="green",relief=Tkinter.RAISED,font=('Helvetica',12))
        timer.place(x=(GUIHandler.windowwidth-timer.winfo_reqwidth())//2,y=3*GUIHandler.windowheight//4.5)

        hintbutton = Button(text="Hint, please!",font=("Helvetica",12),command=lambda :self.getHint())
        hintbutton.place(x=(GUIHandler.windowwidth-hintbutton.winfo_reqwidth())//2,y=3*GUIHandler.windowheight//3.5)

        self.userSetsCreated = Toplevel(self.root)
        self.userSetsHeight = 0
        self.userSetsCreated.title("Sets Created")
        self.userSetsCreated.geometry("%dx%d+%d+%d" % (Card.pixelWidth*3,
                                               self.userSetsCreated.winfo_screenheight(),
                                               self.root.winfo_pointerx()+self.userSetsCreated.winfo_reqwidth(),0))
        self.userSetsCreated.protocol("WM_DELETE_WINDOW",0)
        self.userSetsCreated.resizable(0,0)
        self.root.focus_set()

        self.updateCardsOnField(self.Field)

    ## Process the card location that the user picked. The function calls the game instance's addCardChoice method
    # to get a callback on the result of adding the card choice.
    def processCardChoice(self,i):

        cbutton = self.checkButtonField[i//self.Field.cols()][i%self.Field.cols()]
        cbutton.select()
        result = self.Game.addCardChoice(i)

        if result == 3:
            cbutton.deselect()
            return
        elif not result:
            return

        if result == 2: #Case 1: 3 choices were made and the Game object verified them as a set.
            showinfo("Good Job!","You made a set!")
            self.remainderLabel.config(text="There are %d set(s) remaining on the board." % self.Game.numSetsRemaining())
            x = 0
            for h in map(Card.getCardImgNumber,[self.Field[i//self.Field.cols()][i%self.Field.cols()] for i in self.Game.setsMadeSoFar[-1]]):
                pic = PhotoImage(file='../media/%d.gif'%h)
                label = Label(self.userSetsCreated,image=pic)
                label.image = pic
                label.place(x=x,y=self.userSetsHeight)
                x+=Card.pixelWidth
            self.userSetsHeight+=Card.pixelHeight
            if not self.Game.numSetsRemaining():
                showinfo("WINNER!","Congratulations! You found all sets!")
                self.disableButtons()
        elif result == 1: #Case 2: 3 choices were made but the user has made this set before in the game.
            showinfo("Repeat","You've already made this set")
        elif type(result) == tuple: #Case #3: 3 choices were made but they didn't form a set.
            assert len(result) == 2
            showinfo("Not a set","Not a set because 2 are %s and 1 is %s" % (result[0],result[1]))
        for i in self.checkButtonField:
            for j in i:
                j.deselect()

    def disableButtons(self):
        for i in self.buttonField:
            for j in i:
                j.config(state=Tkinter.DISABLED)
        for i in self.checkButtonField:
            for j in i:
                j.config(state=Tkinter.DISABLED)

    #Hard Coded lists of button widgets because python won't let me generate each of the Button's command
    #feature correctly via list comprehension.

    def setupNoviceField(self):

        self._destroyAllButtons() if self.buttonField else None

        self.buttonField = [[Button(self.root,command=lambda :self.processCardChoice(0)),
                             Button(self.root,command=lambda :self.processCardChoice(1)),
                             Button(self.root,command=lambda :self.processCardChoice(2))],
                            [Button(self.root,command=lambda :self.processCardChoice(3)),
                             Button(self.root,command=lambda :self.processCardChoice(4)),
                             Button(self.root,command=lambda :self.processCardChoice(5))],
                            [Button(self.root,command=lambda :self.processCardChoice(6)),
                             Button(self.root,command=lambda :self.processCardChoice(7)),
                             Button(self.root,command=lambda :self.processCardChoice(8))]]

        self.checkButtonField = [[Checkbutton(self.root,text='1',command=lambda :self.processCardChoice(0)),
                                  Checkbutton(self.root,text='2',command=lambda :self.processCardChoice(1)),
                                  Checkbutton(self.root,text='3',command=lambda :self.processCardChoice(2))],
                                 [Checkbutton(self.root,text='4',command=lambda :self.processCardChoice(3)),
                                  Checkbutton(self.root,text='5',command=lambda :self.processCardChoice(4)),
                                  Checkbutton(self.root,text='6',command=lambda :self.processCardChoice(5))],
                                 [Checkbutton(self.root,text='7',command=lambda :self.processCardChoice(6)),
                                  Checkbutton(self.root,text='8',command=lambda :self.processCardChoice(7)),
                                  Checkbutton(self.root,text='9',command=lambda :self.processCardChoice(8))]]

    #See the comment above setup Novice _Field.

    def setupAdvancedField(self):

        self._destroyAllButtons() if self.buttonField else None

        self.buttonField = [[Button(self.root,command=lambda :self.processCardChoice(0)),
                             Button(self.root,command=lambda :self.processCardChoice(1)),
                             Button(self.root,command=lambda :self.processCardChoice(2)),
                             Button(self.root,command=lambda :self.processCardChoice(3))],
                            [Button(self.root,command=lambda :self.processCardChoice(4)),
                             Button(self.root,command=lambda :self.processCardChoice(5)),
                             Button(self.root,command=lambda :self.processCardChoice(6)),
                             Button(self.root,command=lambda :self.processCardChoice(7))],
                            [Button(self.root,command=lambda :self.processCardChoice(8)),
                             Button(self.root,command=lambda :self.processCardChoice(9)),
                             Button(self.root,command=lambda :self.processCardChoice(10)),
                             Button(self.root,command=lambda :self.processCardChoice(11))]]

        self.checkButtonField = [[Checkbutton(self.root,text='1',command=lambda :self.processCardChoice(0)),
                                  Checkbutton(self.root,text='2',command=lambda :self.processCardChoice(1)),
                                  Checkbutton(self.root,text='3',command=lambda :self.processCardChoice(2)),
                                  Checkbutton(self.root,text='4',command=lambda :self.processCardChoice(3))],
                                 [Checkbutton(self.root,text='5',command=lambda :self.processCardChoice(4)),
                                  Checkbutton(self.root,text='6',command=lambda :self.processCardChoice(5)),
                                  Checkbutton(self.root,text='7',command=lambda :self.processCardChoice(6)),
                                  Checkbutton(self.root,text='8',command=lambda :self.processCardChoice(7))],
                                 [Checkbutton(self.root,text='9',command=lambda :self.processCardChoice(8)),
                                  Checkbutton(self.root,text='10',command=lambda :self.processCardChoice(9)),
                                  Checkbutton(self.root,text='11',command=lambda :self.processCardChoice(10)),
                                  Checkbutton(self.root,text='12',command=lambda :self.processCardChoice(11))]]

    def updateCardsOnField(self,cardField):

        rows = cardField.rows()
        cols = cardField.cols()

        if cols == 3:
            self.setupNoviceField()
        elif cols == 4:
            self.setupAdvancedField()
        else:
            raise IndexError("CardField argument has illegal number of columns")

        assert len(self.buttonField) == rows
        assert len(self.buttonField[0]) == cols

        spacing = (GUIHandler.windowwidth-(cols * Card.pixelWidth) - 5) / (cols-1)
        x,y = 0,0
        cbwidth = self.checkButtonField[0][0].winfo_reqwidth()
        for i in xrange(rows):
            for j in xrange(cols):
                pic = PhotoImage(file='../media/%s.gif' % str(cardField[i][j].getCardImgNumber()))
                self.buttonField[i][j].config(image=pic)
                self.buttonField[i][j].image = pic
                self.buttonField[i][j].place(x=x,y=y)
                self.checkButtonField[i][j].place(x=x + Card.pixelWidth//2 - cbwidth//4,y=(y+Card.pixelHeight+10))
                x += Card.pixelWidth + spacing
            y += Card.pixelHeight + 40
            x = 0

    def startNewGame(self):

        self.userSetsHeight = 0
        [i.destroy() for i in self.userSetsCreated.children.values()]
        self.Game.resetGame()
        self.updateCardsOnField(self.Game.field)
        self.remainderLabel.config(text="There are %d set(s) remaining on the board." % self.Game.numSetsTotal)
        #print map(lambda ls:map(lambda x:x+1,ls),self.Game.setsListTotal)

    def _destroyAllButtons(self):

        for i in self.buttonField:
            for j in i:
                j.destroy()
        for i in self.checkButtonField:
            for j in i:
                j.destroy()

    def changeGameDifficulty(self,difficulty):

        if self.Game.changeGameDifficulty(difficulty):
            self.startNewGame()

    def getHint(self):
        result = self.Game.callHint()
        if result == -3:
            showinfo("One set remains","You cannot use hints in finding the last set.")
        elif result == -2:
            showinfo("Game's over","Game has ended. Start a new game if you wish.")
        elif result == -1:
            showinfo("No more hints","Sorry. You are out of hints to spare.")
        else:
            showinfo("Your Hint","Pick Card #%d"%(result+1))

    def run(self):
        self.root.deiconify()
        self.root.mainloop()