タイムアウト

基本

timeout_seconds

ページに時間制限を設定するには、次のように timeout_seconds を追加します。:

class Page1(Page):
    timeout_seconds = 60

設定した時間が経過すると、自動的にページが遷移します。

本番サーバー( prodserver )で実行している場合、ユーザーがブラウザーウィンドウを閉じたとしてもページは常に送信されます。ただし、開発サーバー( zipserverdevserver )を実行している場合、これは発生しません。

タイムアウト時間を動的に設定したい場合は、 get_timeout_seconds を使用します。

timeout_happened

ページがタイムアウトまでに送信されたかどうかを確認できます。

class Page1(Page):
    timeout_seconds = 60

    @staticmethod
    def before_next_page(player, timeout_happened):
        if timeout_happened:
            player.xyz = True

get_timeout_seconds

timeout_seconds よりも柔軟に設定できます。例えば、タイムアウト時間が playerplayer.session に依存する場合等に有効です。

例:

class MyPage(Page):

    @staticmethod
    def get_timeout_seconds(player):
        return player.my_page_timeout_seconds

また、カスタムセッション構成パラメーターを使用することもできます。( 実行する処理の選択 を参照)。

def get_timeout_seconds(player):
    session = player.session

    return session.config['my_page_timeout_seconds']

高度な技術

タイムアウトによって送信されたフォーム

タイムアウトのためにフォームが自動送信された場合、oTreeは送信時に入力されたフィールドを保存しようとします。ただし、フォームへの入力が終わっておらず、内容が欠落しているか無効であるためにエラーが発生した場合、数値フィールドには 0 、ブールフィールドには False 、および文字列フィールドには空の文字列 '' が設定されます。

タイムアウトによって自動送信された値を破棄したい場合は、 timeout_happened を確認することによって破棄するかどうかを決定できます。

error_message() 関数が失敗した場合、フォームの情報が無効である可能性があるため、そのフォームの情報は破棄されます。

複数のページにまたがるタイムアウト

複数のページ、またはセッション全体にまたがるタイムアウト処理を設定するために get_timeout_seconds を使用できます。方法は、固定の "有効期限" を定義し、各ページで get_timeout_seconds を作成し、その有効期限までの秒数を返すようにすることです。

まず、タイマーを開始する場所を選択します。これは、 "開始する準備ができたらボタンを押してください" などのテキストを表示するページが好ましいです。ユーザーが「次へ」ボタンをクリックすると、 before_next_page が実行されます。

class Start(Page):

    @staticmethod
    def before_next_page(player, timeout_happened):
        participant = player.participant
        import time

        # remember to add 'expiry' to PARTICIPANT_FIELDS.
        participant.expiry = time.time() + 5*60

after_all_players_arrive または creating_session でタイマーを開始することもできます。セッションの全員で同じ場合は、セッションフィールドに保存できます。)

次に、各ページの get_timeout_seconds は、その有効期限までの秒数である必要があります。

class Page1(Page):

    @staticmethod
    def get_timeout_seconds(player):
        participant = player.participant
        import time
        return participant.expiry - time.time()

タイムアウトになると、 get_timeout_seconds は0または負の値が返します。これにより、ページが読み込まれ、すぐに自動送信されます。これは、残りのすべてのページが参加者の画面で自動ですばやく遷移していくことを意味しますが、これは画面がちかちかするので通常は望ましくありません。したがって、参加者がページ全体を実際に読むのに十分な時間がない場合は、 is_displayed を使用してページをスキップするのが望ましいです。

def get_timeout_seconds(player):
    participant = player.participant
    import time
    return participant.expiry - time.time()

class Page1(Page):
    get_timeout_seconds = get_timeout_seconds

    @staticmethod
    def is_displayed(player):
        return get_timeout_seconds(player) > 3

タイマーのデフォルトのテキストには、「このページを完了するまでの残り時間: 」と表示されます。ただし、タイムアウトが複数のページにまたがる場合は、 timer_text を次のように設定して、より正確に表現する必要があります。

class Page1(Page):

    timer_text = 'Time left to complete this section:'

    @staticmethod
    def get_timeout_seconds(player):
        ...

タイマーのカスタマイズ

タイマーを隠す

タイマーを非表示にする場合は、次のCSSを使用します。

.otree-timer {
    display: none;
}

タイマーの動作を変更する

タイマーの機能は、 jQuery Countdown によって提供されます。あなたはjQueryの .on()off() にイベントハンドラを新しくアタッチすることにより、その動作を変更することができます。

oTreeは update.countdownfinish.countdown イベントのハンドラーを設定するため、それらを変更する場合は、 off() でハンドラを取り除いたり、 on() で独自のハンドラーを追加したりできます。カウントダウン要素は .otree-timer__time-left です。

たとえば、残り10秒になるまでタイマーを非表示にするには、

<style>
    .otree-timer {
        display: none;
    }
</style>

<script>
    document.addEventListener("DOMContentLoaded", function (event) {
        $('.otree-timer__time-left').on('update.countdown', function (event) {
            if (event.offset.totalSeconds === 10) {
                $('.otree-timer').show();
            }
        });
    });
</script>

このコードがすべてのページに適用されることを避けるには、 includable template にコードを配置します。

Note: even if you turn off the finish.countdown event handler, the page will still be submitted on the server side. So, instead you should use the technique described in ページを送信しないタイムアウト.

ページを送信しないタイムアウト

ページを送信しないタイムアウトが必要な場合は、組み込みのタイマーを使用する必要はまったくありません。代わりに、JavaScriptを使用して独自のものを作成します。次に例を示します。

setTimeout(
    function () {
        alert("Time has run out. Please make your decision.");
    },
    60*1000 // 60 seconds
);