Search in sources :

Example 6 with TimetableItem

use of de.hpi.bpt.scylla.model.global.resource.TimetableItem in project scylla by bptlab.

the class DateTimeUtils method getTimeTableIndexWithinOrNext.

/**
 * Determines the index of the timetable item in which the given datetime is located.
 *
 * @param dateTime
 *            the datetime in question
 * @param timetable
 *            the timetable in question
 * @return the index of the timetable item in which the given datetime is located
 */
public static int getTimeTableIndexWithinOrNext(ZonedDateTime dateTime, List<TimetableItem> timetable) {
    int index = -1;
    double minDurationToItemStart = Double.MAX_VALUE;
    for (int i = 0; i < timetable.size(); i++) {
        TimetableItem item = timetable.get(i);
        if (isWithin(dateTime, item)) {
            return i;
        }
        double durationUntilItemStart = getDurationInReferenceUnit(dateTime, item.getWeekdayFrom(), item.getBeginTime());
        if (durationUntilItemStart < minDurationToItemStart) {
            minDurationToItemStart = durationUntilItemStart;
            index = i;
        }
    }
    return index;
}
Also used : TimetableItem(de.hpi.bpt.scylla.model.global.resource.TimetableItem)

Example 7 with TimetableItem

use of de.hpi.bpt.scylla.model.global.resource.TimetableItem in project scylla by bptlab.

the class DateTimeUtils method getTaskTerminationTime.

/**
 * Calculates the relative end time of a task. Consideres timetables of resources instances. If any resource
 * instance is idle, the duration is extended by the idle time.
 *
 * @param timeSpan
 *            the original duration of the task without any interruptions
 * @param presentTime
 *            current simulation time
 * @param tuple
 *            resource instances assigned to the task
 * @param event
 *            source event (for logging purposes)
 * @return the end time of the task
 */
public static TimeInstant getTaskTerminationTime(TimeSpan timeSpan, TimeInstant presentTime, ResourceObjectTuple tuple, ScyllaEvent event) {
    SimulationModel model = (SimulationModel) event.getModel();
    ProcessInstance processInstance = event.getProcessInstance();
    ProcessModel processModel = processInstance.getProcessModel();
    String source = event.getSource();
    String taskName = event.getDisplayName();
    int nodeId = event.getNodeId();
    String processScopeNodeId = SimulationUtils.getProcessScopeNodeId(processModel, nodeId);
    Set<String> resources = new HashSet<String>();
    Set<ResourceObject> resourceObjects = tuple.getResourceObjects();
    for (ResourceObject res : resourceObjects) {
        String resourceName = res.getResourceType() + "_" + res.getId();
        resources.add(resourceName);
    }
    // start
    long duration = timeSpan.getTimeRounded(timeUnit);
    if (duration == 0) {
        return presentTime;
    }
    ZonedDateTime dateTime = DateTimeUtils.getDateTime(presentTime);
    List<TimetableItem> timetable = tuple.getSharedTimetable();
    if (timetable == null) {
        return new TimeInstant(presentTime.getTimeRounded(timeUnit) + duration);
    }
    Integer index = null;
    for (int i = 0; i < timetable.size(); i++) {
        TimetableItem item = timetable.get(i);
        if (isWithin(dateTime, item)) {
            index = i;
            break;
        }
    }
    long timePassed = 0;
    while (timePassed < duration) {
        TimetableItem item = timetable.get(index);
        DayOfWeek untilWeekday = item.getWeekdayTo();
        LocalTime untilTime = item.getEndTime();
        ZonedDateTime dateTimeUntilEnd = getNextOrSameZonedDateTime(dateTime, untilWeekday, untilTime);
        long durationUntilEnd = chronoUnit.between(dateTime, dateTimeUntilEnd);
        long amountToAdd;
        if (timePassed + durationUntilEnd >= duration) {
            // task completes in current timetable item
            amountToAdd = duration - timePassed;
        } else {
            // until end of timetable item
            amountToAdd = durationUntilEnd;
        }
        timePassed += amountToAdd;
        dateTime = dateTime.plus(amountToAdd, chronoUnit);
        if (timePassed + durationUntilEnd < duration) {
            // task is not completed in current timetable item, so jump to the start of the next timetable item
            if (model.isOutputLoggingOn()) {
                // log idle during use
                ResourceStatus status = ResourceStatus.IN_USE_IDLE;
                long timeRelativeToStart = getTimeInstant(dateTime).getTimeRounded(timeUnit);
                ResourceInfo info = new ResourceInfo(timeRelativeToStart, status, processInstance, nodeId);
                for (ResourceObject obj : tuple.getResourceObjects()) {
                    String resourceType = obj.getResourceType();
                    String resourceId = obj.getId();
                    model.addResourceInfo(resourceType, resourceId, info);
                }
                ProcessNodeTransitionType transition = ProcessNodeTransitionType.PAUSE;
                ProcessNodeInfo nodeInfo = new ProcessNodeInfo(nodeId, processScopeNodeId, source, timeRelativeToStart, taskName, resources, transition);
                model.addNodeInfo(processModel, processInstance, nodeInfo);
            }
            index++;
            if (index == timetable.size()) {
                index = 0;
            }
            TimetableItem nextItem = timetable.get(index);
            untilWeekday = nextItem.getWeekdayFrom();
            untilTime = nextItem.getBeginTime();
            dateTime = getNextZonedDateTime(dateTime, untilWeekday, untilTime);
            if (model.isOutputLoggingOn()) {
                // log back to work
                ResourceStatus status = ResourceStatus.IN_USE;
                long timeRelativeToStart = getTimeInstant(dateTime).getTimeRounded(timeUnit);
                ResourceInfo info = new ResourceInfo(timeRelativeToStart, status, processInstance, nodeId);
                for (ResourceObject obj : tuple.getResourceObjects()) {
                    String resourceType = obj.getResourceType();
                    String resourceId = obj.getId();
                    model.addResourceInfo(resourceType, resourceId, info);
                }
                ProcessNodeTransitionType transition = ProcessNodeTransitionType.RESUME;
                ProcessNodeInfo nodeInfo = new ProcessNodeInfo(nodeId, processScopeNodeId, source, timeRelativeToStart, taskName, resources, transition);
                model.addNodeInfo(processModel, processInstance, nodeInfo);
            }
        }
    }
    TimeInstant timeInstant = getTimeInstant(dateTime);
    return timeInstant;
}
Also used : ProcessModel(de.hpi.bpt.scylla.model.process.ProcessModel) ResourceObject(de.hpi.bpt.scylla.simulation.ResourceObject) DayOfWeek(java.time.DayOfWeek) ResourceInfo(de.hpi.bpt.scylla.logger.ResourceInfo) LocalTime(java.time.LocalTime) ProcessNodeInfo(de.hpi.bpt.scylla.logger.ProcessNodeInfo) ZonedDateTime(java.time.ZonedDateTime) ProcessNodeTransitionType(de.hpi.bpt.scylla.logger.ProcessNodeTransitionType) ResourceStatus(de.hpi.bpt.scylla.logger.ResourceStatus) ProcessInstance(de.hpi.bpt.scylla.simulation.ProcessInstance) TimetableItem(de.hpi.bpt.scylla.model.global.resource.TimetableItem) SimulationModel(de.hpi.bpt.scylla.simulation.SimulationModel) TimeInstant(desmoj.core.simulator.TimeInstant) HashSet(java.util.HashSet)

Example 8 with TimetableItem

use of de.hpi.bpt.scylla.model.global.resource.TimetableItem in project scylla by bptlab.

the class SimulationUtils method scheduleNextResourceAvailableEvent.

/**
 * Creates and schedules a DesmoJ event which represents a resource instance which returns from idle.
 *
 * @param model
 *            the simulation model
 * @param resourceObject
 *            the resource instance returning from idle
 * @param currentDateTime
 *            the current date time
 * @param currentlyInTimetableItem
 *            true if the resource instance is currently active
 */
public static void scheduleNextResourceAvailableEvent(SimulationModel model, ResourceObject resourceObject, ZonedDateTime currentDateTime, boolean currentlyInTimetableItem) {
    boolean showInTrace = model.traceIsOn();
    TimeUnit timeUnit = DateTimeUtils.getReferenceTimeUnit();
    long currentTime = DateTimeUtils.getTimeInstant(currentDateTime).getTimeRounded(timeUnit);
    List<TimetableItem> timetable = resourceObject.getTimetable();
    if (timetable == null) {
        return;
    }
    int index = DateTimeUtils.getTimeTableIndexWithinOrNext(currentDateTime, timetable);
    if (currentlyInTimetableItem) {
        index++;
        if (index == timetable.size()) {
            index = 0;
        }
    }
    TimetableItem nextTimetableItem = timetable.get(index);
    DayOfWeek weekday = nextTimetableItem.getWeekdayFrom();
    LocalTime time = nextTimetableItem.getBeginTime();
    ZonedDateTime nextDateTime = DateTimeUtils.getNextZonedDateTime(currentDateTime, weekday, time);
    long durationToNextResourceAvailableEvent = DateTimeUtils.getDuration(currentDateTime, nextDateTime);
    if (model.getEndDateTime() != null) {
        long endTimeRelativeToGlobalStart = DateTimeUtils.getDuration(model.getStartDateTime(), model.getEndDateTime());
        if (currentTime + durationToNextResourceAvailableEvent >= endTimeRelativeToGlobalStart) {
            return;
        }
    }
    ResourceAvailabilityEvent event = new ResourceAvailabilityEvent(model, resourceObject, showInTrace);
    event.schedule(new TimeSpan(durationToNextResourceAvailableEvent, timeUnit));
}
Also used : TimeSpan(desmoj.core.simulator.TimeSpan) DayOfWeek(java.time.DayOfWeek) LocalTime(java.time.LocalTime) ZonedDateTime(java.time.ZonedDateTime) TimeUnit(java.util.concurrent.TimeUnit) ResourceAvailabilityEvent(de.hpi.bpt.scylla.simulation.event.ResourceAvailabilityEvent) TimetableItem(de.hpi.bpt.scylla.model.global.resource.TimetableItem)

Example 9 with TimetableItem

use of de.hpi.bpt.scylla.model.global.resource.TimetableItem in project scylla by bptlab.

the class GlobalConfigurationParser method parse.

@Override
public GlobalConfiguration parse(Element rootElement) throws ScyllaValidationException {
    System.out.println(rootElement.getNamespace());
    Iterator<EventOrderType> eventOrderTypesIterator = PluginLoader.dGetPlugins(EventOrderType.class);
    // ServiceLoader.load(EventOrderType.class).iterator();
    // Get all event order type plugins and store them in eventOrderTypes
    Map<String, EventOrderType> eventOrderTypes = new HashMap<String, EventOrderType>();
    while (eventOrderTypesIterator.hasNext()) {
        EventOrderType eot = eventOrderTypesIterator.next();
        eventOrderTypes.put(eot.getName(), eot);
    }
    Namespace bsimNamespace = rootElement.getNamespace();
    List<Element> globalConfigurationElements = rootElement.getChildren(null, bsimNamespace);
    String globalConfId = rootElement.getAttributeValue("id");
    Long randomSeed = null;
    ZoneId zoneId = ZoneId.of("UTC");
    Map<String, Resource> resources = new HashMap<String, Resource>();
    List<EventOrderType> resourceAssignmentOrder = new ArrayList<EventOrderType>();
    // resourceId:[instanceName:timetableId]
    Map<String, Map<String, String>> resourcesToTimetableIds = new HashMap<String, Map<String, String>>();
    Map<String, List<TimetableItem>> timetables = new HashMap<String, List<TimetableItem>>();
    for (Element el : globalConfigurationElements) {
        String elementName = el.getName();
        if (isKnownElement(elementName)) {
            if (el.getText().isEmpty()) {
                continue;
            }
            if (elementName.equals("resourceAssignmentOrder")) {
                String resourceAssignmentOrderString = el.getText();
                String[] orderTypeArray = resourceAssignmentOrderString.split(",");
                for (String orderTypeName : orderTypeArray) {
                    if (orderTypeName.isEmpty()) {
                        continue;
                    }
                    EventOrderType eventOrderType = eventOrderTypes.get(orderTypeName);
                    if (eventOrderType == null) {
                        throw new ScyllaValidationException("Event order type " + orderTypeName + " for resource assignment is unknown.");
                    }
                    resourceAssignmentOrder.add(eventOrderType);
                }
            } else if (elementName.equals("randomSeed")) {
                randomSeed = Long.parseLong(el.getText());
            } else if (elementName.equals("zoneOffset")) {
                zoneId = ZoneId.of("GMT" + el.getText());
            } else if (elementName.equals("resourceData")) {
                List<Element> rDataElements = el.getChildren();
                for (Element elem : rDataElements) {
                    String resourceId = elem.getAttributeValue("id");
                    String rDataElementName = elem.getName();
                    if (rDataElementName.equals("dynamicResource")) {
                        String resourceName = elem.getAttributeValue("name");
                        Integer defaultQuantity = Integer.valueOf(elem.getAttributeValue("defaultQuantity"));
                        Double defaultCost = Double.valueOf(elem.getAttributeValue("defaultCost"));
                        TimeUnit defaultTimeUnit = TimeUnit.valueOf(elem.getAttributeValue("defaultTimeUnit"));
                        DynamicResource dynamicResource = new DynamicResource(resourceId, resourceName, defaultQuantity, defaultCost, defaultTimeUnit);
                        String defaultTimetableId = elem.getAttributeValue("defaultTimetableId");
                        if (resourcesToTimetableIds.containsKey(resourceId)) {
                            throw new ScyllaValidationException("Multiple resource definitions: " + resourceId);
                        }
                        resourcesToTimetableIds.put(resourceId, new HashMap<String, String>());
                        Map<String, DynamicResourceInstance> resourceInstances = dynamicResource.getResourceInstances();
                        List<Element> instanceElements = elem.getChildren("instance", bsimNamespace);
                        // fill up list of resource instances if not explicitly defined
                        if (instanceElements.size() > defaultQuantity) {
                            throw new ScyllaValidationException("Too many instances defined for resource " + resourceId);
                        }
                        int numberOfDefaultInstances = defaultQuantity - instanceElements.size();
                        for (int i = 0; i < numberOfDefaultInstances; i++) {
                            String name = "#" + i;
                            DynamicResourceInstance instance = new DynamicResourceInstance(defaultCost, defaultTimeUnit);
                            resourceInstances.put(name, instance);
                            if (defaultTimetableId != null) {
                                resourcesToTimetableIds.get(resourceId).put(name, defaultTimetableId);
                            }
                        }
                        // parse defined resource instances
                        for (Element element : instanceElements) {
                            String name = element.getAttributeValue("name");
                            if (name == null) {
                                throw new ScyllaValidationException("Resource instance of type " + resourceId + " does not have name.");
                            }
                            Double cost;
                            if (element.getAttributeValue("cost") == null) {
                                cost = defaultCost;
                            } else {
                                cost = Double.valueOf(element.getAttributeValue("cost"));
                            }
                            TimeUnit timeUnit;
                            if (element.getAttributeValue("timeUnit") == null) {
                                timeUnit = defaultTimeUnit;
                            } else {
                                timeUnit = TimeUnit.valueOf(element.getAttributeValue("timeUnit"));
                            }
                            DynamicResourceInstance instance = new DynamicResourceInstance(cost, timeUnit);
                            if (resourceInstances.containsKey(name)) {
                                throw new ScyllaValidationException("Duplicate resource instance: " + name);
                            }
                            resourceInstances.put(name, instance);
                            String timetableId = element.getAttributeValue("timetableId");
                            if (timetableId != null) {
                                resourcesToTimetableIds.get(resourceId).put(name, timetableId);
                            }
                        }
                        resources.put(resourceId, dynamicResource);
                    } else {
                        DebugLogger.log("Element " + elem.getName() + " of resource data is expected to be known, but not supported.");
                    }
                }
            } else if (elementName.equals("timetables")) {
                List<Element> tElements = el.getChildren("timetable", bsimNamespace);
                for (Element tElement : tElements) {
                    String timetableId = tElement.getAttributeValue("id");
                    List<TimetableItem> items = new ArrayList<TimetableItem>();
                    List<Element> tItemElements = tElement.getChildren("timetableItem", bsimNamespace);
                    for (Element tItemElement : tItemElements) {
                        DayOfWeek weekdayFrom = DayOfWeek.valueOf(tItemElement.getAttributeValue("from"));
                        DayOfWeek weekdayTo = DayOfWeek.valueOf(tItemElement.getAttributeValue("to"));
                        LocalTime beginTime = LocalTime.parse(tItemElement.getAttributeValue("beginTime"));
                        LocalTime endTime = LocalTime.parse(tItemElement.getAttributeValue("endTime"));
                        // TODO check for overlapping timetable items and handle them
                        if (DateTimeUtils.compareWeekdayTime(weekdayFrom, beginTime, weekdayTo, endTime) != 0) {
                            if (weekdayFrom.compareTo(weekdayTo) > 0) {
                                // e.g. FRIDAY to MONDAY
                                TimetableItem item = new TimetableItem(weekdayFrom, DayOfWeek.SUNDAY, beginTime, LocalTime.MAX);
                                items.add(item);
                                item = new TimetableItem(DayOfWeek.MONDAY, weekdayTo, LocalTime.MIN, endTime);
                                items.add(item);
                            } else {
                                TimetableItem item = new TimetableItem(weekdayFrom, weekdayTo, beginTime, endTime);
                                items.add(item);
                            }
                        }
                    }
                    timetables.put(timetableId, items);
                }
            }
        } else {
            DebugLogger.log("Element " + el.getName() + " of global configuration is not supported.");
        }
    }
    // match timetables (if any available) and resource data (if any available)s
    for (String resourceId : resourcesToTimetableIds.keySet()) {
        Map<String, String> resourceInstanceIdToTimetableIds = resourcesToTimetableIds.get(resourceId);
        for (String resourceInstanceName : resourceInstanceIdToTimetableIds.keySet()) {
            String timetableId = resourceInstanceIdToTimetableIds.get(resourceInstanceName);
            if (!timetables.containsKey(timetableId)) {
                DebugLogger.log("Timetable " + timetableId + " not found.");
            }
            List<TimetableItem> timetable = timetables.get(timetableId);
            Resource resource = resources.get(resourceId);
            if (resource instanceof DynamicResource) {
                DynamicResource dResource = (DynamicResource) resource;
                dResource.getResourceInstances().get(resourceInstanceName).setTimetable(timetable);
            }
        }
    }
    if (resources.isEmpty()) {
        throw new ScyllaValidationException("No resource data definitions in file.");
    }
    if (randomSeed == null) {
        Random random = new Random();
        randomSeed = random.nextLong();
    }
    DebugLogger.log("Random seed for whole simulation (if not overriden by simulation configuration): " + randomSeed);
    GlobalConfiguration globalConfiguration = new GlobalConfiguration(globalConfId, zoneId, randomSeed, resources, resourceAssignmentOrder);
    return globalConfiguration;
}
Also used : HashMap(java.util.HashMap) Element(org.jdom2.Element) ArrayList(java.util.ArrayList) ScyllaValidationException(de.hpi.bpt.scylla.exception.ScyllaValidationException) Random(java.util.Random) DynamicResourceInstance(de.hpi.bpt.scylla.model.global.resource.DynamicResourceInstance) TimeUnit(java.util.concurrent.TimeUnit) ArrayList(java.util.ArrayList) List(java.util.List) TimetableItem(de.hpi.bpt.scylla.model.global.resource.TimetableItem) DayOfWeek(java.time.DayOfWeek) GlobalConfiguration(de.hpi.bpt.scylla.model.global.GlobalConfiguration) ZoneId(java.time.ZoneId) LocalTime(java.time.LocalTime) EventOrderType(de.hpi.bpt.scylla.plugin_type.parser.EventOrderType) DynamicResource(de.hpi.bpt.scylla.model.global.resource.DynamicResource) Resource(de.hpi.bpt.scylla.model.global.resource.Resource) Namespace(org.jdom2.Namespace) DynamicResource(de.hpi.bpt.scylla.model.global.resource.DynamicResource) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

TimetableItem (de.hpi.bpt.scylla.model.global.resource.TimetableItem)9 DayOfWeek (java.time.DayOfWeek)5 LocalTime (java.time.LocalTime)5 ZonedDateTime (java.time.ZonedDateTime)4 ArrayList (java.util.ArrayList)3 TimeUnit (java.util.concurrent.TimeUnit)3 DynamicResource (de.hpi.bpt.scylla.model.global.resource.DynamicResource)2 DynamicResourceInstance (de.hpi.bpt.scylla.model.global.resource.DynamicResourceInstance)2 Resource (de.hpi.bpt.scylla.model.global.resource.Resource)2 HashSet (java.util.HashSet)2 ScyllaValidationException (de.hpi.bpt.scylla.exception.ScyllaValidationException)1 ProcessNodeInfo (de.hpi.bpt.scylla.logger.ProcessNodeInfo)1 ProcessNodeTransitionType (de.hpi.bpt.scylla.logger.ProcessNodeTransitionType)1 ResourceInfo (de.hpi.bpt.scylla.logger.ResourceInfo)1 ResourceStatus (de.hpi.bpt.scylla.logger.ResourceStatus)1 GlobalConfiguration (de.hpi.bpt.scylla.model.global.GlobalConfiguration)1 ProcessModel (de.hpi.bpt.scylla.model.process.ProcessModel)1 EventOrderType (de.hpi.bpt.scylla.plugin_type.parser.EventOrderType)1 ProcessInstance (de.hpi.bpt.scylla.simulation.ProcessInstance)1 ResourceObject (de.hpi.bpt.scylla.simulation.ResourceObject)1