oTree學習教程(二)Models
Models
models.py
是您定義應用程式資料模型的位置:
- Subsession
- Group
- Player
Player是Group的一部分,這是Subsession的一部分。請參閱概念概述。
主要目的models.py
是定義資料庫表的列。假設您希望實驗生成如下所示的資料:
以下是如何定義上面的表結構:
Defining a column(定義列)
欄位型別
以下是主要的欄位型別:
-
BooleanField
(對於true / false和yes / no值) CurrencyField
貨幣金額; 看貨幣和支付。IntegerField
FloatField
StringField
(用於文字字串)LongStringField
(對於長文字字串;其表單小部件是多行textarea)
StringField
並且LongStringField
是新的(2018年1月新增)。有關更多資訊,請參閱oTree 2.0。
初始/預設值
您的欄位的初始值將是None
,除非您設定initial=
:
最小,最大,選擇
有關如何設定一個欄位的資訊min
,max
或choices
見簡單的表單欄位驗證。
Built-in fields and methods(內建欄位和方法)
定義的欄位和方法。例如,Player
表中有一個名為列payoff
id_in_group
,以及類似的方法in_all_rounds()
和get_others_in_group()
。
下面列出了這些內建欄位和方法。
Subsession
session
本次會話所屬的會話。看什麼是self
round_number
給出當前的輪數。僅當應用程式有多輪(設定Constants.num_rounds
)時才相關。見Rounds。
creating_session()
與大多數其他內建子會話方法不同,此方法是您必須自己定義的方法。您在此處放置的任何程式碼都在建立會話時執行:
creating_session
允許您通過在玩家,組,參與者或子會話的欄位上設定初始值來初始化子級別。例如:
請注意,self
這是一個subsession物件,因為我們在Subsession
類中。所以,你做不到self.player
,因為在subsession中有超過1名玩家。相反,self.get_players()
用來獲取所有這些。
如果您的應用有多輪,則creating_session
連續多次執行:
將輸出
before_session_starts
before_session_starts
已重新命名為creating_session()。但是,before_session_starts
為了向後相容,仍然會執行新版本的oTree 。
group_randomly()
請參閱組匹配。
group_like_round()
請參閱組匹配。
get_group_matrix()
請參閱組匹配。
set_group_matrix()
請參閱組匹配。
get_groups()
返回subsession中所有組的列表。
get_players()
返回subsession中所有玩家的列表。
in_previous_rounds()
in_all_rounds()
in_round(round_number)
in_rounds(self,first,last)
組
會議/子會話
此組所屬的會話/子會話。看什麼是“自我”?。
get_players()
請參閱組。
get_player_by_role(角色)
請參閱組。
get_player_by_id(id_in_group)
請參閱組。
set_players(players_list)
請參閱組匹配。
in_previous_rounds()
in_all_rounds()
in_round(round_number)
in_rounds(self,first,last)
玩家
id_in_group
從1開始自動分配整數。在多人遊戲中,指示這是播放器1,播放器2等。
支付
玩家在這輪中的回報。看到收益。
會話/子會話/組/參與者
此玩家所屬的會話/子會/群組/參與者。看什麼是“自我”?。
get_others_in_group()
請參閱組。
get_others_in_subsession()
請參閱組。
角色()
與大多數其他內建玩家方法不同,這是您自己定義的方法。
此函式應返回帶有玩家角色的標籤,通常取決於id_in_group
。
例如:
然後你可以get_player_by_role('seller')
用來獲得玩家2.見組。
此外,玩家的角色將顯示在oTree管理介面的“結果”選項卡中。
in_previous_rounds()
in_all_rounds()
in_round(round_number)
in_rounds(self,first,last)
會話
NUM_PARTICIPANTS
會議參加人數。
配置
vars
參加者
vars
標籤
請參閱參與者標籤。
id_in_session
會話中的參與者ID。這與玩家的相同 id_in_subsession
。
支付
看到收益。
payoff_plus_participation_fee()
看到收益。
常數
Constants
建議使用該類來放置應用程式的引數和常量,這些引數和常量不會因玩家而異。
以下是必需的常量:
-
name_in_url
:用於在參與者的URL中標識您的應用的名稱。例如,如果將其設定為
public_goods
,參與者的URL可能如下所示:http://otree-demo.herokuapp.com/p/zuzepona/public_goods/Introduction/1/
-
players_per_group
(在小組中描述) -
num_rounds
(在Rounds中描述)
Miscellaneous topics(雜項)
定義自己的方法
您可以在模型上定義自己的方法。這可以幫助您在程式碼變得更復雜時保持程式碼的有序性。例如,您可以定義一個功能來設定玩家的收益:
只需記住從某個地方呼叫此函式,例如您的頁面:
因為它不會被自動執行,不像如內建的功能creating_session()
,after_all_players_arrive()
等等。
oTree如何執行程式碼
任何不在方法內的程式碼基本上都是全域性的,並且只會執行一次 - 當伺服器啟動時。
有些人錯誤地認為程式碼會為每個新會話重新執行。例如,想要生成硬幣翻轉的隨機概率的人可能會在models.py中執行此操作:
從列印輸出中可以看出,p
只計算一次:伺服器啟動時:
這意味著所有會議的所有參與者都是一樣的。
出於同樣的原因,這也不起作用:
“玩家”和“玩家”之間有什麼區別?
在你的程式碼,你應該總是使用小寫player
, group
和subsession
。唯一的例外是在models.py中定義類,您使用class Player(BasePlayer)
的等等。
我們Player
在引用整個玩家表時使用大寫(例如),player
在引用特定玩家時使用小寫(),即表中的一行。在Python中,Player
是一個類,並且player
是該類的例項。
例如,在模板中,為了顯示玩家的收益,我們必須使用{{ player.payoff }}
,而不是{{ Player.payoff }}
。
但是,因為Constants
,我們總是使用大寫。那是因為Constants
不是帶有例項/行的資料庫表,因為所有玩家的常量都是相同的。
IntegerField和Integer有什麼區別?
IntegerField
是資料庫表中的一列。Integer是該表中的一個值。
如何製作多個欄位
假設您的應用有許多幾乎相同的欄位,例如:
這很複雜; 你應該尋找一種簡化方法。
這些欄位是否都顯示在不同的頁面上?如果是這樣,請考慮將其轉換為僅有一個欄位的10輪遊戲。請參閱 真實努力 示例遊戲,瞭解如何讓1個頁面迴圈多輪,改變每輪顯示的問題。
如果那是不可能的,那麼你可以通過定義一個返回欄位的函式來減少重複程式碼的數量(make_field
這只是一個示例名稱;你可以呼叫任何東西)。