From 48759429d3d43ad40d18ba8cf54ba5579b8754c0 Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 11:35:08 +0200 Subject: [PATCH 1/8] Change player names in HTML --- introduction/Coalitions.html | 20 +++++++------- introduction/Proposal.html | 18 ++++++------- introduction/__init__.py | 8 ++++++ live_bargaining/Bargain.html | 24 ++++++++--------- live_bargaining/BargainingResults.html | 12 ++++----- live_bargaining/Info.html | 2 +- live_bargaining/__init__.py | 8 +++++- settings.py | 36 ++++++++++++++++++++------ 8 files changed, 81 insertions(+), 47 deletions(-) diff --git a/introduction/Coalitions.html b/introduction/Coalitions.html index 7a80213..d57fa7b 100644 --- a/introduction/Coalitions.html +++ b/introduction/Coalitions.html @@ -28,7 +28,7 @@

Group formation

All other players get 0. If there is no such agreement, all three players get 0.

-

Note that because Player 1 has to be included for a group to receive a budget, there will be one group at most.

+

Note that because Player {{P1}} has to be included for a group to receive a budget, there will be one group at most.


@@ -67,9 +67,9 @@

All proposals

ID From - P1 - P2 - P3 + {{P1}} + {{P2}} + {{P3}} @@ -84,9 +84,9 @@

Choose a proposal

- Player 1 - Player 2 - Player 3 + Player {{P1}} + Player {{P2}} + Player {{P3}} Accepted proposal ID @@ -149,9 +149,9 @@

Currently accepted proposal

- Player 1 - Player 2 - Player 3 + Player {{P1}} + Player {{P2}} + Player {{P3}} Accept proposal ID diff --git a/introduction/Proposal.html b/introduction/Proposal.html index b74b200..cca0107 100644 --- a/introduction/Proposal.html +++ b/introduction/Proposal.html @@ -14,18 +14,18 @@

Group budgets

- You and the two other players will each be randomly assigned a player number ("Player 1/2/3"). + You and the two other players will each be randomly assigned a player role ({{P1}}, {{P2}}, {{P3}}). The player numbers will be reshuffled each round.

- A group needs to include Player 1 to receive any budget. + A group needs to include Player {{P1}} to receive any budget. The more members a group has, the bigger the budget. For the exact size of the budget in CHF, you will see a table and a corresponding graph like the one below ("Group budgets").

-

For example, if Player 1 and one other player form a group together, they have a budget of 50 CHF. If all players form a group together, they have a budget of 100 CHF. (The exact numbers might be different in the game.)

+

For example, if Player {{P1}} and one other player form a group together, they have a budget of 50 CHF. If all players form a group together, they have a budget of 100 CHF. (The exact numbers might be different in the game.)

@@ -113,9 +113,9 @@

Past proposals

ID From - P1 - P2 - P3 + {{P1}} + {{P2}} + {{P3}} @@ -132,9 +132,9 @@

Make a proposal

- Player 1 - Player 2 - Player 3 + Player {{P1}} + Player {{P2}} + Player {{P3}} Total diff --git a/introduction/__init__.py b/introduction/__init__.py index 5d97b1e..5205419 100644 --- a/introduction/__init__.py +++ b/introduction/__init__.py @@ -41,6 +41,10 @@ def js_vars(player: Player): my_id=1, ) + @staticmethod + def vars_for_template(subsession): + return subsession.session.config["player_names"] + class Coalitions(Page): @staticmethod @@ -49,6 +53,10 @@ def js_vars(player: Player): my_id=1, ) + @staticmethod + def vars_for_template(subsession): + return subsession.session.config["player_names"] + class Payment(Page): pass diff --git a/live_bargaining/Bargain.html b/live_bargaining/Bargain.html index 93f792b..528631b 100644 --- a/live_bargaining/Bargain.html +++ b/live_bargaining/Bargain.html @@ -15,13 +15,13 @@ - This is round {{ actual_round_number }}. You are Player {{ player.id_in_group }}. + This is round {{ actual_round_number }}. You are Player {{ player_name }}. {{ if subsession.round_number == 1 }} @@ -85,9 +85,9 @@

Past proposals

ID From - P1 - P2 - P3 + {{P1}} + {{P2}} + {{P3}} @@ -104,9 +104,9 @@

Make a proposal

- Player 1 - Player 2 - Player 3 + Player {{P1}} + Player {{P2}} + Player {{P3}} Total @@ -142,9 +142,9 @@

Currently accepted proposal

- Player 1 - Player 2 - Player 3 + Player {{P1}} + Player {{P2}} + Player {{P3}} Accepted proposal ID diff --git a/live_bargaining/BargainingResults.html b/live_bargaining/BargainingResults.html index b3589a7..d140251 100644 --- a/live_bargaining/BargainingResults.html +++ b/live_bargaining/BargainingResults.html @@ -17,9 +17,9 @@

Accepted proposals

- Player 1 - Player 2 - Player 3 + Player {{P1}} + Player {{P2}} + Player {{P3}} Accepted proposal ID @@ -45,9 +45,9 @@

All proposals

ID From - P1 - P2 - P3 + {{P1}} + {{P2}} + {{P3}} diff --git a/live_bargaining/Info.html b/live_bargaining/Info.html index 05ed712..d048c12 100644 --- a/live_bargaining/Info.html +++ b/live_bargaining/Info.html @@ -20,7 +20,7 @@

In this round, unlike in previous rounds, adding Player 5 has no impact on the budget.

{{ endif }} -

In this round you are Player {{ player.id_in_group }}.

+

In this round you are Player {{ player_name }}.

Remember, payoffs are determined as follows:
diff --git a/live_bargaining/__init__.py b/live_bargaining/__init__.py index 6dccf97..ed38e2e 100644 --- a/live_bargaining/__init__.py +++ b/live_bargaining/__init__.py @@ -246,7 +246,10 @@ def create_acceptance_data(group: Group): class Info(Page): @staticmethod def vars_for_template(player: Player): - return dict(actual_round_number=player.subsession.round_number - 1) + return dict( + actual_round_number=player.subsession.round_number - 1, + player_name=player.session.config["player_names"][f"P{player.id_in_group}"], + ) @staticmethod def js_vars(player: Player): @@ -286,7 +289,9 @@ def vars_for_template(player: Player): return dict( last_player_is_dummy=len(player.session.config["prod_fct"]) == C.PLAYERS_PER_GROUP - 1, + player_name=player.session.config["player_names"][f"P{player.id_in_group}"], actual_round_number=player.subsession.round_number - 1, + **player.session.config["player_names"], ) @staticmethod @@ -383,6 +388,7 @@ def js_vars(player: Player): def vars_for_template(player: Player): return dict( payoff_to_display=f"CHF {player.payoff_this_round:.2f}", + **player.session.config["player_names"], ) diff --git a/settings.py b/settings.py index c706e3b..c2a47d7 100644 --- a/settings.py +++ b/settings.py @@ -13,10 +13,15 @@ num_demo_participants=3, seconds_per_round=5 * 60, prod_fct={ - "{P2,\xa0P3}": 0, - "{P1,\xa0P2},\n{P1,\xa0P3}": 10, + "{B1,\xa0B2}": 0, + "{A,\xa0B1},\n{A,\xa0B2}": 10, "Everyone": 100, }, + player_names={ + "P1": "A", + "P2": "B1", + "P3": "B2", + }, doc="Treatment with production function [0, 10, 100]", ), dict( @@ -26,10 +31,15 @@ num_demo_participants=3, seconds_per_round=5 * 60, prod_fct={ - "{P2,\xa0P3}": 0, - "{P1,\xa0P2}, {P1,\xa0P3}": 30, + "{B1,\xa0B2}": 0, + "{A,\xa0B1}, {A,\xa0B2}": 30, "Everyone": 100, }, + player_names={ + "P1": "A", + "P2": "B1", + "P3": "B2", + }, doc="Treatment with production function [0, 30, 100]", ), dict( @@ -39,10 +49,15 @@ num_demo_participants=3, seconds_per_round=5 * 60, prod_fct={ - "{P2,\xa0P3}": 0, - "{P1,\xa0P2}, {P1,\xa0P3}": 90, + "{B1,\xa0B2}": 0, + "{A,\xa0B1}, {A,\xa0B2}": 90, "Everyone": 100, }, + player_names={ + "P1": "A", + "P2": "B1", + "P3": "B2", + }, doc="Treatment with production function [0, 90, 100]", ), dict( @@ -52,8 +67,13 @@ num_demo_participants=3, seconds_per_round=5 * 60, prod_fct={ - "{P1,\xa0P3}, {P2,\xa0P3}": 0, - "{P1,\xa0P2}, Everyone": 100, + "{A1,\xa0B}, {A2,\xa0B}": 0, + "{A1,\xa0A2}, Everyone": 100, + }, + player_names={ + "P1": "A1", + "P2": "A2", + "P3": "B", }, doc="Treatment with production function [0, 100] and P3 as dummy player", ), From 3b30f9d289f65f312331e73547a5c31fe2d64c68 Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 11:38:16 +0200 Subject: [PATCH 2/8] Change player names in chat --- _static/live_bargaining.css | 2 +- live_bargaining/Bargain.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_static/live_bargaining.css b/_static/live_bargaining.css index f4d8eb2..6b752be 100644 --- a/_static/live_bargaining.css +++ b/_static/live_bargaining.css @@ -118,7 +118,7 @@ table.shaded-rows tbody tr:nth-child(odd) { } .otree-chat__nickname { - width: 120px; + width: 70px; } #payoff-table { diff --git a/live_bargaining/Bargain.html b/live_bargaining/Bargain.html index 528631b..8de1049 100644 --- a/live_bargaining/Bargain.html +++ b/live_bargaining/Bargain.html @@ -74,7 +74,7 @@

Chat

- {{ chat nickname=player.role }} + {{ chat nickname=player_name }}
From b528b1706b3c6157112340f0c26958e0850439c4 Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 11:46:16 +0200 Subject: [PATCH 3/8] Change player names in JS --- _static/accept.js | 3 ++- _static/coalitions_demo.js | 4 +++- _static/live_bargaining.js | 3 ++- _static/proposal_demo.js | 3 ++- introduction/__init__.py | 2 ++ live_bargaining/__init__.py | 2 ++ 6 files changed, 13 insertions(+), 4 deletions(-) diff --git a/_static/accept.js b/_static/accept.js index ea921ff..2e0c83c 100644 --- a/_static/accept.js +++ b/_static/accept.js @@ -1,4 +1,5 @@ let numPlayers = 3; +let player_names = js_vars.player_names; let pastOffersTable = document.getElementById('past-offers-table'); @@ -12,7 +13,7 @@ function populatePastOffers(pastOffers) { let from = row.insertCell(); from.className = "offer-proposer-col"; - from.innerHTML = `P${offer.player}`; + from.innerHTML = player_names[`P${offer.player}`]; for (let i = 0; i < numPlayers; i++) { let cell = row.insertCell(); diff --git a/_static/coalitions_demo.js b/_static/coalitions_demo.js index 760f271..42253bb 100644 --- a/_static/coalitions_demo.js +++ b/_static/coalitions_demo.js @@ -1,5 +1,7 @@ let numPlayers = 3; +let player_names = js_vars.player_names; + let totalShareable = document.getElementById('total-shareable'); let totalShared = document.getElementById('total-shared'); @@ -101,7 +103,7 @@ function updatePastOffers(newPastOffers) { let from = row.insertCell(); from.className = "offer-proposer-col"; - from.innerHTML = `P${offer.player}`; + from.innerHTML = player_names[`P${offer.player}`]; for (let i = 0; i < numPlayers; i++) { let cell = row.insertCell(); diff --git a/_static/live_bargaining.js b/_static/live_bargaining.js index be60151..e9a0d7e 100644 --- a/_static/live_bargaining.js +++ b/_static/live_bargaining.js @@ -21,6 +21,7 @@ let pastOffers = [] let prod_fct = js_vars.prod_fct; let prod_fct_labels = js_vars.prod_fct_labels; let lastPlayerIsDummy = prod_fct.length == numPlayers - 1; +let player_names = js_vars.player_names; let popupFull = document.getElementById('popup-full'); let popupTitle = document.getElementById('popup-title'); @@ -184,7 +185,7 @@ function updatePastOffers(newPastOffers) { let from = row.insertCell(); from.className = "offer-proposer-col"; - from.innerHTML = `P${offer.player}`; + from.innerHTML = player_names[`P${offer.player}`]; for (let i = 0; i < numPlayers; i++) { let cell = row.insertCell(); diff --git a/_static/proposal_demo.js b/_static/proposal_demo.js index 2e08f09..4aece75 100644 --- a/_static/proposal_demo.js +++ b/_static/proposal_demo.js @@ -19,6 +19,7 @@ let pastOffers = [] let prod_fct = js_vars.prod_fct; let prod_fct_labels = js_vars.prod_fct_labels; let lastPlayerIsDummy = prod_fct.length == numPlayers - 1; +let player_names = js_vars.player_names; let popupFull = document.getElementById('popup-full'); let popupTitle = document.getElementById('popup-title'); @@ -151,7 +152,7 @@ function updatePastOffers(newPastOffers) { let from = row.insertCell(); from.className = "offer-proposer-col"; - from.innerHTML = `P${offer.player}`; + from.innerHTML = player_names[`P${offer.player}`]; for (let i = 0; i < numPlayers; i++) { let cell = row.insertCell(); diff --git a/introduction/__init__.py b/introduction/__init__.py index 5205419..a7e7375 100644 --- a/introduction/__init__.py +++ b/introduction/__init__.py @@ -39,6 +39,7 @@ def js_vars(player: Player): prod_fct=list(player.session.config["prod_fct"].values()), prod_fct_labels=list(player.session.config["prod_fct"].keys()), my_id=1, + player_names=player.session.config["player_names"], ) @staticmethod @@ -51,6 +52,7 @@ class Coalitions(Page): def js_vars(player: Player): return dict( my_id=1, + player_names=player.session.config["player_names"], ) @staticmethod diff --git a/live_bargaining/__init__.py b/live_bargaining/__init__.py index ed38e2e..1647078 100644 --- a/live_bargaining/__init__.py +++ b/live_bargaining/__init__.py @@ -282,6 +282,7 @@ def js_vars(player: Player): my_id=player.id_in_group, prod_fct=list(player.session.config["prod_fct"].values()), prod_fct_labels=list(player.session.config["prod_fct"].keys()), + player_names=player.session.config["player_names"], ) @staticmethod @@ -382,6 +383,7 @@ def js_vars(player: Player): acceptances=acceptance_data["acceptances"], coalition_members=acceptance_data["coalition_members"], payoffs=acceptance_data["payoffs"], + player_names=player.session.config["player_names"], ) @staticmethod From 381e39b46b0d60529d2907560da498c27b5cb76b Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 11:53:19 +0200 Subject: [PATCH 4/8] Make pyright happy --- introduction/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/introduction/__init__.py b/introduction/__init__.py index a7e7375..56067b8 100644 --- a/introduction/__init__.py +++ b/introduction/__init__.py @@ -43,7 +43,7 @@ def js_vars(player: Player): ) @staticmethod - def vars_for_template(subsession): + def vars_for_template(subsession: BaseSubsession): # type: ignore return subsession.session.config["player_names"] @@ -56,7 +56,7 @@ def js_vars(player: Player): ) @staticmethod - def vars_for_template(subsession): + def vars_for_template(subsession: BaseSubsession): # type: ignore return subsession.session.config["player_names"] From 5172707498f0e1b726f89c73a93588a054741fe7 Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 11:59:00 +0200 Subject: [PATCH 5/8] Make pyright happier --- introduction/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/introduction/__init__.py b/introduction/__init__.py index 56067b8..c753778 100644 --- a/introduction/__init__.py +++ b/introduction/__init__.py @@ -43,8 +43,8 @@ def js_vars(player: Player): ) @staticmethod - def vars_for_template(subsession: BaseSubsession): # type: ignore - return subsession.session.config["player_names"] + def vars_for_template(player: Player): + return player.session.config["player_names"] class Coalitions(Page): @@ -56,8 +56,8 @@ def js_vars(player: Player): ) @staticmethod - def vars_for_template(subsession: BaseSubsession): # type: ignore - return subsession.session.config["player_names"] + def vars_for_template(player: Player): + return player.session.config["player_names"] class Payment(Page): From 3b6518ff5b82d1cddcf3d97c77b94c7173dfd140 Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 12:09:42 +0200 Subject: [PATCH 6/8] Remove remaining Player 1 mentions --- _static/live_bargaining.js | 2 +- _static/proposal_demo.js | 2 +- live_bargaining/__init__.py | 6 +----- live_bargaining/tests.py | 7 ++++--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/_static/live_bargaining.js b/_static/live_bargaining.js index e9a0d7e..6d0c0f4 100644 --- a/_static/live_bargaining.js +++ b/_static/live_bargaining.js @@ -69,7 +69,7 @@ for (let i = 0; i < numPlayers; i++) { function sendOffer() { if (totalSharedValue > 0 && !isMemberCheckboxes[0].checked) { - openPopup('Invalid proposal: the budget is zero when Player 1 is not included in the group', 'error'); + openPopup(`Invalid proposal: the budget is zero when Player ${player_names['P1']} is not included in the group`, 'error'); return; } if (totalSharedValue > totalShareableValue) { diff --git a/_static/proposal_demo.js b/_static/proposal_demo.js index 4aece75..77f9c5a 100644 --- a/_static/proposal_demo.js +++ b/_static/proposal_demo.js @@ -92,7 +92,7 @@ function sendOffer() { }; if (totalSharedValue > 0 && !members[0]) { - openPopup('Invalid proposal: the budget is zero when Player 1 is not included in the group', 'error'); + openPopup(`Invalid proposal: the budget is zero when Player ${player_names['P1']} is not included in the group`, 'error'); return; } if (totalSharedValue > totalShareableValue) { diff --git a/live_bargaining/__init__.py b/live_bargaining/__init__.py index 1647078..9be9387 100644 --- a/live_bargaining/__init__.py +++ b/live_bargaining/__init__.py @@ -45,10 +45,6 @@ class C(BaseConstants): PLAYERS_PER_GROUP = 3 NUM_ROUNDS = 5 # todo: adjust for main experiment - BIG_ROLE = "Player 1" - SMALL1_ROLE = "Player 2" - SMALL2_ROLE = "Player 3" - class Subsession(BaseSubsession): start_time = models.FloatField(initial=float("inf")) # type: ignore @@ -183,7 +179,7 @@ def check_proposal_validity(player: Player, members, allocations): return { player.id_in_group: { "type": "error", - "content": "Invalid allocation: allocation has to be zero when Player 1 is not included", # noqa: E501 + "content": f"Invalid allocation: allocation has to be zero when Player {player.session.config['player_names']['P1']} is not included", # noqa: E501 } } diff --git a/live_bargaining/tests.py b/live_bargaining/tests.py index cc904a6..69ac4c4 100644 --- a/live_bargaining/tests.py +++ b/live_bargaining/tests.py @@ -39,7 +39,7 @@ def create_offers(method, Y): ) -def test_invalid_input(method, Y, dummy_player=False): +def test_invalid_input(method, Y, dummy_player, P1_name): non_existing_offer = method(1, {"type": "accept", "offer_id": 1}) expect( non_existing_offer, @@ -96,7 +96,7 @@ def test_invalid_input(method, Y, dummy_player=False): { 3: { "type": "error", - "content": "Invalid allocation: allocation has to be zero when Player 1 is not included", + "content": f"Invalid allocation: allocation has to be zero when Player {P1_name} is not included", } }, ) @@ -179,12 +179,13 @@ def call_live_method(method, **kwargs): ) prod_fct = kwargs["group"].session.config["prod_fct"] + P1_name = kwargs["group"].session.config["player_names"]["P1"] Y = list(prod_fct.values())[1] dummy_player = len(prod_fct) == 2 if kwargs["round_number"] == 1: print("Testing invalid input") - test_invalid_input(method, Y, dummy_player) + test_invalid_input(method, Y, dummy_player, P1_name) if kwargs["round_number"] == 2: print("Testing grand coalition") From dbbd5f130ca8e6611dd89a47a3b87acf07b35b1b Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 14:28:34 +0200 Subject: [PATCH 7/8] Better error message for the dummy player case --- _static/live_bargaining.js | 6 +++++- _static/proposal_demo.js | 6 +++++- live_bargaining/__init__.py | 27 ++++++++++++++++++++++--- live_bargaining/tests.py | 39 ++++++++++++++++++++++++------------- 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/_static/live_bargaining.js b/_static/live_bargaining.js index 6d0c0f4..b72bf68 100644 --- a/_static/live_bargaining.js +++ b/_static/live_bargaining.js @@ -68,10 +68,14 @@ for (let i = 0; i < numPlayers; i++) { } function sendOffer() { - if (totalSharedValue > 0 && !isMemberCheckboxes[0].checked) { + if (!lastPlayerIsDummy && totalSharedValue > 0 && !isMemberCheckboxes[0].checked) { openPopup(`Invalid proposal: the budget is zero when Player ${player_names['P1']} is not included in the group`, 'error'); return; } + if (lastPlayerIsDummy && totalSharedValue > 0 && !(isMemberCheckboxes[0].checked && isMemberCheckboxes[1].checked)) { + openPopup(`Invalid proposal: the budget is zero when Players ${player_names['P1']} and ${player_names['P2']} are not included in the group`, 'error'); + return; + } if (totalSharedValue > totalShareableValue) { openPopup('Invalid proposal: total amount exceeds the budget available to this group', 'error'); return; diff --git a/_static/proposal_demo.js b/_static/proposal_demo.js index 77f9c5a..8d98390 100644 --- a/_static/proposal_demo.js +++ b/_static/proposal_demo.js @@ -91,10 +91,14 @@ function sendOffer() { 'allocations': allocations, }; - if (totalSharedValue > 0 && !members[0]) { + if (!lastPlayerIsDummy && totalSharedValue > 0 && !isMemberCheckboxes[0].checked) { openPopup(`Invalid proposal: the budget is zero when Player ${player_names['P1']} is not included in the group`, 'error'); return; } + if (lastPlayerIsDummy && totalSharedValue > 0 && !(isMemberCheckboxes[0].checked && isMemberCheckboxes[1].checked)) { + openPopup(`Invalid proposal: the budget is zero when Players ${player_names['P1']} and ${player_names['P2']} are not included in the group`, 'error'); + return; + } if (totalSharedValue > totalShareableValue) { openPopup('Invalid proposal: total amount exceeds the budget available to this group', 'error'); return; diff --git a/live_bargaining/__init__.py b/live_bargaining/__init__.py index 9be9387..c10a50a 100644 --- a/live_bargaining/__init__.py +++ b/live_bargaining/__init__.py @@ -175,16 +175,37 @@ def check_proposal_validity(player: Player, members, allocations): } } - if not big_player_included and sum(allocations) > 0: + last_player_is_dummy = len(prod_fct) == C.PLAYERS_PER_GROUP - 1 + + if not last_player_is_dummy and not big_player_included and sum(allocations) > 0: + return { + player.id_in_group: { + "type": "error", + "content": ( + "Invalid allocation: allocation has to be zero when " + f"Player {player.session.config['player_names']['P1']} is not included" + ), + } + } + + if ( + last_player_is_dummy + and not (members[0] and members[1]) + and sum(allocations) > 0 + ): return { player.id_in_group: { "type": "error", - "content": f"Invalid allocation: allocation has to be zero when Player {player.session.config['player_names']['P1']} is not included", # noqa: E501 + "content": ( + "Invalid allocation: allocation has to be zero when Players " + f"{player.session.config['player_names']['P1']} and " + f"{player.session.config['player_names']['P2']} are not included" + ), } } num_small_players = coalition_size - big_player_included - if len(prod_fct) == C.PLAYERS_PER_GROUP - 1: # last player is a dummy player + if last_player_is_dummy: # last player is a dummy player num_small_players -= members[-1] # the dummy player is always last if sum(allocations) > prod_fct[num_small_players]: diff --git a/live_bargaining/tests.py b/live_bargaining/tests.py index 69ac4c4..cb99239 100644 --- a/live_bargaining/tests.py +++ b/live_bargaining/tests.py @@ -39,7 +39,7 @@ def create_offers(method, Y): ) -def test_invalid_input(method, Y, dummy_player, P1_name): +def test_invalid_input(method, Y, dummy_player, player_names): non_existing_offer = method(1, {"type": "accept", "offer_id": 1}) expect( non_existing_offer, @@ -69,8 +69,8 @@ def test_invalid_input(method, Y, dummy_player, P1_name): 2, { "type": "propose", - "members": [True, False, True], - "allocations": [50, 0, 50], + "members": [True, True, True], + "allocations": [50, 50, 10], }, ) expect( @@ -91,15 +91,26 @@ def test_invalid_input(method, Y, dummy_player, P1_name): "allocations": [0, 50, 50], }, ) - expect( - p1_not_included, - { - 3: { - "type": "error", - "content": f"Invalid allocation: allocation has to be zero when Player {P1_name} is not included", - } - }, - ) + if not dummy_player: + expect( + p1_not_included, + { + 3: { + "type": "error", + "content": f"Invalid allocation: allocation has to be zero when Player {player_names['P1']} is not included", + } + }, + ) + else: + expect( + p1_not_included, + { + 3: { + "type": "error", + "content": f"Invalid allocation: allocation has to be zero when Players {player_names['P1']} and {player_names['P2']} are not included", + } + }, + ) invalid_allocaion_negative = method( 1, @@ -179,13 +190,13 @@ def call_live_method(method, **kwargs): ) prod_fct = kwargs["group"].session.config["prod_fct"] - P1_name = kwargs["group"].session.config["player_names"]["P1"] + player_names = kwargs["group"].session.config["player_names"] Y = list(prod_fct.values())[1] dummy_player = len(prod_fct) == 2 if kwargs["round_number"] == 1: print("Testing invalid input") - test_invalid_input(method, Y, dummy_player, P1_name) + test_invalid_input(method, Y, dummy_player, player_names) if kwargs["round_number"] == 2: print("Testing grand coalition") From 9e4bb3afcdb3d1adc3d9ecf4bc5e22d2f48400bf Mon Sep 17 00:00:00 2001 From: Martin Stancsics Date: Tue, 23 Apr 2024 16:10:04 +0200 Subject: [PATCH 8/8] Better wording --- introduction/Proposal.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/introduction/Proposal.html b/introduction/Proposal.html index cca0107..cc4d653 100644 --- a/introduction/Proposal.html +++ b/introduction/Proposal.html @@ -15,7 +15,7 @@

Group budgets

You and the two other players will each be randomly assigned a player role ({{P1}}, {{P2}}, {{P3}}). - The player numbers will be reshuffled each round. + The player roles will be reshuffled each round.