pre/add_new_occupant_version_helper.js

/**
file:///C:/Oasys%2020%20Nightly/workflows/scripts/automotive_assessments/docs/pre/index.html

*/

let occupant_mjs = "C:\\Oasys 20 Nightly\\workflows\\scripts\\automotive_assessments\\modules\\shared\\occupant.mjs";
let occupant_mjs_temp =
    "C:\\Oasys 20 Nightly\\workflows\\scripts\\automotive_assessments\\modules\\shared\\occupant_temp.mjs";

let supplier = "HUMANETICS"; //ATD, HUMANETICS, LSTC, DYNAMORE, PDB
let model = "HIII"; // HIII, THOR, ES2, SID_IIS_D, WS
let percentile = "50"; //5, 50, 95
let type = "Male"; //male/female/child
let version = "1.5.1";
let occupant_version_csv_name = "Humanetics HIII 50M v1.5.1.csv";

let EntitiesMatchStrings = {};

EntitiesMatchStrings.Head = "OccupantEntity.NODE";
EntitiesMatchStrings.Neck = "OccupantEntity.XSECTION";
EntitiesMatchStrings.Chest = '"ET"';
EntitiesMatchStrings.Femur = "OccupantEntity.BEAM_BASIC";
EntitiesMatchStrings.Knee = "OccupantEntity.SPRING";
EntitiesMatchStrings.Tibia = "OccupantEntity.BEAM_BASIC";
EntitiesMatchStrings.Foot = "OccupantEntity.NODE";

//WSID and SID SBDL
EntitiesMatchStrings.Shoulder = "OccupantEntity.BEAM_BASIC"; // || "OccupantEntity.SPRING";

//WSID
EntitiesMatchStrings.Lumbar = "OccupantEntity.BEAM_BASIC";
EntitiesMatchStrings.Abdomen = "OccupantEntity.SPRING";

//THOR
EntitiesMatchStrings.Abdomen = "OccupantEntity.NODE";

let occupant_version_getter_function_name = `${supplier}_${model}_${percentile}_${type.substr(0, 1)}_V${version.replace(
    /\./g,
    "_"
)}`;
let occupant_version_getter_function_comment = `V${version} ${supplier} ${model} ${percentile}th Percentile ${type}`;
//user can override the occupant_version_getter_function_name

// read occupant mjs file

let f, line;
f = new File(occupant_mjs, File.READ);

var new_lines = [];

// f.ReadAll();
// f.Close();

let added_getter = false;
let added_version = false;
let added_neck = false;
let added_chest = false;
let added_femur = false;
let added_knee = false;
let added_tibia = false;
let added_foot = false;
let added_TibiaIndex = false;
let added_Nij = false;

let keys = Object.keys(EntitiesMatchStrings);

while ((line = f.ReadLine()) != undefined) {
    // Add a class constant to the WorkflowOccupant class for the name of the occupant version.
    //For an example search for DYNAMORE_ES2_RE_V6_0. The value of the constant needs to match the name of the csv file that contains the default entity IDs.

    if (!added_getter) {
        if (/Occupant Version Getters/.test(line)) {
            Add_WorkflowOccupant_Getter(
                occupant_version_getter_function_comment,
                occupant_version_getter_function_name,
                occupant_version_csv_name
            );
            //write line?
        }
    }

    // Add it to the array returned by WorkflowOccupant.Versions().

    if (!added_version) {
        if (/static Versions\(\)/.test(line)) {
            Add_WorkflowOccupant_Version(occupant_version_getter_function_name);
        }
    }

    // Add logic to the WorkflowOccupant.CreateWorkflowOccupant() function to create the WorkflowOccupant instance for the new occupant version.

    for (var k = 0; k < keys.length; k++) {
        let key = keys[k];

        let re_value = EntitiesMatchStrings[key];

        if (re_value) {
            let str = `static Create${key}Entities\\(version\\)`;
            let re_key = new RegExp(str, "i");
            if (re_key.test(line)) {
                if (Add_CreateEntities_Version(re_value)) {
                    EntitiesMatchStrings[key] = false; //this means it has already been added so don't check it again
                    break; //out of for loop - saves time (note assumes there is atleast one line between Create${key}Entities )
                }
            }
        }
    }

    // if (!added_neck) {
    //     if (/static CreateNeckEntities\(version\)/i.test(line)) {
    //         added_neck = Add_CreateEntities_Version(occupant_version_getter_function_name, "OccupantEntity.XSECTION");
    //     }
    // }

    // if (!added_chest) {
    //     if (/static CreateChestEntities\(version\)/.test(line)) {
    //         added_chest = Add_CreateEntities_Version(occupant_version_getter_function_name, '"ET"');
    //     }
    // }

    // if (!added_femur) {
    //     if (/static CreateFemurEntities\(version\)/.test(line)) {
    //         added_femur = Add_CreateEntities_Version(occupant_version_getter_function_name, "OccupantEntity.SPRING");
    //     }
    // }

    // if (!added_knee) {
    //     if (/static CreateKneeEntities\(version\)/.test(line)) {
    //         added_knee = Add_CreateEntities_Version(occupant_version_getter_function_name, "OccupantEntity.BEAM_BASIC");
    //     }
    // }

    // if (!added_tibia) {
    //     if (/static CreateTibiaEntities\(version\)/.test(line)) {
    //         added_tibia = Add_CreateEntities_Version(
    //             occupant_version_getter_function_name,
    //             "OccupantEntity.BEAM_BASIC"
    //         );
    //     }
    // }

    // if (!added_foot) {
    //     if (/static CreateFootEntities\(version\)/.test(line)) {
    //         added_foot = Add_CreateEntities_Version(occupant_version_getter_function_name, "OccupantEntity.NODE");
    //     }
    // }

    if (!added_TibiaIndex) {
        if (/GetTibiaIndexCriticalLoads/.test(line)) {
            added_TibiaIndex = true;
        }
    }

    if (!added_Nij) {
        if (/GetNIJCriticalLoads/.test(line)) {
            added_Nij = true;
        }
    }

    // Add logic to the WorkflowOccupant.GetNIJCriticalLoads function to return the critical neck injury loads for the new occupant version.

    // Add logic to the WorkflowOccupant.GetTibiaIndexCriticalLoads function to return the critical tibia index loads for the new occupant version.

    // Add logic to the WorkflowOccupant.GetChestRotationFactors function to return the factors to convert chest rotation values from radians to mm for the new occupant version.

    // Add logic to all the Read{BodyPart}{AssessmentType}() functions in the ProtocolAssessment class to return the assessment
    // values for the new occupant version, e.g. ProtocolAssessment.ReadNeckAxial().
    //This may just require adding the version to an existing switch case if the method for extracting the data is the same as
    // other occupant versions. If not a new case needs to be added to the switch.

    push_line(line);
}
f.Close();

// over-write file

f = new File(occupant_mjs_temp, File.WRITE);

for (var n = 0; n < new_lines.length; n++) {
    f.Writeln(new_lines[n]);
}
f.Close();

/**
 * Adds the getter for the occupant to the WorkflowOccupant class
 * @param {string} occupant_version_getter_function_comment
 * @param {string} occupant_version_getter_function_name
 * @param {string} occupant_version_csv_name
 */
function Add_WorkflowOccupant_Getter(
    occupant_version_getter_function_comment,
    occupant_version_getter_function_name,
    occupant_version_csv_name
) {
    // read all dummy getters and get alphabetical list then insert new occupant version in list dummy

    while (/Occupant Version Getters End/.test(line) == false) {
        if (/\/\*\*/.test(line)) {
            let comment_lines = [line];
            while (/static get/.test(line) == false) {
                line = f.ReadLine();
                comment_lines.push(line);
            }

            //regex used to extract the class constant name
            let re_occupant_class_const_name = /static get(\s*) (.*)\(\)/;

            let match = line.match(re_occupant_class_const_name);
            //first element is full match third element is the second capture group hence [2]
            if (match != null) {
                var current_occupant_version_getter_function_name = match[2];
            }

            //before performing the comparison set it to lower case
            if (
                occupant_version_getter_function_name.toLowerCase() <
                current_occupant_version_getter_function_name.toLowerCase()
            ) {
                //note that spaces and line breaks are important
                push_line(`    /** ${occupant_version_getter_function_comment}`);
                push_line(`     * @type {string} */`);
                push_line(`    static get ${occupant_version_getter_function_name}() {`);
                push_line(`        return "${occupant_version_csv_name}";`);
                push_line(`    }\n`);

                //if the occupant version we are trying to add comes before the one we are currently reading alphabetically then
                //first insert it then return (break) to allow script to keep writing
                added_getter = true;
            }

            for (var i = 0; i < comment_lines.length; i++) {
                push_line(comment_lines[i]);
            }
        } else {
            push_line(line);
        }

        line = f.ReadLine();

        if (added_getter) break;
    }

    if (!added_getter) {
        //add it to the end
        push_line(`    /** ${occupant_version_getter_function_comment}`);
        push_line(`     * @type {string} */`);
        push_line(`    static get ${occupant_version_getter_function_name}() {`);
        push_line(`        return "${occupant_version_csv_name}";`);
        push_line(`    }\n`);

        //if the occupant version we are trying to add comes before the one we are currently reading alphabetically then
        //first insert it then return (break) to allow script to keep writing
        added_getter = true;
    }
}

function push_line(line) {
    new_lines.push(line);
    Message(line);
}

/**
 * Adds the version for the occupant to the WorkflowOccupant class Versions list
 * @param {string} occupant_version_getter_function_name
 */
function Add_WorkflowOccupant_Version(occupant_version_getter_function_name) {
    // read all dummy getters and get alphabetical list then insert new occupant version in list dummy

    let line_buffer = [];
    let separator = ","; // ' ||'

    //end of list is when we have closing square bracket
    while (/WorkflowOccupant\./.test(line) == false) {
        push_line(line);
        line = f.ReadLine();
    }
    while (/WorkflowOccupant\./.test(line) == true) {
        line_buffer.push(line);
        line = f.ReadLine();
    }

    //when we get here line now does not contain 'WorkflowOccupant.string'
    //remember it needs to be pushed to new_lines though after insert_alphabetically
    added_version = insert_alphabetically(line_buffer, occupant_version_getter_function_name, separator);
}

/**
 * Adds the version for the occupant to the CreateNeckEntities function
 * we need to know if the neck uses a beam, joint or an X section
 * @param {string} OccupantEntityString
 */
function Add_CreateEntities_Version(OccupantEntityString) {
    // read all dummy getters and get alphabetical list then insert new occupant version in list dummy

    let line_buffer = [];
    let separator = " ||";

    let WorkflowOccupant_line_buffer = [];

    // let entity_if_statement_groups = {}

    let re_OccupantEntityString = new RegExp(OccupantEntityString, "i");

    let added = false;

    let left_squiggly_brackets = (line.match(/{/g) || []).length;
    let right_squiggly_brackets = (line.match(/}/g) || []).length;

    while (left_squiggly_brackets != right_squiggly_brackets && !added) {
        if (/\s+if\s*\(/.test(line) == true) {
            //add all buffered lines to new_lines
            for (var i = 0; i < line_buffer.length; i++) {
                push_line(line_buffer[i]);
            }

            //then reset the arrays for the next else if statement
            line_buffer = [];
            //WorkflowOccupant_line_buffer = []; //reset for next group
        } else if (re_OccupantEntityString.test(line) == true) {
            // entity_if_statement_groups[OccupantEntityString] = WorkflowOccupant_line_buffer;
            // WorkflowOccupant_line_buffer = []; //reset for next group

            var match = line_buffer[0].match(/(\s*)(.*if\s*\()([^\)]*)/);
            var pre_spaces = match[1];
            var if_statement = match[2];
            var version_WorkflowOccupant = match[3];

            push_line(`${pre_spaces}${if_statement}`);

            if (/WorkflowOccupant\./.test(version_WorkflowOccupant)) {
                WorkflowOccupant_line_buffer.push(`${pre_spaces}    ${version_WorkflowOccupant}`);
            }

            for (var i = 1; i < line_buffer.length; i++) {
                if (/WorkflowOccupant\./.test(line_buffer[i]) == true) {
                    WorkflowOccupant_line_buffer.push(line_buffer[i]);
                } else {
                    break;
                }

                //push_line(line_buffer[i]);
            }

            //when we get here line now does not contain 'WorkflowOccupant.string'
            //remember it needs to be pushed to new_lines though after insert_alphabetically
            added = insert_alphabetically(
                WorkflowOccupant_line_buffer,
                occupant_version_getter_function_name,
                separator
            );

            //deal with special case where if statement only has one condition so we need to add closing brackets to the end
            if (/WorkflowOccupant\./.test(version_WorkflowOccupant)) {
                //or if left_squiggly_brackets-right_squiggly_brackets ==1
                push_line(`${pre_spaces}) {`);
            }

            Message(i);
            //finally push the rest of the lines and break out of while loop
            for (i; i < line_buffer.length; i++) {
                push_line(line_buffer[i]);
            }
            line_buffer = [];
        }

        // if (/OccupantEntity.XSECTION/i.test(line) == true) {
        //     entity_if_statement_groups["XSECTION"] = WorkflowOccupant_line_buffer;
        //     WorkflowOccupant_line_buffer = []; //reset for next group
        // }

        // if (/OccupantEntity.JOINT/i.test(line) == true) {
        //     entity_if_statement_groups["JOINT"] = WorkflowOccupant_line_buffer;
        //     WorkflowOccupant_line_buffer = []; //reset for next group
        // }

        line_buffer.push(line);
        line = f.ReadLine();

        left_squiggly_brackets += (line.match(/{/g) || []).length;
        right_squiggly_brackets += (line.match(/}/g) || []).length;
    }

    for (var i = 0; i < line_buffer.length; i++) {
        push_line(line_buffer[i]);
    }

    return added;
}

/**
 *
 * @param {string[]} line_buffer
 * @param {string} occupant_version_getter_function_name
 * @param {string} separator
 * @example
 * insert_alphabetically(line_buffer, "LSTC_HIII_50M_V130528_BETA_NEW", " ||");
 */
function insert_alphabetically(line_buffer, occupant_version_getter_function_name, separator) {
    //loop through the occupant list and insert new occupant where it fits alphabetically

    let added = false;

    for (var i = 0; i < line_buffer.length; i++) {
        //first element is full match second element is the first capture group hence [2]
        var match = line_buffer[i].match(/(.*WorkflowOccupant\.)(\w*)(.*)/);
        var pre = match[1];
        var current_occupant_version_getter_function_name = match[2];
        let post = match[3];

        //before performing the comparison set it to lower case
        if (!added) {
            if (
                occupant_version_getter_function_name.toLowerCase() <
                current_occupant_version_getter_function_name.toLowerCase()
            ) {
                //note that spaces and line breaks are important

                push_line(`${pre}${occupant_version_getter_function_name}${separator}`);
                //if the occupant version we are trying to add comes before the one we are currently reading alphabetically then
                //first insert it then return (break) to allow script to keep writing
                added = true;
            }
        }

        if (i == line_buffer.length - 1 && !added) {
            //then we need to add version on very end as it is alphabetically last
            //this is a special case which requires us to add a comma (,) to the end of the original last line
            push_line(`${pre}${current_occupant_version_getter_function_name}${separator}${post}`); //note comma here
            push_line(`${pre}${occupant_version_getter_function_name}`); //note no comma here
            added = true;
        } else {
            push_line(line_buffer[i]);
        }
    }

    return added;
}