Tree game - refresh problem

235 views
Skip to first unread message

hale erkan

unread,
Aug 31, 2021, 11:43:54 AM8/31/21
to oTree help & discussion
Hi All,
I have created a single-player game in Otree. Currently, players can refresh the page and change their responses. How can I make sure that they played it once? Or completely eliminate this situation? 

Thanks, 
Hale 

Chris @ oTree

unread,
Aug 31, 2021, 6:29:54 PM8/31/21
to hale erkan, oTree help & discussion
Can you show your code?

Sent from my phone

On Aug 31, 2021, at 8:44 AM, hale erkan <hale...@gmail.com> wrote:

Hi All,
I have created a single-player game in Otree. Currently, players can refresh the page and change their responses. How can I make sure that they played it once? Or completely eliminate this situation? 

Thanks, 
Hale 

--
You received this message because you are subscribed to the Google Groups "oTree help & discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to otree+un...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/otree/f0a286cb-49cf-4b12-a648-30ff069b9257n%40googlegroups.com.

hale erkan

unread,
Sep 2, 2021, 2:33:04 PM9/2/21
to oTree help & discussion
Hi, I copied the settings and  pages.py below. should I also show the html and js files?

Thanks !!
Hale 

####settings#####################################################################################################################################################
from os import environ

# if you set a property in SESSION_CONFIG_DEFAULTS, it will be inherited by all configs
# in SESSION_CONFIGS, except those that explicitly override it.
# the session config can be accessed from methods in your apps as self.session.config,
# e.g. self.session.config['participation_fee']

SESSION_CONFIG_DEFAULTS = dict(
real_world_currency_per_point_GK3=0.001,
real_world_currency_per_point=0.02,
participation_fee=1.00,
doc="",
use_browser_bots=False,
mturk_hit_settings=
{
'keywords': 'bonus, study',
'title': 'Research study',
'description': 'A decision making study, takes 15-20 minutes to complete, $1 to $3 bonus',
'frame_height': 500,
'template': 'global/mturk_template.html',
'minutes_allotted_per_assignment': 40,
'expiration_hours': 6,
'qualification_requirements': [
{
'QualificationTypeId': "00000000000000000071",
'Comparator': "EqualTo",
'LocaleValues': [{'Country': "US"}]
},
# {
# 'QualificationTypeId': "2F1QJWKUDD8XADTFD2Q0G6UTO95ALH", # master qual
# 'Comparator': "Exists"
# },
{
'QualificationTypeId': "00000000000000000040", #number hits approved
'Comparator': "GreaterThan",
'IntegerValues': [500]
},
{
'QualificationTypeId': "000000000000000000L0",  #% hits approved
'Comparator': "GreaterThan",
'IntegerValues': [98]
},
{
'QualificationTypeId': "355FVVGI4M596WBVH80ZOH714AP7LA",  # %prevent retakes
'Comparator': "DoesNotExist",
},
]
}
)

SESSION_CONFIGS = [

dict(
name='GK3',
display_name='GK3',
treatment='A',  # T1 and T2 treatments - early/late with/without
transfer_cost_value=1,  # value of the transfer cost if it is imposed in this treatment
duration_short=5,  # t1 in treatments without transfer cost
duration_long=10,  # t1 in treatments without transfer cost
num_demo_participants=5,
reward=10,
scale=10,  # factor by which rewards and costs are multiplied
app_sequence=[
'Transfers_GK3',
'scl_noloss',
'filler_app',
'scl_loss',
'filler_app2',
'scl_noloss_clone',
'payment_info',
'Transfers_survey'
],
),

dict(
name='GK1',
display_name='GK1',
treatment='T3T4',  # T3 - early/late/mixed with/without cost
transfer_cost_value=1,  # value of the transfer cost if it is imposed in this treatment
base_t1=10,  # t1 in treatments without transfer cost
base_t2=30,  # t2 in treatments without transfer cost, early
transfer_spread_t2=5,  # spread between t2 in treatments with and without transfer cost
num_demo_participants=5,
reward=10,
nudge=0,
perunit_comp=0.4,
scale=10,  # factor by which rewards and costs are multiplied
app_sequence=[
'Transfers_QDET_training',
'Transfers_QDET_R1',
'Transfers_QDET_R2',
'scl_noloss',
'filler_app',
'scl_loss',
'filler_app2',
'scl_noloss_clone',
'payment_info',
'Transfers_survey'
],
),

dict(
name='ADP',
display_name='ADP',
treatment='A',  # T1 and T2 treatments - early/late with/without
num_demo_participants=2,
app_sequence=[
'anxiety_game',
'scl_noloss_ADP',
'filler_app',
'scl_loss_ADP',
'filler_app2',
'scl_noloss_clone_ADP',
'payment_info_ADP',
'ADP_survey'
],
)
]



# ISO-639 code
# for example: de, fr, ja, ko, zh-hans
LANGUAGE_CODE = 'en'

# e.g. EUR, GBP, CNY, JPY
REAL_WORLD_CURRENCY_CODE = 'USD'
USE_POINTS = True
REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2

ROOMS = [
dict(
name='econ101',
display_name='Econ 101 class',
participant_label_file='_rooms/econ101.txt',
),
dict(name='live_demo', display_name='Room for live demo (no participant labels)'),
]

ADMIN_USERNAME = 'admin'
# for security, best to set admin password in an environment variable
# A DMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
ADMIN_PASSWORD = 'Ekagan05'

DEMO_PAGE_INTRO_HTML = """
Here are some oTree games.
"""

# don't share this with anybody.
SECRET_KEY = 't0q&9o2724880fwe-l4ri&f@8(_$52tm7fs&#^pwlp#svvo$x!'

INSTALLED_APPS = ['otree']


#####





#####pages.py################################################################################################################################################
from otree.api import Currency as c, currency_range
from otree.models import player

from ._builtin import Page, WaitPage
from .models import Constants
import datetime, json, time

# ******************************************************************************************************************** #
# *** CLASS INSTRUCTIONS *** #
# ******************************************************************************************************************** #
class Emotion(Page):

form_model = 'player'
form_fields = ['calm', 'tense', 'upset', 'relaxed', 'content', 'worried', 'angry', 'furious', 'irritated', 'mad', 'burnedup']

def get_form_fields(self):
import random
form_fields = ['calm', 'tense', 'upset', 'relaxed', 'content', 'worried', 'angry', 'furious', 'irritated', 'mad', 'burnedup']

random.shuffle(form_fields)
return form_fields

class Emotion2(Page):

form_model = 'player'
form_fields = ['calm2', 'tense2', 'upset2', 'relaxed2', 'content2', 'worried2', 'angry2', 'furious2', 'irritated2', 'mad2', 'burnedup2']
def get_form_fields(self):
import random
form_fields = ['calm2', 'tense2', 'upset2', 'relaxed2', 'content2', 'worried2', 'angry2', 'furious2',
'irritated2', 'mad2', 'burnedup2']

random.shuffle(form_fields)
return form_fields

class Emotion3(Page):

form_model = 'player'
form_fields = ['postcalm','posttense','postupset','postrelaxed','postcontent','postworried','postangry','postfurious','postirritated','postmad','postburnedup']
def get_form_fields(self):
import random
form_fields = ['postcalm', 'posttense', 'postupset', 'postrelaxed', 'postcontent', 'postworried', 'postangry',
'postfurious', 'postirritated', 'postmad', 'postburnedup']

random.shuffle(form_fields)
return form_fields
class PostEmotion2(Page):

form_model = 'player'
form_fields = ['postcalm2','posttense2','postupset2','postrelaxed2','postcontent2','postworried2','postangry2','postfurious2','postirritated2','postmad2','postburnedup2']
def get_form_fields(self):
import random
form_fields = ['postcalm2', 'posttense2', 'postupset2', 'postrelaxed2', 'postcontent2', 'postworried2',
'postangry2', 'postfurious2', 'postirritated2', 'postmad2', 'postburnedup2']

random.shuffle(form_fields)
return form_fields


class _Landing(Page):
form_model = 'player'
form_fields = ['IRB_yes']

def before_next_page(self):
self.player.exclude_player()
self.participant.vars['instr_start_time'] = int(time.mktime(datetime.datetime.now().timetuple()))

class _IRB_NO(Page):
def is_displayed(self):
return self.player.player_excluded == True

class Basics(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Instructions1(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Instructions2(Page):
def is_displayed(self):
return self.subsession.round_number == 1


class Instructions3(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Instructions4(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Instructions5_video(Page):
def is_displayed(self):
return self.subsession.round_number == 1

def before_next_page(self):
self.participant.vars['quiz_start_time'] = int(time.mktime(datetime.datetime.now().timetuple()))


class Instructions_r2_1(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Instructions_r3_1(Page):
def is_displayed(self):
return self.subsession.round_number == 1

form_model = 'player'
form_fields = ['dynamic_choice']

class Ready1(Page):
def is_displayed(self):
return self.subsession.round_number == 1

def before_next_page(self):
self.participant.vars['instr_end_time'] = int(time.mktime(datetime.datetime.now().timetuple()))


class  Ready2(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class  Ready3(Page):
def is_displayed(self):
return self.subsession.round_number == 1

def vars_for_template(self):
if self.player.dynamic_choice == 1:
format_type = "A"
num_prices = 21
num_seconds = 3
else:
format_type = "B"
num_prices = 11
num_seconds= 6
return dict(
format_type=format_type,
num_prices=num_prices,
num_seconds=num_seconds
)

class Quiz_1(Page):
def is_displayed(self):
return self.round_number == 1

form_model = 'player'
form_fields = ['question1']

def error_message(self, values):
solutions = dict(question1=60)
self.player.quiz_total_errors += 1
return {f: 'This answer is incorrect' for f in solutions if values[f] != solutions[f]}


class Quiz_2(Page):
def is_displayed(self):
return self.round_number == 1

form_model = 'player'
form_fields = ['question2']

def error_message(self, values):
solutions = dict(question2=50)
self.player.quiz_total_errors += 1
return {f: 'This answer is incorrect' for f in solutions if values[f] != solutions[f]}

def before_next_page(self):
self.participant.vars['quiz_end_time'] = int(time.mktime(datetime.datetime.now().timetuple()))


class Decision(Page):
form_model = 'player'
form_fields = [
'selected_price',
'time_period',
'selection_made',
]

def before_next_page(self):
self.player.profit1 = 100-self.player.selected_price


class Decision2(Page):
form_model = 'player'
form_fields = [
'selected_price2',
'time_period2',
'selection_made2',
]

def before_next_page(self):
self.player.profit2 = 100-self.player.selected_price2

class Decision3_10(Page):
def is_displayed(self):
return self.player.dynamic_choice==0

form_model = 'player'
form_fields = [
'selected_price3',
'time_period3',
'selection_made3',
]

def before_next_page(self):
self.player.profit3 = 100-self.player.selected_price3
self.player.determine_task_payoff()

class Decision3_20(Page):
def is_displayed(self):
return self.player.dynamic_choice==1
form_model = 'player'
form_fields = [
'selected_price3',
'time_period3',
'selection_made3',
]

def before_next_page(self):
self.player.profit3 = 100-self.player.selected_price3
self.player.determine_task_payoff()

class Results_r1(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Results_r2(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class Results_r3(Page):
def is_displayed(self):
return self.subsession.round_number == 1

class To_Lotteries(Page):
def is_displayed(self):
return self.round_number == Constants.num_rounds

def vars_for_template(self):
if self.player.round_to_pay ==1:
round_to_pay = "A"
elif self.player.round_to_pay ==2:
round_to_pay = "B"
else:
round_to_pay = "C"
return dict(
round_to_pay = round_to_pay
)

class Lottery_intro(Page):
def is_displayed(self):
return self.round_number == Constants.num_rounds

def before_next_page(self):
self.player.compute_payoff()

def app_after_this_page(self, upcoming_apps):
return upcoming_apps[0]

# ******************************************************************************************************************** #
# *** PAGE SEQUENCE *** #
# ******************************************************************************************************************** #
page_sequence = [_Landing, _IRB_NO, Basics, Emotion, Instructions1, Instructions2, Instructions3, Instructions4, Instructions5_video,
Quiz_1 , Quiz_2, Ready1,
Decision, Emotion2, Results_r1,
Instructions_r2_1, Ready2,
Decision2, Emotion3, Results_r2,
Instructions_r3_1, Ready3,
Decision3_20, Decision3_10, Results_r3,
To_Lotteries, Lottery_intro
]

hale erkan

unread,
Sep 10, 2021, 6:51:49 PM9/10/21
to oTree help & discussion

Hi Chris, 
Do you have any suggestions?
 Thank you 
Hale
Reply all
Reply to author
Forward
0 new messages