Пример #1
0
    def create(self):
        """Handles the POST data for creating a group.

        Form Variables:
            name:   the name of the new group
            public: true if the group should be joinable by the public
        """
        if auth.logged_in():
            name = self.request.get('name')
            public = self.request.get('public') == 'public'
            owner = auth.current_user()

            if Group.exists(name):
                Messages.add('A group with that name already exists')
                return self.redirect('/groups/signup')

            Group(name=name,
                  public=public,
                  owner=owner,
                  members=[owner]).put()

            return self.redirect('/groups')
        else:
            Messages.add('You must be logged in to create a group')
            return self.redirect('/groups/signup')
Пример #2
0
 def delete(self, key):
     if auth.user_is_admin():
         Group.get(key).delete()
     else:
         Messages.add('Only an administrator may delete groups. This ' +
                      'incident has been logged.')
     return self.redirect('/groups')
Пример #3
0
 def delete(self, key):
     if auth.user_is_admin():
         Project.get(key).delete()
     else:
         Messages.add('Only and administrator may delete projects. This ' +
                      'incident has been logged.')
     return self.redirect('/projects')
Пример #4
0
 def signup(self):
     user = auth.User(auth.current_user())
     if user.in_group():
         Messages.add('You are already in a group')
         return self.redirect('/groups')
     else:
         return self.render('groups_signup')
Пример #5
0
 def delete(self, key):
     if auth.user_is_admin():
         Idea.get(key).delete()
     else:
         Messages.add('Only and administrator may delete submitted ideas. ' +
                      'This incident has been logged.')
     return self.redirect('/ideas')
Пример #6
0
 def delete(self, key):
     """Deletes a project."""
     if auth.user_is_admin():
         Project.get(key).delete()
     else:
         Messages.add('Only and administrator may delete projects. This ' +
                      'incident has been logged.')
     return self.redirect('/projects')
Пример #7
0
 def signup(self):
     """Displays the group sign up form."""
     user = auth.User(auth.current_user())
     if user.in_group():
         Messages.add('You are already in a group')
         return self.redirect('/groups')
     else:
         return self.render('groups_signup')
Пример #8
0
 def delete(self, key):
     """Deletes a group."""
     if auth.user_is_admin():
         Group.get(key).delete()
     else:
         Messages.add('Only an administrator may delete groups. This ' +
                      'incident has been logged.')
     return self.redirect('/groups')
Пример #9
0
 def delete(self, key):
     """Deletes a project idea."""
     if auth.user_is_admin():
         Idea.get(key).delete()
     else:
         Messages.add('Only and administrator may delete submitted ' +
                      'ideas. This incident has been logged.')
     return self.redirect('/ideas')
Пример #10
0
    def update_group(self, key):
        if not auth.logged_in():
            return self.redirect('/groups')
        
        user = auth.current_user()
        group = Group.get(key)
        if group.owner.user_id() != user.user_id() and not auth.user_is_admin():
            Messages.add('Only the owner of the group owner may modify it')
            return self.redirect('/groups')
        
        name = self.request.get('name')
        public = self.request.get('public') == 'public'
        abandon = self.request.get('abandon-project')
        sub_text = self.request.get('submission-text')
        sub_url = self.request.get('submission-url')
        remove_submission = self.request.get_all('remove-submission')
        remove = self.request.get_all('remove')
        owner = self.request.get('owner')
        delete = self.request.get('delete')
        
        if delete:
            group.delete()
            return self.redirect('/groups')
        
        group.name = name
        group.public = public
        
        if abandon:
            group.project = None
        
        if sub_text and sub_url:
            Submission(text=sub_text, url=sub_url, group=group).put()

        for sub in Submission.get(remove_submission):
            sub.delete()

        pending  = list(group.pending_users)
        for user in pending:
            approve = self.request.get("approve-%s" % user)
            if approve == "approve":
                group.members.append(user)
                group.pending_users.remove(user)
            elif approve == "refuse":
                group.pending_users.remove(user)
        
        group.owner = auth.user_from_email(owner)
        
        for user in remove:
            if auth.user_from_email(user) == group.owner:
                Messages.add('Cannot remove the group owner')
                return self.redirect('/groups/%s/edit' % key)
            else:
                group.members.remove(auth.user_from_email(user))
        
        group.put()
        return self.redirect('/groups/%s' % key)
Пример #11
0
 def edit(self, key):
     if not auth.logged_in():
         return self.redirect('/groups')
     
     user = auth.current_user()
     group = Group.get(key)
     if group.owner.user_id() == user.user_id() or auth.user_is_admin():
         return self.render('groups_edit', { 'group': group })
     else:
         Messages.add('Only the owner of this group may edit it')
         return self.redirect('/groups/%s' % key)
Пример #12
0
 def leave(self, key):
     group = Group.get(key)
     user = auth.User(auth.current_user())
     
     if user.group != group:
         Messages.add('You cannot leave a group you are not in')
         return self.redirect('/groups/%s' % key)
     
     group.members.remove(user.gae_user)
     group.put()
     return self.redirect('/groups')
Пример #13
0
    def edit(self, key):
        """Displays the group moderation form."""
        if not auth.logged_in():
            return self.redirect('/groups')

        user = auth.current_user()
        group = Group.get(key)
        if group.owner.user_id() == user.user_id() or auth.user_is_admin():
            return self.render('groups_edit', {'group': group})
        else:
            Messages.add('Only the owner of this group may edit it')
            return self.redirect('/groups/%s' % key)
Пример #14
0
 def claim(self, key):
     user = auth.User(auth.current_user())
     group = user.group
     if group.owner.user_id() == auth.current_user().user_id():
         project = Project.get(key)
         group.project = project
         group.put()
         return self.redirect('/groups/%s' % group.key())
     else:
         Messages.add('You are not the owner of your group. Only the ' +
                      'owner of the group may select a project.')
         return self.redirect('/projects')
Пример #15
0
    def leave(self, key):
        """Removes the current user from the group's roster."""
        group = Group.get(key)
        user = auth.User(auth.current_user())

        if user.group != group:
            Messages.add('You cannot leave a group you are not in')
            return self.redirect('/groups/%s' % key)

        group.members.remove(user.gae_user)
        group.put()
        return self.redirect('/groups')
Пример #16
0
 def claim(self, key):
     """Claims a project for a group."""
     user = auth.User(auth.current_user())
     group = user.group
     if group.owner.user_id() == auth.current_user().user_id():
         project = Project.get(key)
         group.project = project
         group.put()
         return self.redirect('/groups/%s' % group.key())
     else:
         Messages.add('You are not the owner of your group. Only the ' +
                      'owner of the group may select a project.')
         return self.redirect('/projects')
Пример #17
0
 def approve(self, key):
     if auth.user_is_admin():
         idea = Idea.get(key)
         Project(name=idea.name,
                 description=idea.description,
                 author=idea.author,
                 post_time=idea.post_time).put()
         idea.delete()
         return self.redirect('/projects')
     else:
         Messages.add('Only and administrator may approve submitted ' +
                      'ideas. This incident has been logged.')
         return self.redirect('/ideas')
Пример #18
0
 def approve(self, key):
     """Promotes a project idea to an accepted project."""
     if auth.user_is_admin():
         idea = Idea.get(key)
         Project(name=idea.name,
                 description=idea.description,
                 author=idea.author,
                 post_time=idea.post_time).put()
         idea.delete()
         return self.redirect('/projects')
     else:
         Messages.add('Only and administrator may approve submitted ' +
                      'ideas. This incident has been logged.')
         return self.redirect('/ideas')
Пример #19
0
def getMessages():
    messages = Messages()
    if request.method == 'POST':
        if request.data:
            # Content-Type: application/json
            # ie. - { "foo": "bar", "baz": "moe" }
            data = json.loads(request.data)
        else:
            # Content-Type: x-www-form-urlencoded
            # ie. - foo=bar&baz=moe
            data = dict((k, request.values[k]) for k in request.values.keys())
        return jsonify(messages.add(data))
    else:
        return jsonify(messages.getMessages())
Пример #20
0
 def join(self, key):
     group = Group.get(key)
     user = auth.User(auth.current_user())
     if user.in_group():
         Messages.add('You are already in a group')
         return self.redirect('/groups/%s' % key)
     if user.pending_join():
         Messages.add('You have already applied to join a group')
         return self.redirect('/groups/%s' % key)
     if group.public:
         group.members.append(auth.current_user())
         Messages.add('You have joined the group')
     else:
         group.pending_users.append(auth.current_user())
         Messages.add('You have requested to join the group')
     group.put()
     return self.redirect('/groups/%s' % key)
Пример #21
0
 def join(self, key):
     """Adds the current user to the group's roster."""
     group = Group.get(key)
     user = auth.User(auth.current_user())
     if user.in_group():
         Messages.add('You are already in a group')
         return self.redirect('/groups/%s' % key)
     if user.pending_join():
         Messages.add('You have already applied to join a group')
         return self.redirect('/groups/%s' % key)
     if group.public:
         group.members.append(auth.current_user())
         Messages.add('You have joined the group')
     else:
         group.pending_users.append(auth.current_user())
         Messages.add('You have requested to join the group')
     group.put()
     return self.redirect('/groups/%s' % key)
Пример #22
0
    def update_group(self, key):
        """Updates a group with information from the moderation form.

        Form Variables:
            name:              the name of the group
            public:            true if the group should be joinable by the
                               public
            abandon-project:   true if the group moderator wants to abandon the
                               current project
            submission-text:   the text to be displayed for the new submission
            submission-url:    the URL of the new submission
            remove-submission: a list of submissions to be removed
            remove:            a list of users to be removed from the group
            owner:             the owner of the group
            delete:            true if the group moderator wants to disband the
                               group
        """
        if not auth.logged_in():
            return self.redirect('/groups')

        user = auth.current_user()
        group = Group.get(key)
        if (group.owner.user_id() != user.user_id() and
                not auth.user_is_admin()):
            Messages.add('Only the owner of the group owner may modify it')
            return self.redirect('/groups')

        name = self.request.get('name')
        public = self.request.get('public') == 'public'
        abandon = self.request.get('abandon-project')
        sub_text = self.request.get('submission-text')
        sub_url = self.request.get('submission-url')
        remove_submission = self.request.get_all('remove-submission')
        remove = self.request.get_all('remove')
        owner = self.request.get('owner')
        delete = self.request.get('delete')

        if delete:
            group.delete()
            return self.redirect('/groups')

        group.name = name
        group.public = public

        if abandon:
            group.project = None

        if sub_text and sub_url:
            Submission(text=sub_text, url=sub_url, group=group).put()

        for sub in Submission.get(remove_submission):
            sub.delete()

        pending = list(group.pending_users)
        for user in pending:
            approve = self.request.get("approve-%s" % user)
            if approve == "approve":
                group.members.append(user)
                group.pending_users.remove(user)
            elif approve == "refuse":
                group.pending_users.remove(user)

        group.owner = auth.user_from_email(owner)

        for user in remove:
            if auth.user_from_email(user) == group.owner:
                Messages.add('Cannot remove the group owner')
                return self.redirect('/groups/%s/edit' % key)
            else:
                group.members.remove(auth.user_from_email(user))

        group.put()
        return self.redirect('/groups/%s' % key)
Пример #23
0
class Window(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title)

        # Splitters and Panels
        self.controls_map_splitter = wx.SplitterWindow(self)
        self.controls_map_splitter.SetMinimumPaneSize(300)

        controls_panel = wx.Panel(self.controls_map_splitter)
        map_panel = wx.Panel(self.controls_map_splitter)

        self.graphs_messages_splitter = wx.SplitterWindow(controls_panel)
        self.graphs_messages_splitter.SetMinimumPaneSize(50)

        graphs_panel = wx.Panel(self.graphs_messages_splitter)
        messages_panel = wx.Panel(self.graphs_messages_splitter)

        # World graphic
        self._graphics = worldmap.WorldMap(map_panel)
        self.graphics_sizer = wx.BoxSizer(wx.VERTICAL)
        self.graphics_sizer.Add(self._graphics, 1, wx.EXPAND)
        map_panel.SetSizerAndFit(self.graphics_sizer)

        # Controls panel
        self.controls = Controls(controls_panel, (300, 250), self)

        # Info panel
        self.info = Info(controls_panel, (300, 250))

        # Graph canvas
        self.graphs = graphs.Graphs(graphs_panel, (300, 300))

        # Messages panel
        self.messages = Messages(messages_panel, (600, 200))

        self.interface_sizer = wx.BoxSizer(wx.VERTICAL)

        self.controls_info_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.controls_info_sizer.Add(self.info, 0, wx.EXPAND)
        self.controls_info_sizer.Add((20, -1), proportion=0)    # Padding
        self.controls_info_sizer.Add(self.controls, 1, wx.EXPAND)

        self.messages_sizer = wx.BoxSizer(wx.VERTICAL)
        self.messages_sizer.Add(self.messages, 1, wx.EXPAND)
        messages_panel.SetSizerAndFit(self.messages_sizer)

        self.graphs_sizer = wx.BoxSizer(wx.VERTICAL)
        self.graphs_sizer.Add(self.graphs, 1, wx.EXPAND)
        graphs_panel.SetSizerAndFit(self.graphs_sizer)

        self.interface_sizer.Add(self.controls_info_sizer, 0, wx.EXPAND)
        self.interface_sizer.Add(self.graphs_messages_splitter, 1, wx.EXPAND)

        controls_panel.SetSizerAndFit(self.interface_sizer)

        self.graphs_messages_splitter.SplitHorizontally(
            messages_panel,
            graphs_panel
        )

        self.controls_map_splitter.SplitVertically(controls_panel, map_panel)

        # Set up event handler for any worker thread results
        EVT_RESULT(self, self.OnResult)
        EVT_STOP(self, self.OnStop)

        # Set up close event so timer is properly stopped
        wx.EVT_CLOSE(self, self.OnClose)

        self.reset_gui()
        self.Show()

    def reset_gui(self):
        self.controls.reset_buttons()
        self.messages.clear()
        self.graphs.reset_data()

    # Event Methods
    def OnStart(self, event):
        self.controls.set_buttons_ready()

        self._simulation = simulation.Simulation()

        self._simulation.setup_config(self.controls.get_config_filename())
        self.simulation_info = self._simulation.initialize()

        if not self.simulation_info.interface_config.print_messages:
            self.messages.deactivate()

        self._graphics.num_max_complaints = \
            self.simulation_info.num_max_complaints

        self.rounds = 0
        self.steps = 0

        self.next_phase = "COASTPLAN"
        self.prev_phase = None

        self.worker = None

    def run(self, rounds, steps):
        assert rounds >= 0, "Rounds has to be a positive integer."
        assert steps >= 0, "Steps has to be a positive integer."
        assert steps > 0 or rounds > 0, "Rounds or steps needs to be positive."
        self.controls.set_status(rounds, steps)
        self.controls.set_buttons_processing()
        self.rounds = rounds
        self.steps = steps
        if self.worker is None:
            self.prev_phase = self.next_phase
            self.info.set_current_phase(self.next_phase)
            self.worker = WorkerThread(self._simulation, self)

    def OnResult(self, event):
        if not event.source is self.worker: # ongoing simulation was aborted
            return
        self.worker = None
        self.simulation_info.map.grid = util.update_map(
            self.simulation_info.map.grid, event.result.map.grid
        )
        self.next_phase = event.result.next_phase

        handle_statistics(self.graphs, event.result.round, event.result.data)
        self._graphics.set_map(self.simulation_info.map)
        if event.result.phase == "HEARING":
            self._graphics.add_votes(event.result.complaints)
        self._graphics.update()

        for m in event.result.messages:
            self.messages.add(str(m))

        newr = self.prev_phase == "LEARNING" and self.next_phase == "COASTPLAN"
        if newr:
            self._graphics.reset_votes()
        if newr and self.rounds > 0:
            self.rounds -= 1
        elif self.rounds == 0:
            self.steps -= 1

        if self.rounds > 0 or self.steps > 0:
            self.run(self.rounds, self.steps)
        else:
            self.controls.set_buttons_ready()

    def OnStop(self, event):
        self.reset_gui()
        self._simulation = None
        self.worker = None
        self.simulation_info = None

    def OnClose(self, event):
        # TODO: Fix
        self.Destroy()
Пример #24
0
class Feed(object):
    def __init__(self, page):
        self.page = page
        self.conf = conf.getInstance()
        messageLikes_addHeaders(page)
        messageComments_addHeaders(page)

        self.messages = Messages()
        self.scroll_pos = 0
        self.num_messages = None
        self.url_preview_html = unicode(open('url_preview.html').read())

    def process(self):

        # add new messages
        if 'new_message' in self.page.form:
            data = {
                'user_id': self.page.session.user.id,
                'text': self.page.form['new_message'].value
            }
            id = self.messages.add(data)

        # add like
        if 'like' in self.page.form:
            message_id = int(self.page.form['like'].value)
            if message_id:
                message = Message(message_id)
                MessageLikes(message).toggle(self.page.session.user.id)

        # add comment
        for field in self.page.form.keys():
            if field.startswith('new_comment_'):
                reference_id = field.split('_')[2]
                if reference_id:
                    data = {
                        'user_id': self.page.session.user.id,
                        'reference_id': reference_id,
                        'text': self.page.form[field].value
                    }
                    id = self.messages.add(data)
                break

        # remember scroll
        if 'scroll_pos' in self.page.form:
            p = self.page.form['scroll_pos'].value
            self.scroll_pos = int(round(float(p), 0))

    def getMessages(self, user_id=None, search=None, school_id=None):
        # TO DO: rename getMyMessages to something like getThisUsersMessages

        if search:
            messages = self.messages.getSearchMessages(search)['messages']
        elif school_id:
            messages = self.messages.getSchoolSearchMessages(school_id)\
                       ['messages']
        else:
            if not user_id:
                user_id = self.page.session.user.id
            if self.page.name == 'profile':
                messages = self.messages.getMyMessages(user_id)['messages']
            else:
                messages = self.messages.getUserMessages(user_id)['messages']

        self.num_messages = len(messages)

        hidden_fields = \
            input(name='like', type='hidden') + \
            input(name='scroll_pos', type='hidden') + \
            input(name='prev_scroll_pos', type='hidden', value=self.scroll_pos)

        o = ''
        o += hidden_fields
        for m in messages:
            o += self._getMessageCard(m, search=search)
        return form(div(o, id='messageArea'), name='messages-form')

    def getNewMessageCard(self):
        return form(open('new-message2.html', 'r').read(),
                    name='new-card-form')

    def _getMessageCard(self, message, search=None):
        message = odict(message)
        image = getUserImage(message.user_id)
        user_icon = div(img(src=image, width='70px', class_='img-thumbnail'),
                        class_='userIcon')
        username = div(message.author, class_='messageAuthor')
        reason = div(message.reason, class_='messageReason')
        date = div(message.created, class_='messageDate')
        name_link = a(username,
                      href='//%s/profile.py?u=%s' %
                      (self.conf.baseurl, encrypt_int(message.user_id)))
        username_and_date = div(name_link + reason + date,
                                class_='usernameAndDate')

        text = urlize(message.text,
                      trim_url_limit=50,
                      nofollow=True,
                      target='_blank')
        text = self._highlightKeyTerms(text, search)

        messageLikes = MessageLikes(message)
        messageComments = MessageComments(message)
        footer = \
            messageLikes.html_widget(self.page.session.user) + \
            messageComments.html_widget()

        # hack need to instantiate m for each mesage:
        url_previews = ''
        for preview in Message(message.id).url_previews:
            preview2 = copy(preview)
            preview2['thumbnail_width'] = min(preview2['thumbnail_width'], 500)
            if not preview2['thumbnail_url']:
                preview2['thumbnail_url'] = ''
            url_previews += self.url_preview_html.format(**preview2)

        o = ''
        o += user_icon + username_and_date
        o += div(text, class_='messageText')
        o += url_previews
        o += div(footer, class_='messageFooter')
        o += messageLikes.html_likersSection()
        o += messageComments.html_commentsSection(self.page.session.user,
                                                  search=search)

        return div(o, class_='messageCard', id='message_card_%s' % message.id)

    def _highlightKeyTerms(self, text, search=None):
        if not search:
            return text

        text2 = text
        for term in search.split(' '):
            term2 = r'(%s)(?!=)' % term
            text2 = re.sub(term2,
                           r'<span class="search-term">\1</span>',
                           text2,
                           flags=re.IGNORECASE)
        return text2
Пример #25
0
class Window(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title)

        # Splitters and Panels
        self.controls_map_splitter = wx.SplitterWindow(self)
        self.controls_map_splitter.SetMinimumPaneSize(300)

        controls_panel = wx.Panel(self.controls_map_splitter)
        map_panel = wx.Panel(self.controls_map_splitter)

        self.graphs_messages_splitter = wx.SplitterWindow(controls_panel)
        self.graphs_messages_splitter.SetMinimumPaneSize(50)

        graphs_panel = wx.Panel(self.graphs_messages_splitter)
        messages_panel = wx.Panel(self.graphs_messages_splitter)

        # World graphic
        self._graphics = worldmap.WorldMap(map_panel)
        self.graphics_sizer = wx.BoxSizer(wx.VERTICAL)
        self.graphics_sizer.Add(self._graphics, 1, wx.EXPAND)
        map_panel.SetSizerAndFit(self.graphics_sizer)

        # Controls panel
        self.controls = Controls(controls_panel, (300, 250), self)

        # Info panel
        self.info = Info(controls_panel, (300, 250))

        # Graph canvas
        self.graphs = graphs.Graphs(graphs_panel, (300, 300))

        # Messages panel
        self.messages = Messages(messages_panel, (600, 200))

        self.interface_sizer = wx.BoxSizer(wx.VERTICAL)

        self.controls_info_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.controls_info_sizer.Add(self.info, 0, wx.EXPAND)
        self.controls_info_sizer.Add((20, -1), proportion=0)  # Padding
        self.controls_info_sizer.Add(self.controls, 1, wx.EXPAND)

        self.messages_sizer = wx.BoxSizer(wx.VERTICAL)
        self.messages_sizer.Add(self.messages, 1, wx.EXPAND)
        messages_panel.SetSizerAndFit(self.messages_sizer)

        self.graphs_sizer = wx.BoxSizer(wx.VERTICAL)
        self.graphs_sizer.Add(self.graphs, 1, wx.EXPAND)
        graphs_panel.SetSizerAndFit(self.graphs_sizer)

        self.interface_sizer.Add(self.controls_info_sizer, 0, wx.EXPAND)
        self.interface_sizer.Add(self.graphs_messages_splitter, 1, wx.EXPAND)

        controls_panel.SetSizerAndFit(self.interface_sizer)

        self.graphs_messages_splitter.SplitHorizontally(
            messages_panel, graphs_panel)

        self.controls_map_splitter.SplitVertically(controls_panel, map_panel)

        # Set up event handler for any worker thread results
        EVT_RESULT(self, self.OnResult)
        EVT_STOP(self, self.OnStop)

        # Set up close event so timer is properly stopped
        wx.EVT_CLOSE(self, self.OnClose)

        self.reset_gui()
        self.Show()

    def reset_gui(self):
        self.controls.reset_buttons()
        self.messages.clear()
        self.graphs.reset_data()

    # Event Methods
    def OnStart(self, event):
        self.controls.set_buttons_ready()

        self._simulation = simulation.Simulation()

        self._simulation.setup_config(self.controls.get_config_filename())
        self.simulation_info = self._simulation.initialize()

        if not self.simulation_info.interface_config.print_messages:
            self.messages.deactivate()

        self._graphics.num_max_complaints = \
            self.simulation_info.num_max_complaints

        self.rounds = 0
        self.steps = 0

        self.next_phase = "COASTPLAN"
        self.prev_phase = None

        self.worker = None

    def run(self, rounds, steps):
        assert rounds >= 0, "Rounds has to be a positive integer."
        assert steps >= 0, "Steps has to be a positive integer."
        assert steps > 0 or rounds > 0, "Rounds or steps needs to be positive."
        self.controls.set_status(rounds, steps)
        self.controls.set_buttons_processing()
        self.rounds = rounds
        self.steps = steps
        if self.worker is None:
            self.prev_phase = self.next_phase
            self.info.set_current_phase(self.next_phase)
            self.worker = WorkerThread(self._simulation, self)

    def OnResult(self, event):
        if not event.source is self.worker:  # ongoing simulation was aborted
            return
        self.worker = None
        self.simulation_info.map.grid = util.update_map(
            self.simulation_info.map.grid, event.result.map.grid)
        self.next_phase = event.result.next_phase

        handle_statistics(self.graphs, event.result.round, event.result.data)
        self._graphics.set_map(self.simulation_info.map)
        if event.result.phase == "HEARING":
            self._graphics.add_votes(event.result.complaints)
        self._graphics.update()

        for m in event.result.messages:
            self.messages.add(str(m))

        newr = self.prev_phase == "LEARNING" and self.next_phase == "COASTPLAN"
        if newr:
            self._graphics.reset_votes()
        if newr and self.rounds > 0:
            self.rounds -= 1
        elif self.rounds == 0:
            self.steps -= 1

        if self.rounds > 0 or self.steps > 0:
            self.run(self.rounds, self.steps)
        else:
            self.controls.set_buttons_ready()

    def OnStop(self, event):
        self.reset_gui()
        self._simulation = None
        self.worker = None
        self.simulation_info = None

    def OnClose(self, event):
        # TODO: Fix
        self.Destroy()