/*

This is the common set of Javascript code for the Programming 102 web pages
 Copyright ( c ) 2008 Walter Milner
This is based on script.js
 
Notes..

When a while is encountered, and the condition is not immediately false, the following
is pushed onto the stack -
w, lineNo, cond
the w flags a while loop, lineNo is the first executable line in the loop, and cond
is the loop condition. The entry is popped off the stack when the loop terminates

Similarly for a repeat loop,
r, lineNo, count
is pushed onto the stack.

At the start of an if block, where the condition is true,
if
is pushed onto the stack, and popped off at the end of the block

When a } is reached, data is popped off the stack and appropriate action taken

*/
// global variables
var lineNumber=1; // the line number about to be executed on the next step
var a=0; // the actual variables
var b=0;
var c=0;
var d=0;
var e=0;
var g=[]; // the array g
var arrayLimit=15; //we display only g[0] to g[14]
for (i=0; i<arrayLimit; i++)
    g[i]=0;
var h=[]; // the array h
for (i=0; i<arrayLimit; i++)
    h[i]=0;    
var olda=0; // their previous values
var oldb=0;
var oldc=0;
var oldd=0;
var olde=0;
var maxLine=19; // max possible number of statement lines
var stack = [];
var stackPtr=0;
var inputCount=0;
var score=0;
var outof=0;
var repeatID; // for continuous running
//some initial programs
// element 0 is a title
// element access
var prog1 = ['Program 1', 'g[0]=12', 'g[1]=5', 'g[3]=4','g[2]=7','h[1]=9','h[0]=g[1]+g[2]'];
// fill
var prog2 = ['Program 2', 'a=9', 'b=0','repeat 15','{','g[b]=a','b=b+1','}'];
// search
var prog3 = ['Program 3', 'input a', 'b=0','repeat 15','{','if g[b]==a','{','output "Found at "+b','}','b=b+1','}'];
// count
var prog4 = ['Program 4', 'input a', 'b=0','c=0', 'repeat 15','{','if g[b]>a','{','c=c+1','}','b=b+1','}', 'output c+" values greater than "+a'];
// total
var prog5 = ['Program 5','a=0', 'b=0','repeat 15','{','a=a+g[b]','b=b+1','}', 'output "Total = "+a'];
// pre-sort
var prog6 = ['Program 6','b=0','repeat 14','{','if g[b]>g[b+1]','{','a=g[b]','g[b]=g[b+1]','g[b+1]=a','}','b=b+1','}'];
// sort
var prog7 = ['Program 6','repeat 15', '{','b=0','repeat 14','{','if g[b]>g[b+1]','{','a=g[b]','g[b]=g[b+1]','g[b+1]=a','}','b=b+1','}','}'];
// reverse
var prog8 = ['Program 8','a=0','while a<7','{',' b=g[a]','g[a]=g[14-a]','g[14-a]=b','a=a+1','}'];
var prog9 = ['Program 9','input a','if a>10','{','output "Bigger than 10"','}'];
var prog10 = ['Program 10','a=0','repeat 5','{','  input b','  if b> a','  {','    a=b','  }','}','output a'];
var prog11 = ['Program 11','repeat 5','{','input a','if a==99', '{', 'output "Found 99"','}','}' ];
var prog12 = ['Program 12','input a','input b', 'c=a', 'a=b','b=c', 'output a', 'output b'];
var prog13 = ['Program 13','a=0','while a<5','{','b=0','while b<5','{','c=a*b','output c','b=b+1','}','a=a+1', '}'];

//all progs in an array
var progs = [prog1, prog2, prog3, prog4, prog5, prog6, prog7, prog8, prog9, prog10, prog11, prog12, prog13];
var currentProg=1; // which is the current prog : 0 = first prog
var progChanged=false; // whether the current program has been altered
function push(value)
{

   stack[stackPtr]=value;
   stackPtr++;

}

function pop()
{
if (stackPtr==0) alert("Stack underflow");
else 
     {
     stackPtr--;
     return stack[stackPtr];
     }

}

function trim(value) {// remove spaces and other white space
   var temp = value;
   var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
   if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
   var obj = /  /g;
   while (temp.match(obj)) { temp = temp.replace(obj, " "); }
   return temp;
}

function mytrim(value) // remove leading spaces
{
var temp = value;
while (temp.charAt(0)==' ') temp = temp.substr(1);
return temp;
}

function flicker(id)
{// the idea of this is to flicker the body of the element id
flickwhite(id, 8);
}

function flickred(id, c)
{
if (c<0) return;
thing = document.getElementById(id);
thing.style.color="red";
setTimeout("flickwhite('"+id+"',"+(c-1)+")", 100);
}

function flickwhite(id, c)
{
if (c<0) return;
thing = document.getElementById(id);
thing.style.color="white";
setTimeout("flickred('"+id+"',"+(c-1)+")", 100);
}




// the following is called when program text has been altered, and
// the corresponding update button has been clicked
function updateProg(progNo)
{
// start new array
var newArray = [];
// get program title
newArray[0]=document.getElementById("pn"+(progNo+1)).value
// get program lines
for (line=1; line<maxLine+1; line++)
{
lineID = "s"+line;
text=document.getElementById(lineID).value;
if (text=="") break;
newArray[line]=text;
}
// set this array in place in array of programs
progs[progNo]=newArray;
// disable update button
document.getElementById("ep"+(progNo+1)).disabled=true;
    
}

function finish()
{
//alert("Doing finish");
for (i=0; i<progs.length; i++)
{
// write cookie
  text=progs[i][0]+"=";
  for (line=1; line<maxLine+1; line++)
      {
      lineText=progs[i][line];
      if (lineText==undefined) break;
      text+=lineText+"&";
      }
     text+="; expires=Tue, 5 May 2020 20:47:11 UTC; path=/"; 
  document.cookie = text;
  }
}
function deleteLine(start)
{
for (i=start; i<maxLine; i++)
  {
  thisLineID="s"+i;
  nextLineID="s"+(i+1);
  document.getElementById(thisLineID).value=document.getElementById(nextLineID).value;
  }
}

function insertLine(start)
{
for (i=maxLine-1; i>=start; i--)
  { 
  thisLineID="s"+i;
  nextLineID="s"+(i+1);
  document.getElementById(nextLineID).value=document.getElementById(thisLineID).value;
  }
  document.getElementById("s"+start).value="";
}
function setProg(progNo)
{
if (progNo>progs.length-1) return;
// put program lines into text fields
for (i=1; i<=progs[progNo].length-1; i++)
{
lineID = "s"+i;
document.getElementById(lineID).value=progs[progNo][i];
}
// clear the rest
for (i=progs[progNo].length; i<=maxLine; i++)
{
lineID = "s"+i;
document.getElementById(lineID).value="";
} 
reset();
}

function reset()
{
id ="l"+lineNumber;
document.getElementById(id).style.background="green";
lineNumber=1;
id ="l"+lineNumber;
document.getElementById(id).style.background="red";
a=b=c=d=e=0;
for (i=0; i<g.length; i++)
    g[i]=Math.floor(Math.random()*100);
for (i=0; i<h.length; i++)
    h[i]=0;    
showVarVals();
inputCount=0;
score=0;
outof=0;
// clear output
document.getElementById("out").value="";
}

function showVarVals()
{
for (i=0; i<arrayLimit; i++)
  {
  v=eval("g["+i+"]");
  document.getElementById("a"+i).innerHTML=v;
  }
for (i=0; i<arrayLimit; i++)
  {
  v=eval("h["+i+"]");
  document.getElementById("h"+i).innerHTML=v;
  }  
  
v=eval("a");
if (v!=olda)
   flicker("v1");
document.getElementById("v1").innerHTML=v;

v=eval("b");
if (v!=oldb)
   flicker("v2");
document.getElementById("v2").innerHTML=v;

v=eval("c");
if (v!=oldc)
   flicker("v3");
document.getElementById("v3").innerHTML=v;

v=eval("d");
if (v!=oldd)
   flicker("v4");
document.getElementById("v4").innerHTML=v;

v=eval("e");
if (v!=olde)
   flicker("v5");
document.getElementById("v5").innerHTML=v;

}

// check the script for various errors

function check()
{
var brackets=0;
for (i=1; i<=maxLine; i++)
    {
    lineID = "s"+i;
    line = document.getElementById(lineID).value;
    line = trim(line); // remove spaces
    if (line=="{") brackets++;
    if (line=="}") brackets--;
    }
if (brackets!=0) return "Problem : brackets { } do not match";
return "";
}


// called when a line of program text is altered since last update
function changed()
{
progChanged=true; // flag it has changed

}


//do the input statemet
function doInput()
{
//get this line
lineID = "s"+lineNumber;
line = document.getElementById(lineID).value;
line = mytrim(line);
line=line.substr(5);
line=mytrim(line); // this is variable to assign
inputs=document.getElementById("in").value; // all input values
if (inputs=="") 
   {
   alert("Error - need input data value");
   stop();
   reset();
   lineNumber--;
   return;
   }

inputs=inputs.split(",");                   // separate
//alert(inputs.length+""+inputCount);
if (inputs.length<(inputCount+1) )          // have we got enough?
   {
   alert("Error - not enough input data values");
   reset();
   lineNumber--;
   }
else
  {   
  input=inputs[inputCount];        // get correct one
  inputCount++;
  assign=line+" = "+input+";";         // make assignment
  eval(assign);                    // do it
  }
}

//do the output statement
function doOutput()
{
//get this line
lineID = "s"+lineNumber;
line = document.getElementById(lineID).value;
line = trim(line);
line=line.substr(6);
line=trim(line); // this is value to output
outs=document.getElementById("out").value; // all input values
if (outs=="") outs = eval(line);
else outs = outs+", "+eval(line);
document.getElementById("out").value=outs;
}


// the following is done when we hit a }
function doCloseBracket()
{
data=pop();
if (data=="if")
   return;
//alert("Close bracket "+data);
var values=data.split(",");
if (values[0]=="w")// this was a while loop
   {
   result=eval(values[2]);
   //alert(values[2]+" "+result);
   if (result)
      {
      push(data);
      lineNumber=parseFloat(values[1])-1;
      return;
      }
    else
      return;  
   }
if (values[0]=="r")// this was a repeat loop
   {
   result=eval(values[2]);
   //alert(values[2]+" "+result);
   if (result>1)
      {
      result--;
      data="r,"+values[1]+","+result;
      push(data);
      lineNumber=parseFloat(values[1])-1;
      return;
      }
    else
      return;  
   }   
   
}

// the following happens when a repeat is encountered
function doRepeat()
{
// find the matching } where loop ends
bracketCount=1;
where = lineNumber+2
while (bracketCount!=0)
      {
      lineID = "s"+where;
      line = document.getElementById(lineID).value;
      line = trim(line); // remove spaces
      if (line=="{") bracketCount++;
      if (line=="}") bracketCount--;
      //alert(bracketCount+" "+line+lineNumber);
      where++;
      } // now where is the line after the closing }
// get the repeat line, then the count
lineID = "s"+lineNumber;
line = document.getElementById(lineID).value;
line = trim(line); // remove spaces
count = line.substr(6);
count = eval(count);
if (isNaN(count)) 
  {
  alert("Error - "+line+" repeat must be followed by a number eg repeat 10");
  return;
  }
start=lineNumber+2;
data="r,"+start+","+count;
push(data);
lineNumber=start-1;
}

// the following is done when a while statement is encountered
function doWhile()
{
// find the matching }
bracketCount=1;
where = lineNumber+2
while (bracketCount!=0)
      {
      lineID = "s"+where;
      line = document.getElementById(lineID).value;
      line = trim(line); // remove spaces
      if (line=="{") bracketCount++;
      if (line=="}") bracketCount--;
      //alert(bracketCount+" "+line+lineNumber);
      where++;
      } // now where is the line after the closing }
// get the while line, then the boolean expression
lineID = "s"+lineNumber;
line = document.getElementById(lineID).value;
line = trim(line); // remove spaces
condition = line.substr(5);
result = eval(condition);
if (!result)             // if its false first time in
   {
   lineNumber=where-1; // step advances it another 1
   return;             // finished
   }
start=lineNumber+2;
data="w,"+start+","+condition;
push(data);
lineNumber=start-1;
   
}

function doIf(line)
{

line = line.substr(2); //this is the boolean expression

result = eval(line);

if (result) // the if is true
   {
   lineNumber+=1; //go past the {
   push("if");
   return;
   }
else //its false
    {
    bracketCount=1;
    lineNumber+=2;
    while (bracketCount!=0)
          {
          lineID = "s"+lineNumber;
          line = document.getElementById(lineID).value;
          line = trim(line); // remove spaces
          if (line=="{") bracketCount++;
          if (line=="}") bracketCount--;
          //alert(bracketCount+" "+line+lineNumber);
          lineNumber++;
          }
    lineNumber--;
    }

}


function run() // continuous steps
{
repeatID=setInterval('step()', 100);
}

function stop()
{
clearInterval(repeatID);
}

function step()
{
result=check();
if (result!="")
   {
   alert(result);
   return;
   }
if (lineNumber==maxLine) { clearInterval(repeatID); return};
//reset line number
id ="l"+lineNumber;
document.getElementById(id).style.background="green";
//get the statement
lineID = "s"+lineNumber;
line = document.getElementById(lineID).value;
line = mytrim(line); // remove spaces
if (line=="") { clearInterval(repeatID); return};
start = line.substr(0,2);
if (start=="if")
   doIf(line);
else
    {
      start = line.substr(0,5);  
      if (start=="while")
         doWhile()
      else  
      if (line.substr(0,6)=="repeat")
         doRepeat();
      else
        if (line.substr(0,5)=="input")
          doInput();
        else   
          if (line.substr(0,6)=="output")
          doOutput();
          else
            if (line=="}")
               doCloseBracket();
            else       
             eval(line);
    }
showVarVals();
lineNumber++;

// set next line number color
id ="l"+lineNumber;
document.getElementById(id).style.background="red";
}
