// module: True
/* Class to represent a OccupantVersion version*/
import { find_all_json_files } from "./file_helper.mjs";
import { Occupant, OccupantProduct, OccupantSupplier, OccupantPhysiology } from "./occupant.mjs";
import { JSPath } from "./path.mjs";
class OccupantVersion {
/**
* Class to store supported Occupant versions with getters for
* product names based on supplier and product. It is not instantiable. It behaves like a singleton
* where the files should only be imported once.
*
* if we want to reimport the json files we simply need to call OccupantVersion.importAllOccupantJSONFiles()
* again and it will overwrite this._occupants property returned by OccupantVersion.occupants
*/
/** Occupants from json files
* @type {Occupant[]} */
static get occupants() {
if (!this._occupants) OccupantVersion.importAllOccupantJSONFiles();
return this._occupants;
}
/**
* This function scrapes the Occupant directory for the Occupant json files
* and imports the data for them. It also checks that the JSON files are all valid and
* skips them if they are not (printing out a warning message)
*/
static importAllOccupantJSONFiles() {
this._occupants = [];
var occupants_directory = JSPath.GetOccupantsDirectory();
try {
//throw an error if it cannot find the occupants folder. This may be because user has moved it.
if (!File.Exists(occupants_directory)) {
throw new Error(`Could not find occupants directory here:\n${occupants_directory}`);
}
var file_list = find_all_json_files(occupants_directory);
//throw an error if it cannot find the any occupant json files.
if (file_list.length == 0) {
throw new Error(`Failed to find any occupant data json files in ${occupants_directory}`);
}
} catch (error) {
ErrorMessage(`${error}\nTerminate workflow`);
Exit();
}
let names = []; //store the names of added occupants so far
for (let filepath of file_list) {
let occupant;
try {
if (/\.json$/i.test(filepath)) {
occupant = Occupant.FromJSONFile(filepath);
if (occupant) {
if (names.indexOf(occupant.name) == -1) {
this.occupants.push(occupant);
names.push(occupant.name);
} else
WarningMessage(
`Failed to parse occupant data from ${filepath} as it was not unique so skipping file`
);
} else WarningMessage(`Failed to parse occupant data from ${filepath} so skipping file`);
//TODO write check for occupant (or add check to FromJSONFile and throw errors)
}
} catch (error) {
ErrorMessage(`${error} so skipping file ${filepath}`);
}
}
//return occupants;
}
// /* Static methods */
/**
* Returns an array of all the Occupant Versions. Equivalent to OccupantVersion.occupants
* @returns {Occupant[]}
* @example
* let occupants = OccupantVersion.GetAll();
*/
static GetAll() {
return OccupantVersion.occupants;
}
/**
* Returns an array of all the Occupant Version names
* @returns {string[]}
* @example
* let occupant_names = OccupantVersion.GetAllNames();
*/
static GetAllNames() {
let occupants = OccupantVersion.GetAll();
let names = [];
for (let occupant of occupants) {
names.push(occupant.name);
}
return names;
}
/**
* Returns the Occupant Version matching the name
* @param {string} name
* @returns {Occupant}
* @example
* let occupant = OccupantVersion.GetFromName("Humanetics SID IIs SBLD v.4.3.1");
*/
static GetFromName(name) {
let occupants = OccupantVersion.GetAll();
for (let occupant of occupants) {
if (occupant.name == name) {
return occupant;
}
}
throw new Error(`Unsupported version name ${name} in GetFromName`);
}
/**
* Returns an array of all the Occupant Version names made by the supplier
* @param {string} supplier
* @returns {string[]} supplier names
* @example
* let supplier_names = OccupantVersion.GetOnlySupplier(OccupantSupplier.ATD);
*/
static GetOnlySupplier(supplier) {
let versions = OccupantVersion.GetAll();
let names = [];
if (!OccupantSupplier.Valid(supplier)) {
throw new Error(`Invalid supplier ${supplier} in GetOnlySupplier`);
}
for (let version of versions) {
if (version.supplier == supplier) {
names.push(version.name);
}
}
return names;
}
/**
* The user data object in the workflow file
* @typedef {Object} Filters
* @property {string[]} suppliers list of valid suppliers
* @property {string[]} products list of valid products
* @property {string[]} physiologies list of valid physiologies
*/
/**
* Returns an object of the valid filters for supplier, product, and physiology of all the Occupant Version names that are passes
* @param {string[]} version_names
* @returns {Filters} of {suppliers:[], products:[], physiologies:[]}
* @example
* let filters = OccupantVersion.GetValidFilters(version_names);
*/
static GetValidFilters(version_names) {
let version;
// "all" is always a valid filter
let suppliers = ["all"];
let products = ["all"];
let physiologies = ["all"];
for (let name of version_names) {
version = OccupantVersion.GetFromName(name);
suppliers.push(version.supplier);
products.push(version.product);
physiologies.push(version.physiology);
}
return {
//set strips out duplicates and spread operator converts set back to array
//note cannot use Set class as PRIMER uses Set class
suppliers: suppliers, //[...new Set(suppliers)],
products: products, //[...new Set(products)],
physiologies: physiologies // [...new Set(physiologies)]
};
}
/**
* Returns an array of all the Occupant Version names of type product
* @param {string} product
* @returns {string[]}
* @example
* let product_names = OccupantVersion.GetOnlyProduct(OccupantProduct.HIII);
*/
static GetOnlyProduct(product) {
let versions = OccupantVersion.GetAll();
let names = [];
if (!OccupantProduct.Valid(product)) {
throw new Error(`Invalid product ${product} in GetOnlyProduct`);
}
for (let version of versions) {
if (version.product == product) {
names.push(version.name);
}
}
return names;
}
/**
* Filter the versions that match the input params.
* Note that passing 'ALL' (or invalid value) for any parameter means that all occupant versions will be considered
* @param {string} supplier
* @param {string} product
* @param {string} physiology
* @returns {string[]} array of occupant names
* @example
* all_50thPercentileMale_hybrid3_products = OccupantVersion.GetOnly('ALL', OccupantProduct.HIII, OccupantPhysiology.M50);
*/
static GetOnly(supplier, product, physiology) {
let versions = OccupantVersion.GetAll();
let temp_versions = [];
if (OccupantSupplier.Valid(supplier)) {
for (let version of versions) {
if (version.supplier == supplier) {
temp_versions.push(version);
}
}
versions = temp_versions;
temp_versions = [];
}
if (OccupantProduct.Valid(product)) {
for (let version of versions) {
if (version.product == product) {
temp_versions.push(version);
}
}
versions = temp_versions;
temp_versions = [];
}
if (OccupantPhysiology.Valid(physiology)) {
for (let version of versions) {
if (version.physiology == physiology) {
temp_versions.push(version);
}
}
versions = temp_versions;
temp_versions = [];
}
let names = [];
for (let version of versions) {
names.push(version.name);
}
return names;
}
/*could add getter to filter on physiology,
*but at the momement there are not many so will stick with just supplier and product
*/
}
export { OccupantVersion };