QScript R Variable Creation Functions

From Q
Jump to navigation Jump to search

This page contains functions to aid in the construction of variables which are based on R code.

To make these functions available when writing a QScript or Rule see JavaScript Reference.

Source Code

// Wrapper function for dataFile.newRQuestion.
// Modifies source_code to allow large data objects
// to be returned, and applies the function 
// TidyDataForRVariableSet from flipU to the returned
// value. This ensures that names attributes
// are stripped before data is given to Displayr,
// reducing the size of the object and reducing
// the likelihood that the variable will return an
// error because it exceeds the size limit for R
// calculations.
function robustNewRQuestion(data_file, 
                            source_code, 
                            question_name, 
                            variable_base_name, 
                            after, 
                            gui_control_code, 
                            gui_control_values) {

    // Double the default value. Could be increased, but
    // Core team should probably address this issue
    // rather than it being addressed in R code.
    const allowed_size = '256000000'; 
    let last_line = checkAndGetLastLineOfCode(source_code);
    let new_line = `${last_line} = TidyDataForRVariableSet(${last_line})`
    let new_source_code = `QAllowLargeResultObject(${allowed_size})
${insertLineBeforeLast(source_code, new_line)}`;

    let r_question = data_file.newRQuestion(new_source_code, 
                                            question_name, 
                                            variable_base_name, 
                                            after, 
                                            gui_control_code, 
                                            gui_control_values);
    return r_question;
}

// The last line of the source_code should simply be the
// name of the object to be returned. This makes is easy
// to append additional function calls prior to the return.
// Enables addidtional code to be added following the last
// asignment.
function checkAndGetLastLineOfCode(source_code) {
    let split_code = source_code.split("\n");
    split_code = split_code.map(s => s.trim());
    split_code = split_code.filter(s => s.length > 1);
    let last_line = split_code[split_code.length - 1];
    last_line = last_line.trim();
    let forbidden_chars = new RegExp(/\(|\)|=|-|<|\+|\s/);
    if (forbidden_chars.test(last_line))
        throw("The R code in this variable needs to be updated so that the last line contains only the name of the returned value.");
    return last_line;
}

function insertLineBeforeLast(source_code, code_to_add) {
    let split_code = source_code.split("\n");
    split_code.splice(split_code.length - 1, 0, code_to_add)
    return split_code.join("\n");
}

See also