From: Stefan F. <ste...@us...> - 2010-05-14 15:20:06
|
Update of /cvsroot/rails/18xx/rails/algorithms In directory sfp-cvsdas-4.v30.ch3.sourceforge.com:/tmp/cvs-serv8794/rails/algorithms Modified Files: NetworkTrain.java RevenueAdapter.java RevenueBonus.java RevenueBonusTemplate.java NetworkGraphBuilder.java RevenueCalculator.java Added Files: RevenueTrainRun.java Log Message: Updated and refactored revenue calculation, added support for 1835 Index: RevenueCalculator.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/RevenueCalculator.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** RevenueCalculator.java 12 May 2010 18:50:26 -0000 1.12 --- RevenueCalculator.java 14 May 2010 15:19:57 -0000 1.13 *************** *** 10,13 **** --- 10,14 ---- private final int nbTrains; private final int nbEdges; + private final int nbBonuses; // static vertex data *************** *** 17,24 **** private final int[] vertexNbNeighbors; private final int[] vertexNbVisitSets; private final int[][] vertexNeighbors; private final int[][] vertexEdges; ! private final int[][] vertexVisitSets; // start vertexes --- 18,27 ---- private final int[] vertexNbNeighbors; private final int[] vertexNbVisitSets; + private final int[] vertexNbBonusSets; private final int[][] vertexNeighbors; private final int[][] vertexEdges; ! private final int[][] vertexVisitSets; // vertex belongs to a visit set, dimension: nbVertex x maxBlocks ! private final int[][] vertexBonusSets; // vertex belongs to a bonus set, dimension: nbVertex x nbBonuses // start vertexes *************** *** 48,52 **** --- 51,65 ---- private final int [] trainStartEdge; + // static bonus data + private final int [] bonusValue; + private final boolean [][] bonusActiveForTrain; // dimensions: bonus x train + private final int [] bonusRequiresVertices; + + // dynamic bonus data + private final int [][] bonusTrainVertices; + // run settings + private int startTrainSet; + private int finalTrainSet; private int startTrain; private int finalTrain; *************** *** 85,99 **** ! public RevenueCalculator (RevenueAdapter revenueAdapter, int nbVertexes, int nbEdges, int maxNeighbors, int maxBlocks, int nbTrains) { log.info("RC defined: nbVertexes = " + nbVertexes + ", nbEdges = " + nbEdges + ", maxNeighbors = " + maxNeighbors + ! ", maxBlocks = " + maxBlocks + ", nbTrains = " + nbTrains); this.revenueAdapter = revenueAdapter; this.nbVertexes = nbVertexes; this.nbEdges = nbEdges; - this.nbTrains = nbTrains; ! // initialize all required variables --- 98,112 ---- ! public RevenueCalculator (RevenueAdapter revenueAdapter, int nbVertexes, int nbEdges, ! int maxNeighbors, int maxVertexSets, int nbTrains, int nbBonuses) { log.info("RC defined: nbVertexes = " + nbVertexes + ", nbEdges = " + nbEdges + ", maxNeighbors = " + maxNeighbors + ! ", maxVertexSets = " + maxVertexSets + ", nbTrains = " + nbTrains + ", nbBonuses = " + nbBonuses ); this.revenueAdapter = revenueAdapter; this.nbVertexes = nbVertexes; this.nbEdges = nbEdges; this.nbTrains = nbTrains; ! this.nbBonuses = nbBonuses; // initialize all required variables *************** *** 103,109 **** vertexNbNeighbors = new int[nbVertexes]; vertexNbVisitSets = new int[nbVertexes]; vertexNeighbors = new int[nbVertexes][maxNeighbors]; vertexEdges = new int[nbVertexes][maxNeighbors]; ! vertexVisitSets = new int[nbVertexes][maxBlocks]; edgeGreedy = new boolean[nbEdges]; --- 116,124 ---- vertexNbNeighbors = new int[nbVertexes]; vertexNbVisitSets = new int[nbVertexes]; + vertexNbBonusSets = new int[nbVertexes]; vertexNeighbors = new int[nbVertexes][maxNeighbors]; vertexEdges = new int[nbVertexes][maxNeighbors]; ! vertexVisitSets = new int[nbVertexes][maxVertexSets]; ! vertexBonusSets = new int[nbVertexes][nbBonuses]; edgeGreedy = new boolean[nbEdges]; *************** *** 119,129 **** trainMinors = new int[nbTrains]; trainVisited = new boolean[nbTrains][nbVertexes]; ! trainVertexStack = new int[nbTrains][nbVertexes]; ! trainEdgeStack = new int[nbTrains][nbVertexes]; trainStackPos = new int[nbTrains]; trainBottomPos = new int[nbTrains]; trainStartEdge = new int[nbTrains]; ! currentBestRun = new int[nbTrains][nbVertexes]; useRevenuePrediction = false; --- 134,150 ---- trainMinors = new int[nbTrains]; trainVisited = new boolean[nbTrains][nbVertexes]; ! trainVertexStack = new int[nbTrains][nbVertexes + 1]; ! // increase necessary due to buttom train ! trainEdgeStack = new int[nbTrains][nbVertexes + 1]; trainStackPos = new int[nbTrains]; trainBottomPos = new int[nbTrains]; trainStartEdge = new int[nbTrains]; ! bonusValue = new int[nbBonuses]; ! bonusRequiresVertices = new int[nbBonuses]; ! bonusActiveForTrain = new boolean[nbBonuses][nbTrains]; ! bonusTrainVertices = new int[nbBonuses][nbTrains]; ! ! currentBestRun = new int[nbTrains][nbVertexes + 1]; useRevenuePrediction = false; *************** *** 133,139 **** vertexMajor[id] = major; vertexMinor[id] = minor; ! // default neighbors && blocks vertexNbNeighbors[id] = 0; vertexNbVisitSets[id] = 0; } --- 154,161 ---- vertexMajor[id] = major; vertexMinor[id] = minor; ! // default neighbors && visit and bonus sets vertexNbNeighbors[id] = 0; vertexNbVisitSets[id] = 0; + vertexNbBonusSets[id] = 0; } *************** *** 151,163 **** } ! ! void setVertexVisitSets(int id, int[] blocks) { ! // copy blocks ! for (int j=0; j < blocks.length; j++) { ! vertexVisitSets[id][j] = blocks[j]; ! } ! vertexNbVisitSets[id] = blocks.length; ! } ! void setStartVertexes(int[] startVertexes) { this.startVertexes = startVertexes; --- 173,177 ---- } ! void setStartVertexes(int[] startVertexes) { this.startVertexes = startVertexes; *************** *** 176,179 **** --- 190,216 ---- } + void setVisitSet(int[] vertices) { + for (int j=0; j < vertices.length; j++) { + int vertexId = vertices[j]; + for (int k=0; k < vertices.length; k++) { + if (k == j) continue; + vertexVisitSets[vertexId][vertexNbVisitSets[vertexId]++] = vertices[k]; + } + } + } + + void setBonus(int id, int value, int[] vertices, boolean[] bonusForTrain) { + log.info("RC: define bonus value = " + value + ", vertices = " + Arrays.toString(vertices) + + ", bonusForTrain = " + Arrays.toString(bonusForTrain)); + + bonusValue[id] = value; + bonusRequiresVertices[id] = vertices.length; + for (int j=0; j < vertices.length; j++) { + int vertexId = vertices[j]; + vertexBonusSets[vertexId][vertexNbBonusSets[vertexId]++] = id; + } + bonusActiveForTrain[id] = bonusForTrain; + } + int[][] getOptimalRun() { log.info("RC: currentBestRun = " + Arrays.deepToString(currentBestRun)); *************** *** 244,250 **** if (startTrain > finalTrain) return; ! useRevenuePrediction = true; this.maxCumulatedTrainRevenues = new int[nbTrains]; initRevenueValues(startTrain, finalTrain); --- 281,293 ---- if (startTrain > finalTrain) return; ! ! this.startTrainSet = startTrain; ! this.finalTrainSet = finalTrain; useRevenuePrediction = true; this.maxCumulatedTrainRevenues = new int[nbTrains]; + for (int i=0; i < nbTrains; i++) { + currentBestRun[i][0] = -1; + } + initRevenueValues(startTrain, finalTrain); *************** *** 255,261 **** log.info("RC: start individual prediction Runs"); - int cumulatedRevenues = 0; int[] maxSingleTrainRevenues = new int[nbTrains]; ! for (int j=finalTrain; j >= startTrain; j--) { this.startTrain = j; this.finalTrain = j; --- 298,303 ---- log.info("RC: start individual prediction Runs"); int[] maxSingleTrainRevenues = new int[nbTrains]; ! for (int j = startTrain; j <= finalTrain; j++) { this.startTrain = j; this.finalTrain = j; *************** *** 265,273 **** " after " + getStatistics()); maxSingleTrainRevenues[j] = currentBestValue; ! cumulatedRevenues += currentBestValue; maxCumulatedTrainRevenues[j] = cumulatedRevenues; } ! if (startTrain == finalTrain-1) return; log.info("RC: start combined prediction runs"); --- 307,318 ---- " after " + getStatistics()); maxSingleTrainRevenues[j] = currentBestValue; ! } ! int cumulatedRevenues = 0; ! for (int j = finalTrain; j >= startTrain; j--) { ! cumulatedRevenues += maxSingleTrainRevenues[j]; maxCumulatedTrainRevenues[j] = cumulatedRevenues; } ! if (startTrain == finalTrain - 1) return; log.info("RC: start combined prediction runs"); *************** *** 275,279 **** for (int j=finalTrain - 1; j > startTrain; j--) { this.startTrain = j; ! currentBestValue = 0; runTrain(j); log.info("RC: Best prediction run until train nb. " + j + " value = " + currentBestValue + --- 320,324 ---- for (int j=finalTrain - 1; j > startTrain; j--) { this.startTrain = j; ! // currentBestValue = 0; runTrain(j); log.info("RC: Best prediction run until train nb. " + j + " value = " + currentBestValue + *************** *** 287,293 **** log.info("RC: calculateRevenue trains from " + startTrain + " to " + finalTrain); this.startTrain = startTrain; ! this.finalTrain = finalTrain; ! currentBestValue = 0; runTrain(startTrain); --- 332,346 ---- log.info("RC: calculateRevenue trains from " + startTrain + " to " + finalTrain); + if (!useRevenuePrediction) { + for (int i=0; i < nbTrains; i++) { + currentBestRun[i][0] = -1; + } + } + + this.startTrainSet = startTrain; + this.finalTrainSet = finalTrain; + this.startTrain = startTrain; ! this.finalTrainSet = finalTrain; runTrain(startTrain); *************** *** 302,309 **** log.debug("RC: runTrain " + trainId); ! // intialize value trainCurrentValue[trainId] = 0; ! // initialize lengths trainMajors[trainId] = trainMaxMajors[trainId]; trainMinors[trainId] = trainMaxMinors[trainId]; --- 355,362 ---- log.debug("RC: runTrain " + trainId); ! // initialize value trainCurrentValue[trainId] = 0; ! // initialize train lengths trainMajors[trainId] = trainMaxMajors[trainId]; trainMinors[trainId] = trainMaxMinors[trainId]; *************** *** 313,316 **** --- 366,374 ---- trainBottomPos[trainId] = 0; + // initialize bonuses + for (int b=0; b < nbBonuses; b++) { + bonusTrainVertices[b][trainId] = bonusRequiresVertices[b]; + } + // check if the revenue is enough if (useRevenuePrediction && predictRevenues(trainId)) *************** *** 336,342 **** // then try all edges of it for (int j = 0; j < vertexNbNeighbors[vertexId]; j++) { - int neighborId = vertexNeighbors[vertexId][j]; - log.debug("RC: Testing Neighbor Nr. " + j + " of startVertex is " + neighborId); int edgeId = vertexEdges[vertexId][j]; if (travelEdge(trainId, edgeId, true)) { trainStartEdge[trainId] = j; // store start edge --- 394,405 ---- // then try all edges of it for (int j = 0; j < vertexNbNeighbors[vertexId]; j++) { int edgeId = vertexEdges[vertexId][j]; + if (edgeUsed[edgeId]) continue; + log.debug("RC: Testing Neighbor Nr. " + j + " of startVertex"); + int neighborId = vertexNeighbors[vertexId][j]; + if (trainVisited[trainId][neighborId]) { + log.debug("RC: Hex already visited"); + continue; + } if (travelEdge(trainId, edgeId, true)) { trainStartEdge[trainId] = j; // store start edge *************** *** 375,378 **** --- 438,443 ---- for (int j = trainStartEdge[trainId] + 1; j < vertexNbNeighbors[vertexId]; j++) { + int edgeId = vertexEdges[vertexId][j]; + if (edgeUsed[edgeId]) continue; int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of bottomVertex is " + neighborId); *************** *** 381,385 **** continue; } - int edgeId = vertexEdges[vertexId][j]; if (travelEdge(trainId, edgeId, true)) { nextVertex(trainId, neighborId, edgeGreedy[edgeId]); --- 446,449 ---- *************** *** 415,418 **** --- 479,484 ---- if (trainTerminated == Terminated.NotYet) { for (int j = 0; j < vertexNbNeighbors[vertexId]; j++) { + int edgeId = vertexEdges[vertexId][j]; + if (edgeUsed[edgeId]) continue; int neighborId = vertexNeighbors[vertexId][j]; log.debug("RC: Testing Neighbor Nr. " + j + " of " + vertexId + " is " + neighborId); *************** *** 421,425 **** continue; } - int edgeId = vertexEdges[vertexId][j]; if (travelEdge(trainId, edgeId, previousGreedy)) { nextVertex(trainId, neighborId, edgeGreedy[edgeId]); --- 487,490 ---- *************** *** 475,481 **** // check vertex sets for (int j=0; j < vertexNbVisitSets[vertexId]; j++) { ! if (vertexVisitSets[vertexId][j] != -1) { ! trainVisited[trainId][vertexVisitSets[vertexId][j]] = arrive; ! log.debug("RC: visited = " + arrive + " for vertex " + vertexVisitSets[vertexId][j] + " due to block rule"); } } --- 540,565 ---- // check vertex sets for (int j=0; j < vertexNbVisitSets[vertexId]; j++) { ! trainVisited[trainId][vertexVisitSets[vertexId][j]] = arrive; ! log.info("RC: visited = " + arrive + " for vertex " + vertexVisitSets[vertexId][j] + " due to block rule"); ! } ! ! // check bonus sets ! for (int j=0; j < vertexNbBonusSets[vertexId]; j++) { ! int bonusId = vertexBonusSets[vertexId][j]; ! if (!bonusActiveForTrain[bonusId][trainId]) continue; ! if (arrive) { ! bonusTrainVertices[bonusId][trainId]--; ! log.debug("RC: Decreased bonus " + bonusId + " to " + bonusTrainVertices[bonusId][trainId]); ! if (bonusTrainVertices[bonusId][trainId] == 0) { ! trainCurrentValue[trainId] += bonusValue[bonusId]; ! log.debug("RC: Added bonus " + bonusId + " with value " + bonusValue[bonusId]); ! } ! } else { ! if (bonusTrainVertices[bonusId][trainId] == 0) { ! trainCurrentValue[trainId] -= bonusValue[bonusId]; ! log.debug("RC: Removed bonus " + bonusId + " with value " + bonusValue[bonusId]); ! } ! bonusTrainVertices[bonusId][trainId]++; ! log.debug("RC: Increases bonus " + bonusId + " to " + bonusTrainVertices[bonusId][trainId]); } } *************** *** 486,493 **** private boolean travelEdge(int trainId, int edgeId, boolean previousGreedy) { ! if (edgeUsed[edgeId]) { ! log.debug("RC: Edge id " + edgeId + " already used" ); ! return false; ! } else if (previousGreedy || edgeGreedy[edgeId]) { log.debug("RC: Travel edge id " + edgeId); edgeUsed[edgeId] = true; --- 570,574 ---- private boolean travelEdge(int trainId, int edgeId, boolean previousGreedy) { ! if (previousGreedy || edgeGreedy[edgeId]) { log.debug("RC: Travel edge id " + edgeId); edgeUsed[edgeId] = true; *************** *** 561,564 **** --- 642,646 ---- for (int j = startTrain; j <= finalTrain; j++) { totalValue += trainCurrentValue[j]; + // check for two stations requirement not necessary if stationVertex approach works // if (trainIgnoreMinors[j]) { // if (trainMaxMajors[j] - trainMajors[j] >= 2) *************** *** 577,582 **** currentBestValue = totalValue; // exceed thus deep copy of vertex stack ! for (int j = 0; j <= finalTrain; j++) { ! for (int v = 0; v < nbVertexes; v++) { if (v < trainStackPos[j]) { currentBestRun[j][v] = trainVertexStack[j][v]; --- 659,664 ---- currentBestValue = totalValue; // exceed thus deep copy of vertex stack ! for (int j = startTrainSet; j <= finalTrainSet; j++) { ! for (int v = 0; v < nbVertexes + 1; v++) { if (v < trainStackPos[j]) { currentBestRun[j][v] = trainVertexStack[j][v]; *************** *** 622,625 **** --- 704,708 ---- for (int j = startTrain; j < trainId; j++) { totalValue += trainCurrentValue[j]; + // check for two stations requirement not necessary if stationVertex approach works // if (trainIgnoreMinors[j]) { // if (trainMaxMajors[j] - trainMajors[j] >= 2) *************** *** 649,652 **** --- 732,739 ---- buffer.append("vertexNeighbors:" + Arrays.deepToString(vertexNeighbors) + "\n"); buffer.append("vertexEdges:" + Arrays.deepToString(vertexEdges) + "\n"); + buffer.append("vertexVisitSets:" + Arrays.deepToString(vertexVisitSets) + "\n"); + buffer.append("vertexBonusSets:" + Arrays.deepToString(vertexBonusSets) + "\n"); + buffer.append("vertexNbVisitSets:" + Arrays.toString(vertexNbVisitSets) + "\n"); + buffer.append("vertexNbBonusSets:" + Arrays.toString(vertexNbBonusSets) + "\n"); buffer.append("edgeGreedy:" + Arrays.toString(edgeGreedy) + "\n"); buffer.append("edgeDistance:" + Arrays.toString(edgeDistance) + "\n"); Index: RevenueBonusTemplate.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/RevenueBonusTemplate.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RevenueBonusTemplate.java 11 May 2010 21:47:21 -0000 1.1 --- RevenueBonusTemplate.java 14 May 2010 15:19:57 -0000 1.2 *************** *** 28,31 **** --- 28,34 ---- private final int value; + // bonus name + private final String name; + // template condition attributes private final List<Integer> identVertices; *************** *** 37,40 **** --- 40,44 ---- value = tag.getAttributeAsInteger("value"); + name = tag.getAttributeAsString("name"); identVertices = new ArrayList<Integer>(); *************** *** 79,83 **** public RevenueBonus toRevenueBonus(MapHex hex, GameManagerI gm, NetworkGraphBuilder ngb) { log.info("Convert " + this); ! RevenueBonus bonus = new RevenueBonus(value); if (!convertVertices(bonus, ngb, hex)) { log.info("Not all vertices found"); --- 83,87 ---- public RevenueBonus toRevenueBonus(MapHex hex, GameManagerI gm, NetworkGraphBuilder ngb) { log.info("Convert " + this); ! RevenueBonus bonus = new RevenueBonus(value, name); if (!convertVertices(bonus, ngb, hex)) { log.info("Not all vertices found"); *************** *** 121,125 **** public String toString() { StringBuffer s = new StringBuffer(); ! s.append("RevenueBonusTemplate with value " + value); s.append(", identVertices = " + identVertices); s.append(", identTrainTypes = " + identTrainTypes); --- 125,134 ---- public String toString() { StringBuffer s = new StringBuffer(); ! s.append("RevenueBonusTemplate"); ! if (name == null) ! s.append (" unnamed"); ! else ! s.append(" name = " + name); ! s.append(", value " + value); s.append(", identVertices = " + identVertices); s.append(", identTrainTypes = " + identTrainTypes); Index: RevenueBonus.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/RevenueBonus.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RevenueBonus.java 11 May 2010 21:47:21 -0000 1.1 --- RevenueBonus.java 14 May 2010 15:19:57 -0000 1.2 *************** *** 17,20 **** --- 17,23 ---- private final int value; + // bonus name, also identifies mutually exclusive bonuses + private final String name; + // internal attributes private List<NetworkVertex> vertices; *************** *** 22,27 **** private List<PhaseI> phases; ! public RevenueBonus(int value) { this.value = value; vertices = new ArrayList<NetworkVertex>(); --- 25,31 ---- private List<PhaseI> phases; ! public RevenueBonus(int value, String name) { this.value = value; + this.name = name; vertices = new ArrayList<NetworkVertex>(); *************** *** 46,49 **** --- 50,57 ---- } + public String getName() { + return name; + } + public List<NetworkVertex> getVertices() { return vertices; *************** *** 62,69 **** --- 70,112 ---- } + public boolean addToRevenueCalculator(RevenueCalculator rc, int bonusId, List<NetworkVertex> allVertices, List<NetworkTrain> trains, PhaseI phase) { + if (isSimpleBonus() || !phases.isEmpty() && !phases.contains(phase)) return false; + // only non-simple bonuses and checks phase condition + + int[] verticesArray = new int[vertices.size()]; + for (int j=0; j < vertices.size(); j++) { + if (!allVertices.contains(vertices.get(j))) return false; // if vertex is not on graph, do not add bonus + verticesArray[j] = allVertices.indexOf(vertices.get(j)); + } + + boolean[] trainsArray = new boolean[trains.size()]; + for (int j=0; j < trains.size(); j++) { + trainsArray[j] = checkConditions(trains.get(j).getRailsTrainType(), phase); + } + + log.info("Add revenueBonus to RC, id = " + bonusId + ", bonus = " + this); + + rc.setBonus(bonusId, value, verticesArray, trainsArray); + + return true; + } + public boolean checkSimpleBonus(NetworkVertex vertex, TrainTypeI trainType, PhaseI phase) { return (isSimpleBonus() && vertices.contains(vertex) && checkConditions(trainType, phase)); } + public boolean checkComplexBonus(List<NetworkVertex> visitVertices, TrainTypeI trainType, PhaseI phase) { + boolean result = !isSimpleBonus() && checkConditions(trainType, phase); + if (result) { + for (NetworkVertex vertex:vertices) { + if (!visitVertices.contains(vertex)) { + result = false; + break; + } + } + } + return result; + } + public boolean checkConditions(TrainTypeI trainType, PhaseI phase) { boolean result = true; *************** *** 88,96 **** return result; } ! @Override public String toString() { StringBuffer s = new StringBuffer(); ! s.append("RevenueBonus with value " + value); s.append(", vertices = " + vertices); s.append(", trainTypes = " + trainTypes); --- 131,144 ---- return result; } ! @Override public String toString() { StringBuffer s = new StringBuffer(); ! s.append("RevenueBonus"); ! if (name == null) ! s.append (" unnamed"); ! else ! s.append(" name = " + name); ! s.append(", value " + value); s.append(", vertices = " + vertices); s.append(", trainTypes = " + trainTypes); *************** *** 98,101 **** --- 146,158 ---- return s.toString(); } + + + public static int getNumberNonSimpleBonuses(List<RevenueBonus> bonuses) { + int number = 0; + for (RevenueBonus bonus:bonuses) { + if (!bonus.isSimpleBonus()) number++; + } + return number; + } } Index: RevenueAdapter.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/RevenueAdapter.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** RevenueAdapter.java 12 May 2010 18:50:26 -0000 1.12 --- RevenueAdapter.java 14 May 2010 15:19:57 -0000 1.13 *************** *** 6,13 **** --- 6,16 ---- import java.util.ArrayList; import java.util.Arrays; + import java.util.Collection; import java.util.Collections; import java.util.HashMap; + import java.util.HashSet; import java.util.List; import java.util.Map; + import java.util.Set; import org.apache.log4j.Logger; *************** *** 24,161 **** ! public class RevenueAdapter implements Runnable { protected static Logger log = Logger.getLogger(RevenueAdapter.class.getPackage().getName()); ! private GameManagerI gameManager; ! private NetworkGraphBuilder graphBuilder; ! private PublicCompanyI company; ! private PhaseI phase; ! private SimpleGraph<NetworkVertex, NetworkEdge> graph; ! ! private RevenueCalculator rc; ! private int maxNeighbors; ! private int maxBlocks; ! private List<NetworkVertex> vertexes; ! private List<NetworkEdge> edges; ! private List<NetworkVertex> startVertexes; private List<NetworkTrain> trains; ! private Map<NetworkVertex, List<NetworkVertex>> vertexVisitSets; private List<RevenueBonus> revenueBonuses; ! // revenue listener private RevenueListener revenueListener; ! public RevenueAdapter(GameManagerI gameManager, NetworkGraphBuilder graphBuilder, PublicCompanyI company){ this.gameManager = gameManager; this.graphBuilder = graphBuilder; ! this.graph = NetworkGraphBuilder.optimizeGraph(graphBuilder.getRailRoadGraph(company)); ! this.vertexes = new ArrayList<NetworkVertex>(graph.vertexSet()); ! this.edges = new ArrayList<NetworkEdge>(graph.edgeSet()); this.trains = new ArrayList<NetworkTrain>(); ! this.startVertexes = new ArrayList<NetworkVertex>(); ! this.vertexVisitSets = new HashMap<NetworkVertex, List<NetworkVertex>>(); this.revenueBonuses = new ArrayList<RevenueBonus>(); } ! private void defineRevenueBonuses() { ! // check each vertex hex for a potential revenue bonus ! for (NetworkVertex vertex:vertexes) { ! MapHex hex = vertex.getHex(); ! if (hex == null) continue; ! ! List<RevenueBonusTemplate> bonuses = new ArrayList<RevenueBonusTemplate>(); ! List<RevenueBonusTemplate> hexBonuses = hex.getRevenueBonuses(); ! if (hexBonuses != null) bonuses.addAll(hexBonuses); ! // List<RevenueBonusTemplate> tileBonuses = hex.getCurrentTile().getRevenueBonuses(); ! // if (tileBonuses != null) bonuses.addAll(hexBonuses); ! if (bonuses == null) continue; ! for (RevenueBonusTemplate bonus:bonuses) { ! revenueBonuses.add(bonus.toRevenueBonus(hex, gameManager, graphBuilder)); ! } } ! log.info("RevenueBonuses = " + revenueBonuses); } ! private int defineVertexVisitSets() { // define map of all locationNames ! Map<String, List<NetworkVertex>> locations = new HashMap<String, List<NetworkVertex>>(); ! for (NetworkVertex vertex:vertexes) { String ln = vertex.getCityName(); if (ln == null) continue; if (locations.containsKey(ln)) { ! locations.get(ln).add(vertex); } else { ! List<NetworkVertex> v = new ArrayList<NetworkVertex>(); ! v.add(vertex); locations.put(ln, v); } } log.info("Locations = " + locations); ! // transfer those locationNames to vertexBlocks ! int maxBlocks = 0; ! for (List<NetworkVertex> location:locations.values()) { ! if (location.size() >= 2) { ! for (NetworkVertex vertex:location){ ! if (vertexVisitSets.containsKey(vertex)) { ! for (NetworkVertex v:location) { ! if (v != vertex && !vertexVisitSets.get(vertex).contains(v)) { ! vertexVisitSets.get(vertex).add(v); ! } ! } ! } else { ! List<NetworkVertex> blocks = new ArrayList<NetworkVertex>(); ! for (NetworkVertex v:location) { ! if (v != vertex) { ! blocks.add(v); ! } ! } ! vertexVisitSets.put(vertex, blocks); ! } ! } ! maxBlocks = Math.max(maxBlocks, location.size()); } } - log.info("RA: Block of " + vertexVisitSets + ", maxBlocks = " + maxBlocks); - return maxBlocks; } ! public void initRevenueCalculator(){ ! if (rc == null) { ! // define blocks and return those ! maxBlocks = defineVertexVisitSets(); ! ! // define revenueBonuses ! defineRevenueBonuses(); ! // define the maximum number of vertexes ! maxNeighbors = 0; ! for (NetworkVertex vertex:vertexes) ! if (!vertex.isHQ()) ! maxNeighbors = Math.max(maxNeighbors, ! graph.edgesOf(vertex).size()); ! log.info("maxNeighbors = " + maxNeighbors); ! this.rc = new RevenueCalculator(this, vertexes.size(), edges.size(), maxNeighbors, maxBlocks, trains.size()); } } ! public void refreshRevenueCalculator() { ! rc = null; ! // refresh startVertexes ! this.startVertexes = new ArrayList<NetworkVertex>(); ! // refresh revenueBonuses ! this.revenueBonuses = new ArrayList<RevenueBonus>(); } ! private void prepareRevenuePrediction(boolean activatePrediction) { // separate vertexes List<NetworkVertex> cities = new ArrayList<NetworkVertex>(); List<NetworkVertex> towns = new ArrayList<NetworkVertex>(); ! for (NetworkVertex vertex: vertexes) { if (vertex.isMajor()) cities.add(vertex); if (vertex.isMinor()) towns.add(vertex); --- 27,289 ---- ! public final class RevenueAdapter implements Runnable { protected static Logger log = Logger.getLogger(RevenueAdapter.class.getPackage().getName()); ! // define VertexVisitSet ! public class VertexVisit { ! Set<NetworkVertex> set; ! VertexVisit() {set = new HashSet<NetworkVertex>();} ! public String toString() { ! return "VertexVisit Set:" + set; ! } ! } ! // basic links, to be defined at creation ! private final GameManagerI gameManager; ! private final NetworkGraphBuilder graphBuilder; ! private final PublicCompanyI company; ! private final PhaseI phase; ! ! // basic components, defined empty at creation ! private SimpleGraph<NetworkVertex, NetworkEdge> graph; ! private Set<NetworkVertex> startVertices; private List<NetworkTrain> trains; ! private List<VertexVisit> vertexVisitSets; private List<RevenueBonus> revenueBonuses; + private Set<NetworkVertex> protectedVertices; ! // components related to the revenue calculator ! private RevenueCalculator rc; ! SimpleGraph<NetworkVertex,NetworkEdge> rcGraph; ! private List<NetworkVertex> rcVertices; ! private List<NetworkEdge> rcEdges; ! private List<RevenueTrainRun> optimalRun; ! ! // revenue listener to communicate results private RevenueListener revenueListener; ! public RevenueAdapter(GameManagerI gameManager, NetworkGraphBuilder graphBuilder, PublicCompanyI company, PhaseI phase){ this.gameManager = gameManager; this.graphBuilder = graphBuilder; + this.company = company; + this.phase = phase; ! this.graph = new SimpleGraph<NetworkVertex, NetworkEdge>(NetworkEdge.class); this.trains = new ArrayList<NetworkTrain>(); ! this.startVertices = new HashSet<NetworkVertex>(); ! this.vertexVisitSets = new ArrayList<VertexVisit>(); this.revenueBonuses = new ArrayList<RevenueBonus>(); + this.protectedVertices = new HashSet<NetworkVertex>(); } ! public PhaseI getPhase() { ! return phase; ! } ! ! public Set<NetworkVertex> getVertices() { ! return graph.vertexSet(); ! } ! ! public Set<NetworkEdge> getEdges() { ! return graph.edgeSet(); ! } ! ! public SimpleGraph<NetworkVertex,NetworkEdge> getRCGraph() { ! return rcGraph; ! } ! ! public int getRCVertexId(NetworkVertex vertex) { ! return rcVertices.indexOf(vertex); ! } ! public int getRCEdgeId(NetworkEdge edge) { ! return rcEdges.indexOf(edge); ! } ! ! public Set<NetworkVertex> getStartVertices() { ! return startVertices; ! } ! ! public boolean addStartVertex(NetworkVertex startVertex) { ! if (startVertices.contains(startVertex)) return false; ! ! startVertices.add(startVertex); ! return true; ! } ! ! public List<NetworkTrain> getTrains() { ! return trains; ! } ! ! public boolean addTrain(TrainI railsTrain){ ! NetworkTrain train = NetworkTrain.createFromRailsTrain(railsTrain); ! if (train == null) { ! return false; ! } else { ! trains.add(train); ! return true; } ! } ! ! public boolean addTrainByString(String trainString) { ! TrainTypeI trainType = gameManager.getTrainManager().getTypeByName(trainString.trim()); ! if (trainType != null) { // string defines available trainType ! log.info("RA: found trainType" + trainType); ! TrainI railsTrain = trainType.cloneTrain(); ! return addTrain(railsTrain); ! } else { // otherwise interpret the train ! NetworkTrain train = NetworkTrain.createFromString(trainString); ! if (train == null) return false; ! trains.add(train); ! return true; ! } ! } ! ! public List<VertexVisit> getVertexVisitSets() { ! return vertexVisitSets; } ! public void addVertexVisitSet(VertexVisit visit) { ! vertexVisitSets.add(visit); ! protectedVertices.addAll(visit.set); ! } ! ! public List<RevenueBonus> getRevenueBonuses() { ! return revenueBonuses; ! } ! ! public void addRevenueBonus(RevenueBonus bonus) { ! revenueBonuses.add(bonus); ! protectedVertices.addAll(bonus.getVertices()); ! } ! ! public void populateFromRails() { ! // define graph, without HQ ! graph = graphBuilder.getRailRoadGraph(company, false); ! ! // define startVertexes ! startVertices.addAll(graphBuilder.getCompanyBaseTokenVertexes(company)); ! ! // define visit sets ! defineVertexVisitSets(); ! ! // define revenueBonuses ! defineRevenueBonuses(); ! ! // define Trains ! company.getPortfolio().getTrainList(); ! for (TrainI train:company.getPortfolio().getTrainList()) { ! addTrain(train); ! } ! ! } ! private void defineVertexVisitSets() { // define map of all locationNames ! Map<String, VertexVisit> locations = new HashMap<String, VertexVisit>(); ! for (NetworkVertex vertex:getVertices()) { String ln = vertex.getCityName(); if (ln == null) continue; if (locations.containsKey(ln)) { ! locations.get(ln).set.add(vertex); } else { ! VertexVisit v = new VertexVisit(); ! v.set.add(vertex); locations.put(ln, v); } } log.info("Locations = " + locations); ! // convert the location map to the vertex sets ! for (VertexVisit location:locations.values()) { ! if (location.set.size() >= 2) { ! addVertexVisitSet(location); } } } + + private void defineRevenueBonuses() { + // create set of all hexes + Set<MapHex> hexes = new HashSet<MapHex>(); + for (NetworkVertex vertex:getVertices()) { + MapHex hex = vertex.getHex(); + if (hex != null) hexes.add(hex); + } ! // check each vertex hex for a potential revenue bonus ! for (MapHex hex:hexes) { ! List<RevenueBonusTemplate> bonuses = new ArrayList<RevenueBonusTemplate>(); ! List<RevenueBonusTemplate> hexBonuses = hex.getRevenueBonuses(); ! if (hexBonuses != null) bonuses.addAll(hexBonuses); ! List<RevenueBonusTemplate> tileBonuses = hex.getCurrentTile().getRevenueBonuses(); ! if (tileBonuses != null) bonuses.addAll(tileBonuses); ! ! if (bonuses == null) continue; ! for (RevenueBonusTemplate bonus:bonuses) { ! addRevenueBonus(bonus.toRevenueBonus(hex, gameManager, graphBuilder)); ! } } + log.info("RA: RevenueBonuses = " + revenueBonuses); } + ! public void initRevenueCalculator(){ ! // optimize graph (optimizeGraph clones the graph) ! rcGraph = NetworkGraphBuilder.optimizeGraph(graph, protectedVertices); ! ! // define the vertices and edges lists ! rcVertices = new ArrayList<NetworkVertex>(rcGraph.vertexSet()); ! NetworkVertex.initAllRailsVertices(rcVertices, company, phase); ! // define ordering on vertexes by value ! Collections.sort(rcVertices, new NetworkVertex.ValueOrder()); ! rcEdges = new ArrayList<NetworkEdge>(rcGraph.edgeSet()); ! ! // prepare train length ! prepareTrainLengths(rcVertices); ! ! // check dimensions ! int maxVisitVertices = maxVisitVertices(); ! int maxBonusVertices = maxRevenueBonusVertices(); ! int maxNeighbors = maxVertexNeighbors(rcVertices); ! ! rc = new RevenueCalculator(this, rcVertices.size(), rcEdges.size(), ! maxNeighbors, maxVisitVertices, trains.size(), maxBonusVertices); ! ! populateRevenueCalculator(); ! } ! ! private int maxVisitVertices() { ! int maxNbVertices = 0; ! for (VertexVisit vertexVisit:vertexVisitSets) { ! maxNbVertices = Math.max(maxNbVertices, vertexVisit.set.size()); ! } ! log.info("RA: Block of " + vertexVisitSets + ", maximum vertices in a set = "+ maxNbVertices); ! return maxNbVertices; ! } ! ! ! private int maxVertexNeighbors(Collection<NetworkVertex> vertices) { ! int maxNeighbors = 0; ! for (NetworkVertex vertex:vertices) { ! maxNeighbors = Math.max(maxNeighbors, rcGraph.edgesOf(vertex).size()); ! } ! log.info("RA: Maximum neighbors in graph = "+ maxNeighbors); ! return maxNeighbors; ! } ! ! private int maxRevenueBonusVertices() { ! // get the number of non-simple bonuses ! int nbBonuses = RevenueBonus.getNumberNonSimpleBonuses(revenueBonuses); ! log.info("Number of non simple bonuses = " + nbBonuses); ! return nbBonuses; } ! private void prepareTrainLengths(Collection<NetworkVertex> vertices) { // separate vertexes List<NetworkVertex> cities = new ArrayList<NetworkVertex>(); List<NetworkVertex> towns = new ArrayList<NetworkVertex>(); ! for (NetworkVertex vertex: vertices) { if (vertex.isMajor()) cities.add(vertex); if (vertex.isMinor()) towns.add(vertex); *************** *** 181,204 **** } ! public void populateRevenueCalculator(PhaseI phase, boolean activatePrediction){ ! // store phase ! this.phase = phase; ! ! if (rc == null) initRevenueCalculator(); ! ! // prepare and optionally activate revenue prediction ! prepareRevenuePrediction(activatePrediction); ! ! // Define ordering on vertexes by value ! NetworkVertex.initAllRailsVertices(vertexes, company, phase); ! Collections.sort(vertexes, new NetworkVertex.ValueOrder()); ! for (int id=0; id < vertexes.size(); id++){ ! NetworkVertex v = vertexes.get(id); ! if (v.isHQ()) { ! // HQ is not added to list, but used to assign startVertexes ! startVertexes.addAll(Graphs.neighborListOf(graph, v)); ! continue; ! } // add to revenue calculator v.addToRevenueCalculator(rc, id); --- 309,316 ---- } ! private void populateRevenueCalculator(){ ! for (int id=0; id < rcVertices.size(); id++){ ! NetworkVertex v = rcVertices.get(id); // add to revenue calculator v.addToRevenueCalculator(rc, id); *************** *** 210,242 **** // set neighbors if (!v.isSink()) { ! List<NetworkVertex> neighbors = Graphs.neighborListOf(graph, v); int j=0, neighborsArray[] = new int[neighbors.size()]; for (NetworkVertex n:neighbors){ ! neighborsArray[j++] = vertexes.indexOf(n); } ! // sort by value order Arrays.sort(neighborsArray, 0, j); // define according edges int[] edgesArray = new int[j]; for (int e=0; e < j; e++) { ! NetworkVertex n = vertexes.get(neighborsArray[e]); ! edgesArray[e] = edges.indexOf(graph.getEdge(v, n)); } rc.setVertexNeighbors(id, neighborsArray, edgesArray); } - // set blocks - if (vertexVisitSets.containsKey(v)) { - int b = 0, blocks[] = new int[vertexVisitSets.get(v).size()]; - for (NetworkVertex n: vertexVisitSets.get(v)) { - blocks[b++] = vertexes.indexOf(n); - } - rc.setVertexVisitSets(id, blocks); - } } // set startVertexes ! int[] sv = new int[startVertexes.size()]; ! for (int j=0; j < startVertexes.size(); j++) { ! sv[j] = vertexes.lastIndexOf(startVertexes.get(j)); } Arrays.sort(sv); // sort by value order --- 322,346 ---- // set neighbors if (!v.isSink()) { ! List<NetworkVertex> neighbors = Graphs.neighborListOf(rcGraph, v); int j=0, neighborsArray[] = new int[neighbors.size()]; for (NetworkVertex n:neighbors){ ! neighborsArray[j++] = rcVertices.indexOf(n); } ! // sort by value orderboolean activatePrediction Arrays.sort(neighborsArray, 0, j); // define according edges int[] edgesArray = new int[j]; for (int e=0; e < j; e++) { ! NetworkVertex n = rcVertices.get(neighborsArray[e]); ! edgesArray[e] = rcEdges.indexOf(rcGraph.getEdge(v, n)); } rc.setVertexNeighbors(id, neighborsArray, edgesArray); } } // set startVertexes ! int startVertexId =0, sv[] = new int[startVertices.size()]; ! for (NetworkVertex startVertex:startVertices) { ! sv[startVertexId++] = rcVertices.indexOf(startVertex); } Arrays.sort(sv); // sort by value order *************** *** 244,250 **** // set edges ! for (int id=0; id < edges.size(); id++) { // prepare values ! NetworkEdge e = edges.get(id); boolean greedy = e.isGreedy(); int distance = e.getDistance(); --- 348,354 ---- // set edges ! for (int id=0; id < rcEdges.size(); id++) { // prepare values ! NetworkEdge e = rcEdges.get(id); boolean greedy = e.isGreedy(); int distance = e.getDistance(); *************** *** 258,261 **** --- 362,381 ---- } + // set vertex sets + for (VertexVisit visit:vertexVisitSets) { + int j=0, setArray[] = new int[visit.set.size()]; + for (NetworkVertex n:visit.set){ + setArray[j++] = rcVertices.indexOf(n); + } + rc.setVisitSet(setArray); + } + + + log.info("rcVertices:" + rcVertices); + // set revenue bonuses + int id = 0; + for (RevenueBonus bonus:revenueBonuses) { + if (bonus.addToRevenueCalculator(rc, id, rcVertices, trains, phase)) id ++; + } } *************** *** 276,348 **** } ! public void addDefaultTrain(int cities) { ! String trainName = Integer.valueOf(cities).toString(); ! NetworkTrain train =new NetworkTrain(cities, 0, false, 1, 1, trainName, null); ! trains.add(train); ! } ! ! public void addTrain(TrainI railsTrain){ ! NetworkTrain train = NetworkTrain.createFromRailsTrain(railsTrain); ! if (train != null) trains.add(train); ! } ! ! public void addTrainByString(String trainString) { ! String t = trainString.trim(); ! TrainTypeI trainType = gameManager.getTrainManager().getTypeByName(trainString); ! if (trainType != null) { // string defines available trainType ! TrainI railsTrain = trainType.cloneTrain(); ! addTrain(railsTrain); ! log.info("RA: found trainType" + trainType); ! } else { // otherwise interpret the train ! int cities = 0; int towns = 0; boolean ignoreTowns = false; int multiplyCities = 1; int multiplyTowns = 1; ! if (t.equals("D")) { ! cities = 99; // diesel ! } else if (t.contains("+")) { ! cities = Integer.parseInt(t.split("\\+")[0]); // + train ! towns = Integer.parseInt(t.split("\\+")[1]); ! } else if (t.contains("E")) { ! // express train ! cities = Integer.parseInt(t.replace("E", "")); ! ignoreTowns = true; ! multiplyTowns = 0; ! } else if (t.contains("D")) { ! // double (express) train ! cities = Integer.parseInt(t.replace("D", "")); ! ignoreTowns = true; ! multiplyCities = 2; ! multiplyTowns = 0; ! } else { ! // default train ! cities = Integer.parseInt(t); } - NetworkTrain networkTrain = new NetworkTrain(cities, towns, ignoreTowns, multiplyCities, multiplyTowns, t, null); - trains.add(networkTrain); } } - public void addStartVertex(NetworkVertex v) { - startVertexes.add(v); - } - - public void addRevenueBonus(RevenueBonus bonus) { - revenueBonuses.add(bonus); - } ! public Map<NetworkTrain, List<NetworkVertex>> getOptimalRun() { ! int[][] optimalRunRaw = rc.getOptimalRun(); ! Map<NetworkTrain, List<NetworkVertex>> optimalRun = new HashMap<NetworkTrain, List<NetworkVertex>>(); ! for (int j=0; j < optimalRunRaw.length; j++) { ! List<NetworkVertex> runList = new ArrayList<NetworkVertex>(); ! for (int v=0; v < optimalRunRaw[j].length; v++) { ! int vertexId = optimalRunRaw[j][v]; if (vertexId == -1) break; ! runList.add(vertexes.get(vertexId)); } ! optimalRun.put(trains.get(j), runList); } ! return optimalRun; } - public int calculateRevenue() { return calculateRevenue(0, trains.size() - 1); --- 396,430 ---- } ! public String getVertexValueAsString(NetworkVertex vertex, NetworkTrain train, PhaseI phase) { ! StringBuffer s = new StringBuffer(); ! ! // base value ! s.append(vertex.getValueByTrain(train)); ! ! // add potential revenueBonuses ! for (RevenueBonus bonus:revenueBonuses) { ! if (bonus.checkSimpleBonus(vertex, train.getRailsTrainType(), phase)) { ! s.append("+" + bonus.getValue()); } } + return s.toString(); } ! private List<RevenueTrainRun> convertRcRun(int[][] rcRun) { ! ! List<RevenueTrainRun> convertRun = new ArrayList<RevenueTrainRun>(); ! for (int j=0; j < rcRun.length; j++) { ! RevenueTrainRun trainRun = new RevenueTrainRun(this, trains.get(j)); ! for (int v=0; v < rcRun[j].length; v++) { ! int vertexId = rcRun[j][v]; if (vertexId == -1) break; ! trainRun.addVertex(rcVertices.get(vertexId)); } ! convertRun.add(trainRun); } ! return convertRun; } public int calculateRevenue() { return calculateRevenue(0, trains.size() - 1); *************** *** 350,358 **** public int calculateRevenue(int startTrain, int finalTrain) { ! if (startTrain < 0 || finalTrain >= trains.size() || startTrain > finalTrain) return -1; rc.initialPredictionRuns(startTrain, finalTrain); ! return rc.calculateRevenue(startTrain, finalTrain); } - public void addRevenueListener(RevenueListener listener) { --- 432,447 ---- public int calculateRevenue(int startTrain, int finalTrain) { ! if (startTrain < 0 || finalTrain >= trains.size() || startTrain > finalTrain) { ! optimalRun = null; ! return 0; ! } rc.initialPredictionRuns(startTrain, finalTrain); ! int value = rc.calculateRevenue(startTrain, finalTrain); ! optimalRun = convertRcRun(rc.getOptimalRun()); ! return value; ! } ! public List<RevenueTrainRun> getOptimalRun() { ! return optimalRun; } public void addRevenueListener(RevenueListener listener) { *************** *** 382,417 **** public String getOptimalRunPrettyPrint() { StringBuffer runPrettyPrint = new StringBuffer(); ! Map<NetworkTrain, List<NetworkVertex>> run = getOptimalRun(); ! ! for (NetworkTrain train:run.keySet()) { ! runPrettyPrint.append("Train " + train + ": "); ! MapHex currentHex = null; ! NetworkVertex startVertex = null; ! for (NetworkVertex vertex:run.get(train)) { ! if (startVertex == null) { ! currentHex = vertex.getHex(); ! startVertex = vertex; ! runPrettyPrint.append(vertex.getHex().getName() + "("); ! } else if (startVertex == vertex) { ! currentHex = vertex.getHex(); ! runPrettyPrint.append(") / " + vertex.getHex().getName() + "(0"); ! continue; ! } else if (vertex.getHex() != currentHex) { ! currentHex = vertex.getHex(); ! runPrettyPrint.append("), " + vertex.getHex().getName() + "("); ! } else { ! runPrettyPrint.append(","); ! } ! if (vertex.isStation()) { ! runPrettyPrint.append(getVertexValue(vertex, train, phase)); ! } else { ! runPrettyPrint.append(currentHex.getOrientationName(vertex.getSide())); ! } ! } ! if (currentHex != null) { ! runPrettyPrint.append(")"); ! } ! runPrettyPrint.append("\n"); } return runPrettyPrint.toString(); --- 471,479 ---- public String getOptimalRunPrettyPrint() { + if (optimalRun == null) return "No Optimal Run"; + StringBuffer runPrettyPrint = new StringBuffer(); ! for (RevenueTrainRun run:optimalRun) { ! runPrettyPrint.append(run.prettyPrint()); } return runPrettyPrint.toString(); *************** *** 420,471 **** public void drawOptimalRunAsPath(HexMap map) { List<GeneralPath> pathList = new ArrayList<GeneralPath>(); ! Map<NetworkTrain, List<NetworkVertex>> run = getOptimalRun(); ! ! for (NetworkTrain train:run.keySet()) { ! GeneralPath path = new GeneralPath(); ! NetworkVertex startVertex = null; ! NetworkVertex previousVertex = null; ! for (NetworkVertex vertex:run.get(train)) { ! log.debug("RA: Next vertex " + vertex); ! Point2D vertexPoint = NetworkVertex.getVertexPoint2D(map, vertex); ! if (startVertex == null) { ! startVertex = vertex; ! previousVertex = vertex; ! path.moveTo((float)vertexPoint.getX(), (float)vertexPoint.getY()); ! continue; ! } else if (startVertex == vertex) { ! path.moveTo((float)vertexPoint.getX(), (float)vertexPoint.getY()); ! previousVertex = vertex; ! continue; ! } ! // draw hidden vertexes ! NetworkEdge edge = graph.getEdge(previousVertex, vertex); ! if (edge != null) { ! log.debug("RA: draw edge "+ edge.toFullInfoString()); ! List<NetworkVertex> hiddenVertexes = edge.getHiddenVertexes(); ! if (edge.getSource() == vertex) { ! log.debug("RA: reverse hiddenVertexes"); ! for (int i = hiddenVertexes.size() - 1; i >= 0; i--) { ! NetworkVertex v = hiddenVertexes.get(i); ! Point2D vPoint = NetworkVertex.getVertexPoint2D(map, v); ! if (vPoint != null) { ! path.lineTo((float)vPoint.getX(), (float)vPoint.getY()); ! } ! } ! } else { ! for (NetworkVertex v:hiddenVertexes) { ! Point2D vPoint = NetworkVertex.getVertexPoint2D(map, v); ! if (vPoint != null) { ! path.lineTo((float)vPoint.getX(), (float)vPoint.getY()); ! } ! } ! } ! } ! if (vertexPoint != null) { ! path.lineTo((float)vertexPoint.getX(), (float)vertexPoint.getY()); ! } ! previousVertex = vertex; } - pathList.add(path); } map.setTrainPaths(pathList); --- 482,489 ---- public void drawOptimalRunAsPath(HexMap map) { List<GeneralPath> pathList = new ArrayList<GeneralPath>(); ! if (optimalRun != null) { ! for (RevenueTrainRun run:optimalRun) { ! pathList.add(run.getAsPath(map)); } } map.setTrainPaths(pathList); *************** *** 475,484 **** public String toString() { StringBuffer buffer = new StringBuffer(); ! buffer.append("RevenueCalculator: \n" + rc); ! buffer.append("\n Vertexes: \n" + vertexes); ! buffer.append("\n Edges: \n" + edges); return buffer.toString(); } - } --- 493,502 ---- public String toString() { StringBuffer buffer = new StringBuffer(); ! buffer.append("RevenueCalculator:\n" + rc + "\n"); ! buffer.append("rcVertices:\n" + rcVertices + "\n"); ! buffer.append("rcEdges:\n" + rcEdges + "\n"); ! buffer.append("startVertices:" + startVertices); return buffer.toString(); } } Index: NetworkGraphBuilder.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/algorithms/NetworkGraphBuilder.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** NetworkGraphBuilder.java 11 May 2010 21:47:21 -0000 1.9 --- NetworkGraphBuilder.java 14 May 2010 15:19:57 -0000 1.10 *************** *** 4,7 **** --- 4,8 ---- import java.awt.Rectangle; import java.util.ArrayList; + import java.util.Collection; import java.util.HashMap; import java.util.HashSet; *************** *** 29,33 **** import rails.game.BaseToken; import rails.game.City; - import rails.game.GameManagerI; import rails.game.MapHex; import rails.game.PublicCompanyI; --- 30,33 ---- *************** *** 153,157 **** } ! public SimpleGraph<NetworkVertex, NetworkEdge> getRailRoadGraph(PublicCompanyI company) { // set sinks on mapgraph --- 153,157 ---- } ! public SimpleGraph<NetworkVertex, NetworkEdge> getRailRoadGraph(PublicCompanyI company, boolean addHQ) { // set sinks on mapgraph *************** *** 165,174... [truncated message content] |