示例#1
0
文件: frame.py 项目: Pycz/SeaWarCrazy
class MyFrame(wx.Frame):

        def __init__(self):
            wx.Frame.__init__(self, None, -1, size=(790, 620), title = "SeaWar Judge", pos = (300, 60))
            self.panel = wx.Panel(self, -1)
            self.judge = None
            self.field_top = 30
            self.field_left = 30
            self.field_down = self.field_top + 400
            self.field1 = Field( Map(), self.panel, (self.field_left, self.field_top), 30)
            self.field2 = Field( Map(), self.panel, (400, self.field_top), 30)


            self.b_add_bot1 = wx.Button(self.panel, -1, "Choose bot 1", pos = (self.field_left + 30,
                                                                               self.field_down),
                                        size = (300, 40))

            self.Bind(wx.EVT_BUTTON, self.on_add_bot1, self.b_add_bot1)

            self.b_add_bot2 = wx.Button(self.panel, -1, "Choose bot 2", pos = (430,
                                                                               self.field_down),
                                        size = (300, 40))

            self.Bind(wx.EVT_BUTTON, self.on_add_bot2, self.b_add_bot2)


            wildcard = "Python files (*.py)|*.py|All files (*.*)|*.*"
            self.dialog = wx.FileDialog(None, "Choose a bot executable", os.getcwd(),
                                   "", wildcard, wx.OPEN)

            self.bot1_path = None
            self.bot2_path = None

            self.bot1_name = None
            self.bot2_name = None

            self.l_bot1_name = wx.StaticText(self.panel, -1, "?BOT1?", pos = (self.field_left + self.field1.size,
                                                                               self.field_top - 20))

            self.l_bot2_name = wx.StaticText(self.panel, -1, "?BOT2?", pos = (400 + self.field2.size,
                                                                               self.field_top - 20))

            self.big_font = wx.Font(18, wx.DEFAULT, wx.DEFAULT, wx.DEFAULT)
            self.small_font = wx.Font(8, wx.DEFAULT, wx.DEFAULT, wx.DEFAULT)
            self.bold_font = wx.Font(40, wx.DEFAULT, wx.DEFAULT, wx.BOLD)
            self.l_bot1_name.SetForegroundColour("Green")
            self.l_bot2_name.SetForegroundColour("Red")
            self.l_bot1_name.SetFont(self.big_font)
            self.l_bot2_name.SetFont(self.big_font)


            self.l_bot1_wins = wx.StaticText(self.panel, -1, "0", pos = (self.field_left + 70,
                                                                               self.field_down - 70))

            self.l_wins = wx.StaticText(self.panel, -1, ":", pos = (390, self.field_down - 70))
            self.l_wins.SetFont(self.bold_font)
            self.l_wins.SetForegroundColour("Blue")

            self.l_bot2_wins = wx.StaticText(self.panel, -1, "0", pos = (470, self.field_down - 70))
            self.l_bot1_wins.SetFont(self.bold_font)
            self.l_bot2_wins.SetFont(self.bold_font)
            self.l_bot1_wins.SetForegroundColour("Green")
            self.l_bot2_wins.SetForegroundColour("Red")

            self.winlist = [0, 0, 0]
            self.maplist = [Map(), Map(), 0]

            self.b_start_chemp = wx.Button(self.panel, -1, "START!", pos = (self.field_left + 240,
                                                                               self.field_down + 60),
                                                                        size = (250, 100))

            self.b_start_chemp.SetFont(self.bold_font)

            self.Bind(wx.EVT_BUTTON, self.on_start_chemp, self.b_start_chemp)



            self.c_rounds = wx.SpinCtrl(self.panel,
                                        -1,
                                        value = '',
                                        pos = (self.field_left + 630, self.field_down + 55),
                                        size = (70, 30),
                                        style = wx.SP_ARROW_KEYS,
                                        min = 1,
                                        max = 10000,
                                        initial = 1)

            self.l_rounds = wx.StaticText(self.panel, -1, "How many rounds:",
                                          pos = (self.field_left + 500, self.field_down + 65))

            self.c_round_pause = wx.TextCtrl(self.panel, -1, value = "0",
                                             pos = (self.field_left + 630, self.field_down + 95),
                                             size = (70, 30),
                                             validator = Is_Float_and_time())

            self.l_round_pause = wx.StaticText(self.panel, -1, "Pause between rounds:",
                                          pos = (self.field_left + 500, self.field_down + 105))

            self.l_round_pause.SetFont(self.small_font)

            self.l_turn_pause = wx.StaticText(self.panel, -1, "Pause between turns:",
                                          pos = (self.field_left + 500, self.field_down + 145))

            self.l_turn_pause.SetFont(self.small_font)

            self.c_turn_pause = wx.TextCtrl(self.panel, -1, value = "0",
                                             pos = (self.field_left + 630, self.field_down + 135),
                                             size = (70, 30),
                                             validator = Is_Float_and_time())

            self.b_pause_play = wx.Button(self.panel, -1, "Pause", pos = (self.field_left + 30,
                                                                               self.field_down + 120),
                                                                        size = (65, 40))

            self.Bind(wx.EVT_BUTTON, self.on_pause_play, self.b_pause_play)

            self.b_stop = wx.Button(self.panel, -1, "STOP", pos = (self.field_left + 95,
                                                                               self.field_down + 120),
                                                                        size = (65, 40))

            self.Bind(wx.EVT_BUTTON, self.on_stop, self.b_stop)

            self.b_flush = wx.Button(self.panel, -1, "Default", pos = (self.field_left + 165,
                                                                               self.field_down + 120),
                                                                        size = (65, 40))

            self.Bind(wx.EVT_BUTTON, self.on_default, self.b_flush)

            self.g_progress = wx.Gauge(self.panel, -1, 100,
                                        pos = (self.field_left + 30, self.field_down + 70),
                                        size = (200, 40),
                                        style = wx.GA_HORIZONTAL)

            self.status_bar = self.CreateStatusBar()
            self.status_bar.SetStatusText('Hello there! Choose bots and click "START!"')

            self.lock = threading.Lock()
            self.running = True


            self.Bind(wx.EVT_CLOSE, self.on_close, self)

            self.enable_disable_set = [self.b_add_bot1,
                                       self.b_add_bot2,
                                       self.b_start_chemp,
                                       self.b_flush,
                                       self.c_round_pause,
                                       self.c_rounds,
                                       self.c_turn_pause]

            self.play_thread_alive = [True, ]
            self.str_for_statusbar = 'Hello! Choose bots and press "START!"'

            self.make_elements_active(False, *[self.b_pause_play, self.b_stop])

            self.judge = None

            self.supe = superthreading
            self.supe.frame = self

            self.is_computing = False

            self.graphic_tread = threading.Thread(target = self.refresh)
            self.graphic_tread.daemon = True
            self.graphic_tread.start()


        def make_elements_active(self, active = False, *els):
            for el in els:
                wx.CallAfter(el.Enable, active)

        def on_stop(self, event):
            self.play_thread_alive[0] = False
            self.str_for_statusbar = "Stopping..."


        def on_default(self, event):
            self.flush_all_to_default()
            self.str_for_statusbar = "All settings flushed to default"

        def on_pause_play(self, event):
            if self.b_pause_play.GetLabel() == "Play":
                self.lock.release()
                wx.CallAfter(self.b_pause_play.SetLabel, "Pause")
                self.str_for_statusbar = "Computing... "

            else:
                wx.CallAfter(self.b_pause_play.SetLabel, "Play")
                self.lock.acquire()
                self.str_for_statusbar = "Computing paused... "


        def on_close(self, event):
            self.play_thread_alive[0] = False
            self.running = False
            wx.Exit()

        def flush_for_start(self):
            self.make_elements_active(True, *self.enable_disable_set)
            wx.CallAfter(self.b_pause_play.SetLabel, "Pause")


            self.lock.acquire()
            self.winlist[0] = 0
            self.winlist[1] = 0
            self.winlist[2] = 0
            self.maplist[0] = Map()
            self.maplist[1] = Map()
            self.maplist[2] = 0
            self.lock.release()

            wx.CallAfter(self.l_bot1_wins.SetLabel, "0")
            wx.CallAfter(self.l_bot2_wins.SetLabel, "0")


            wx.CallAfter(self.g_progress.SetRange, 100)
            wx.CallAfter(self.g_progress.SetValue, 0)


        def flush_all_to_default(self):
            self.make_elements_active(True, *self.enable_disable_set)
            wx.CallAfter(self.b_pause_play.SetLabel, "Pause")
            self.judge = None
            self.bot1_path = None
            self.bot2_path = None
            self.bot1_name = None
            self.bot2_name = None

            self.lock.acquire()
            self.winlist[0] = 0
            self.winlist[1] = 0
            self.winlist[2] = 0
            self.maplist[0] = Map()
            self.maplist[1] = Map()
            self.maplist[2] = 0
            self.lock.release()

            wx.CallAfter(self.l_bot1_name.SetLabel, "?BOT1?")
            wx.CallAfter(self.l_bot2_name.SetLabel, "?BOT2?")
            wx.CallAfter(self.l_bot1_wins.SetLabel, "0")
            wx.CallAfter(self.l_bot2_wins.SetLabel, "0")

            wx.CallAfter(self.b_add_bot1.SetLabel, "Choose bot 1")
            wx.CallAfter(self.b_add_bot2.SetLabel, "Choose bot 2")

            wx.CallAfter(self.c_round_pause.SetValue, "0")
            wx.CallAfter(self.c_rounds.SetValue, 1)
            wx.CallAfter(self.c_turn_pause.SetValue, "0")

            wx.CallAfter(self.g_progress.SetRange, 100)
            wx.CallAfter(self.g_progress.SetValue, 0)


            #self.lock.release()


        def get_round_pause(self):
            x = self.c_round_pause.GetValue()
            try:
                x = float(x)
                if 0 <= x <= 3:
                    return x
                else:
                    wx.CallAfter(self.c_round_pause.SetValue, str(min(x, 3) if x > 3 else max(0, x)))
                    self.str_for_statusbar = "Warning! Pause must be between 0 and 3 sec! "
                    return float(min(x, 3) if x > 3 else max(0, x))
            except:
                self.str_for_statusbar = "Error! Pause must be a float number between 0 and 3 sec! "
                wx.CallAfter(self.c_round_pause.SetValue, str(0))
                return 0.0


        def get_turn_pause(self):
            x = self.c_turn_pause.GetValue()
            try:
                x = float(x)
                if 0 <= x <= 3:
                    return x
                else:
                    wx.CallAfter(self.c_turn_pause.SetValue, str(min(x, 3) if x > 3 else max(0, x)))
                    self.str_for_statusbar = "Warning! Pause must be between 0 and 3 sec! "
                    return float(min(x, 3) if x > 3 else max(0, x))
            except:
                self.str_for_statusbar = "Error! Pause must be a float number between 0 and 3 sec! "
                wx.CallAfter(self.c_turn_pause.SetValue, str(0))
                return 0.0



        def start_judge(self):
            if self.bot1_path and self.bot2_path:
                try:
                    self.play_thread_alive[0] = True
                    if self.judge:
                        self.judge.__del__()

                    tp = self.get_turn_pause()
                    rp = self.get_round_pause()
                    if not (tp is None) and not(rp is None):
                        self.judge = Judge(self.bot1_path, self.bot2_path,
                                       tp,
                                       rp,
                                       self.lock,
                                       self.play_thread_alive)
                        self.bot1_name = self.judge.bot1.name
                        wx.CallAfter(self.l_bot1_name.SetLabel, self.bot1_name + " (1)")
                        self.bot2_name = self.judge.bot2.name
                        wx.CallAfter(self.l_bot2_name.SetLabel, self.bot2_name + " (2)")
                except:
                    self.flush_all_to_default()
                    self.str_for_statusbar = "Error! You choose wrong file or file isn't a Bot program"


        def on_add_bot1(self, event):
            if self.b_add_bot1.GetLabel() != "OK":
                if self.dialog.ShowModal() == wx.ID_OK:
                    self.bot1_path = self.dialog.GetPath()
                    wx.CallAfter(self.b_add_bot1.SetLabel, "OK")
                    self.start_judge()
                    self.str_for_statusbar = "Bot 1 choosed"



        def on_add_bot2(self, event):
            if self.b_add_bot2.GetLabel() != "OK":
                if self.dialog.ShowModal() == wx.ID_OK:
                    self.bot2_path = self.dialog.GetPath()
                    wx.CallAfter(self.b_add_bot2.SetLabel, "OK")
                    self.start_judge()
                    self.str_for_statusbar = "Bot 2 choosed"



        def start_chemp(self, *args):
            self.flush_for_start()
            self.is_computing = True

            self.make_elements_active(False, *self.enable_disable_set)
            self.make_elements_active(True, *[self.b_pause_play, self.b_stop])
            wx.CallAfter(self.g_progress.SetRange, args[0])
            wx.CallAfter(self.g_progress.SetValue, 0)
            self.start_judge()
            self.str_for_statusbar = "Computing..."
            try:
                self.judge.play_championship(*args)
            except:
                pass
            self.make_elements_active(True, *self.enable_disable_set)
            self.make_elements_active(False, *[self.b_pause_play, self.b_stop])

            self.is_computing = False
            if not self.play_thread_alive[0]:
                self.str_for_statusbar = "Stopped."
            else:
                self.str_for_statusbar = "Complete!"


        def on_start_chemp(self, event):
            if self.judge:
                t = threading.Thread(target = self.start_chemp,
                                      args = (self.c_rounds.GetValue(), self.maplist, self.winlist))
                #self.judge.play_championship(3, self.maplist, self.winlist)
                t.start()


        def refresh(self):
            qmap = 0
            qwin = 0
            while self.running:
                self.lock.acquire()

                if self.maplist[2] != qmap:
                    qmap = self.maplist[2]
                    wx.CallAfter(self.field1.make_empty, self.maplist[0])
                    wx.CallAfter(self.field2.make_empty, self.maplist[1])
                    #self.field1.make_empty(self.maplist[0])
                    #self.field2.make_empty(self.maplist[1])
                if self.winlist[2] != qwin:
                    qwin = self.winlist[2]
                    wx.CallAfter(self.l_bot1_wins.SetLabel, str(self.winlist[0]))
                    wx.CallAfter(self.l_bot2_wins.SetLabel, str(self.winlist[1]))

                wx.CallAfter(self.g_progress.SetValue, self.winlist[2])
                if self.is_computing:
                    wx.CallAfter(self.status_bar.SetStatusText, self.str_for_statusbar +
                                 " Now on %d round" % (self.winlist[2]+1, ) )
                else:
                    wx.CallAfter(self.status_bar.SetStatusText, self.str_for_statusbar)
                wx.CallAfter(self.field1.refresh)
                wx.CallAfter(self.field2.refresh)

                #self.Refresh()

                self.lock.release()
                time.sleep(0.1)