Getting Started¶
Gotchas¶
otree-redwood currently only works with python3 and Google Chrome. We have long term plans to add support for other browsers, but for now only google chrome will work correctly
Redwood has not been tested on Windows. There’s no reason it shouldn’t work, but you may have some troubles, particularly with the virtual environment
- Consider using the Windows Subsystem for Linux. This will give you an Ubuntu-like environment on Windows and may make installation easier. You can find instructions for that on the Microsoft website here
If you see an error that looks like error: Python.h: No such file or directory, you need to install the Python development libraries. These should be included on OS X. On Linux, you can install them with your package manager, for example:
sudo apt-get install python3-dev
If your Redwood experiment generates a large number of messages, you may get warnings from oTree about sqlite running out of connections. The solution to this problem is to use a fully featured database such as Postgres. Instructions for integrating Postgres with oTree can be found in the oTree docs
Installing otree-redwood¶
- (Optional) Create and activate a python virtual environment to manage otree’s python dependencies:
python3 -m venv venv source venv/bin/activateVirtual environments allow you to isolate your project’s dependencies from your main python installation. Read more about virtual environments here
- Use pip to install the otree-redwood library and the LEEPS fork of otree-core:
pip install otree-redwood git+https://github.com/leeps-lab/otree-core
- Start a new oTree project:
otree startproject oTree cd oTree
- Save current versions of all dependencies in a requirements file so they can be quickly installed later:
pip freeze > requirements_base.txtYou can reinstall these dependencies later with
pip install -r requirements_base.txt
- Update INSTALLED_APPS and EXTENSION_APPS in your settings.py
... INSTALLED_APPS = ['otree', 'django_extensions'] EXTENSION_APPS = ['otree_redwood'] ...
- Create a new oTree experiment:
otree startapp my_experiment
- Use the otree-redwood classes in your experiment’s models.py file:
Instead of extending otree.api.BaseGroup, your Group class extends one of the otree-redwood Groups - Base Group or DecisionGroup. Your Group class needs a
period_lengthfunction. This is similar to oTree’stimeout_secondsvariable. When the period timer expires players will be automatically moved to the next page.You still extend otree.api.BasePlayer, but your Player class needs an
initial_decisionfunction. This is the decision the player starts with. You can let the player choose their initial decision with a normal oTree page.from otree_redwood.models import Event, DecisionGroup class Group(DecisionGroup): def period_length(self): return Constants.period_length class Player(BasePlayer): def initial_decision(self): return 0.5
- Use the otree-redwood web components in one of your experiments HTML templates.
Make sure your template inherits from “otree_redwood/Page.html” instead of the usual “global/Page.html”. This is required for the otree-constants webcomponent to work correctly.
An example minimal otree_redwood template:
{% extends "otree_redwood/Page.html" %} {% block scripts %} <!-- Import the redwood-decision and redwood-period webcomponents. --> <link rel="import" href="/static/otree-redwood/webcomponents/redwood-decision/redwood-decision.html"> <link rel="import" href="/static/otree-redwood/webcomponents/redwood-period/redwood-period.html"> <script> // Get the decision component and other-decision element. var decision = document.querySelector("redwood-decision"); var otherDecision = document.getElementById("other-decision"); // Log period start/end to the JavaScript console. document.querySelector("redwood-period").addEventListener('period-start', function(event) { console.log('period started'); }); document.querySelector("redwood-period").addEventListener('period-end', function(event) { console.log('period ended'); }); // When group decisions changes, update the text of the otherDecision element. decision.addEventListener('group-decisions-changed', function(event) { otherDecision.innerText = decision.otherDecision; }); // Attach this to a button onclick event to set your decision when the button is clicked. function setDecision(d) { decision.myDecision = d; } </script> {% endblock %} {% block content %} <!-- Include the components on the page --> <redwood-period></redwood-period> <redwood-decision></redwood-decision> <p>Other Decision: <span id="other-decision"></span></p> <button type="button" onclick="setDecision(0)">Decision=0</button> <button type="button" onclick="setDecision(1)">Decision=1</button> {% endblock %}