﻿//This JavaScript file implements the game from the paper Jaeggi, Buschkuel, Jonides, & Perrig 
//entitled "Improving fluid intelligence with training on working memory
//Author: Christopher Kanan (ckanan@ucsd.edu)
//Copyright 2008

var base_game_trials = 20;

var debugMode = false;
var gadgetMode = false;

var middlePlus = false;

var eGame_state = {not_running:1, displaying:2, waiting:3};
var game_state;
var timer;


var multiEmbed = false;

var feature_dims = 9;

var color_list = ['red', 'black', 'green', 'blue', 'yellow', 'orange', 'aqua', 'HotPink' , 'RosyBrown'];
var audio_files = ['m', 'b', 'j', 'h', 't', 's', 'd', 'p', 'c'];
var animal_files = ['puppy.jpg', 'panda.jpg', 'duckling.jpg', 'seal.jpg', 'rabbit.jpg', 'kitten.jpg', 'hedgehog.jpg', 'hamster.jpg', 'goat.jpg'];

var events_spatial, events_audio, events_color;

var mainButton;
var button_audio, button_spatial, button_color;

var feature_start;

var last_level = -1;
var current_level = 1;
var current_feat_spatial;
var current_feat_color;
var current_feat_baby;
var current_feat_audio;

var cell;

//game parameters
var grid_x, grid_y; //table
var n_back = 1;
var game_length;
var big_game_length;

var hist_spatial, hist_audio, hist_color;

var audio = null; //used for playing sounds

var image_list = new Array();

var feat_spatial = true;
var feat_color = true;
var feat_audio = true;
var feat_baby = true;

var feedback_spatial, feedback_audio, feedback_color; //cells

var initialized = false;

var charList = [81, 86, 90, 65, 75, 76, 83, 70, 74, 72, 77, 78];

var num_load = 0;

var hostSite = '';
var embedAudio = null;


//set up sound stuff

var flashError = 0;


soundManager.debugMode = false;
soundManager.consoleOnly = false;

//-----------Stats---------------
var start_date = new Date();

var spatial_perf = 0;
var audio_perf = 0;
var color_perf = 0;
var overall = 0;

var hits_spatial = 0;
var false_alarms_spatial = 0;

var hits_audio = 0;
var false_alarms_audio = 0;

var hits_color = 0;
var false_alarms_color = 0;

var trials = 0;
var total_spatial = 0;
var total_audio = 0;
var total_color = 0;
//-------------------------------


soundManager.onload = function() {
	var i, f_url;

        if (debugMode && gadgetMode)
        {
            SetUpSound();
            return;
        }
		
		num_load = num_load + audio_files.length + 1;
			
				
		for (i=0; i < audio_files.length; i++)
		{
			f_url = hostSite + 'Audio/' + audio_files[i] + '.mp3';
			soundManager.createSound({
				id: audio_files[i],
				url: f_url,
				autoLoad: true,
				autoPlay: false,
				volume: 100,
				onload: function() { Loader();}            
			});
		}

		f_url = hostSite + 'Audio/' + 'welcome.mp3';
		
		soundManager.createSound({
			id: 'welcome',
			url: f_url,
			autoLoad: true,
			autoPlay: false,
			volume: 100,
			onload: function() { Loader();}
		});
		
		
		DebugDisplay('Flash audio loaded.');     
	}
    
    //had a problem loading flash
    soundManager.onerror = function() {                
        DebugDisplay('Failed to load flash audio.');                   
        //PlayAudio('welcome');                    
        SetUpSound();
    }
    
    


function SetUpSound()
{
    if (gadgetMode)
    {        
        
        //hostSite = 'http://www.cse.ucsd.edu/~ckanan/';
        //mainButton.removeAttribute('disabled');    
        //mainButton.setAttribute('value', 'Start Game!');    
                                  
        var embedArea = document.getElementById('EmbedArea');
        var i;
        var err;
        
        embedAudio = new Array(audio_files.length);
        
        num_load += audio_files.length;
        
        for (i=0; i < audio_files.length;i++)
        {
            if (multiEmbed)
            {
                embedAudio[num_load] = document.createElement('embed');       
                embedAudio[num_load].setAttribute('hidden', true);
                embedAudio[num_load].setAttribute('autostart', false);    
                embedAudio[num_load].setAttribute('type', 'audio/wav');
                embedAudio[num_load].setAttribute('src', url);
                embedArea.appendChild(embedAudio[num_load]);                                     
            }
         }           
            
            //_IG_FetchContent(hostSite + 'Audio/welcome.wav', Loader);                          
            //PlayAudio('welcome');         
            
        mainButton.removeAttribute('disabled');    
        mainButton.setAttribute('value', 'Start Game!');            
        mainButton.focus();       
        //we have to return for now        
        return;
    }
    else //just hope it works
    {
        mainButton.removeAttribute('disabled');    
        mainButton.setAttribute('value', 'Start Game!');    
        mainButton.focus();       
    }    
}


function DebugDisplay(msg)
{
    if (!debugMode)
        return;
    var debug = document.getElementById('Debug');
    debug.innerHTML = msg + '<br />' + debug.innerHTML;
}





//
function Loader()
{       
    num_load--;        
    DebugDisplay('called loader: ' + num_load);
    
    if (gadgetMode && num_load > 0)
    {           

    }                                      
    
    if (num_load <= 0)
    {
        //PlayAudio('welcome');    
        mainButton.removeAttribute('disabled');    
        mainButton.setAttribute('value', 'Start Game!');            
        mainButton.focus();       
    }        
}

//done with flash sound effects stuff

//x is the number of cells in the x direction
//y is the number of cells in the y direction
//n refers to n-back
//t refers to number of minutes the game should last
function InitGame()
{
    var i;
    var instr_message;

    //these 3 lines are necessary if reset button was pushed
    game_state = eGame_state.not_running;        
    document.onkeydown = null;
    clearTimeout(timer);
            
    SetLevelParams();
              
    max_game_length = n_back + base_game_trials;
           
    var main = document.getElementById('Main');
        
    center = document.createElement('center');    
    main.appendChild(center);
    
    main.innerHTML = '';

	var right = document.createElement('right');
	main.appendChild(right);
	
	if (logged == true)
	{
		right.innerHTML = 'Logged in as: <a href="http://sutas.lt/wp-admin/admin.php?page=gf_game_stats">' + username + ',</a> <a href="'+logout_url+'">logout</a>';
	}
	else
	{
		right.innerHTML = '<span style="color:red">Please <a href="'+login_url+'">login</a>/<a href="'+register_url+'">register</a> before playing game for statistics saving!</span>';
	}
    
    main.appendChild(center);
    

        
    if (!gadgetMode)        
        center.innerHTML = '<h1>The Working Memory and Attention Training Game</h1>' + '<h2>Level ' + level + ': N = ' + n_back + '</h2>';
    else
        center.innerHTML = '<b>The Working Memory and Attention Training Game</b>' + '<br/>Level ' + level + ': N = ' + n_back + '<br/><br />';
    
    center.innerHTML += 'Level ' + level + ' Warp Code: ' + EncodeLevelCode() + '<br \><br \>';
    
    if (!gadgetMode)
    {
            
        instr_message = '<b>Instructions: </b>'

        if (n_back == 1)
        {
            if (feat_spatial)
                instr_message += 'If you see a block "light" up twice in a row then press K.<br />';
            if (feat_audio)
                instr_message += 'If you hear the same sound twice in a row then press D.<br />';    

            if (feat_baby)
                instr_message += 'If you see the same baby animal twice in a row then press SPACE BAR. The location of the block does not matter.<br />';
            else if (feat_color)
                instr_message += 'If you see the same color twice in a row then press SPACE BAR. The location of the block does not matter.<br />';
        }
        else
        {        
            
            if (feat_audio && (feat_spatial || feat_color))
                instr_message += 'This game requires that you remember what you both saw and heard ' + n_back + ' steps before the current block appeared.<br />';
            else if (feat_audio)
                instr_message += 'This game requires that you remember what you heard ' + n_back + ' steps before the current block appeared.<br />';
            else
                instr_message += 'This game requires that you remember what you saw ' + n_back + ' steps before the current block appeared.<br />';
            
            if (feat_spatial)
                instr_message += 'For spatial location, press the K key if you saw something in that block ' + n_back + ' blocks ago.<br />'
            if (feat_audio)
                instr_message += 'For the sounds, press the D key if you heard the same sound ' + n_back + ' blocks ago.<br />'    
            if (feat_baby)
                instr_message += 'For baby animals, press the SPACE BAR if you saw the same baby animal ' + n_back + ' blocks ago. The location does not matter.<br />'                
            else if (feat_color)
                instr_message += 'For colors, press the SPACE BAR if you saw the same color ' + n_back + ' blocks ago. The location does not matter.<br />'                
        }
        
        
        if (feat_spatial && feat_audio && (feat_color || feat_baby))    
            instr_message += 'In a particular round you may need to do nothing, press only K, press only D, press only SPACE BAR, or press some of the keys together.<br />'
        else if (feat_spatial && feat_audio)
            instr_message += 'In a particular round you may need to do nothing, press only K, press only D, or press both D and K.<br />'
                

        instr_message += 'You have until the next block appears to respond.<br />';
        //instr_message += 'If you are confused, try a game or two and you will quickly get the hang of it.<br /><br />';
        instr_message += '<b>While you can use the buttons on the screen, it is much easier to use the buttons on your keyboard.</b><br />';
        
        if (give_feedback)
            instr_message += 'A correct response will make a green light will appear above the appropriate button; a red light will appear instead if you are wrong.';      
               
        center.innerHTML += instr_message;
        
        
        if (n_back == 1)
            center.innerHTML += '<br /><br /><img src="Images/tutorial3.jpg" />';
        else if (n_back == 2)
            center.innerHTML += '<br /><br /><img src="Images/tutorial2.jpg" />';
        
        
        center.innerHTML += '<br />';   
    }
    
    mainButton = document.createElement('input');
    mainButton.setAttribute('type', 'button');    
        
    
    if (!initialized)
    {        
        mainButton.setAttribute('value', 'Loading...');
        mainButton.setAttribute('disabled', true);        
        
        //preload baby animals
        for (i = 0; i < animal_files.length;i++)
        {            
            image_list[i] = new Image();
            image_list[i].src = 'Images/' + animal_files[i];
        }       
    }
    else
    {
        mainButton.setAttribute('value', 'Start Game!');  
        mainButton.focus();       
    }
   

    if (feat_spatial)   
        feature_dims = grid_x * grid_y;
    else
        feature_dims = 8;
                
                
    if (last_level != level)                
        feature_start = Math.round(Math.random() * (8 - feature_dims));        

    DebugDisplay('feature_start=' + feature_start);


   //Ensure images have been preloaded
    if (feat_baby && last_level != level)
    {        
        for (i = feature_start; i < feature_start + feature_dims; i++)
        {                    
            if (!image_list[i].complete)
            {                
                DebugDisplay(animal_files[i] + ' incomplete!');
            
                //we need to do something here
                num_load++;
                image_list[i].onLoad = Loader();                
                
                mainButton.setAttribute('value', 'Loading...');
                mainButton.setAttribute('disabled', true);
            }    
            else
                DebugDisplay(animal_files[i] + ' complete!');
        }     
    }
    last_level = level;

    center.appendChild(mainButton);
    
    mainButton.onclick = function() {PlayGame()};
        
    game_state = eGame_state.not_running;    
           
    
    big_game_length = max_game_length;
    game_length = max_game_length;
    
    hist_spatial = new Array();
    hist_audio = new Array();            
    hist_color = new Array();

    feedback = true; //provide user with feedback if they get the answer right or wrong  
    
    initialized = true;


    //code for level reset button
    passwordLink = document.createElement('a');
    passwordLink.setAttribute('href', '#');
    passwordLink.onclick = function() {HandleWarpCode()}; 
    passwordLink.appendChild(document.createTextNode("Enter Level Warp Code"));
    
    center.appendChild(document.createElement('br'));
    center.appendChild(document.createElement('br'));
    center.appendChild(passwordLink);

	start_date = new Date();
                                    
    return;        
}

function EncodeLevelCode()
{
    var code = '';
    var codedLevel = 0;
    
    if (!traditional_game)
        codedLevel = (level * 1231).toString();
    else
        codedLevel = (level * 1237).toString();
        
        
    codedLevel = parseInt(codedLevel, 17);
    codedLevel = codedLevel.toString();
          
    
    for (var i = 0; i < codedLevel.length; i++)
    {
        code += unescape('%' + charList[codedLevel.charAt(i)].toString(16));     
    }
    
    
            
    DebugDisplay(code);    
        
    DecodeLevelCode(code);
    
    return code;
}

function DecodeLevelCode(code)
{
    var val = 0;
    var found = false;
    
        
    codedLevel = '';
    for (var i = 0; i < code.length; i++)
    {
        val = code.charCodeAt(i);
            
        found = false;
        for (var k = 0; k < charList.length; k++)
        {
            if (charList[k] == val)
            {
                found = true;
                codedLevel += k.toString();
                break;
            }
        }                   
        if (!found)
            return -1;
    }
    
    
    codedLevel = parseInt(parseInt(codedLevel).toString(17));

    if (!traditional_game)        
        codedLevel = codedLevel / 1231;
    else
        codedLevel = codedLevel / 1237;
    
    if (Math.round(codedLevel) - codedLevel != 0)
        return -1;
    
    DebugDisplay('decode: ' + codedLevel );           


    return codedLevel;
}


function HandleWarpCode()
{
    var warpCode = prompt('Please enter the code for the level you wish to warp to', '');
    
    if (warpCode == null)
        return;
        
    warpCode = warpCode.replace(/^\s+|\s+$/g, '');
    warpCode = warpCode.toUpperCase();
    
    if (warpCode == '')
        return;
        
    DebugDisplay(warpCode);
    
        
    warpLevel = DecodeLevelCode(warpCode);
    
    if (warpLevel < 1)
    {
        alert('The code you entered is not valid.');                
    }
    else
    {
        level = warpLevel;
        InitGame();   
    }
}


//play audio
function PlayAudio(file)
{
    var altMethod = false;
    
    var main = document.getElementById('Main');
    var embedArea = document.getElementById('EmbedArea');
    
    
    DebugDisplay('testy: ' + file);

    if (soundManager != null && soundManager.supported())
    {
        if (soundManager.getSoundById(file).readyState != 3)
        {
            setTimeout('PlayAudio(' + file + ');', 50);            
            return;
        }
               
        soundManager.stopAll();
        soundManager.play(file);        
    }
    else
    {
        if (embedAudio != null)
        {
            //find the index
            var i;
            var ndx = -1;
            
            for (i = 0; i < audio_files.length;i++)
            {
                if (audio_files[i] == file)
                {
                    ndx = i;
                    break;
                }
            }
            
            if (ndx >= 0)
            {
                var myerr;
                
                for (i = 0; i < audio_files.length; i++)
                {
                    try
                    {
                        embedAudio[i].Stop();
                    }
                    catch (myerr) 
                    {
                        try
                        {
                            embedAudio[i].stop();
                        }
                        catch (myerr) {}
                     }
                            
                }
            
                
                try 
                {
                    embedAudio[ndx].Play();
                } catch (myerr) 
                {
                    try 
                    {
                        embedAudio[ndx].play();
                    } catch (myerr) {};
                 }   

                return;
            }
        }
    
    
        file += '.wav';
        
        
        if (audio != null)
        {
            try
            {        
                if (audio.Stop)
                    audio.Stop();
                else
                    altMethod = true;          
            } catch (err) 
            {
                altMethod = true;
            }
            
            if (!altMethod && audio.Play)
            {
                audio.setAttribute('src', hostSite + 'Audio/' + file);
                audio.Play();    
            }        
       }
       else
       {
            altMethod = true;
        }
        
        
        if (altMethod)
        {
            
            try
            {
                embedArea.removeChild(audio);
            } catch (err) {}
            
            audio = document.createElement('embed');       
            audio.setAttribute('hidden', true);
            audio.setAttribute('autostart', true);    
            audio.setAttribute('type', 'audio/wav');
            audio.setAttribute('src', hostSite + 'Audio/' + file);
            
            embedArea.appendChild(audio);
            
                        
        }
    
    }        
    
    return;
}

//generate which events must be trials
function GenerateHitTrials(trials, hitEvents)
{
    var list = Array(trials);
    var i, eventCount, r;
    
        
    eventCount = 0;
    
    for (i = 0; i < trials; i++);
        list[i] = false;
        
    while (eventCount < hitEvents)
    {
        r = Math.floor(Math.random() * (trials - n_back)) + n_back;
        
        if (!list[r])
        {
            list[r] = true;
            eventCount++;
        }
            
    }   
    return list;
}




//initialize the grid
function InitializeGrid()
{
    //generate the table for the game    
    var i, j;
    var sz;
                  
    sz = 120; //the grid size for normal
    gadgetSize = 70; // the gadget grid size
    
    
    
    var main = document.getElementById('Main');  
    
    cell = new Array(grid_y);                              
    main.innerHTML = '';    
    
    var centerHeader = document.createElement('center');
    main.appendChild(centerHeader);
    
    
    if (!gadgetMode)        
        centerHeader.innerHTML = '<h1>The Working Memory and Attention Training Game</h1>' + '<h2>Level ' + level + ': N = ' + n_back + '</h2>';
    else
        centerHeader.innerHTML = '<b>Level ' + level + ': N = ' + n_back + '</b><br/>';
    

    var center = document.createElement('center');    
    main.appendChild(center);      
               
    var oTable = document.createElement('table');
    var oBody = document.createElement('tbody');
    
    oTable.border = 1;    
    
    if (gadgetMode)
    {        
        oTable.setAttribute('width', gadgetSize + '%');
        oTable.setAttribute('height', gadgetSize + '%');
   
    }    
    else
    {    
        
        oTable.setAttribute('width', sz * grid_x);
        oTable.setAttribute('height', sz * grid_y);
    }
    
    
    for (j=0; j < grid_y; j++)
    {
        var oRow = document.createElement('tr');    
        cell[j] = new Array(grid_x);
        
        for (i=0; i < grid_x; i++)
        {
            cell[j][i] = document.createElement('td');                        
            
            cell[j][i].setAttribute('width', (100 / grid_x) + '%');
            cell[j][i].setAttribute('height', (100 / grid_y) + '%');
            
           
            cell[j][i].bgColor = 'white';
            //cell[j][i].setAttribute('bgcolor', 'white');
            
            cell[j][i].innerHTML = '<center>&nbsp</center>'; //necessary for IE           
            oRow.appendChild(cell[j][i]);                        
        }                                           
        oBody.appendChild(oRow);  
    }               
                             
    oTable.appendChild(oBody);               
    center.appendChild(oTable);    
    
    if (!gadgetMode)
        center.appendChild(document.createElement('br'));
    
    //create a new table for buttons and feedback
    var btnTable = document.createElement('table');
    var btnBody = document.createElement('tbody');
    
    btnTable.border = 0;    
        
    btnTable.appendChild(btnBody);                
    center.appendChild(btnTable);
    
    if (!gadgetMode)
        btnTable.setAttribute('width', sz * grid_x);             
    else
        btnTable.setAttribute('width', gadgetSize + '%');             
        
        
    //add a row for feedback
    if (give_feedback)    
    {
        var feedbackRow = document.createElement('tr');
        
        btnBody.appendChild(feedbackRow);
        
                
        if (feat_audio)
        {    
            feedback_audio = document.createElement('td');                                 
            feedback_audio.innerHTML = '&nbsp';
            feedbackRow.appendChild(feedback_audio);                          
        }
        
        if (feat_color || feat_baby)
        {                  
            feedback_color = document.createElement('td');    
            feedback_color.innerHTML = '&nbsp';
            feedbackRow.appendChild(feedback_color);
            
        }
        
        
        if (feat_spatial)
        {               
            feedback_spatial = document.createElement('td');    
            feedback_spatial.innerHTML = '&nbsp';
            feedbackRow.appendChild(feedback_spatial);
        }
        
   }
   
    btnRow = document.createElement('tr');        
    btnBody.appendChild(btnRow);
    

    if (feat_audio)
    {
        button_audio = document.createElement('input');
        button_audio.setAttribute('type', 'button');    
        button_audio.setAttribute('value', 'D (Audio)');
        button_audio.onclick = function() {keyListener(68)};
        button_audio.setAttribute('disabled', true);
        
        audioCell = document.createElement('td');     
        btnRow.appendChild(audioCell);        
     
        var audioCenter = document.createElement('center');
        audioCenter.appendChild(button_audio);
        audioCell.appendChild(audioCenter);
    }
    
    if (feat_color || feat_baby)
    {
        button_color = document.createElement('input');
        button_color.setAttribute('type', 'button');    
        
        if (feat_baby)
            button_color.setAttribute('value', 'SPACE (Animal)');
        else
            button_color.setAttribute('value', 'SPACE (Color)');
            
        button_color.onclick = function() {keyListener(32)};
        button_color.setAttribute('disabled', true);
        
        colorCell = document.createElement('td');     
        btnRow.appendChild(colorCell);        
     
        var colorCenter = document.createElement('center');
        colorCenter.appendChild(button_color);
        colorCell.appendChild(colorCenter);    
    }
    
    if (feat_spatial)
    {
        button_spatial = document.createElement('input');
        button_spatial.setAttribute('type', 'button');    
        button_spatial.setAttribute('value', 'K (Spatial)');
        button_spatial.onclick = function() {keyListener(75)};
        button_spatial.setAttribute('disabled', true);
        
        spatialCell = document.createElement('td');     
        btnRow.appendChild(spatialCell);
        var spatialCenter = document.createElement('center');    
        spatialCenter.appendChild(button_spatial);            
        spatialCell.appendChild(spatialCenter);        
    }
    
    events_audio = GenerateHitTrials(base_game_trials + n_back, 6);
    events_spatial = GenerateHitTrials(base_game_trials + n_back, 6);  
    events_color = GenerateHitTrials(base_game_trials + n_back, 6);                                                 
    
    
    //code for level reset button
    resetLink = document.createElement('a');
    resetLink.setAttribute('href', '#');
    resetLink.onclick = function() {InitGame()}; 
    resetLink.appendChild(document.createTextNode("Reset Level?"));
    
    center.appendChild(document.createElement('br'));
    center.appendChild(resetLink);   
}


//plays the game with the given parameters
function PlayGame()
{
    var displayTime = 500; //in ms
    var delayTime = 2500;//2500 // in ms    
    var nextTimeOut;
    var i, j;
    var baby_file;
    var baby_index;
        
    var main = document.getElementById('Main');        
                 
                        
    if (game_length <= 0)
    {
        game_state = eGame_state.not_running;        
        document.onkeydown = null;
        clearTimeout(timer);
		
        EvaluateResults();
		if (logged == true && submit_score == true) SubmitResults();
        
        return;
    }   

      
    //now the main game's loop
    if (game_state == eGame_state.not_running)
    {        
        //initialization stuff
        
        InitializeGrid();
        
        game_state = eGame_state.waiting;
        document.onkeydown = keyListener;
        
        hits_spatial = 0;
        total_spatial = 0;
        false_alarms_spatial = 0;
        hits_audio = 0;
        total_audio = 0;
        hits_color = 0;
        false_alarms_audio = 0;
        total_color = 0;
        false_alarms_color = 0;
        
        trials = 0;
                
    }
    

    //clear all the grids                        
    for (i = 0; i < grid_y; i++)
    {
        for (j = 0; j < grid_x; j++)
        {     
            cell[i][j].bgColor = 'white';   
            cell[i][j].removeAttribute('background');
            cell[i][j].innerHTML = '<center>&nbsp</center>';
            //cell[i][j].setAttribute('bgcolor', '#FFFFFF');
        }
    }
    
    
    
    //see what state to do next based on the current state
    if (game_state == eGame_state.waiting) //need to display
    {                        
            game_state = eGame_state.displaying;        
            nextTimeOut = displayTime;
            trials++;
                        
            if (give_feedback)
            {
                if (feat_audio)
                    feedback_audio.bgColor = 'white';             
                
                if (feat_color || feat_baby)
                    feedback_color.bgColor = 'white'; 
                    
                if (feat_spatial)
                    feedback_spatial.bgColor = 'white'; 
            }
            
            
                                   
            if (trials >= n_back + 1) //the user can play now
            {
                if (feat_audio)
                    button_audio.removeAttribute('disabled');
                if (feat_spatial)
                    button_spatial.removeAttribute('disabled');
                if (feat_color || feat_baby)
                    button_color.removeAttribute('disabled');
             }
                
            
            if (feat_baby)
            {
                var c_index = Math.floor(Math.random() * feature_dims) + feature_start;
            
                len = hist_color.length;
            
                if (len >= n_back + 1)
                {                
                    hist_color.shift();                           
                
                    if (events_color[trials])
                        c_index = hist_color[0];                                                          
                    
                    len = n_back;                                
                }
            
                hist_color[len] = c_index;
                        
            
                if ((hist_color.length >= n_back + 1) &&  hist_color[0] == hist_color[n_back])   
                    total_color++; 
                                    
                baby_index = c_index;
                baby_file = animal_files[c_index];            
            }
            

                                  
            //for color                       
            var color = 'black';
            if (feat_color && !feat_baby)
            {
                var c_index = Math.floor(Math.random() * feature_dims);
            
                len = hist_color.length;
            
                if (len >= n_back + 1)
                {                
                    hist_color.shift();                           
                
                    if (events_color[trials])
                        c_index = hist_color[0];                                                          
                    
                    len = n_back;                                
                }
            
                hist_color[len] = c_index;
            
                if ((hist_color.length >= n_back + 1) &&  hist_color[0] == hist_color[n_back])   
                    total_color++; 
                    
                color = color_list[c_index];      
            }
            
            //for spatial location
            //choose a random x and y
            
            if (feat_spatial)
            {
                var rndX, rndY;
                            
                rndX = Math.floor(Math.random() * grid_x);
                rndY = Math.floor(Math.random() * grid_y);                                                                    
                
                var len = hist_spatial.length;

                         
                if (len >= n_back + 1)
                {   
                    hist_spatial.shift();                           
                    
                    if (events_spatial[trials])
                    {
                        rndX = hist_spatial[0][0];
                        rndY = hist_spatial[0][1];
                    }
                    len = n_back;  
                }
                
                hist_spatial[len] = [rndX, rndY];
                
                //cell[rndY][rndX].setAttribute('bgcolor', 'black');
                cell[rndY][rndX].bgColor = color;
                
                if (feat_baby)                    
                {
                
                    //DebugDisplay(navigator.appName);
                    
                    if (navigator.appName == 'Microsoft Internet Explorer')
                        //cell[rndY][rndX].setAttribute('background', 'Images/' + baby_file);
                        cell[rndY][rndX].setAttribute('background', image_list[baby_index].src);
                    else
                        //cell[rndY][rndX].innerHTML = '<img width="100%" height="100%" src="Images/' + baby_file + '" />';
                        //cell[rndY][rndX].innerHTML = '<img width="100%" height="100%" src="http://cse.ucsd.edu/~ckanan/Images/' + baby_file + '" />';
                        cell[rndY][rndX].innerHTML = '<img width="100%" height="100%" src="' + image_list[baby_index].src +   '" />';                        
                }
                
                if ((hist_spatial.length >= n_back + 1) &&  hist_spatial[0][0] == hist_spatial[n_back][0] && hist_spatial[0][1] == hist_spatial[n_back][1])   
                    total_spatial++;
            }
                               
            //now for the audio                
            //var a_index = Math.floor(Math.random() * audio_files.length);
            
            if (feat_audio)
            {
                var a_index = Math.floor(Math.random() * feature_dims);
                            
                len = hist_audio.length;
                
                if (len >= n_back + 1)
                {                
                    hist_audio.shift();                           
                    
                    //if (hit_prob > Math.random()) //set it manually                
                    if (events_audio[trials])
                        a_index = hist_audio[0];                                                          
                        
                    len = n_back;                                
                }
                
                hist_audio[len] = a_index;
                                                   
                
                if ((hist_audio.length >= n_back + 1) &&  hist_audio[0] == hist_audio[n_back])   
                    total_audio++;                                                  
                
                
                PlayAudio(audio_files[a_index]);
             }                                 
     }
     else //must be displaying already, so switch to waiting                            
     {
            game_length--;
            game_state = eGame_state.waiting;            
            nextTimeOut = delayTime;                                                        
     }       
            
                         
    timer = setTimeout('PlayGame();', nextTimeOut);                   
                   
    return;
}

//event listener
function keyListener(e)
{
         
   if(!e){
      //for IE
      e = window.event;
   }
   
   //check to see if the game has gone on long enough
   if (trials < n_back + 1)
    return;
       
   if (e.keyCode)
    keyCode = e.keyCode;
   else
    keyCode = e;
     
      
   if (game_state == eGame_state.not_running)
    return;
   
   //spatial key hit
   if ((keyCode == 75 || keyCode == 107) && feat_spatial) //'k'
   {
        //check to see if spatial was hits      
                
        if (hist_spatial[0][0] == -1) //user isn't allowed
            return;
        
        if (hist_spatial[0][0] == hist_spatial[n_back][0] && hist_spatial[0][1] == hist_spatial[n_back][1])   
        {
            hits_spatial++;       
            if (give_feedback)     
                feedback_spatial.bgColor = 'green'; 
        }
        else
        {
            false_alarms_spatial++;  
            if (give_feedback)          
                feedback_spatial.bgColor = 'red'; 
        }
        hist_spatial[0][0] = -1; //can't get or lose more points
                
        button_spatial.setAttribute('disabled', true);        
   }
   
   //audio key hit
   if ((keyCode == 68 || keyCode == 100) && feat_audio)
   {
        if (hist_audio[0] == -1) // user isn't allowed
            return;
            
        if (hist_audio[0] == hist_audio[n_back])
        {
            hits_audio++;       
            if (give_feedback)
                feedback_audio.bgColor = 'green';  
        }
        else
        {
            false_alarms_audio++;
            if (give_feedback)
                feedback_audio.bgColor = 'red';  
        }
        hist_audio[0] = -1; // can't get or lose more points   
        button_audio.setAttribute('disabled', true);
   }      
   
    //audio key hit
   if ((keyCode == 32) && (feat_color || feat_baby))
   {
        if (hist_color[0] == -1) // user isn't allowed
            return;
            
        if (hist_color[0] == hist_color[n_back])
        {
            hits_color++;
            if (give_feedback)
                feedback_color.bgColor = 'green';  
        }
        else
        {
            false_alarms_color++;
            if (give_feedback)
                feedback_color.bgColor = 'red';  
        }
        hist_color[0] = -1; // can't get or lose more points   
        button_color.setAttribute('disabled', true);
   }      
   
}

function SubmitResults()
{
	//YYYY-MM-DD HH:MM:SS (MySQL datetime)
	var start_date_string = start_date.getFullYear() + '-' + (start_date.getMonth()*1+1) + '-' + start_date.getDate() + ' ' + start_date.getHours() + ':' + start_date.getMinutes() + ':' + start_date.getSeconds();
	
	var end_date = new Date(); 
	var end_date_string = end_date.getFullYear() + '-' + (end_date.getMonth()*1+1) + '-' + end_date.getDate() + ' ' + end_date.getHours() + ':' + end_date.getMinutes() + ':' + end_date.getSeconds();
	

	var poststr= "s=" + escape(encodeURI(start_date_string)) +
				"&e=" + escape(encodeURI(end_date_string)) +
				"&tg=" + escape(encodeURI(Number(traditional_game))) +
				"&l=" + escape(encodeURI(level)) +
				"&cl=" + escape(encodeURI(current_level)) +
				"&gf=" + escape(encodeURI(Number(give_feedback))) +
				"&fs=" + escape(encodeURI(Number(current_feat_spatial))) +
				"&fc=" + escape(encodeURI(Number(current_feat_color) || Number(current_feat_baby))) +
				"&fa=" + escape(encodeURI(Number(current_feat_audio))) + 
				"&hs=" + escape(encodeURI(hits_spatial)) +
				"&fas=" + escape(encodeURI(false_alarms_spatial)) +
				"&ts=" + escape(encodeURI(total_spatial)) +
				"&ha=" + escape(encodeURI(hits_audio)) +
				"&faa=" + escape(encodeURI(false_alarms_audio)) +
				"&ta=" + escape(encodeURI(total_audio)) +
				"&hc=" + escape(encodeURI(hits_color)) +
				"&fac=" + escape(encodeURI(false_alarms_color)) +
				"&tc=" + escape(encodeURI(total_color)) +
				"&sp=" + escape(encodeURI(spatial_perf)) +
				"&ap=" + escape(encodeURI(audio_perf)) +
				"&cp=" + escape(encodeURI(color_perf)) +
				"&o=" + escape(encodeURI(overall));
    
	makePOSTRequest('submit.php', poststr);
}

//determine how well the player did
function EvaluateResults()
{
	current_level = level;
	current_feat_spatial = feat_spatial;
	current_feat_color = feat_color;
	current_feat_baby = feat_baby;
	current_feat_audio = feat_audio;
	
    var main = document.getElementById('Main');    
    
	var right = document.createElement('left');
	main.appendChild(right);
	
	if (logged == true)
	{
		right.innerHTML = 'Logged in as: <a href="http://sutas.lt/wp-admin/admin.php?page=gf_game_stats">' + username + ',</a> <a href="'+logout_url+'">logout</a>';
	}
	else
	{
		right.innerHTML = '<span style="color:red">Please <a href="'+login_url+'">login</a>/<a href="'+register_url+'">register</a> before playing game for statistics saving!</span>';
	}
	
    main.innerHTML = '<br />';    
    center = document.createElement('center');    
    main.appendChild(center);
    
    if (!gadgetMode)
    {
        center.innerHTML = '<h1>The Working Memory and Attention Training Game</h1>';
        center.innerHTML += '<h3><u>Performance Statistics</u></h3>';
    }
    else
        center.innerHTML += '<u><b>Performance Statistics</b></u>';
    
        
    var spatial_hr = 100;
    if (total_spatial > 0)
        spatial_hr = 100 * (hits_spatial / total_spatial)             
    spatial_fr = 100 * (false_alarms_spatial / (trials - total_spatial));
    
        
    var dim_count = 0;
    
   	spatial_perf = 0;
    audio_perf = 0;
    color_perf = 0;
    
    if (feat_spatial)
    {               
        spatial_perf = 100 * (hits_spatial - false_alarms_spatial) / total_spatial;
        if (spatial_perf < 0)
            spatial_perf = 0;
                        
        center.innerHTML += '<br /><b>Spatial Performance: ' + Math.round(spatial_perf) + '%</b>';
        dim_count++;
    }
    
    if (feat_audio)
    {    
        audio_perf = 100 * (hits_audio - false_alarms_audio) / total_audio;
        if (audio_perf < 0)
            audio_perf = 0;
            
        center.innerHTML += '<br /><b>Audio Performance: ' + Math.round(audio_perf) + '%</b>';   
        
        dim_count++;
    }
    
    if (feat_color || feat_baby)
    {                   
        color_perf = 100 * (hits_color - false_alarms_color) / total_color;
        if (color_perf < 0)
            color_perf = 0;
            
        if (feat_baby)
            center.innerHTML += '<br /><b>Animal Performance: ' + Math.round(color_perf) + '%</b>';       
        else
            center.innerHTML += '<br /><b>Color Performance: ' + Math.round(color_perf) + '%</b>';       
        
        dim_count++;
    }
    
    overall = (spatial_perf + audio_perf + color_perf) / dim_count;
    
    center.innerHTML += '<br /><b>Overall Performance: ' + Math.round(overall) + '%</b>'
    
            
                              
    DebugDisplay('<br /><b>Spatial HR: ' + Math.round(spatial_hr) + '%</b>');
    DebugDisplay('<br /><b>False Alarm Rate: ' + Math.round(spatial_fr) + '%</b><br />');
    DebugDisplay('hits = ' + hits_spatial + ' spatial total=' + total_spatial +  ' false = ' + false_alarms_spatial + ' trials = ' + trials);
    DebugDisplay('<br />audio hits = ' + hits_audio + ' audio total=' + total_audio +  ' false = ' + false_alarms_audio + ' trials = ' + trials); 
    DebugDisplay('<br />color hits = ' + hits_color + ' fa color=' + false_alarms_color + ' color total = ' + total_color);
     

    var replaying = true;
    
    //heuristic to increase difficulty                          
    if ( overall > 80)
    {        
        if (!gadgetMode)    
            center.innerHTML += '<br /><br /><b>DIFFICULTY INCREASED! You played a fantastic game. Make sure to read the rules again, because they have now changed to make the game harder.</b>';
        else
            center.innerHTML += '<br /><br /><b>DIFFICULTY INCREASED! You played a fantastic game.</b>';
        level++;   
    
        replaying = false;    
        if (!gadgetMode)
            center.innerHTML += '<h2>Welcome to Level ' + level + '.</h2>';        
        else
            center.innerHTML += '<br /><b>Welcome to Level ' + level + '.</b>';        
            
        center.innerHTML += 'Level ' + level + ' Warp Code: ' + EncodeLevelCode() + '';    
            
    }
    else if (n_back > 1 && overall < 50 && traditional_game)
    {
        if (!gadgetMode)
            center.innerHTML += '<br /><br /><b>The difficulty has been LOWERED! It looks like you need some more training. Make sure to read the rules again, because they have now changed to make the game easier.</b>';        
        else
            center.innerHTML += '<br /><br /><b>The difficulty has been LOWERED!</b>';        
            
        level--;          
                  
        replaying = false;
        
        if (!gadgetMode)
            center.innerHTML += '<h2>Welcome back to Level ' + level + '.</h2>';        
        else
            center.innerHTML += '<br /><b>Welcome back to Level ' + level + '.</b><br />';
        
    }           
        
    if (replaying)
    {
        center.innerHTML += '<br />You need an overall score of at least 80% to advance to the next level.<br /> Do not give up!';
        if (!gadgetMode)
            center.innerHTML += '<br />Some players spend a week on a single level before surpassing it.';
    }
                
    SetLevelParams();
    
    
    center.innerHTML += '<br /><br />';
                                           
    mainButton = document.createElement('input');
    mainButton.setAttribute('type', 'button');    
    
    
    if (replaying)
        mainButton.setAttribute('value', 'Play Level ' + level + ' Again?');
    else
        mainButton.setAttribute('value', 'Play Level ' + level + '?');
    
    mainButton.onclick = function() {InitGame()};
    
    
	

	if (logged == true)
	{	
		var statusText = document.createElement('text');
		statusText.setAttribute('id', 'statusText');
		
		if (submit_score == true)
		{
			var progressBar = document.createElement('img');
			progressBar.setAttribute('src', 'ajax-loader.gif');
			progressBar.setAttribute('id', 'progressBar');
			center.appendChild(progressBar);
	
			statusText.innerHTML = 'Submitting...';
		} else
		{
			statusText.innerHTML = 'Score submitting disabled!';
		}
		center.appendChild(statusText);
		center.innerHTML += '<br/>';
	}
	center.appendChild(mainButton);
}


//determines the game's parameters for Chris' modified game
function SetLevelParams()
{
    if (traditional_game) // almost just like Jaeggi et al
    {
        n_back = level;
        feat_color = false;
        feat_baby = false;
        feat_audio = true;
        feat_spatial = true;
        //give_feedback = false;
        grid_x = 3;
        grid_y = 3;  
    } 
    else //Chris' modifications
    {
        //give_feedback = true;
        var levelParams = 0;
        var cases = 9;
        
        switch(level)
        {
            case 1:
                levelParams = 1;
                n_back = 1;
                break;
            case 2:
                levelParams = 2;
                n_back = 1;
                break;
            
            default:
                
                if (level <= cases)
                {
                    levelParams = level;        
                    n_back = 2;
                }   
                else
                {
                    levelParams = ((level - 2) % (cases - 2)) + 2;                    

                    n_back = Math.ceil( (level - 2) / (cases - 2)) + 1;
                }
        }
        
        feat_baby = false;
        feat_color = false;
        feat_audio = false;
        
        switch(levelParams)
        {
            case 1:
                //n_back = 1;
                feat_audio = true;
                feat_spatial = true;
                feat_color = false;
                feat_baby = false;
                grid_x = 3;
                grid_y = 3;                    
                break;
            case 2:
                //n_back = 1;
                feat_audio = true;
                feat_spatial = true;
                //feat_color = true;
                feat_color = false;
                feat_baby = true;
                
                grid_x = 2;
                grid_y = 2;                            
            
                break;
            case 3:
                //n_back = 2;                
                feat_spatial = true;
                feat_audio = false;
                feat_color = false;
                grid_x = 3;
                grid_y = 1;      

                break;
            case 4:
                //n_back = 2;
                feat_audio = false;
                feat_spatial = true;
                feat_color = false;
                grid_x = 3;
                grid_y = 2;      
                break;
            case 5:
                //n_back = 2;
                feat_audio = true;
                feat_spatial = false;
                feat_color = false;
                //grid_x = 3;
                //grid_y = 2;      
                grid_x = 1;
                grid_y = 1;
                break;
            
            case 6:
                //n_back = 2;
                feat_audio = true;
                feat_spatial = true;
                feat_color = false;
                grid_x = 2;
                grid_y = 2;      
                break;
            
            case 7:
                //n_back = 2;
                feat_audio = false;
                feat_spatial = true;
                //feat_color = true;
                feat_color = false;
                feat_baby = true;
                grid_x = 2;
                grid_y = 3;      
                break;

            case 8:
                //n_back = 2;
                feat_audio = true;
                feat_spatial = true;
                feat_color = false;
                grid_x = 3;
                grid_y = 3;      
                break;
            
             case 9:
                feat_audio = true;
                feat_spatial = true;
                feat_color = true;
                grid_x = 2;
                grid_y = 2;      
                break;            
            
            
            default:
                n_back++;
                feat_color = false;
                feat_spatial = true;
                feat_audio = true;
                grid_x = 3;
                grid_y = 3;
                                       

        }    
        
        if (!feat_spatial)
        {
            grid_x = 1;
            grid_y = 1;
        }
        
    }
}



