Beispiel #1
0
 def group_name(self, page_index, participant_code):
     return channel_utils.auto_advance_group(participant_code)
Beispiel #2
0
    def advance_last_place_participants(self):
        # django.test takes 0.5 sec to import,
        # if this is done globally then it adds to each startup
        # it's only used here, and often isn't used at all.
        # so best to do it only here
        # it gets cached
        import django.test

        client = django.test.Client()

        participants = self.get_participants()

        # in case some participants haven't started
        unvisited_participants = []
        for p in participants:
            if p._index_in_pages == 0:
                unvisited_participants.append(p)
                client.get(p._start_url(), follow=True)

        if unvisited_participants:
            # that's it -- just visit the start URL, advancing by 1
            return

        last_place_page_index = min([p._index_in_pages for p in participants])
        last_place_participants = [
            p for p in participants
            if p._index_in_pages == last_place_page_index
        ]

        for p in last_place_participants:
            try:
                current_form_page_url = p._current_form_page_url
                if current_form_page_url:
                    resp = client.post(
                        current_form_page_url,
                        data={
                            otree.constants.timeout_happened: True,
                            otree.constants.admin_secret_code:
                            ADMIN_SECRET_CODE,
                        },
                        follow=True,
                    )
                    # not sure why, but many users are getting HttpResponseNotFound
                    if resp.status_code >= 400:
                        msg = ('Submitting page {} failed, '
                               'returned HTTP status code {}.'.format(
                                   current_form_page_url, resp.status_code))
                        content = resp.content
                        if len(content) < 600:
                            msg += ' response content: {}'.format(content)
                        raise AssertionError(msg)

                else:
                    # it's possible that the slowest user is on a wait page,
                    # especially if their browser is closed.
                    # because they were waiting for another user who then
                    # advanced past the wait page, but they were never
                    # advanced themselves.
                    start_url = p._start_url()
                    resp = client.get(start_url, follow=True)
            except:
                logging.exception("Failed to advance participants.")
                raise

            # do the auto-advancing here,
            # rather than in increment_index_in_pages,
            # because it's only needed here.
            otree.channels.utils.sync_group_send_wrapper(
                type='auto_advanced',
                group=auto_advance_group(p.code),
                event={})
Beispiel #3
0
    def advance_last_place_participants(self):
        """the problem with using the test client to make get/post requests is
        (1) this request already has the global asyncio.lock
        (2) there are apparently some issues with async/await and event loops.
        """
        from otree.lookup import get_page_lookup
        from otree.api import WaitPage, Page

        participants = self.get_participants()

        # in case some participants haven't started
        unvisited_participants = False
        for p in participants:
            if p._index_in_pages == 0:
                p.initialize(None)

        if unvisited_participants:
            # that's it -- just visit the start URL, advancing by 1
            return

        last_place_page_index = min([p._index_in_pages for p in participants])
        last_place_participants = [
            p for p in participants
            if p._index_in_pages == last_place_page_index
        ]
        for p in last_place_participants:
            page_index = p._index_in_pages
            if page_index >= p._max_page_index:
                return
            page = get_page_lookup(
                self.code,
                page_index).page_class.instantiate_without_request()
            page.set_attributes(p)

            if isinstance(page, Page):

                from starlette.datastructures import FormData

                page._is_frozen = False
                page._form_data = FormData({
                    otree.constants.admin_secret_code:
                    ADMIN_SECRET_CODE,
                    otree.constants.timeout_happened:
                    '1',
                })
                # TODO: should we also call .get() so that _update_monitor_table will also get run?
                resp = page.post()
                if resp.status_code >= 400:
                    msg = (
                        f'Submitting page {p._current_form_page_url} failed, '
                        f'returned HTTP status code {resp.status_code}. '
                        'Check the logs')
                    raise AssertionError(msg)
            else:
                # it's possible that the slowest user is on a wait page,
                # especially if their browser is closed.
                # because they were waiting for another user who then
                # advanced past the wait page, but they were never
                # advanced themselves.
                resp = page.inner_dispatch(request=None)

            # do the auto-advancing here,
            # rather than in increment_index_in_pages,
            # because it's only needed here.
            otree.channels.utils.sync_group_send(group=auto_advance_group(
                p.code),
                                                 data={'auto_advanced': True})