模型

一个oTree应用有三个数据模型:子会话,小组与玩家。

玩家是小组的一部分,小组是子会话的一部分。参考 概念总览.

假设你想要你的实验生成下面这样的数据:

name    age is_student
John    30  False
Alice   22  True
Bob     35  False
...

下面的代码展示了如何定义上面的表结构:

class Player(BasePlayer):
    name = models.StringField()
    age = models.IntegerField()
    is_student = models.BooleanField()

所以,一个 模型 实际上就是一张数据库表。一个 字段 就是表中的一列。

字段

字段类型

  • BooleanField (表示 true/false 或者 yes/no 这样的值)
  • CurrencyField 表示货币数量; 参考 货币.
  • IntegerField
  • FloatField (表示实数)
  • StringField (表示字符串)
  • LongStringField (表示长字符串; 它的表单控件是一个多行文本框)

初始/默认值

字段的初始值为 None,除非你设置了 initial=:

class Player(BasePlayer):
    some_number = models.IntegerField(initial=0)

最小值,最大值,可选项

如何设置字段的最小值,最大值与可选项,参考 简单的表单验证.

内置字段与方法

玩家,小组与子会话有一些预定义的字段。举例来说, Playerpayoffid_in_group 字段, in_all_rounds()get_others_in_group() 方法.

这些内置的字段与方法列出如下。

子会话

round_number

给出当前是第几轮。仅在应用有多轮时有意义(轮数由 Constants.num_rounds 设置 )。参考 轮次.

get_groups()

返回一个包含子会话中所有小组的列表。

get_players()

返回一个包含子会话中所有玩家的列表。

玩家

id_in_group

自动被赋值为从1开始的正整数。在多人游戏中,表示哪位是玩家1,哪位是玩家2,诸如此类。

payoff

玩家在本轮的收益。参考 收益.

round_number

Gives the current round number.

会话

num_participants

会话中参与人的数量。

vars

参考 Session fields.

参与人

id_in_session

会话中参与人的ID。这与玩家的 id_in_subsession 相同。

其他参与人属性与方法

常量

Constants 是推荐存放应用的参数或是玩家之间没有区别的常量的地方。

下面是内置的常量:

  • players_per_group ( 小组 中所描述)
  • num_rounds ( 轮次 中所描述)

如果你不想让自己应用的真实名字被显示在URL中,那么可以定义一个字符串常量 name_in_url 并赋予你想显示的名字。

Constants can be numbers, strings, booleans, lists, etc. But for more complex data types like dicts, lists of dicts, etc, you should instead define it in a function. For example, instead of defining a Constant called my_dict, do this:

def my_dict(subsession):
    return dict(a=[1,2], b=[3,4])

杂项

定义你自己的方法

除了本页列出的方法,你可以定义自己的方法。只需记住在 某处 调用它们!仅仅用 def 定义它们是没有任何作用的。

举例来说:

def set_payoffs(group):
    print('in set_payoffs')
    # etc ...

然后如下调用:

class MyWaitPage(WaitPage):
    after_all_players_arrive = 'set_payoffs'

关于使用 random()

Never generate random values outside of a function. For example, don’t do this:

class Constants(BaseConstants):
    p = random.randint(1, 10) # wrong

如果它随机变化,它就不算一个常量。

或者这样的代码:

class Player(BasePlayer):

    p = models.FloatField(
        # wrong
        initial=random.randint(1, 10)
    )

These won’t work because they will change every time the server launches a new process. It may appear to work during testing but will eventually break. Instead, you should generate the random variables inside a function, such as 实验组(Treatments) (and preferably not vars_for_template, which gets re-executed if the user refreshes the page).

如果你想使用自己的随机种子,不要用 random.seed() 函数。而应当生成 random.Random 的实例,如在 这里 所描述的