// window.B2_top.Circle(Widget.GREEN, true, 20, 10, 50);
// window.B2_top.category = Widget.CATEGORY_ENTITY;
// CATEGORY_UNSEL_ALL
// CATEGORY_SEL_ALL// - green
// CATEGORY_UPDATE
// GETEGORY_GENERIC_2 //latent
import { OccupantPhysiology, OccupantProduct } from "./occupant.mjs";
import { OccupantVersion } from "./occupant_version.mjs";
import { WorkflowOccupant } from "./workflow_occupant.mjs";
export { ProtocolVehicle, VehicleOccupant };
class ProtocolVehicle {
/**
* Class to define a Vehicle with Occupants that can occupy each seat
* @param {VehicleOccupant} driver array of OccupantProduct names in driver seat
* @param {VehicleOccupant} front array of OccupantProduct names in front seat
* @param {VehicleOccupant} behind_driver array of OccupantProduct names in behind_driver seat
* @param {VehicleOccupant} behind_front array of OccupantProduct names in behind_front seat
* @param {VehicleOccupant} middle array of OccupantProduct names in middle seat
* @example
* let vehicle = new ProtocolVehicle(driver, front, behind_driver, behind_front, middle);
*/
constructor(driver, front, behind_driver, behind_front, middle) {
this.driver = driver;
this.front = front;
this.behind_driver = behind_driver;
this.behind_front = behind_front;
this.middle = middle;
}
/** driver occupant names array
* @type {VehicleOccupant} */
get driver() {
return this._driver;
}
set driver(new_driver) {
this._driver = new_driver;
}
/** front occupant names array
* @type {VehicleOccupant} */
get front() {
return this._front;
}
set front(new_front) {
this._front = new_front;
}
/** behind_driver occupant names array
* @type {VehicleOccupant} */
get behind_driver() {
return this._behind_driver;
}
set behind_driver(new_behind_driver) {
this._behind_driver = new_behind_driver;
}
/** behind_front occupant names array
* @type {VehicleOccupant} */
get behind_front() {
return this._behind_front;
}
set behind_front(new_behind_front) {
this._behind_front = new_behind_front;
}
/** middle occupant names array
* @type {VehicleOccupant} */
get middle() {
return this._middle;
}
set middle(new_middle) {
this._middle = new_middle;
}
/**
* @typedef {Object} ProductPhysiology
* @property {string} product Occupant product type
* @property {string} physiology Occupant physiology
*/
/**
* @typedef {Object} ProtocolVehicleJSON
* @property {ProductPhysiology} driver Occupant product and physiology in driver seat
* @property {ProductPhysiology} front Occupant product and physiology in front seat
* @property {ProductPhysiology} behind_driver Occupant product and physiology in behind_driver seat
* @property {ProductPhysiology} behind_front Occupant product and physiology in behind_front seat
* @property {ProductPhysiology} middle Occupant product and physiology in middle seat
*/
/**
* constrcut a ProtocolVehicle from JSON
* @param {ProtocolVehicleJSON} json
* @return {ProtocolVehicle}
*/
static FromJSON(json) {
let vehicle = new ProtocolVehicle(
new VehicleOccupant(
WorkflowOccupant.DRIVER,
WorkflowOccupant.LEFT,
WorkflowOccupant.FRONT,
json.driver.product,
json.driver.physiology
),
new VehicleOccupant(
WorkflowOccupant.PASSENGER,
WorkflowOccupant.RIGHT,
WorkflowOccupant.FRONT,
json.front.product,
json.front.physiology
),
new VehicleOccupant(
WorkflowOccupant.PASSENGER,
WorkflowOccupant.LEFT,
WorkflowOccupant.REAR,
json.behind_driver.product,
json.behind_driver.physiology
),
new VehicleOccupant(
WorkflowOccupant.PASSENGER,
WorkflowOccupant.RIGHT,
WorkflowOccupant.REAR,
json.behind_front.product,
json.behind_front.physiology
),
new VehicleOccupant(
WorkflowOccupant.PASSENGER,
WorkflowOccupant.MIDDLE,
WorkflowOccupant.REAR,
json.middle.product,
json.middle.physiology
)
);
return vehicle;
}
/**
* get array of all the VehicleOccupants in the ProtocolVehicle
* @returns {VehicleOccupant[]}
* @example
* let occupants = this.Occupants();
*/
Occupants() {
let vehicle = this;
return [vehicle.driver, vehicle.behind_driver, vehicle.front, vehicle.behind_front, vehicle.middle];
}
/**
* get array of all the VehicleOccupants in the ProtocolVehicle
*/
/**
* returns an array of valid (non-empty) VehicleOccupants that match all the passed criteria for position
* side and front_rear.
* Note that null can be passed for any of these criteria and it will not filter on that property
* Note also that zero length array is returned if no matching occupants found
* @param {?string} [position = null] Workflowoccupant.DRIVER or WorkflowOccupant.PASSENGER
* @param {?string} [front_rear = null] front or rear row seat
* @param {?string} [side = null] WorkflowOccupant.LEFT, WorkflowOccupant.RIGHT or WorkflowOccupant.MIDDLE
* @param {string} [drive_side = VehicleOccupant.LHD] VehicleOccupant.LHD by default, but can set to VehicleOccupant.RHD. This is only used if side is not null
* @returns {VehicleOccupant[]}
* @example
* let occupants = this.OnlyOccupants(WorkflowOccupant.PASSENGER, WorkflowOccupant.REAR);
*/
OnlyOccupants(position = null, front_rear = null, side = null, drive_side = VehicleOccupant.LHD) {
let occupants = this.Occupants();
let output_occupants = [];
for (let occupant of occupants) {
if (!occupant.Empty()) {
if (position != null) {
if (occupant.position != position) {
continue;
}
}
if (front_rear != null) {
if (occupant.front_rear != front_rear) {
continue;
}
}
if (side != null) {
if (occupant.GetSide(drive_side) != side) {
continue;
}
}
output_occupants.push(occupant);
}
}
return output_occupants;
}
}
class VehicleOccupant {
/**
* this class holds vehicle occupant data from the protocol json file
* it also adds meta data e.g. side and position. Positions assume
* left-hand drive (LHD) by default, but GetPosition method can be used
* to return the correct positions if vehicle is right-hand drive (RHD).
*/
/**
*
* @param {string} position
* @param {string} side assumed WorkflowOccupant.LEFT
* @param {string} front_rear
* @param {?string} product taken from JSON
* @param {?string} physiology taken from JSON
* @example let driver = new VehicleOccupant(
WorkflowOccupant.DRIVER,
WorkflowOccupant.LEFT,
WorkflowOccupant.FRONT,
json.driver.product,
json.driver.physiology
)
*/
constructor(position, side, front_rear, product, physiology) {
this.position = position;
this.side = side;
this.front_rear = front_rear;
this.product = product;
this.physiology = physiology;
}
/** Left-hand drive (LHD) constant
* @type {string} */
static get LHD() {
return "LHD";
}
/** Right-hand drive (RHD) constant
* @type {string} */
static get RHD() {
return "RHD";
}
/**
* if the hand drive is valid returns the value passed, otherwise prints warning and return VehicleOccupant.LHD
* @param {string} drive_side
* @returns {string}
*/
static GetValidHandDrive(drive_side) {
if (drive_side == VehicleOccupant.LHD || drive_side == VehicleOccupant.RHD) return drive_side;
WarningMessage(
`Vehicle hand drive ${drive_side} was not valid so cannot be set. Defaulting to ${VehicleOccupant.LHD}`
);
return VehicleOccupant.LHD;
}
/**
* occupant may be empty if either product or physiology are null
* @returns {boolean} empty
*/
Empty() {
if (this.position && this.physiology) return false;
return true;
}
/**
* Occupant position constant
* @type {string} */
get position() {
return this._position;
}
set position(new_position) {
if (WorkflowOccupant.Positions().indexOf(new_position) == -1) {
throw new Error(`Invalid position: ${new_position} in VehicleOccupant constructor`);
}
this._position = new_position;
}
/**
* Occupant side setter (no getter as need to use member function GetSide(<drive_side>))
* @param {string} new_side */
set side(new_side) {
if (WorkflowOccupant.Sides().indexOf(new_side) == -1) {
throw new Error(`Invalid side: ${new_side} in VehicleOccupant constructor`);
}
this._side = new_side;
}
/**
* Occupant front/Rear constant
* @type {string} */
get front_rear() {
return this._front_rear;
}
set front_rear(new_front_rear) {
if (WorkflowOccupant.FrontRear().indexOf(new_front_rear) == -1) {
throw new Error(`Invalid front_rear: ${new_front_rear} in VehicleOccupant constructor`);
}
this._front_rear = new_front_rear;
}
/** Occupant product
* @type {?string|undefined} */
get product() {
return this._product;
}
set product(new_product) {
if (!new_product) new_product = null;
else if (!OccupantProduct.Valid(new_product)) {
throw new Error(`Invalid product ${new_product} in VehicleOccupant constructor`);
}
this._product = new_product;
}
/** Occupant physiology
* @type {?string|undefined} */
get physiology() {
return this._physiology;
}
set physiology(new_physiology) {
if (!new_physiology) new_physiology = null;
else if (!OccupantPhysiology.Valid(new_physiology)) {
throw new Error(`Invalid physiology ${new_physiology} in VehicleOccupant constructor`);
}
this._physiology = new_physiology;
}
/**
* Get the side of an occupant for a given drive side (LHD or RHD)
* @param {string} [drive_side = VehicleOccupant.LHD] VehicleOccupant.LHD (default) or VehicleOccupant.RHD
* @returns {string}
*/
GetSide(drive_side = VehicleOccupant.LHD) {
// Middle is always middle regardless of drive_side
if (this._side == WorkflowOccupant.MIDDLE) return this._side;
// If LHD, return occupant side unaltered
if (drive_side == VehicleOccupant.LHD) return this._side;
// If RHD, return the opposite
if (this._side == WorkflowOccupant.LEFT) return WorkflowOccupant.RIGHT;
return WorkflowOccupant.LEFT;
}
/**
* returns an array of valid (supported) occupant names corresponding to
* the occupant product and physiology properties
* @returns {string[]} occupant names array
*/
GetOccupantNames() {
return OccupantVersion.GetOnly("ALL", this.product, this.physiology);
}
}