ch.uzh.phys.ecn.oboma.map.model.Node.java Source code

Java tutorial

Introduction

Here is the source code for ch.uzh.phys.ecn.oboma.map.model.Node.java

Source

/*
 * The MIT License (MIT)
 * Copyright  2014 different authors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the Software?), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED AS IS?, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package ch.uzh.phys.ecn.oboma.map.model;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import lombok.EqualsAndHashCode;

import org.apache.commons.lang3.StringUtils;

import ch.uzh.phys.ecn.oboma.agents.model.Agent;
import ch.uzh.phys.ecn.oboma.common.InfectionState;
import ch.uzh.phys.ecn.oboma.functions.api.ITransformationFunction;
import ch.uzh.phys.ecn.oboma.functions.nop.NopTransformationFunction;
import ch.uzh.phys.ecn.oboma.map.api.INode;

@EqualsAndHashCode
public class Node implements INode {

    private final String mId;
    private final String mName;
    private final double mLatitude;
    private final double mLongitude;
    private final int mTimeBlocked;
    private final int mSize;
    private ITransformationFunction mInfectionFunction;
    private final Map<String, INode> mDestinationNodes;
    private final Map<String, INode> mOriginNodes;

    private final List<AgentPlacement> mAgents;
    private final List<Agent> mLeavingAgents; // No queue (list based fifo-if-free-seats)

    public Node(String pId, String pName, double pLat, double pLng, int pTimeBlocked, int pSize) {
        this(pId, pName, pLat, pLng, pTimeBlocked, pSize, new NopTransformationFunction());
    }

    public Node(String pId, String pName, double pLat, double pLng, int pTimeBlocked, int pSize,
            ITransformationFunction pInfectionFunction) {
        checkArgument(pId != null);
        checkArgument(pName != null);
        checkArgument(pSize >= 0);
        checkArgument(pInfectionFunction != null);

        mId = pId;
        mName = pName;
        mLatitude = pLat;
        mLongitude = pLng;
        mTimeBlocked = pTimeBlocked;
        mSize = pSize;
        mInfectionFunction = pInfectionFunction;

        mAgents = new ArrayList<>();
        mLeavingAgents = new ArrayList<>();
        mDestinationNodes = new HashMap<>();
        mOriginNodes = new HashMap<>();
    }

    @Override
    public String getId() {
        return mId;
    }

    @Override
    public String getName() {
        return mName;
    }

    @Override
    public double getLatitude() {
        return mLatitude;
    }

    @Override
    public double getLongitude() {
        return mLongitude;
    }

    @Override
    public boolean isConnecting() {
        return false;
    }

    @Override
    public List<INode> getDestinations() {
        return new ArrayList<>(mDestinationNodes.values());
    }

    @Override
    public void addDestination(INode pNode) {
        mDestinationNodes.put(pNode.getId(), pNode);
    }

    @Override
    public List<INode> getOrigins() {
        return new ArrayList<>(mOriginNodes.values());
    }

    @Override
    public void addOrigin(INode pNode) {
        mOriginNodes.put(pNode.getId(), pNode);
    }

    @Override
    public boolean place(Agent pAgent) {
        checkArgument(pAgent != null);

        if (countFreeSeats() > 0) {
            int prefTime = pAgent.getPreferredTimeOfStay(mId);
            mAgents.add(new AgentPlacement(pAgent, Math.max(mTimeBlocked, prefTime)));
            return true;
        }
        return false;
    }

    @Override
    public int countFreeSeats() {
        return mSize == 0 ? Integer.MAX_VALUE : (mSize - mAgents.size());
    }

    @Override
    public List<Agent> getAllAgents() {
        List<Agent> ret = new ArrayList<>(mAgents.size() + mLeavingAgents.size());
        for (AgentPlacement ap : mAgents) {
            ret.add(ap.getAgent());
        }
        ret.addAll(mLeavingAgents);
        return ret;
    }

    @Override
    public List<Agent> getLeavingAgents() {
        return new ArrayList<Agent>(mLeavingAgents);
    }

    @Override
    public void setTransformationFunction(ITransformationFunction pInfectionFunction) {
        mInfectionFunction = pInfectionFunction != null ? pInfectionFunction : new NopTransformationFunction();
    }

    @Override
    public void preelapse() {
        // timestep on this node starts
        mInfectionFunction.onBeforeTimestep(this);

        Iterator<AgentPlacement> itr = mAgents.iterator();
        while (itr.hasNext()) {
            AgentPlacement ap = itr.next();
            // Elapse time for current dependant
            ap.preelapse();
            // Move agents to outgoing queue
            if (!ap.isStaying()) {
                mLeavingAgents.add(ap.getAgent());
                itr.remove();
            }
        }
    }

    @Override
    public void postelapse() {
        Iterator<Agent> itr = mLeavingAgents.iterator();
        while (itr.hasNext()) {
            Agent a = itr.next();
            String nextWaypoint = a.getNextWaypoint(mId);
            INode dest;
            if (StringUtils.equals(mId, nextWaypoint) || (nextWaypoint == null)) {
                dest = this;
            } else {
                dest = mDestinationNodes.get(nextWaypoint);
            }

            if (dest == null) {
                // check origin nodes when agent is going backwards
                dest = mOriginNodes.get(nextWaypoint);
            }
            checkState(dest != null);

            if (dest.place(a)) {
                itr.remove();
            }
        }

        // timestep on this node is done
        mInfectionFunction.onAfterTimestep(this);
    }

    @Override
    public void infect() {
        Map<Agent, InfectionState> agentMods = new HashMap<>();
        final Consumer<Agent> doInfect = a -> {
            InfectionState next = mInfectionFunction.apply(a, this);
            if (next != a.getState()) {
                agentMods.put(a, next);
            }
        };
        mAgents.stream().map(AgentPlacement::getAgent).forEach(doInfect);
        mLeavingAgents.forEach(doInfect);
        agentMods.forEach((a, i) -> a.setState(i));
    }

}