[virtualcommons-svn] SF.net SVN: virtualcommons:[71] foraging/trunk/src/main/java/edu/asu/ commons/
Status: Beta
Brought to you by:
alllee
From: <al...@us...> - 2009-01-02 23:06:36
|
Revision: 71 http://virtualcommons.svn.sourceforge.net/virtualcommons/?rev=71&view=rev Author: alllee Date: 2009-01-02 23:06:31 +0000 (Fri, 02 Jan 2009) Log Message: ----------- adding movement statistics processor to save file conversion to generate movement distribution (distribution of how often player X moves in the same direction) Modified Paths: -------------- foraging/trunk/src/main/java/edu/asu/commons/foraging/model/GroupDataModel.java foraging/trunk/src/main/java/edu/asu/commons/foraging/util/ForagingSaveFileConverter.java Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/model/GroupDataModel.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/model/GroupDataModel.java 2008-12-20 00:01:02 UTC (rev 70) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/model/GroupDataModel.java 2009-01-02 23:06:31 UTC (rev 71) @@ -44,8 +44,8 @@ private final Map<Point, Resource> resourceDistribution = new HashMap<Point, Resource>(); private final transient Map<Identifier, Resource> resourceOwners = new HashMap<Identifier, Resource>(); - private final transient Set<Resource> removedResources; - private final transient Set<Resource> addedResources; + private transient Set<Resource> removedResources; + private transient Set<Resource> addedResources; private transient ServerDataModel serverDataModel; @@ -92,7 +92,7 @@ for (ClientData clientState : clients.values()) { clientState.reset(); } - removedResources.addAll(resourceDistribution.values()); + getRemovedResources().addAll(resourceDistribution.values()); addedResources.clear(); resourceDistribution.clear(); } @@ -116,14 +116,14 @@ public void addResource(Resource resource) { Point position = resource.getPosition(); resourceDistribution.put(position, resource); - addedResources.add(resource); + getAddedResources().add(resource); } public void addResources(Set<Resource> resources) { for (Resource resource: resources) { Point position = resource.getPosition(); resourceDistribution.put(position, resource); - addedResources.add(resource); + getAddedResources().add(resource); } } @@ -232,7 +232,7 @@ public void collectToken(ClientData clientData) { Point position = clientData.getPoint(); if (resourceDistribution.containsKey(position)) { - removedResources.add( resourceDistribution.remove(position) ); + getRemovedResources().add( resourceDistribution.remove(position) ); clientData.addToken(); serverDataModel.getEventChannel().handle(new TokenCollectedEvent(clientData.getId(), position)); } @@ -309,12 +309,11 @@ ClientData clientData = clients.get(id); clientData.addTokens( getRoundConfiguration().calculateTokens(resource.getAge()) ); Point position = resource.getPosition(); - removedResources.add(resourceDistribution.remove(position)); + getRemovedResources().add(resourceDistribution.remove(position)); resourceOwners.remove(id); } } - //TODO: Add # tokens and/or dollars per token for fruits public void harvestFruits(Identifier id, Resource resource) { if ( isResourceOwner(id, resource) ) { ClientData clientData = clients.get(id); @@ -414,10 +413,16 @@ public Set<Resource> getRemovedResources() { + if (removedResources == null) { + removedResources = new HashSet<Resource>(); + } return removedResources; } public Set<Resource> getAddedResources() { + if (addedResources == null) { + addedResources = new HashSet<Resource>(); + } return addedResources; } Modified: foraging/trunk/src/main/java/edu/asu/commons/foraging/util/ForagingSaveFileConverter.java =================================================================== --- foraging/trunk/src/main/java/edu/asu/commons/foraging/util/ForagingSaveFileConverter.java 2008-12-20 00:01:02 UTC (rev 70) +++ foraging/trunk/src/main/java/edu/asu/commons/foraging/util/ForagingSaveFileConverter.java 2009-01-02 23:06:31 UTC (rev 71) @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ import edu.asu.commons.foraging.event.ResourcesAddedEvent; import edu.asu.commons.foraging.event.TokenCollectedEvent; import edu.asu.commons.foraging.model.ClientData; +import edu.asu.commons.foraging.model.Direction; import edu.asu.commons.foraging.model.GroupDataModel; import edu.asu.commons.foraging.model.Resource; import edu.asu.commons.foraging.model.ResourceDispenser; @@ -45,7 +47,8 @@ processors.addAll(Arrays.asList( new AllDataProcessor(), new AggregateTimeIntervalProcessor(), - new SummaryProcessor())); + new SummaryProcessor(), + new MovementStatisticsProcessor())); Persister.processSaveFiles(allSaveFilesDirectory, processors); return true; } @@ -60,6 +63,137 @@ convert(args[0]); } + private static class MovementStatisticsProcessor extends SaveFileProcessor.Base { + private Map<Identifier, ClientMovementStatistics> clientStatisticsMap = new LinkedHashMap<Identifier, ClientMovementStatistics>(); + private Map<GroupDataModel, Integer> resourceCountMap = new HashMap<GroupDataModel, Integer>(); + + @Override + public void process(SavedRoundData savedRoundData, PrintWriter writer) { + ServerDataModel serverDataModel = (ServerDataModel) savedRoundData.getDataModel(); + for (GroupDataModel group: serverDataModel.getGroups()) { + for (Identifier id: group.getOrderedClientIdentifiers()) { + clientStatisticsMap.put(id, new ClientMovementStatistics(id, (RoundConfiguration) savedRoundData.getRoundParameters())); + } + resourceCountMap.put(group, 0); + } + + for (PersistableEvent event: savedRoundData.getActions()) { + if (event instanceof MovementEvent) { + MovementEvent movementEvent = (MovementEvent) event; + Identifier id = movementEvent.getId(); + GroupDataModel groupDataModel = serverDataModel.getGroup(id); + if (resourceCountMap.get(groupDataModel) > 0) { + clientStatisticsMap.get(id).move(movementEvent.getDirection()); + } + else { + // stop counting for this group. +// System.err.println("Ignoring movement due to 0 resource count " + movementEvent + resourceCountMap); + } + } + else if (event instanceof ResourcesAddedEvent) { + ResourcesAddedEvent resourcesAddedEvent = (ResourcesAddedEvent) event; + GroupDataModel group = resourcesAddedEvent.getGroup(); + int resources = resourceCountMap.get(group); + resources += resourcesAddedEvent.getResources().size(); + resourceCountMap.put(group, resources); + } + else if (event instanceof TokenCollectedEvent) { + TokenCollectedEvent tokenCollectedEvent = (TokenCollectedEvent) event; + Identifier id = tokenCollectedEvent.getId(); + GroupDataModel groupDataModel = serverDataModel.getGroup(id); + int resources = resourceCountMap.get(groupDataModel); + resourceCountMap.put(groupDataModel, resources - 1); + } + } + // tally their very last movement counts + // (since ClientMovementStatistics only adds to the movement distribution when they change direction) + for (ClientMovementStatistics summary: clientStatisticsMap.values()) { + summary.incrementMovementDistribution(); + } + int maximumMoves = Math.max(serverDataModel.getBoardHeight(), serverDataModel.getBoardWidth()); + final Integer[] movementHeader = new Integer[maximumMoves]; + for (int iotaIndex = 0; iotaIndex < maximumMoves; iotaIndex++) { + movementHeader[iotaIndex] = iotaIndex + 1; + } + + // write out the header line. + writer.println(Utils.join(',', "Identifier", Utils.join(',', Arrays.asList(movementHeader)))); + + // and then write out each Identifier's movement distribution. + for (Map.Entry<Identifier, ClientMovementStatistics> entry : clientStatisticsMap.entrySet()) { + writer.println(Utils.join(',', entry.getKey(), Utils.join(',', + Arrays.asList(entry.getValue().getMovementDistribution())))); + } + } + + @Override + public String getOutputFileExtension() { + return "-movement-summary-statistics.txt"; + } + + @Override + public void dispose() { + clientStatisticsMap.clear(); + resourceCountMap.clear(); + } + + } + + private static class ClientMovementStatistics { + private final Identifier id; + private Direction lastDirection; + // distribution of moves, each entry in the array represents the number of times they've moved. + private int[] movementDistribution; + private int currentMoveCount = 0; + private int allMoves; + public ClientMovementStatistics(Identifier id, RoundConfiguration configuration) { + this.id = id; + int maximumNumberOfMoves = Math.max(configuration.getBoardSize().height, configuration.getBoardSize().width); + movementDistribution = new int[maximumNumberOfMoves]; + } + public synchronized void move(Direction direction) { + if (direction != null) { + allMoves++; + } + if (lastDirection == null) { + lastDirection = direction; + currentMoveCount = 1; + } + else if (lastDirection.equals(direction)) { + currentMoveCount++; + } + else { + lastDirection = direction; + incrementMovementDistribution(); + } + } + private void incrementMovementDistribution() { + int movementDistributionIndex = Math.min(currentMoveCount, movementDistribution.length-1); + if (movementDistributionIndex > 0) { + movementDistribution[movementDistributionIndex-1]++; + } + currentMoveCount = 1; + } + public Integer[] getMovementDistribution() { +// return Arrays.copyOf(movementDistribution, movementDistribution.length); + Integer[] rv = new Integer[movementDistribution.length]; + for (int i = 0; i < movementDistribution.length; i++) { + rv[i] = Integer.valueOf(movementDistribution[i]); + } + return rv; + } + public void validate() { + int sum = 0; + for (int i = 0; i < movementDistribution.length; i++) { + sum += ((i+1) * movementDistribution[i]); + } + if (allMoves != sum) { + throw new RuntimeException("Identifier id: " + id + " -- allMoves: " + allMoves + " not equal to sum of all moves: " + sum); + } + } + + } + private static class SummaryProcessor extends SaveFileProcessor.Base { @Override public void process(SavedRoundData savedRoundData, PrintWriter writer) { @@ -319,11 +453,11 @@ // accumulated stats if (secondsElapsed >= endOfInterval) { // generate group expected token counts -// List<Double> expectedTokenProbabilities = getExpectedTokenProbabilities(gameState); + List<Double> expectedTokenProbabilities = getExpectedTokenProbabilities(serverDataModel); // report summary stats and reset List<Integer> movesTaken = new ArrayList<Integer>(); List<Integer> harvestedTokens = new ArrayList<Integer>(); -// List<Integer> tokensLeft = getTokensLeft(groups); + List<Integer> tokensLeft = getTokensLeft(groups); List<Double> distances = getClientDistances(groups); for (Identifier id : orderedIdentifiers) { ClientStats stats = clientStatistics.get(id); @@ -335,9 +469,10 @@ Utils.join(',', endOfInterval, Utils.join(',', movesTaken), Utils.join(',', harvestedTokens), + Utils.join(',', expectedTokenProbabilities), + Utils.join(',', tokensLeft), Utils.join(',', distances) ); -// System.err.println("dataline: " + dataline); writer.println(dataline); currentInterval++; } @@ -369,18 +504,16 @@ stats.tokens += roundConfiguration.calculateTokens(request.getResource().getAge()); } else if (event instanceof ResourceAddedEvent) { -// ResourceAddedEvent resourceAddedEvent = (ResourceAddedEvent) event; -// assert serverDataModel.getGroups().contains(resourceAddedEvent.getGroup()); -// resourceAddedEvent.getGroup().addResource(resourceAddedEvent.getPosition()); + ResourceAddedEvent resourceAddedEvent = (ResourceAddedEvent) event; + assert serverDataModel.getGroups().contains(resourceAddedEvent.getGroup()); + resourceAddedEvent.getGroup().addResource(resourceAddedEvent.getPosition()); } else if (event instanceof ResourcesAddedEvent) { -// ResourcesAddedEvent resourcesAddedEvent = (ResourcesAddedEvent) event; -// assert serverDataModel.getGroups().contains(resourcesAddedEvent.getGroup()); -// resourcesAddedEvent.getGroup().addResources(resourcesAddedEvent.getResources()); + ResourcesAddedEvent resourcesAddedEvent = (ResourcesAddedEvent) event; + assert serverDataModel.getGroups().contains(resourcesAddedEvent.getGroup()); + resourcesAddedEvent.getGroup().addResources(resourcesAddedEvent.getResources()); } } - writer.flush(); - writer.close(); } private List<Double> getClientDistances(List<GroupDataModel> groups) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |