Timeouts
Conceptos básicos
timeout_seconds
Para establecer un límite de tiempo en tu página, añade timeout_seconds:
class Page1(Page):
timeout_seconds = 60
Después de que se acabe el tiempo, la página se enviará automáticamente.
Si estás ejecutando el servidor de producción (prodserver), la página siempre se enviará, incluso si el usuario cierra su ventana del navegador. Sin embargo, esto no ocurre si estás ejecutando el servidor de desarrollo (zipserver o devserver).
Si necesitas que el tiempo de espera se determine dinámicamente, utiliza get_timeout_seconds.
timeout_happened
Puedes comprobar si la página fue enviada por timeout:
class Page1(Page):
form_model = 'player'
form_fields = ['xyz']
timeout_seconds = 60
@staticmethod
def before_next_page(player, timeout_happened):
if timeout_happened:
# you may want to fill a default value for any form fields,
# because otherwise they may be left null.
player.xyz = False
get_timeout_seconds
Esta es una alternativa más flexible a timeout_seconds, para que puedas hacer que el timeout dependa de player, player.session, etc.
Por ejemplo:
class MyPage(Page):
@staticmethod
def get_timeout_seconds(player):
return player.my_page_timeout_seconds
O, utilizando un parámetro de configuración de sesión personalizado (ver Eligiendo qué tratamiento jugar).
def get_timeout_seconds(player):
session = player.session
return session.config['my_page_timeout_seconds']
Técnicas avanzadas
Formularios enviados por tiempo de espera
Si un formulario se envía automáticamente debido a un tiempo de espera, oTree intentará guardar los campos que se completaron en el momento de la presentación. Si un campo en el formulario tiene un error porque falta o es inválido, se establecerá en 0 para campos numéricos, False para campos booleanos y la cadena vacía '' para campos de texto.
Si deseas descartar los valores enviados automáticamente, puedes simplemente verificar si timeout_happened y, si es así, sobrescribir los valores.
Si la función error_message() falla, entonces todo el formulario podría ser inválido, por lo que se descartará todo el formulario.
Timeouts que abarcan múltiples páginas
Puedes usar get_timeout_seconds para crear timeouts que abarquen múltiples páginas o incluso toda la sesión. El truco es definir un «tiempo de expiración» fijo y luego, en cada página, hacer que get_timeout_seconds devuelva el número de segundos hasta ese tiempo de expiración.
Primero, elige un lugar para iniciar el temporizador. Esto podría ser una página llamada «Inicio» que muestre un texto como «Presiona el botón cuando estés listo para comenzar». Cuando el usuario haga clic en el botón «siguiente», se ejecutará 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
(También podrías iniciar el temporizador en after_all_players_arrive o creating_session, y podría almacenarse en un campo de sesión si es el mismo para todos en la sesión.)
Luego, el get_timeout_seconds de cada página debe ser el número de segundos hasta ese tiempo de expiración:
class Page1(Page):
@staticmethod
def get_timeout_seconds(player):
participant = player.participant
import time
return participant.expiry - time.time()
Cuando se agote el tiempo, get_timeout_seconds devolverá 0 o un valor negativo, lo que resultará en que la página se cargue y se envíe automáticamente de inmediato. Esto significa que todas las páginas restantes parpadearán rápidamente en la pantalla del participante, lo cual generalmente no es deseado. Por lo tanto, deberías usar is_displayed para omitir la página si no hay suficiente tiempo para que el participante lea realmente toda la página.
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
El texto predeterminado en el temporizador dice «Tiempo restante para completar esta página:». Pero si tu tiempo de espera abarca múltiples páginas, deberías expresarlo de manera más precisa, configurando timer_text:
class Page1(Page):
timer_text = 'Time left to complete this section:'
@staticmethod
def get_timeout_seconds(player):
...
Personalizando el temporizador
Ocultando el temporizador
Si deseas ocultar el temporizador, utiliza este CSS:
.otree-timer {
display: none;
}
Cambiar el comportamiento del temporizador
La funcionalidad del temporizador es proporcionada por jQuery Countdown. Puedes cambiar su comportamiento adjuntando y eliminando controladores de eventos con .on() y off() de jQuery.
oTree establece controladores para los eventos update.countdown y finish.countdown, así que si deseas modificarlos, puedes desadjuntarlos con off(), y/o agregar tu propio controlador con on(). El elemento de cuenta regresiva es .otree-timer__time-left.
Por ejemplo, para ocultar el temporizador hasta que queden solo 10 segundos,
<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>
Para evitar copiar y pegar este código en cada página, colócalo en una plantilla incluyente.
Nota: incluso si desactivas el controlador de eventos finish.countdown, la página aún se enviará en el lado del servidor. Por lo tanto, en su lugar, deberías usar la técnica descrita en Tiempo de espera que no envía la página.
Tiempo de espera que no envía la página
Si solo deseas un tiempo de espera suave, no necesitas usar el temporizador incorporado en absoluto. En su lugar, crea el tuyo propio con JavaScript, por ejemplo:
setTimeout(
function () {
alert("Time has run out. Please make your decision.");
},
60*1000 // 60 seconds
);