© 2020 (CC BY) Gerd Wagner, Brandenburg University of Technology, Germany.
You can inspect the model's OESjs code on the OES GitHub repo.
A haul service company has resource pools for dump trucks and wheel loaders. While the activities go (back) to loading site, haul, dump and go home just require a truck (or a wheel loader) as a resource, load activities require both a truck and a wheel loader.
The potentially relevant object types are:
Potentially relevant types of events and activities are:
Both object types and event types, together with their participation associations, can be visually described in a conceptual information model in the form of a UML class diagram, as shown below.
Notice that the association end annotations «rr» and «rp» denote resource roles and resource pools. A haul service company has resource pools for trucks and wheel loaders. The activity types haul, dump and go back to loading site have a resource role truck for assigning a truck to any activity of one of those types. The activity types go to loading site and go home have either a a resource role truck or a resource role wheel loader, as indicated by the alternative association constraint expressed with a dashed line annotated with {xor}. The activity type load has both resource role truck and a resource role wheel loaders for assigning at least one and at most two wheel loaders to any load activity (as indicated by the multiplicity "1..2" at the «rr» association end at the class wheel loaders).
The involved types of events and activities can be related with each other via resource-dependent activity start arrows and event scheduling arrows, as shown in the following DPMN process diagram:
Notice that there are three types of arrows in this DPMN diagram:
The model shows that when a haul request comes in, the haul service company deploys multiple trucks and wheel loaders to the loading site, each of them performing a go to loading site activity, as indicated by the double arrow between the haul requests event circle and the go to loading site activity rectangle. Each of these activities leads to enqueuing a new planned load activity, as indicated by the resource-dependent activity start arrow from the go to loading site activity shape to the load activity shape. Such an enqueued (planned) activity is going to be dequeued and started as soon as the required resources become available. This means that as soon as a wheel loader is available, the next load activity is going to be started. When a load activity is completed, a haul activity and then a dump activity are going to start immediately, as indicated by the event scheduling arrows between them.
A more complete model prevents trucks to go back to the loading site and perform a load activity even when the job has been completed during the go back activity (resulting in haul and dump activities with an empty truck). For avoiding this uneconomic behavior, a second decision if the job has been done needs to be taken after the go back activity. In addition, the model has to describe that wheel loaders also go home when their job has been done. This is shown in the following refined model:
In our simulation design, we consider only one particular haul service company, which does not have to be modeled as an explicit object. Also, we abstract away from the fact that also wheel loaders have to go to, and return from, the loading site by assuming that they are already at the site when the dump trucks arrive.
In the information design model, we need to define a status attribute for all resource object types, such as Truck and WheelLoader, and a duration function, typically representing a random variable, for each activity type:
Notice how functions representing random
  variables, like the duration function of all activity types,
  are marked with the keyword (or UML 'stereotype') «rv» standing for "random
  variable". These random variable functions sample from a probability
  distribution function (PDF), which is symbolically indicated with
  expressions like Tri(30,50,40) standing for the triangular PDF with lower
  and upper bounds 30 and 50, and a median of 40. 
Each activity type is associated with Truck or WheelLoader as their resource role(s), indicated with the association end stereotype «rr» standing for "resource role".
In the process design model, we need to specify the state changes and follow-up events caused by events, including activity start and end events, and the constructor arguments for scheduling follow-up events, using model variables (possibly referencing resource pools), as shown in the following DPMN diagram:
The JavaScript-based simulator OESjs implements the Object Event Simulation paradigm, and, consequently, allows a straight-forward coding of OEM class models and DPMN process models.
For implementing the information design model, we have to code all object types, event types and activity types specified in the model in the form of classes.
The Truck
  object class can be coded with OESjs-Core2 in the following way:
class Truck extends oBJECT {
  constructor({ id, name, status}) {
    super( id, name);  // invoke the oBJECT constructor
    this.status = status;
  }
}
// a class-level attribute
Truck.capacity = 15;  // m3All object classes inherit an
  id attribute and a name attribute from the
  pre-defined OES foundation class oBJECT. Since trucks are
  resource objects, we need to define a status property for them.
  We also define a class-level attribute capacity for modeling
  their load capacity, assuming that all trucks have the same
  capacity.
The WheelLoader object class is coded in the same way as Truck.
The
  HaulRequest event class can be coded in the following
  way:
class HaulRequest extends eVENT {
  constructor({ occTime, delay, quantity}) {
    super({occTime, delay});
    this.quantity = quantity;
  }
  onEvent() {
    ...
  }
}All event classes inherit an occTime attribute and a
  delay attribute from the pre-defined OES foundation class
  eVENT. Any event in OES can be created either with a value for
  the attribute occTime (standing for occurrence time)
  or with a value for the attribute delay. In the latter case,
  the event's occurrence time is automatically derived by adding the value of
  delay to the current simulation time. In addition, the
  HaulRequest event class has a property quantity for
  specifying the quantity to be hauled.. 
The onEvent
  method of the HaulRequest event class is not part of the information
  design model. Rather, it is implementing an event rule specified in the
  process design model. Consequently, it will be discussed below.
The GoToLoadingSite activity class can be coded in the following way:
class GoToLoadingSite extends aCTIVITY {
  constructor({id, startTime, duration}={}) {
    super({id, startTime, duration});
  }
  static duration() {return rand.triangular( 30, 50, 40);}
}
GoToLoadingSite.resourceRoles = {
  "truck": {range: Truck}
}All activity classes inherit the attributes id,
  startTime and duration from the pre-defined OES
  foundation class aCTIVITY. When an activity is created as a JS
  object during a simulation run, the value of its duration
  property is obtained by invoking the duration() function
  defined as a class-level ("static") function for its activity class. These
  activity duration functions typically implement a random variable by
  invoking a random variate sampling function, such as
  rand.triangular(30,50,40), which samples from the triangular
  probability distribution function (with min/max=30/50 and
  mode=40).
Notice how the resource role association between
  GoToLoadingSite and Truck, which defines the resource
  reference property GoToLoadingSite::truck, is coded by a
  corresponding entry in the map-valued class-level property
  resourceRoles.
A
  DPMN process design model can be decomposed into a set of event rule design
  models, one for each type of event specified in the design model. Starting
  with the HaulRequest event rule design model, we show how the
  event rules specified by each of these event rule design models can be coded
  in the form of an onEvent method.
HaulRequest event rule.In the following
  HaulRequest event rule method onEvent, all
  available trucks are allocated to the current haul request, and, after
  computing the number of loads, for each of the allocated trucks a new
  GoToLoadingSite activity is started:
class HaulRequest extends eVENT {
  ...
  onEvent() {
    const followupEvents=[],
          allocatedTrucks = sim.resourcePools["trucks"].allocateAll();
    // assign model variable
    sim.model.v.nmrOfLoads = Math.ceil( this.quantity / Truck.capacity);
    for (const t of allocatedTrucks) {
      const goActy = new GoToLoadingSite();
      // assign truck as required resource
      goActy.truck = t;
      // start GoToLoadingSite activity
      followupEvents.push( new aCTIVITYsTART({plannedActivity: goActy}));
    }
    return followupEvents;
  }
}Since activities are composite events, we also have event rules for them. The following GoToLoadingSite event rule is triggered whenever a GoToLoadingSite activity is completed, since the completion of an activity counts as its occurrence event.
GoToLoadingSite event rule.This rule states that whenever a GoToLoadingSite activity ends (or is completed), then a new planned Load activity is enqueued, if no wheel loader is available, or, otherwise, a new Load activity is started. In OESjs, it is coded in the following declarative way:
GoToLoadingSite.successorActivity = "Load"
Such a successor activity assignment allows the simulator to check if the required resources are available and then start the successor activity, or, otherwise, enqueue a new planned successor activity.
Load
  event rule.This rule states that whenever a Load activity ends, the model variable nmrOfLoads is decremented by 1, and a Haul activity is immediately started (as a successor activity). Since the Haul activity doesn't require any additional resources, there is no need to enqueue a planned activity and wait for the availability of resources. In OESjs, this rule is coded in the following way:
class Load extends aCTIVITY {
  ...
  onActivityEnd() {
    const followupEvents = [];
    // decrement nmrOfLoads counter
    sim.model.v.nmrOfLoads--;
    return followupEvents;
  }
  ...
}
Load.successorActivity = "Haul";Notice that the state change
  expressed in the modelVariables object rectangle, the decrementation
  of nmrOfLoads, is taken care of in the onActivityEnd
  method of the Load activity class. Instead of explicitly
  scheduling the start of the succeeding Haul activity in that
  method, we simply define Haul to be the successor activity of
  Load.
Haul event rule.The Haul event rule states that whenever a Haul activity ends, it is immediately succeeded by a Dump activity. It is coded in the following way:
Haul.successorActivity = "Dump";
Dump event rule.The Dump event rule states that when a Dump activity ends and the model variable nmrOfLoads has the value 0, it is immediately succeeded by a GoHome activity, otherwise it is immediately succeeded by a GoBackToLoadingSite activity. The rule is coded by defining the successor activity as a function returning either "GoBackToLoadingSite" or "GoHome" in the following way:
Dump.successorActivity = function () {
  return sim.model.v.nmrOfLoads === 0 ? "GoHome":"GoBackToLoadingSite";
}GoBackToLoadingSite event rule.The GoBackToLoadingSite event rule states that when a GoBackToLoadingSite activity ends and the model variable nmrOfLoads still has a value greater than 0, a new planned Load activity is enqueued; otherwise a GoHome activity is immediately started. The rule is coded by defining the successor activity of GoBackToLoadingSite as a function returning either "Load" or "GoHome" in the following way:
GoBackToLoadingSite.successorActivity = function () {
  return sim.model.v.nmrOfLoads > 0 ? "Load":"GoHome";
}