Skip to content
/ oTree Public
forked from oTree-org/oTree

Python framework for multiplayer decision games, behavioral experiments, and surveys

License

Notifications You must be signed in to change notification settings

DeSciL/oTree

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oTree

oTree is a Python framework that lets you build:

  • Multiplayer strategy games, like the prisoner's dilemma, public goods game, and auctions
  • Controlled behavioral experiments in economics, psychology, and related fields
  • Surveys and quizzes

Live demo

http://demo.otree.org/

Homepage

http://www.otree.org/

Docs

http://otree.readthedocs.org

Quick start

Rather than cloning this repo directly, run these commands:

pip3 install -U otree
otree startproject oTree
cd oTree
otree devserver

Example game: guess 2/3 of the average

Below is a full implementation of the Guess 2/3 of the average game, where everyone guesses a number, and the winner is the person closest to 2/3 of the average. The game is repeated for 3 rounds. You can play the below game here.

models.py

from otree.api import (
    models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
    Currency
)

class Constants(BaseConstants):
    players_per_group = 3
    num_rounds = 3
    name_in_url = 'guess_two_thirds'

    jackpot = Currency(100)
    guess_max = 100


class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    two_thirds_avg = models.FloatField()
    best_guess = models.IntegerField()
    num_winners = models.IntegerField()

    def set_payoffs(self):
        players = self.get_players()
        guesses = [p.guess for p in players]
        two_thirds_avg = (2 / 3) * sum(guesses) / len(players)
        self.two_thirds_avg = round(two_thirds_avg, 2)

        self.best_guess = min(guesses,
            key=lambda guess: abs(guess - self.two_thirds_avg))

        winners = [p for p in players if p.guess == self.best_guess]
        self.num_winners = len(winners)

        for p in winners:
            p.is_winner = True
            p.payoff = Constants.jackpot / self.num_winners

    def two_thirds_avg_history(self):
        return [g.two_thirds_avg for g in self.in_previous_rounds()]


class Player(BasePlayer):
    guess = models.IntegerField(min=0, max=Constants.guess_max)
    is_winner = models.BooleanField(initial=False)

pages.py

from otree.api import Page, WaitPage


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


class Guess(Page):
    form_model = 'player'
    form_fields = ['guess']


class ResultsWaitPage(WaitPage):
    def after_all_players_arrive(self):
        self.group.set_payoffs()


class Results(Page):
    def vars_for_template(self):
        sorted_guesses = sorted(p.guess for p in self.group.get_players())

        return {'sorted_guesses': sorted_guesses}


page_sequence = [Introduction,
                 Guess,
                 ResultsWaitPage,
                 Results]

HTML templates

Instructions.html Introduction.html Guess.html Results.html

tests.py (optional)

Test bots for multiplayer games run in parallel, and can run either from the command line, or in the browser, which you can try here.

from otree.api import Bot, SubmissionMustFail
from . import pages
from .models import Constants

class PlayerBot(Bot):
    cases = ['p1_wins', 'p1_and_p2_win']

    def play_round(self):
        if self.round_number == 1:
            yield (pages.Introduction)

        if self.case == 'p1_wins':
            if self.player.id_in_group == 1:
                for invalid_guess in [-1, 101]:
                    yield SubmissionMustFail(pages.Guess, {"guess": invalid_guess})
                yield (pages.Guess, {"guess": 9})
                assert self.player.payoff == Constants.jackpot
                assert 'you win' in self.html
            else:
                yield (pages.Guess, {"guess": 10})
                assert self.player.payoff == 0
                assert 'you did not win' in self.html
        else:
            if self.player.id_in_group in [1, 2]:
                yield (pages.Guess, {"guess": 9})
                assert self.player.payoff == Constants.jackpot / 2
                assert 'you are one of the 2 winners' in self.html
            else:
                yield (pages.Guess, {"guess": 10})
                assert self.player.payoff == 0
                assert 'you did not win' in self.html

        yield (pages.Results)

See docs on bots.

Features

  • Easy-to-use admin interface for launching games & surveys, managing participants, monitoring data, etc.
  • Simple yet extensive API
  • Publish your games to Amazon Mechanical Turk

Contact & support

Help & discussion mailing list

Contact [email protected] with bug reports.

Related repositories

The oTree core libraries are here.

About

Python framework for multiplayer decision games, behavioral experiments, and surveys

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 59.3%
  • HTML 40.5%
  • CSS 0.2%