クラウドソーシングサービス×oTreeでのオンライン実験
普段から私は、クラウドソーシングサービスとoTreeで作った実験プログラムを使ってオンライン実験をしています。クラウドソーシングサービスで参加者を募集してoTreeでの実験プログラムへのリンクにアクセスしてもらい、実験プログラムの最後に表示されるコードを入力してもらうことで謝礼を支払います。つまり、参加者の募集と謝礼の支払いをクラウドソーシングサービスで、実験課題と入力用コードの表示をoTreeで行っているということです。
マッチング不成立問題
しかし、グループで相互作用ををするタイプの実験をするときに、困ることがあります。それは、なかなか参加者のマッチングが成立しない場合があることです。例えば、4人グループで行う実験で最後の一人がなかなか来ないと、先に来た3人は実験課題が始められず、ずっと待つことになってしまうわけです。
その対策として、以前はマッチング待機画面を用意して「5分以上マッチングが成立しない場合は連絡してください、謝礼をお渡しするためのコードを送ります」とお伝えしていたのですが、必要以上に連絡をお願いするのもよくないですし、手動だと安定しないので、自動で謝礼支払い用のコードが表示されるようにしました。
画面見本
※ 静止画だとわからないですが、黒丸部分がアニメーションになっていて、動きます。
方法: 時間が経過したらメッセージを表示するJavescriptのついたWaitページを用意する
matchingWait.html
oTreeで使うテンプレートとして、こちらのコードをmatchingWait.htmlとして追加します。
static→templatesの中に新しいhtmlファイルmatchingWait.htmlを追加します。
{{ block content }} <div id="wait-text"> 他の参加者が来るのを待っています。5分経っても4人の参加者がマッチングしなかった場合は、謝礼をお渡しするためのコードを自動で表示します。 </div> <div class="spinner" id="spinner"> <div class="double-bounce1"></div> <div class="double-bounce2"></div> </div> <script type="text/javascript"> function startCountdown() { var countdownEnd = localStorage.getItem('countdownEnd'); if (!countdownEnd) { countdownEnd = Date.now() + 5* 60 * 1000; // 5分後のタイムスタンプを保存 localStorage.setItem('countdownEnd', countdownEnd); } var interval = setInterval(function() { var now = Date.now(); var timeLeft = countdownEnd - now; if (timeLeft <= 0) { clearInterval(interval); clearInterval(refreshInterval); // リフレッシュを停止 document.getElementById('wait-text').innerText = '5分以内にマッチングしませんでした。【数字】0000 をクラウドソーシング側にご入力いただければ、謝礼をお支払いします。入力後、こちらの画面は閉じていただいて構いません。この度は誠にありがとうございました。'; document.getElementById('spinner').style.display = 'none'; // アニメーションを停止 localStorage.removeItem('countdownEnd'); } }, 1000); } // ページがリロードされてもタイマーを保持 startCountdown(); // 5秒ごとにページをリフレッシュ var refreshInterval = setInterval(function() { location.reload(); }, 5000); </script> <style> .spinner { width: 40px; height: 40px; position: relative; margin: 100px auto; } .double-bounce1, .double-bounce2 { width: 100%; height: 100%; border-radius: 50%; background-color: #333; opacity: 0.6; position: absolute; top: 0; left: 0; -webkit-animation: sk-bounce 2.0s infinite ease-in-out; animation: sk-bounce 2.0s infinite ease-in-out; } .double-bounce2 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s; } @-webkit-keyframes sk-bounce { 0%, 100% { -webkit-transform: scale(0.0) } 50% { -webkit-transform: scale(1.0) } } @keyframes sk-bounce { 0%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); } 50% { transform: scale(1.0); -webkit-transform: scale(1.0); } } </style> {{ endblock }}
ポイントは、5秒おきにリフレッシュしているところです。これをしないと、マッチングが成立したのにも関わらず画面がこのページのまま自動で切り替わらないという問題が起こりました。
また、<style>~<style>の部分は、待っているときのアニメーションを表示させるためだけのコードなので、別になくてもいいです(上の画面見本の黒い〇の部分です)。
iniy.py Pages部分での設定
作ったテンプレートを読み込むように設定しています。
# PAGES class matchingWait(WaitPage): def is_displayed(player): return player.round_number == 1 template_name = 'matchingWait.html' def after_all_players_arrive(group: Group):
懸念点: サーバーへの負荷
懸念点として、「5秒ごとにリフレッシュする」という動作がどれくらいサーバーに負担をかけるのかがわかっていません。
少なくともこの間の実験では、Herokuサーバーの
dyno: Standard x2
Postgress Standard 7
同時接続: 100人
で、問題はありませんでした。
コメント