psychopy.org | Reference | Downloads | Github

Difficulty converting functions into JS

I am trying to run an experiment online and I get:
“ReferenceError: determineCurrentRule is not defined”

I am having difficulty converting the following functions (written in python) to javaScript. I am fairly familiar with python, but I have not used javaScript extensively so I can’t readily identify what the issues are. Can anyone help me identify the problems?

def isOutOfBounds(currentRule, currentTarget, phaseParameters, targetBounds):
    ## takes as input:
    ## currentRule: list where each element is a step
    ## currentTarget: the target number at the start of the sequence
    ## phaseTrialLimit: how many trials will the sequence run for
    ## bounds: a dict containing upper and lower bounds that target shouldn't exceed
    ## returns 1 if the rule pushes the currentStim out of bounds
    ## returns 0 otherwise
    
    out = 0
    
    ## if it's a non rule phase, just check one ahead
    if phaseParameters['phaseId'] == 'nonRulePhase':
        currentTarget += currentRule[0]
        if (currentTarget > targetBounds['upperTargetBound'] or currentTarget < targetBounds['lowerTargetBound']):
            out = 1
    
    ## if it's a rule phase, need to make sure adding the increment will work for the whole sequence
    else:
        ## for each trial where the rule will be applied
        for trial in range(phaseParameters['phaseTrialLimit']):
            ## for each step in the rule
            for step in currentRule:
                ## add the step to the current stimulus
                currentTarget += step
                ## check whether it's out of bounds
                if (currentTarget > targetBounds['upperTargetBound'] or currentTarget < targetBounds['lowerTargetBound']):
                    out = 1
                
    return(out)


            
def updatePhaseParameters(phaseParameters):
    ## takes as input phaseParameters dict where:
    ## {'phaseTrialCount': number of trials phase will last for,
    ## 'phaseId': 'rulePhase' or 'nonRulePhase'}
    ## returns the inverse of the input
    ## eg, if given rule phase, returns non rule phase
    
    ## Update phase id
    phaseId = 'rulePhase' if phaseParameters['phaseId'] == 'nonRulePhase' else 'nonRulePhase'

    ## Determine trial limit by randomly drawing an integer within the range of the phase boundaries
    lowerLimit = phaseBounds[phaseId][0]
    upperLimit = phaseBounds[phaseId][1]
    phaseTrialLimit = Math.random(lowerLimit, upperLimit)

    phaseParameters = {'phaseId': phaseId, 'phaseTrialLimit': phaseTrialLimit}
    return(phaseParameters)
    
    

def determineCurrentRule(phaseParameters, currentTarget, conditionContainer, targetBounds):
    ## takes as input phase information, the current target, all conditions, and target boundaries
    ## randomly iterates through the rules until it finds one that stays in bounds
    
    ## make a list of condition indices
    availableIndices = list(range(len(conditionContainer)))
    
    out = 1
    
    while out:
        
        try:
            ## randomly sample from conditions
            ## the line below is the one that will fail if all conditions are exhausted
            chosenIndex = availableIndices[Math.random(0, len(availableIndices))]
            ## if a condition is successfully drawn, drop it from the available indices list
            availableIndices.remove(chosenIndex)
            ## update the current rule
            currentRule = conditionContainer[chosenIndex]
            ## call isOutOfBounds() to test whether the rule will be valid for the phase
            ## if yes, terminate the while loop and return the current rule
            ## if not, repeat loop to draw another rule and test it against the phase
            out = isOutOfBounds(currentRule['steps'], currentTarget, phaseParameters, targetBounds)
            
        except:
            ## if all conditions are exhausted
            ## regenerate the target stimulus to be close to the median of possible targets
            currentTarget = Math.random(currentTarget - 2, currentTarget + 2)
            ## refresh available indicies so all rules can be sampled again
            availableIndices = list(range(len(conditionContainer)))
        
        
    return([currentRule, currentTarget])
``

________________Here is how it autoconverts into javascript__________________:

``
        // add-on: list(s: string): string[]
        function list(s) {
            // if s is a string, we return a list of its characters
            if (typeof s === 'string')
                return s.split('');
            else
                // otherwise we return s:
                return s;
        }
        
        function isOutOfBounds(currentRule, currentTarget, phaseParameters, targetBounds) {
    var out;
    out = 0;
    if ((phaseParameters["phaseId"] === "nonRulePhase")) {
        currentTarget += currentRule[0];
        if (((currentTarget > targetBounds["upperTargetBound"]) || (currentTarget < targetBounds["lowerTargetBound"]))) {
            out = 1;
        }
    } else {
        for (var trial = 0, _pj_a = phaseParameters["phaseTrialLimit"]; (trial < _pj_a); trial += 1) {
            for (var step, _pj_d = 0, _pj_b = currentRule, _pj_c = _pj_b.length; (_pj_d < _pj_c); _pj_d += 1) {
                step = _pj_b[_pj_d];
                currentTarget += step;
                if (((currentTarget > targetBounds["upperTargetBound"]) || (currentTarget < targetBounds["lowerTargetBound"]))) {
                    out = 1;
                }
            }
        }
    }
    return out;
}
function updatePhaseParameters(phaseParameters) {
    var lowerLimit, phaseId, phaseTrialLimit, upperLimit;
    phaseId = ((phaseParameters["phaseId"] === "nonRulePhase") ? "rulePhase" : "nonRulePhase");
    lowerLimit = phaseBounds[phaseId][0];
    upperLimit = phaseBounds[phaseId][1];
    phaseTrialLimit = Math.random(lowerLimit, upperLimit);
    phaseParameters = {"phaseId": phaseId, "phaseTrialLimit": phaseTrialLimit};
    return phaseParameters;
}
function determineCurrentRule(phaseParameters, currentTarget, conditionContainer, targetBounds) {
    var availableIndices, chosenIndex, currentRule, out;
    availableIndices = list(range(conditionContainer.length));
    out = 1;
    while (out) {
        try {
            chosenIndex = availableIndices[Math.random(0, availableIndices.length)];
            availableIndices.remove(chosenIndex);
            currentRule = conditionContainer[chosenIndex];
            out = isOutOfBounds(currentRule["steps"], currentTarget, phaseParameters, targetBounds);
        } catch(e) {
            currentTarget = Math.random((currentTarget - 2), (currentTarget + 2));
            availableIndices = list(range(conditionContainer.length));
        }
    }
    return [currentRule, currentTarget];
}
``