Best JavaScript code snippet using mocha
jspsych-rdk.js
Source:jspsych-rdk.js
1/*2 3 RDK plugin for JsPsych4 ----------------------5 6 This code was created in the Consciousness and Metacognition Lab at UCLA, 7 under the supervision of Brian Odegaard and Hakwan Lau89 We would appreciate it if you cited this paper when you use the RDK: 10 Rajananda, S., Lau, H. & Odegaard, B., (2018). A Random-Dot Kinematogram for Web-Based Vision Research. Journal of Open Research Software. 6(1), p.6. DOI: [http://doi.org/10.5334/jors.194]11 12 ----------------------13 14 Copyright (C) 2017 Sivananda Rajananda15 16 This program is free software: you can redistribute it and/or modify17 it under the terms of the GNU General Public License as published by18 the Free Software Foundation, either version 3 of the License, or19 (at your option) any later version.20 21 This program is distributed in the hope that it will be useful,22 but WITHOUT ANY WARRANTY; without even the implied warranty of23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the24 GNU General Public License for more details.25 26 You should have received a copy of the GNU General Public License27 along with this program. If not, see <http://www.gnu.org/licenses/>.28 29*/30 31 32jsPsych.plugins["rdk"] = (function() {3334 var plugin = {};35 36 plugin.info = {37 name: "rdk",38 parameters: {39 choices: {40 type: jsPsych.plugins.parameterType.INT,41 pretty_name: "Choices",42 default: [],43 array: true,44 description: "The valid keys that the subject can press to indicate a response"45 },46 correct_choice: {47 type: jsPsych.plugins.parameterType.STRING,48 pretty_name: "Correct choice",49 default: undefined,50 array: true,51 description: "The correct keys for that trial"52 },53 trial_duration: {54 type: jsPsych.plugins.parameterType.INT,55 pretty_name: "Trial duration",56 default: 500,57 description: "The length of stimulus presentation"58 },59 response_ends_trial: {60 type: jsPsych.plugins.parameterType.BOOL,61 pretty_name: "Response ends trial",62 default: true,63 description: "If true, then any valid key will end the trial"64 },65 number_of_apertures: {66 type: jsPsych.plugins.parameterType.INT,67 pretty_name: "Number of apertures",68 default: 1,69 description: "The number of RDK apertures (If more than one, make sure to separate them by setting aperture_center_x and aperture_center_y for each RDK)"70 },71 number_of_dots: {72 type: jsPsych.plugins.parameterType.INT,73 pretty_name: "Number of dots",74 default: 300,75 description: "The number of dots per set in the stimulus"76 },77 number_of_sets: {78 type: jsPsych.plugins.parameterType.INT,79 pretty_name: "Number of sets",80 default: 1,81 description: "The number of sets of dots to cycle through"82 },83 coherent_direction: {84 type: jsPsych.plugins.parameterType.INT,85 pretty_name: "Coherent direction",86 default: 0,87 description: "The direction of coherent motion in degrees"88 },89 coherence: {90 type: jsPsych.plugins.parameterType.FLOAT,91 pretty_name: "Coherence",92 default: 0.5,93 description: "The percentage of dots moving in the coherent direction"94 },95 opposite_coherence: {96 type: jsPsych.plugins.parameterType.FLOAT,97 pretty_name: "Opposite coherence",98 default: 0,99 description: "The percentage of dots moving in the direction opposite of the coherent direction"100 },101 dot_radius: {102 type: jsPsych.plugins.parameterType.INT,103 pretty_name: "Dot radius",104 default: 2,105 description: "The radius of the dots in pixels"106 },107 dot_life: {108 type: jsPsych.plugins.parameterType.INT,109 pretty_name: "Dot life",110 default: -1,111 description: "The number of frames that pass before each dot disappears and reappears somewhere else"112 },113 move_distance: {114 type: jsPsych.plugins.parameterType.INT,115 pretty_name: "Move distance",116 default: 1,117 description: "The distance in pixels each dot moves per frame"118 },119 aperture_width: {120 type: jsPsych.plugins.parameterType.INT,121 pretty_name: "Aperture width",122 default: 600,123 description: "The width of the aperture in pixels"124 },125 aperture_height: {126 type: jsPsych.plugins.parameterType.INT,127 pretty_name: "Aperture height",128 default: 400,129 description: "The height of the aperture in pixels"130 },131 dot_color: {132 type: jsPsych.plugins.parameterType.STRING,133 pretty_name: "Dot color",134 default: "white",135 description: "The color of the dots"136 },137 background_color: {138 type: jsPsych.plugins.parameterType.STRING,139 pretty_name: "Background color",140 default: "gray",141 description: "The background of the stimulus"142 },143 RDK_type: {144 type: jsPsych.plugins.parameterType.INT,145 pretty_name: "RDK type",146 default: 3,147 description: "The Type of RDK (refer to documentation for details)"148 },149 aperture_type: {150 type: jsPsych.plugins.parameterType.INT,151 pretty_name: "Aperture Type",152 default: 2,153 description: "The shape of the aperture"154 },155 reinsert_type: {156 type: jsPsych.plugins.parameterType.INT,157 pretty_name: "Reinsert type",158 default: 2,159 description: "The reinsertion rule for dots that move out of the aperture"160 },161 aperture_center_x: {162 type: jsPsych.plugins.parameterType.INT,163 pretty_name: "Aperture center X",164 default: window.innerWidth/2,165 description: "The x-coordinate of the center of the aperture"166 },167 aperture_center_y: {168 type: jsPsych.plugins.parameterType.INT,169 pretty_name: "Aperture center Y",170 default: window.innerHeight/2,171 description: "The y-coordinate of the center of the aperture"172 },173 fixation_cross: {174 type: jsPsych.plugins.parameterType.INT, //boolean175 pretty_name: "Fixation cross",176 default: false,177 description: "If true, then a fixation cross will be present in the middle of the screen"178 },179 fixation_cross_width: {180 type: jsPsych.plugins.parameterType.INT,181 pretty_name: "Fixation cross width",182 default: 20,183 description: "The width of the fixation cross in pixels"184 },185 fixation_cross_height: {186 type: jsPsych.plugins.parameterType.INT,187 pretty_name: "Fixation cross height",188 default: 20,189 description: "The height of the fixation cross in pixels"190 },191 fixation_cross_color: {192 type: jsPsych.plugins.parameterType.STRING,193 pretty_name: "Fixation cross color",194 default: "black",195 description: "The color of the fixation cross"196 },197 fixation_cross_thickness: {198 type: jsPsych.plugins.parameterType.INT,199 pretty_name: "Fixation cross thickness",200 default: 1,201 description: "The thickness of the fixation cross"202 },203 border: {204 type: jsPsych.plugins.parameterType.BOOL,205 pretty_name: "Border",206 default: false,207 description: "The presence of a border around the aperture"208 },209 border_thickness: {210 type: jsPsych.plugins.parameterType.INT,211 pretty_name: "Border width",212 default: 1,213 description: "The thickness of the border in pixels"214 },215 border_color: {216 type: jsPsych.plugins.parameterType.STRING,217 pretty_name: "Border Color",218 default: 1,219 description: "The color of the border"220 }221 }222 }223224225 //BEGINNING OF TRIAL 226 plugin.trial = function(display_element, trial) {227228 //--------------------------------------229 //---------SET PARAMETERS BEGIN---------230 //--------------------------------------231 232 233 //Note on '||' logical operator: If the first option is 'undefined', it evalutes to 'false' and the second option is returned as the assignment234 trial.choices = assignParameterValue(trial.choices, []);235 trial.correct_choice = assignParameterValue(trial.correct_choice, undefined);236 trial.trial_duration = assignParameterValue(trial.trial_duration, 500);237 trial.response_ends_trial = assignParameterValue(trial.response_ends_trial, true);238 trial.number_of_apertures = assignParameterValue(trial.number_of_apertures, 1);239 trial.number_of_dots = assignParameterValue(trial.number_of_dots, 300);240 trial.number_of_sets = assignParameterValue(trial.number_of_sets, 1);241 trial.coherent_direction = assignParameterValue(trial.coherent_direction, 0);242 trial.coherence = assignParameterValue(trial.coherence, 0.5);243 trial.opposite_coherence = assignParameterValue(trial.opposite_coherence, 0);244 trial.dot_radius = assignParameterValue(trial.dot_radius, 2);245 trial.dot_life = assignParameterValue(trial.dot_life, -1);246 trial.move_distance = assignParameterValue(trial.move_distance, 1);247 trial.aperture_width = assignParameterValue(trial.aperture_width, 600);248 trial.aperture_height = assignParameterValue(trial.aperture_height, 400);249 trial.dot_color = assignParameterValue(trial.dot_color, "white");250 trial.background_color = assignParameterValue(trial.background_color, "gray");251 trial.RDK_type = assignParameterValue(trial.RDK_type, 3);252 trial.aperture_type = assignParameterValue(trial.aperture_type, 2);253 trial.reinsert_type = assignParameterValue(trial.reinsert_type, 2);254 trial.aperture_center_x = assignParameterValue(trial.aperture_center_x, window.innerWidth/2);255 trial.aperture_center_y = assignParameterValue(trial.aperture_center_y, window.innerHeight/2);256 trial.fixation_cross = assignParameterValue(trial.fixation_cross, false); 257 trial.fixation_cross_width = assignParameterValue(trial.fixation_cross_width, 20);258 trial.fixation_cross_height = assignParameterValue(trial.fixation_cross_height, 20);259 trial.fixation_cross_color = assignParameterValue(trial.fixation_cross_color, "black");260 trial.fixation_cross_thickness = assignParameterValue(trial.fixation_cross_thickness, 1);261 trial.border = assignParameterValue(trial.border, false);262 trial.border_thickness = assignParameterValue(trial.border_thickness, 1);263 trial.border_color = assignParameterValue(trial.border_color, "black");264 265 266 //For square and circle, set the aperture height == aperture width267 if (apertureType == 1 || apertureType == 3) {268 trial.aperture_height = trial.aperture_width;269 }270271 //Convert the parameter variables to those that the code below can use272 273 var nApertures = trial.number_of_apertures; //The number of apertures274 var nDots = trial.number_of_dots; //Number of dots per set (equivalent to number of dots per frame)275 var nSets = trial.number_of_sets; //Number of sets to cycle through per frame276 var coherentDirection = trial.coherent_direction; //The direction of the coherentDots in degrees. Starts at 3 o'clock and goes counterclockwise (0 == rightwards, 90 == upwards, 180 == leftwards, 270 == downwards), range 0 - 360277 var coherence = trial.coherence; //Proportion of dots to move together, range from 0 to 1278 var oppositeCoherence = trial.opposite_coherence; // The coherence for the dots going the opposite direction as the coherent dots279 var dotRadius = trial.dot_radius; //Radius of each dot in pixels280 var dotLife = trial.dot_life; //How many frames a dot will keep following its trajectory before it is redrawn at a random location. -1 denotes infinite life (the dot will only be redrawn if it reaches the end of the aperture).281 var moveDistance = trial.move_distance; //How many pixels the dots move per frame282 var apertureWidth = trial.aperture_width; // How many pixels wide the aperture is. For square aperture this will be the both height and width. For circle, this will be the diameter.283 var apertureHeight = trial.aperture_height; //How many pixels high the aperture is. Only relevant for ellipse and rectangle apertures. For circle and square, this is ignored.284 var dotColor = trial.dot_color; //Color of the dots285 var backgroundColor = trial.background_color; //Color of the background286 var apertureCenterX = trial.aperture_center_x; // The x-coordinate of center of the aperture on the screen, in pixels287 var apertureCenterY = trial.aperture_center_y; // The y-coordinate of center of the aperture on the screen, in pixels288 289290 /* RDK type parameter291 ** See Fig. 1 in Scase, Braddick, and Raymond (1996) for a visual depiction of these different signal selection rules and noise types292293 -------------------294 SUMMARY:295296 Signal Selection rule:297 -Same: Each dot is designated to be either a coherent dot (signal) or incoherent dot (noise) and will remain so throughout all frames in the display. Coherent dots will always move in the direction of coherent motion in all frames.298 -Different: Each dot can be either a coherent dot (signal) or incoherent dot (noise) and will be designated randomly (weighted based on the coherence level) at each frame. Only the dots that are designated to be coherent dots will move in the direction of coherent motion, but only in that frame. In the next frame, each dot will be designated randomly again on whether it is a coherent or incoherent dot.299300 Noise Type:301 -Random position: The incoherent dots appear in a random location in the aperture in each frame302 -Random walk: The incoherent dots will move in a random direction (designated randomly in each frame) in each frame.303 -Random direction: Each incoherent dot has its own alternative direction of motion (designated randomly at the beginning of the trial), and moves in that direction in each frame.304305 -------------------306307 1 - same && random position308 2 - same && random walk309 3 - same && random direction310 4 - different && random position311 5 - different && random walk312 6 - different && random direction */313314 var RDK = trial.RDK_type;315316317 /* 318 Shape of aperture319 1 - Circle320 2 - Ellipse321 3 - Square322 4 - Rectangle323 */324 var apertureType = trial.aperture_type;325326 /*327 Out of Bounds Decision328 How we reinsert a dot that has moved outside the edges of the aperture:329 1 - Randomly appear anywhere in the aperture330 2 - Appear on the opposite edge of the aperture (Random if square or rectangle, reflected about origin in circle and ellipse)331 */332 var reinsertType = trial.reinsert_type;333 334 //Fixation Cross Parameters335 var fixationCross = trial.fixation_cross; //To display or not to display the cross336 var fixationCrossWidth = trial.fixation_cross_width; //The width of the fixation cross in pixels337 var fixationCrossHeight = trial.fixation_cross_height; //The height of the fixation cross in pixels338 var fixationCrossColor = trial.fixation_cross_color; //The color of the fixation cross339 var fixationCrossThickness = trial.fixation_cross_thickness; //The thickness of the fixation cross, must be positive number above 1340 341 //Border Parameters342 var border = trial.border; //To display or not to display the border343 var borderThickness = trial.border_thickness; //The width of the border in pixels344 var borderColor = trial.border_color; //The color of the border345346347348 //--------------------------------------349 //----------SET PARAMETERS END----------350 //--------------------------------------351352 //--------Set up Canvas begin-------353 354 //Create a canvas element and append it to the DOM355 var canvas = document.createElement("canvas");356 display_element.appendChild(canvas); 357 358 359 //The document body IS 'display_element' (i.e. <body class="jspsych-display-element"> .... </body> )360 var body = document.getElementsByClassName("jspsych-display-element")[0];361 362 //Save the current settings to be restored later363 var originalMargin = body.style.margin;364 var originalPadding = body.style.padding;365 var originalBackgroundColor = body.style.backgroundColor;366 367 //Remove the margins and paddings of the display_element368 body.style.margin = 0;369 body.style.padding = 0;370 body.style.backgroundColor = backgroundColor; //Match the background of the display element to the background color of the canvas so that the removal of the canvas at the end of the trial is not noticed371372 //Remove the margins and padding of the canvas373 canvas.style.margin = 0;374 canvas.style.padding = 0; 375 376 //Get the context of the canvas so that it can be painted on.377 var ctx = canvas.getContext("2d");378379 //Declare variables for width and height, and also set the canvas width and height to the window width and height380 var canvasWidth = canvas.width = window.innerWidth;381 var canvasHeight = canvas.height = window.innerHeight;382383 //Set the canvas background color384 canvas.style.backgroundColor = backgroundColor;385386 //--------Set up Canvas end-------387 388 389 390 //--------RDK variables and function calls begin--------391 392 //This is the main part of the trial that makes everything run393394 //Global variable for the current aperture number395 var currentApertureNumber;396397 //3D Array to hold the dots (1st D is Apertures, 2nd D is Sets, 3rd D is Dots)398 var dotArray3d = [];399400 //Variables for different apertures (initialized in setUpMultipleApertures function below)401 var nDotsArray;402 var nSetsArray;403 var coherentDirectionArray;404 var coherenceArray;405 var oppositeCoherenceArray;406 var dotRadiusArray;407 var dotLifeArray;408 var moveDistanceArray;409 var apertureWidthArray;410 var apertureHeightArray;411 var dotColorArray;412 var apertureCenterXArray;413 var apertureCenterYArray;414 415 // Set up multiple apertures416 setUpMultipleApertures();417418 //Declare aperture parameters for initialization based on shape (used in initializeApertureDimensions function below)419 var horizontalAxis;420 var verticalAxis;421422 //Calculate the x and y jump sizes for coherent dots423 var coherentJumpSizeX;424 var coherentJumpSizeY;425426 //Calculate the number of coherent, opposite coherent, and incoherent dots427 var nCoherentDots;428 var nOppositeCoherentDots;429 var nIncoherentDots;430431 //Make the array of arrays containing dot objects432 var dotArray2d;433434 var dotArray; //Declare a global variable to hold the current array435 var currentSetArray; //Declare and initialize a global variable to cycle through the dot arrays436437 438 //Initialize stopping condition for animateDotMotion function that runs in a loop439 var stopDotMotion = false;440 441 //Variable to control the frame rate, to ensure that the first frame is skipped because it follows a different timing442 var firstFrame = true; //Used to skip the first frame in animate function below (in animateDotMotion function)443 444 //Variable to start the timer when the time comes445 var timerHasStarted = false;446447 //Initialize object to store the response data. Default values of -1 are used if the trial times out and the subject has not pressed a valid key448 var response = {449 rt: -1,450 key: -1451 }452 453 //Declare a global timeout ID to be initialized below in animateDotMotion function and to be used in after_response function454 var timeoutID;455 456 //Declare global variable to be defined in startKeyboardListener function and to be used in end_trial function457 var keyboardListener; 458 459 //Declare global variable to store the frame rate of the trial460 var frameRate = []; //How often the monitor refreshes, in ms. Currently an array to store all the intervals. Will be converted into a single number (the average) in end_trial function.461 462 //variable to store how many frames were presented.463 var numberOfFrames = 0;464465 //This runs the dot motion simulation, updating it according to the frame refresh rate of the screen.466 animateDotMotion();467 468 469 //--------RDK variables and function calls end--------470471472473 //-------------------------------------474 //-----------FUNCTIONS BEGIN-----------475 //-------------------------------------476477 //----JsPsych Functions Begin----478 479 480 //Function to start the keyboard listener481 function startKeyboardListener(){482 //Start the response listener if there are choices for keys483 if (trial.choices != jsPsych.NO_KEYS) {484 //Create the keyboard listener to listen for subjects' key response485 keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({486 callback_function: after_response, //Function to call once the subject presses a valid key487 valid_responses: trial.choices, //The keys that will be considered a valid response and cause the callback function to be called488 rt_method: 'performance', //The type of method to record timing information. 489 persist: false, //If set to false, keyboard listener will only trigger the first time a valid key is pressed. If set to true, it has to be explicitly cancelled by the cancelKeyboardResponse plugin API.490 allow_held_key: false //Only register the key once, after this getKeyboardResponse function is called. (Check JsPsych docs for better info under 'jsPsych.pluginAPI.getKeyboardResponse').491 });492 }493 }494495 //Function to end the trial proper496 function end_trial() {497 498 //Stop the dot motion animation499 stopDotMotion = true;500 501 //Store the number of frames502 numberOfFrames = frameRate.length;503 504 //Variable to store the frame rate array505 var frameRateArray = frameRate;506 507 //Calculate the average frame rate508 if(frameRate.length > 0){//Check to make sure that the array is not empty509 frameRate = frameRate.reduce((total,current) => total + current)/frameRate.length; //Sum up all the elements in the array510 }else{511 frameRate = 0; //Set to zero if the subject presses an answer before a frame is shown (i.e. if frameRate is an empty array)512 }513514 //Kill the keyboard listener if keyboardListener has been defined515 if (typeof keyboardListener !== 'undefined') {516 jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);517 }518519 //Place all the data to be saved from this trial in one data object520 var trial_data = { 521 "rt": response.rt, //The response time522 "key_press": response.key, //The key that the subject pressed523 "correct": correctOrNot(), //If the subject response was correct524 "choices": trial.choices, //The set of valid keys525 "correct_choice": trial.correct_choice, //The correct choice526 "trial_duration": trial.trial_duration, //The trial duration 527 "response_ends_trial": trial.response_ends_trial, //If the response ends the trial528 "number_of_apertures": trial.number_of_apertures,529 "number_of_dots": trial.number_of_dots,530 "number_of_sets": trial.number_of_sets,531 "coherent_direction": trial.coherent_direction,532 "coherence": trial.coherence,533 "opposite_coherence": trial.opposite_coherence,534 "dot_radius": trial.dot_radius,535 "dot_life": trial.dot_life,536 "move_distance": trial.move_distance,537 "aperture_width": trial.aperture_width,538 "aperture_height": trial.aperture_height,539 "dot_color": trial.dot_color,540 "background_color": trial.background_color,541 "RDK_type": trial.RDK_type,542 "aperture_type": trial.aperture_type,543 "reinsert_type": trial.reinsert_type,544 "frame_rate": frameRate, //The average frame rate for the trial545 "frame_rate_array": JSON.stringify(frameRateArray), //The array of ms per frame in this trial, in the form of a JSON string546 "number_of_frames": numberOfFrames, //The number of frames in this trial547 "aperture_center_x": trial.aperture_center_x,548 "aperture_center_y": trial.aperture_center_y,549 "fixation_cross": trial.fixation_cross,550 "fixation_cross_width": trial.fixation_cross_width,551 "fixation_cross_height": trial.fixation_cross_height,552 "fixation_cross_color": trial.fixation_cross_color,553 "fixation_cross_thickness": trial.fixation_cross_thickness,554 "border": trial.border,555 "border_thickness": trial.border_thickness,556 "border_color": trial.border_color,557 "canvas_width": canvasWidth,558 "canvas_height": canvasHeight559 560 }561 562 //Remove the canvas as the child of the display_element element563 display_element.innerHTML='';564 565 //Restore the settings to JsPsych defaults566 body.style.margin = originalMargin;567 body.style.padding = originalPadding;568 body.style.backgroundColor = originalBackgroundColor569570 //End this trial and move on to the next trial571 jsPsych.finishTrial(trial_data);572 573 } //End of end_trial574575 //Function to record the first response by the subject576 function after_response(info) {577578 //If the response has not been recorded, record it579 if (response.key == -1) {580 response = info; //Replace the response object created above581 }582583 //If the parameter is set such that the response ends the trial, then kill the timeout and end the trial584 if (trial.response_ends_trial) {585 window.clearTimeout(timeoutID);586 end_trial();587 }588589 } //End of after_response590 591 //Function that determines if the response is correct592 function correctOrNot(){593 594 //Check that the correct_choice has been defined595 if(typeof trial.correct_choice !== 'undefined'){596 //If the correct_choice variable holds an array597 if(trial.correct_choice.constructor === Array){ //If it is an array598 //If the elements are characters599 if(typeof trial.correct_choice[0] === 'string' || trial.correct_choice[0] instanceof String){600 trial.correct_choice = trial.correct_choice.map(function(x){return x.toUpperCase();}); //Convert all the values to upper case601 return trial.correct_choice.includes(String.fromCharCode(response.key)); //If the response is included in the correct_choice array, return true. Else, return false.602 }603 //Else if the elements are numbers (javascript character codes)604 else if (typeof trial.correct_choice[0] === 'number'){605 return trial.correct_choice.includes(response.key); //If the response is included in the correct_choice array, return true. Else, return false.606 }607 }608 //Else compare the char with the response key609 else{610 //If the element is a character611 if(typeof trial.correct_choice === 'string' || trial.correct_choice instanceof String){612 //Return true if the user's response matches the correct answer. Return false otherwise.613 return response.key == trial.correct_choice.toUpperCase().charCodeAt(0);614 }615 //Else if the element is a number (javascript character codes)616 else if (typeof trial.correct_choice === 'number'){617 console.log(response.key == trial.correct_choice);618 return response.key == trial.correct_choice;619 }620 }621 }622 }623624 //----JsPsych Functions End----625626 //----RDK Functions Begin----627628 //Set up the variables for the apertures629 function setUpMultipleApertures(){630 nDotsArray = setParameter(nDots);631 nSetsArray = setParameter(nSets); 632 coherentDirectionArray = setParameter(coherentDirection); 633 coherenceArray = setParameter(coherence); 634 oppositeCoherenceArray = setParameter(oppositeCoherence); 635 dotRadiusArray = setParameter(dotRadius); 636 dotLifeArray = setParameter(dotLife); 637 moveDistanceArray = setParameter(moveDistance); 638 apertureWidthArray = setParameter(apertureWidth); 639 apertureHeightArray = setParameter(apertureHeight); 640 dotColorArray = setParameter(dotColor); 641 apertureCenterXArray = setParameter(apertureCenterX); 642 apertureCenterYArray = setParameter(apertureCenterY); 643 RDKArray = setParameter(RDK);644 apertureTypeArray = setParameter(apertureType);645 reinsertTypeArray = setParameter(reinsertType);646 fixationCrossArray = setParameter(fixationCross);647 fixationCrossWidthArray = setParameter(fixationCrossWidth);648 fixationCrossHeightArray = setParameter(fixationCrossHeight);649 fixationCrossColorArray = setParameter(fixationCrossColor);650 fixationCrossThicknessArray = setParameter(fixationCrossThickness);651 borderArray = setParameter(border);652 borderThicknessArray = setParameter(borderThickness);653 borderColorArray = setParameter(borderColor);654 655 currentSetArray = setParameter(0); //Always starts at zero656657658 //Loop through the number of apertures to make the dots659 for(currentApertureNumber = 0; currentApertureNumber < nApertures; currentApertureNumber++){660 661 //Initialize the parameters to make the 2d dot array (one for each aperture);662 initializeCurrentApertureParameters();663 664 //Make each 2d array and push it into the 3d array665 dotArray3d.push(makeDotArray2d());666 }667 }668 669 //Function to set the parameters of the array670 function setParameter(originalVariable){671 //Check if it is an array and its length matches the aperture then return the original array672 if(originalVariable.constructor === Array && originalVariable.length === nApertures){673 return originalVariable;674 }675 //Else if it is not an array, we make it an array with duplicate values676 else if(originalVariable.constructor !== Array){677 678 var tempArray = [];679 680 //Make a for loop and duplicate the values681 for(var i = 0; i < nApertures; i++){682 tempArray.push(originalVariable);683 }684 return tempArray;685 }686 //Else if the array is not long enough, then print out that error message687 else if(originalVariable.constructor === Array && originalVariable.length !== nApertures){688 console.error("If you have more than one aperture, please ensure that arrays that are passed in as parameters are the same length as the number of apertures. Else you can use a single value without the array");689 }690 //Else print a generic error691 else{692 console.error("A parameter is incorrectly set. Please ensure that the nApertures parameter is set to the correct value (if using more than one aperture), and all others parameters are set correctly.");693 }694 }695 696 //Function to set the global variables to the current aperture so that the correct dots are updated and drawn697 function initializeCurrentApertureParameters(){698 699 //Set the global variables to that relevant to the current aperture700 nDots = nDotsArray[currentApertureNumber];701 nSets = nSetsArray[currentApertureNumber]; 702 coherentDirection = coherentDirectionArray[currentApertureNumber]; 703 coherence = coherenceArray[currentApertureNumber]; 704 oppositeCoherence = oppositeCoherenceArray[currentApertureNumber]; 705 dotRadius = dotRadiusArray[currentApertureNumber]; 706 dotLife = dotLifeArray[currentApertureNumber]; 707 moveDistance = moveDistanceArray[currentApertureNumber]; 708 apertureWidth = apertureWidthArray[currentApertureNumber]; 709 apertureHeight = apertureHeightArray[currentApertureNumber]; 710 dotColor = dotColorArray[currentApertureNumber]; 711 apertureCenterX = apertureCenterXArray[currentApertureNumber]; 712 apertureCenterY = apertureCenterYArray[currentApertureNumber]; 713 RDK = RDKArray[currentApertureNumber];714 apertureType = apertureTypeArray[currentApertureNumber];715 reinsertType = reinsertTypeArray[currentApertureNumber];716 fixationCross = fixationCrossArray[currentApertureNumber];717 fixationCrossWidth = fixationCrossWidthArray[currentApertureNumber];718 fixationCrossHeight = fixationCrossHeightArray[currentApertureNumber];719 fixationCrossColor = fixationCrossColorArray[currentApertureNumber];720 fixationCrossThickness = fixationCrossThicknessArray[currentApertureNumber];721 border = borderArray[currentApertureNumber];722 borderThickness = borderThicknessArray[currentApertureNumber];723 borderColor = borderColorArray[currentApertureNumber];724725 //Calculate the x and y jump sizes for coherent dots726 coherentJumpSizeX = calculateCoherentJumpSizeX(coherentDirection);727 coherentJumpSizeY = calculateCoherentJumpSizeY(coherentDirection);728729 //Initialize the aperture parameters730 initializeApertureDimensions();731732 //Calculate the number of coherent, opposite coherent, and incoherent dots733 nCoherentDots = nDots * coherence;734 nOppositeCoherentDots = nDots * oppositeCoherence;735 nIncoherentDots = nDots - (nCoherentDots + nOppositeCoherentDots);736 737 //If the 3d array has been made, then choose the 2d array and the current set738 dotArray2d = dotArray3d.length !==0 ? dotArray3d[currentApertureNumber] : undefined;739 740 }// End of initializeCurrentApertureParameters741 742 //Calculate coherent jump size in the x direction743 function calculateCoherentJumpSizeX(coherentDirection) {744 var angleInRadians = coherentDirection * Math.PI / 180;745 return moveDistance * Math.cos(angleInRadians);746 }747748 //Calculate coherent jump size in the y direction749 function calculateCoherentJumpSizeY(coherentDirection) {750 var angleInRadians = -coherentDirection * Math.PI / 180; //Negative sign because the y-axis is flipped on screen751 return moveDistance * Math.sin(angleInRadians);752 }753754 //Initialize the parameters for the aperture for further calculation755 function initializeApertureDimensions() {756 //For circle and square757 if (apertureType == 1 || apertureType == 3) {758 horizontalAxis = verticalAxis = apertureWidth/2;759 }760 //For ellipse and rectangle761 else if (apertureType == 2 || apertureType == 4) {762 horizontalAxis = apertureWidth / 2;763 verticalAxis = apertureHeight / 2;764 }765 }766767 //Make the 2d array, which is an array of array of dots768 function makeDotArray2d() {769 //Declare an array to hold the sets of dot arrays770 var tempArray = []771 //Loop for each set of dot array772 for (var i = 0; i < nSets; i++) {773 tempArray.push(makeDotArray()); //Make a dot array and push it into the 2d array774 }775776 return tempArray;777 }778779 //Make the dot array780 function makeDotArray() {781 var tempArray = []782 for (var i = 0; i < nDots; i++) {783 //Initialize a dot to be modified and inserted into the array784 var dot = {785 x: 0, //x coordinate786 y: 0, //y coordinate787 vx: 0, //coherent x jumpsize (if any)788 vy: 0, //coherent y jumpsize (if any)789 vx2: 0, //incoherent (random) x jumpsize (if any)790 vy2: 0, //incoherent (random) y jumpsize (if any)791 latestXMove: 0, //Stores the latest x move direction for the dot (to be used in reinsertOnOppositeEdge function below)792 latestYMove: 0, //Stores the latest y move direction for the dot (to be used in reinsertOnOppositeEdge function below)793 lifeCount: Math.floor(randomNumberBetween(0, dotLife)), //Counter for the dot's life. Updates every time it is shown in a frame794 updateType: "" //String to determine how this dot is updated795 };796 797 //randomly set the x and y coordinates798 dot = resetLocation(dot);799800 //For the same && random position RDK type801 if (RDK == 1) {802 //For coherent dots803 if (i < nCoherentDots) {804 dot = setvxvy(dot); // Set dot.vx and dot.vy805 dot.updateType = "constant direction";806 }807 //For opposite coherent dots808 else if(i >= nCoherentDots && i < (nCoherentDots + nOppositeCoherentDots)){809 dot = setvxvy(dot); // Set dot.vx and dot.vy810 dot.updateType = "opposite direction";811 }812 //For incoherent dots813 else {814 dot.updateType = "random position";815 }816 } //End of RDK==1817818 //For the same && random walk RDK type819 if (RDK == 2) {820 //For coherent dots821 if (i < nCoherentDots) {822 dot = setvxvy(dot); // Set dot.vx and dot.vy823 dot.updateType = "constant direction";824 }825 //For opposite coherent dots826 else if(i >= nCoherentDots && i < (nCoherentDots + nOppositeCoherentDots)){827 dot = setvxvy(dot); // Set dot.vx and dot.vy828 dot.updateType = "opposite direction";829 }830 //For incoherent dots831 else {832 dot.updateType = "random walk";833 }834 } //End of RDK==2835836 //For the same && random direction RDK type837 if (RDK == 3) {838 //For coherent dots839 if (i < nCoherentDots) {840 dot = setvxvy(dot); // Set dot.vx and dot.vy841 dot.updateType = "constant direction";842 }843 //For opposite coherent dots844 else if(i >= nCoherentDots && i < (nCoherentDots + nOppositeCoherentDots)){845 dot = setvxvy(dot); // Set dot.vx and dot.vy846 dot.updateType = "opposite direction";847 }848 //For incoherent dots849 else {850 setvx2vy2(dot); // Set dot.vx2 and dot.vy2851 dot.updateType = "random direction";852 }853 } //End of RDK==3854855 //For the different && random position RDK type856 if (RDK == 4) {857 //For all dots858 dot = setvxvy(dot); // Set dot.vx and dot.vy859 dot.updateType = "constant direction or opposite direction or random position";860 } //End of RDK==4861862 //For the different && random walk RDK type863 if (RDK == 5) {864 //For all dots865 dot = setvxvy(dot); // Set dot.vx and dot.vy866 dot.updateType = "constant direction or opposite direction or random walk";867 } //End of RDK==5868869 //For the different && random direction RDK type870 if (RDK == 6) {871 //For all dots872 dot = setvxvy(dot); // Set dot.vx and dot.vy873 //Each dot will have its own alternate direction of motion874 setvx2vy2(dot); // Set dot.vx2 and dot.vy2875 dot.updateType = "constant direction or opposite direction or random direction";876 } //End of RDK==6877878 tempArray.push(dot);879 } //End of for loop880 return tempArray;881 }882 883 //Function to update all the dots all the apertures and then draw them884 function updateAndDraw(){885 886 //Three for loops that do things in sequence: clear, update, and draw dots.887 888 // Clear all the current dots889 for(currentApertureNumber = 0; currentApertureNumber < nApertures; currentApertureNumber++){890 891 //Initialize the variables for each parameter892 initializeCurrentApertureParameters(currentApertureNumber);893 894 //Clear the canvas by drawing over the current dots895 clearDots();896 }897 898 // Update all the relevant dots899 for(currentApertureNumber = 0; currentApertureNumber < nApertures; currentApertureNumber++){900 901 //Initialize the variables for each parameter902 initializeCurrentApertureParameters(currentApertureNumber);903 904 //Update the dots905 updateDots();906 }907 908 // Draw all the relevant dots on the canvas909 for(currentApertureNumber = 0; currentApertureNumber < nApertures; currentApertureNumber++){910 911 //Initialize the variables for each parameter912 initializeCurrentApertureParameters(currentApertureNumber);913 914 //Draw on the canvas915 draw();916 }917 } 918 919 //Function that clears the dots on the canvas by drawing over it with the color of the baclground920 function clearDots(){921 922 //Load in the current set of dot array for easy handling923 var dotArray = dotArray2d[currentSetArray[currentApertureNumber]];924 925 //Loop through the dots one by one and draw them926 for (var i = 0; i < nDots; i++) {927 dot = dotArray[i];928 ctx.beginPath();929 ctx.arc(dot.x, dot.y, dotRadius+1, 0, Math.PI * 2);930 ctx.fillStyle = backgroundColor;931 ctx.fill();932 }933 }934935 //Draw the dots on the canvas after they're updated936 function draw() {937 938 //Load in the current set of dot array for easy handling939 var dotArray = dotArray2d[currentSetArray[currentApertureNumber]];940 941 //Loop through the dots one by one and draw them942 for (var i = 0; i < nDots; i++) {943 dot = dotArray[i];944 ctx.beginPath();945 ctx.arc(dot.x, dot.y, dotRadius, 0, Math.PI * 2);946 ctx.fillStyle = dotColor;947 ctx.fill();948 }949 950 //Draw the fixation cross if we want it951 if(fixationCross === true){952 953 //Horizontal line954 ctx.beginPath();955 ctx.lineWidth = fixationCrossThickness;956 ctx.moveTo(canvasWidth/2 - fixationCrossWidth, canvasHeight/2);957 ctx.lineTo(canvasWidth/2 + fixationCrossWidth, canvasHeight/2);958 ctx.fillStyle = fixationCrossColor;959 ctx.stroke();960 961 //Vertical line962 ctx.beginPath();963 ctx.lineWidth = fixationCrossThickness;964 ctx.moveTo(canvasWidth/2, canvasHeight/2 - fixationCrossHeight);965 ctx.lineTo(canvasWidth/2, canvasHeight/2 + fixationCrossHeight);966 ctx.fillStyle = fixationCrossColor;967 ctx.stroke();968 }969 970 //Draw the border if we want it971 if(border === true){972 973 //For circle and ellipse974 if(apertureType === 1 || apertureType === 2){975 ctx.lineWidth = borderThickness;976 ctx.strokeStyle = borderColor;977 ctx.beginPath();978 ctx.ellipse(apertureCenterX, apertureCenterY, horizontalAxis+(borderThickness/2), verticalAxis+(borderThickness/2), 0, 0, Math.PI*2);979 ctx.stroke();980 }//End of if circle or ellipse981 982 //For square and rectangle983 if(apertureType === 3 || apertureType === 4){984 ctx.lineWidth = borderThickness;985 ctx.strokeStyle = borderColor;986 ctx.strokeRect(apertureCenterX-horizontalAxis-(borderThickness/2), apertureCenterY-verticalAxis-(borderThickness/2), (horizontalAxis*2)+borderThickness, (verticalAxis*2)+borderThickness);987 }//End of if square or 988 989 }//End of if border === true990 991 }//End of draw992993 //Update the dots with their new location994 function updateDots() {995 996 //Cycle through to the next set of dots997 if (currentSetArray[currentApertureNumber] == nSets - 1) {998 currentSetArray[currentApertureNumber] = 0;999 } else {1000 currentSetArray[currentApertureNumber] = currentSetArray[currentApertureNumber] + 1;1001 }1002 1003 //Load in the current set of dot array for easy handling1004 var dotArray = dotArray2d[currentSetArray[currentApertureNumber]];1005 1006 //Load in the current set of dot array for easy handling1007 //dotArray = dotArray2d[currentSetArray[currentApertureNumber]]; //Global variable, so the draw function also uses this array10081009 //Loop through the dots one by one and update them accordingly1010 for (var i = 0; i < nDots; i++) {1011 var dot = dotArray[i]; //Load the current dot into the variable for easy handling1012 1013 //Generate a random value1014 var randomValue = Math.random();10151016 //Update based on the dot's update type1017 if (dot.updateType == "constant direction") {1018 dot = constantDirectionUpdate(dot);1019 } else if (dot.updateType == "opposite direction") {1020 dot = oppositeDirectionUpdate(dot);1021 } else if (dot.updateType == "random position") {1022 dot = resetLocation(dot);1023 } else if (dot.updateType == "random walk") {1024 dot = randomWalkUpdate(dot);1025 } else if (dot.updateType == "random direction") {1026 dot = randomDirectionUpdate(dot);1027 } else if (dot.updateType == "constant direction or opposite direction or random position") {1028 1029 //Randomly select if the dot goes in a constant direction or random position, weighted based on the coherence level1030 if (randomValue < coherence) {1031 dot = constantDirectionUpdate(dot);1032 } else if(randomValue >= coherence && randomValue < (coherence + oppositeCoherence)){1033 dot = oppositeDirectionUpdate(dot);1034 } else {1035 dot = resetLocation(dot);1036 }1037 } else if (dot.updateType == "constant direction or opposite direction or random walk") {1038 //Randomly select if the dot goes in a constant direction or random walk, weighted based on the coherence level1039 if (randomValue < coherence) {1040 dot = constantDirectionUpdate(dot);1041 } else if(randomValue >= coherence && randomValue < (coherence + oppositeCoherence)){1042 dot = oppositeDirectionUpdate(dot);1043 } else {1044 dot = randomWalkUpdate(dot);1045 }1046 } else if (dot.updateType == "constant direction or opposite direction or random direction") {1047 //Randomly select if the dot goes in a constant direction or random direction, weighted based on the coherence level1048 if (randomValue < coherence) {1049 dot = constantDirectionUpdate(dot);1050 } else if(randomValue >= coherence && randomValue < (coherence + oppositeCoherence)){1051 dot = oppositeDirectionUpdate(dot);1052 } else {1053 dot = randomDirectionUpdate(dot);1054 }1055 }//End of if dot.updateType == ...10561057 //Increment the life count1058 dot.lifeCount++;10591060 //Check if out of bounds or if life ended1061 if (lifeEnded(dot)) {1062 dot = resetLocation(dot);1063 }10641065 //If it goes out of bounds, do what is necessary (reinsert randomly or reinsert on the opposite edge) based on the parameter chosen1066 if (outOfBounds(dot)) {1067 switch (reinsertType) {1068 case 1:1069 dot = resetLocation(dot);1070 break;1071 case 2:1072 dot = reinsertOnOppositeEdge(dot);1073 break;1074 } //End of switch statement1075 } //End of if10761077 } //End of for loop1078 } //End of updateDots function10791080 //Function to check if dot life has ended1081 function lifeEnded(dot) {1082 //If we want infinite dot life1083 if (dotLife < 0) {1084 dot.lifeCount = 0; //resetting to zero to save memory. Otherwise it might increment to huge numbers.1085 return false;1086 }1087 //Else if the dot's life has reached its end1088 else if (dot.lifeCount >= dotLife) {1089 dot.lifeCount = 0;1090 return true;1091 }1092 //Else the dot's life has not reached its end1093 else {1094 return false;1095 }1096 }10971098 //Function to check if dot is out of bounds1099 function outOfBounds(dot) {1100 //For circle and ellipse1101 if (apertureType == 1 || apertureType == 2) {1102 if (dot.x < xValueNegative(dot.y) || dot.x > xValuePositive(dot.y) || dot.y < yValueNegative(dot.x) || dot.y > yValuePositive(dot.x)) {1103 return true;1104 } else {1105 return false;1106 }1107 }1108 //For square and rectangle1109 if (apertureType == 3 || apertureType == 4) {1110 if (dot.x < (apertureCenterX) - horizontalAxis || dot.x > (apertureCenterX) + horizontalAxis || dot.y < (apertureCenterY) - verticalAxis || dot.y > (apertureCenterY) + verticalAxis) {1111 return true;1112 } else {1113 return false;1114 }1115 }11161117 }11181119 //Set the vx and vy for the dot to the coherent jump sizes of the X and Y directions1120 function setvxvy(dot) {1121 dot.vx = coherentJumpSizeX;1122 dot.vy = coherentJumpSizeY;1123 return dot;1124 }11251126 //Set the vx2 and vy2 based on a random angle1127 function setvx2vy2(dot) {1128 //Generate a random angle of movement1129 var theta = randomNumberBetween(-Math.PI, Math.PI);1130 //Update properties vx2 and vy2 with the alternate directions1131 dot.vx2 = Math.cos(theta) * moveDistance;1132 dot.vy2 = -Math.sin(theta) * moveDistance;1133 return dot;1134 }11351136 //Updates the x and y coordinates by moving it in the x and y coherent directions1137 function constantDirectionUpdate(dot) {1138 dot.x += dot.vx;1139 dot.y += dot.vy;1140 dot.latestXMove = dot.vx;1141 dot.latestYMove = dot.vy;1142 return dot;1143 }11441145 //Updates the x and y coordinates by moving it in the opposite x and y coherent directions1146 function oppositeDirectionUpdate(dot) {1147 dot.x -= dot.vx;1148 dot.y -= dot.vy;1149 dot.latestXMove = -dot.vx;1150 dot.latestYMove = -dot.vy;1151 return dot;1152 }11531154 //Creates a new angle to move towards and updates the x and y coordinates1155 function randomWalkUpdate(dot) {1156 //Generate a random angle of movement1157 var theta = randomNumberBetween(-Math.PI, Math.PI);1158 //Generate the movement from the angle1159 dot.latestXMove = Math.cos(theta) * moveDistance;1160 dot.latestYMove = -Math.sin(theta) * moveDistance;1161 //Update x and y coordinates with the new location1162 dot.x += dot.latestXMove;1163 dot.y += dot.latestYMove;1164 return dot;1165 }11661167 //Updates the x and y coordinates with the alternative move direction1168 function randomDirectionUpdate(dot) {1169 dot.x += dot.vx2;1170 dot.y += dot.vy2;1171 dot.latestXMove = dot.vx2;1172 dot.latestYMove = dot.vy2;1173 return dot;1174 }11751176 //Calculates a random position on the opposite edge to reinsert the dot1177 function reinsertOnOppositeEdge(dot) {1178 //If it is a circle or ellipse1179 if (apertureType == 1 || apertureType == 2) {1180 //Bring the dot back into the aperture by moving back one step1181 dot.x -= dot.latestXMove;1182 dot.y -= dot.latestYMove;11831184 //Move the dot to the position relative to the origin to be reflected about the origin1185 dot.x -= apertureCenterX;1186 dot.y -= apertureCenterY;11871188 //Reflect the dot about the origin1189 dot.x = -dot.x;1190 dot.y = -dot.y;11911192 //Move the dot back to the center of the screen1193 dot.x += apertureCenterX;1194 dot.y += apertureCenterY;11951196 } //End of if apertureType == 1 | == 211971198 //If it is a square or rectangle, re-insert on one of the opposite edges1199 if (apertureType == 3 || apertureType == 4) {12001201 /* The formula for calculating whether a dot appears from the vertical edge (left or right edges) is dependent on the direction of the dot and the ratio of the vertical and horizontal edge lengths.1202 E.g. 1203 Aperture is 100 px high and 200px wide1204 Dot is moving 3 px in x direction and 4px in y direction1205 Weight on vertical edge (sides) = (100/(100+200)) * (|3| / (|3| + |4|)) = 1/71206 Weight on horizontal edge (top or bottom) = (200/(100+200)) * (|4| / (|3| + |4|)) = 8/211207 1208 The weights above are the ratios to one another.1209 E.g. (cont.)1210 Ratio (vertical edge : horizontal edge) == (1/7 : 8/21)1211 Total probability space = 1/7 + 8/21 = 11/211212 Probability that dot appears on vertical edge = (1/7)/(11/21) = 3/111213 Probability that dot appears on horizontal edge = (8/21)/(11/21) = 8/111214 */12151216 //Get the absolute values of the latest X and Y moves and store them in variables for easy handling.1217 var absX = Math.abs(dot.latestXMove);1218 var absY = Math.abs(dot.latestYMove);1219 //Calculate the direction weights based on direction the dot was moving1220 var weightInXDirection = absX / (absX + absY);1221 var weightInYDirection = absY / (absX + absY);1222 //Calculate the weight of the edge the dot should appear from, based on direction of dot and ratio of the aperture edges1223 var weightOnVerticalEdge = (verticalAxis / (verticalAxis + horizontalAxis)) * weightInXDirection;1224 var weightOnHorizontalEdge = (horizontalAxis / (verticalAxis + horizontalAxis)) * weightInYDirection;122512261227 //Generate a bounded random number to determine if the dot should appear on the vertical edge or the horizontal edge1228 if (weightOnVerticalEdge > (weightOnHorizontalEdge + weightOnVerticalEdge) * Math.random()) { //If yes, appear on the left or right edge (vertical edge)1229 if (dot.latestXMove < 0) { //If dots move left, appear on right edge1230 dot.x = apertureCenterX + horizontalAxis;1231 dot.y = randomNumberBetween((apertureCenterY) - verticalAxis, (apertureCenterY) + verticalAxis);1232 } else { //Else dots move right, so they should appear on the left edge1233 dot.x = apertureCenterX - horizontalAxis;1234 dot.y = randomNumberBetween((apertureCenterY) - verticalAxis, (apertureCenterY) + verticalAxis);1235 }1236 } else { //Else appear on the top or bottom edge (horizontal edge)1237 if (dot.latestYMove < 0) { //If dots move upwards, then appear on bottom edge1238 dot.y = apertureCenterY + verticalAxis;1239 dot.x = randomNumberBetween((apertureCenterX) - horizontalAxis, (apertureCenterX) + horizontalAxis)1240 } else { //If dots move downwards, then appear on top edge1241 dot.y = apertureCenterY - verticalAxis;1242 dot.x = randomNumberBetween((apertureCenterX) - horizontalAxis, (apertureCenterX) + horizontalAxis)1243 }1244 }1245 } //End of apertureType == 31246 return dot;1247 } //End of reinsertOnOppositeEdge12481249 //Calculate the POSITIVE y value of a point on the edge of the ellipse given an x-value1250 function yValuePositive(x) {1251 var x = x - (apertureCenterX); //Bring it back to the (0,0) center to calculate accurately (ignore the y-coordinate because it is not necessary for calculation)1252 return verticalAxis * Math.sqrt(1 - (Math.pow(x, 2) / Math.pow(horizontalAxis, 2))) + apertureCenterY; //Calculated the positive y value and added apertureCenterY to recenter it on the screen 1253 }12541255 //Calculate the NEGATIVE y value of a point on the edge of the ellipse given an x-value1256 function yValueNegative(x) {1257 var x = x - (apertureCenterX); //Bring it back to the (0,0) center to calculate accurately (ignore the y-coordinate because it is not necessary for calculation)1258 return -verticalAxis * Math.sqrt(1 - (Math.pow(x, 2) / Math.pow(horizontalAxis, 2))) + apertureCenterY; //Calculated the negative y value and added apertureCenterY to recenter it on the screen1259 }12601261 //Calculate the POSITIVE x value of a point on the edge of the ellipse given a y-value1262 function xValuePositive(y) {1263 var y = y - (apertureCenterY); //Bring it back to the (0,0) center to calculate accurately (ignore the x-coordinate because it is not necessary for calculation)1264 return horizontalAxis * Math.sqrt(1 - (Math.pow(y, 2) / Math.pow(verticalAxis, 2))) + apertureCenterX; //Calculated the positive x value and added apertureCenterX to recenter it on the screen1265 }12661267 //Calculate the NEGATIVE x value of a point on the edge of the ellipse given a y-value1268 function xValueNegative(y) {1269 var y = y - (apertureCenterY); //Bring it back to the (0,0) center to calculate accurately (ignore the x-coordinate because it is not necessary for calculation)1270 return -horizontalAxis * Math.sqrt(1 - (Math.pow(y, 2) / Math.pow(verticalAxis, 2))) + apertureCenterX; //Calculated the negative x value and added apertureCenterX to recenter it on the screen1271 }12721273 //Calculate a random x and y coordinate in the ellipse1274 function resetLocation(dot) {12751276 //For circle and ellipse1277 if (apertureType == 1 || apertureType == 2) {1278 var phi = randomNumberBetween(-Math.PI, Math.PI);1279 var rho = Math.random();12801281 x = Math.sqrt(rho) * Math.cos(phi);1282 y = Math.sqrt(rho) * Math.sin(phi);12831284 x = x * horizontalAxis + apertureCenterX;1285 y = y * verticalAxis + apertureCenterY;12861287 dot.x = x;1288 dot.y = y;1289 }1290 //For square and rectangle1291 else if (apertureType == 3 || apertureType == 4) {1292 dot.x = randomNumberBetween((apertureCenterX) - horizontalAxis, (apertureCenterX) + horizontalAxis); //Between the left and right edges of the square / rectangle1293 dot.y = randomNumberBetween((apertureCenterY) - verticalAxis, (apertureCenterY) + verticalAxis); //Between the top and bottom edges of the square / rectangle1294 }12951296 return dot;1297 }12981299 //Generates a random number (with decimals) between 2 values1300 function randomNumberBetween(lowerBound, upperBound) {1301 return lowerBound + Math.random() * (upperBound - lowerBound);1302 }1303 1304 //Function to make the dots move on the canvas1305 function animateDotMotion() {1306 //frameRequestID saves a long integer that is the ID of this frame request. The ID is then used to terminate the request below.1307 var frameRequestID = window.requestAnimationFrame(animate);1308 1309 //Start to listen to subject's key responses1310 startKeyboardListener(); 1311 1312 //Delare a timestamp1313 var previousTimestamp;1314 1315 function animate() {1316 //If stopping condition has been reached, then stop the animation1317 if (stopDotMotion) {1318 window.cancelAnimationFrame(frameRequestID); //Cancels the frame request1319 }1320 //Else continue with another frame request1321 else {1322 frameRequestID = window.requestAnimationFrame(animate); //Calls for another frame request1323 1324 //If the timer has not been started and it is set, then start the timer1325 if ( (!timerHasStarted) && (trial.trial_duration > 0) ){1326 //If the trial duration is set, then set a timer to count down and call the end_trial function when the time is up1327 //(If the subject did not press a valid keyboard response within the trial duration, then this will end the trial)1328 timeoutID = window.setTimeout(end_trial,trial.trial_duration); //This timeoutID is then used to cancel the timeout should the subject press a valid key1329 //The timer has started, so we set the variable to true so it does not start more timers1330 timerHasStarted = true;1331 }1332 1333 updateAndDraw(); //Update and draw each of the dots in their respective apertures1334 1335 //If this is before the first frame, then start the timestamp1336 if(previousTimestamp === undefined){1337 previousTimestamp = performance.now();1338 }1339 //Else calculate the time and push it into the array1340 else{1341 var currentTimeStamp = performance.now(); //Variable to hold current timestamp1342 frameRate.push(currentTimeStamp - previousTimestamp); //Push the interval into the frameRate array1343 previousTimestamp = currentTimeStamp; //Reset the timestamp1344 }1345 }1346 }1347 }13481349 //----RDK Functions End----1350 1351 //----General Functions Begin//----1352 1353 //Function to assign the default values for the staircase parameters1354 function assignParameterValue(argument, defaultValue){1355 return typeof argument !== 'undefined' ? argument : defaultValue;1356 }1357 1358 //----General Functions End//----135913601361 //-------------------------------------1362 //-----------FUNCTIONS END-------------1363 //-------------------------------------136413651366 }; // END OF TRIAL13671368 //Return the plugin object which contains the trial1369 return plugin;
...
bsdfs.glsl.js
Source:bsdfs.glsl.js
1export default /* glsl */`2// Analytical approximation of the DFG LUT, one half of the3// split-sum approximation used in indirect specular lighting.4// via 'environmentBRDF' from "Physically Based Shading on Mobile"5// https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile6vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {7 const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );8 const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );9 vec4 r = roughness * c0 + c1;10 float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;11 return vec2( -1.04, 1.04 ) * a004 + r.zw;12}13float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {14#if defined ( PHYSICALLY_CORRECT_LIGHTS )15 // based upon Frostbite 3 Moving to Physically-based Rendering16 // page 32, equation 26: E[window1]17 // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf18 // this is intended to be used on spot and point lights who are represented as luminous intensity19 // but who must be converted to luminous irradiance for surface lighting calculation20 float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );21 if( cutoffDistance > 0.0 ) {22 distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );23 }24 return distanceFalloff;25#else26 if( cutoffDistance > 0.0 && decayExponent > 0.0 ) {27 return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );28 }29 return 1.0;30#endif31}32vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {33 return RECIPROCAL_PI * diffuseColor;34} // validated35vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {36 // Original approximation by Christophe Schlick '9437 // float fresnel = pow( 1.0 - dotLH, 5.0 );38 // Optimized variant (presented by Epic at SIGGRAPH '13)39 // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf40 float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );41 return ( 1.0 - specularColor ) * fresnel + specularColor;42} // validated43vec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {44 // See F_Schlick45 float fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );46 vec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;47 return Fr * fresnel + F0;48}49// Microfacet Models for Refraction through Rough Surfaces - equation (34)50// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html51// alpha is "roughness squared" in Disneyâs reparameterization52float G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {53 // geometry term (normalized) = G(l)â
G(v) / 4(nâ
l)(nâ
v)54 // also see #1215155 float a2 = pow2( alpha );56 float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );57 float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );58 return 1.0 / ( gl * gv );59} // validated60// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 261// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf62float G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {63 float a2 = pow2( alpha );64 // dotNL and dotNV are explicitly swapped. This is not a mistake.65 float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );66 float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );67 return 0.5 / max( gv + gl, EPSILON );68}69// Microfacet Models for Refraction through Rough Surfaces - equation (33)70// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html71// alpha is "roughness squared" in Disneyâs reparameterization72float D_GGX( const in float alpha, const in float dotNH ) {73 float a2 = pow2( alpha );74 float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 175 return RECIPROCAL_PI * a2 / pow2( denom );76}77// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility78vec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {79 float alpha = pow2( roughness ); // UE4's roughness80 vec3 halfDir = normalize( incidentLight.direction + viewDir );81 float dotNL = saturate( dot( normal, incidentLight.direction ) );82 float dotNV = saturate( dot( normal, viewDir ) );83 float dotNH = saturate( dot( normal, halfDir ) );84 float dotLH = saturate( dot( incidentLight.direction, halfDir ) );85 vec3 F = F_Schlick( specularColor, dotLH );86 float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );87 float D = D_GGX( alpha, dotNH );88 return F * ( G * D );89} // validated90// Rect Area Light91// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines92// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt93// code: https://github.com/selfshadow/ltc_code/94vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {95 const float LUT_SIZE = 64.0;96 const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;97 const float LUT_BIAS = 0.5 / LUT_SIZE;98 float dotNV = saturate( dot( N, V ) );99 // texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) )100 vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );101 uv = uv * LUT_SCALE + LUT_BIAS;102 return uv;103}104float LTC_ClippedSphereFormFactor( const in vec3 f ) {105 // Real-Time Area Lighting: a Journey from Research to Production (p.102)106 // An approximation of the form factor of a horizon-clipped rectangle.107 float l = length( f );108 return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );109}110vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {111 float x = dot( v1, v2 );112 float y = abs( x );113 // rational polynomial approximation to theta / sin( theta ) / 2PI114 float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;115 float b = 3.4175940 + ( 4.1616724 + y ) * y;116 float v = a / b;117 float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;118 return cross( v1, v2 ) * theta_sintheta;119}120vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {121 // bail if point is on back side of plane of light122 // assumes ccw winding order of light vertices123 vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];124 vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];125 vec3 lightNormal = cross( v1, v2 );126 if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );127 // construct orthonormal basis around N128 vec3 T1, T2;129 T1 = normalize( V - N * dot( V, N ) );130 T2 = - cross( N, T1 ); // negated from paper; possibly due to a different handedness of world coordinate system131 // compute transform132 mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );133 // transform rect134 vec3 coords[ 4 ];135 coords[ 0 ] = mat * ( rectCoords[ 0 ] - P );136 coords[ 1 ] = mat * ( rectCoords[ 1 ] - P );137 coords[ 2 ] = mat * ( rectCoords[ 2 ] - P );138 coords[ 3 ] = mat * ( rectCoords[ 3 ] - P );139 // project rect onto sphere140 coords[ 0 ] = normalize( coords[ 0 ] );141 coords[ 1 ] = normalize( coords[ 1 ] );142 coords[ 2 ] = normalize( coords[ 2 ] );143 coords[ 3 ] = normalize( coords[ 3 ] );144 // calculate vector form factor145 vec3 vectorFormFactor = vec3( 0.0 );146 vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );147 vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );148 vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );149 vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );150 // adjust for horizon clipping151 float result = LTC_ClippedSphereFormFactor( vectorFormFactor );152/*153 // alternate method of adjusting for horizon clipping (see referece)154 // refactoring required155 float len = length( vectorFormFactor );156 float z = vectorFormFactor.z / len;157 const float LUT_SIZE = 64.0;158 const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;159 const float LUT_BIAS = 0.5 / LUT_SIZE;160 // tabulated horizon-clipped sphere, apparently...161 vec2 uv = vec2( z * 0.5 + 0.5, len );162 uv = uv * LUT_SCALE + LUT_BIAS;163 float scale = texture2D( ltc_2, uv ).w;164 float result = len * scale;165*/166 return vec3( result );167}168// End Rect Area Light169// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile170vec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {171 float dotNV = saturate( dot( normal, viewDir ) );172 vec2 brdf = integrateSpecularBRDF( dotNV, roughness );173 return specularColor * brdf.x + brdf.y;174} // validated175// Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"176// Approximates multiscattering in order to preserve energy.177// http://www.jcgt.org/published/0008/01/03/178void BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {179 float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );180 vec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );181 vec2 brdf = integrateSpecularBRDF( dotNV, roughness );182 vec3 FssEss = F * brdf.x + brdf.y;183 float Ess = brdf.x + brdf.y;184 float Ems = 1.0 - Ess;185 vec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619; // 1/21186 vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );187 singleScatter += FssEss;188 multiScatter += Fms * Ems;189}190float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {191 // geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)192 return 0.25;193}194float D_BlinnPhong( const in float shininess, const in float dotNH ) {195 return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );196}197vec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {198 vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );199 //float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );200 //float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );201 float dotNH = saturate( dot( geometry.normal, halfDir ) );202 float dotLH = saturate( dot( incidentLight.direction, halfDir ) );203 vec3 F = F_Schlick( specularColor, dotLH );204 float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );205 float D = D_BlinnPhong( shininess, dotNH );206 return F * ( G * D );207} // validated208// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html209float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {210 return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );211}212float BlinnExponentToGGXRoughness( const in float blinnExponent ) {213 return sqrt( 2.0 / ( blinnExponent + 2.0 ) );214}215#if defined( USE_SHEEN )216// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L94217float D_Charlie(float roughness, float NoH) {218 // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF"219 float invAlpha = 1.0 / roughness;220 float cos2h = NoH * NoH;221 float sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16222 return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);223}224// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L136225float V_Neubelt(float NoV, float NoL) {226 // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"227 return saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));228}229vec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {230 vec3 N = geometry.normal;231 vec3 V = geometry.viewDir;232 vec3 H = normalize( V + L );233 float dotNH = saturate( dot( N, H ) );234 return specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );235}236#endif...
sm-std-basic.js
Source:sm-std-basic.js
1import Common from './common';2const { Create, Update, Delete, Dot, Import, Export, Detail, CreateType, UpdateOrder } = Common;3const GroupName = 'AbpStdBasic';4const GroupNameComponentCategories = GroupName + Dot + 'ComponentCategories';5const ComponentCategories = {6 Default: GroupNameComponentCategories,7 Create: GroupNameComponentCategories + Dot + Create,8 Update: GroupNameComponentCategories + Dot + Update,9 Delete: GroupNameComponentCategories + Dot + Delete,10 Detail: GroupNameComponentCategories + Dot + Detail,11 Import: GroupNameComponentCategories + Dot + Import,12 Export: GroupNameComponentCategories + Dot + Export,13};14const GroupNameProductCategories = GroupName + Dot + 'ProductCategories';15const ProductCategories = {16 Default: GroupNameProductCategories,17 Create: GroupNameProductCategories + Dot + Create,18 Update: GroupNameProductCategories + Dot + Update,19 Delete: GroupNameProductCategories + Dot + Delete,20 Detail: GroupNameProductCategories + Dot + Detail,21 Import: GroupNameProductCategories + Dot + Import,22 Export: GroupNameProductCategories + Dot + Export,23};24const GroupNameWorkAttention = GroupName + Dot + 'WorkAttention';25const WorkAttention = {26 Default: GroupNameWorkAttention,27 Create: GroupNameWorkAttention + Dot + Create,28 Update: GroupNameWorkAttention + Dot + Update,29 Delete: GroupNameWorkAttention + Dot + Delete,30 Detail: GroupNameWorkAttention + Dot + Detail,31 CreateType: GroupNameWorkAttention + Dot + CreateType,32};33const GroupNameManufactures = GroupName + Dot + 'Manufactures';34const Manufactures = {35 Default: GroupNameManufactures,36 Create: GroupNameManufactures + Dot + Create,37 Update: GroupNameManufactures + Dot + Update,38 Delete: GroupNameManufactures + Dot + Delete,39 Detail: GroupNameManufactures + Dot + Detail,40 Import: GroupNameManufactures + Dot + Import,41 Export: GroupNameManufactures + Dot + Export,42};43const GroupNameStandardEquipments = GroupName + Dot + 'StandardEquipments';44const StandardEquipments = {45 Default: GroupNameStandardEquipments,46 Create: GroupNameStandardEquipments + Dot + Create,47 Update: GroupNameStandardEquipments + Dot + Update,48 Delete: GroupNameStandardEquipments + Dot + Delete,49 Detail: GroupNameStandardEquipments + Dot + Detail,50 Import: GroupNameStandardEquipments + Dot + Import,51 Export: GroupNameStandardEquipments + Dot + Export,52};53const GroupNameTerminals = GroupName + Dot + 'Terminals';54const Terminals = {55 Default: GroupNameTerminals,56 Create: GroupNameTerminals + Dot + Create,57 Update: GroupNameTerminals + Dot + Update,58 Delete: GroupNameTerminals + Dot + Delete,59 Detail: GroupNameTerminals + Dot + Detail,60};61const GroupNameRepairGroup = GroupName + Dot + 'RepairGroup';62const RepairGroup = {63 Default: GroupNameRepairGroup,64 Create: GroupNameRepairGroup + Dot + Create,65 Update: GroupNameRepairGroup + Dot + Update,66 Delete: GroupNameRepairGroup + Dot + Delete,67 Detail: GroupNameRepairGroup + Dot + Detail,68};69const GroupNameRepairItems = GroupName + Dot + 'RepairItems';70const RepairItems = {71 Default: GroupNameRepairItems,72 Create: GroupNameRepairItems + Dot + Create,73 Update: GroupNameRepairItems + Dot + Update,74 Delete: GroupNameRepairItems + Dot + Delete,75 Detail: GroupNameRepairItems + Dot + Detail,76 CreateTagMigration: GroupNameRepairItems + Dot + 'CreateTagMigration',77};78const GroupNameRepairTestItems = GroupName + Dot + 'RepairTestItems';79const RepairTestItems = {80 Default: GroupNameRepairTestItems,81 Create: GroupNameRepairTestItems + Dot + Create,82 Update: GroupNameRepairTestItems + Dot + Update,83 Delete: GroupNameRepairTestItems + Dot + Delete,84 Detail: GroupNameRepairTestItems + Dot + Detail,85 UpdateOrder: GroupNameRepairTestItems + Dot + UpdateOrder,86 Upgrade: GroupNameRepairTestItems + Dot + 'Upgrade',87};88const GroupNameInfluenceRanges = GroupName + Dot + 'InfluenceRanges';89const InfluenceRanges = {90 Default: GroupNameInfluenceRanges,91 Create: GroupNameInfluenceRanges + Dot + Create,92 Update: GroupNameInfluenceRanges + Dot + Update,93 Delete: GroupNameInfluenceRanges + Dot + Delete,94 Detail: GroupNameInfluenceRanges + Dot + Detail,95};96const GroupNameMVDCategory = GroupName + Dot + 'MVDCategory';97const MVDCategory = {98 Default: GroupNameMVDCategory,99 Create: GroupNameMVDCategory + Dot + Create,100 Update: GroupNameMVDCategory + Dot + Update,101 Delete: GroupNameMVDCategory + Dot + Delete,102 Detail: GroupNameMVDCategory + Dot + Detail,103 Import: GroupNameMVDCategory + Dot + Import,104 Export: GroupNameMVDCategory + Dot + Export,105};106const GroupNameMVDProperty = GroupName + Dot + 'MVDProperty';107const MVDProperty = {108 Default: GroupNameMVDProperty,109 Create: GroupNameMVDProperty + Dot + Create,110 Update: GroupNameMVDProperty + Dot + Update,111 Delete: GroupNameMVDProperty + Dot + Delete,112 Detail: GroupNameMVDProperty + Dot + Detail,113 Import: GroupNameMVDProperty + Dot + Import,114 Export: GroupNameMVDProperty + Dot + Export,115};116const GroupNameProjectItems = GroupName + Dot + 'ProjectItems';117const ProjectItems = {118 Default: GroupNameProjectItems,119 Create: GroupNameProjectItems + Dot + Create,120 Update: GroupNameProjectItems + Dot + Update,121 Delete: GroupNameProjectItems + Dot + Delete,122 Detail: GroupNameProjectItems + Dot + Detail,123 Import: GroupNameProjectItems + Dot + Import,124 Export: GroupNameProjectItems + Dot + Export,125};126const GroupNameIndividualProjects = GroupName + Dot + 'IndividualProjects';127const IndividualProjects = {128 Default: GroupNameIndividualProjects,129 Create: GroupNameIndividualProjects + Dot + Create,130 Update: GroupNameIndividualProjects + Dot + Update,131 Delete: GroupNameIndividualProjects + Dot + Delete,132 Detail: GroupNameIndividualProjects + Dot + Detail,133 Import: GroupNameIndividualProjects + Dot + Import,134 Export: GroupNameIndividualProjects + Dot + Export,135};136const GroupNameProcessTemplates = GroupName + Dot + 'ProcessTemplates';137const ProcessTemplates = {138 Default: GroupNameProcessTemplates,139 Create: GroupNameProcessTemplates + Dot + Create,140 Update: GroupNameProcessTemplates + Dot + Update,141 Delete: GroupNameProcessTemplates + Dot + Delete,142 Detail: GroupNameProcessTemplates + Dot + Detail,143 Import: GroupNameProcessTemplates + Dot + Import,144 Export: GroupNameProcessTemplates + Dot + Export,145};146const GroupNameQuotaCategorys = GroupName + Dot + 'QuotaCategorys';147const QuotaCategorys = {148 Default: GroupNameQuotaCategorys ,149 Create: GroupNameQuotaCategorys + Dot + Create,150 Update: GroupNameQuotaCategorys + Dot + Update,151 Delete: GroupNameQuotaCategorys + Dot + Delete,152 Detail: GroupNameQuotaCategorys + Dot + Detail,153 Import: GroupNameQuotaCategorys + Dot + Import,154 Export: GroupNameQuotaCategorys + Dot + Export,155};156const GroupNameQuotas = GroupName + Dot + 'Quotas';157const Quotas = {158 Default: GroupNameQuotas ,159 Create: GroupNameQuotas + Dot + Create,160 Update: GroupNameQuotas + Dot + Update,161 Delete: GroupNameQuotas + Dot + Delete,162 Detail: GroupNameQuotas + Dot + Detail,163 Import: GroupNameQuotas + Dot + Import,164 Export: GroupNameQuotas + Dot + Export,165};166const GroupNameQuotaItems = GroupName + Dot + 'QuotaItems';167const QuotaItems = {168 Default: GroupNameQuotaItems ,169 Create: GroupNameQuotaItems + Dot + Create,170 Update: GroupNameQuotaItems + Dot + Update,171 Delete: GroupNameQuotaItems + Dot + Delete,172 Detail: GroupNameQuotaItems + Dot + Detail,173 Import: GroupNameQuotaItems + Dot + Import,174 Export: GroupNameQuotaItems + Dot + Export,175};176const GroupNameBasePrices = GroupName + Dot + 'BasePrices';177const BasePrices = {178 Default: GroupNameBasePrices ,179 Create: GroupNameBasePrices + Dot + Create,180 Update: GroupNameBasePrices + Dot + Update,181 Delete: GroupNameBasePrices + Dot + Delete,182 Detail: GroupNameBasePrices + Dot + Detail,183 Import: GroupNameBasePrices + Dot + Import,184 Export: GroupNameBasePrices + Dot + Export,185};186const GroupNameComputerCodes = GroupName + Dot + 'ComputerCodes';187const ComputerCodes = {188 Default: GroupNameComputerCodes ,189 Create: GroupNameComputerCodes + Dot + Create,190 Update: GroupNameComputerCodes + Dot + Update,191 Delete: GroupNameComputerCodes + Dot + Delete,192 Detail: GroupNameComputerCodes + Dot + Detail,193 Import: GroupNameComputerCodes + Dot + Import,194 Export: GroupNameComputerCodes + Dot + Export,195};196export default {197 GroupName,198 WorkAttention,199 ComponentCategories,200 ProductCategories,201 Manufactures,202 StandardEquipments,203 Terminals,204 RepairGroup,205 RepairItems,206 RepairTestItems,207 InfluenceRanges,208 MVDProperty,209 MVDCategory,210 ProjectItems,211 IndividualProjects,212 ProcessTemplates,213 QuotaCategorys,214 Quotas,215 QuotaItems,216 BasePrices,217 ComputerCodes,...
coolio.js
Source:coolio.js
...43 d_radius: 150,44 array: []45 };46 }47 function Dot(){48 this.x = Math.random() * experience.canvas.width;49 this.y = Math.random() * experience.canvas.height;50 this.vx = -.5 + Math.random();51 this.vy = -.5 + Math.random();52 this.radius = Math.random();53 }54 Dot.prototype = {55 create: function(){56 ctx.beginPath();57 ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);58 ctx.fill();59 }60 };61 Dot.animate = function(){62 var i, dot;63 for(i = 0; i < dots.nb; i++){64 dot = dots.array[i];65 if(dot.y < 0 || dot.y > experience.canvas.height){66 dot.vx = dot.vx;67 dot.vy = - dot.vy;68 }69 else if(dot.x < 0 || dot.x > experience.canvas.width){70 dot.vx = - dot.vx;71 dot.vy = dot.vy;72 }73 dot.x += dot.vx;74 dot.y += dot.vy;75 }76 };77 Dot.line = function(){78 var i, j, i_dot, j_dot;79 for(i = 0; i < dots.nb; i++){80 for(j = 0; j < dots.nb; j++){81 i_dot = dots.array[i];82 j_dot = dots.array[j];83 if((i_dot.x - mousePosition.x) < dots.d_radius && (i_dot.y - mousePosition.y) < dots.d_radius && (i_dot.x - mousePosition.x) > - dots.d_radius && (i_dot.y - mousePosition.y) > - dots.d_radius){84 if((i_dot.x - j_dot.x) < dots.distance && (i_dot.y - j_dot.y) < dots.distance && (i_dot.x - j_dot.x) > - dots.distance && (i_dot.y - j_dot.y) > - dots.distance){85 ctx.beginPath();86 ctx.moveTo(i_dot.x, i_dot.y);87 ctx.lineTo(j_dot.x, j_dot.y);88 ctx.stroke();89 ctx.closePath();90 }91 }92 }93 }94 };95 function isMobile() {96 return (97 /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)98 )99 };100 function createDots(){101 var i;102 ctx.clearRect(0, 0, experience.canvas.width, experience.canvas.height);103 if(dots.array.length < 1) {104 for(i = 0; i < dots.nb; i++){105 dots.array.push(new Dot());106 }107 }108 for(i = 0; i < dots.nb; i++){109 var dot = dots.array[i];110 dot.create();111 }112 Dot.line();113 Dot.animate();114 }115 $('#experience').on('mousemove mouseleave', function(e){116 if(e.type == 'mousemove'){117 mousePosition.x = e.pageX;118 mousePosition.y = e.pageY;119 }...
ban.js
Source:ban.js
...46 this.g = colorValue(min);47 this.b = colorValue(min);48 this.style = createColorStyle(this.r, this.g, this.b);49 }50 function Dot(){51 this.x = Math.random() * canvas.width;52 this.y = Math.random() * canvas.height;53 this.vx = -.5 + Math.random();54 this.vy = -.5 + Math.random();55 this.radius = Math.random() * 2;56 this.color = new Color();57 }58 Dot.prototype = {59 draw: function(){60 ctx.beginPath();61 ctx.fillStyle = this.color.style;62 ctx.arc(this.x, this.y, this.radius, 0, Math.PI, false);63 ctx.fill();64 }65 };66 function createDots(){67 for(i = 0; i < dots.nb; i++){68 dots.array.push(new Dot());69 }70 }71 function moveDots() {72 for(i = 0; i < dots.nb; i++){73 var dot = dots.array[i];74 if(dot.y < 0 || dot.y > canvas.height){75 dot.vx = dot.vx;76 dot.vy = - dot.vy;77 }78 else if(dot.x < 0 || dot.x > canvas.width){79 dot.vx = - dot.vx;80 dot.vy = dot.vy;81 }82 dot.x += dot.vx;...
morse.js
Source:morse.js
1const dot = "â¢";2const dash = "â";3module.exports = {4 a: dot + dash,5 b: dash + dot + dot + dot,6 c: dash + dot + dash + dot,7 d: dash + dot + dot,8 e: dot,9 f: dot + dot + dash + dot,10 g: dash + dash + dot,11 h: dot + dot + dot + dot,12 i: dot + dot,13 j: dot + dash + dash + dash,14 k: dash + dot + dash,15 l: dot + dash + dot + dot,16 m: dash + dash,17 n: dash + dot,18 o: dash + dash + dash,19 p: dot + dash + dash + dot,20 q: dash + dash + dot + dash,21 r: dot + dash + dot,22 s: dot + dot + dot,23 t: dash,24 u: dot + dot + dash,25 v: dot + dot + dot + dash,26 w: dot + dash + dash,27 x: dash + dot + dot + dash,28 y: dash + dot + dash + dash,29 z: dash + dash + dot + dot,30 0: dash + dash + dash + dash + dash,31 1: dot + dash + dash + dash + dash,32 2: dot + dot + dash + dash + dash,33 3: dot + dot + dot + dash + dash,34 4: dot + dot + dot + dot + dash,35 5: dot + dot + dot + dot + dot,36 6: dash + dot + dot + dot + dot,37 7: dash + dash + dot + dot + dot,38 8: dash + dash + dash + dot + dot,39 9: dash + dash + dash + dash + dot,40 ".": dot + dash + dot + dash + dot + dash,41 ",": dash + dash + dot + dot + dash + dash,42 "?": dot + dot + dash + dash + dot + dot,43 "'": dot + dash + dash + dash + dash + dot,44 "!": dash + dot + dash + dot + dash + dash,45 "/": dash + dot + dot + dash + dot,46 "(": dash + dot + dash + dash + dot,47 ")": dash + dot + dash + dash + dot + dash,48 "&": dot + dash + dot + dot + dot,49 ":": dash + dash + dash + dot + dot + dot,50 ";": dash + dot + dash + dot + dash + dot,51 "=": dash + dot + dot + dot + dash,52 "+": dot + dash + dot + dash + dot,53 "-": dash + dot + dot + dot + dot + dash,54 '"': dot + dash + dot + dot + dash + dot,55 $: dot + dot + dot + dash + dot + dot + dash,56 "@": dot + dash + dash + dot + dash + dot,57 à : dot + dash + dash + dot + dash,58 ä: dot + dash + dot + dash,59 Ã¥: dot + dash + dash + dot + dash,60 Ä
: dot + dash + dot + dash,61 æ: dot + dash + dot + dash,62 Ä: dash + dot + dash + dot + dot,63 Ä: dash + dot + dash + dot + dot,64 ç: dash + dot + dash + dot + dot,65 ch: dash + dash + dash + dash,66 Ä: dot + dot + dash + dot + dot,67 ð: dot + dot + dash + dash + dot,68 é: dot + dot + dash + dot + dot,69 è: dot + dash + dot + dot + dash,70 Ä: dot + dot + dash + dot + dot,71 Ä: dash + dash + dot + dash + dot,72 Ä¥: dash + dash + dash + dash,73 ĵ: dot + dash + dash + dash + dot,74 Å: dot + dash + dot + dot + dash,75 Å: dash + dash + dot + dash + dash,76 ñ: dash + dash + dot + dash + dash,77 ó: dash + dash + dash + dot,78 ö: dash + dash + dash + dot,79 ø: dash + dash + dash + dot,80 Å: dot + dot + dot + dash + dot + dot + dot,81 Å: dot + dot + dot + dash + dot,82 Å¡: dash + dash + dash + dash,83 þ: dot + dash + dash + dot + dot,84 ü: dot + dot + dash + dash,85 Å: dot + dot + dash + dash,86 ź: dash + dash + dot + dot + dash + dot,87 ż: dash + dash + dot + dot + dash,88 " ": "\u2007",...
depsDump.js
Source:depsDump.js
1define([2 "../buildControl",3 "../fileUtils",4 "../fs",5 "dojo/_base/lang",6 "dojo/_base/array",7 "dojo/json"8], function(bc, fileUtils, fs, lang, array, json){9 return function(resource, callback){10 if(!bc.depsDumpDotFilename && !bc.depsDumpFilename){11 return 0;12 }13 var dotModules = 0, traceForDot = {}, traceForDotDone = {};14 if(bc.dotModules){15 dotModules = {};16 array.forEach(bc.dotModules.split(","), function(module){17 dotModules[lang.trim(module)] = traceForDot;18 });19 }20 var modules = [],21 midToId = {},22 i = 0,23 dotOutput = "digraph {\n",24 r, p, destFilename;25 for(p in bc.resources){26 r = bc.resources[p];27 if(r.deps){28 if(!dotModules || dotModules[r.mid]){29 dotModules[r.mid] = traceForDotDone;30 r.deps.forEach(function(module){31 dotOutput += '"' + r.mid + '" -> "' + module.mid + '";\n';32 if (dotModules[module.mid]!==traceForDotDone){33 dotModules[module.mid] = traceForDot;34 }35 });36 }37 r.uid = i;38 midToId[bc.resources[p].mid] = i;39 modules.push(r);40 i++;41 }42 }43 if(bc.depsDumpDotFilename){44 var foundOne = dotModules;45 while(foundOne){46 foundOne = false;47 for(p in bc.resources){48 r = bc.resources[p];49 if(dotModules[r.mid]==traceForDot){50 foundOne = true;51 dotModules[r.mid] = traceForDotDone;52 if(r.deps){53 r.deps.forEach(function(module){54 dotOutput += '"' + r.mid + '" -> "' + module.mid + '";\n';55 if (dotModules[module.mid]!==traceForDotDone){56 dotModules[module.mid] = traceForDot;57 }58 });59 }60 }61 }62 }63 dotOutput += "}\n";64 var filename = fileUtils.computePath(bc.depsDumpDotFilename, bc.destBasePath);65 fileUtils.ensureDirectory(fileUtils.getFilepath(filename));66 fs.writeFileSync(filename, dotOutput, "ascii");67 }68 if(bc.depsDumpFilename){69 var depsTree = modules.map(function(module){70 return module.deps.map(function(item){ return item.uid; });71 }),72 idTree = {},73 getItem = function(parts, bag){74 var part = parts.shift();75 if(!(part in bag)){76 bag[part] = {};77 }78 if(parts.length){79 return getItem(parts, bag[part]);80 }else{81 return bag[part];82 }83 };84 modules.forEach(function(item, i){85 var parts = item.mid.split("/");86 getItem(parts, idTree)["*"] = i;87 });88 filename = fileUtils.computePath(bc.depsDumpFilename, bc.destBasePath);89 fileUtils.ensureDirectory(fileUtils.getFilepath(filename));90 fs.writeFileSync(filename, json.stringify({depsTree:depsTree, idTree:idTree}), "ascii");91 }92 return 0;93 };...
dotconferences.js
Source:dotconferences.js
1export default {2 indexName: 'dotconferences',3 playlists: [4 'PLMW8Xq7bXrG7LL-bLSweRFmFw7y2HhypC', // dotJS 20185 'PLMW8Xq7bXrG702XVNfv_zqfFdt-498iV_', // dotCSS 20186 'PLMW8Xq7bXrG4zEMLdfZTpS9VCKjXeD--h', // dotScale 20187 'PLMW8Xq7bXrG6M2Nabwt3LuBxZyHVHRZhf', // dotAI 20188 'PLMW8Xq7bXrG4OC1CZW7m-davg4p4ZCBmZ', // dotSwift 20189 'PLMW8Xq7bXrG4gs_BDyI7q009IVDUMQRXB', // dotJS 201710 'PLMW8Xq7bXrG7acNjsU5YMGl5MMK5gl2vn', // dotGo 201711 'PLMW8Xq7bXrG7xzLo4j6bDznWzH7ZDc3wx', // dotSecurity 201712 'PLMW8Xq7bXrG4AcSG9ZcqvMQSp6f0C7mi5', // dotSwift 201713 'PLMW8Xq7bXrG78Xxnlxov8N_M9mNUN-1Ny', // dotCSS 201714 'PLMW8Xq7bXrG7fNNYHvpeagKHw4DaUkgud', // dotScale 201715 'PLMW8Xq7bXrG6-vlD0QFfFf0oi5vtTDcmQ', // dotAI 201716 'PLMW8Xq7bXrG6tcAXDsAVATUbrflLOsIG_', // dotGo 201617 'PLMW8Xq7bXrG7AAvnkys8joKEq8uMGykx7', // dotScale 201618 'PLMW8Xq7bXrG7XSuKb3M3bSJ4d1XM0Z-gI', // dotCSS 201619 'PLMW8Xq7bXrG7rZnRaYCel_RJY5yAXLQ2H', // dotJS 201620 'PLMW8Xq7bXrG4jymjKULrw5_yEvK3uzATe', // dotSecurity 201621 'PLMW8Xq7bXrG70G62mxQR0OC4GkUcNLRnC', // dotJS 201522 'PLMW8Xq7bXrG5kujoYQdw94ip3cnV4WR59', // dotCSS 201523 'PLMW8Xq7bXrG4Vw-JAnBmqA2IqzM2sf2Na', // dotGo 201524 'PLMW8Xq7bXrG64KRc6PC0JLWFX2ygzFJDG', // dotScale 201525 'PLMW8Xq7bXrG5B_oW-EX8AuLDG0BCwouis', // dotCSS 201426 'PLMW8Xq7bXrG4bTkovexbhgrcD8BVyHmiS', // dotJS 201427 'PLMW8Xq7bXrG58Qk-9QSy2HRh2WVeIrs7e', // dotGo 201428 'PLMW8Xq7bXrG4pl13YVsKkaAUDeLdnrEQZ', // dotScale 201429 'PLMW8Xq7bXrG6ZItH9Oq2tceeTS0fjXyii', // dotRB 201330 'PLMW8Xq7bXrG77SV1VAAiAciRyq3VSC2Gq', // dotJS 201231 'PLMW8Xq7bXrG486Mh95hKjiXRdci60zUlL', // dotJS 201332 'PLMW8Xq7bXrG7XGG29sXso2hYYNW_14s_A', // dotScale 201333 ],34 transformData(rawRecord, helper) {35 let record = rawRecord;36 // Get conference name from the playlist title37 record = helper.enrich(record, 'playlist.title', '{conference.name} {_}');38 // Extract speaker name and video title from title39 record = helper.enrich(40 record,41 'video.title',42 '{_} - {_speakers_} - {video.title}'43 );44 return record;45 },...
Using AI Code Generation
1var expect = require('chai').expect;2describe('Array', function() {3 describe('#indexOf()', function() {4 it('should return -1 when the value is not present', function() {5 expect([1,2,3].indexOf(4)).to.equal(-1);6 });7 });8});
Using AI Code Generation
1const assert = require('assert');2const User = require('../src/user');3describe('Creating records', () => {4 it('saves a user', (done) => {5 const joe = new User({ name: 'Joe' });6 joe.save()7 .then(() => {8 assert(!joe.isNew);9 done();10 });11 });12});13const mongoose = require('mongoose');14const Schema = mongoose.Schema;15const UserSchema = new Schema({16});17const User = mongoose.model('user', UserSchema);18module.exports = User;19const mongoose = require('mongoose');20mongoose.Promise = global.Promise;21before((done) => {22 .once('open', () => { done(); })23 .on('error', (error) => {24 console.warn('Warning', error);25 });26});27beforeEach((done) => {28 mongoose.connection.collections.users.drop(() => {29 done();30 });31});32afterEach((done) => {33 mongoose.connection.collections.users.drop(() => {34 done();35 });36});37after((done) => {38 mongoose.connection.close();39 done();40});41db.users.find()42const assert = require('assert');43const User = require('../src/user');44describe('Creating records', () => {45 it('saves a user', (
Using AI Code Generation
1const assert = require('assert')2const User = require('../src/user')3describe('Creating records', () => {4 it('saves a user', (done) => {5 const joe = new User({ name: 'Joe' })6 joe.save()7 .then(() => {8 assert(!joe.isNew)9 done()10 })11 })12})13const mongoose = require('mongoose')14const UserSchema = new Schema({15})16const User = mongoose.model('user', UserSchema)17{18 "scripts": {19 },20 "dependencies": {21 },22 "devDependencies": {23 }24}
Using AI Code Generation
1const assert = require('assert');2const MarioChar = require('../models/mariochar');3describe('Finding records', function(){4 var char;5 beforeEach(function(done){6 char = new MarioChar({7 });8 char.save().then(function(){9 assert(char.isNew === false);10 done();11 });12 });13 it('Finds one record from the database', function(done){14 MarioChar.findOne({name: 'Mario'}).then(function(result){15 assert(result.name === 'Mario');16 done();17 });18 });19 it('Finds one record by ID from the database', function(done){20 MarioChar.findOne({_id: char._id}).then(function(result){21 assert(result._id.toString() === char._id.toString());22 done();23 });24 });25});26const mongoose = require('mongoose');27const Schema = mongoose.Schema;28const MarioCharSchema = new Schema({29});30const MarioChar = mongoose.model('mariochar', MarioCharSchema);31module.exports = MarioChar;32 "scripts": {
Using AI Code Generation
1var assert = require('assert');2var chai = require('chai');3var expect = chai.expect;4var should = chai.should();5var request = require('supertest');6var app = require('../app');7var mongoose = require('mongoose');8var db = mongoose.connection;9var User = require('../models/user');10var helpers = require('../helpers/helpers');11describe('User', function() {12 it('should be defined', function() {13 expect(User).to.be.a('function');14 });15 it('should have a name', function() {16 var user = new User({17 });18 expect(user.name).to.equal('Test');19 });20 it('should have a email', function() {21 var user = new User({
Using AI Code Generation
1var assert = require('assert');2var app = require('../app.js');3describe('App', function(){4 it('app should return hello', function(){5 assert.equal(app.hello(), 'hello');6 })7})8module.exports.hello = function(){9 return 'hello';10}11{12 "scripts": {13 },14 "dependencies": {15 },16 "devDependencies": {},17}
Using AI Code Generation
1var assert = require('assert');2var should = require('should');3var request = require('supertest');4var app = require('../app.js');5var expect = require('chai').expect;6describe('Array', function() {7 describe('#indexOf()', function() {8 it('should return -1 when the value is not present', function() {9 assert.equal(-1, [1,2,3].indexOf(5));10 assert.equal(-1, [1,2,3].indexOf(0));11 });12 });13});14describe('String', function() {15 describe('#indexOf()', function() {16 it('should return -1 when the value is not present', function() {17 [1,2,3].indexOf(5).should.equal(-1);18 [1,2,3].indexOf(0).should.equal(-1);19 });20 });21});22describe('Array', function() {23 describe('#indexOf()', function() {24 it('should return -1 when the value is not present', function() {25 expect([1,2,3].indexOf(5)).to.equal(-1);26 expect([1,2,3].indexOf(0)).to.equal(-1);27 });28 });29});30describe('Array', function() {31 describe('#indexOf()', function() {32 it('should return -1 when the value is not present', function() {33 [1,2,3].indexOf(5).should.equal(-1);34 [1,2,3].indexOf(0).should.equal(-1);35 });36 });37});38describe('Array', function() {39 describe('#indexOf()', function() {40 it('should return -1 when the value is not present', function() {41 expect([1,2,3].indexOf(5)).to.equal(-1);42 expect([1,2,3].indexOf(0)).to.equal(-1);43 });44 });45});46describe('GET /', function() {47 it('respond with hello world', function(done) {48 request(app).get('/').expect
Using AI Code Generation
1var assert = require('assert');2var myMath = require('./myMath');3describe('myMath', function(){4 describe('add', function(){5 it('should return 5 when 2 and 3 are passed', function(){6 assert.equal(5, myMath.add(2,3));7 });8 });9 describe('multiply', function(){10 it('should return 6 when 2 and 3 are passed', function(){11 assert.equal(6, myMath.multiply(2,3));12 });13 });14});15var myMath = {16 add: function(a,b){17 return a + b;18 },19 multiply: function(a,b){20 return a * b;21 }22};23module.exports = myMath;
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!