virtualcommons-svn Mailing List for Virtual Commons Experiment Software (Page 24)
Status: Beta
Brought to you by:
alllee
You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(21) |
Aug
(31) |
Sep
(6) |
Oct
(15) |
Nov
(2) |
Dec
(9) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(4) |
Feb
(6) |
Mar
(12) |
Apr
(52) |
May
(14) |
Jun
(19) |
Jul
(81) |
Aug
(115) |
Sep
(36) |
Oct
(88) |
Nov
(46) |
Dec
(58) |
2010 |
Jan
(52) |
Feb
(55) |
Mar
(48) |
Apr
(15) |
May
(5) |
Jun
(38) |
Jul
(27) |
Aug
(24) |
Sep
(28) |
Oct
(1) |
Nov
(2) |
Dec
(29) |
2011 |
Jan
(87) |
Feb
(39) |
Mar
(63) |
Apr
(42) |
May
(26) |
Jun
(53) |
Jul
(23) |
Aug
(43) |
Sep
(37) |
Oct
(25) |
Nov
(4) |
Dec
(7) |
2012 |
Jan
(73) |
Feb
(79) |
Mar
(62) |
Apr
(28) |
May
(12) |
Jun
(2) |
Jul
(9) |
Aug
(1) |
Sep
(8) |
Oct
|
Nov
(3) |
Dec
(3) |
2013 |
Jan
(8) |
Feb
(16) |
Mar
(38) |
Apr
(74) |
May
(62) |
Jun
(15) |
Jul
(49) |
Aug
(19) |
Sep
(9) |
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(25) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Bitbucket <com...@bi...> - 2012-01-18 05:18:07
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/b084c905fdf1/ changeset: b084c905fdf1 user: alllee date: 2012-01-18 06:17:50 summary: adding special case for show exit instructions (only needed for trust game enabled in the final round) affected #: 3 files diff -r 3514a9bf2d20efaa68d51ded573d1a2b486e6a9b -r b084c905fdf19036392f6639bb714a97c5753ac8 src/main/java/edu/asu/commons/foraging/client/ForagingClient.java --- a/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java +++ b/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java @@ -185,14 +185,9 @@ }); addEventProcessor(new EventTypeProcessor<RoundStartedEvent>(RoundStartedEvent.class) { public void handle(RoundStartedEvent event) { - System.err.println("client starting round: " + dataModel.is2dExperiment()); - dataModel.initialize(event.getGroupDataModel()); + dataModel.initialize(event.getGroupDataModel()); setId(event.getId()); - getGameWindow().startRound(); - if (dataModel.is2dExperiment()) { - messageQueue.start(); - } - state = ClientState.RUNNING; + messageQueue.start(); } }); @@ -229,7 +224,7 @@ addEventProcessor(new EventTypeProcessor<TrustGameResultsClientEvent>(TrustGameResultsClientEvent.class) { @Override public void handle(TrustGameResultsClientEvent event) { - getGameWindow2D().updateTrustGame(event); + getGameWindow2D().updateDebriefingWith(event); } }); initialize2DEventProcessors(); @@ -361,6 +356,8 @@ } public void run() { + getGameWindow().startRound(); + state = ClientState.RUNNING; secondTick.start(); while (running) { Event request = get(); diff -r 3514a9bf2d20efaa68d51ded573d1a2b486e6a9b -r b084c905fdf19036392f6639bb714a97c5753ac8 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -797,6 +797,7 @@ NumberFormat formatter = NumberFormat.getCurrencyInstance(); populateClientEarnings(data, getParentConfiguration(), formatter, showExitInstructions); st.add("clientData", data); + // FIXME: replace showExitInstructions within client debriefing with a ExitInstructions template? st.add("showExitInstructions", showExitInstructions); st.add("showUpPayment", formatter.format(getParentConfiguration().getShowUpPayment())); return st.render(); diff -r 3514a9bf2d20efaa68d51ded573d1a2b486e6a9b -r b084c905fdf19036392f6639bb714a97c5753ac8 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -164,7 +164,7 @@ * * @param event */ - public void init() { + public synchronized void init() { final RoundConfiguration roundConfiguration = dataModel.getRoundConfiguration(); SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -541,7 +541,7 @@ // getPanel().repaint(); // } - public void startRound() { + public synchronized void startRound() { final RoundConfiguration configuration = dataModel.getRoundConfiguration(); if (timer != null) { timer.stop(); @@ -798,7 +798,7 @@ SwingUtilities.invokeLater(runnable); } - public void endRound(final EndRoundEvent event) { + public synchronized void endRound(final EndRoundEvent event) { Runnable runnable = new Runnable() { public void run() { if (inRoundChatPanel != null) { @@ -817,7 +817,9 @@ instructionsEditorPane.setText("Waiting for updated round totals from the server..."); switchInstructionsPane(); } - showDebriefing(event.getClientData(), false); + // FIXME: replace with facilitator driven show exit instructions signal? + boolean showExitInstructions = event.isLastRound() && ! roundConfiguration.isTrustGameEnabled(); + showDebriefing(event.getClientData(), showExitInstructions); } }; try { @@ -878,8 +880,11 @@ switchInstructionsPane(); } - public void updateTrustGame(TrustGameResultsClientEvent event) { - // show last round + public void updateDebriefingWith(TrustGameResultsClientEvent event) { + // FIXME: currently hard coded to always show exit instructions in this case + // should change this to either have an explicit show exit instructions fired off by the + // facilitator or figure out a cleaner way of distinguishing between "we have to wait for + // some final calculation to occur before showing the final debriefing + exit instructions" showDebriefing(event.getClientData(), true); } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 23:20:05
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/aaec0bffe99a/ changeset: aaec0bffe99a user: alllee date: 2012-01-18 00:20:06 summary: kw affected #: 1 file diff -r 81fa4a6fbddf8c30702c6d36218fb56261a2685a -r aaec0bffe99a283940e965e3e01bdcd2d4ff224d src/test/java/edu/asu/commons/foraging/model/ResourceDispenserTest.java --- a/src/test/java/edu/asu/commons/foraging/model/ResourceDispenserTest.java +++ b/src/test/java/edu/asu/commons/foraging/model/ResourceDispenserTest.java @@ -10,10 +10,10 @@ import edu.asu.commons.net.Identifier; /** - * $Id: ResourceDispenserTest.java 76 2009-02-25 18:02:38Z alllee $ + * $Id$ * * @author <a href='mailto:All...@as...'>Allen Lee</a> - * @version $Revision: 76 $ + * @version $Revision$ */ public class ResourceDispenserTest { Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 23:19:01
|
4 new commits in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/c9d18da5330d/ changeset: c9d18da5330d user: alllee date: 2012-01-18 00:14:02 summary: templatizing client debriefing in RoundConfiguration / ServerConfiguration affected #: 2 files diff -r 71e89c0d123b30b6a9deebf1f9a3d32124512945 -r c9d18da5330d7b493c22c8fb65994c5dcef9b014 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -787,6 +787,29 @@ public double tokensToDollars(int tokens) { return isPracticeRound() ? 0.0d : tokens * getDollarsPerToken(); } + + public String getClientDebriefing() { + return getProperty("client-debriefing", getParentConfiguration().getClientDebriefing()); + } + + public String generateClientDebriefing(ClientData data) { + ST st = createStringTemplate(getClientDebriefing()); + populateClientEarnings(data); + st.add("clientData", data); + st.add("showUpPayment", NumberFormat.getCurrencyInstance().format(getParentConfiguration().getShowUpPayment())); + return st.render(); + } + + private void populateClientEarnings(ClientData data) { + populateClientEarnings(data, getParentConfiguration(), NumberFormat.getCurrencyInstance()); + } + + private void populateClientEarnings(ClientData data, ServerConfiguration serverConfiguration, NumberFormat formatter) { + data.setGrandTotalIncome(formatter.format(serverConfiguration.getTotalIncome(data))); + data.setCurrentIncome(formatter.format(tokensToDollars(data.getCurrentTokens()))); + data.setQuizEarnings(formatter.format(serverConfiguration.getQuizEarnings(data))); + data.setTrustGameEarnings(formatter.format(data.getTrustGameIncome())); + } public String generateFacilitatorDebriefing(ServerDataModel serverDataModel) { ST template = createStringTemplate(getFacilitatorDebriefing()); @@ -794,10 +817,7 @@ ServerConfiguration serverConfiguration = getParentConfiguration(); NumberFormat formatter = NumberFormat.getCurrencyInstance(); for (ClientData data: serverDataModel.getClientDataMap().values()) { - data.setGrandTotalIncome(formatter.format(serverConfiguration.getTotalIncome(data))); - data.setCurrentIncome(formatter.format(tokensToDollars(data.getCurrentTokens()))); - data.setQuizEarnings(formatter.format(serverConfiguration.getQuizEarnings(data))); - data.setTrustGameEarnings(formatter.format(data.getTrustGameIncome())); + populateClientEarnings(data, serverConfiguration, formatter); } template.add("clientDataList", serverDataModel.getClientDataMap().values()); return template.render(); diff -r 71e89c0d123b30b6a9deebf1f9a3d32124512945 -r c9d18da5330d7b493c22c8fb65994c5dcef9b014 src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java @@ -122,6 +122,10 @@ return assistant.getProperty("facilitator-debriefing"); } + public String getClientDebriefing() { + return assistant.getProperty("client-debriefing"); + } + public double getTotalIncome(ClientData data) { return data.getTotalIncome() + getShowUpPayment() + getQuizEarnings(data) + data.getTrustGameIncome(); } https://bitbucket.org/virtualcommons/foraging/changeset/d661cd58ca4d/ changeset: d661cd58ca4d user: alllee date: 2012-01-18 00:15:05 summary: fixes issue 29 - now checking if round is in progress before sending any in-round requests affected #: 1 file diff -r c9d18da5330d7b493c22c8fb65994c5dcef9b014 -r d661cd58ca4d38156bd4bd658e7292599592b328 src/main/java/edu/asu/commons/foraging/client/ForagingClient.java --- a/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java +++ b/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java @@ -40,6 +40,7 @@ import edu.asu.commons.foraging.event.ShowVotingInstructionsRequest; import edu.asu.commons.foraging.event.SurveyIdSubmissionRequest; import edu.asu.commons.foraging.event.SynchronizeClientEvent; +import edu.asu.commons.foraging.event.TrustGameResultsClientEvent; import edu.asu.commons.foraging.event.TrustGameSubmissionRequest; import edu.asu.commons.foraging.rules.ForagingRule; import edu.asu.commons.foraging.ui.GameWindow; @@ -225,6 +226,13 @@ getGameWindow().update(event.getTimeLeft()); } }); + addEventProcessor(new EventTypeProcessor<TrustGameResultsClientEvent>(TrustGameResultsClientEvent.class) { + @Override + public void handle(TrustGameResultsClientEvent event) { + getGameWindow2D().updateTrustGame(event); + } + + }); initialize2DEventProcessors(); // initialize3DEventProcessors(); messageQueue = new MessageQueue(); @@ -305,19 +313,21 @@ }); channel.add(this, new EventTypeProcessor<ClientMovementRequest>(ClientMovementRequest.class) { public void handle(ClientMovementRequest request) { - add(request); + if (isRoundInProgress()) { + add(request); + } } }); channel.add(this, new EventTypeProcessor<CollectTokenRequest>(CollectTokenRequest.class) { public void handle(CollectTokenRequest request) { - if (state == ClientState.RUNNING) { + if (isRoundInProgress()) { transmit(request); } } }); channel.add(this, new EventTypeProcessor<ResetTokenDistributionRequest>(ResetTokenDistributionRequest.class) { public void handle(ResetTokenDistributionRequest event) { - if (state == ClientState.RUNNING && dataModel.getRoundConfiguration().isPracticeRound()) { + if (isRoundInProgress() && dataModel.getRoundConfiguration().isPracticeRound()) { transmit(event); } } @@ -441,4 +451,9 @@ transmit(new RuleVoteRequest(getId(), selectedRule)); getGameWindow2D().ruleVoteSubmitted(); } + + + public boolean isRoundInProgress() { + return state == ClientState.RUNNING; + } } https://bitbucket.org/virtualcommons/foraging/changeset/630355d1b141/ changeset: 630355d1b141 user: alllee date: 2012-01-18 00:16:05 summary: updated full vision + in round chat configuration with client debriefing template affected #: 4 files diff -r d661cd58ca4d38156bd4bd658e7292599592b328 -r 630355d1b14195576d188c9bdbf5cde228a39df2 src/main/resources/configuration/asu-experiments/2011/t1/round4.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round4.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round4.xml @@ -18,8 +18,6 @@ <entry key='in-round-chat-enabled'>true</entry><entry key="initial-distribution">.25</entry> -<entry key='resource-generator'>top-bottom-patchy</entry> - <entry key="instructions"><![CDATA[ <h3>Round {roundNumber} Instructions</h3> diff -r d661cd58ca4d38156bd4bd658e7292599592b328 -r 630355d1b14195576d188c9bdbf5cde228a39df2 src/main/resources/configuration/asu-experiments/2011/t1/round5.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round5.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round5.xml @@ -13,6 +13,5 @@ <entry key='always-explicit'>true</entry><entry key='max-cell-occupancy'>1</entry><entry key="in-round-chat-enabled">true</entry> -<entry key='resource-generator'>top-bottom-patchy</entry></properties> diff -r d661cd58ca4d38156bd4bd658e7292599592b328 -r 630355d1b14195576d188c9bdbf5cde228a39df2 src/main/resources/configuration/asu-experiments/2011/t1/round6.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round6.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round6.xml @@ -16,9 +16,6 @@ <entry key='max-cell-occupancy'>1</entry><entry key='trust-game'>true</entry> - -<entry key='resource-generator'>top-bottom-patchy</entry> - <entry key="last-round-debriefing"><![CDATA[ <h2>Survey</h2> diff -r d661cd58ca4d38156bd4bd658e7292599592b328 -r 630355d1b14195576d188c9bdbf5cde228a39df2 src/main/resources/configuration/asu-experiments/2011/t1/server.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/server.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/server.xml @@ -202,4 +202,47 @@ </table> ]]></entry> +<entry key='client-debriefing'> +<![CDATA[ +<h1>{if (self.practiceRound)}Practice Round{else}Round {self.roundNumber}{endif} Results</h1> +<hr> +<ul> +<li>Tokens collected in this round: {clientData.currentTokens}</li> +<li>Income from tokens collected: {clientData.currentIncome}</li> +<li>Total tokens: {clientData.totalTokens}</li> +<li>Quiz earnings: {clientData.quizEarnings}</li> +<li>Show up payment: {showUpPayment}</li> +</ul> +{if (self.lastRound && ! clientData.trustGameLog.empty) } +<h2>Trust Game Earnings</h2> +<hr> +<ol> +{clientData.trustGameLog: {trustGameLog| +<li>Trust Game #{i}: {trustGameLog}</li> +}} +</ol> +{endif} +<h2>Total Income</h2> +<hr> +<p> +Your <b>total income across all rounds</b> is {clientData.grandTotalIncome}. +</p> +{if (self.lastRound)} +<h2>Exit Survey</h2> +<hr> +<p> +This was the last round, but not the end of the experiment. We will now determine your payments. While we are doing this, we request that you carefully fill out a brief survey. +</p> +<h2>Payments</h2> +<hr> +<p>NOTE: Your computer number is <b>{id}</b></p> +<p> +When the payments are ready we will call you one by one and pay you in private. Please wait until your computer number, <b>{id}</b>, is called before you come up and turn in your survey. Please answer the survey carefully and thank you for participating. +</p> +{endif} + + + +]]> +</entry></properties> https://bitbucket.org/virtualcommons/foraging/changeset/81fa4a6fbddf/ changeset: 81fa4a6fbddf user: alllee date: 2012-01-18 00:18:35 summary: fixes issue 30 - adding client side update for trust game results in last round affected #: 4 files diff -r 630355d1b14195576d188c9bdbf5cde228a39df2 -r 81fa4a6fbddf8c30702c6d36218fb56261a2685a src/main/java/edu/asu/commons/foraging/event/ClientPositionUpdateEvent.java --- a/src/main/java/edu/asu/commons/foraging/event/ClientPositionUpdateEvent.java +++ b/src/main/java/edu/asu/commons/foraging/event/ClientPositionUpdateEvent.java @@ -1,7 +1,6 @@ package edu.asu.commons.foraging.event; import java.awt.Point; -import java.util.List; import java.util.Map; import java.util.Queue; diff -r 630355d1b14195576d188c9bdbf5cde228a39df2 -r 81fa4a6fbddf8c30702c6d36218fb56261a2685a src/main/java/edu/asu/commons/foraging/model/ClientData.java --- a/src/main/java/edu/asu/commons/foraging/model/ClientData.java +++ b/src/main/java/edu/asu/commons/foraging/model/ClientData.java @@ -70,6 +70,7 @@ private ForagingRule votedRule; private ArrayList<String> trustGameLog = new ArrayList<String>(); + // String fields to be set and formatted for use in templates. private String grandTotalIncome; private String currentIncome; private String quizEarnings; diff -r 630355d1b14195576d188c9bdbf5cde228a39df2 -r 81fa4a6fbddf8c30702c6d36218fb56261a2685a src/main/java/edu/asu/commons/foraging/ui/ChatPanel.java --- a/src/main/java/edu/asu/commons/foraging/ui/ChatPanel.java +++ b/src/main/java/edu/asu/commons/foraging/ui/ChatPanel.java @@ -1,10 +1,7 @@ package edu.asu.commons.foraging.ui; import java.awt.BorderLayout; -import java.awt.Color; import java.awt.Dimension; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.List; @@ -133,17 +130,17 @@ } } }); - chatField.addFocusListener(new FocusListener() { - @Override - public void focusGained(FocusEvent e) { - chatField.setBackground(Color.YELLOW); - } - @Override - public void focusLost(FocusEvent e) { - chatField.setBackground(Color.WHITE); - } - - }); +// chatField.addFocusListener(new FocusListener() { +// @Override +// public void focusGained(FocusEvent e) { +// chatField.setBackground(Color.YELLOW); +// } +// @Override +// public void focusLost(FocusEvent e) { +// chatField.setBackground(Color.WHITE); +// } +// +// }); JLabel headerLabel = new JLabel("Chat"); headerLabel.setFont(UserInterfaceUtils.DEFAULT_BOLD_FONT); add(headerLabel, BorderLayout.NORTH); diff -r 630355d1b14195576d188c9bdbf5cde228a39df2 -r 81fa4a6fbddf8c30702c6d36218fb56261a2685a src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -51,6 +51,7 @@ import edu.asu.commons.foraging.event.QuizResponseEvent; import edu.asu.commons.foraging.event.RealTimeSanctionRequest; import edu.asu.commons.foraging.event.ResetTokenDistributionRequest; +import edu.asu.commons.foraging.event.TrustGameResultsClientEvent; import edu.asu.commons.foraging.model.ClientData; import edu.asu.commons.foraging.model.Direction; import edu.asu.commons.foraging.rules.ForagingRule; @@ -417,6 +418,9 @@ // FIXME: refactor this method if possible. @Override public void keyPressed(KeyEvent keyEvent) { + if (! client.isRoundInProgress()) { + return; + } int keyChar = (int) keyEvent.getKeyChar(); int keyCode = keyEvent.getKeyCode(); Event event = null; @@ -608,35 +612,10 @@ } return dataModel.getRoundConfiguration().getDollarsPerToken() * numTokens; } - - private void addDebriefingText(EndRoundEvent event) { + + public void showDebriefing(ClientData clientData) { instructionsBuilder.delete(0, instructionsBuilder.length()); - // FIXME: should be round-specific? We're not resetting correct quiz answers either. - int correctQuizAnswers = event.getClientData().getCorrectQuizAnswers(); - double quizReward = correctQuizAnswers * dataModel.getRoundConfiguration().getQuizCorrectAnswerReward(); - instructionsBuilder.append( - String.format("<h3>Your stats in this round:</h3>" + - "<ul>" + - "<li>Tokens collected: %d</li>" + - "<li>Income: $%3.2f</li>" + - "<li>Quiz questions answered correctly: %d (adds $%3.2f to your total)</li>" + - "</ul>", - event.getCurrentTokens(), getIncome(event.getCurrentTokens()), correctQuizAnswers, quizReward) - ); - double showUpPayment = dataModel.getRoundConfiguration().getParentConfiguration().getShowUpPayment(); - instructionsBuilder.append(String.format("Your <b>total income</b> so far (including a $%3.2f bonus for showing up) is : $%3.2f<hr>", - showUpPayment, dataModel.getTotalIncome() + showUpPayment + quizReward)); - for (String trustGameLog : event.getTrustGameLog()) { - instructionsBuilder.append(trustGameLog); - } - if (event.isLastRound()) { - // FIXME: show final round debriefing explicitly -// for (String trustGameLog : event.getTrustGameLog()) { -// instructionsBuilder.append(trustGameLog); -// } - instructionsBuilder.append(client.getDataModel().getLastRoundDebriefing()); - timeLeftLabel.setText("The experiment is now over."); - } + instructionsBuilder.append(dataModel.getRoundConfiguration().generateClientDebriefing(clientData)); setInstructions(instructionsBuilder.toString()); } @@ -840,7 +819,7 @@ switchInstructionsPane(); } // generate debriefing text from data culled from the Event - addDebriefingText(event); + showDebriefing(event.getClientData()); } }; try { @@ -901,5 +880,9 @@ switchInstructionsPane(); } + public void updateTrustGame(TrustGameResultsClientEvent event) { + showDebriefing(event.getClientData()); + } + } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 08:41:50
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/71e89c0d123b/ changeset: 71e89c0d123b user: alllee date: 2012-01-17 09:41:48 summary: kwexpand affected #: 1 file diff -r 736606d4c166cf511efd40dc9ee6a618574e78c1 -r 71e89c0d123b30b6a9deebf1f9a3d32124512945 src/main/java/edu/asu/commons/foraging/facilitator/ReplayControlPanel.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/ReplayControlPanel.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/ReplayControlPanel.java @@ -37,7 +37,7 @@ * Basic replay control panel for csan experiment. Only works for 2D version (and probably broken right now)... * * @author <a href='mailto:All...@as...'>Allen Lee</a> - * @version $Revision: 384 $ + * @version $Revision$ */ public class ReplayControlPanel extends JPanel { Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 08:39:18
|
4 new commits in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/603fec679005/ changeset: 603fec679005 user: alllee date: 2012-01-17 07:58:43 summary: server now signals facilitator and clients when trust game results are available affected #: 3 files diff -r 12876cd1bd8f3d434698704b527d1a37c530e3ee -r 603fec679005f2acac145e7a06d0ac300934bc1d src/main/java/edu/asu/commons/foraging/event/TrustGameResultsClientEvent.java --- a/src/main/java/edu/asu/commons/foraging/event/TrustGameResultsClientEvent.java +++ b/src/main/java/edu/asu/commons/foraging/event/TrustGameResultsClientEvent.java @@ -10,6 +10,7 @@ private static final long serialVersionUID = -9129989958983083574L; private final ClientData clientData; + public TrustGameResultsClientEvent(ClientData clientData, String log) { super(clientData.getId(), log); this.clientData = clientData; diff -r 12876cd1bd8f3d434698704b527d1a37c530e3ee -r 603fec679005f2acac145e7a06d0ac300934bc1d src/main/java/edu/asu/commons/foraging/facilitator/ReplayControlPanel.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/ReplayControlPanel.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/ReplayControlPanel.java @@ -19,7 +19,7 @@ import edu.asu.commons.event.EventChannelFactory; import edu.asu.commons.event.PersistableEvent; -import edu.asu.commons.experiment.Persister; +import edu.asu.commons.experiment.IPersister; import edu.asu.commons.foraging.conf.RoundConfiguration; import edu.asu.commons.foraging.conf.ServerConfiguration; import edu.asu.commons.foraging.event.AddClientEvent; @@ -87,7 +87,7 @@ * Initializes the replay control panel with a directory containing a persisted experiment run. * @param replayFilePath */ - public void init(File replayFilePath, Persister<ServerConfiguration, RoundConfiguration> persister) { + public void init(File replayFilePath, IPersister<ServerConfiguration, RoundConfiguration> persister) { this.replayFile = replayFilePath; replayExperimentFilePath.setText(replayFile.getAbsolutePath()); replayRoundThread = new ReplayRoundThread(persister); @@ -244,7 +244,7 @@ private volatile PersistableEvent currentPersistableEvent; - public ReplayRoundThread(Persister<ServerConfiguration, RoundConfiguration> persister) { + public ReplayRoundThread(IPersister<ServerConfiguration, RoundConfiguration> persister) { this.actions = new ArrayList<PersistableEvent>(persister.getActions()); // FIXME: provide data model restore functionality in persister // this.serverDataModel = persister.restoreInitialGameState(); diff -r 12876cd1bd8f3d434698704b527d1a37c530e3ee -r 603fec679005f2acac145e7a06d0ac300934bc1d src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -30,6 +30,8 @@ import edu.asu.commons.event.SetConfigurationEvent; import edu.asu.commons.event.SocketIdentifierUpdateRequest; import edu.asu.commons.experiment.AbstractExperiment; +import edu.asu.commons.experiment.IPersister; +import edu.asu.commons.experiment.Persister; import edu.asu.commons.experiment.StateMachine; import edu.asu.commons.foraging.conf.RoundConfiguration; import edu.asu.commons.foraging.conf.ServerConfiguration; @@ -114,7 +116,7 @@ private StateMachine stateMachine = new ForagingStateMachine(); - private ForagingPersister persister; + private Persister<ServerConfiguration, RoundConfiguration> persister; private volatile int numberOfSubmittedQuizzes; private volatile int numberOfCompletedSanctions; @@ -643,7 +645,6 @@ @Override public void handle(TrustGameSubmissionRequest request) { if (getCurrentRoundConfiguration().isTrustGameEnabled()) { - // basic sanity check ClientData clientData = clients.get(request.getId()); clientData.setTrustGamePlayerOneAmountToKeep(request.getPlayerOneAmountToKeep()); clientData.setTrustGamePlayerTwoAmountsToKeep(request.getPlayerTwoAmountsToKeep()); @@ -652,7 +653,9 @@ numberOfSubmissions++; sendFacilitatorMessage(String.format("Received trust game submission %s (%d total)", request, numberOfSubmissions)); } - // FIXME: groups have not been assigned in the transition between practice round and this round.. + else { + warnFacilitator("Received trust game submission request but trust game wasn't enabled: " + request); + } if (numberOfSubmissions >= clients.size()) { // once all clients have submitted their decisions, execute the trust game. processTrustGame(); @@ -717,8 +720,7 @@ trustGameResult)); } } - // FIXME: update facilitator AND clients if it is the last round of the experiment - transmit(new TrustGameResultsFacilitatorEvent(facilitatorId, serverDataModel.getClientDataMap(), allTrustGameResults)); + transmitAndStore(new TrustGameResultsFacilitatorEvent(facilitatorId, serverDataModel.getClientDataMap(), allTrustGameResults)); } protected boolean isReadyToStartRound() { @@ -768,6 +770,13 @@ transmit(new FacilitatorMessageEvent(facilitatorId, message)); } } + + private void warnFacilitator(String message) { + logger.warning(message); + if (facilitatorId != null) { + transmit(new FacilitatorMessageEvent(facilitatorId, "!. " + message)); + } + } // FIXME: remove Dispatcher reference if it's unused. public void execute(Dispatcher dispatcher) { @@ -1043,4 +1052,10 @@ server.start(); server.repl(); } + + @Override + public IPersister<ServerConfiguration, RoundConfiguration> getPersister() { + return persister; + } + } https://bitbucket.org/virtualcommons/foraging/changeset/e454c3ee8f4f/ changeset: e454c3ee8f4f user: alllee date: 2012-01-17 09:36:07 summary: fixing path in template test affected #: 1 file diff -r 603fec679005f2acac145e7a06d0ac300934bc1d -r e454c3ee8f4fcf5679b97ef686fa566fd5ca4afb src/test/java/edu/asu/commons/foraging/conf/RoundConfigurationTest.java --- a/src/test/java/edu/asu/commons/foraging/conf/RoundConfigurationTest.java +++ b/src/test/java/edu/asu/commons/foraging/conf/RoundConfigurationTest.java @@ -14,7 +14,7 @@ @Before public void setUp() { - ServerConfiguration serverConfiguration = new ServerConfiguration("configuration/indiana-experiments/fall-2011/pretest"); + ServerConfiguration serverConfiguration = new ServerConfiguration("configuration/indiana-experiments/2011/vote-punish"); roundConfiguration = serverConfiguration.getAllParameters().get(4); } https://bitbucket.org/virtualcommons/foraging/changeset/57266c20ec10/ changeset: 57266c20ec10 user: alllee date: 2012-01-17 09:37:13 summary: fixing failing test usage of generateVotingResults and minor test coverage additions affected #: 1 file diff -r e454c3ee8f4fcf5679b97ef686fa566fd5ca4afb -r 57266c20ec10f43300ca88a52fed5ea331d82b9d src/test/java/edu/asu/commons/foraging/model/GroupDataModelTest.java --- a/src/test/java/edu/asu/commons/foraging/model/GroupDataModelTest.java +++ b/src/test/java/edu/asu/commons/foraging/model/GroupDataModelTest.java @@ -1,9 +1,12 @@ package edu.asu.commons.foraging.model; -import java.util.ArrayList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -11,7 +14,6 @@ import edu.asu.commons.foraging.conf.RoundConfiguration; import edu.asu.commons.foraging.rules.ForagingRule; import edu.asu.commons.net.Identifier; -import static org.junit.Assert.*; public class GroupDataModelTest { @@ -39,7 +41,9 @@ data.setVotedRule(rule); } // verify that this is the rule in place. - assertEquals(rule, group.generateVotingResults()); + Map<ForagingRule, Integer> votingResults = group.generateVotingResults(); + assertEquals(1, votingResults.size()); + assertEquals(rule, group.getSelectedRule()); } } } @@ -59,7 +63,12 @@ ForagingRule votedRule = rules.get(index); data.setVotedRule(votedRule); } - assertTrue(tieBreakerRules.contains(group.generateVotingResults())); + Map<ForagingRule, Integer> votingResults = group.generateVotingResults(); + assertEquals("There should be 3 rules voted on, total" + votingResults, 3, votingResults.size()); + for (ForagingRule tieBreaker: tieBreakerRules) { + assertEquals(2, votingResults.get(tieBreaker).intValue()); + } + assertTrue(tieBreakerRules.contains(group.getSelectedRule())); } } https://bitbucket.org/virtualcommons/foraging/changeset/30069402c6a0/ changeset: 30069402c6a0 user: alllee date: 2012-01-17 09:38:50 summary: trust game results now properly update the facilitator payment screen. refactored usage of RoundConfiguration and debriefing display. affected #: 6 files diff -r 57266c20ec10f43300ca88a52fed5ea331d82b9d -r 30069402c6a05dd6b4d62463a8aba1c362f3e103 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -11,7 +11,6 @@ import java.util.concurrent.TimeUnit; import org.stringtemplate.v4.ST; -import org.stringtemplate.v4.STGroupString; import edu.asu.commons.conf.ExperimentRoundParameters; import edu.asu.commons.foraging.graphics.Point3D; @@ -759,7 +758,11 @@ @Override public String toString() { List<RoundConfiguration> allParameters = getParentConfiguration().getAllParameters(); - return String.format("Round %d of %d\n\t%s", allParameters.indexOf(this) + 1, allParameters.size(), getProperties()); + return String.format("Round %d of %d", allParameters.indexOf(this) + 1, allParameters.size()); + } + + public String fullStatus() { + return toString() + "\n\t" + getProperties(); } public String getQuizResults(List<String> incorrectQuestionNumbers, Map<Object, Object> actualAnswers) { @@ -799,4 +802,9 @@ template.add("clientDataList", serverDataModel.getClientDataMap().values()); return template.render(); } + + // returns the next round configuration without advancing the pointer in ServerConfiguration + public RoundConfiguration nextRound() { + return getParentConfiguration().getNextRoundConfiguration(); + } } diff -r 57266c20ec10f43300ca88a52fed5ea331d82b9d -r 30069402c6a05dd6b4d62463a8aba1c362f3e103 src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java @@ -112,6 +112,11 @@ public double getDollarsPerToken() { return DEFAULT_DOLLARS_PER_TOKEN; } + + public String getFinalRoundFacilitatorInstructions() { + return assistant.getProperty("facilitator-payment-instructions", + "<h3>The experiment has ended and participant payments are listed above. We recommend that you copy and paste it into a text editor for your records.</h3>"); + } public String getFacilitatorDebriefing() { return assistant.getProperty("facilitator-debriefing"); diff -r 57266c20ec10f43300ca88a52fed5ea331d82b9d -r 30069402c6a05dd6b4d62463a8aba1c362f3e103 src/main/java/edu/asu/commons/foraging/event/TrustGameResultsFacilitatorEvent.java --- a/src/main/java/edu/asu/commons/foraging/event/TrustGameResultsFacilitatorEvent.java +++ b/src/main/java/edu/asu/commons/foraging/event/TrustGameResultsFacilitatorEvent.java @@ -1,10 +1,9 @@ package edu.asu.commons.foraging.event; import java.util.List; -import java.util.Map; import edu.asu.commons.event.AbstractPersistableEvent; -import edu.asu.commons.foraging.model.ClientData; +import edu.asu.commons.foraging.model.ServerDataModel; import edu.asu.commons.net.Identifier; /** @@ -14,12 +13,12 @@ private static final long serialVersionUID = 5834548819829135618L; private List<String> allTrustGameResults; - private Map<Identifier, ClientData> clientDataMap; + private ServerDataModel serverDataModel; public TrustGameResultsFacilitatorEvent(Identifier facilitatorId, - Map<Identifier, ClientData> clientDataMap, List<String> allTrustGameResults) { + ServerDataModel serverDataModel, List<String> allTrustGameResults) { super(facilitatorId); this.allTrustGameResults = allTrustGameResults; - this.clientDataMap = clientDataMap; + this.serverDataModel = serverDataModel; } public List<String> getAllTrustGameResults() { return allTrustGameResults; @@ -27,11 +26,12 @@ public void setAllTrustGameResults(List<String> allTrustGameResults) { this.allTrustGameResults = allTrustGameResults; } - public Map<Identifier, ClientData> getClientDataMap() { - return clientDataMap; + public ServerDataModel getServerDataModel() { + return serverDataModel; } - public void setClientDataMap(Map<Identifier, ClientData> clientDataMap) { - this.clientDataMap = clientDataMap; + public void setServerDataModel(ServerDataModel serverDataModel) { + this.serverDataModel = serverDataModel; } + } diff -r 57266c20ec10f43300ca88a52fed5ea331d82b9d -r 30069402c6a05dd6b4d62463a8aba1c362f3e103 src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java @@ -26,6 +26,7 @@ import edu.asu.commons.foraging.event.ShowTrustGameRequest; import edu.asu.commons.foraging.event.ShowVoteScreenRequest; import edu.asu.commons.foraging.event.ShowVotingInstructionsRequest; +import edu.asu.commons.foraging.event.TrustGameResultsFacilitatorEvent; import edu.asu.commons.foraging.event.TrustGameSubmissionEvent; import edu.asu.commons.foraging.model.ServerDataModel; @@ -50,12 +51,17 @@ public Facilitator(ServerConfiguration configuration) { super(configuration); addEventProcessor(new EventTypeProcessor<SetConfigurationEvent>(SetConfigurationEvent.class) { - public void handle(SetConfigurationEvent event) { RoundConfiguration configuration = (RoundConfiguration) event.getParameters(); setServerConfiguration(configuration.getParentConfiguration()); } }); + addEventProcessor(new EventTypeProcessor<TrustGameResultsFacilitatorEvent>(TrustGameResultsFacilitatorEvent.class){ + @Override + public void handle(TrustGameResultsFacilitatorEvent event) { + facilitatorWindow.updateTrustGame(event); + } + }); addEventProcessor(new EventTypeProcessor<FacilitatorUpdateEvent>(FacilitatorUpdateEvent.class) { public void handle(FacilitatorUpdateEvent event) { @@ -179,10 +185,6 @@ return facilitatorWindow; } - public ServerDataModel getServerGameState() { - return serverDataModel; - } - public void setRoundParameters( List<RoundConfiguration> roundConfiguration) { getServerConfiguration().setAllParameters(roundConfiguration); @@ -220,7 +222,7 @@ return getServerConfiguration().getCurrentParameters(); } - public void setServerGameState(ServerDataModel serverGameState) { + public void setServerDataModel(ServerDataModel serverGameState) { this.serverDataModel = serverGameState; } diff -r 57266c20ec10f43300ca88a52fed5ea331d82b9d -r 30069402c6a05dd6b4d62463a8aba1c362f3e103 src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java @@ -5,8 +5,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.TreeSet; @@ -21,12 +19,13 @@ import javax.swing.text.BadLocationException; import edu.asu.commons.foraging.conf.RoundConfiguration; -import edu.asu.commons.foraging.conf.ServerConfiguration; import edu.asu.commons.foraging.event.FacilitatorEndRoundEvent; import edu.asu.commons.foraging.event.FacilitatorSanctionUpdateEvent; import edu.asu.commons.foraging.event.QuizCompletedEvent; +import edu.asu.commons.foraging.event.TrustGameResultsFacilitatorEvent; import edu.asu.commons.foraging.event.TrustGameSubmissionEvent; import edu.asu.commons.foraging.model.ClientData; +import edu.asu.commons.foraging.model.ServerDataModel; import edu.asu.commons.net.Identifier; import edu.asu.commons.ui.HtmlEditorPane; import edu.asu.commons.ui.UserInterfaceUtils; @@ -61,8 +60,11 @@ private JMenuItem startChatMenuItem; private JMenuItem showTrustGameMenuItem; - private JMenuItem showVotingInstructionsMenuItem; + @SuppressWarnings("unused") + private JMenuItem showVotingInstructionsMenuItem; + @SuppressWarnings("unused") private JMenuItem showVoteScreenMenuItem; + @SuppressWarnings("unused") private JMenuItem showSurveyInstructionsMenuItem; private HtmlEditorPane messageEditorPane; @@ -265,7 +267,7 @@ repaint(); } - // FXIME: get rid of duplication here & displayDebriefing.. + // FIXME: get rid of duplication here & displayDebriefing.. public void updateDebriefing(FacilitatorSanctionUpdateEvent event) { Map<Identifier, ClientData> clientDataMap = event.getClientDataMap(); StringBuilder buffer = new StringBuilder(); @@ -291,59 +293,33 @@ informationEditorPane.setText(buffer.toString()); } - public void displayDebriefing(FacilitatorEndRoundEvent event) { - // FIXME: use StringTemplate instead - -// Map<Identifier, ClientData> clientDataMap = event.getClientDataMap(); - // this is the round that was just played. - RoundConfiguration roundConfiguration = facilitator.getCurrentRoundConfiguration(); - System.out.println("Displaying debriefing for round " + roundConfiguration); - instructionsBuilder = new StringBuilder(roundConfiguration.generateFacilitatorDebriefing(event.getServerDataModel())); -// instructionsBuilder = new StringBuilder(); - -// instructionsBuilder.append(String.format("<h3>%s Results</h3>", roundConfiguration.isPracticeRound() ? "Practice round" : "Round " + roundConfiguration.getRoundNumber())); -// List<String> headers = Arrays.asList("Participant", "Current tokens", "Current income", "Quiz earnings", "Trust game earnings", "Total income"); -// instructionsBuilder.append("<table><thead>"); -// for (String header : headers) { -// instructionsBuilder.append("<th>").append(header).append("</th>"); -// } -// instructionsBuilder.append("</thead><tbody>"); -// TreeSet<Identifier> orderedSet = new TreeSet<Identifier>(clientDataMap.keySet()); -// for (Identifier clientId : orderedSet) { -// ClientData data = clientDataMap.get(clientId); -// instructionsBuilder.append(String.format( -// "<tr><td>%s</td>" + -// "<td align='center'>%d</td>" + -// "<td align='center'>$%3.2f</td>" + -// "<td align='center'>$%3.2f</td>" + -// "<td align='center'>$%3.2f</td>" + -// "<td align='center'>$%3.2f</td>" + -// "</tr>", -// clientId.toString(), -// data.getCurrentTokens(), -// getIncome(data.getCurrentTokens()), -// getQuizEarnings(data), -// data.getTrustGameEarnings(), -// getTotalIncome(data))); -// } -// instructionsBuilder.append("</tbody></table><hr>"); -// if (event.isLastRound()) { -// instructionsBuilder.append("<h2><font color='blue'>The experiment is over. Please prepare payments.</font></h2>"); -// } - + public void displayDebriefing(ServerDataModel serverDataModel) { + RoundConfiguration roundConfiguration = serverDataModel.getRoundConfiguration(); + System.err.println("Displaying debriefing: " + roundConfiguration); + instructionsBuilder = new StringBuilder(roundConfiguration.generateFacilitatorDebriefing(serverDataModel)); showInstructionsMenuItem.setEnabled(true); stopRoundMenuItem.setEnabled(false); - } - - private double getTotalIncome(ClientData data) { - ServerConfiguration serverConfiguration = facilitator.getServerConfiguration(); - double quizEarnings = getQuizEarnings(data); - double trustGameEarnings = data.getTrustGameIncome(); - return data.getTotalIncome() + serverConfiguration.getShowUpPayment() + quizEarnings + trustGameEarnings; - } - - private double getQuizEarnings(ClientData data) { - return data.getCorrectQuizAnswers() * facilitator.getServerConfiguration().getQuizCorrectAnswerReward(); + if (serverDataModel.isLastRound()) { + instructionsBuilder.append(facilitator.getServerConfiguration().getFinalRoundFacilitatorInstructions()); + } + else { + RoundConfiguration upcomingRound = roundConfiguration.nextRound(); + boolean showInstructionsNext = true; + if (upcomingRound.isTrustGameEnabled()) { + showTrustGameMenuItem.setEnabled(true); + instructionsBuilder.append("<h2>TRUST GAME: Run a trust game next. Click on the Round menu and select Show Trust Game</h2>"); + showInstructionsNext = false; + } + if (upcomingRound.isChatRoundEnabled()) { + startChatMenuItem.setEnabled(true); + instructionsBuilder.append("<h2>COMMUNICATION ROUND: There is a communication round configured to run at the end of this round. Click on the Round menu and select Start Chat Round</h2>"); + showInstructionsNext = false; + } + if (showInstructionsNext) { + instructionsBuilder.append("<h2>SHOW INSTRUCTIONS: Click on the Round menu and select Show instructions when ready.</h2>"); + } + } + informationEditorPane.setText(instructionsBuilder.toString()); } private double getIncome(float numTokens) { @@ -356,32 +332,15 @@ public void endRound(FacilitatorEndRoundEvent endRoundEvent) { System.out.println("Ending round: " + endRoundEvent); - displayDebriefing(endRoundEvent); - if (endRoundEvent.isLastRound()) { - facilitator.endExperiment(); - } - else { - // FIXME: doesn't allow for very first round to be chat-enabled or trust-game-enabled - RoundConfiguration roundConfiguration = facilitator.getServerConfiguration().nextRound(); - boolean showInstructionsNext = true; - if (roundConfiguration.isTrustGameEnabled()) { - showTrustGameMenuItem.setEnabled(true); - instructionsBuilder.append("<h2>TRUST GAME: Run a trust game next. Click on the Round menu and select Show Trust Game</h2>"); - showInstructionsNext = false; - } - if (roundConfiguration.isChatRoundEnabled()) { - startChatMenuItem.setEnabled(true); - instructionsBuilder.append("<h2>COMMUNICATION ROUND: There is a communication round configured to run at the end of this round. Click on the Round menu and select Start Chat Round</h2>"); - showInstructionsNext = false; - } - if (showInstructionsNext) { - instructionsBuilder.append("<h2>SHOW INSTRUCTIONS: Click on the Round menu and select Show instructions when ready.</h2>"); - } - informationEditorPane.setText(instructionsBuilder.toString()); - } + ServerDataModel serverDataModel = endRoundEvent.getServerDataModel(); + displayDebriefing(serverDataModel); completedQuizzes = 0; completedTrustGames = 0; } + + public void setRoundConfiguration(RoundConfiguration roundConfiguration) { + + } public void configureForReplay() { //Enable the replay menus @@ -394,7 +353,7 @@ public void addMessage(String message) { try { - messageEditorPane.getDocument().insertString(0, message + "\n", null); + messageEditorPane.getDocument().insertString(0, "-----\n" + message + "\n", null); } catch (BadLocationException exception) { exception.printStackTrace(); @@ -411,4 +370,12 @@ addMessage(String.format("%d completed trust games (%s)", completedTrustGames, event)); } + public void updateTrustGame(TrustGameResultsFacilitatorEvent event) { + addMessage("Received new trust game payment data, recalculating debriefing."); + displayDebriefing(event.getServerDataModel()); + for (String result: event.getAllTrustGameResults()) { + addMessage(result); + } + } + } diff -r 57266c20ec10f43300ca88a52fed5ea331d82b9d -r 30069402c6a05dd6b4d62463a8aba1c362f3e103 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.logging.FileHandler; import java.util.logging.Handler; @@ -129,8 +128,6 @@ private volatile boolean experimentStarted; - private Random random = new Random(); - // FIXME: add the ability to reconfigure an already instantiated server public ForagingServer() { this(new ServerConfiguration()); @@ -720,7 +717,7 @@ trustGameResult)); } } - transmitAndStore(new TrustGameResultsFacilitatorEvent(facilitatorId, serverDataModel.getClientDataMap(), allTrustGameResults)); + transmitAndStore(new TrustGameResultsFacilitatorEvent(facilitatorId, serverDataModel, allTrustGameResults)); } protected boolean isReadyToStartRound() { Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 05:25:45
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/12876cd1bd8f/ changeset: 12876cd1bd8f user: alllee date: 2012-01-17 06:25:17 summary: minor hygiene and bugfixes for trust game earnings log, was using amountSent instead of totalAmountSent to display player 2 trust game log affected #: 3 files diff -r cb332a1f2783cf38c99c467895ab8ab8e893b776 -r 12876cd1bd8f3d434698704b527d1a37c530e3ee src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java --- a/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java @@ -418,6 +418,7 @@ double playerOneEarnings = playerOneAmountToKeep; double playerTwoEarnings = 0.0d; double amountReturnedToPlayerOne = 0.0d; + double totalAmountSent = amountSent * 3.0d; if (amountSent > 0) { int index = 0; if (amountSent == 0.25d) { @@ -430,25 +431,30 @@ index = 3; } playerTwoEarnings = playerTwoAmountsToKeep[index]; - double totalAmountSent = 3 * amountSent; amountReturnedToPlayerOne = totalAmountSent - playerTwoEarnings; playerOneEarnings += amountReturnedToPlayerOne; } - String playerOneLog = String.format("Player 1 kept %s and received %s back from Player 2 for a total of %s", - CURRENCY_FORMATTER.format(playerOneAmountToKeep), + String playerOneLog = String.format("Player 1 kept %s, sent %s, and received %s back from Player 2 for a total of %s", + CURRENCY_FORMATTER.format(playerOneAmountToKeep), + CURRENCY_FORMATTER.format(amountSent), CURRENCY_FORMATTER.format(amountReturnedToPlayerOne), CURRENCY_FORMATTER.format(playerOneEarnings)); playerOne.logTrustGame("You were player one. " + playerOneLog); playerOne.addTrustGameEarnings(playerOneEarnings); builder.append(playerOne).append(playerOneLog).append("\n"); if (shouldLogPlayerTwo(playerOne, playerTwo)) { - String playerTwoLog = String.format("Player 2 received %s and sent back %s to Player 1, earning %s", - CURRENCY_FORMATTER.format(amountSent), - CURRENCY_FORMATTER.format(amountSent - playerTwoEarnings), + String playerTwoLog = String.format("Player 2: received %s from Player 1 and sent back %s, earning %s", + CURRENCY_FORMATTER.format(totalAmountSent), + CURRENCY_FORMATTER.format(totalAmountSent - playerTwoEarnings), CURRENCY_FORMATTER.format(playerTwoEarnings)); - playerTwo.logTrustGame(playerTwoLog); + playerTwo.logTrustGame("You were player two. " + playerTwoLog); playerTwo.addTrustGameEarnings(playerTwoEarnings); - builder.append(playerTwoLog).append("\n"); + builder.append(playerTwo).append(playerTwoLog).append("\n"); + } + else { + builder.append( + String.format("Player 2: (%s) already participated in the trust game and was only used as a strategy to respond to Player 1.", + playerTwo)); } return builder.toString(); } diff -r cb332a1f2783cf38c99c467895ab8ab8e893b776 -r 12876cd1bd8f3d434698704b527d1a37c530e3ee src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -677,6 +677,9 @@ // FIXME: handle reconfiguration requests from facilitator } + /** + * Performs a random pairing of every member in the group to generate trust game payment results. + */ protected void processTrustGame() { List<String> allTrustGameResults = new ArrayList<String>(); for (GroupDataModel group : serverDataModel.getGroups()) { @@ -687,7 +690,6 @@ // using an iterator to consume both players and ensure that a player doesn't // have the trust game calculated on them twice (except as a player 2 selection) - boolean lastRound = getConfiguration().isLastRound(); for (ListIterator<ClientData> iter = clientList.listIterator(); iter.hasNext();) { ClientData playerOne = iter.next(); @@ -695,11 +697,14 @@ if (iter.hasNext()) { playerTwo = iter.next(); } - else { + // FIXME: upon second thought, this isn't strictly necessary as the list is already + // being shuffled and the random strategy needed to complete the pairings + // doesn't need to be doubly randomized +// else { // clumsy, see if we can express this differently // why doesn't listIterator offer a currentIndex() method as well? - playerTwo = clientList.get(random.nextInt(iter.previousIndex() + 1)); - } +// playerTwo = clientList.get(random.nextInt(iter.previousIndex() + 1)); +// } logger.info("TRUST GAME: about to pair " + playerOne + " with " + playerTwo); String trustGameResult = serverDataModel.calculateTrustGame(playerOne, playerTwo); allTrustGameResults.add(trustGameResult); diff -r cb332a1f2783cf38c99c467895ab8ab8e893b776 -r 12876cd1bd8f3d434698704b527d1a37c530e3ee src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -807,6 +807,7 @@ JPanel panel = getPanel(); cardLayout.show(panel, panelName); panel.repaint(); + mainPanel.requestFocusInWindow(); } public void updateDebriefing(final PostRoundSanctionUpdateEvent event) { @@ -886,7 +887,7 @@ @Override public void requestFocusInWindow() { - getPanel().requestFocusInWindow(); + mainPanel.requestFocusInWindow(); } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 03:24:39
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/cb332a1f2783/ changeset: cb332a1f2783 user: alllee date: 2012-01-17 04:24:40 summary: fixing reference to template config object affected #: 1 file diff -r 469558236f7e014f837f5fb345504aa5bb6c975e -r cb332a1f2783cf38c99c467895ab8ab8e893b776 src/main/resources/configuration/asu-experiments/2011/t1/server.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/server.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/server.xml @@ -190,7 +190,7 @@ </entry><entry key='facilitator-debriefing'><![CDATA[ -<h1>Round {cfg.roundNumber} results</h1> +<h1>Round {self.roundNumber} results</h1><hr><table border=1 cellspacing=3 cellpadding=3><tr> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-17 03:24:03
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/469558236f7e/ changeset: 469558236f7e user: alllee date: 2012-01-17 04:23:32 summary: persisting entire trust game log, adding trust game update events for client and facilitator, and some refactoring of trust game calculation algorithm. the second player is now randomly selected from all the participants that have already played the trust game, not just the first one. Also fixed a bug where the second time a player participated in the trust game would give them additional earnings and another trust log entry. affected #: 5 files diff -r f7ce903339bbb1d0a6e967b86221ed4a3ad647fb -r 469558236f7e014f837f5fb345504aa5bb6c975e src/main/java/edu/asu/commons/foraging/event/TrustGameResultsClientEvent.java --- /dev/null +++ b/src/main/java/edu/asu/commons/foraging/event/TrustGameResultsClientEvent.java @@ -0,0 +1,20 @@ +package edu.asu.commons.foraging.event; + +import edu.asu.commons.event.AbstractEvent; +import edu.asu.commons.foraging.model.ClientData; + +/** + * Used to update clients with their trust game log. + */ +public class TrustGameResultsClientEvent extends AbstractEvent { + private static final long serialVersionUID = -9129989958983083574L; + + private final ClientData clientData; + public TrustGameResultsClientEvent(ClientData clientData, String log) { + super(clientData.getId(), log); + this.clientData = clientData; + } + public ClientData getClientData() { + return clientData; + } +} diff -r f7ce903339bbb1d0a6e967b86221ed4a3ad647fb -r 469558236f7e014f837f5fb345504aa5bb6c975e src/main/java/edu/asu/commons/foraging/event/TrustGameResultsFacilitatorEvent.java --- /dev/null +++ b/src/main/java/edu/asu/commons/foraging/event/TrustGameResultsFacilitatorEvent.java @@ -0,0 +1,37 @@ +package edu.asu.commons.foraging.event; + +import java.util.List; +import java.util.Map; + +import edu.asu.commons.event.AbstractPersistableEvent; +import edu.asu.commons.foraging.model.ClientData; +import edu.asu.commons.net.Identifier; + +/** + * Persistable event usd to update the facilitator and store all the trust game results for the given round. + */ +public class TrustGameResultsFacilitatorEvent extends AbstractPersistableEvent { + + private static final long serialVersionUID = 5834548819829135618L; + private List<String> allTrustGameResults; + private Map<Identifier, ClientData> clientDataMap; + public TrustGameResultsFacilitatorEvent(Identifier facilitatorId, + Map<Identifier, ClientData> clientDataMap, List<String> allTrustGameResults) { + super(facilitatorId); + this.allTrustGameResults = allTrustGameResults; + this.clientDataMap = clientDataMap; + } + public List<String> getAllTrustGameResults() { + return allTrustGameResults; + } + public void setAllTrustGameResults(List<String> allTrustGameResults) { + this.allTrustGameResults = allTrustGameResults; + } + public Map<Identifier, ClientData> getClientDataMap() { + return clientDataMap; + } + public void setClientDataMap(Map<Identifier, ClientData> clientDataMap) { + this.clientDataMap = clientDataMap; + } + +} diff -r f7ce903339bbb1d0a6e967b86221ed4a3ad647fb -r 469558236f7e014f837f5fb345504aa5bb6c975e src/main/java/edu/asu/commons/foraging/model/ClientData.java --- a/src/main/java/edu/asu/commons/foraging/model/ClientData.java +++ b/src/main/java/edu/asu/commons/foraging/model/ClientData.java @@ -585,7 +585,7 @@ } public String toString() { - return String.format("id (%s) assigned number (%d)", id, assignedNumber); + return String.format("[%s #%d]", id, assignedNumber); } public void addTrustGameEarnings(double trustGameEarnings) { diff -r f7ce903339bbb1d0a6e967b86221ed4a3ad647fb -r 469558236f7e014f837f5fb345504aa5bb6c975e src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java --- a/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java @@ -414,8 +414,11 @@ double amountSent = 1.0d - playerOneAmountToKeep; StringBuilder builder = new StringBuilder(); builder.append(String.format("%s (Player 1) sent %s to %s (Player 2)\n", playerOne, CURRENCY_FORMATTER.format(amountSent), playerTwo)); + + double playerOneEarnings = playerOneAmountToKeep; + double playerTwoEarnings = 0.0d; + double amountReturnedToPlayerOne = 0.0d; if (amountSent > 0) { - double playerTwoEarnings = 0.0d; int index = 0; if (amountSent == 0.25d) { index = 0; @@ -428,29 +431,43 @@ } playerTwoEarnings = playerTwoAmountsToKeep[index]; double totalAmountSent = 3 * amountSent; - double amountReturnedToP1 = totalAmountSent - playerTwoEarnings; - double playerOneEarnings = playerOneAmountToKeep + amountReturnedToP1; - String playerOneLog = String.format("%s (Player 1) kept %s and received %s back from Player two for a total of %s", - playerOne, - CURRENCY_FORMATTER.format(playerOneAmountToKeep), - CURRENCY_FORMATTER.format(amountReturnedToP1), - CURRENCY_FORMATTER.format(playerOneEarnings)); - builder.append(playerOneLog).append("\n"); - playerOne.logTrustGame(playerOneLog); - playerOne.addTrustGameEarnings(playerOneAmountToKeep + amountReturnedToP1); - String playerTwoLog = String.format("%s (Player 2) and earned %s", playerTwo, playerTwoEarnings); - builder.append(playerTwoLog).append("\n"); - playerTwo.logTrustGame(playerTwoLog); - playerTwo.addTrustGameEarnings(playerTwoEarnings); + amountReturnedToPlayerOne = totalAmountSent - playerTwoEarnings; + playerOneEarnings += amountReturnedToPlayerOne; } - else { - String playerOneLog = String.format("%s (Player 1) sent nothing to Player 2 and earned %s", playerOne, playerOneAmountToKeep); - playerOne.logTrustGame(playerOneLog); - playerOne.addTrustGameEarnings(playerOneAmountToKeep); - playerTwo.logTrustGame(playerOneLog + " - you were player two and didn't receive anything."); + String playerOneLog = String.format("Player 1 kept %s and received %s back from Player 2 for a total of %s", + CURRENCY_FORMATTER.format(playerOneAmountToKeep), + CURRENCY_FORMATTER.format(amountReturnedToPlayerOne), + CURRENCY_FORMATTER.format(playerOneEarnings)); + playerOne.logTrustGame("You were player one. " + playerOneLog); + playerOne.addTrustGameEarnings(playerOneEarnings); + builder.append(playerOne).append(playerOneLog).append("\n"); + if (shouldLogPlayerTwo(playerOne, playerTwo)) { + String playerTwoLog = String.format("Player 2 received %s and sent back %s to Player 1, earning %s", + CURRENCY_FORMATTER.format(amountSent), + CURRENCY_FORMATTER.format(amountSent - playerTwoEarnings), + CURRENCY_FORMATTER.format(playerTwoEarnings)); + playerTwo.logTrustGame(playerTwoLog); + playerTwo.addTrustGameEarnings(playerTwoEarnings); + builder.append(playerTwoLog).append("\n"); } return builder.toString(); } + + /** + * Returns true if player two has not yet participated in the trust game as a player one, in which case their trust game log + * would already have an entry and so its size would be equivalent to the size of the player one log. In most cases it should + * always be 1 smaller than the player one trust game log + * + * @param playerOne + * @param playerTwo + * @return + */ + private boolean shouldLogPlayerTwo(ClientData playerOne, ClientData playerTwo) { + logger.info(String.format("%s (P1) log: %s vs. %s (P2) log: %s", playerOne, playerOne.getTrustGameLog(), + playerTwo, playerTwo.getTrustGameLog())); + // is this sufficient? + return playerTwo.getTrustGameLog().size() < playerOne.getTrustGameLog().size(); + } @Override public List<Identifier> getAllClientIdentifiers() { diff -r f7ce903339bbb1d0a6e967b86221ed4a3ad647fb -r 469558236f7e014f837f5fb345504aa5bb6c975e src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -7,10 +7,11 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; import java.util.Map; +import java.util.Random; import java.util.Set; import java.util.logging.FileHandler; import java.util.logging.Handler; @@ -62,6 +63,8 @@ import edu.asu.commons.foraging.event.ShowRequest; import edu.asu.commons.foraging.event.SurveyIdSubmissionRequest; import edu.asu.commons.foraging.event.SynchronizeClientEvent; +import edu.asu.commons.foraging.event.TrustGameResultsClientEvent; +import edu.asu.commons.foraging.event.TrustGameResultsFacilitatorEvent; import edu.asu.commons.foraging.event.TrustGameSubmissionEvent; import edu.asu.commons.foraging.event.TrustGameSubmissionRequest; import edu.asu.commons.foraging.event.UnlockResourceRequest; @@ -123,6 +126,8 @@ // private Duration chatDuration; private volatile boolean experimentStarted; + + private Random random = new Random(); // FIXME: add the ability to reconfigure an already instantiated server public ForagingServer() { @@ -247,7 +252,9 @@ public void handle(ConnectionEvent event) { // handle incoming connections if (experimentStarted) { - // do not allow any new connections + // currently not allowing any new connections + // FIXME: would be nice to allow for reconnection / reassociation of clients to ids and data. + // should be logged however so we can remember the context of the data transmit(new ClientMessageEvent(event.getId(), "The experiment has already started, we cannot add you at this time.")); return; } @@ -647,37 +654,17 @@ } // FIXME: groups have not been assigned in the transition between practice round and this round.. if (numberOfSubmissions >= clients.size()) { - // once all clients have submitted their decisions, execute the trust game. - for (GroupDataModel group : serverDataModel.getGroups()) { - LinkedList<ClientData> clientList = new LinkedList<ClientData>(group.getClientDataMap().values()); - Collections.shuffle(clientList); - logger.info("TRUST GAME shuffled client list: " + clientList); - ClientData first = clientList.getFirst(); - for (Iterator<ClientData> iter = clientList.iterator(); iter.hasNext();) { - ClientData playerOne = iter.next(); - ClientData playerTwo = first; - if (iter.hasNext()) { - playerTwo = iter.next(); - } - logger.info("TRUST GAME: about to pair " + playerOne + " with " + playerTwo); - String trustGameResults = serverDataModel.calculateTrustGame(playerOne, playerTwo); - sendFacilitatorMessage(String.format("Pairing %s with %s for trust game resulted in:\n\t %s", playerOne, playerTwo, - trustGameResults)); - } - } - transmit(new FacilitatorEndRoundEvent(facilitatorId, serverDataModel)); + // once all clients have submitted their decisions, execute the trust game. + processTrustGame(); numberOfSubmissions = 0; } } + }); addEventProcessor(new EventTypeProcessor<BeginChatRoundRequest>(BeginChatRoundRequest.class) { public void handle(BeginChatRoundRequest request) { if (getCurrentRoundConfiguration().isChatEnabled()) { - // FIXME: need to handle properly corner case where chat is enabled before the first round - // - at that point the clients haven't been added to any groups yet. - // another way to handle this is to have the clients added - // to groups when the show instructions request is handled.. sendFacilitatorMessage("Sending begin chat round request to all participants"); for (Map.Entry<Identifier, ClientData> entry : clients.entrySet()) { Identifier id = entry.getKey(); @@ -689,6 +676,45 @@ }); // FIXME: handle reconfiguration requests from facilitator } + + protected void processTrustGame() { + List<String> allTrustGameResults = new ArrayList<String>(); + for (GroupDataModel group : serverDataModel.getGroups()) { + LinkedList<ClientData> clientList = new LinkedList<ClientData>(group.getClientDataMap().values()); + Collections.shuffle(clientList); + logger.info("TRUST GAME shuffled client list: " + clientList); + ClientData first = clientList.getFirst(); + + // using an iterator to consume both players and ensure that a player doesn't + // have the trust game calculated on them twice (except as a player 2 selection) + + boolean lastRound = getConfiguration().isLastRound(); + for (ListIterator<ClientData> iter = clientList.listIterator(); iter.hasNext();) { + ClientData playerOne = iter.next(); + ClientData playerTwo = first; + if (iter.hasNext()) { + playerTwo = iter.next(); + } + else { + // clumsy, see if we can express this differently + // why doesn't listIterator offer a currentIndex() method as well? + playerTwo = clientList.get(random.nextInt(iter.previousIndex() + 1)); + } + logger.info("TRUST GAME: about to pair " + playerOne + " with " + playerTwo); + String trustGameResult = serverDataModel.calculateTrustGame(playerOne, playerTwo); + allTrustGameResults.add(trustGameResult); + if (lastRound) { + transmit(new TrustGameResultsClientEvent(playerOne, trustGameResult)); + transmit(new TrustGameResultsClientEvent(playerTwo, trustGameResult)); + } + + sendFacilitatorMessage(String.format("Pairing %s with %s for trust game resulted in:\n\t %s", playerOne, playerTwo, + trustGameResult)); + } + } + // FIXME: update facilitator AND clients if it is the last round of the experiment + transmit(new TrustGameResultsFacilitatorEvent(facilitatorId, serverDataModel.getClientDataMap(), allTrustGameResults)); + } protected boolean isReadyToStartRound() { if (getCurrentRoundConfiguration().isQuizEnabled()) { @@ -772,6 +798,7 @@ // persister MUST be initialized early so that we store pre-round events like QuizResponseEvent, ChatEvent, and the various Ranking // requests. setupRound(); + initializeGroups(); sendFacilitatorMessage("Ready to show instructions and the start next round."); if (getCurrentRoundConfiguration().isQuizEnabled()) { getLogger().info("Waiting for all quizzes to be submitted."); @@ -782,6 +809,9 @@ startRound(); break; case WAITING_FOR_CONNECTIONS: + // while waiting for connections we must defer group initialization till all clients + // are connected (which is unknown, we allow clients to connect until the experiment has started) + setupRound(); sendFacilitatorMessage("Ready to show instructions and the start next round."); if (getCurrentRoundConfiguration().isQuizEnabled()) { getLogger().info("Waiting for all quizzes to be submitted."); @@ -789,7 +819,7 @@ } // then wait for the signal from the facilitator to actually start the round (a chat session might occur or a voting session). Utils.waitOn(roundSignal); - setupRound(); + initializeGroups(); startRound(); break; default: @@ -799,7 +829,6 @@ private void setupRound() { persister.initialize(getCurrentRoundConfiguration()); - initializeGroups(); } private void stopRound() { @@ -870,7 +899,7 @@ // for (GroupDataModel group : serverDataModel.getGroups()) { // for (ClientData clientData : group.getClientDataMap().values()) { // // ask each client if it wants to grab a token, wherever it is. -// clientData.collectToken(); +// group.collectToken(clientData); // } // } for (GroupDataModel group : serverDataModel.getGroups()) { Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-16 21:38:34
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/f7ce903339bb/ changeset: f7ce903339bb user: alllee date: 2012-01-16 22:38:34 summary: adding facilitator debriefing template to server configuration affected #: 1 file diff -r 4bc5f2e09840acff13d8e0a5200f97e1d67a3525 -r f7ce903339bbb1d0a6e967b86221ed4a3ad647fb src/main/resources/configuration/asu-experiments/2011/t1/server.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/server.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/server.xml @@ -188,4 +188,18 @@ <p><b>Do you have any questions?</b> If you have any questions at this time please raise your hand and someone will come over to your station and answer it.</p> ]]></entry> +<entry key='facilitator-debriefing'> +<![CDATA[ +<h1>Round {cfg.roundNumber} results</h1> +<hr> +<table border=1 cellspacing=3 cellpadding=3> +<tr> +<th>Participant</th><th>Current tokens</th><th>Current income</th><th>Quiz earnings</th><th>Trust game earnings</th><th>Total income</th> +</tr> +{clientDataList: {data | +<tr><td>{data.id}</td><td>{data.currentTokens}</td><td>{data.currentIncome}</td><td>{data.quizEarnings}</td><td>{data.trustGameEarnings}</td><td>{data.grandTotalIncome}</td></tr> +}} +</table> +]]> +</entry></properties> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-16 07:30:01
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/4bc5f2e09840/ changeset: 4bc5f2e09840 user: alllee date: 2012-01-16 08:30:02 summary: kwexpand affected #: 2 files diff -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 -r 4bc5f2e09840acff13d8e0a5200f97e1d67a3525 src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java @@ -30,10 +30,10 @@ import edu.asu.commons.foraging.model.ServerDataModel; /** - * $Id: Facilitator.java 529 2010-08-17 00:08:01Z alllee $ + * $Id$ * * @author <a href='ano...@gm...'>Allen Lee</a>, Deepali Bhagvat - * @version $Revision: 529 $ + * @version $Revision$ */ public class Facilitator extends BaseFacilitator<ServerConfiguration> { diff -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 -r 4bc5f2e09840acff13d8e0a5200f97e1d67a3525 src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java --- a/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java @@ -40,13 +40,13 @@ import edu.asu.commons.net.Identifier; /** - * $Id: ServerDataModel.java 508 2010-04-19 08:02:04Z alllee $ + * $Id$ * * The ForagerServerGameState is the data model needed on the server side. * * * @author Allen Lee, Deepali Bhagvat - * @version $Revision: 508 $ + * @version $Revision$ */ public class ServerDataModel extends ForagingDataModel { Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-16 07:27:03
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/88d0e042e52b/ changeset: 88d0e042e52b user: alllee date: 2012-01-16 08:26:27 summary: templatizing facilitator debriefing and refactoring income calculations. Temporarily adding a number of transient String variables to ClientData so we can inject the information we need when rendering out the facilitator debriefing - should look for a better long-term solution. affected #: 8 files diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -11,12 +11,14 @@ import java.util.concurrent.TimeUnit; import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroupString; import edu.asu.commons.conf.ExperimentRoundParameters; import edu.asu.commons.foraging.graphics.Point3D; import edu.asu.commons.foraging.model.ClientData; import edu.asu.commons.foraging.model.EnforcementMechanism; import edu.asu.commons.foraging.model.ResourceDispenser; +import edu.asu.commons.foraging.model.ServerDataModel; import edu.asu.commons.foraging.rules.ForagingRule; import edu.asu.commons.net.Identifier; import edu.asu.commons.util.Duration; @@ -750,6 +752,10 @@ return template.render(); } + public String getFacilitatorDebriefing() { + return getProperty("facilitator-debriefing", getParentConfiguration().getFacilitatorDebriefing()); + } + @Override public String toString() { List<RoundConfiguration> allParameters = getParentConfiguration().getAllParameters(); @@ -774,4 +780,23 @@ public void setSelectedRules(List<ForagingRule> selectedRules) { this.selectedRules = selectedRules; } + + public double tokensToDollars(int tokens) { + return isPracticeRound() ? 0.0d : tokens * getDollarsPerToken(); + } + + public String generateFacilitatorDebriefing(ServerDataModel serverDataModel) { + ST template = createStringTemplate(getFacilitatorDebriefing()); + template.add("lastRound", serverDataModel.isLastRound()); + ServerConfiguration serverConfiguration = getParentConfiguration(); + NumberFormat formatter = NumberFormat.getCurrencyInstance(); + for (ClientData data: serverDataModel.getClientDataMap().values()) { + data.setGrandTotalIncome(formatter.format(serverConfiguration.getTotalIncome(data))); + data.setCurrentIncome(formatter.format(tokensToDollars(data.getCurrentTokens()))); + data.setQuizEarnings(formatter.format(serverConfiguration.getQuizEarnings(data))); + data.setTrustGameEarnings(formatter.format(data.getTrustGameIncome())); + } + template.add("clientDataList", serverDataModel.getClientDataMap().values()); + return template.render(); + } } diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java @@ -5,6 +5,7 @@ import org.stringtemplate.v4.ST; import edu.asu.commons.conf.ExperimentConfiguration; +import edu.asu.commons.foraging.model.ClientData; /** * $Id$ @@ -111,5 +112,17 @@ public double getDollarsPerToken() { return DEFAULT_DOLLARS_PER_TOKEN; } + + public String getFacilitatorDebriefing() { + return assistant.getProperty("facilitator-debriefing"); + } + + public double getTotalIncome(ClientData data) { + return data.getTotalIncome() + getShowUpPayment() + getQuizEarnings(data) + data.getTrustGameIncome(); + } + + public double getQuizEarnings(ClientData data) { + return data.getCorrectQuizAnswers() * getQuizCorrectAnswerReward(); + } } diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/Facilitator.java @@ -198,7 +198,6 @@ public static void main(String[] args) { Runnable createGuiRunnable = new Runnable() { - public void run() { Dimension dimension = new Dimension(700, 700); Facilitator facilitator = Facilitator.getInstance(); diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java @@ -292,40 +292,44 @@ } public void displayDebriefing(FacilitatorEndRoundEvent event) { - Map<Identifier, ClientData> clientDataMap = event.getClientDataMap(); + // FIXME: use StringTemplate instead + +// Map<Identifier, ClientData> clientDataMap = event.getClientDataMap(); // this is the round that was just played. RoundConfiguration roundConfiguration = facilitator.getCurrentRoundConfiguration(); - instructionsBuilder = new StringBuilder(); + System.out.println("Displaying debriefing for round " + roundConfiguration); + instructionsBuilder = new StringBuilder(roundConfiguration.generateFacilitatorDebriefing(event.getServerDataModel())); +// instructionsBuilder = new StringBuilder(); - instructionsBuilder.append(String.format("<h3>%s Results</h3>", roundConfiguration.isPracticeRound() ? "Practice round" : "Round " + roundConfiguration.getRoundNumber())); - List<String> headers = Arrays.asList("Participant", "Current tokens", "Current income", "Quiz earnings", "Trust game earnings", "Total income"); - instructionsBuilder.append("<table><thead>"); - for (String header : headers) { - instructionsBuilder.append("<th>").append(header).append("</th>"); - } - instructionsBuilder.append("</thead><tbody>"); - TreeSet<Identifier> orderedSet = new TreeSet<Identifier>(clientDataMap.keySet()); - for (Identifier clientId : orderedSet) { - ClientData data = clientDataMap.get(clientId); - instructionsBuilder.append(String.format( - "<tr><td>%s</td>" + - "<td align='center'>%d</td>" + - "<td align='center'>$%3.2f</td>" + - "<td align='center'>$%3.2f</td>" + - "<td align='center'>$%3.2f</td>" + - "<td align='center'>$%3.2f</td>" + - "</tr>", - clientId.toString(), - data.getCurrentTokens(), - getIncome(data.getCurrentTokens()), - getQuizEarnings(data), - data.getTrustGameEarnings(), - getTotalIncome(data))); - } - instructionsBuilder.append("</tbody></table><hr>"); - if (event.isLastRound()) { - instructionsBuilder.append("<h2><font color='blue'>The experiment is over. Please prepare payments.</font></h2>"); - } +// instructionsBuilder.append(String.format("<h3>%s Results</h3>", roundConfiguration.isPracticeRound() ? "Practice round" : "Round " + roundConfiguration.getRoundNumber())); +// List<String> headers = Arrays.asList("Participant", "Current tokens", "Current income", "Quiz earnings", "Trust game earnings", "Total income"); +// instructionsBuilder.append("<table><thead>"); +// for (String header : headers) { +// instructionsBuilder.append("<th>").append(header).append("</th>"); +// } +// instructionsBuilder.append("</thead><tbody>"); +// TreeSet<Identifier> orderedSet = new TreeSet<Identifier>(clientDataMap.keySet()); +// for (Identifier clientId : orderedSet) { +// ClientData data = clientDataMap.get(clientId); +// instructionsBuilder.append(String.format( +// "<tr><td>%s</td>" + +// "<td align='center'>%d</td>" + +// "<td align='center'>$%3.2f</td>" + +// "<td align='center'>$%3.2f</td>" + +// "<td align='center'>$%3.2f</td>" + +// "<td align='center'>$%3.2f</td>" + +// "</tr>", +// clientId.toString(), +// data.getCurrentTokens(), +// getIncome(data.getCurrentTokens()), +// getQuizEarnings(data), +// data.getTrustGameEarnings(), +// getTotalIncome(data))); +// } +// instructionsBuilder.append("</tbody></table><hr>"); +// if (event.isLastRound()) { +// instructionsBuilder.append("<h2><font color='blue'>The experiment is over. Please prepare payments.</font></h2>"); +// } showInstructionsMenuItem.setEnabled(true); stopRoundMenuItem.setEnabled(false); @@ -334,7 +338,7 @@ private double getTotalIncome(ClientData data) { ServerConfiguration serverConfiguration = facilitator.getServerConfiguration(); double quizEarnings = getQuizEarnings(data); - double trustGameEarnings = data.getTrustGameEarnings(); + double trustGameEarnings = data.getTrustGameIncome(); return data.getTotalIncome() + serverConfiguration.getShowUpPayment() + quizEarnings + trustGameEarnings; } @@ -351,6 +355,7 @@ } public void endRound(FacilitatorEndRoundEvent endRoundEvent) { + System.out.println("Ending round: " + endRoundEvent); displayDebriefing(endRoundEvent); if (endRoundEvent.isLastRound()) { facilitator.endExperiment(); diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/model/ClientData.java --- a/src/main/java/edu/asu/commons/foraging/model/ClientData.java +++ b/src/main/java/edu/asu/commons/foraging/model/ClientData.java @@ -40,7 +40,6 @@ private ForagingRole foragingRole = ForagingRole.HARVEST; - private double totalIncome; private int totalTokens; private int currentTokens; private int tokensCollectedLastRound; @@ -70,8 +69,14 @@ private ForagingRule votedRule; private ArrayList<String> trustGameLog = new ArrayList<String>(); + + private String grandTotalIncome; + private String currentIncome; + private String quizEarnings; + private String trustGameEarnings; - private double trustGameEarnings = 0.0d; + private double totalIncome = 0.0d; + private double trustGameIncome = 0.0d; private int correctQuizAnswers = 0; public void setTrustGamePlayerOneAmountToKeep(double trustGamePlayerOneAmountToKeep) { @@ -398,9 +403,9 @@ } } -// public void setCollecting() { -// collecting = true; -// } + public void setCollecting() { + collecting = true; + } public void collectToken() { // if (collecting) { @@ -584,14 +589,14 @@ } public void addTrustGameEarnings(double trustGameEarnings) { - this.trustGameEarnings += trustGameEarnings; + this.trustGameIncome += trustGameEarnings; } - public double getTrustGameEarnings() { - return trustGameEarnings; + public double getTrustGameIncome() { + return trustGameIncome; } - public void logTrustGameEarnings(String log) { + public void logTrustGame(String log) { trustGameLog.add(log); } @@ -618,5 +623,38 @@ public String getSurveyId() { return getId().getSurveyId(); } - + + public String getGrandTotalIncome() { + return grandTotalIncome; + } + + public void setGrandTotalIncome(String grandTotalIncome) { + this.grandTotalIncome = grandTotalIncome; + } + + public String getCurrentIncome() { + return currentIncome; + } + + public void setCurrentIncome(String currentIncome) { + this.currentIncome = currentIncome; + } + + public String getQuizEarnings() { + return quizEarnings; + } + + public void setQuizEarnings(String quizEarnings) { + this.quizEarnings = quizEarnings; + } + + public void setTrustGameEarnings(String trustGameEarnings) { + this.trustGameEarnings = trustGameEarnings; + } + + public String getTrustGameEarnings() { + return trustGameEarnings; + } + + } diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java --- a/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/model/ServerDataModel.java @@ -4,6 +4,7 @@ import java.awt.Point; import java.io.IOException; import java.io.ObjectInputStream; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -52,6 +53,8 @@ private static final long serialVersionUID = 8166812955398387600L; private transient Logger logger = Logger.getLogger( getClass().getName() ); + + private final static NumberFormat CURRENCY_FORMATTER = NumberFormat.getCurrencyInstance(); private transient Random random = new Random(); @@ -401,16 +404,18 @@ public String calculateTrustGame(ClientData playerOne, ClientData playerTwo) { if (playerOne.getId().equals(playerTwo.getId())) { - return "Tried to calculate trust game with self, aborting"; + String errorMessage = playerOne + " tried to calculate trust game with self, aborting"; + logger.warning(errorMessage); + return errorMessage; } - double p1AmountToKeep = playerOne.getTrustGamePlayerOneAmountToKeep(); - double[] p2AmountsToKeep = playerTwo.getTrustGamePlayerTwoAmountsToKeep(); + double playerOneAmountToKeep = playerOne.getTrustGamePlayerOneAmountToKeep(); + double[] playerTwoAmountsToKeep = playerTwo.getTrustGamePlayerTwoAmountsToKeep(); - double amountSent = 1.0d - p1AmountToKeep; + double amountSent = 1.0d - playerOneAmountToKeep; StringBuilder builder = new StringBuilder(); - builder.append(String.format("Player one (%s) sent %s to player two (%s)\n", playerOne, amountSent, playerTwo)); + builder.append(String.format("%s (Player 1) sent %s to %s (Player 2)\n", playerOne, CURRENCY_FORMATTER.format(amountSent), playerTwo)); if (amountSent > 0) { - double p2AmountToKeep = 0.0d; + double playerTwoEarnings = 0.0d; int index = 0; if (amountSent == 0.25d) { index = 0; @@ -421,23 +426,28 @@ } else if (amountSent == 1.0d) { index = 3; } - p2AmountToKeep = p2AmountsToKeep[index]; + playerTwoEarnings = playerTwoAmountsToKeep[index]; double totalAmountSent = 3 * amountSent; - double amountReturnedToP1 = totalAmountSent - p2AmountToKeep; - String playerOneLog = String.format("Player one (%s) earned %s + %s = %s", playerOne, p1AmountToKeep, amountReturnedToP1, p1AmountToKeep + amountReturnedToP1); + double amountReturnedToP1 = totalAmountSent - playerTwoEarnings; + double playerOneEarnings = playerOneAmountToKeep + amountReturnedToP1; + String playerOneLog = String.format("%s (Player 1) kept %s and received %s back from Player two for a total of %s", + playerOne, + CURRENCY_FORMATTER.format(playerOneAmountToKeep), + CURRENCY_FORMATTER.format(amountReturnedToP1), + CURRENCY_FORMATTER.format(playerOneEarnings)); builder.append(playerOneLog).append("\n"); - playerOne.logTrustGameEarnings(playerOneLog); - playerOne.addTrustGameEarnings(p1AmountToKeep + amountReturnedToP1); - String playerTwoLog = String.format("Player two (%s) earned %s", playerTwo, p2AmountToKeep); + playerOne.logTrustGame(playerOneLog); + playerOne.addTrustGameEarnings(playerOneAmountToKeep + amountReturnedToP1); + String playerTwoLog = String.format("%s (Player 2) and earned %s", playerTwo, playerTwoEarnings); builder.append(playerTwoLog).append("\n"); - playerTwo.logTrustGameEarnings(playerTwoLog); - playerTwo.addTrustGameEarnings(p2AmountToKeep); + playerTwo.logTrustGame(playerTwoLog); + playerTwo.addTrustGameEarnings(playerTwoEarnings); } else { - String playerOneLog = "Player one " + playerOne + " didn't send any money and kept: " + p1AmountToKeep; - playerOne.logTrustGameEarnings(playerOneLog); - playerOne.addTrustGameEarnings(p1AmountToKeep); - playerTwo.logTrustGameEarnings(playerOneLog + " - you were player two and didn't receive anything."); + String playerOneLog = String.format("%s (Player 1) sent nothing to Player 2 and earned %s", playerOne, playerOneAmountToKeep); + playerOne.logTrustGame(playerOneLog); + playerOne.addTrustGameEarnings(playerOneAmountToKeep); + playerTwo.logTrustGame(playerOneLog + " - you were player two and didn't receive anything."); } return builder.toString(); } diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -661,10 +661,11 @@ } logger.info("TRUST GAME: about to pair " + playerOne + " with " + playerTwo); String trustGameResults = serverDataModel.calculateTrustGame(playerOne, playerTwo); - sendFacilitatorMessage(String.format("Pairing %s with %s for trust game resulted in: %s", playerOne, playerTwo, + sendFacilitatorMessage(String.format("Pairing %s with %s for trust game resulted in:\n\t %s", playerOne, playerTwo, trustGameResults)); } } + transmit(new FacilitatorEndRoundEvent(facilitatorId, serverDataModel)); numberOfSubmissions = 0; } } @@ -846,22 +847,22 @@ private void processRound() { boolean secondHasPassed = secondTick.hasExpired(); if (secondHasPassed) { - // handle rotating monitors. - if (getCurrentRoundConfiguration().isRotatingMonitorEnabled() - && currentRoundDuration.getElapsedTimeInSeconds() % monitorRotationInterval == 0) - { - for (GroupDataModel group : serverDataModel.getGroups()) { - boolean rotated = group.rotateMonitorIfNecessary(); - if (rotated) { - // send new roles to all clients - // FIXME: this is inefficient, we could synchronize twice. - for (ClientData clientData : group.getClientDataMap().values()) { - transmit(new SynchronizeClientEvent(clientData, currentRoundDuration.getTimeLeft())); - } - } - - } - } + // XXX: rotating monitor handling currently disabled, find a new place for this logic. +// if (getCurrentRoundConfiguration().isRotatingMonitorEnabled() +// && currentRoundDuration.getElapsedTimeInSeconds() % monitorRotationInterval == 0) +// { +// for (GroupDataModel group : serverDataModel.getGroups()) { +// boolean rotated = group.rotateMonitorIfNecessary(); +// if (rotated) { +// // send new roles to all clients +// // FIXME: this is inefficient, we could synchronize twice. +// for (ClientData clientData : group.getClientDataMap().values()) { +// transmit(new SynchronizeClientEvent(clientData, currentRoundDuration.getTimeLeft())); +// } +// } +// +// } +// } resourceDispenser.generateResources(); secondTick.restart(); } diff -r f4e75ba7256a7a069918fead050f2a65923efca5 -r 88d0e042e52b794fc0b6ebdb88d2878c1ff0e410 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -630,6 +630,7 @@ instructionsBuilder.append(trustGameLog); } if (event.isLastRound()) { + // FIXME: show final round debriefing explicitly // for (String trustGameLog : event.getTrustGameLog()) { // instructionsBuilder.append(trustGameLog); // } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-13 00:11:06
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/f4e75ba7256a/ changeset: f4e75ba7256a user: alllee date: 2012-01-13 01:11:02 summary: fixes issue 26 - getting rid of collecting flag on ClientData in favor of handling the token collection immediately. This does muck up our ability to have an implicit collection mode, will need to fix that support later - adding a third state to ServerState to distinguish between waiting on initial connections to the server and being in between rounds. It's kludgy but works for now until we can figure out a more elegant design. affected #: 6 files diff -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 -r f4e75ba7256a7a069918fead050f2a65923efca5 src/main/java/edu/asu/commons/foraging/event/ShowFinalRoundDebriefingRequest.java --- /dev/null +++ b/src/main/java/edu/asu/commons/foraging/event/ShowFinalRoundDebriefingRequest.java @@ -0,0 +1,26 @@ +package edu.asu.commons.foraging.event; + +import edu.asu.commons.event.AbstractEvent; +import edu.asu.commons.net.Identifier; + +/** + * $Id$ + * + * Facilitator request to show the final round debriefing on each client. + * + * @author <a href='mailto:all...@as...'>Allen Lee</a> + * @version $Rev$ + */ +public class ShowFinalRoundDebriefingRequest extends AbstractEvent implements ShowRequest<ShowFinalRoundDebriefingRequest> { + + private static final long serialVersionUID = 4971173111061909285L; + + public ShowFinalRoundDebriefingRequest(Identifier id) { + super(id); + } + + @Override + public ShowFinalRoundDebriefingRequest copy(Identifier id) { + return new ShowFinalRoundDebriefingRequest(id); + } +} diff -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 -r f4e75ba7256a7a069918fead050f2a65923efca5 src/main/java/edu/asu/commons/foraging/event/ShowInstructionsRequest.java --- a/src/main/java/edu/asu/commons/foraging/event/ShowInstructionsRequest.java +++ b/src/main/java/edu/asu/commons/foraging/event/ShowInstructionsRequest.java @@ -3,6 +3,14 @@ import edu.asu.commons.event.AbstractEvent; import edu.asu.commons.net.Identifier; +/** + * $Id$ + * + * + * + * @author <a href='mailto:all...@as...'>Allen Lee</a> + * @version $Rev$ + */ public class ShowInstructionsRequest extends AbstractEvent implements ShowRequest<ShowInstructionsRequest> { private static final long serialVersionUID = 3774308614796618926L; diff -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 -r f4e75ba7256a7a069918fead050f2a65923efca5 src/main/java/edu/asu/commons/foraging/event/ShowRequest.java --- a/src/main/java/edu/asu/commons/foraging/event/ShowRequest.java +++ b/src/main/java/edu/asu/commons/foraging/event/ShowRequest.java @@ -12,8 +12,5 @@ * @version $Rev$ */ public interface ShowRequest<T extends ShowRequest<T>> extends FacilitatorRequest { - - public T copy(Identifier id); - } diff -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 -r f4e75ba7256a7a069918fead050f2a65923efca5 src/main/java/edu/asu/commons/foraging/model/ClientData.java --- a/src/main/java/edu/asu/commons/foraging/model/ClientData.java +++ b/src/main/java/edu/asu/commons/foraging/model/ClientData.java @@ -398,15 +398,15 @@ } } - public void setCollecting() { - collecting = true; - } +// public void setCollecting() { +// collecting = true; +// } public void collectToken() { - if (collecting) { - getGroupDataModel().collectToken(this); - } - collecting = false; +// if (collecting) { + getGroupDataModel().collectToken(this); +// } +// collecting = false; } public boolean isExplicitCollectionMode() { diff -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 -r f4e75ba7256a7a069918fead050f2a65923efca5 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -17,7 +17,6 @@ import java.util.logging.Logger; import java.util.logging.SimpleFormatter; -import edu.asu.commons.command.Command; import edu.asu.commons.event.BeginRoundRequest; import edu.asu.commons.event.ChatEvent; import edu.asu.commons.event.ChatRequest; @@ -190,17 +189,26 @@ protected StateMachine getStateMachine() { return stateMachine; } - + private RoundConfiguration getCurrentRoundConfiguration() { return getConfiguration().getCurrentParameters(); } enum ServerState { - WAITING, ROUND_IN_PROGRESS - }; + WAITING_FOR_CONNECTIONS, IN_BETWEEN_ROUNDS, ROUND_IN_PROGRESS; + public boolean isWaiting() { + switch (this) { + case WAITING_FOR_CONNECTIONS: + case IN_BETWEEN_ROUNDS: + return true; + default: + return false; + } + + } + } private class ForagingStateMachine implements StateMachine { - private Command roundProcessor; private ServerDataModel serverDataModel; private ResourceDispenser resourceDispenser; private ServerState serverState; @@ -211,34 +219,14 @@ * Initializes the state machine before the experiment ever begins. */ public void initialize() { - serverState = ServerState.WAITING; + serverState = ServerState.WAITING_FOR_CONNECTIONS; serverDataModel = new ServerDataModel(getEventChannel()); - // these two seem to be paired up frequently. serverDataModel.setRoundConfiguration(getCurrentRoundConfiguration()); - initializeRoundProcessor(); resourceDispenser = new ResourceDispenser(serverDataModel); initializeClientHandlers(); initializeFacilitatorHandlers(); } - // FIXME: remove this as we phase out the 3d environment - private void initializeRoundProcessor() { - if (serverDataModel.getRoundConfiguration().is2dExperiment()) { - roundProcessor = new Command() { - public void execute() { - processRound2d(); - } - }; - } - else { - roundProcessor = new Command() { - public void execute() { - processRound3d(); - } - }; - } - } - private void initializeClientHandlers() { addEventProcessor(new EventTypeProcessor<SocketIdentifierUpdateRequest>(SocketIdentifierUpdateRequest.class) { @Override @@ -287,7 +275,7 @@ sendFacilitatorMessage("configuration doesn't allow for chat but received " + request); return; } - relayChatRequest(request); + relayChatRequest(request); } }); addEventProcessor(new EventTypeProcessor<FacilitatorCensoredChatRequest>(FacilitatorCensoredChatRequest.class) { @@ -340,6 +328,82 @@ } } }); + addEventProcessor(new EventTypeProcessor<ClientMovementRequest>(ClientMovementRequest.class) { + public void handle(ClientMovementRequest event) { + if (serverState == ServerState.IN_BETWEEN_ROUNDS) + return; + Identifier id = event.getId(); + Direction direction = event.getDirection(); + serverDataModel.moveClient(id, direction); + } + }); + + addEventProcessor(new EventTypeProcessor<ExplicitCollectionModeRequest>(ExplicitCollectionModeRequest.class) { + public void handleInExperimentThread(ExplicitCollectionModeRequest event) { + clients.get(event.getId()).setExplicitCollectionMode(event.isExplicitCollectionMode()); + } + }); + addEventProcessor(new EventTypeProcessor<CollectTokenRequest>(CollectTokenRequest.class) { + @Override + public void handleInExperimentThread(CollectTokenRequest event) { + ClientData clientData = clients.get(event.getId()); + clientData.collectToken(); + // clientData.setCollecting(); + } + }); + addEventProcessor(new EventTypeProcessor<ResetTokenDistributionRequest>(ResetTokenDistributionRequest.class) { + public void handleInExperimentThread(ResetTokenDistributionRequest event) { + resourceDispenser.resetTokenDistribution(event); + } + }); + addEventProcessor(new EventTypeProcessor<RuleVoteRequest>(RuleVoteRequest.class) { + int votesReceived = 0; + + @Override + public void handle(RuleVoteRequest request) { + sendFacilitatorMessage("Received vote rule request: " + request); + ClientData client = clients.get(request.getId()); + client.setVotedRule(request.getRule()); + votesReceived++; + if (votesReceived >= clients.size()) { + // calculate votes + for (GroupDataModel group : serverDataModel.getGroups()) { + Map<ForagingRule, Integer> votingResults = group.generateVotingResults(); + List<ForagingRule> selectedRules = group.getSelectedRules(); + for (Identifier id : group.getClientIdentifiers()) { + sendFacilitatorMessage(String.format( + "%s selected [%s] from all rules (%s)", + group, selectedRules, votingResults)); + transmit(new RuleSelectedUpdateEvent(id, selectedRules, votingResults)); + } + + } + } + } + }); + addEventProcessor(new EventTypeProcessor<RealTimeSanctionRequest>(RealTimeSanctionRequest.class) { + @Override + public void handleInExperimentThread(final RealTimeSanctionRequest request) { + handleRealTimeSanctionRequest(request); + // validate request + // a user can sanction iff the following hold: + // 1. sanctioning is enabled or they are the monitor + // 2. the sanctioner has tokens + // 3. the resource distribution is non-empty + // if (getCurrentRoundConfiguration().isVotingAndRegulationEnabled()) { + // handleEnforcementSanctionRequest(request); + // } + // else { + + // } + } + }); + + } + + @Deprecated + @SuppressWarnings("unused") + private void initialize3DHandlers() { // 3d handlers addEventProcessor(new EventTypeProcessor<AgentInfoRequest>(AgentInfoRequest.class) { public void handle(AgentInfoRequest event) { @@ -357,78 +421,9 @@ } } }); - - addEventProcessor(new EventTypeProcessor<ClientMovementRequest>(ClientMovementRequest.class) { - public void handle(ClientMovementRequest event) { - if (serverState == ServerState.WAITING) - return; - Identifier id = event.getId(); - Direction direction = event.getDirection(); - serverDataModel.moveClient(id, direction); - } - }); - addEventProcessor(new EventTypeProcessor<ExplicitCollectionModeRequest>(ExplicitCollectionModeRequest.class) { - public void handleInExperimentThread(ExplicitCollectionModeRequest event) { - clients.get(event.getId()).setExplicitCollectionMode(event.isExplicitCollectionMode()); - } - }); - addEventProcessor(new EventTypeProcessor<CollectTokenRequest>(CollectTokenRequest.class) { - public void handle(CollectTokenRequest event) { - ClientData clientData = clients.get(event.getId()); - // FIXME: change this to collect the token immediately - clientData.setCollecting(); - } - }); - addEventProcessor(new EventTypeProcessor<ResetTokenDistributionRequest>(ResetTokenDistributionRequest.class) { - public void handleInExperimentThread(ResetTokenDistributionRequest event) { - resourceDispenser.resetTokenDistribution(event); - } - }); - addEventProcessor(new EventTypeProcessor<RuleVoteRequest>(RuleVoteRequest.class) { - int votesReceived = 0; - @Override - public void handle(RuleVoteRequest request) { - sendFacilitatorMessage("Received vote rule request: " + request); - ClientData client = clients.get(request.getId()); - client.setVotedRule(request.getRule()); - votesReceived++; - if (votesReceived >= clients.size()) { - // calculate votes - for (GroupDataModel group: serverDataModel.getGroups()) { - Map<ForagingRule, Integer> votingResults = group.generateVotingResults(); - List<ForagingRule> selectedRules = group.getSelectedRules(); - for (Identifier id: group.getClientIdentifiers()) { - sendFacilitatorMessage(String.format( - "%s selected [%s] from all rules (%s)", - group, selectedRules, votingResults)); - transmit(new RuleSelectedUpdateEvent(id, selectedRules, votingResults)); - } - - } - } - - - } - }); - addEventProcessor(new EventTypeProcessor<RealTimeSanctionRequest>(RealTimeSanctionRequest.class) { - @Override - public void handleInExperimentThread(final RealTimeSanctionRequest request) { - // validate request - // a user can sanction iff the following hold: - // 1. sanctioning is enabled or they are the monitor - // 2. the sanctioner has tokens - // 3. the resource distribution is non-empty - if (getCurrentRoundConfiguration().isVotingAndRegulationEnabled()) { - handleEnforcementSanctionRequest(request); - } - else { - handleRealTimeSanctionRequest(request); - } - } - }); addEventProcessor(new EventTypeProcessor<ClientPoseUpdate>(ClientPoseUpdate.class) { public void handleInExperimentThread(ClientPoseUpdate event) { - if (serverState == ServerState.WAITING) + if (serverState == ServerState.IN_BETWEEN_ROUNDS) return; ClientData client = clients.get(event.getId()); client.setPosition(event.getPosition()); @@ -437,10 +432,9 @@ client.setAnimationActiveFlag(event.isAnimationActive()); } }); - // FIXME: turn into lockResource/unlockResource? addEventProcessor(new EventTypeProcessor<LockResourceRequest>(LockResourceRequest.class) { public void handleInExperimentThread(LockResourceRequest event) { - if (serverState == ServerState.WAITING) + if (serverState == ServerState.IN_BETWEEN_ROUNDS) return; boolean successfullyLocked = serverDataModel.lockResource(event); transmit(new LockResourceEvent(event.getId(), event.getResource(), successfullyLocked)); @@ -448,27 +442,29 @@ }); addEventProcessor(new EventTypeProcessor<UnlockResourceRequest>(UnlockResourceRequest.class) { public void handleInExperimentThread(UnlockResourceRequest event) { - if (serverState == ServerState.WAITING) + if (serverState == ServerState.IN_BETWEEN_ROUNDS) return; serverDataModel.unlockResource(event); } }); addEventProcessor(new EventTypeProcessor<HarvestResourceRequest>(HarvestResourceRequest.class) { public void handleInExperimentThread(HarvestResourceRequest event) { - if (serverState == ServerState.WAITING) + if (serverState == ServerState.IN_BETWEEN_ROUNDS) return; serverDataModel.harvestResource(event); } }); addEventProcessor(new EventTypeProcessor<HarvestFruitRequest>(HarvestFruitRequest.class) { public void handleInExperimentThread(HarvestFruitRequest event) { - if (serverState == ServerState.WAITING) + if (serverState == ServerState.IN_BETWEEN_ROUNDS) return; serverDataModel.harvestFruits(event); } }); } + @SuppressWarnings("unused") + @Deprecated private void handleEnforcementSanctionRequest(RealTimeSanctionRequest request) { ClientData sourceClient = clients.get(request.getSource()); ClientData targetClient = clients.get(request.getTarget()); @@ -519,7 +515,8 @@ ClientData targetClient = clients.get(request.getTarget()); // validate request // FIXME:Added a new test condition to check for the simplified version of sanctioning - boolean invalidSanctionRequest = sourceClient.getCurrentTokens() == 0 || targetClient.getCurrentTokens() == 0 || sourceClient.getGroupDataModel().isResourceDistributionEmpty(); + boolean invalidSanctionRequest = sourceClient.getCurrentTokens() == 0 || targetClient.getCurrentTokens() == 0 + || sourceClient.getGroupDataModel().isResourceDistributionEmpty(); if (invalidSanctionRequest) { // ignore the sanction request, send a message to the sanctioner. logger.warning("Ignoring token reduction request, sending new client error message event to : " + sourceClient.getId()); @@ -560,6 +557,7 @@ sourceClient.getAssignedNumber(), subtractedTokens))); } + @SuppressWarnings("rawtypes") private void initializeFacilitatorHandlers() { // facilitator handlers @@ -576,10 +574,10 @@ @Override public void handle(ShowRequest request) { if (request.getId().equals(facilitatorId)) { - for (Identifier id: clients.keySet()) { + for (Identifier id : clients.keySet()) { transmit(request.copy(id)); } -// sendFacilitatorMessage("Received " + request + " from facilitator, copied & broadcast to all clients."); + // sendFacilitatorMessage("Received " + request + " from facilitator, copied & broadcast to all clients."); } else { sendFacilitatorMessage("Ignoring show request from non facilitator id: " + request.getId()); @@ -596,8 +594,8 @@ } else { sendFacilitatorMessage(String.format( - "Couldn't start round, waiting on %d of %d quizzes", - numberOfSubmittedQuizzes, + "Couldn't start round, waiting on %d of %d quizzes", + numberOfSubmittedQuizzes, clients.size())); } } @@ -620,9 +618,11 @@ synchronized (clients) { ClientData clientData = clients.get(request.getId()); String surveyId = request.getSurveyId(); - for (ClientData data: clients.values()) { + for (ClientData data : clients.values()) { if (surveyId.equals(data.getSurveyId())) { - sendFacilitatorMessage(String.format("WARNING: survey id %s was already assigned to client %s but is now also being assigned to %s", surveyId, data, clientData)); + sendFacilitatorMessage(String.format( + "WARNING: survey id %s was already assigned to client %s but is now also being assigned to %s", surveyId, data, + clientData)); } } clientData.getId().setSurveyId(request.getSurveyId()); @@ -632,6 +632,7 @@ }); addEventProcessor(new EventTypeProcessor<TrustGameSubmissionRequest>(TrustGameSubmissionRequest.class) { int numberOfSubmissions = 0; + @Override public void handle(TrustGameSubmissionRequest request) { if (getCurrentRoundConfiguration().isTrustGameEnabled()) { @@ -642,14 +643,15 @@ persister.store(request); transmit(new TrustGameSubmissionEvent(facilitatorId, request)); numberOfSubmissions++; - sendFacilitatorMessage(String.format("%d trust game submissions (%s)", numberOfSubmissions, request)); + sendFacilitatorMessage(String.format("Received trust game submission %s (%d total)", request, numberOfSubmissions)); } + // FIXME: groups have not been assigned in the transition between practice round and this round.. if (numberOfSubmissions >= clients.size()) { // once all clients have submitted their decisions, execute the trust game. for (GroupDataModel group : serverDataModel.getGroups()) { LinkedList<ClientData> clientList = new LinkedList<ClientData>(group.getClientDataMap().values()); Collections.shuffle(clientList); - // FIXME: arbitrary choice to save the first one to pair up with the last one as well. + logger.info("TRUST GAME shuffled client list: " + clientList); ClientData first = clientList.getFirst(); for (Iterator<ClientData> iter = clientList.iterator(); iter.hasNext();) { ClientData playerOne = iter.next(); @@ -657,8 +659,10 @@ if (iter.hasNext()) { playerTwo = iter.next(); } + logger.info("TRUST GAME: about to pair " + playerOne + " with " + playerTwo); String trustGameResults = serverDataModel.calculateTrustGame(playerOne, playerTwo); - sendFacilitatorMessage(String.format("Pairing %s with %s for trust game resulted in: %s", playerOne, playerTwo, trustGameResults)); + sendFacilitatorMessage(String.format("Pairing %s with %s for trust game resulted in: %s", playerOne, playerTwo, + trustGameResults)); } } numberOfSubmissions = 0; @@ -673,7 +677,6 @@ // - at that point the clients haven't been added to any groups yet. // another way to handle this is to have the clients added // to groups when the show instructions request is handled.. - initializeGroups(); sendFacilitatorMessage("Sending begin chat round request to all participants"); for (Map.Entry<Identifier, ClientData> entry : clients.entrySet()) { Identifier id = entry.getKey(); @@ -688,7 +691,7 @@ protected boolean isReadyToStartRound() { if (getCurrentRoundConfiguration().isQuizEnabled()) { - return numberOfSubmittedQuizzes >= clients.size(); + return numberOfSubmittedQuizzes >= clients.size(); } return true; } @@ -726,7 +729,7 @@ transmit(chatEvent); } } - + private void sendFacilitatorMessage(String message) { logger.info(message); if (facilitatorId != null) { @@ -749,25 +752,25 @@ stopRound(); break; } + processRound(); - roundProcessor.execute(); // Thread.yield(); Utils.sleep(SERVER_SLEEP_INTERVAL); break; - case WAITING: + case IN_BETWEEN_ROUNDS: // FIXME: there is an inherent nastiness going on with this model of control flow - // the problem is this: when we first spin up the server, there are no connected clients. control flow + // the problem is this: when we first spin up the server, there are no connected clients. control flow // enters here, we initialize the round (with no participants, etc.) and then wait on the quiz signal - + // the issue is that we need to initialize the groups at some clear, well-defined time. // we have to do it after all the clients are connected, so perhaps showInstructions can be the time to do it? // the previous way which I've been slowly refactoring was to do it on the beginning of the first round (as a special case) - // in the handler for BeginRoundRequest) and to do it at the end of every round. Probably better to do it in round initialization - + // in the handler for BeginRoundRequest) and to do it at the end of every round. Probably better to do it in round initialization + // initialize persister first so we store all relevant events. // persister MUST be initialized early so that we store pre-round events like QuizResponseEvent, ChatEvent, and the various Ranking // requests. - persister.initialize(getCurrentRoundConfiguration()); + setupRound(); sendFacilitatorMessage("Ready to show instructions and the start next round."); if (getCurrentRoundConfiguration().isQuizEnabled()) { getLogger().info("Waiting for all quizzes to be submitted."); @@ -775,7 +778,17 @@ } // then wait for the signal from the facilitator to actually start the round (a chat session might occur or a voting session). Utils.waitOn(roundSignal); - + startRound(); + break; + case WAITING_FOR_CONNECTIONS: + sendFacilitatorMessage("Ready to show instructions and the start next round."); + if (getCurrentRoundConfiguration().isQuizEnabled()) { + getLogger().info("Waiting for all quizzes to be submitted."); + Utils.waitOn(quizSignal); + } + // then wait for the signal from the facilitator to actually start the round (a chat session might occur or a voting session). + Utils.waitOn(roundSignal); + setupRound(); startRound(); break; default: @@ -783,29 +796,54 @@ } } - private void processRound3d() { - boolean secondHasPassed = secondTick.hasExpired(); - if (secondHasPassed) { - int secondsPerYear = getConfiguration().getCurrentParameters().getResourceAgingSecondsPerYear(); - for (GroupDataModel group : serverDataModel.getGroups()) { - // update resource age - if (secondTick.getStartCount() % secondsPerYear == 0) { - resourceDispenser.updateResourceAge(group); - } - // renew resources - resourceDispenser.generateResources(group); - } - secondTick.restart(); - } - // send new information to each client - long timeLeft = currentRoundDuration.getTimeLeft(); - for (ClientData data : clients.values()) { - transmit(new SynchronizeClientEvent(data, timeLeft)); - } - serverDataModel.clearDiffLists(); + private void setupRound() { + persister.initialize(getCurrentRoundConfiguration()); + initializeGroups(); } - private void processRound2d() { + private void stopRound() { + serverState = ServerState.IN_BETWEEN_ROUNDS; + sendEndRoundEvents(); + if (getCurrentRoundConfiguration().isPostRoundSanctioningEnabled()) { + // stop most of the round but don't persist/cleanup yet. + // block until we receive all postround sanctioning events. + // FIXME: use new java.util.concurrent constructs? CountDownLatch or CyclicBarrier? + // postRoundSanctionLatch = new CountDownLatch(clients.size()); + // try { postRoundSanctionLatch.await(); } + // catch (InterruptedException ignored) {} + Utils.waitOn(postRoundSanctioningSignal); + } + persister.persist(serverDataModel); + cleanupRound(); + // FIXME: make sure this is needed and document. + // Utils.sleep(2000); + advanceToNextRound(); + } + + private void cleanupRound() { + numberOfSubmittedQuizzes = 0; + groupsInitialized = false; + serverDataModel.cleanupRound(); + for (ClientData clientData : clients.values()) { + clientData.reset(); + } + } + + private void advanceToNextRound() { + if (getConfiguration().isLastRound()) { + return; + } + RoundConfiguration nextRoundConfiguration = getConfiguration().nextRound(); + serverDataModel.setRoundConfiguration(nextRoundConfiguration); + logger.info("Advancing to round # " + getConfiguration().getCurrentRoundNumber()); + // send the next round configuration to each client + for (Identifier id : clients.keySet()) { + transmit(new SetConfigurationEvent<RoundConfiguration>(id, nextRoundConfiguration)); + } + transmit(new SetConfigurationEvent<RoundConfiguration>(facilitatorId, nextRoundConfiguration)); + } + + private void processRound() { boolean secondHasPassed = secondTick.hasExpired(); if (secondHasPassed) { // handle rotating monitors. @@ -827,29 +865,31 @@ resourceDispenser.generateResources(); secondTick.restart(); } + // FIXME: commented out since we're now collecting tokens as the requests come in.. +// for (GroupDataModel group : serverDataModel.getGroups()) { +// for (ClientData clientData : group.getClientDataMap().values()) { +// // ask each client if it wants to grab a token, wherever it is. +// clientData.collectToken(); +// } +// } for (GroupDataModel group : serverDataModel.getGroups()) { - for (ClientData clientData : group.getClientDataMap().values()) { - // ask each client if it wants to grab a token, wherever it is. - clientData.collectToken(); - } - } - for (GroupDataModel group: serverDataModel.getGroups()) { Set<Resource> addedTokensSet = group.getAddedResources(); Resource[] addedResources = addedTokensSet.toArray(new Resource[addedTokensSet.size()]); Set<Resource> removedTokensSet = group.getRemovedResources(); Resource[] removedResources = removedTokensSet.toArray(new Resource[removedTokensSet.size()]); Map<Identifier, Integer> clientTokens = group.getClientTokens(); Map<Identifier, Point> clientPositions = group.getClientPositions(); - for (ClientData data: group.getClientDataMap().values()) { + for (ClientData data : group.getClientDataMap().values()) { if (shouldSynchronize(data.getAssignedNumber())) { transmit(new SynchronizeClientEvent(data, currentRoundDuration.getTimeLeft())); } else { - transmit(new ClientPositionUpdateEvent(data, addedResources, removedResources, clientTokens, clientPositions, currentRoundDuration.getTimeLeft())); + transmit(new ClientPositionUpdateEvent(data, addedResources, removedResources, clientTokens, clientPositions, + currentRoundDuration.getTimeLeft())); } } } - // FIXME: refine this, send basic info to the facilitator (how many resources left, etc.) + // FIXME: refine this, send basic info to the facilitator (how many resources left, etc.) if (shouldUpdateFacilitator()) { transmit(new FacilitatorUpdateEvent(facilitatorId, serverDataModel, currentRoundDuration.getTimeLeft())); } @@ -867,25 +907,6 @@ return (startCount < 3) || ((startCount % SYNCHRONIZATION_FREQUENCY) == (assignedNumber * 10)); } - private void stopRound() { - serverState = ServerState.WAITING; - sendEndRoundEvents(); - if (getCurrentRoundConfiguration().isPostRoundSanctioningEnabled()) { - // stop most of the round but don't persist/cleanup yet. - // block until we receive all postround sanctioning events. - // FIXME: use new java.util.concurrent constructs? CountDownLatch or CyclicBarrier? - // postRoundSanctionLatch = new CountDownLatch(clients.size()); - // try { postRoundSanctionLatch.await(); } - // catch (InterruptedException ignored) {} - Utils.waitOn(postRoundSanctioningSignal); - } - persistRound(); - cleanupRound(); - // FIXME: make sure this is needed and document. - Utils.sleep(2000); - advanceToNextRound(); - } - private void sendEndRoundEvents() { // send each client some debriefing information: // 1. avg number of tokens collected in this round for the group @@ -900,39 +921,10 @@ } } - private void persistRound() { - persister.persist(serverDataModel); - } - - private void cleanupRound() { - numberOfSubmittedQuizzes = 0; - groupsInitialized = false; - serverDataModel.cleanupRound(); - for (ClientData clientData : clients.values()) { - clientData.reset(); - } - } - - private void advanceToNextRound() { - if (getConfiguration().isLastRound()) { - // stop the experiment. - serverState = ServerState.WAITING; - return; - } - RoundConfiguration nextRoundConfiguration = getConfiguration().nextRound(); - serverDataModel.setRoundConfiguration(nextRoundConfiguration); - initializeRoundProcessor(); - logger.info("Advancing to round # " + getConfiguration().getCurrentRoundNumber()); - // send the next round configuration to each client - for (Identifier id : clients.keySet()) { - transmit(new SetConfigurationEvent<RoundConfiguration>(id, nextRoundConfiguration)); - } - transmit(new SetConfigurationEvent<RoundConfiguration>(facilitatorId, nextRoundConfiguration)); - } - private boolean shouldShuffleParticipants() { // guard to ensure that we don't shuffle participants twice in a round (in the event there was a chat round preceding the normal game round) - if (groupsInitialized) return false; + if (groupsInitialized) + return false; RoundConfiguration currentRoundConfiguration = getCurrentRoundConfiguration(); RoundConfiguration previousRoundConfiguration = getConfiguration().getPreviousRoundConfiguration(); // we shuffle participants: @@ -963,7 +955,7 @@ clientData.initializePosition(); } } - + private void initializeGroups() { // reset group linkages if necessary if (shouldShuffleParticipants()) { @@ -985,9 +977,6 @@ private void startRound() { RoundConfiguration roundConfiguration = getCurrentRoundConfiguration(); // actually start the round once we receive the facilitator signal. - getLogger().info("Initializing groups."); - // FIXME: what if we want groups before the round actually begins..? - initializeGroups(); // send RoundStartedEvents to all connected clients for (Map.Entry<Identifier, ClientData> entry : clients.entrySet()) { Identifier id = entry.getKey(); diff -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 -r f4e75ba7256a7a069918fead050f2a65923efca5 src/main/resources/configuration/asu-experiments/2011/t1/round0.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round0.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round0.xml @@ -88,7 +88,7 @@ B. When you have collected all tokens on the screen, no new tokens will appear.<br> C. Tokens grow from the middle of the screen.<br> D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br> -<br><br> +<br><span class='q2'>Q2. Which sequence of situations is not possible?</span><br><b> {incorrect_q2} Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-12 20:22:16
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/c77bebdc8b2d/ changeset: c77bebdc8b2d user: alllee date: 2012-01-12 21:22:15 summary: new foraging checkerboard image from Mady affected #: 1 file diff -r e1ee74e8c9c3e618593c88c0bb7a587121e22900 -r c77bebdc8b2df41bf90a5b53f365bd570c4144f8 src/main/resources/images/foraging-checkerboard.png Binary file src/main/resources/images/foraging-checkerboard.png has changed Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-12 20:19:29
|
2 new commits in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/cc86ea7d6493/ changeset: cc86ea7d6493 user: alllee date: 2012-01-12 20:41:59 summary: - more instructions fixes & improvements, changing tags to be HTML 3.2 to comply with Java's HTMLEditorKit support. - adding id attribute to last round debriefing so we can properly associate payments, may need to tweak how csidex SocketIdentifier renders itself affected #: 10 files diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/java/edu/asu/commons/foraging/client/ClientDataModel.java --- a/src/main/java/edu/asu/commons/foraging/client/ClientDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/client/ClientDataModel.java @@ -284,4 +284,8 @@ throw new UnsupportedOperationException("3D support is currently unavailable"); } + public String getLastRoundDebriefing() { + return getRoundConfiguration().getLastRoundDebriefing(getId()); + } + } diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -336,8 +336,10 @@ return getProperty("regulation-instructions"); } - public String getLastRoundDebriefing() { - return getProperty("last-round-debriefing"); + public String getLastRoundDebriefing(Identifier id) { + ST template = createStringTemplate(getProperty("last-round-debriefing")); + template.add("id", id); + return template.render(); } /** @@ -751,9 +753,11 @@ ST template = createStringTemplate(getProperty("quiz-results")); // FIXME: actual answers includes the submit button, so there's an off-by-one that we need to deal with. int totalQuestions = actualAnswers.size() - 1; + int numberCorrect = totalQuestions - incorrectQuestionNumbers.size(); template.add("allCorrect", incorrectQuestionNumbers.isEmpty()); - template.add("numberCorrect", totalQuestions - incorrectQuestionNumbers.size()); + template.add("numberCorrect", numberCorrect); template.add("totalQuestions", totalQuestions); + template.add("totalQuizEarnings", NumberFormat.getCurrencyInstance().format(getQuizCorrectAnswerReward() * numberCorrect)); for (String incorrectQuestionNumber : incorrectQuestionNumbers) { template.add("incorrect_" + incorrectQuestionNumber, String.format("Your answer, %s, was incorrect.", actualAnswers.get(incorrectQuestionNumber))); } diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -633,7 +633,7 @@ // for (String trustGameLog : event.getTrustGameLog()) { // instructionsBuilder.append(trustGameLog); // } - instructionsBuilder.append(client.getDataModel().getRoundConfiguration().getLastRoundDebriefing()); + instructionsBuilder.append(client.getDataModel().getLastRoundDebriefing()); timeLeftLabel.setText("The experiment is now over."); } setInstructions(instructionsBuilder.toString()); @@ -662,7 +662,7 @@ instructionsBuilder.append(String.format("Your <b>total income</b> so far is: $%3.2f<hr>", getIncome(clientData.getTotalTokens()))); if (event.isLastRound()) { - instructionsBuilder.append(client.getDataModel().getRoundConfiguration().getLastRoundDebriefing()); + instructionsBuilder.append(client.getDataModel().getLastRoundDebriefing()); } setInstructions(instructionsBuilder.toString()); diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/java/edu/asu/commons/foraging/ui/InstructionsView.java --- a/src/main/java/edu/asu/commons/foraging/ui/InstructionsView.java +++ b/src/main/java/edu/asu/commons/foraging/ui/InstructionsView.java @@ -64,7 +64,7 @@ instructionsBuilder.append(String.format("Your <b>total income</b> so far (including a $%3.2f bonus for showing up) is : $%3.2f<hr>", showUpPayment, dataModel.getTotalIncome() + showUpPayment)); if (lastRound) { - instructionsBuilder.append(roundConfiguration.getLastRoundDebriefing()); + instructionsBuilder.append(dataModel.getLastRoundDebriefing()); } setInstructions(instructionsBuilder.toString()); } diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/resources/configuration/asu-experiments/2011/t1/round0.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round0.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round0.xml @@ -69,9 +69,9 @@ <hr><p> {if (allCorrect)} - You have answered all the questions correctly. + You have answered all the questions correctly and earned <b>{totalQuizEarnings}</b>. {else} - YOu answered {numberCorrect}/{totalQuestions} questions correctly. Questions you've answered + You answered {numberCorrect} out of {totalQuestions} questions correctly and earned <b>{totalQuizEarnings}</b>. Questions you've answered incorrectly are highlighted in red. Please see below for more details. {endif} </p> diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/resources/configuration/asu-experiments/2011/t1/round1.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round1.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round1.xml @@ -15,7 +15,7 @@ <entry key="instructions"><![CDATA[ -<h3>Round 1 Instructions</h3> +<h3>Round {roundNumber} Instructions</h3><hr><p> This is the first round of the experiment. The length of the round is @@ -23,31 +23,37 @@ you will earn <b>{dollarsPerToken}</b> for each token collected. You <b>cannot</b> reset the distribution of green tokens. </p> +<h3>Groups</h3> +<hr><p> -In this round the renewable resource will become five times bigger. You will share -this larger environment with four other players in this room that have been randomly -selected. Each group's resource environment is distinct from the other groups. +In this round the renewable resource will become five times bigger. You will share this +larger environment with four other random players in this room. In particular, +each of you in this room has been randomly assigned to one of several equal-sized {clientsPerGroup} +person groups and everyone in your group has been randomly assigned a number from 1 +to {clientsPerGroup}. You will stay in the same group for the entire experiment, and each person's +number from 1 to {clientsPerGroup} will remain the same throughout the experiment. +The other three people in your group will appear on the screen as blue dots +<img src="@CODEBASE_URL@/images/gem-other.gif"> with a white number embedded in the dot. </p><p> - Each of you has been assigned a number from 1 to {clientsPerGroup}. These - numbers will remain the same throughout the experiment but you will <b>not</b> - be able to identify which person in the room has been assigned which number, so - your anonymity is guaranteed. + In each round of the token task, you can see how many tokens each player has + collected at the top right corner of the screen. On the top left corner of the + screen you will see the remaining time in the round. </p> - +<h3>Anonymity</h3> +<hr><p> -The other players will appear on the screen as blue dots <img - src="@CODEBASE_URL@/images/gem-other.gif"> with a white number embedded in the - dot. On the top right corner of the screen you can see how many tokens each - player has collected. On the top left corner of the screen you can see a clock - that displays the remaining time in the round.</p><p>Since you can only see the - resource within your vision you may neither see all the other participants nor - all the resource units. The figure below indicates the vision range compared to - the whole environment</p> -<img src="@CODEBASE_URL@/images/vision-range.jpg"> -<p> -<p><b>Do you have any questions?</b> If you have any questions at this time please raise your hand and someone will come over to your station and answer it.</p> + Because group membership was randomly assigned by the computer, neither you nor + the experimenter will be able to identify which person in the room has been + assigned to a particular group or number within a group. Your anonymity is + guaranteed. </p> +<h3>Tokens</h3> +<hr> + <p> + Each group has its own set of token resources. + </p> +<p><b>Do you have any questions so far?</b> If you have any questions at this time, raise your hand and someone will come over to your station and answer it.</p> ]]></entry><entry key="chat-instructions"> diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/resources/configuration/asu-experiments/2011/t1/round4.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round4.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round4.xml @@ -18,6 +18,8 @@ <entry key='in-round-chat-enabled'>true</entry><entry key="initial-distribution">.25</entry> +<entry key='resource-generator'>top-bottom-patchy</entry> + <entry key="instructions"><![CDATA[ <h3>Round {roundNumber} Instructions</h3> diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/resources/configuration/asu-experiments/2011/t1/round5.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round5.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round5.xml @@ -13,5 +13,6 @@ <entry key='always-explicit'>true</entry><entry key='max-cell-occupancy'>1</entry><entry key="in-round-chat-enabled">true</entry> +<entry key='resource-generator'>top-bottom-patchy</entry></properties> diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/resources/configuration/asu-experiments/2011/t1/round6.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round6.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round6.xml @@ -17,22 +17,32 @@ <entry key='trust-game'>true</entry> +<entry key='resource-generator'>top-bottom-patchy</entry> + <entry key="last-round-debriefing"><![CDATA[ +<h2>Survey</h2> +<hr><p> This was the last round, but not the end of the experiment. We will now determine your payments. While we are doing this, we request that you carefully fill out a brief survey. </p> +<h2>Payments</h2> +<hr> + <p>NOTE: Your computer number is <b>{id}</b></p><p> When we are ready we will call you one by one to the room next door. We will -pay you there in private. Please wait until your computer number is called, -and then proceed to the room next door to turn in your computer number and +pay you there in private. Please wait until your computer number, <b>{id}</b>, is +called, and then proceed to the room next door to turn in your computer number and your survey. </p><p> Please answer the survey carefully and thank you for participating. </p> + + + ]]></entry></properties> diff -r c55e94b5c6b7d769cef350cb593801d9d7b81c13 -r cc86ea7d6493a94fd85152f634d764ccd8d14481 src/main/resources/configuration/asu-experiments/2011/t1/server.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/server.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/server.xml @@ -56,6 +56,7 @@ <entry key="general-instructions"><![CDATA[ <h1>General Instructions</h1> +<hr><p><b>Welcome</b>. You have already earned {showUpPayment} dollars just for showing up at this experiment. </p> @@ -100,10 +101,10 @@ </tr><tr><td align="center"> - <img src="@CODEBASE_URL@/images/8neighbors.jpg" alt="image 1"></img> + <img src="@CODEBASE_URL@/images/8neighbors.jpg" alt="image 1"></td><td align="center"> - <img src="@CODEBASE_URL@/images/5neighbors.jpg" alt="image 2"></img> + <img src="@CODEBASE_URL@/images/5neighbors.jpg" alt="image 2"></td></tr></table> @@ -117,7 +118,7 @@ regrowth. The best arrangement of tokens that maximizes overall regrowth is the checkerboard diagram shown below. <br> -<img src="@CODEBASE_URL@/images/foraging-checkerboard.png" alt="Checkerboard Resource"></img> +<img src="@CODEBASE_URL@/images/foraging-checkerboard.png" alt="Checkerboard Resource"></p> ]]></entry> https://bitbucket.org/virtualcommons/foraging/changeset/e1ee74e8c9c3/ changeset: e1ee74e8c9c3 user: alllee date: 2012-01-12 21:19:27 summary: more instructions + configuration refactoring affected #: 3 files diff -r cc86ea7d6493a94fd85152f634d764ccd8d14481 -r e1ee74e8c9c3e618593c88c0bb7a587121e22900 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -16,6 +16,7 @@ import edu.asu.commons.foraging.graphics.Point3D; import edu.asu.commons.foraging.model.ClientData; import edu.asu.commons.foraging.model.EnforcementMechanism; +import edu.asu.commons.foraging.model.ResourceDispenser; import edu.asu.commons.foraging.rules.ForagingRule; import edu.asu.commons.net.Identifier; import edu.asu.commons.util.Duration; @@ -39,6 +40,12 @@ */ public class RoundConfiguration extends ExperimentRoundParameters.Base<ServerConfiguration> { + private static final double DEFAULT_PATCHY_BOTTOM_INITIAL_DISTRIBUTION = 0.25; + + private static final double DEFAULT_PATCHY_TOP_INITIAL_DISTRIBUTION = 0.50; + + private static final double DEFAULT_TOP_REGROWTH_RATE = 0.02; + private final static long serialVersionUID = 8575239803733029326L; public final static double DEFAULT_REGROWTH_RATE = 0.01; @@ -430,23 +437,23 @@ } public double getTopRegrowthScalingFactor() { - return getDoubleProperty("top-rate", 0.02); + return getDoubleProperty("top-rate", DEFAULT_TOP_REGROWTH_RATE); } public double getBottomRegrowthScalingFactor() { - return getDoubleProperty("bottom-rate", 0.01); + return getDoubleProperty("bottom-rate", DEFAULT_REGROWTH_RATE); } public double getTopInitialResourceDistribution() { - return getDoubleProperty("top-initial-distribution", 0.50); + return getDoubleProperty("top-initial-distribution", DEFAULT_PATCHY_TOP_INITIAL_DISTRIBUTION); } public double getBottomInitialResourceDistribution() { - return getDoubleProperty("bottom-initial-distribution", 0.25); + return getDoubleProperty("bottom-initial-distribution", DEFAULT_PATCHY_BOTTOM_INITIAL_DISTRIBUTION); } public String getResourceGeneratorType() { - return getProperty("resource-generator", "density-dependent"); + return getProperty("resource-generator", ResourceDispenser.Type.DENSITY_DEPENDENT.toString()); } public int getWorldWidth() { diff -r cc86ea7d6493a94fd85152f634d764ccd8d14481 -r e1ee74e8c9c3e618593c88c0bb7a587121e22900 src/main/resources/configuration/asu-experiments/2011/t1/round1.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round1.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round1.xml @@ -15,7 +15,7 @@ <entry key="instructions"><![CDATA[ -<h3>Round {roundNumber} Instructions</h3> +<h1>Round {roundNumber} Instructions</h1><hr><p> This is the first round of the experiment. The length of the round is @@ -26,14 +26,15 @@ <h3>Groups</h3><hr><p> -In this round the renewable resource will become five times bigger. You will share this -larger environment with four other random players in this room. In particular, -each of you in this room has been randomly assigned to one of several equal-sized {clientsPerGroup} -person groups and everyone in your group has been randomly assigned a number from 1 -to {clientsPerGroup}. You will stay in the same group for the entire experiment, and each person's -number from 1 to {clientsPerGroup} will remain the same throughout the experiment. -The other three people in your group will appear on the screen as blue dots -<img src="@CODEBASE_URL@/images/gem-other.gif"> with a white number embedded in the dot. +In this round the renewable resource will become five times bigger. You will share +this larger environment with four other random players in this room. Each +participant in the room has been randomly assigned to one of several equal-sized +{clientsPerGroup} person groups and everyone in your group has been randomly +assigned a number from 1 to {clientsPerGroup}. You will stay in the same group for +the entire experiment, and each person's number from 1 to {clientsPerGroup} will +remain the same throughout the experiment. The other members of your group will +appear on the screen as blue dots <img src="@CODEBASE_URL@/images/gem-other.gif"> +with a white number embedded in the dot. </p><p> In each round of the token task, you can see how many tokens each player has @@ -56,23 +57,4 @@ <p><b>Do you have any questions so far?</b> If you have any questions at this time, raise your hand and someone will come over to your station and answer it.</p> ]]></entry> -<entry key="chat-instructions"> -<![CDATA[ -<p> -You can chat with the other participants in your group during this round. -You may communicate about any aspect of the experiment that you would like to -discuss with other participants with whom you have been matched. You may not promise -them side-payments after the experiment is completed or threaten them with any -consequence after the experiment is finished. We are monitoring the chat traffic -while you chat. If we see that somebody reveals his or her identity, we have to stop -the experiment and remove the whole group from which this person is a member out of -this room. -</p> -<p> - You will see other participants labeled from 1 to {clientsPerGroup} in the chat - window. You can send a chat message by typing into the textfield and pressing - the enter key. -</p> -]]> -</entry></properties> diff -r cc86ea7d6493a94fd85152f634d764ccd8d14481 -r e1ee74e8c9c3e618593c88c0bb7a587121e22900 src/main/resources/configuration/asu-experiments/2011/t1/server.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/server.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/server.xml @@ -167,18 +167,18 @@ <li>You <b>may not promise side-payments after the experiment is completed or threaten anyone with any consequence after the experiment is finished</b>.</li><li>You <b>may not reveal your actual identity</b></li></ol> +<p> We are monitoring the chat traffic while you chat. If we detect any violation of the -rules we will have to stop the the experiment and remove the group where the offense -occurred from the room. +rules we will have to stop the experiment and remove the offending group from the +room. </p><p> -You will see other participants labeled as "1", "2","3", "4", or "5" in the chat -box. You can send a chat message by typing into the textfield and pressing the -enter key. + You will see other participants labeled from 1 to {clientsPerGroup} in the chat + window. You can send a chat message by typing into the textfield and pressing + the enter key. </p> ]]></entry> - <entry key="sameRoundAsPreviousInstructions"><![CDATA[ <h3>Round {roundNumber} Instructions</h3> @@ -188,5 +188,4 @@ <p><b>Do you have any questions?</b> If you have any questions at this time please raise your hand and someone will come over to your station and answer it.</p> ]]></entry> - </properties> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-12 00:20:04
|
2 new commits in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/576add3f3931/ changeset: 576add3f3931 user: alllee date: 2012-01-11 23:30:52 summary: fixing bug with surveyURL, trying to interpolate twice with StringTemplate was adding a newline between the surveyId query parameter and surveyUrl and consequently upsetting Java's URL parser affected #: 5 files diff -r f5add5427f726ff41dfcf33c067475bead723c86 -r 576add3f39318806e5a7a533b5806684a4ef6587 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -709,15 +709,16 @@ return getProperty("survey-instructions"); } - public String getSurveyUrl() { - return getProperty("survey-url", "https://qtrial.qualtrics.com/SE/?SID=SV_38lReBOv0Wk7wgY"); + public String getSurveyUrl(Identifier id) { + ST template = createStringTemplate(getProperty("survey-url", "https://qtrial.qualtrics.com/SE/?SID=SV_38lReBOv0Wk7wgY")); + template.add("surveyId", id.getSurveyId()); + return template.render(); } public String getSurveyInstructions(Identifier id) { String surveyInstructions = getSurveyInstructions(); ST template = createStringTemplate(surveyInstructions); - template.add("surveyUrl", getSurveyUrl()); - template.add("surveyId", id.getSurveyId()); + template.add("surveyUrl", getSurveyUrl(id)); return template.render(); } @@ -732,20 +733,6 @@ template.add("tiebreaker", selectedRules.size() > 1); template.add("selectedRules", selectedRules); return template.render(); - /* - StringBuilder builder = new StringBuilder("<h1>Voting Results</h1><hr>"); - if (selectedRules.size() > 1) { - // tiebreaker - builder.append("<p><b>NOTE:</b> There was a tie and the first rule listed here was randomly selected as the winner.</p><ul>"); - for (ForagingRule rule: selectedRules) { - builder.append("<li>").append(rule.toString()); - } - builder.append("</ul>"); - } - builder.append("<h1>Selected Rule</h1><hr>"); - builder.append("<p><b>").append(selectedRules.get(0)).append("</b></p>"); - return builder.toString(); - */ } @Override @@ -756,7 +743,11 @@ public String getQuizResults(List<String> incorrectQuestionNumbers, Map<Object, Object> actualAnswers) { ST template = createStringTemplate(getProperty("quiz-results")); + // FIXME: actual answers includes the submit button, so there's an off-by-one that we need to deal with. + int totalQuestions = actualAnswers.size() - 1; template.add("allCorrect", incorrectQuestionNumbers.isEmpty()); + template.add("numberCorrect", totalQuestions - incorrectQuestionNumbers.size()); + template.add("totalQuestions", totalQuestions); for (String incorrectQuestionNumber : incorrectQuestionNumbers) { template.add("incorrect_" + incorrectQuestionNumber, String.format("Your answer, %s, was incorrect.", actualAnswers.get(incorrectQuestionNumber))); } diff -r f5add5427f726ff41dfcf33c067475bead723c86 -r 576add3f39318806e5a7a533b5806684a4ef6587 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -768,7 +768,7 @@ // persister MUST be initialized early so that we store pre-round events like QuizResponseEvent, ChatEvent, and the various Ranking // requests. persister.initialize(getCurrentRoundConfiguration()); - getLogger().info("Initialized persister, waiting for facilitator signal to start next round."); + sendFacilitatorMessage("Ready to show instructions and the start next round."); if (getCurrentRoundConfiguration().isQuizEnabled()) { getLogger().info("Waiting for all quizzes to be submitted."); Utils.waitOn(quizSignal); diff -r f5add5427f726ff41dfcf33c067475bead723c86 -r 576add3f39318806e5a7a533b5806684a4ef6587 src/main/java/edu/asu/commons/foraging/ui/VotingForm.java --- a/src/main/java/edu/asu/commons/foraging/ui/VotingForm.java +++ b/src/main/java/edu/asu/commons/foraging/ui/VotingForm.java @@ -10,6 +10,7 @@ */ package edu.asu.commons.foraging.ui; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; @@ -23,6 +24,7 @@ import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; +import javax.swing.JPanel; import javax.swing.JRadioButton; import edu.asu.commons.foraging.client.ForagingClient; @@ -33,7 +35,7 @@ * $Id$ * @author Allen Lee */ -public class VotingForm extends javax.swing.JPanel { +public class VotingForm extends JPanel { private static final long serialVersionUID = 3871660663519284024L; @@ -76,10 +78,10 @@ horizontalLabelParallelGroup.addComponent(strategyHeaderLabel); verticalGroup.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(strategyHeaderLabel).addGap(10).addComponent(rightHeaderLabel)); - int ruleIndex = 0; + Dimension oneByOne = new Dimension(1, 1); for (ForagingRule rule: rules) { - ruleIndex++; - JLabel ruleLabel = new JLabel(String.format("Strategy %d: %s", ruleIndex, rule)); + JLabel ruleLabel = new JLabel("<html" + rule.getDescription() + "</html>"); + ruleLabel.setPreferredSize(oneByOne); ruleLabel.setFont(UserInterfaceUtils.DEFAULT_PLAIN_FONT); horizontalLabelParallelGroup.addComponent(ruleLabel); JComponent component = null; diff -r f5add5427f726ff41dfcf33c067475bead723c86 -r 576add3f39318806e5a7a533b5806684a4ef6587 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml @@ -69,9 +69,9 @@ <hr><p> {if (allCorrect)} - You have answered all the questions correctly. For more details, see below. + You have answered all the questions correctly. {else} - At least one of your answers was incorrect. Questions you've answered + You answered {numberCorrect}/{totalQuestions} questions correctly. Questions you've answered incorrectly are highlighted in red. Please see below for more details. {endif} </p> diff -r f5add5427f726ff41dfcf33c067475bead723c86 -r 576add3f39318806e5a7a533b5806684a4ef6587 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml @@ -142,15 +142,13 @@ <hr><p> Before we continue to the next round of the token task, we would like to ask you - some quick questions. Please <a href='{surveyUrl}&SURVEY_ID={surveyId}'>click here</a> to + some quick questions. Please <a href='{surveyUrl}'>click here</a> to begin the survey. </p> ]]></entry><entry key='survey-url'> - <![CDATA[ - https://qtrial.qualtrics.com/SE/?SID=SV_cLX7jnYikmD9eSM - ]]> + <![CDATA[https://qtrial.qualtrics.com/SE/?SID=SV_cLX7jnYikmD9eSM&SURVEY_ID={surveyId}]]></entry><entry key='sanction-type'>real-time</entry> https://bitbucket.org/virtualcommons/foraging/changeset/12f32da88243/ changeset: 12f32da88243 user: alllee date: 2012-01-12 01:19:59 summary: updating instructions template with sanction costs + penalties and a selected rule if it exists. should try to find a better way to inject data into these templates without being so explicit soon affected #: 2 files diff -r 576add3f39318806e5a7a533b5806684a4ef6587 -r 12f32da88243c2065bb1f6aff50beffef6360b9c src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -301,6 +301,11 @@ template.add("clientsPerGroup", getClientsPerGroup()); template.add("dollarsPerToken", NumberFormat.getCurrencyInstance().format(getDollarsPerToken())); template.add("initialDistribution", NumberFormat.getPercentInstance().format(getInitialDistribution())); + template.add("sanctionCost", getSanctionCost()); + template.add("sanctionPenalty", getSanctionPenalty()); + if (selectedRules != null && ! selectedRules.isEmpty()) { + template.add("selectedRule", selectedRules.get(0)); + } return template.render(); } diff -r 576add3f39318806e5a7a533b5806684a4ef6587 -r 12f32da88243c2065bb1f6aff50beffef6360b9c src/main/java/edu/asu/commons/foraging/ui/VotingForm.java --- a/src/main/java/edu/asu/commons/foraging/ui/VotingForm.java +++ b/src/main/java/edu/asu/commons/foraging/ui/VotingForm.java @@ -10,7 +10,9 @@ */ package edu.asu.commons.foraging.ui; +import java.awt.BorderLayout; import java.awt.Dimension; +import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; @@ -26,6 +28,8 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.WindowConstants; import edu.asu.commons.foraging.client.ForagingClient; import edu.asu.commons.foraging.rules.ForagingRule; @@ -56,8 +60,9 @@ private void initForm(Map<ForagingRule, Integer> votingResults) { ForagingRule[] rules = ForagingRule.values(); - GroupLayout groupLayout = new GroupLayout(this); - setLayout(groupLayout); + JPanel panel = new JPanel(); + GroupLayout groupLayout = new GroupLayout(panel); + panel.setLayout(groupLayout); groupLayout.setAutoCreateGaps(true); groupLayout.setAutoCreateContainerGaps(true); GroupLayout.SequentialGroup horizontalGroup = groupLayout.createSequentialGroup(); @@ -68,7 +73,7 @@ horizontalGroup.addGroup(horizontalButtonParallelGroup); GroupLayout.SequentialGroup verticalGroup = groupLayout.createSequentialGroup(); - String rightColumnHeader = votingResults.isEmpty() ? "Select one" : "Nominations"; + String rightColumnHeader = votingResults.isEmpty() ? "Select" : "Nominations"; JLabel rightHeaderLabel = new JLabel(rightColumnHeader); rightHeaderLabel.setFont(UserInterfaceUtils.DEFAULT_BOLD_FONT); horizontalButtonParallelGroup.addComponent(rightHeaderLabel); @@ -77,12 +82,12 @@ strategyHeaderLabel.setFont(UserInterfaceUtils.DEFAULT_BOLD_FONT); horizontalLabelParallelGroup.addComponent(strategyHeaderLabel); - verticalGroup.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(strategyHeaderLabel).addGap(10).addComponent(rightHeaderLabel)); - Dimension oneByOne = new Dimension(1, 1); + verticalGroup.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(strategyHeaderLabel).addGap(20).addComponent(rightHeaderLabel)); + Dimension labelDimension = new Dimension(800, 100); for (ForagingRule rule: rules) { - JLabel ruleLabel = new JLabel("<html" + rule.getDescription() + "</html>"); - ruleLabel.setPreferredSize(oneByOne); + JLabel ruleLabel = new JLabel("<html>" + rule.getDescription() + "</html>"); ruleLabel.setFont(UserInterfaceUtils.DEFAULT_PLAIN_FONT); + ruleLabel.setMaximumSize(labelDimension); horizontalLabelParallelGroup.addComponent(ruleLabel); JComponent component = null; if (votingResults.isEmpty()) { @@ -107,6 +112,9 @@ } groupLayout.setHorizontalGroup(horizontalGroup); groupLayout.setVerticalGroup(verticalGroup); + JScrollPane scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + setLayout(new BorderLayout()); + add(scrollPane, BorderLayout.CENTER); } private JButton getSubmitButton() { @@ -143,6 +151,8 @@ JFrame frame = new JFrame(); frame.add(new VotingForm(null)); frame.pack(); + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setVisible(true); } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-11 20:26:20
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/f5add5427f72/ changeset: f5add5427f72 user: alllee date: 2012-01-11 21:26:14 summary: fixing template attribute error affected #: 1 file diff -r 27a5a9748096161d031e7b57d24d78fa9c229190 -r f5add5427f726ff41dfcf33c067475bead723c86 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -716,7 +716,7 @@ public String getSurveyInstructions(Identifier id) { String surveyInstructions = getSurveyInstructions(); ST template = createStringTemplate(surveyInstructions); - template.add("surveyLink", getSurveyUrl()); + template.add("surveyUrl", getSurveyUrl()); template.add("surveyId", id.getSurveyId()); return template.render(); } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-11 20:19:20
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/27a5a9748096/ changeset: 27a5a9748096 user: alllee date: 2012-01-11 21:19:13 summary: updating voting results template affected #: 4 files diff -r 49a442883dbaec38c07b09415eb478d4220cc61b -r 27a5a9748096161d031e7b57d24d78fa9c229190 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -558,7 +558,9 @@ } public String getInitialVotingInstructions() { - return getProperty("initial-voting-instructions", "<h1>Notice</h1><hr><p>You will be given the ability to vote for rules in the next screen.</p>"); + ST template = createStringTemplate(getProperty("initial-voting-instructions", "<h1>Notice</h1><hr><p>You will be given the ability to vote for rules in the next screen.</p>")); + template.add("clientsPerGroup", getClientsPerGroup()); + return template.render(); } public List<ForagingRule> getForagingRules() { @@ -729,7 +731,6 @@ ST template = createStringTemplate(getProperty("voting-results")); template.add("tiebreaker", selectedRules.size() > 1); template.add("selectedRules", selectedRules); - template.add("selectedRule", selectedRules.get(0)); return template.render(); /* StringBuilder builder = new StringBuilder("<h1>Voting Results</h1><hr>"); diff -r 49a442883dbaec38c07b09415eb478d4220cc61b -r 27a5a9748096161d031e7b57d24d78fa9c229190 src/main/java/edu/asu/commons/foraging/rules/ForagingRule.java --- a/src/main/java/edu/asu/commons/foraging/rules/ForagingRule.java +++ b/src/main/java/edu/asu/commons/foraging/rules/ForagingRule.java @@ -11,7 +11,9 @@ * @version $Rev$ */ public enum ForagingRule { - WAIT_ONE_MINUTE("Wait 60 seconds for the screen to fill up with tokens (the timer will have {remainingTime} left). Then everyone collects tokens for the remaining amount of time."), + // FIXME: hard coded for 4 minute rounds, but templatizing this text is a bit of overkill at the moment unless + // we move this over to the configuration. + WAIT_ONE_MINUTE("Wait 60 seconds for the screen to fill up with tokens (the timer will have 180 seconds left). Then everyone collects tokens for the remaining amount of time."), PRIVATE_PROPERTY("Players divide the field up into four equally-sized areas and can do whatever they want within their area. With four people, each person takes an area around one of the four corners."), LIMITED_COLLECTION_RATE("Each person collects tokens at a rate of 1 token every 4 seconds."), MAINTAIN_TOKEN_CLUSTERS("Players leave two tokens untouched when the tokens are in a cluster of three or more that surround an empty cell."), diff -r 49a442883dbaec38c07b09415eb478d4220cc61b -r 27a5a9748096161d031e7b57d24d78fa9c229190 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml @@ -23,14 +23,15 @@ <p> During the practice round, you will have {duration} to practice with the experimental environment. The decisions you make in this round will NOT - influence your earnings. At the beginning of the practice round a quarter of the - cells are occupied with green tokens. The environment is a {resourceWidth} x {resourceDepth} grid of cells. + influence your earnings. At the beginning of the practice round + {initialDistribution} of the cells are occupied with green tokens. The + environment is a {resourceWidth} x {resourceDepth} grid of cells. </p><p> During this practice round, and <b>only during</b> this practice round, you are able to reset the tokens displayed on the screen. When you push the <b>R</b> key -you will reset the distribution of the tokens to randomly occupying a quarter of the -cells with green tokens. +you will reset the distribution of the tokens to randomly occupying +{initialDistribution} of the cells with green tokens. </p><p><b>Do you have any questions?</b> If you have any questions at this time please raise your hand and someone will come over to your station and answer it.</p> ]]> diff -r 49a442883dbaec38c07b09415eb478d4220cc61b -r 27a5a9748096161d031e7b57d24d78fa9c229190 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml @@ -15,11 +15,46 @@ <entry key='voting-enabled'>true</entry><entry key="instructions"><![CDATA[ + <h1>Important New Instructions</h1> + <h2>Reducing Other Player's Earnings</h2> + <hr><p> - Round {roundNumber} is about to begin. You have the option to reduce the - earnings of another participant at a cost to your own earnings by typing that - participants' number key from 1 to {clientsPerGroup}. +Round {roundNumber} is about to begin. You have the option to reduce the +earnings of another participant at a cost to your own earnings by typing that +participants' number key from 1 to {clientsPerGroup}. </p> + <ul> + <li>Each player in your group has a number from 1 to {clientsPerGroup}. If + you press a number key 1-{clientsPerGroup}, you will reduce the number + of tokens that player has collected during the round by + {sanctionPenalty} tokens. This will also reduce your own token amount by + {sanctionCost} token. The decision whether or when to use this option is + up to you. + </li> + <li>When you reduce the number of tokens of another participant, they will + receive a message stating that you have reduced their tokens. Likewise, if + another participant reduces your number of tokens, you will also receive a + message. These messages will be displayed on the bottom of your screen. + </li> + <li>If your tokens are being reduced or you are reducing another participant's + tokens, you will receive some visual cues. When your tokens are being reduced + your yellow dot will turn red briefly with a blue background. The participant + currently reducing your tokens will turn purple with a white background. + </li> + <li>You may reduce the earnings of other participants as long as (1) there are + tokens remaining on the screen and (2) both you and the other participant + have a positive number of tokens collected during the round. <b>Each time</b> + you press the numeric key corresponding to another participant your token + amount is reduced by <b>{sanctionCost}</b>, and their token amount is reduced by + <b>{sanctionPenalty}</b>. + </li> + </ul> +<h2>Strategy Reminder</h2> +<hr> + <p> + {selectedStrategy} + </p> + <p><b>Do you have any questions?</b> If you have any questions at this time, raise your hand and someone will come over to your station and answer it. @@ -27,6 +62,23 @@ ]]></entry> +<entry key='voting-results'> + <![CDATA[ + <h1>Voting Results</h1> + <h2>Selected Strategy</h2> + <hr> + <p><b> {first(selectedRules)} </b></p> + {if (tiebreaker)} + <p><b>NOTE:</b> There was a tie and selected strategy listed here was randomly selected as the winner.</p> + <h2>Other Nominated Strategies</h2> + <hr> + <ol> + {rest(selectedRules): {selectedRule | <li><b>{selectedRule}</b></li>}} + </ol> + {endif} + ]]> +</entry> + <entry key='initial-voting-instructions'><![CDATA[ <h1>Important New Instructions</h1> @@ -78,7 +130,7 @@ <p> The identity of people who nominated a particular strategy will NOT be revealed. Therefore, neither you nor the experimenter will know who nominated a particular -rule. +strategy. </p> ]]></entry> @@ -95,53 +147,17 @@ </p> ]]></entry> - <entry key='survey-url'><![CDATA[ https://qtrial.qualtrics.com/SE/?SID=SV_cLX7jnYikmD9eSM ]]></entry> - <entry key='sanction-type'>real-time</entry><entry key="sanction-cost">1</entry><entry key="sanction-multiplier">2</entry><entry key='sanction-instructions'><![CDATA[ - <h1>Important New Instructions</h1> - <h2>Reducing Other Player's Earnings</h2> - <hr> -<p> -Beginning with the upcoming round you will have the option to reduce the earnings of -another participant at a cost to your own earnings. -</p> - <ul> - <li>Each player in your group has a number from 1 to {clientsPerGroup}. If - you press a number key 1-{clientsPerGroup}, you will reduce the number - of tokens that player has collected during the round by - {sanctionPenalty} tokens. This will also reduce your own token amount by - {sanctionCost} token. The decision whether or when to use this option is - up to you. - </li> - <li>When you reduce the number of tokens of another participant, they will - receive a message stating that you have reduced their tokens. Likewise, if - another participant reduces your number of tokens, you will also receive a - message. These messages will be displayed on the bottom of your screen. - </li> - <li>If your tokens are being reduced or you are reducing another participant's - tokens, you will receive some visual cues. When your tokens are being reduced - your yellow dot will turn red briefly with a blue background. The participant - currently reducing your tokens will turn purple with a white background. - </li> - <li>You may reduce the earnings of other participants as long as (1) there are - tokens remaining on the screen and (2) both you and the other participant - have a positive number of tokens collected during the round. <b>Each time</b> - you press the numeric key corresponding to another participant your token - amount is reduced by <b>{sanctionCost}</b>, and their token amount is reduced by - <b>{sanctionPenalty}</b>. - </li> - </ul> ]]></entry> - </properties> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-11 19:52:32
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/49a442883dba/ changeset: 49a442883dba user: alllee date: 2012-01-11 20:52:28 summary: adding stringtemplate and antlr runtime to facilitator jnlp dependencies affected #: 1 file diff -r e54d653447fbdba25eb878886ea141c8a539f176 -r 49a442883dbaec38c07b09415eb478d4220cc61b src/main/resources/web/facilitator.jnlp --- a/src/main/resources/web/facilitator.jnlp +++ b/src/main/resources/web/facilitator.jnlp @@ -12,6 +12,8 @@ <resources><j2se version="1.6+"/><jar href="facilitator.jar"/> + <jar href='stringtemplate.jar'/> + <jar href='antlr-runtime.jar'/><jar href='@FRAMEWORK_JAR@'/></resources><application-desc main-class="@MAIN_CLASS@"/> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-11 06:26:26
|
3 new commits in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/0ee57867796a/ changeset: 0ee57867796a user: alllee date: 2012-01-10 21:35:58 summary: more instructions refactoring, working on integrating rule reminder into the regular round instructions. affected #: 7 files diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -51,6 +51,8 @@ private static final double DEFAULT_TOKEN_BIRTH_PROBABILITY = 0.01d; + private List<ForagingRule> selectedRules; + public double getTrustGamePayoffIncrement() { return getDoubleProperty("trust-game-payoff", 0.25d); } @@ -290,13 +292,15 @@ */ public String getInstructions() { ST template = createStringTemplate(getProperty("instructions", getParentConfiguration().getSameRoundAsPreviousInstructions())); - // FIXME: see if it's possible to simplify usage here so bean properties are transparently accessed within a templatized instruction. + // FIXME: this isn't ideal, figure out how to get any bean properties transparently accessible within a templatized instruction + // could do it via 1. reflection 2. annotations 3. ??? template.add("resourceWidth", getResourceWidth()); template.add("resourceDepth", getResourceDepth()); template.add("duration", inMinutes(getDuration()) + " minutes"); template.add("roundNumber", getRoundNumber()); template.add("clientsPerGroup", getClientsPerGroup()); template.add("dollarsPerToken", NumberFormat.getCurrencyInstance().format(getDollarsPerToken())); + template.add("initialDistribution", NumberFormat.getPercentInstance().format(getInitialDistribution())); return template.render(); } @@ -637,14 +641,11 @@ } public StringBuilder addAllSpecialInstructions(StringBuilder instructionsBuilder) { - // FIXME: refactor this convoluted conditional logic if possible + // FIXME: refactor this convoluted conditional logic, use StringTemplate StringBuilder builder = new StringBuilder(); if (isFieldOfVisionEnabled()) { addSpecialInstructions(builder, getFieldOfVisionInstructions()); } - if (isSanctioningEnabled()) { - addSpecialInstructions(builder, getSanctionInstructions()); - } if (isInRoundChatEnabled()) { addSpecialInstructions(builder, getInRoundChatInstructions()); } @@ -706,20 +707,19 @@ return getProperty("survey-instructions"); } - public String getSurveyLink() { - return getProperty("survey-link", "https://qtrial.qualtrics.com/SE/?SID=SV_38lReBOv0Wk7wgY"); + public String getSurveyUrl() { + return getProperty("survey-url", "https://qtrial.qualtrics.com/SE/?SID=SV_38lReBOv0Wk7wgY"); } public String getSurveyInstructions(Identifier id) { String surveyInstructions = getSurveyInstructions(); ST template = createStringTemplate(surveyInstructions); - template.add("surveyLink", getSurveyLink()); - template.add("participantId", id); + template.add("surveyLink", getSurveyUrl()); template.add("surveyId", id.getSurveyId()); return template.render(); } - public String getVotingNominationInstructions(List<ForagingRule> selectedRules) { + public String getVotingNominationInstructions() { // FIXME: move to template style construction StringBuilder builder = new StringBuilder("<h1>Voting Results</h1><hr>"); if (selectedRules.size() > 1) { @@ -749,4 +749,8 @@ } return template.render(); } + + public void setSelectedRules(List<ForagingRule> selectedRules) { + this.selectedRules = selectedRules; + } } diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -773,7 +773,9 @@ votingPanel.remove(votingForm); votingPanel.add(resultsForm); votingPanel.revalidate(); - votingInstructionsEditorPane.setText(client.getCurrentRoundConfiguration().getVotingNominationInstructions(selectedRules)); + RoundConfiguration currentRoundConfiguration = client.getCurrentRoundConfiguration(); + currentRoundConfiguration.setSelectedRules(selectedRules); + votingInstructionsEditorPane.setText(currentRoundConfiguration.getVotingNominationInstructions()); showPanel(VotingForm.NAME); } }); diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/java/edu/asu/commons/foraging/ui/VotingForm.java --- a/src/main/java/edu/asu/commons/foraging/ui/VotingForm.java +++ b/src/main/java/edu/asu/commons/foraging/ui/VotingForm.java @@ -30,14 +30,14 @@ import edu.asu.commons.ui.UserInterfaceUtils; /** - * - * @author alllee + * $Id$ + * @author Allen Lee */ public class VotingForm extends javax.swing.JPanel { private static final long serialVersionUID = 3871660663519284024L; - public final static String NAME = "Voting form"; + public final static String NAME = "Strategy voting form"; private ForagingClient client; @@ -71,15 +71,15 @@ rightHeaderLabel.setFont(UserInterfaceUtils.DEFAULT_BOLD_FONT); horizontalButtonParallelGroup.addComponent(rightHeaderLabel); - JLabel ruleHeaderLabel = new JLabel("Rule"); - ruleHeaderLabel.setFont(UserInterfaceUtils.DEFAULT_BOLD_FONT); - horizontalLabelParallelGroup.addComponent(ruleHeaderLabel); + JLabel strategyHeaderLabel = new JLabel("Strategy"); + strategyHeaderLabel.setFont(UserInterfaceUtils.DEFAULT_BOLD_FONT); + horizontalLabelParallelGroup.addComponent(strategyHeaderLabel); - verticalGroup.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(ruleHeaderLabel).addGap(10).addComponent(rightHeaderLabel)); + verticalGroup.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(strategyHeaderLabel).addGap(10).addComponent(rightHeaderLabel)); int ruleIndex = 0; for (ForagingRule rule: rules) { ruleIndex++; - JLabel ruleLabel = new JLabel(String.format("Rule %d: %s", ruleIndex, rule)); + JLabel ruleLabel = new JLabel(String.format("Strategy %d: %s", ruleIndex, rule)); ruleLabel.setFont(UserInterfaceUtils.DEFAULT_PLAIN_FONT); horizontalLabelParallelGroup.addComponent(ruleLabel); JComponent component = null; @@ -113,7 +113,7 @@ public void actionPerformed(ActionEvent e) { ButtonModel model = buttonGroup.getSelection(); if (model == null) { - JOptionPane.showMessageDialog(VotingForm.this, "Please select a rule."); + JOptionPane.showMessageDialog(VotingForm.this, "Please select a strategy."); return; } ForagingRule selectedRule = ForagingRule.valueOf(model.getActionCommand()); diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml @@ -2,7 +2,6 @@ <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"><properties><comment>Foraging XML-ized experiment round configuration</comment> -<entry key='initial-distribution'>0.5d</entry><entry key="resource-width">13</entry><entry key="resource-depth">13</entry><entry key="practice-round">true</entry> @@ -33,7 +32,7 @@ you will reset the distribution of the tokens to randomly occupying a quarter of the cells with green tokens. </p> -<p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> +<p><b>Do you have any questions?</b> If you have any questions at this time please raise your hand and someone will come over to your station and answer it.</p> ]]></entry> diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round1.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round1.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round1.xml @@ -25,13 +25,13 @@ <hr><p> In this round the renewable resource will become five times bigger. You will share this -larger environment with three other random players in this room . In particular, -each of you in this room has been randomly assigned to one of several equal-sized 4 +larger environment with three other random players in this room. In particular, +each of you in this room has been randomly assigned to one of several equal-sized {clientsPerGroup} person groups and everyone in your group has been randomly assigned a number from 1 to {clientsPerGroup}. You will stay in the same group for the entire experiment, and each person's -number from 1 to 4 will remain the same throughout the experiment. The other three people in your group will appear -on the screen as blue dots <img src="@CODEBASE_URL@/images/gem-other.gif"> with a -white number embedded in the dot. +number from 1 to {clientsPerGroup} will remain the same throughout the experiment. +The other three people in your group will appear on the screen as blue dots +<img src="@CODEBASE_URL@/images/gem-other.gif"> with a white number embedded in the dot. </p><p> In each round of the token task, you can see how many tokens each player has diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml @@ -29,40 +29,56 @@ <entry key='initial-voting-instructions'><![CDATA[ -<h1>Notice</h1> +<h1>Important New Instructions</h1> +<h2>Strategies for managing how players collect tokens for the rest of the experiment</h2><hr><p> -In a moment, you will see a screen on your computer called Rule Options. It -will list 6 different rules that you can consider as options for managing how -each of your groups collect green tokens today. +In a moment, you will have the option to implement one of six strategies for how you +and the three other people in your group collect tokens for the rest of the +experiment. +</p> +<h2>Procedure for Deciding the Strategy</h2> +<hr> +<p> + Each of the {clientsPerGroup} people in your group can nominate one of the six + potential strategies. The single strategy that receives the most nominations + wins. </p><p> -You can nominate one rule from the list to help decide whether or not to have a -rule and what that rule will be. The rule that has the most nominations will be -considered chosen and established as the rule. If there is a tie, then each -tied nominated rule will receive an equal chance of getting selected at random. + <b>If there is a tie</b>, one of the tied options will be selected at random by + the computer. Each of the tied strategies will have an equal chance of being + selected. </p> +<h2>Implementation</h2> +<hr> + <p>Neither the computer nor the experimenter will intervene to implement the + strategy. + </p> + + <p> + <b>Do you have any questions?</b> If you have any questions at this time, + raise your hand and someone will come over to your station and answer it. + </p> ]]></entry><entry key='voting-instructions'><![CDATA[ -<h1>Instructions</h1> +<h1>Strategy Nomination Instructions</h1><hr><p> -To nominate a rule, click the radio button to the left of the one you choose, and -then click "submit." The computer will tally the nominations and then report -the results on the next screen. The results will be presented to each -participant in your group and the experimenter. +To nominate a strategy, click the button to the right of the one you choose, and +then click "submit." The computer will tally the nominations and then report the +results on the next screen. The results will be presented to each person in +your group. </p> - +<h2>Your selection will be anonymous</h2> +<hr><p> -The identity of people who nominated a particular rule will NOT be revealed. -Therefore, neither you nor the experimenter will know who nominated a -particular rule. -</p> - +The identity of people who nominated a particular strategy will NOT be revealed. +Therefore, neither you nor the experimenter will know who nominated a particular +rule. </p> ]]></entry> @@ -74,18 +90,13 @@ <hr><p> Before we continue to the next round of the token task, we would like to ask you - some quick questions. At the beginning of the survey you will need to enter: - </p> - <ul> - <li><b>Your survey ID</b>: {surveyId} </li> - </ul> - <p> - Please <a href='{surveyLink}'>click here</a> to begin the survey. + some quick questions. Please <a href='{surveyUrl}&SURVEY_ID={surveyId}'>click here</a> to + begin the survey. </p> ]]></entry> -<entry key='survey-link'> +<entry key='survey-url'><![CDATA[ https://qtrial.qualtrics.com/SE/?SID=SV_cLX7jnYikmD9eSM ]]> @@ -97,7 +108,8 @@ <entry key="sanction-multiplier">2</entry><entry key='sanction-instructions'><![CDATA[ - <h1>Important New Instructions! Reducing other player's earnings.</h1> + <h1>Important New Instructions</h1> + <h2>Reducing Other Player's Earnings</h2><hr><p> Beginning with the upcoming round you will have the option to reduce the earnings of diff -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 src/main/resources/configuration/indiana-experiments/2011/vote-punish/server.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/server.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/server.xml @@ -176,7 +176,7 @@ <hr><p>Round {roundNumber} is the same as the previous round.</p><p>The length of this round is {duration}.</p> -<p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> +<p><b>Do you have any questions?</b> If you have any questions at this time please raise your hand and someone will come over to your station and answer it.</p> ]]></entry> https://bitbucket.org/virtualcommons/foraging/changeset/131e2e6862dd/ changeset: 131e2e6862dd user: alllee date: 2012-01-11 01:23:16 summary: updating foraging rules / strategies affected #: 1 file diff -r 0ee57867796a62492ab9d0a13eaeb23c4113a809 -r 131e2e6862ddfa41395062f771187eba8dcbfb50 src/main/java/edu/asu/commons/foraging/rules/ForagingRule.java --- a/src/main/java/edu/asu/commons/foraging/rules/ForagingRule.java +++ b/src/main/java/edu/asu/commons/foraging/rules/ForagingRule.java @@ -3,20 +3,20 @@ /** * $Id$ * - * A set of rules for the Indiana experiments run by Daniel DeCaro, Fall 2011. + * A set of rules for the Indiana experiments run by Daniel DeCaro in 2011/2012. * - * Split into a .iu subpackage if it turns out these aren't generic enough. + * Split into an .iu or other subpackage if it turns out these aren't generic enough. * * @author <a href='mailto:all...@as...'>Allen Lee</a> * @version $Rev$ */ public enum ForagingRule { - WAIT_TWO_MINUTES("Wait 2 minutes for the screen to fill up with green tokens. Then everyone collect tokens for the remaining amount of time."), - PRIVATE_PROPERTY("Each person gets a set area within which they can do whatever they want with the green tokens. With four people, each person gets one of the four corners."), - LIMITED_COLLECTION_RATE("Each person collects green tokens at a certain rate: 1 token every 3 seconds (i.e., count to 3 between each token you collect)."), - MAINTAIN_TOKEN_CLUSTERS("When someone collects from a cluster of green tokens (i.e., 3 or more tokens that are touching each other) that person leaves at least 2 tokens touching each other."), - LEAVE_TEN_FOR_REGROWTH("Collect green tokens until only about 10 are left; at that point, everyone must wait at least 1 minute before collecting any more tokens."), - NONE("No rule (Everyone can do whatever they want)."); + WAIT_ONE_MINUTE("Wait 60 seconds for the screen to fill up with tokens (the timer will have {remainingTime} left). Then everyone collects tokens for the remaining amount of time."), + PRIVATE_PROPERTY("Players divide the field up into four equally-sized areas and can do whatever they want within their area. With four people, each person takes an area around one of the four corners."), + LIMITED_COLLECTION_RATE("Each person collects tokens at a rate of 1 token every 4 seconds."), + MAINTAIN_TOKEN_CLUSTERS("Players leave two tokens untouched when the tokens are in a cluster of three or more that surround an empty cell."), + LEAVE_TEN_FOR_REGROWTH("Collect tokens until only 10 are left; at that point, everyone must wait at least 30 seconds before collecting any more tokens."), + NONE("Everyone can do whatever they want."); private final String description; https://bitbucket.org/virtualcommons/foraging/changeset/e54d653447fb/ changeset: e54d653447fb user: alllee date: 2012-01-11 07:26:21 summary: templatizing voting results, need to integrate strategy reminder and finish up the remaining screens next. affected #: 2 files diff -r 131e2e6862ddfa41395062f771187eba8dcbfb50 -r e54d653447fbdba25eb878886ea141c8a539f176 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -718,9 +718,20 @@ template.add("surveyId", id.getSurveyId()); return template.render(); } + + public String getSubmittedVoteInstructions() { + return getProperty("submitted-vote-instructions", "<h1>Submitted</h1><hr><p>Thank you for submitting your vote. Please wait while we tally the rest of the votes from the other members of your group.</p>"); + } - public String getVotingNominationInstructions() { + public String getVotingResults(List<ForagingRule> selectedRules) { + setSelectedRules(selectedRules); // FIXME: move to template style construction + ST template = createStringTemplate(getProperty("voting-results")); + template.add("tiebreaker", selectedRules.size() > 1); + template.add("selectedRules", selectedRules); + template.add("selectedRule", selectedRules.get(0)); + return template.render(); + /* StringBuilder builder = new StringBuilder("<h1>Voting Results</h1><hr>"); if (selectedRules.size() > 1) { // tiebreaker @@ -733,6 +744,7 @@ builder.append("<h1>Selected Rule</h1><hr>"); builder.append("<p><b>").append(selectedRules.get(0)).append("</b></p>"); return builder.toString(); + */ } @Override diff -r 131e2e6862ddfa41395062f771187eba8dcbfb50 -r e54d653447fbdba25eb878886ea141c8a539f176 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -750,6 +750,7 @@ private VotingForm votingForm; private HtmlEditorPane votingInstructionsEditorPane; + private JPanel getVotingPanel() { if (votingPanel == null) { votingPanel = new JPanel(); @@ -774,8 +775,7 @@ votingPanel.add(resultsForm); votingPanel.revalidate(); RoundConfiguration currentRoundConfiguration = client.getCurrentRoundConfiguration(); - currentRoundConfiguration.setSelectedRules(selectedRules); - votingInstructionsEditorPane.setText(currentRoundConfiguration.getVotingNominationInstructions()); + votingInstructionsEditorPane.setText(currentRoundConfiguration.getVotingResults(selectedRules)); showPanel(VotingForm.NAME); } }); @@ -895,8 +895,7 @@ } public void ruleVoteSubmitted() { - // TODO Auto-generated method stub - setInstructions("<h1>Submitted</h1><hr><p>Thank you for submitting your vote. Please wait while we tally the rest of the votes from the other members of your group.</p>"); + setInstructions(dataModel.getRoundConfiguration().getSubmittedVoteInstructions()); switchInstructionsPane(); } Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-10 00:12:22
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/62b5da02b0bc/ changeset: 62b5da02b0bc user: alllee date: 2012-01-10 01:12:16 summary: more instruction templating improvements, almost done with vote punish configuration. affected #: 12 files diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -18,6 +18,7 @@ import edu.asu.commons.foraging.model.EnforcementMechanism; import edu.asu.commons.foraging.rules.ForagingRule; import edu.asu.commons.net.Identifier; +import edu.asu.commons.util.Duration; /** @@ -64,6 +65,10 @@ } } } + + public enum PositionType { + LINE, SQUARE; + } private final static Map<String, ExperimentType> experimentTypeMap = new HashMap<String, ExperimentType>(3); @@ -281,13 +286,17 @@ } /** - * Returns the instructions for this round. + * Returns the instructions for this round. If undefined at the round level it uses default instructions at the parent ServerConfiguration level. */ public String getInstructions() { - ST template = createStringTemplate(getProperty("instructions")); + ST template = createStringTemplate(getProperty("instructions", getParentConfiguration().getSameRoundAsPreviousInstructions())); // FIXME: see if it's possible to simplify usage here so bean properties are transparently accessed within a templatized instruction. template.add("resourceWidth", getResourceWidth()); template.add("resourceDepth", getResourceDepth()); + template.add("duration", inMinutes(getDuration()) + " minutes"); + template.add("roundNumber", getRoundNumber()); + template.add("clientsPerGroup", getClientsPerGroup()); + template.add("dollarsPerToken", NumberFormat.getCurrencyInstance().format(getDollarsPerToken())); return template.render(); } @@ -305,6 +314,10 @@ return template.render(); } + public long inMinutes(Duration duration) { + return inMinutes(duration.getTimeLeftInSeconds()); + } + public long inMinutes(long seconds) { return TimeUnit.MINUTES.convert(seconds, TimeUnit.SECONDS); } @@ -707,6 +720,7 @@ } public String getVotingNominationInstructions(List<ForagingRule> selectedRules) { + // FIXME: move to template style construction StringBuilder builder = new StringBuilder("<h1>Voting Results</h1><hr>"); if (selectedRules.size() > 1) { // tiebreaker @@ -728,13 +742,6 @@ } public String getQuizResults(List<String> incorrectQuestionNumbers, Map<Object, Object> actualAnswers) { -// if (incorrectQuestionNumbers.isEmpty()) { -// notify the server and also notify the participant. -// builder.append("<p>You have answered all questions correctly. Please see below for more details.</p><hr>"); -// } -// else { -// builder.append("<p>At least one of your answers was incorrect. Please see below for more details.</p><hr>"); -// } ST template = createStringTemplate(getProperty("quiz-results")); template.add("allCorrect", incorrectQuestionNumbers.isEmpty()); for (String incorrectQuestionNumber : incorrectQuestionNumbers) { diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java @@ -1,5 +1,9 @@ package edu.asu.commons.foraging.conf; +import java.text.NumberFormat; + +import org.stringtemplate.v4.ST; + import edu.asu.commons.conf.ExperimentConfiguration; /** @@ -20,10 +24,13 @@ * @version $Revision$ */ public class ServerConfiguration extends ExperimentConfiguration.Base<RoundConfiguration> { - + private static final long serialVersionUID = -1737412253553943902L; - private final static String DEFAULT_LOG_FILE_DESTINATION = "foraging-server.log"; + private static final double DEFAULT_SHOW_UP_PAYMENT = 5.0d; + private static final double DEFAULT_QUIZ_CORRECT_ANSWER_REWARD = 0.50d; + private static final String SAME_ROUND_AS_PREVIOUS_INSTRUCTIONS = "<h3>Round {roundNumber} Instructions</h3><hr><p>Round {roundNumber} is the same as the previous round.</p><p>The length of this round is {duration}.</p><p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p>"; + private static final String DEFAULT_LOG_FILE_DESTINATION = "foraging-server.log"; private static final double DEFAULT_DOLLARS_PER_TOKEN = .02d; public ServerConfiguration() { @@ -69,11 +76,11 @@ } public double getShowUpPayment() { - return assistant.getDoubleProperty("show-up-payment", 5.0d); + return assistant.getDoubleProperty("show-up-payment", DEFAULT_SHOW_UP_PAYMENT); } public double getQuizCorrectAnswerReward() { - return assistant.getDoubleProperty("quiz-correct-answer-reward", 0.50d); + return assistant.getDoubleProperty("quiz-correct-answer-reward", DEFAULT_QUIZ_CORRECT_ANSWER_REWARD); } public String getWelcomeInstructions() { @@ -81,7 +88,15 @@ } public String getGeneralInstructions() { - return assistant.getStringProperty("general-instructions", ""); + ST st = createStringTemplate(assistant.getStringProperty("general-instructions", "")); + NumberFormat formatter = NumberFormat.getCurrencyInstance(); + st.add("showUpPayment", formatter.format(getShowUpPayment())); + st.add("dollarsPerToken", formatter.format(getDollarsPerToken())); + return st.render(); + } + + public String getSameRoundAsPreviousInstructions() { + return assistant.getStringProperty("sameRoundAsPreviousInstructions", SAME_ROUND_AS_PREVIOUS_INSTRUCTIONS); } public String getFieldOfVisionInstructions() { diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml @@ -22,11 +22,10 @@ task. </p><p> - During the practice round, you will have four minutes to practice with the + During the practice round, you will have {duration} to practice with the experimental environment. The decisions you make in this round will NOT influence your earnings. At the beginning of the practice round a quarter of the - cells are occupied with green tokens. The environment is a 13 x 13 grid of - cells. + cells are occupied with green tokens. The environment is a {resourceWidth} x {resourceDepth} grid of cells. </p><p> During this practice round, and <b>only during</b> this practice round, you are able @@ -45,7 +44,7 @@ <p> In a moment, you will do a practice round of the token task. Before we go to the practice round, answer the following questions to make sure you understand - the instructions. You will earn $0.50 for each correct answer. + the instructions. You will earn {quizCorrectAnswerReward} for each correct answer. </p><br><br><form> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round1.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round1.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round1.xml @@ -13,12 +13,12 @@ <entry key="instructions"><![CDATA[ -<h3>Instructions for Round 1</h3> +<h3>Instructions for Round {roundNumber}</h3><hr><p> The first round of the experiment will begin in a moment. The length of the - round is 4 minutes. As in the practice round you can collect green tokens. - This time you will earn <b>two cents</b> for each token collected. This time + round is {duration}. As in the practice round you can collect green tokens. + This time you will earn <b>{dollarsPerToken}</b> for each token collected. This time you <b>cannot</b> reset the distribution of green tokens. </p><h3>Groups</h3> @@ -28,7 +28,7 @@ larger environment with three other random players in this room . In particular, each of you in this room has been randomly assigned to one of several equal-sized 4 person groups and everyone in your group has been randomly assigned a number from 1 -to 4. You will stay in the same group for the entire experiment, and each person's +to {clientsPerGroup}. You will stay in the same group for the entire experiment, and each person's number from 1 to 4 will remain the same throughout the experiment. The other three people in your group will appear on the screen as blue dots <img src="@CODEBASE_URL@/images/gem-other.gif"> with a white number embedded in the dot. diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round2.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round2.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round2.xml @@ -15,17 +15,4 @@ <entry key='always-explicit'>true</entry><entry key='max-cell-occupancy'>1</entry> -<entry key="instructions"> -<![CDATA[ -<h3>Round 2 Instructions</h3> -<hr> -<p> -Round 2 is the same as round 1. -</p> -<p> -If you have any questions please raise your hand. <b>Do you have any -questions so far?</b> -</p> -]]> -</entry></properties> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round3.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round3.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round3.xml @@ -14,16 +14,4 @@ <!-- resource regrowth parameters --><entry key="initial-distribution">.25</entry> - -<entry key="instructions"> -<![CDATA[ -<h3>Round 3 Instructions</h3> -<hr> -<p>This round is the same as the previous round.</p> -<p> -If you have any questions please raise your hand. <b>Do you have any -questions so far?</b> -</p> -]]> -</entry></properties> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round4.xml @@ -13,6 +13,20 @@ <entry key="initial-distribution">.25</entry><entry key='voting-enabled'>true</entry> +<entry key="instructions"> + <![CDATA[ +<p> + Round {roundNumber} is about to begin. You have the option to reduce the + earnings of another participant at a cost to your own earnings by typing that + participants' number key from 1 to {clientsPerGroup}. +</p> +<p> + <b>Do you have any questions?</b> If you have any questions at this time, raise + your hand and someone will come over to your station and answer it. +</p> + ]]> +</entry> + <entry key='initial-voting-instructions'><![CDATA[ <h1>Notice</h1> @@ -53,24 +67,6 @@ ]]></entry> -<entry key="instructions"> -<![CDATA[ -<h3>Round 4 Instructions</h3> -<hr> -<p> - Round 4 is about to begin. -</p> - -<p> -The length of this round is four minutes. -</p> -<p> -If you have any questions please raise your hand. <b>Do you have any -questions so far?</b> -</p> -]]> -</entry> - <entry key='external-survey-enabled'>true</entry><entry key='survey-instructions'><![CDATA[ @@ -110,9 +106,10 @@ <ul><li>Each player in your group has a number from 1 to {clientsPerGroup}. If you press a number key 1-{clientsPerGroup}, you will reduce the number - of tokens that player has collected during the round by two tokens. This - will also reduce your own token amount by one token. The decision - whether or when to use this option is up to you. + of tokens that player has collected during the round by + {sanctionPenalty} tokens. This will also reduce your own token amount by + {sanctionCost} token. The decision whether or when to use this option is + up to you. </li><li>When you reduce the number of tokens of another participant, they will receive a message stating that you have reduced their tokens. Likewise, if @@ -128,8 +125,8 @@ tokens remaining on the screen and (2) both you and the other participant have a positive number of tokens collected during the round. <b>Each time</b> you press the numeric key corresponding to another participant your token - amount is reduced by <b>one</b>, and their token amount is reduced by - <b>two</b>. + amount is reduced by <b>{sanctionCost}</b>, and their token amount is reduced by + <b>{sanctionPenalty}</b>. </li></ul> ]]> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round5.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round5.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round5.xml @@ -13,21 +13,6 @@ <entry key='always-explicit'>true</entry><entry key='max-cell-occupancy'>1</entry> -<entry key="instructions"> -<![CDATA[ -<h3>Round 5 Instructions</h3> -<hr> -<p> -Round 5 is the same as round 4.</p> -<p> -The length of this round is again four minutes. -</p> -<p> -If you have any questions please raise your hand. <b>Do you have any -questions so far?</b> -</p> -]]> -</entry><entry key='sanction-type'>real-time</entry><entry key="sanction-cost">1</entry> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round6.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round6.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round6.xml @@ -53,19 +53,4 @@ ]]></entry> -<entry key="instructions"> -<![CDATA[ -<h3>Round 6 Instructions</h3> -<hr> -<p> -Round 6 is the same as round 5.</p> -<p> -The length of this round is again four minutes. -</p> -<p> -If you have any questions please raise your hand. <b>Do you have any -questions so far?</b> -</p> -]]> -</entry></properties> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round7.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round7.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round7.xml @@ -45,8 +45,9 @@ <h3>Instructions</h3><hr><p> -From this point forward, participants will NOT have the option to reduce the earnings of another participant. The length of this round is four minutes. +From this point forward, participants will NOT have the option to reduce the earnings of another participant. </p> +<p>The length of this round is {duration}.</p><p> If you have any questions please raise your hand. <b>Do you have any questions so far?</b> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round8.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round8.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round8.xml @@ -16,18 +16,4 @@ <entry key='always-explicit'>true</entry><entry key='max-cell-occupancy'>1</entry> - -<entry key="instructions"> -<![CDATA[ -<h3>Instructions</h3> -<hr> -<p> -The length of this round is again four minutes. -</p> -<p> -If you have any questions please raise your hand. <b>Do you have any -questions so far?</b> -</p> -]]> -</entry></properties> diff -r aab63233a67b3567a0a7eb144db559bae1437eb7 -r 62b5da02b0bcb5813fe6e8b1e807fe8bd02f35e9 src/main/resources/configuration/indiana-experiments/2011/vote-punish/server.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/server.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/server.xml @@ -59,7 +59,7 @@ <h2>Your Earnings</h2><hr><p> -You have already earned 5 dollars by showing up at this experiment. You can + You have already earned {showUpPayment} by showing up at this experiment. You can earn more, up to a maximum of about $15-$40, by participating in this experiment which will take about an hour to an hour and a half. The amount of money you earn depends on your decisions as well as the decisions of your group members.</p> @@ -68,7 +68,7 @@ <p> Today's experiment is on the computer. In the experiment, you can collect green diamond shaped tokens <img src="@CODEBASE_URL@/images/gem-token.gif"></img>, and - you will earn <b>two cents</b> for each token you collect. When the token task + you will earn <b>{dollarsPerToken}</b> for each token you collect. When the token task begins, you will appear on the screen as a yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img>. To collect a token, move your yellow dot over a green token and <b>press the space bar</b>. If you move over a token without pressing the space bar you will @@ -170,4 +170,14 @@ ]]></entry> +<entry key="sameRoundAsPreviousInstructions"> +<![CDATA[ +<h3>Round {roundNumber} Instructions</h3> +<hr> +<p>Round {roundNumber} is the same as the previous round.</p> +<p>The length of this round is {duration}.</p> +<p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> +]]> +</entry> + </properties> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-06 04:27:06
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/aab63233a67b/ changeset: aab63233a67b user: alllee date: 2012-01-06 05:26:57 summary: taking advantage of string template for instructions in configuration for asu and indiana experiments affected #: 4 files diff -r 0285ac97304f506e7f02e03a0c056be2754cae5a -r aab63233a67b3567a0a7eb144db559bae1437eb7 src/main/resources/configuration/asu-experiments/2011/pretest/round0.xml --- a/src/main/resources/configuration/asu-experiments/2011/pretest/round0.xml +++ b/src/main/resources/configuration/asu-experiments/2011/pretest/round0.xml @@ -7,7 +7,6 @@ <entry key="practice-round">true</entry><entry key="private-property">true</entry><entry key="duration">240</entry> - <entry key='tokens-field-of-vision'>true</entry><entry key='subjects-field-of-vision'>true</entry> @@ -23,14 +22,14 @@ <p> You will now have four minutes to practice with the experimental environment. The decisions you make in this round will NOT influence your earnings. At the beginning -of the practice round half of the cells are occupied with green tokens. The +of the practice round a quarter of the cells are occupied with green tokens. The environment is a {resourceWidth} x {resourceDepth} grid of cells. </p><p> During this practice round, and <b>only during</b> this practice round, you are able to reset the tokens displayed on the screen by pressing the <b>R</b> key. When you press the <b>R</b> key you will reset the resource to its initial distribution, -randomly filling half of the cells. +randomly filling a quarter of the cells. </p><p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> ]]> @@ -41,15 +40,17 @@ <h2>Quiz</h2><hr><p> -Before we begin the practice round please answer the following questions. You will earn {quizCorrectAnswerReward} for each correct answer. + In a moment, you will do a practice round of the token task. Before we go to + the practice round, answer the following questions to make sure you understand + the instructions. You will earn {quizCorrectAnswerReward} for each correct answer. </p><br><br><form> -<span class='q1'>Q1. Which one of the following statements is incorrect?</span><br> +<span class='q1'>Q1. Which of these statements is NOT correct?</span><br><input type="radio" name="q1" value="A">A. Your decisions of where to collect tokens affects the regeneration of tokens.<br><input type="radio" name="q1" value="B">B. When you have collected all tokens on the screen, no new tokens will appear.<br><input type="radio" name="q1" value="C">C. Tokens grow from the middle of the screen.<br> -<input type="radio" name="q1" value="D">D. In order to collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br> +<input type="radio" name="q1" value="D">D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br><br><br><span class='q2'>Q2. Which sequence of situations is not possible?</span><br><img src="@CODEBASE_URL@/images/question2.jpg"></img><br> @@ -60,16 +61,40 @@ </form> ]]></entry> -<entry key='q1-explanation'> +<entry key='quiz-results'><![CDATA[ - Tokens only regenerate when there are other tokens present in their immediately - neighboring cells. They do not spontaneously generate from the middle of the - screen. - ]]> -</entry> -<entry key='q2-explanation'> - <![CDATA[ - Tokens cannot regenerate on an empty screen as shown in sequence B. + <h2>Quiz Results</h2> + <hr> + <p> + {if (allCorrect)} + You have answered all the questions correctly. For more details, see below. + {else} + At least one of your answers was incorrect. Questions you've answered + incorrectly are highlighted in red. Please see below for more details. + {endif} + </p> + <br><hr> +<form> +<span class='q1'>Q1. Which of these statements is NOT correct?</span><br> + <b>{incorrect_q1} + In this question, "A", "B", and "D" are all true. "C" is false. Tokens only + regenerate when there are other tokens present in their immediately neighboring + cells. They do not spontaneously generate from the middle of the screen. + </b> +<br> +A. Your decisions of where to collect tokens affects the regeneration of tokens.<br> +B. When you have collected all tokens on the screen, no new tokens will appear.<br> +C. Tokens grow from the middle of the screen.<br> +D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br> +<br><br> +<span class='q2'>Q2. Which sequence of situations is not possible?</span><br> + <b> + {incorrect_q2} + In this question, sequence "B" is not possible. Tokens cannot regenerate on an empty screen as shown in sequence B. + </b> + <br> +<img src="@CODEBASE_URL@/images/question2.jpg"></img><br> +</form> ]]></entry></properties> diff -r 0285ac97304f506e7f02e03a0c056be2754cae5a -r aab63233a67b3567a0a7eb144db559bae1437eb7 src/main/resources/configuration/asu-experiments/2011/stationary-limitedvision/round0.xml --- a/src/main/resources/configuration/asu-experiments/2011/stationary-limitedvision/round0.xml +++ b/src/main/resources/configuration/asu-experiments/2011/stationary-limitedvision/round0.xml @@ -8,101 +8,90 @@ <entry key="private-property">true</entry><entry key="duration">240</entry> -<entry key='tokens-field-of-vision'>true</entry> -<entry key='subjects-field-of-vision'>true</entry> - <entry key="quiz">true</entry><entry key="q1">C</entry><entry key="q2">B</entry><entry key='instructions'><![CDATA[ -<h3>Practice Round Instructions</h3> +<h2>Practice Round Instructions</h2><hr><p> -You will now have four minutes to practice with the experimental environment. -The decisions you make in this round will NOT influence your earnings. At the -At the beginning of the practice round half of the cells are occupied -with green tokens. The environment is a 13 x 13 grid of cells. +You will now have four minutes to practice with the experimental environment. The +decisions you make in this round will NOT influence your earnings. At the beginning +of the practice round a quarter of the cells are occupied with green tokens. The +environment is a {resourceWidth} x {resourceDepth} grid of cells. </p><p> During this practice round, and <b>only during</b> this practice round, you are able to reset the tokens displayed on the screen by pressing the <b>R</b> key. When you press the <b>R</b> key you will reset the resource to its initial distribution, -randomly filling half of the cells. +randomly filling a quarter of the cells. </p> -<p><b> Please do not communicate with any other participant.</b></p> -<p>If you have any questions please raise your hand. <b>Do you have any -questions so far?</b></p> +<p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> ]]></entry><entry key="quiz-instructions"><![CDATA[ +<h2>Quiz</h2> +<hr><p> -Before we begin the practice round please answer the following questions. + In a moment, you will do a practice round of the token task. Before we go to + the practice round, answer the following questions to make sure you understand + the instructions. You will earn {quizCorrectAnswerReward} for each correct answer. </p> -<br> +<br><br><form> -<span class='q1'>Q1. Which of the statements is <b><u>incorrect</u></b>?</span><br> +<span class='q1'>Q1. Which of these statements is NOT correct?</span><br><input type="radio" name="q1" value="A">A. Your decisions of where to collect tokens affects the regeneration of tokens.<br><input type="radio" name="q1" value="B">B. When you have collected all tokens on the screen, no new tokens will appear.<br> -<input type="radio" name="q1" value="C">C. Tokens grow from the middle of the -screen.<br> -<input type="radio" name="q1" value="D">D. In order to collect a token you need -to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"> is on a cell with a token.<br> +<input type="radio" name="q1" value="C">C. Tokens grow from the middle of the screen.<br> +<input type="radio" name="q1" value="D">D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br><br><br> - -<span class='q2'>Q2. Which sequence of situations is <b><u>not possible</u></b>?</span><br> -<img src="@CODEBASE_URL@/images/question2.jpg"><br> +<span class='q2'>Q2. Which sequence of situations is not possible?</span><br> +<img src="@CODEBASE_URL@/images/question2.jpg"></img><br><input type="radio" name="q2" value="A">A<br><input type="radio" name="q2" value="B">B<br><input type="radio" name="q2" value="C">C<br> -<br> -<input type="submit" name="submit" value="Submit"> +<input type="submit" name="submit" value="Submit"><br></form> ]]></entry> - -<entry key='trust-game-instructions'> -<![CDATA[ -<h3>Task</h3> -<p> -You will be matched with another person in your group, but you will not know who -that person is. And that person will not know who you are. You make decisions for -the case you are drawn to be player 1 and the case you will be player 2. The -results of the decisions are given to you at the end of the whole experiment. -</p> - -<p> -The person drawn to be player 1 has the following decision to make. You will receive -an endowment of one dollar and decide how much to keep and how much to send to -another person in your group. -</p> - -<p> -The amount you send to the other person will be tripled and then given to the person -in your group with whom you have been matched. That person will decide how much to -keep and how much to send back to you. For example, if you send 0 extra credit -points to the other person, 0 extra credit points will be sent to the other person. -However, if you write 3 extra credit points on the form, 9 extra credit points will -be sent to the person. The other person would then decide how much to return to -you. -</p> - -<p> -Player 2 has the following decision to make. You have to choose for each of the 4 -possible cases how much to receive from player 1 how much to keep and how much to -send back to player 1. We ask you to fill in the tables for player 1 as well as for -player 2, and we will drawn whether you are player 1 or 2 after you have made the -decisions. -</p> - -<p> -Are there any questions? If you have a question, raise your hand and I will try to -answer it. -</p> -]]> +<entry key='quiz-results'> + <![CDATA[ + <h2>Quiz Results</h2> + <hr> + <p> + {if (allCorrect)} + You have answered all the questions correctly. For more details, see below. + {else} + At least one of your answers was incorrect. Questions you've answered + incorrectly are highlighted in red. Please see below for more details. + {endif} + </p> + <br><hr> +<form> +<span class='q1'>Q1. Which of these statements is NOT correct?</span><br> + <b>{incorrect_q1} + In this question, "A", "B", and "D" are all true. "C" is false. Tokens only + regenerate when there are other tokens present in their immediately neighboring + cells. They do not spontaneously generate from the middle of the screen. + </b> +<br> +A. Your decisions of where to collect tokens affects the regeneration of tokens.<br> +B. When you have collected all tokens on the screen, no new tokens will appear.<br> +C. Tokens grow from the middle of the screen.<br> +D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br> +<br><br> +<span class='q2'>Q2. Which sequence of situations is not possible?</span><br> + <b> + {incorrect_q2} + In this question, sequence "B" is not possible. Tokens cannot regenerate on an empty screen as shown in sequence B. + </b> + <br> +<img src="@CODEBASE_URL@/images/question2.jpg"></img><br> +</form> + ]]></entry> - </properties> diff -r 0285ac97304f506e7f02e03a0c056be2754cae5a -r aab63233a67b3567a0a7eb144db559bae1437eb7 src/main/resources/configuration/asu-experiments/2011/t1/round0.xml --- a/src/main/resources/configuration/asu-experiments/2011/t1/round0.xml +++ b/src/main/resources/configuration/asu-experiments/2011/t1/round0.xml @@ -19,14 +19,14 @@ <p> You will now have four minutes to practice with the experimental environment. The decisions you make in this round will NOT influence your earnings. At the beginning -of the practice round half of the cells are occupied with green tokens. The -environment is a 13 x 13 grid of cells. +of the practice round a quarter of the cells are occupied with green tokens. The +environment is a {resourceWidth} x {resourceDepth} grid of cells. </p><p> During this practice round, and <b>only during</b> this practice round, you are able to reset the tokens displayed on the screen by pressing the <b>R</b> key. When you press the <b>R</b> key you will reset the resource to its initial distribution, -randomly filling half of the cells. +randomly filling a quarter of the cells. </p><p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> ]]> @@ -37,15 +37,17 @@ <h2>Quiz</h2><hr><p> -Before we begin the practice round please answer the following questions. You will earn $0.50 for each correct answer. + In a moment, you will do a practice round of the token task. Before we go to + the practice round, answer the following questions to make sure you understand + the instructions. You will earn {quizCorrectAnswerReward} for each correct answer. </p><br><br><form> -<span class='q1'>Q1. Which one of the following statements is incorrect?</span><br> +<span class='q1'>Q1. Which of these statements is NOT correct?</span><br><input type="radio" name="q1" value="A">A. Your decisions of where to collect tokens affects the regeneration of tokens.<br><input type="radio" name="q1" value="B">B. When you have collected all tokens on the screen, no new tokens will appear.<br><input type="radio" name="q1" value="C">C. Tokens grow from the middle of the screen.<br> -<input type="radio" name="q1" value="D">D. In order to collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br> +<input type="radio" name="q1" value="D">D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br><br><br><span class='q2'>Q2. Which sequence of situations is not possible?</span><br><img src="@CODEBASE_URL@/images/question2.jpg"></img><br> @@ -56,16 +58,40 @@ </form> ]]></entry> -<entry key='q1-explanation'> +<entry key='quiz-results'><![CDATA[ - Tokens only regenerate when there are other tokens present in their immediately - neighboring cells. They do not spontaneously generate from the middle of the - screen. - ]]> -</entry> -<entry key='q2-explanation'> - <![CDATA[ - Tokens cannot regenerate on an empty screen as shown in sequence B. + <h2>Quiz Results</h2> + <hr> + <p> + {if (allCorrect)} + You have answered all the questions correctly. For more details, see below. + {else} + At least one of your answers was incorrect. Questions you've answered + incorrectly are highlighted in red. Please see below for more details. + {endif} + </p> + <br><hr> +<form> +<span class='q1'>Q1. Which of these statements is NOT correct?</span><br> + <b>{incorrect_q1} + In this question, "A", "B", and "D" are all true. "C" is false. Tokens only + regenerate when there are other tokens present in their immediately neighboring + cells. They do not spontaneously generate from the middle of the screen. + </b> +<br> +A. Your decisions of where to collect tokens affects the regeneration of tokens.<br> +B. When you have collected all tokens on the screen, no new tokens will appear.<br> +C. Tokens grow from the middle of the screen.<br> +D. To collect a token you need to press the space bar while your yellow dot <img src="@CODEBASE_URL@/images/gem-self.gif"></img> is on a cell with a token.<br> +<br><br> +<span class='q2'>Q2. Which sequence of situations is not possible?</span><br> + <b> + {incorrect_q2} + In this question, sequence "B" is not possible. Tokens cannot regenerate on an empty screen as shown in sequence B. + </b> + <br> +<img src="@CODEBASE_URL@/images/question2.jpg"></img><br> +</form> ]]></entry></properties> diff -r 0285ac97304f506e7f02e03a0c056be2754cae5a -r aab63233a67b3567a0a7eb144db559bae1437eb7 src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml --- a/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml +++ b/src/main/resources/configuration/indiana-experiments/2011/vote-punish/round0.xml @@ -24,14 +24,14 @@ <p> During the practice round, you will have four minutes to practice with the experimental environment. The decisions you make in this round will NOT - influence your earnings. At the beginning of the practice round half of the + influence your earnings. At the beginning of the practice round a quarter of the cells are occupied with green tokens. The environment is a 13 x 13 grid of cells. </p><p> During this practice round, and <b>only during</b> this practice round, you are able to reset the tokens displayed on the screen. When you push the <b>R</b> key -you will reset the distribution of the tokens to randomly occupying half of the +you will reset the distribution of the tokens to randomly occupying a quarter of the cells with green tokens. </p><p>If you have any questions please raise your hand. <b>Do you have any questions so far?</b></p> @@ -100,16 +100,4 @@ </form> ]]></entry> -<entry key='q1-explanation'> - <![CDATA[ - In this question, "A", "B", and "D" are all true. "C" is false. Tokens only - regenerate when there are other tokens present in their immediately neighboring - cells. They do not spontaneously generate from the middle of the screen. - ]]> -</entry> -<entry key='q2-explanation'> - <![CDATA[ - In this question, sequence "B" is not possible. Tokens cannot regenerate on an empty screen as shown in sequence B. - ]]> -</entry></properties> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2012-01-04 06:25:00
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/6289a219bd24/ changeset: 6289a219bd24 user: all...@SHESC-ALEE14-01.ph.cox.net date: 2012-01-04 07:24:00 summary: fixing display maximization bug caused by improper ordering of setVisible affected #: 3 files diff -r ff6f681c74fd5eb3ce19bc6652dd480e92b07e3a -r 6289a219bd24b0b06a468eaae6bf2c97569afa13 src/main/java/edu/asu/commons/foraging/client/ForagingClient.java --- a/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java +++ b/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java @@ -3,6 +3,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Frame; +import java.awt.Toolkit; import java.util.LinkedList; import javax.swing.JFrame; @@ -416,10 +417,10 @@ client.connect(); frame.setTitle("Client Window: " + client.getId()); frame.add(client.clientPanel); - frame.setVisible(true); frame.setExtendedState(Frame.MAXIMIZED_BOTH); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.pack(); + frame.setVisible(true); } }; SwingUtilities.invokeLater(createGuiRunnable); diff -r ff6f681c74fd5eb3ce19bc6652dd480e92b07e3a -r 6289a219bd24b0b06a468eaae6bf2c97569afa13 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -275,7 +275,7 @@ @Override public void handle(DisconnectionRequest event) { synchronized (clients) { - logger.warning("Disconnecting client, removing from clients: " + event.getId()); + logger.warning("Disconnecting client, removing " + event.getId() + " from clients " + clients.keySet()); clients.remove(event.getId()); } } diff -r ff6f681c74fd5eb3ce19bc6652dd480e92b07e3a -r 6289a219bd24b0b06a468eaae6bf2c97569afa13 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -343,8 +343,7 @@ } private String getTimeLeftLabelText(long roundTimeLeft) { - long secondsLeft = roundTimeLeft / 1000L; - return "Time left: " + secondsLeft + " second(s)"; + return String.format("Time left: %d second(s)", roundTimeLeft / 1000L); } private void setInstructions(String s) { Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-12-20 20:57:29
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/ff6f681c74fd/ changeset: ff6f681c74fd user: alllee date: 2011-12-20 21:57:17 summary: updating ivy configuration to exclude source and javadoc jars to avoid http://stackoverflow.com/questions/7283757/how-do-i-solve-multiple-artifacts-of-the-module-x-are-retrieved-to-the-same-file affected #: 2 files diff -r 3d41176b27e1e91a9520889a74d69a6a3639f813 -r ff6f681c74fd5eb3ce19bc6652dd480e92b07e3a build.xml --- a/build.xml +++ b/build.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> -<!-- $Id: build.xml 330 2008-02-13 05:31:26Z alllee $ +<!-- $Id$ vim:sts=2:sw=2: - Version: $Revision: 330 $ + Version: $Revision$ --><project xmlns:ivy="antlib:org.apache.ivy.ant" name="foraging" default="build-all" basedir="."><!-- ensure ivy availability --> diff -r 3d41176b27e1e91a9520889a74d69a6a3639f813 -r ff6f681c74fd5eb3ce19bc6652dd480e92b07e3a ivy.xml --- a/ivy.xml +++ b/ivy.xml @@ -5,9 +5,9 @@ <ivy-module version="2.0"><info organisation="edu.asu.commons" module="foraging"/><dependencies> - <dependency org="edu.asu.commons" name="csidex" rev="0.2-SNAPSHOT"/> + <dependency org="edu.asu.commons" name="csidex" rev="0.2-SNAPSHOT" /><dependency org="net.java.dev.jogl" name="jogl" rev="1.1.1-rc6"/><dependency org="javax.media" name="jmf" rev="2.1.1e"/> - <dependency org="org.antlr" name="stringtemplate" rev="4.0.2"/> + <dependency org="org.antlr" name="stringtemplate" rev="4.0.2" conf="*->*,!sources,!javadoc"/></dependencies></ivy-module> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-12-14 23:51:20
|
1 new commit in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/3d41176b27e1/ changeset: 3d41176b27e1 user: alllee date: 2011-12-15 00:51:15 summary: moving dollarsPerToken into the ServerConfiguration as well and having RoundConfiguration defer to it in the event that it's not set in the round configuration. Adding dollar defaults to the stockholm censored chat configuration so Micael knows where to modify them. May also need to have a configuration parameter / localization issue to switch from dollars to krona. affected #: 3 files diff -r 6901d927ccc1366ae4556829dda17cda64518b40 -r 3d41176b27e1e91a9520889a74d69a6a3639f813 src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/RoundConfiguration.java @@ -46,14 +46,10 @@ private static final int DEFAULT_SANCTION_FLASH_DURATION = 3; - private static final double DEFAULT_DOLLARS_PER_TOKEN = .02d; - private static final double DEFAULT_TOKEN_MOVEMENT_PROBABILITY = 0.2d; private static final double DEFAULT_TOKEN_BIRTH_PROBABILITY = 0.01d; - - public double getTrustGamePayoffIncrement() { return getDoubleProperty("trust-game-payoff", 0.25d); } @@ -281,7 +277,7 @@ } public double getDollarsPerToken() { - return getDoubleProperty("dollars-per-token", DEFAULT_DOLLARS_PER_TOKEN); + return getDoubleProperty("dollars-per-token", getParentConfiguration().getDollarsPerToken()); } /** diff -r 6901d927ccc1366ae4556829dda17cda64518b40 -r 3d41176b27e1e91a9520889a74d69a6a3639f813 src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java @@ -24,7 +24,8 @@ private static final long serialVersionUID = -1737412253553943902L; private final static String DEFAULT_LOG_FILE_DESTINATION = "foraging-server.log"; - + private static final double DEFAULT_DOLLARS_PER_TOKEN = .02d; + public ServerConfiguration() { super(); } @@ -91,5 +92,9 @@ public boolean shouldAskForSurveyId() { return getBooleanProperty("survey-id-enabled"); } + + public double getDollarsPerToken() { + return DEFAULT_DOLLARS_PER_TOKEN; + } } diff -r 6901d927ccc1366ae4556829dda17cda64518b40 -r 3d41176b27e1e91a9520889a74d69a6a3639f813 src/main/resources/configuration/stockholm/censored-chat/server.xml --- a/src/main/resources/configuration/stockholm/censored-chat/server.xml +++ b/src/main/resources/configuration/stockholm/censored-chat/server.xml @@ -11,6 +11,8 @@ <entry key="round4">round4.xml</entry><entry key="round5">round5.xml</entry><entry key="round6">round6.xml</entry> +<entry key='show-up-payment'>10.0</entry> +<entry key='show-up-payment'>0.02</entry><entry key="wait-for-participants">true</entry><entry key="number-of-rounds">7</entry><entry key="facilitator-instructions"> Repository URL: https://bitbucket.org/virtualcommons/foraging/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. |
From: Bitbucket <com...@bi...> - 2011-12-13 00:40:08
|
3 new commits in foraging: https://bitbucket.org/virtualcommons/foraging/changeset/80094b419037/ changeset: 80094b419037 user: alllee date: 2011-12-06 22:17:42 summary: censored chat is now working again, still need to test sanctioning in this condition affected #: 6 files diff -r 7065b38e2c9c054b0517b14b6f571fdaa3bf7f3b -r 80094b4190373fe4b978f246cf97d86f106f26f1 src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java --- a/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java +++ b/src/main/java/edu/asu/commons/foraging/conf/ServerConfiguration.java @@ -3,7 +3,7 @@ import edu.asu.commons.conf.ExperimentConfiguration; /** - * $Id: ServerConfiguration.java 529 2010-08-17 00:08:01Z alllee $ + * $Id$ * * Contains the know-how for parsing and programmatically accessing the * server's configuration file properties. The forager server's config file @@ -17,7 +17,7 @@ * * @author <a href='mailto:All...@as...'>Allen Lee</a> * @see - * @version $Revision: 529 $ + * @version $Revision$ */ public class ServerConfiguration extends ExperimentConfiguration.Base<RoundConfiguration> { @@ -47,7 +47,7 @@ } public boolean isCensoredChat() { - return assistant.getBooleanProperty("censored-chat", false); + return assistant.getBooleanProperty("censored-chat-enabled", false); } public boolean shouldInitialize3D() { diff -r 7065b38e2c9c054b0517b14b6f571fdaa3bf7f3b -r 80094b4190373fe4b978f246cf97d86f106f26f1 src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java --- a/src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java +++ b/src/main/java/edu/asu/commons/foraging/event/FacilitatorCensoredChatRequest.java @@ -6,7 +6,7 @@ import edu.asu.commons.net.Identifier; /** - * $Id: FacilitatorCensoredChatRequest.java 522 2010-06-30 19:17:48Z alllee $ + * $Id$ * * Event used to forward censored chat requests to the facilitator. * @@ -19,8 +19,8 @@ private ChatRequest censoredChatRequest; - public FacilitatorCensoredChatRequest(Identifier facilitatorId, ChatRequest request) { - super(facilitatorId); + public FacilitatorCensoredChatRequest(Identifier id, ChatRequest request) { + super(id); this.censoredChatRequest = request; } @@ -36,5 +36,9 @@ return censoredChatRequest.getTarget(); } + public void setId(Identifier id) { + super.id = id; + } + } diff -r 7065b38e2c9c054b0517b14b6f571fdaa3bf7f3b -r 80094b4190373fe4b978f246cf97d86f106f26f1 src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorChatPanel.java @@ -23,11 +23,13 @@ import edu.asu.commons.util.ResourceLoader; /** - * $Id: FacilitatorChatPanel.java 533 2010-11-23 19:31:57Z alllee $ + * $Id$ * * Exposes a JPanel for approving chat messages and tied to a specific Facilitator instance. * + * * FIXME: should get rid of Facilitator dependency and use EventChannel instead + * FIXME: turn this into a JTable instead. * * * @author <a href='mailto:All...@as...'>Allen Lee</a> @@ -79,7 +81,7 @@ chatRequestsPanel.setLayout(groupLayout); groupLayout.setAutoCreateGaps(true); GroupLayout.SequentialGroup horizontalGroup = groupLayout.createSequentialGroup(); - JLabel messagesLabel = new JLabel("Messages"); + JLabel messagesLabel = new JLabel("Message"); JLabel approveLabel = new JLabel("Approve"); JLabel statusLabel = new JLabel("Status"); JLabel denyLabel = new JLabel("Deny"); @@ -162,7 +164,7 @@ statusLabelParallelGroup.addComponent(statusLabel); denyParallelGroup.addComponent(denyButton); - GroupLayout.ParallelGroup rowParallelGroup = groupLayout.createParallelGroup(Alignment.BASELINE); + GroupLayout.ParallelGroup rowParallelGroup = groupLayout.createParallelGroup(Alignment.LEADING); rowParallelGroup.addComponent(chatMessageTextArea).addComponent(approveButton).addComponent(statusLabel).addComponent(denyButton); verticalGroup.addGroup(rowParallelGroup); } diff -r 7065b38e2c9c054b0517b14b6f571fdaa3bf7f3b -r 80094b4190373fe4b978f246cf97d86f106f26f1 src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java @@ -224,9 +224,7 @@ - informationScrollPane = new JScrollPane(informationEditorPane, - ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, - ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + informationScrollPane = new JScrollPane(informationEditorPane); setInstructions(facilitator.getServerConfiguration().getFacilitatorInstructions()); @@ -237,21 +235,19 @@ Dimension minimumSize = new Dimension(600, 200); messagePanel.setMinimumSize(minimumSize); informationScrollPane.setMinimumSize(minimumSize); - - if (facilitator.getServerConfiguration().isCensoredChat()) { - facilitatorChatPanel = new FacilitatorChatPanel(facilitator); - messagePanel.add(facilitatorChatPanel.getComponent(), BorderLayout.CENTER); - } - else { - messageEditorPane = UserInterfaceUtils.createInstructionsEditorPane(); - JScrollPane messageScrollPane = new JScrollPane(messageEditorPane); - messagePanel.add(messageScrollPane, BorderLayout.CENTER); - } + messageEditorPane = UserInterfaceUtils.createInstructionsEditorPane(); + JScrollPane messageScrollPane = new JScrollPane(messageEditorPane); + messagePanel.add(messageScrollPane, BorderLayout.CENTER); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, informationScrollPane, messagePanel); add(splitPane, BorderLayout.CENTER); double proportion = 0.6d; splitPane.setDividerLocation(proportion); splitPane.setResizeWeight(proportion); + // add censored chat component if necessary + if (facilitator.getServerConfiguration().isCensoredChat()) { + facilitatorChatPanel = new FacilitatorChatPanel(facilitator); + add(facilitatorChatPanel.getComponent(), BorderLayout.SOUTH); + } } private void setInstructions(String contents) { diff -r 7065b38e2c9c054b0517b14b6f571fdaa3bf7f3b -r 80094b4190373fe4b978f246cf97d86f106f26f1 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -81,12 +81,12 @@ import edu.asu.commons.util.Utils; /** - * $Id: ForagingServer.java 529 2010-08-17 00:08:01Z alllee $ + * $Id$ * * Main experiment server class for costly sanctioning 2D experiment. * * @author <a href='mailto:All...@as...'>Allen Lee</a> - * @version $Revision: 529 $ + * @version $Revision$ */ public class ForagingServer extends AbstractExperiment<ServerConfiguration, RoundConfiguration> { @@ -284,11 +284,18 @@ sendFacilitatorMessage("configuration doesn't allow for chat but received " + request); return; } - if (configuration.isCensoredChat()) { - transmit(new FacilitatorCensoredChatRequest(facilitatorId, request)); + relayChatRequest(request); + } + }); + addEventProcessor(new EventTypeProcessor<FacilitatorCensoredChatRequest>(FacilitatorCensoredChatRequest.class) { + public void handle(FacilitatorCensoredChatRequest request) { + if (getCurrentRoundConfiguration().isCensoredChat()) { + sendFacilitatorMessage("needs approval: " + request); + request.setId(facilitatorId); + transmit(request); } else { - relayChatRequest(request); + sendFacilitatorMessage("WARNING: received censored chat request but censored chat isn't enabled, bug in configuration."); } } }); diff -r 7065b38e2c9c054b0517b14b6f571fdaa3bf7f3b -r 80094b4190373fe4b978f246cf97d86f106f26f1 src/main/java/edu/asu/commons/foraging/ui/ChatPanel.java --- a/src/main/java/edu/asu/commons/foraging/ui/ChatPanel.java +++ b/src/main/java/edu/asu/commons/foraging/ui/ChatPanel.java @@ -23,6 +23,7 @@ import edu.asu.commons.experiment.DataModel; import edu.asu.commons.foraging.client.ForagingClient; import edu.asu.commons.foraging.conf.RoundConfiguration; +import edu.asu.commons.foraging.event.FacilitatorCensoredChatRequest; import edu.asu.commons.net.Identifier; import edu.asu.commons.ui.UserInterfaceUtils; @@ -155,9 +156,16 @@ if (message == null || "".equals(message) || targetIdentifier == null) { return; } - client.transmit(new ChatRequest(client.getId(), message, targetIdentifier)); + RoundConfiguration configuration = client.getCurrentRoundConfiguration(); + ChatRequest request = new ChatRequest(client.getId(), message, targetIdentifier); + if (configuration.isCensoredChat()) { + client.transmit(new FacilitatorCensoredChatRequest(client.getId(), request)); + } + else { + client.transmit(request); + } // special case for in round chat - if (client.getCurrentRoundConfiguration().isInRoundChatEnabled()) { + if (configuration.isInRoundChatEnabled()) { client.getGameWindow().requestFocusInWindow(); } else { https://bitbucket.org/virtualcommons/foraging/changeset/a1fbd4dbf928/ changeset: a1fbd4dbf928 user: alllee date: 2011-12-08 01:28:17 summary: profiling refactor, removing GroupDataModel from ClientDataModel and instead storing data directly on the ClientDataModel. affected #: 16 files diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/client/ClientDataModel.java --- a/src/main/java/edu/asu/commons/foraging/client/ClientDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/client/ClientDataModel.java @@ -12,37 +12,32 @@ import edu.asu.commons.foraging.event.ClientPositionUpdateEvent; import edu.asu.commons.foraging.event.ExplicitCollectionModeRequest; import edu.asu.commons.foraging.event.RealTimeSanctionRequest; -import edu.asu.commons.foraging.event.SynchronizeClientEvent; +import edu.asu.commons.foraging.graphics.Point3D; import edu.asu.commons.foraging.model.ClientData; -import edu.asu.commons.foraging.model.EnforcementMechanism; import edu.asu.commons.foraging.model.ForagingDataModel; import edu.asu.commons.foraging.model.GroupDataModel; -import edu.asu.commons.foraging.model.RegulationData; import edu.asu.commons.foraging.model.Resource; -import edu.asu.commons.foraging.model.SanctionMechanism; import edu.asu.commons.foraging.rules.ForagingRule; -import edu.asu.commons.foraging.ui.GameWindow2D; import edu.asu.commons.net.Identifier; import edu.asu.commons.util.Duration; /** - * $Id: ClientDataModel.java 499 2010-03-31 00:58:49Z alllee $ + * $Id$ * * This class should only provide game state relevant to a particular client. * * @author Allen Lee - * @version $Revision: 499 $ + * @version $Revision$ */ public class ClientDataModel extends ForagingDataModel { private static final long serialVersionUID = -3424256672940188027L; - private GroupDataModel groupDataModel; +// private GroupDataModel groupDataModel; private final List<Identifier> allClientIdentifiers = new ArrayList<Identifier>(); - // FIXME: can obtain tokensConsumed from the clientDataMap now. - private int currentTokens; + private ClientData clientData; // these are the subjects whom we have sanctioned private Map<Identifier, Duration> sanctioned = new HashMap<Identifier, Duration>(); @@ -55,6 +50,12 @@ private volatile boolean explicitCollectionMode = false; + private Map<Identifier, Point> clientPositions; + + private Map<Identifier, Integer> clientTokens; + + private Map<Point, Resource> resourceDistribution; + public ClientDataModel(ForagingClient client) { super(client.getEventChannel()); this.client = client; @@ -65,13 +66,6 @@ client.transmit(new ExplicitCollectionModeRequest(client.getId(), explicitCollectionMode)); } - public Identifier getMonitorId() { - if (groupDataModel.getActiveMonitor() != null) { - return groupDataModel.getActiveMonitor().getId(); - } - return Identifier.NULL; - } - public boolean isSanctioningAllowed() { return getRoundConfiguration().isSanctioningEnabled(); } @@ -97,15 +91,23 @@ * Returns a Set containing the positions of food pellets. */ public Set<Point> getResourcePositions() { - return groupDataModel.getResourcePositions(); + return resourceDistribution.keySet(); } public Map<Point, Resource> getResourceDistribution() { - return groupDataModel.getResourceDistribution(); + return resourceDistribution; + } + + public Point getClientPosition(Identifier sanctionee) { + return clientPositions.get(sanctionee); + } + + public Map<Identifier, Point> getClientPositions() { + return clientPositions; } public ClientData getClientData() { - return groupDataModel.getClientData(getId()); + return clientData; } public Identifier getId() { @@ -116,32 +118,20 @@ allClientIdentifiers.clear(); sanctioned.clear(); sanctioners.clear(); - if (groupDataModel != null) { - groupDataModel.clear(); - groupDataModel = null; - } + // FIXME: replace } - public List<RegulationData> getSubmittedRegulations() { - return groupDataModel.getSubmittedRegulations(); - } - - public EnforcementMechanism getActiveEnforcementMechanism() { - return groupDataModel.getActiveEnforcementMechanism(); - } - - public SanctionMechanism getActiveSanctionMechanism() { - return groupDataModel.getActiveSanctionMechanism(); - } - public void initialize(GroupDataModel groupDataModel) { clear(); - this.groupDataModel = groupDataModel; Map<Identifier, ClientData> clientDataMap = groupDataModel.getClientDataMap(); Identifier[] ids = new Identifier[clientDataMap.size()]; + // ensure that the allClientIdentifiers natural ordering is by assigned number. for (Map.Entry<Identifier, ClientData> entry : clientDataMap.entrySet()) { - int index = entry.getValue().getAssignedNumber() - 1; - ids[index] = entry.getKey(); + Identifier id = entry.getKey(); + ClientData data = entry.getValue(); + int index = data.getAssignedNumber() - 1; + ids[index] = id; +// clientAssignedNumbers.put(id, data.getAssignedNumber()); } allClientIdentifiers.addAll(Arrays.asList(ids)); } @@ -160,19 +150,23 @@ // if (this.groupDataModel != null) { // this.groupDataModel.clear(); // } - this.groupDataModel = groupDataModel; - currentTokens = groupDataModel.getCurrentTokens( getId() ); +// this.groupDataModel = groupDataModel; + this.clientData = groupDataModel.getClientData(getId()); + update(groupDataModel.getClientTokens(), groupDataModel.getClientPositions(), clientData.getLatestSanctions(), null, null); +// currentTokens = groupDataModel.getCurrentTokens( getId() ); } public List<Identifier> getAllClientIdentifiers() { return allClientIdentifiers; } + @Deprecated public List<ClientData> getOtherClients() { - List<ClientData> clients = new ArrayList<ClientData>(); - clients.addAll(groupDataModel.getClientDataMap().values()); - clients.remove(getClientData()); - return clients; + throw new UnsupportedOperationException("This is now deprecated."); +// List<ClientData> clients = new ArrayList<ClientData>(); +// clients.addAll(groupDataModel.getClientDataMap().values()); +// clients.remove(getClientData()); +// return clients; } public int getAssignedNumber(Identifier id) { @@ -180,43 +174,39 @@ } /** - * Updates client positions, current tokens, etc. FIXME: slight optimization - * hot-spot, 9% of time spent here. + * Updates client positions, current tokens, etc. */ - public void updateDiffs(ClientPositionUpdateEvent event, GameWindow2D window) { - currentTokens = event.getCurrentTokens(); - groupDataModel.updateDiffs(event); - handleRealTimeSanctions(event.getLatestSanctions()); - window.update(event.getTimeLeft()); + public void update(ClientPositionUpdateEvent event) { + update(event.getClientTokens(), event.getClientPositions(), event.getLatestSanctions(), event.getAddedTokens(), event.getRemovedTokens()); } - - /** - * FIXME: lift repeated code from here and update(..) - * - * @param event - * @param window - */ - public void update(SynchronizeClientEvent event, GameWindow2D window) { - if (event.getCurrentTokens() > currentTokens) { - window.collectToken(event.getClientPosition()); + + public void update(Map<Identifier, Integer> clientTokens, + Map<Identifier, Point> currentPositions, + Queue<RealTimeSanctionRequest> latestSanctions, + Resource[] addedResources, + Resource[] removedResources) + { + this.clientTokens = clientTokens; + this.clientPositions = currentPositions; + handleRealTimeSanctions(latestSanctions); + synchronized (resourceDistribution) { + if (removedResources != null) { + for (Resource resource: removedResources) { + resourceDistribution.remove(resource.getPosition()); + } + } + if (addedResources != null) { + for (Resource resource: addedResources) { + resourceDistribution.put(resource.getPosition(), resource); + } + } } - currentTokens = event.getCurrentTokens(); - // groupDataModel.update(event); - handleRealTimeSanctions(event.getLatestSanctions()); } private synchronized void handleRealTimeSanctions(Queue<RealTimeSanctionRequest> latestSanctions) { -// if (!getRoundConfiguration().isRealTimeSanctioningEnabled()) { -// return; -// } for (RealTimeSanctionRequest sanctionRequest : latestSanctions) { System.err.println("Processing real time sanction: from " + sanctionRequest.getSource() + " to " + sanctionRequest.getTarget()); sanction(sanctionRequest.getSource(), sanctionRequest.getTarget()); -// if (getId().equals(sanctionEvent.getTarget())) { - // received a penalty, change colors for the duration of the - // sanction. -// sanction(sanctionEvent.getSource(), getId()); -// } } } @@ -225,19 +215,23 @@ } public int getCurrentTokens() { - return currentTokens; + return clientData.getCurrentTokens(); + } + + public int getCurrentTokens(Identifier id) { + return clientTokens.get(id); } - public Map<Identifier, ClientData> getClientDataMap() { - return new HashMap<Identifier, ClientData>(groupDataModel.getClientDataMap()); - } +// public Map<Identifier, ClientData> getClientDataMap() { +// return groupDataModel.getClientDataMap(); +// } public synchronized boolean isBeingSanctioned(Identifier id) { return checkSanctionStatus(sanctioned, id); } public int getTotalTokens() { - return groupDataModel.getClientData(getId()).getTotalTokens(); + return clientData.getTotalTokens(); } public double getCurrentIncome() { @@ -276,25 +270,6 @@ } // FIXME: deprecate and remove these later - public void clearDiffLists() { - groupDataModel.clearDiffLists(); - } - - public Set<Resource> getAddedResources() { - return groupDataModel.getAddedResources(); - } - - public Set<Resource> getRemovedResources() { - return groupDataModel.getRemovedResources(); - } - - public void setActiveRegulation(RegulationData regulationData) { - groupDataModel.setActiveRegulation(regulationData); - } - - public RegulationData getActiveRegulation() { - return groupDataModel.getActiveRegulation(); - } public void setSelectedRules(List<ForagingRule> selectedRules) { this.selectedRules = selectedRules; } @@ -302,4 +277,10 @@ public List<ForagingRule> getSelectedRules() { return selectedRules; } + + public Point3D getPoint3D(Identifier id) { + // FIXME: this is broken + throw new UnsupportedOperationException("3D support is currently unavailable"); + } + } diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/client/ForagingClient.java --- a/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java +++ b/src/main/java/edu/asu/commons/foraging/client/ForagingClient.java @@ -2,7 +2,6 @@ import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Dimension; import java.awt.Frame; import java.util.LinkedList; @@ -27,7 +26,6 @@ import edu.asu.commons.foraging.event.ClientPositionUpdateEvent; import edu.asu.commons.foraging.event.CollectTokenRequest; import edu.asu.commons.foraging.event.EndRoundEvent; -import edu.asu.commons.foraging.event.LockResourceEvent; import edu.asu.commons.foraging.event.PostRoundSanctionRequest; import edu.asu.commons.foraging.event.PostRoundSanctionUpdateEvent; import edu.asu.commons.foraging.event.RealTimeSanctionRequest; @@ -49,6 +47,7 @@ import edu.asu.commons.foraging.ui.GameWindow3D; import edu.asu.commons.net.SocketIdentifier; import edu.asu.commons.util.Duration; +import edu.asu.commons.util.Utils; @@ -208,29 +207,37 @@ } } }); + addEventProcessor(new EventTypeProcessor<ClientPositionUpdateEvent>(ClientPositionUpdateEvent.class) { + public void handle(ClientPositionUpdateEvent event) { + if (state == ClientState.RUNNING) { + dataModel.update(event); + getGameWindow().update(event.getTimeLeft()); + } + } + }); addEventProcessor(new EventTypeProcessor<SynchronizeClientEvent>(SynchronizeClientEvent.class) { public void handle(SynchronizeClientEvent event) { dataModel.setGroupDataModel(event.getGroupDataModel()); - // FIXME: gross - if (dataModel.is2dExperiment()) { - dataModel.update(event, getGameWindow2D()); - } + +// if (dataModel.is2dExperiment()) { +// dataModel.update(event, getGameWindow2D()); +// } getGameWindow().update(event.getTimeLeft()); } }); initialize2DEventProcessors(); - initialize3DEventProcessors(); +// initialize3DEventProcessors(); messageQueue = new MessageQueue(); } - private void initialize3DEventProcessors() { - addEventProcessor(new EventTypeProcessor<LockResourceEvent>(LockResourceEvent.class) { - public void handle(LockResourceEvent event) { - // tell the game window to highlight the appropriate resource - getGameWindow3D().highlightResource(event); - } - }); - } +// private void initialize3DEventProcessors() { +// addEventProcessor(new EventTypeProcessor<LockResourceEvent>(LockResourceEvent.class) { +// public void handle(LockResourceEvent event) { +// // tell the game window to highlight the appropriate resource +// getGameWindow3D().highlightResource(event); +// } +// }); +// } private void initialize2DEventProcessors() { addEventProcessor(new EventTypeProcessor<BeginChatRoundRequest>(BeginChatRoundRequest.class) { @@ -244,13 +251,7 @@ getGameWindow2D().updateDebriefing(event); } }); - addEventProcessor(new EventTypeProcessor<ClientPositionUpdateEvent>(ClientPositionUpdateEvent.class) { - public void handle(ClientPositionUpdateEvent event) { - if (state == ClientState.RUNNING) { - dataModel.updateDiffs(event, getGameWindow2D()); - } - } - }); + addEventProcessor(new EventTypeProcessor<ClientMessageEvent>(ClientMessageEvent.class) { public void handle(ClientMessageEvent event) { @@ -358,8 +359,8 @@ // moveClient(request); transmit(request); } -// Utils.sleep(100); - Thread.yield(); + Utils.sleep(100); +// Thread.yield(); } } diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/event/ClientPositionUpdateEvent.java --- a/src/main/java/edu/asu/commons/foraging/event/ClientPositionUpdateEvent.java +++ b/src/main/java/edu/asu/commons/foraging/event/ClientPositionUpdateEvent.java @@ -3,18 +3,16 @@ import java.awt.Point; import java.util.Map; import java.util.Queue; -import java.util.Set; import edu.asu.commons.event.AbstractEvent; import edu.asu.commons.foraging.model.ClientData; -import edu.asu.commons.foraging.model.GroupDataModel; import edu.asu.commons.foraging.model.Resource; import edu.asu.commons.net.Identifier; /** - * $Id: ClientPositionUpdateEvent.java 4 2008-07-25 22:51:44Z alllee $ + * $Id$ * * Only contains the differences between rounds since this event is sent quite frequently. * @@ -22,7 +20,7 @@ * * @author Deepali Bhagvat * @author Allen Lee - * @version $Revision: 4 $ + * @version $Revision$ */ public class ClientPositionUpdateEvent extends AbstractEvent { @@ -30,28 +28,24 @@ private final Resource[] addedResources; private final Resource[] removedResources; + // FIXME: merge these two using a Pair private final Map<Identifier, Integer> clientTokens; private final Map<Identifier, Point> clientPositions; private final Queue<RealTimeSanctionRequest> latestSanctions; private final long timeLeft; - public ClientPositionUpdateEvent(ClientData clientData, long timeLeft) { - this(clientData.getId(), clientData.getGroupDataModel(), timeLeft); + public ClientPositionUpdateEvent(ClientData data, Resource[] addedResources, Resource[] removedResources, Map<Identifier, Integer> clientTokens, + Map<Identifier, Point> clientPositions, long timeLeft) { + super(data.getId()); + this.addedResources = addedResources; + this.removedResources = removedResources; + this.clientTokens = clientTokens; + this.clientPositions = clientPositions; + this.timeLeft = timeLeft; + this.latestSanctions = data.getLatestSanctions(); } - public ClientPositionUpdateEvent(Identifier id, GroupDataModel group, long timeLeft) { - super(id); - Set<Resource> addedTokensSet = group.getAddedResources(); - this.addedResources = addedTokensSet.toArray(new Resource[addedTokensSet.size()]); - Set<Resource> removedTokensSet = group.getRemovedResources(); - this.removedResources = removedTokensSet.toArray(new Resource[removedTokensSet.size()]); - this.timeLeft = timeLeft; - this.clientTokens = group.getClientTokens(); - this.clientPositions = group.getClientPositions(); - this.latestSanctions = group.getClientData(id).getLatestSanctions(); - } - public int getCurrentTokens() { return getCurrentTokens( getId() ); } @@ -71,7 +65,7 @@ public Resource[] getRemovedTokens() { return removedResources; } - + public Point getClientPosition() { return getClientPosition(id); } @@ -83,4 +77,12 @@ public long getTimeLeft() { return timeLeft; } + + public Map<Identifier, Point> getClientPositions() { + return clientPositions; + } + + public Map<Identifier, Integer> getClientTokens() { + return clientTokens; + } } diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java --- a/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java +++ b/src/main/java/edu/asu/commons/foraging/facilitator/FacilitatorWindow.java @@ -18,7 +18,6 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; -import javax.swing.ScrollPaneConstants; import javax.swing.text.BadLocationException; import edu.asu.commons.foraging.conf.RoundConfiguration; diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/model/ForagingDataModel.java --- a/src/main/java/edu/asu/commons/foraging/model/ForagingDataModel.java +++ b/src/main/java/edu/asu/commons/foraging/model/ForagingDataModel.java @@ -9,12 +9,12 @@ /** - * $Id: ForagingDataModel.java 4 2008-07-25 22:51:44Z alllee $ The + * $Id$ The * - * Convenience abstract class for storing csan data. + * Base class for the foraging client side and server side data models. * * @author Allen Lee - * @version $Revision: 4 $ + * @version $Revision$ */ public abstract class ForagingDataModel implements DataModel<RoundConfiguration> { @@ -24,6 +24,8 @@ protected transient EventChannel channel; protected transient boolean sanctioningEnabled; protected transient boolean experiment2d; + protected transient int boardWidth; + protected transient int boardHeight; private RoundConfiguration roundConfiguration; @@ -36,28 +38,34 @@ } public int getBoardWidth() { - return roundConfiguration.getResourceWidth(); + return boardWidth; } public int getBoardHeight() { - return roundConfiguration.getResourceDepth(); + return boardHeight; } public RoundConfiguration getRoundConfiguration() { return roundConfiguration; } - // FIXME: considers game world to be flat rectilinear, will need to adapt to - // torus - // (wraparound on vertical edge only) for other experiments. + // FIXME: considers game world to be flat rectilinear, may need to adapt to + // torus (wraparound on vertical edge only) for other experiments. public boolean isValidPosition(Point p) { - return p.x >= 0 && p.x < getBoardWidth() && p.y >= 0 && p.y < getBoardHeight(); + return isValidPosition(p.x, p.y); + } + + public boolean isValidPosition(int x, int y) { + return x >= 0 && x < boardWidth && y >= 0 && y < boardHeight; } public void setRoundConfiguration(RoundConfiguration configuration) { this.roundConfiguration = configuration; sanctioningEnabled = configuration.isSanctioningEnabled(); experiment2d = configuration.is2dExperiment(); + boardHeight = configuration.getResourceDepth(); + boardWidth = configuration.getResourceWidth(); + } public boolean isSanctioningEnabled() { diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/model/ResourceDispenser.java --- a/src/main/java/edu/asu/commons/foraging/model/ResourceDispenser.java +++ b/src/main/java/edu/asu/commons/foraging/model/ResourceDispenser.java @@ -16,14 +16,14 @@ /** - * $Id: ResourceDispenser.java 489 2010-03-10 19:05:12Z alllee $ + * $Id$ * * Creates resource tokens in the game world. Current implementation generates a * resource token probabilistically. The probability that a token will be generated * in an empty space is * P(t) = r * the number of neighboring cells containing a resource token / totalNumberOfNeighboringCells * - * @version $Revision: 489 $ + * @version $Revision$ */ public class ResourceDispenser { @@ -360,7 +360,7 @@ return rate * getNeighborsTokenRatio(group, currentX, currentY); } - protected double getNeighborsTokenRatio(GroupDataModel group, int currentX, int currentY) { + protected double getNeighborsTokenRatio(final GroupDataModel group, final int currentX, final int currentY) { double neighborsWithTokens = 0; // start off at -1 to offset the off-by-one we get from adding the // current cell. diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/server/ForagingServer.java --- a/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java +++ b/src/main/java/edu/asu/commons/foraging/server/ForagingServer.java @@ -1,5 +1,6 @@ package edu.asu.commons.foraging.server; +import java.awt.Point; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; @@ -10,6 +11,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.FileHandler; import java.util.logging.Handler; import java.util.logging.Logger; @@ -68,6 +70,7 @@ import edu.asu.commons.foraging.model.Direction; import edu.asu.commons.foraging.model.EnforcementMechanism; import edu.asu.commons.foraging.model.GroupDataModel; +import edu.asu.commons.foraging.model.Resource; import edu.asu.commons.foraging.model.ResourceDispenser; import edu.asu.commons.foraging.model.ServerDataModel; import edu.asu.commons.foraging.rules.ForagingRule; @@ -312,7 +315,6 @@ sendFacilitatorMessage("Received all quizzes, ready to start round."); Utils.notify(quizSignal); } - } }); addEventProcessor(new EventTypeProcessor<PostRoundSanctionRequest>(PostRoundSanctionRequest.class) { @@ -847,16 +849,23 @@ clientData.collectToken(); } } - - for (ClientData clientData : clients.values()) { - if (shouldSynchronize(clientData.getAssignedNumber())) { - transmit(new SynchronizeClientEvent(clientData, currentRoundDuration.getTimeLeft())); - } - else { - transmit(new ClientPositionUpdateEvent(clientData, currentRoundDuration.getTimeLeft())); + for (GroupDataModel group: serverDataModel.getGroups()) { + Set<Resource> addedTokensSet = group.getAddedResources(); + Resource[] addedResources = addedTokensSet.toArray(new Resource[addedTokensSet.size()]); + Set<Resource> removedTokensSet = group.getRemovedResources(); + Resource[] removedResources = removedTokensSet.toArray(new Resource[removedTokensSet.size()]); + Map<Identifier, Integer> clientTokens = group.getClientTokens(); + Map<Identifier, Point> clientPositions = group.getClientPositions(); + for (ClientData data: group.getClientDataMap().values()) { + if (shouldSynchronize(data.getAssignedNumber())) { + transmit(new SynchronizeClientEvent(data, currentRoundDuration.getTimeLeft())); + } + else { + transmit(new ClientPositionUpdateEvent(data, addedResources, removedResources, clientTokens, clientPositions, currentRoundDuration.getTimeLeft())); + } } } - // send the current ServerGameState to the facilitator + // FIXME: refine this, send basic info to the facilitator (how many resources left, etc.) if (shouldUpdateFacilitator()) { transmit(new FacilitatorUpdateEvent(facilitatorId, serverDataModel, currentRoundDuration.getTimeLeft())); } @@ -866,8 +875,7 @@ } private boolean shouldUpdateFacilitator() { - long startCount = secondTick.getStartCount(); - return (startCount < 3); + return false; } private boolean shouldSynchronize(int assignedNumber) { diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/ui/Circle.java --- a/src/main/java/edu/asu/commons/foraging/ui/Circle.java +++ b/src/main/java/edu/asu/commons/foraging/ui/Circle.java @@ -4,20 +4,18 @@ import java.io.Serializable; /** - * $Id: Circle.java 416 2009-12-25 05:17:14Z alllee $ + * $Id$ * * Simple Circle class given a Point center and radius and providing methods to detect * if a point is within the circle. * * @author <a href='mailto:All...@as...'>Allen Lee</a> - * @version $Revision: 416 $ + * @version $Revision$ */ public class Circle implements Serializable { private static final long serialVersionUID = 6400834001276229287L; - private static final double FUDGE_FACTOR = 0.1d; - private Point center; private final double radius; @@ -30,12 +28,11 @@ if (point == null) { throw new IllegalArgumentException("Null point passed to Circle.contains()"); } - return center.distance(point) <= (radius + FUDGE_FACTOR); + return center.distance(point) <= radius; } public void setCenter(Point center) { this.center = center; } - } diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java --- a/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java +++ b/src/main/java/edu/asu/commons/foraging/ui/GameWindow2D.java @@ -302,31 +302,32 @@ if (dataModel.getRoundConfiguration().shouldDisplayGroupTokens()) { StringBuilder builder = new StringBuilder("Tokens collected:"); // XXX: use this method so that we get the proper ordering of client ids/assigned numbers.. - Map<Identifier, ClientData> clientDataMap = dataModel.getClientDataMap(); +// Map<Identifier, ClientData> clientDataMap = dataModel.getClientDataMap(); Point clientPosition = dataModel.getCurrentPosition(); + // FIXME: refactor this ugliness. for (Identifier id : dataModel.getAllClientIdentifiers()) { - ClientData clientData = clientDataMap.get(id); +// ClientData clientData = clientDataMap.get(id); String formatString = ""; if (id.equals(dataModel.getId())) { formatString = " [%d (you) : %d] "; - builder.append(String.format(formatString, clientData.getAssignedNumber(), clientData.getCurrentTokens())); + builder.append(String.format(formatString, dataModel.getAssignedNumber(id), dataModel.getCurrentTokens(id))); } else { if (!dataModel.getRoundConfiguration().isFieldOfVisionEnabled()) { formatString = " [%d : %d] "; - builder.append(String.format(formatString, clientData.getAssignedNumber(), clientData.getCurrentTokens())); + builder.append(String.format(formatString, dataModel.getAssignedNumber(id), dataModel.getCurrentTokens(id))); } else { double radius = dataModel.getRoundConfiguration().getViewSubjectsRadius(); Circle fieldOfVision = new Circle(clientPosition, radius); - if (fieldOfVision.contains(clientData.getPosition())) { + if (fieldOfVision.contains(dataModel.getClientPosition(id))) { formatString = " [%d : %d] "; - builder.append(String.format(formatString, clientData.getAssignedNumber(), clientData.getCurrentTokens())); + builder.append(String.format(formatString, dataModel.getAssignedNumber(id), dataModel.getCurrentTokens(id))); } else { formatString = " [%d : XX] "; - builder.append(String.format(formatString, clientData.getAssignedNumber())); + builder.append(String.format(formatString, dataModel.getAssignedNumber(id))); } } } @@ -505,7 +506,7 @@ return; } // only allow sanctions for subjects within this subject's field of vision - Point subjectPosition = dataModel.getClientDataMap().get(sanctionee).getPoint(); + Point subjectPosition = dataModel.getClientPosition(sanctionee); if (dataModel.getClientData().isSubjectInFieldOfVision(subjectPosition)) { event = new RealTimeSanctionRequest(dataModel.getId(), sanctionee); System.out.println("sending sanctioning event : " + event); diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/ui/SubjectView.java --- a/src/main/java/edu/asu/commons/foraging/ui/SubjectView.java +++ b/src/main/java/edu/asu/commons/foraging/ui/SubjectView.java @@ -14,7 +14,6 @@ import edu.asu.commons.foraging.client.ClientDataModel; import edu.asu.commons.foraging.conf.RoundConfiguration; -import edu.asu.commons.foraging.model.ClientData; import edu.asu.commons.net.Identifier; import edu.asu.commons.util.Duration; @@ -148,7 +147,6 @@ } protected void paintSubjects(Graphics2D graphics2D) { - Map<Identifier, ClientData> positions = dataModel.getClientDataMap(); graphics2D.setFont(font); FontMetrics fontMetrics = graphics2D.getFontMetrics(font); int characterHeight = fontMetrics.getAscent(); @@ -176,9 +174,9 @@ graphics2D.fill(circle); graphics2D.setPaint(originalPaint); } - for (Map.Entry<Identifier, ClientData> entry : positions.entrySet()) { + for (Map.Entry<Identifier, Point> entry : dataModel.getClientPositions().entrySet()) { Identifier id = entry.getKey(); - Point subjectLocation = entry.getValue().getPosition(); + Point subjectLocation = entry.getValue(); // optimized conditional if (viewSubjectsField == null || id.equals(dataModel.getId()) || viewSubjectsField.contains(subjectLocation)) { // only draw if: @@ -221,9 +219,9 @@ graphics2D.fillRect(x, y, getCellWidth(), getCellHeight()); graphics2D.drawImage(scaledSanctioningImage, x, y, this); } - else if (id.equals(dataModel.getMonitorId())) { - graphics2D.drawImage(scaledMonitorImage, x, y, this); - } +// else if (id.equals(dataModel.getMonitorId())) { +// graphics2D.drawImage(scaledMonitorImage, x, y, this); +// } else if (id.equals(dataModel.getId())) { if (dataModel.isExplicitCollectionMode()) { graphics2D.drawImage(scaledSelfExplicitCollectionModeImage, x, y, this); diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/visualization/conceptual/AbstractView.java --- a/src/main/java/edu/asu/commons/foraging/visualization/conceptual/AbstractView.java +++ b/src/main/java/edu/asu/commons/foraging/visualization/conceptual/AbstractView.java @@ -35,7 +35,6 @@ import edu.asu.commons.foraging.graphics.TextureLoader; import edu.asu.commons.foraging.graphics.Triangulation; import edu.asu.commons.foraging.graphics.Vector3D; -import edu.asu.commons.foraging.model.ClientData; import edu.asu.commons.foraging.model.Resource; import edu.asu.commons.foraging.util.Tuple2i; import edu.asu.commons.foraging.util.Tuple3i; @@ -491,12 +490,12 @@ Agent agent; synchronized (getDataModel()) { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { + for (Identifier id : getDataModel().getAllClientIdentifiers()) { //String textureFile = TEXTURES[clientData.getAssignedNumber() - 1]; - Color color = clientData.getSkinColor(); - agent = new Agent(clientData.getPoint3D(), 0, new RGBA(color), Agent.textureFile, clientData.getAssignedNumber(), this); + Color color = getDataModel().getClientData().getSkinColor(); + agent = new Agent(dataModel.getPoint3D(id), 0, new RGBA(color), Agent.textureFile, dataModel.getAssignedNumber(id), this); // this client is always the first agent in the list. - agents.put(clientData.getId(), agent); + agents.put(id, agent); } } @@ -931,14 +930,14 @@ } public void updateAgentPositions() { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - Identifier id = clientData.getId(); + for (Identifier id : getDataModel().getAllClientIdentifiers()) { if (id.equals(client.getId())) { continue; } Agent agent = agents.get(id); - agent.setPosition(clientData.getPoint3D()); - agent.setHeading(clientData.getHeading()); + agent.setPosition(dataModel.getPoint3D(id)); + // FIXME: unimplemented +// agent.setHeading(dataModel.getHeading(id)); } } @@ -954,8 +953,7 @@ Point labelPosition; //Other clients Identifier selfId = client.getId(); - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - Identifier id = clientData.getId(); + for (Identifier id: getDataModel().getAllClientIdentifiers()) { if (id.equals(selfId)) { // skip ourselves continue; diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/visualization/forestry/shader/ForestryView.java --- a/src/main/java/edu/asu/commons/foraging/visualization/forestry/shader/ForestryView.java +++ b/src/main/java/edu/asu/commons/foraging/visualization/forestry/shader/ForestryView.java @@ -38,7 +38,6 @@ import edu.asu.commons.foraging.graphics.SkyBox; import edu.asu.commons.foraging.graphics.Triangle; import edu.asu.commons.foraging.graphics.Vector3D; -import edu.asu.commons.foraging.model.ClientData; import edu.asu.commons.foraging.model.Resource; import edu.asu.commons.foraging.util.Tuple2f; import edu.asu.commons.foraging.util.Tuple2i; @@ -313,16 +312,16 @@ //Create avatars Woodcutter avatar; synchronized (getDataModel()) { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - int avatarNo = clientData.getAssignedNumber(); -// avatar = loadAvatar(AVATARS[avatarNo - 1], clientData.getPosition(), avatarNo ); -// String avatarFile = clientData.isMale()? AVATAR_FILE_PATH + "maleWoodcutter.cfg": AVATAR_FILE_PATH + "femaleWoodcutter.cfg"; - String avatarFile = AVATAR_FILE; - avatar = loadAvatar(avatarFile, clientData.getHairColor(), clientData.getSkinColor(), - clientData.getShirtColor(), clientData.getTrouserColor(), clientData.getShoesColor(), - clientData.getPoint3D(), avatarNo); - avatars.put(clientData.getId(), avatar); - } +// for (ClientData clientData : getDataModel().getClientDataMap().values()) { +// int avatarNo = clientData.getAssignedNumber(); +//// avatar = loadAvatar(AVATARS[avatarNo - 1], clientData.getPosition(), avatarNo ); +//// String avatarFile = clientData.isMale()? AVATAR_FILE_PATH + "maleWoodcutter.cfg": AVATAR_FILE_PATH + "femaleWoodcutter.cfg"; +// String avatarFile = AVATAR_FILE; +// avatar = loadAvatar(avatarFile, clientData.getHairColor(), clientData.getSkinColor(), +// clientData.getShirtColor(), clientData.getTrouserColor(), clientData.getShoesColor(), +// clientData.getPoint3D(), avatarNo); +// avatars.put(clientData.getId(), avatar); +// } } avatar = avatars.get(client.getId()); setCamera(avatar); @@ -554,30 +553,30 @@ //Added this line as each tree was getting added twice as it is present in //the resourceDistribution as well as addedResources list // FIXME: figure out how this is being used. - getDataModel().clearDiffLists(); +// getDataModel().clearDiffLists(); repaint(); } @Override public void updateResources() { - for (Resource resource: getDataModel().getRemovedResources()) { - Tree tree = (Tree) treeGrid.getNode(resource.getPosition()); - if (! tree.harvested) { - treeGrid.remove(resource.getPosition()); - } - } - for (Resource resource: getDataModel().getAddedResources()) { - addTree(resource); - //System.out.println("A new tree added"); - } - for (Resource resource : getDataModel().getResourceDistribution().values()) { - Tree tree = (Tree) treeGrid.getNode(resource.getPosition()); - if (!tree.isHarvested() && tree.getAge() != resource.getAge()) { - tree.setAge(resource.getAge()); - } - } - getDataModel().clearDiffLists(); +// for (Resource resource: getDataModel().getRemovedResources()) { +// Tree tree = (Tree) treeGrid.getNode(resource.getPosition()); +// if (! tree.harvested) { +// treeGrid.remove(resource.getPosition()); +// } +// } +// for (Resource resource: getDataModel().getAddedResources()) { +// addTree(resource); +// //System.out.println("A new tree added"); +// } +// for (Resource resource : getDataModel().getResourceDistribution().values()) { +// Tree tree = (Tree) treeGrid.getNode(resource.getPosition()); +// if (!tree.isHarvested() && tree.getAge() != resource.getAge()) { +// tree.setAge(resource.getAge()); +// } +// } +// getDataModel().clearDiffLists(); } private void addTree(Resource resource) { @@ -670,17 +669,17 @@ } public void updateAgentPositions() { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - Identifier id = clientData.getId(); - if (id.equals(client.getId())) { - continue; - } - Woodcutter avatar = avatars.get(id); - avatar.setPosition(clientData.getPoint3D()); - avatar.setHeading(clientData.getHeading()); - if (clientData.isAnimationActive()) - avatar.animate( clientData.getAnimationState() ); - } +// for (ClientData clientData : getDataModel().getClientDataMap().values()) { +// Identifier id = clientData.getId(); +// if (id.equals(client.getId())) { +// continue; +// } +// Woodcutter avatar = avatars.get(id); +// avatar.setPosition(clientData.getPoint3D()); +// avatar.setHeading(clientData.getHeading()); +// if (clientData.isAnimationActive()) +// avatar.animate( clientData.getAnimationState() ); +// } } //################### Avatar picking related functions ##################### diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/visualization/forestry/shader/TestView.java --- a/src/main/java/edu/asu/commons/foraging/visualization/forestry/shader/TestView.java +++ b/src/main/java/edu/asu/commons/foraging/visualization/forestry/shader/TestView.java @@ -141,7 +141,7 @@ } //Added this line as each tree was getting added twice as it is present in //the resourceDistribution as well as addedResources list - getDataModel().clearDiffLists(); +// getDataModel().clearDiffLists(); } @Override @@ -230,7 +230,7 @@ if (treeCount == nTrees) break; } - getDataModel().clearDiffLists(); +// getDataModel().clearDiffLists(); } diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/visualization/forestry/va/ForestryView.java --- a/src/main/java/edu/asu/commons/foraging/visualization/forestry/va/ForestryView.java +++ b/src/main/java/edu/asu/commons/foraging/visualization/forestry/va/ForestryView.java @@ -430,13 +430,13 @@ //Create avatars Woodcutter avatar; synchronized (getDataModel()) { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - int avatarNo = clientData.getAssignedNumber(); - avatar = loadAvatar(AVATAR_FILE, clientData.getHairColor(), clientData.getSkinColor(), - clientData.getShirtColor(), clientData.getTrouserColor(), clientData.getShoesColor(), - clientData.getPoint3D(), avatarNo); - avatars.put(clientData.getId(), avatar); - } +// for (ClientData clientData : getDataModel().getClientDataMap().values()) { +// int avatarNo = clientData.getAssignedNumber(); +// avatar = loadAvatar(AVATAR_FILE, clientData.getHairColor(), clientData.getSkinColor(), +// clientData.getShirtColor(), clientData.getTrouserColor(), clientData.getShoesColor(), +// clientData.getPoint3D(), avatarNo); +// avatars.put(clientData.getId(), avatar); +// } } avatar = avatars.get(client.getId()); setCamera(avatar); @@ -711,17 +711,17 @@ * Updates avatar positions, headings and animation states according to the information sent by the server */ public void updateAgentPositions() { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - Identifier id = clientData.getId(); - if (id.equals(client.getId())) { - continue; - } - Woodcutter avatar = avatars.get(id); - avatar.setPosition(clientData.getPoint3D()); - avatar.setHeading(clientData.getHeading()); - if (clientData.isAnimationActive()) - avatar.animate( clientData.getAnimationState() ); - } +// for (ClientData clientData : getDataModel().getClientDataMap().values()) { +// Identifier id = clientData.getId(); +// if (id.equals(client.getId())) { +// continue; +// } +// Woodcutter avatar = avatars.get(id); +// avatar.setPosition(clientData.getPoint3D()); +// avatar.setHeading(clientData.getHeading()); +// if (clientData.isAnimationActive()) +// avatar.animate( clientData.getAnimationState() ); +// } } //################### Avatar picking related functions ##################### diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/visualization/forestry/va/TestView.java --- a/src/main/java/edu/asu/commons/foraging/visualization/forestry/va/TestView.java +++ b/src/main/java/edu/asu/commons/foraging/visualization/forestry/va/TestView.java @@ -20,7 +20,7 @@ /** * The TestView class is used to test the trees created in this package. * @author <a href='dee...@as...'>Deepali Bhagvat</a> - * @version $Revision: 4 $ + * @version $Revision$ * */ public class TestView extends GameView3d { @@ -69,7 +69,7 @@ } //Added this line as each tree was getting added twice as it is present in //the resourceDistribution as well as addedResources list - getDataModel().clearDiffLists(); +// getDataModel().clearDiffLists(); } /** @@ -135,7 +135,7 @@ if (treeCount == nTrees) break; } - getDataModel().clearDiffLists(); +// getDataModel().clearDiffLists(); } diff -r 80094b4190373fe4b978f246cf97d86f106f26f1 -r a1fbd4dbf9289edc81730ecd5d859d58ec46fec2 src/main/java/edu/asu/commons/foraging/visualization/forestry/vbo/ForestryView.java --- a/src/main/java/edu/asu/commons/foraging/visualization/forestry/vbo/ForestryView.java +++ b/src/main/java/edu/asu/commons/foraging/visualization/forestry/vbo/ForestryView.java @@ -311,16 +311,16 @@ //Create avatars Woodcutter avatar; synchronized (getDataModel()) { - for (ClientData clientData : getDataModel().getClientDataMap().values()) { - int avatarNo = clientData.getAssignedNumber(); -// avatar = loadAvatar(AVATARS[avatarNo - 1], clientData.getPosition(), avatarNo ); -// String avatarFile = clientData.isMale()? AVATAR_FILE_PATH + "maleWoodcutter.cfg": AVATAR_FILE_PATH + "femaleWoodcutter.cfg"; - String avatarFile = AVATAR_FILE; - avatar = loadAvatar(avatarFile, clientData.getHairColor(), clientData.getSkinColor(), - clientData.getShirtColor(), clientData.getTrouserColor(), clientData.getShoesColor(), - clientData.getPoint3D(), avatarNo); - avatars.put(clientData.getId(), avatar); - } +// for (ClientData clientData : getDataModel().getClientDataMap().values()) { +// int avatarNo = clientData.getAssignedNumber(); +//// avatar = loadAvatar(AVATARS[avatarNo - 1], clientData.getPosition(), avatarNo ); +//// String avatarFile = clientData.isMale()? AVATAR_FILE_PATH + "maleWoodcutter.cfg": AVATAR_FILE_PATH + "femaleWoodcutter.cfg"; +// String avatarFile = AVATAR_FILE; +// avatar = loadAvatar(avatarFile, clientData.getHairColor(), clientData.getSkinColor(), +// clientData.getShirtColor(), clientData.getTrouserColor(), clientData.getShoesColor(), +// clientData.getPoint3D(), avatarNo); +// avatars.put(clientData.getId(), avatar); +// } } avatar = avatars.get(client.getId()); setCamera(avatar); @@ -551,30 +551,30 @@ } //Added this line as each tree was getting added twice as it is present in //the resourceDistribution as well as addedResources list - getDataModel().clearDiffLists(); +// getDataModel().clearDiffLists(); repaint(); } @Override public void updateResources() { - for (Resource resource: getDataModel().getRemovedResources()) { - Tree tree = (Tree) treeGrid.getNode(resource.getPosition()); - if (! tree.harvested) { - treeGrid.remove(resource.getPosition()); - } - } - for (Resource resource... [truncated message content] |