All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.rinde.rinsim.examples.demo.factory.AgvModel Maven / Gradle / Ivy

/*
 * Copyright (C) 2011-2017 Rinde van Lon, imec-DistriNet, KU Leuven
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.rinde.rinsim.examples.demo.factory;

import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newLinkedHashSet;

import java.math.RoundingMode;
import java.util.List;
import java.util.Set;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;

import org.apache.commons.math3.random.RandomGenerator;

import com.github.rinde.rinsim.core.SimulatorAPI;
import com.github.rinde.rinsim.core.SimulatorUser;
import com.github.rinde.rinsim.core.model.DependencyProvider;
import com.github.rinde.rinsim.core.model.Model.AbstractModel;
import com.github.rinde.rinsim.core.model.ModelBuilder.AbstractModelBuilder;
import com.github.rinde.rinsim.core.model.ModelProvider;
import com.github.rinde.rinsim.core.model.ModelReceiver;
import com.github.rinde.rinsim.core.model.pdp.PDPModel;
import com.github.rinde.rinsim.core.model.pdp.PDPModel.PDPModelEventType;
import com.github.rinde.rinsim.core.model.pdp.PDPModelEvent;
import com.github.rinde.rinsim.core.model.rand.RandomProvider;
import com.github.rinde.rinsim.core.model.road.RoadModel;
import com.github.rinde.rinsim.core.model.time.TickListener;
import com.github.rinde.rinsim.core.model.time.TimeLapse;
import com.github.rinde.rinsim.event.Event;
import com.github.rinde.rinsim.event.Listener;
import com.github.rinde.rinsim.geom.Point;
import com.google.auto.value.AutoValue;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.math.DoubleMath;

class AgvModel
    extends AbstractModel
    implements TickListener, ModelReceiver, SimulatorUser, Listener {

  Optional rm;
  Optional simulator;
  final RandomGenerator rng;
  Set occupiedPositions;
  ImmutableList> points;
  int currentBox;

  List boxes;
  final List border;

  AgvModel(RandomGenerator r, ImmutableList> ps,
      ImmutableList b) {
    rm = Optional.absent();
    simulator = Optional.absent();
    rng = r;
    occupiedPositions = newLinkedHashSet();
    points = ps;
    currentBox = 0;
    boxes = newArrayList();
    border = b;
  }

  @Override
  public void tick(TimeLapse timeLapse) {}

  @Override
  public void afterTick(TimeLapse timeLapse) {}

  @Override
  public void registerModelProvider(ModelProvider mp) {
    rm = Optional.fromNullable(mp.tryGetModel(RoadModel.class));
    Optional
      .fromNullable(mp.tryGetModel(PDPModel.class))
      .get()
      .getEventAPI()
      .addListener(this, PDPModelEventType.END_DELIVERY,
        PDPModelEventType.END_PICKUP);
  }

  @Override
  public void setSimulator(SimulatorAPI api) {
    simulator = Optional.of(api);
  }

  void init() {
    if (simulator.isPresent() && rm.isPresent()) {
      int max = 0;
      for (final List ps : points) {
        max = Math.max(max, ps.size());
      }
      final int num = max;
      for (int i = 0; i < num; i++) {
        final long duration = DoubleMath.roundToLong(
          FactoryExample.SERVICE_DURATION / 2d
            + rng.nextDouble() * FactoryExample.SERVICE_DURATION,
          RoundingMode.CEILING);

        final Point rnd = rndBorder();
        final Point dest;
        if (i >= points.get(0).size()) {
          dest = rndBorder();
        } else {
          dest = points.get(0).get(i);
          occupiedPositions.add(dest);
        }

        final BoxHandle bh = new BoxHandle(i);
        final Box b = new Box(rnd, dest, duration, bh);
        bh.box = b;

        boxes.add(bh);
        simulator.get()
          .register(verifyNotNull(boxes.get(boxes.size() - 1).box));
      }
    }
  }

  @Override
  public boolean register(AGV element) {
    element.registerAgvModel(this);
    return true;
  }

  @Override
  public boolean unregister(AGV element) {
    return false;
  }

  @Override
  public void handleEvent(Event e) {
    verify(e instanceof PDPModelEvent);
    final PDPModelEvent event = (PDPModelEvent) e;
    final Box box = (Box) verifyNotNull(event.parcel);
    if (e.getEventType() == PDPModelEventType.END_PICKUP) {
      occupiedPositions.remove(box.getPickupLocation());
    }
    if (e.getEventType() == PDPModelEventType.END_DELIVERY) {
      final long duration = DoubleMath.roundToLong(
        FactoryExample.SERVICE_DURATION / 2d
          + rng.nextDouble() * FactoryExample.SERVICE_DURATION,
        RoundingMode.CEILING);
      simulator.get().unregister(box);

      final BoxHandle bh = box.boxHandle;
      bh.wordIndex = (bh.wordIndex + 1) % points.size();

      final Point dest;
      if (bh.index >= points.get(bh.wordIndex).size()) {
        dest = rndBorder();
      } else {
        dest = points.get(bh.wordIndex).get(bh.index);
        occupiedPositions.add(dest);
      }

      final Box newBox = new Box(box.getDeliveryLocation(),
        dest, duration, bh);
      bh.box = newBox;

      simulator.get().register(newBox);
    }
  }

  Point rndBorder() {
    return border.get(rng.nextInt(border.size()));
  }

  Point rnd() {
    Point p;
    do {
      p = rm.get().getRandomPosition(rng);
    } while (occupiedPositions.contains(p));
    occupiedPositions.add(p);
    return p;
  }

  @Nullable
  Box nextDestination() {
    if (boxes.isEmpty()) {
      init();
    }
    verify(!boxes.isEmpty());
    final Box b = boxes.get(currentBox % boxes.size()).box;
    currentBox++;
    return b;
  }

  static Builder builder() {
    return Builder.create(ImmutableList.>of(),
      ImmutableList.of());
  }

  static class BoxHandle {
    int wordIndex;
    final int index;
    @Nullable
    Box box;

    BoxHandle(int i) {
      index = i;
      wordIndex = 0;
    }
  }

  @AutoValue
  abstract static class Builder extends AbstractModelBuilder {

    private static final long serialVersionUID = -8527252625057713751L;

    Builder() {
      setDependencies(RandomProvider.class);
    }

    abstract ImmutableList> getPoints();

    abstract ImmutableList getBorder();

    @CheckReturnValue
    Builder withPoints(ImmutableList> ps,
        ImmutableList b) {
      return create(ps, b);
    }

    @Override
    public AgvModel build(DependencyProvider dependencyProvider) {
      final RandomGenerator r = dependencyProvider.get(RandomProvider.class)
        .newInstance();
      return new AgvModel(r, getPoints(), getBorder());
    }

    static Builder create(ImmutableList> ps,
        ImmutableList b) {
      return new AutoValue_AgvModel_Builder(ps, b);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy