/*

A random organic alkane is generated, and its name is determined!

Basically, a hexagonal grid is created by assigning every other
point of a Cartesian plane with 'up' and 'down' characteristics:

    y          x   z
    |           \ /
   / \ 'uxyz'    | 'dxyz'  where x,y,z are 0/1
  x   z          y

16 images are loaded, encompassing all possibilities: u000,u001,...,d111.
A table is generated on the fly containing just the right images and
presented to the user.

Current Limitations:

(1) no branched branches (yet).
(2) no competing longest chains.
(3) no quaternary Cs (yet).
(4) acyclic alkanes only.

*/

HMAX=14    /* Columns */
VMAX=14    /* Rows */
ORIGIN=[3,7]
MINLEN=4   /* Shortest parent chain */
MAXBRANCHLEN=3 /* Longest branch allowed */
DEBUG=0   /* =1 for debugging */

/* You may add more prefixes. Make sure it is in BOTH of the next two arrays */

Name=new Array("","meth","eth","prop","but","pent","hex","hept","oct","non","dec","undec","dodec")
AlphaOrder=new Array(4,10,2,12,7,6,1,9,8,5,3,11) /* but,dec,di,etc...*/

MAXLEN=Name.length-1


Prename=new Array("","","di","tri","tetra","penta","hexa","hepta","octa","nona","deca","undeca","dodeca")
Grid=new Array() /* an HMAX x VMAX array of points */
Atom=new Array() /* hash containing i,j,up, and root */
NName=new Array() /* NName[n] = # of branches of length n for di,tri, etc. */
Rows=[999,0]
Cols=[999,0]
SubsLtoR=new Array() 
Structure=new Array()

/* an array of arrays [n][iatom] = # of branches of length n at each pt
   note: we don't know which end is which until we are all done! */
DigitCodes="abcdefghijklmnopqrstuvwxyz" /* used for random branch locations */

clen=0  /* chain length */
ix=0    /* x-coord */
iy=0    /* y-coord */
nC=0    /* # of carbons */
up=0    /* up=1,down=0 */
nsubLtoR=0 /* used to determine L--R or R--L numbering */
nsubRtoL=0
sdebug=""  /* displayed at end when DEBUG=1*/
sname="Click 'New' to generate a new structure first."   /* final compound name */
sanalysis=sname /* help */
sanalysis0=sname
schain="" /* (1,2)(1,3) etc */
answer=""

function dowrite(doc,s,isrep)
{
 if(arguments.length==2)isrep=true
 isrep?doc.open("text/html","replace"):doc.open()
 doc.write("<html><body><center>"+s+"</center></body></html>")
 doc.close()
} 

function isay(what){
 
	if(what==answer){
		dowrite(parent.fraAA.document,"Correct. <p>These two structures are "+answer+". <a href=javascript:top.fraIndexA.another(true)>another</a>")
	}else{
		if(sanalysis==sanalysis0){another(true)}
		sanalysis0=sanalysis
		dowrite(parent.fraAA.document,"<font color=red>" + sname2 + "</font> <br><br><a href=javascript:top.fraIndexA.another(true)>another</a>")
		another(false)
	}

	if(answer=="the same") {
		dowrite(parent.fraStatusA.document,"<h2>"+sname+"</h2>")
	} else {
		dowrite(parent.fraStatusA.document,"<h2>"+sname1+"</h2>")
		parent.fraQA.document.getElementById("name2").innerHTML = "<h2>"+sname1b+"</h2>"
	}

}

function another(isnew){
 //window.location=document.URL
 if (isnew){
  smake2=""
  sname1=""
  sname2=""
  sname1b=""
  dowrite(parent.fraStatusA.document,"")
  dowrite(parent.fraAA.document,"Are these two structures <p><a href=javascript:parent.fraIndexA.isay('different')>different</a> or <a href=\"javascript:parent.fraIndexA.isay('the same')\">the same</a>?<br>")
  sanalysis=sanalysis0
  createstructure(true)
  var s=maketable(true)
  smake2=maketable(false)
  var sn=sname + "\n"+Structure
  sname1=sname
  createstructure(false)
  s+=maketable(true)
  smake2+=maketable(false)
  sname1b=sname
  answer=(sname1b==sname1?"the same":"different")
  sname2=(sname1b==sname1?"These two structures are the same.<p>"+sanalysis
	:"These two structures are different.")
  if(sname1!=sname1b)sname=""
 }else{
  var s=smake2
 }
 if(DEBUG){
  s+=maketable2()
  s+="</center><pre>" + sdebug + "</pre>"
  s= sname + "<P>" + s
 }
 dowrite(parent.fraQA.document,s + "<div id='name2'></div>")
 if(isnew && sanalysis==sanalysis0){another(true)}
}

function initialize(){
 sanalysis=""
 sdebug=""
 sname=""
 schain=""
 nC=0
 nsubLtoR=0
 nsubRtoL=0
 Rows=[999,0]
 Cols=[999,0]
 up=0
 Grid=new Array()
 Atom=new Array()
 SubsLtoR=new Array()
 NName=new Array()
 for (var i=1;i<=MAXLEN;i++){
  NName[i]=0
  SubsLtoR[i]=new Array()
  for (var j=1;j<=MAXLEN;j++){
   SubsLtoR[i][j]=0
  }
 }
 for (var i=1;i<=HMAX;i++){Grid[i]=new Array()}
 for (var j=1;j<=VMAX;j++){
  for (var i=1;i<=HMAX;i++){Grid[i][j]=0}
 }
}

function createstructure(isnew){
 var blen=0
 var root=0
 var slist=""
 initialize()
 if(isnew){
  Structure=new Array()
  clen=Math.floor(Math.random()*(MAXLEN-MINLEN)+MINLEN)+1
  getchain(clen)
  Structure[0]=new Array(clen,0)
  slist=DigitCodes.substring(2,clen)
  var ilen=Math.floor(Math.random()*MAXBRANCHLEN)+1
  for (var i=1;i<=ilen;i++){
   if(slist=="")return
   var na=Math.floor(Math.random()*slist.length)
   var n=DigitCodes.indexOf(slist.substring(na,na+1))
   slist=slist.substring(0,na)+slist.substring(na+1,slist.length)
   root=Atom[n]["root"]
   //if(root>2){root--}
   /* ensures that the first chain is the valid longest chain
    (only important if adding branches to branches)
   */
   blen=Math.floor(Math.random()*root+1)  
   Structure[0][1]+=blen
   Structure[i]=new Array(n,blen)
  }
 }else{
  clen=Structure[0][0]
  getchain(clen)
 }
 sname=Name[clen]+"ane"
 for (var i=1;i<Structure.length;i++){
  blen=addbranch(clen,Structure[i][0],Structure[i][1])
 }
 var s1=getname(clen,true)
 var s2=getname(clen,false)
 if(nsubLtoR!=nsubRtoL){
  sname=(nsubLtoR<nsubRtoL?s1:s2)
  sanalysis="Of the two possible numbering schemes,<p>"+(sname==s1?"<b>":"")+s1 + "</b><p>and<p>"+(sname==s1?"":"<b>")+s2+"</b>,<p>the "+(sname==s1?"first":"second")+" is correct."
 }else{
  sname=(s1>s2?s2:s1)
  if(s1!=s2){
   sanalysis="Of the two possible numbering schemes,<p>"+(sname==s1?"<b>":"")+s1 + "</b><p>and<p>"+(sname==s1?"":"<b>")+s2+"</b><p>the "+(sname==s1?"first":"second")+" results in the lower numbering for the first-cited substituent."
 }else{
   sanalysis="Only one numbering scheme is possible in this case: <p><b>" + sname
  }
 }  
 sdebug+="\n"+nsubLtoR + ","+nsubRtoL
}

function getname(clen,mode){
  var s=""
  var n=0
  var sn=""
  for(var i=0;i<=MAXLEN;i++){
   n=AlphaOrder[i]
   //sdebug+="\n"+n+" "+NName[n]
   if(NName[n]){
    if(s.length){s+="-"}
    s+=getsubname(n,mode)+"-"+Prename[NName[n]]+Name[n]+"yl"
   }
  }
  return s+sname 
}

function getsubname(n,LtoR)
{
 var sn=""
 if(LtoR){
  for(var j=1;j!=MAXLEN;j++){
   for(var k=1;k<=SubsLtoR[n][j];k++){
    sn+=(sn==""?"":",")+j
   }
  }
 }else{
  for(var j=MAXLEN;j>=1;j--){
   for(var k=1;k<=SubsLtoR[n][j];k++){
    sn+=(sn==""?"":",")+(clen+1-j)
   }
  }
 }
 return sn
}

function getchain(l){
 var root=0
 sdebug+= "\nchain " + l 
 for (var n=1;n<=l;n++){
   getnextpt(root)
   if(root>=0 && n<l/2)root++
   if(root<0 || n>l/2)root--
   schain+="("+Atom[nC]["i"]+","+Atom[nC]["j"]+")"
 }
}

function addbranch(clen,iatom,blen){
 ix=Atom[iatom]["i"]
 iy=Atom[iatom]["j"]
 up=1-Atom[iatom]["up"]
 var n=blen
 var nC0=nC
 for (var i=1;i<=n;i++){
  var trying=10
  while(trying){
   trying--
   getnextpt(-1)
   if(nC>nC0){trying=0}
  }
 }
 n=nC-nC0
 if(n){
  NName[n]++
  SubsLtoR[n][iatom]++
  nsubLtoR=nsubLtoR+Math.pow(2,iatom)
  nsubRtoL=nsubRtoL+Math.pow(2,clen+1-iatom)
 }
 return n
}


function getnextpt(root){
 //alert(up)
 var i=ix
 var j=iy
 var j2=iy+(up?1:-1)
 if(root<0){
  if(Math.random()>0.5 || Grid[ix][j2]){
   i+=(Math.random()>0.5?1:-1)
 //  sdebug+="\ntryingi " +i + " " + j + " up " + up
   if(i<1||i>=HMAX){return}
   if(i+1!=ix && i<HMAX && Grid[i+1][j]){sdebug+=" a";return}
   if(i-1!=ix && i>1 && Grid[i-1][j]){sdebug+=" b";return}
   if(!up && j<VMAX && Grid[i][j+1]){sdebug+=" c";return}
   if(up && j>1 && Grid[i][j-1]){sdebug+=" d";return}

  }else{
   j=j2
//   sdebug+="\ntryingj " +i + " " + j
   if(j<1||j>=VMAX){return}
   if(i<HMAX && Grid[i+1][j]){return}
   if(i>1 && Grid[i-1][j]){return}
  } 
 }else{
  if(nC==0){
   i=ORIGIN[0]
   j=ORIGIN[1]
  }else{
   if(Math.random()>0.5 || Grid[ix][j2]){
    i++
   }else{
    j=j2
   }
  }
 }
 if (Grid[i][j]){sdebug+= " Grid["+i+","+j+"]!=0";return}
 ix=i
 iy=j
 Grid[ix][iy]=1
 if(ix<Cols[0]){Cols[0]=ix}
 if(ix>Cols[1]){Cols[1]=ix}
 if(iy<Rows[0]){Rows[0]=iy}
 if(iy>Rows[1]){Rows[1]=iy}
 nC++
 Atom[nC]=new Array()
 Atom[nC]["i"]=ix
 Atom[nC]["j"]=iy
 Atom[nC]["root"]=root
 Atom[nC]["up"]=up
 sdebug+="\nnextpt "+nC + ":" + ix + " " + iy + " " + root + " " + up
 up=1-up
}

function maketable(isnew){
 var up=0
 var row=1
 var a1=0
 var a2=0
 var a3=0
 var j2=0
 var sc=""
 var salt=""
 var s="<center><table border=0 cellspacing=0 cellpadding=0>"
 //alert(schain)
 for (var j=1;j<=Rows[1];j++){
   if(j>=Rows[0]){
    s+="<tr>\n"
    up=(row?0:1)
    for (var i=1;i<=Cols[1];i++){
      if(i>=Cols[0]){
       if (Grid[i][j]){
        j2=j+(up?-1:1)
	s+="<td><img src="+(up?"u":"d")
        a1=(i==1?0:(Grid[i-1][j]?1:0))
	a2=(j==(up?0:VMAX)?0:(Grid[i][j2]?1:0))
        a3=(i==HMAX?0:(Grid[i+1][j]?1:0))
 	if(!isnew && ischain(i,j)){
 	 if(a1 && !ischain(i-1,j)){a1="x"}
 	 if(a2 && !ischain(i,j2)){a2="x"}
 	 if(a3 && !ischain(i+1,j)){a3="x"}
	 sc="c"
	}else{
	 sc=""
	}
	s+=""+a1+a2+a3+sc
        s+=".gif alt="+salt+"></td>\n"
       }else{
        s+="<td><img src=u000.gif></td>\n"
       }
      }
      up=1-up
    }
    s+="</tr>\n"
   }
   row=1-row
 }
 return s+"</table></center>"
}

function ischain(i,j){
 return(schain.indexOf("("+i+","+j+")")>=0)
}
function maketable2(){
 var up=0
 var row=0
 var s="<table>"
 for (var j=1;j<VMAX;j++){
   s+="<tr>\n"
   up=(row?0:1)
   for (var i=1;i<HMAX;i++){
     if (Grid[i][j]){
      s+="<td>1 src="+(up?"u":"d")
      s+=(i==1?"0":(Grid[i-1][j]?"1":"0"))
      s+=(j==(up?0:VMAX)?"0":(Grid[i][j+(up?-1:1)]?"1":"0"))
      s+=(i==HMAX?"0":(Grid[i+1][j]?"1":"0"))
      s+=".gif</td>\n"
     }else{
      s+="<td>0 src=u000</td>\n"
     }
     up=1-up
   }
   s+="</tr>\n"
   row=1-row
 }
 return s+"</table>"
}

function clearFrames(trigger) {
  if(!trigger) {
	setTimeout('clearFrames(1)',200)
	return
  }
  if (!parent.fraQA.document.getElementById("name2"))return
  dowrite(parent.fraStatusA.document,"")
  dowrite(parent.fraQA.document,"")
  dowrite(parent.fraAA.document,"")
}
