小组

你可以在多人游戏中将玩家分为多个小组。(如果你只是需要报酬意义上的分组,组内玩家并不真的产生交互,那么参考 实验组(Treatments).)

要设置每组的人数,前往Constants并设置 players_per_group 变量即可.举例来说,对于2人游戏,设置 players_per_group = 2.

如果所有玩家均在同一组内,或者这是一个单人游戏,将其设为 None:

每名玩家均有一个 id_in_group 属性,这一属性告诉你这是玩家 1,玩家 2,诸如此类。

获得玩家

小组对象有下面这些方法:

get_players()

返回组内玩家的列表(按照 id_in_group 排序)。

get_player_by_id(n)

返回组内具有所指定 id_in_group 的玩家。

获得其他玩家

玩家对象有 get_others_in_group()get_others_in_subsession() 方法,分别返回同一小组与子会话中的 其他 玩家的列表。

Roles

注解

New as of January 2021

If each group has multiple roles, such as buyer/seller, principal/agent, etc., you can define them in Constants. Make their names end with _role:

class Constants(BaseConstants):
    ...

    principal_role = 'Principal'
    agent_role = 'Agent

oTree will then automatically assign each role to a different player (sequentially according to id_in_group). You can use this to show each role different content, e.g.:

class AgentPage(Page):

    @staticmethod
    def is_displayed(player):
        return player.role == Constants.agent_role

然后在模板中:

You are the {{ player.role }}.

You can also use group.get_player_by_role(), which is similar to get_player_by_id():

def set_payoffs(group):
    principal = group.get_player_by_role(Constants.principal_role)
    agent = group.get_player_by_role(Constants.agent_role)
    # ...

If you want to switch players’ roles, you should rearrange the groups, using group.set_players(), subsession.group_randomly(), etc.

小组配对

固定配对

默认情况下,每一轮中,每位玩家被分为数个小组,每组人数为 Constants.players_per_group.分组是按照顺序进行的——举例来说,如果2人一组,那么玩家1与玩家2就会被分为一组,然后是玩家3与玩家4被分为一组,以此类推。 id_in_group 也在每组中被顺序分配。

这意味着默认情况下,每一轮中分组是相同的,甚至在不同应用之间均有相同的 players_per_group.

如果你想重新安排小组,你可以使用下面的技巧。

group_randomly()

子会话有一个 group_randomly() 方法可以随机排列玩家,此时玩家被随机分配在任一小组的任一位置。

如果你想要在不同小组间随机安排玩家但保持玩家的角色不变,使用 group_randomly(fixed_id_in_group=True).

举例来说,下面的代码会使玩家在每一轮之间随机组队:

def creating_session(subsession):
    subsession.group_randomly()

下面的代码让玩家在每一轮之间随机组队,但是保持 id_in_group 不变:

def creating_session(subsession):
    subsession.group_randomly(fixed_id_in_group=True)

下面的例子中,假定 players_per_group = 3, 并且会话中共有12名参与者:

def creating_session(subsession):
    print(subsession.get_group_matrix()) # outputs the following:
    # [[<Player  1>, <Player  2>, <Player  3>],
    #  [<Player  4>, <Player  5>, <Player  6>],
    #  [<Player  7>, <Player  8>, <Player  9>],
    #  [<Player 10>, <Player 11>, <Player 12>]]

    subsession.group_randomly(fixed_id_in_group=True)
    print(subsession.get_group_matrix()) # outputs the following:
    # [[<Player  1>, <Player  8>, <Player 12>],
    #  [<Player 10>, <Player  5>, <Player  3>],
    #  [<Player  4>, <Player  2>, <Player  6>],
    #  [<Player  7>, <Player 11>, <Player  9>]]

    subsession.group_randomly()
    print(subsession.get_group_matrix()) # outputs the following:
    # [[<Player  8>, <Player 10>, <Player  3>],
    #  [<Player  4>, <Player 11>, <Player  2>],
    #  [<Player  9>, <Player  1>, <Player  6>],
    #  [<Player 12>, <Player  5>, <Player  7>]]

group_like_round()

在不同轮之间复制小组的结构,可使用 group_like_round(n) 方法。方法中的参数即小组结构被复制的那一轮的轮次。

在下面的例子中,第一轮将随机组队,后面的轮次均复制第一轮的小组结构。

def creating_session(subsession):
    if subsession.round_number == 1:
        # <some shuffling code here>
    else:
        subsession.group_like_round(1)

get_group_matrix()

Subsessions have a method called get_group_matrix() that return the structure of groups as a matrix, for example:

[[1, 3, 5],
 [7, 9, 11],
 [2, 4, 6],
 [8, 10, 12]]

set_group_matrix()

set_group_matrix() lets you modify the group structure in any way you want. First, get the list of players with get_players(), or the pre-existing group matrix with get_group_matrix(). Make your matrix then pass it to set_group_matrix():

def creating_session(subsession):
    matrix = subsession.get_group_matrix()

    for row in matrix:
        row.reverse()

    # now the 'matrix' variable looks like this,
    # but it hasn't been saved yet!
    # [[<Player  3>, <Player  2>, <Player  1>],
    #  [<Player  6>, <Player  5>, <Player  4>],
    #  [<Player  9>, <Player  8>, <Player  7>],
    #  [<Player 12>, <Player 11>, <Player 10>]]

    # save it
    subsession.set_group_matrix(matrix)

你也可以传递一个整数矩阵。整数矩阵中必须包含从1到子会话中的玩家数量的所有整数。每一个整数代表 id_in_subsession 为此整数的玩家。举例如下:

def creating_session(subsession):

    new_structure = [[1,3,5], [7,9,11], [2,4,6], [8,10,12]]
    subsession.set_group_matrix(new_structure)

    print(subsession.get_group_matrix()) # will output this:

    # [[<Player  1>, <Player  3>, <Player  5>],
    #  [<Player  7>, <Player  9>, <Player 11>],
    #  [<Player  2>, <Player  4>, <Player  6>],
    #  [<Player  8>, <Player 10>, <Player 12>]]

为了检查小组重排是否工作正常,打开浏览器并切换到你的会话的”Results”选项卡,并检查每一轮中的 groupid_in_group 两栏是否正确。

group.set_players()

This is similar to set_group_matrix, but it only shuffles players within a group, e.g. so that you can give them different roles.

在会话中重排小组

creating_session 通常是重排小组的好地方,但是 creating_session 是在会话创建前运行,即玩家开始行动之前。所以如果你的重排逻辑需要依赖于会话开始后的因素,你应当在等待页面重排。

假定你在子会话中定义了一个方法,名为 do_my_shuffle() ,它使用了 set_group_matrix ,诸如此类。

你需要创建一个 WaitPage 且在其中设定 wait_for_all_groups=True 并将重排的代码放入 after_all_players_arrive 中:

class ShuffleWaitPage(WaitPage):
    wait_for_all_groups = True
    after_all_players_arrive = 'do_my_shuffle'

按照到达时间组队

参考 group_by_arrival_time.