private void moveLink(final QLinkInternalI link, final double now) { if (link instanceof QLinkLanesImpl) { // This cannot be moved to QLinkLanesImpl since we want to be able to serve other lanes if one // lane is blocked. // kai, feb'12 // yyyy but somehow I think this should be solved "under the hood" in QLinkLanesImpl. kai, // sep'13 // zzzz the above yyyy solution would get really ugly with the current interface and the code // in the // else {} branch: link.isNotOfferingVehicle():boolean would return sequentially the state of // the single // lanes. Each call would have side effects on a state machine within QLinkLanesImpl. // Proposal: think // about a better interface first, then solve under the hood. dg, mar'14 for (QLaneI lane : ((QLinkLanesImpl) link).getToNodeQueueLanes()) { while (!lane.isNotOfferingVehicle()) { QVehicle veh = lane.getFirstVehicle(); Id<Link> nextLink = veh.getDriver().chooseNextLinkId(); if (!(lane.hasGreenForToLink(nextLink) && moveVehicleOverNode(veh, lane, now))) { break; } } } } else { while (!link.isNotOfferingVehicle()) { QVehicle veh = link.getFirstVehicle(); if (!moveVehicleOverNode(veh, link, now)) { break; } } } }
/** * Moves vehicles from the inlinks' buffer to the outlinks where possible.<br> * The inLinks are randomly chosen, and for each link all vehicles in the buffer are moved to * their desired outLink as long as there is space. If the front most vehicle in a buffer cannot * move across the node because there is no free space on its destination link, the work on this * inLink is finished and the next inLink's buffer is handled (this means, that at the node, all * links have only like one lane, and there are no separate lanes for the different outLinks. Thus * if the front most vehicle cannot drive further, all other vehicles behind must wait, too, even * if their links would be free). * * @param now The current time in seconds from midnight. * @return Whether the QNode stays active or not. */ /*package*/ boolean doSimStep(final double now) { int inLinksCounter = 0; double inLinksCapSum = 0.0; // Check all incoming links for buffered agents for (QLinkInternalI link : this.inLinksArrayCache) { if (!link.isNotOfferingVehicle()) { this.tempLinks[inLinksCounter] = link; inLinksCounter++; inLinksCapSum += link.getLink().getCapacity(now); } } if (inLinksCounter == 0) { this.active.set(false); return false; // Nothing to do } // randomize based on capacity for (int auxCounter = 0; auxCounter < inLinksCounter; auxCounter++) { double rndNum = random.nextDouble() * inLinksCapSum; double selCap = 0.0; for (int i = 0; i < inLinksCounter; i++) { QLinkInternalI link = this.tempLinks[i]; if (link != null) { selCap += link.getLink().getCapacity(now); if (selCap >= rndNum) { inLinksCapSum -= link.getLink().getCapacity(now); this.tempLinks[i] = null; this.moveLink(link, now); break; } } } } return true; }