
function determinename(){

/* 

At this point we have the grid set up. That is all we will assume.
Structures:

 Grid[i][j]["val"] 1 for atom to do, -1 for atom done, 0 otherwise

*/
 initializegrid()

 if(!getallchains()){
	alert("Cyclic path found! Can't continue.")
 }
 showanalysis(false)
}

function getallchains(){
 var row=0
 var k=0

 EndArray=new Array()
 ChainArray=new Array() 
 nchains=0
 for (var n=1;n<=nC;n++){
  if(Atom[n]["valence"]==1){
    for (var k=1;k<=nC;k++){
	Atom[k]["chain"]=new Array()
	Atom[k]["branch"]=new Array()  
	Atom[k]["nch"]=0
	Atom[k]["nbr"]=0
	Atom[k]["prev"]=0
    }
    if(!getchain(n,0,0,0)){return 0}
  }
 }
 var maxc=0
 for(var i=0;i<nchains;i++){
   ChainArray[i][0][0]=0
   ChainArray[i][1][0]=1
   if(ChainArray[i][0].length>maxc)maxc=ChainArray[i][0].length
 }
 var maxb=0
 for(var i=0;i<nchains;i++){
   if(ChainArray[i][0].length==maxc){
	ChainArray[i][0][0]=1
	if(ChainArray[i][1].length>maxb)maxb=ChainArray[i][1].length
   }
 }

 var firstb=999
 for(var i=0;i<nchains;i++){
   ChainArray[i][0][0]=(ChainArray[i][0][0] && ChainArray[i][1].length==maxb)
   if(ChainArray[i][0][0] && ChainArray[i][1][1]<firstb)firstb=ChainArray[i][1][1]
 }

//temporarily removing identical chains
 for(var i=1;i<nchains;i++){
   for(var j=0;j<i;j++){
	if(ChainArray[i][0][0] && ChainArray[j][0][0]){
		if(ChainArray[j][0][maxc-1] && ChainArray[j][0][1]==ChainArray[i][0][maxc-1]){
			if(ChainArray[i][1][1]==firstb){var i2=j}else{var i2=i}
			ChainArray[i2][1][0]=0
		}
		
	}
   }
 }

 for(var i=0;i<nchains;i++){
	if(ChainArray[i][0][0]){
	   ChainArray[i][0][0]=(ChainArray[i][1][1]==firstb)
	}
 }

 var nch=0
 var ncshow=0
 sanalysis="<br>Click on a link to <br>highlight the specified chain.<p>" 
 for(var i=0;i<nchains;i++){
   if(ChainArray[i][1][0]){
	sanalysis+="<br><a href=javascript:parent.fraIndexD.showchain("+i+")>Chain "+(++ncshow)+"</a> " 
	if(ChainArray[i][0][0]==true){
		nch++
//		sanalysis+=ChainArray[i][0]+" "+ChainArray[i][1]
		sanalysis+=" has "+ (maxc-1) + " carbons."
	}else{
		if(ChainArray[i][0].length<maxc){
			sanalysis+=" is too short."
		}else{
			if(ChainArray[i][1].length<maxb){
				sanalysis+=" has too few branches."
			}else{
				if(ChainArray[i][1][1]>firstb){
					sanalysis+=" too large # for 1<sup>st</sup> branch" + ChainArray[i][1][1]+" " + firstb
				}
			}
		}
	}
   }
 }


 maxc--
 maxb-=2
 sanalysis+="<p>There "+(nch>1?"are "+nch+" chains":"is only one chain")+ " "+(maxc)+ " carbons long to consider.<p>"+(nch==1?"There ":"In each case there ")+(maxb==1?"is ":"are ") + maxb +" branch"+(maxb==1?"":"es")+(maxb>1?", the first of which is":"")+(maxb>0?" at position "+ firstb:"")+"."
 return 1
}

function showchain(ichain){
 for (var j=1;j<=VMAX;j++){
	for (var i=1;i<=HMAX;i++){
		Grid[i][j]["ischain"]=0
	}
 }
 for (var i=1;i<ChainArray[ichain][0].length;i++){
	var iatom=ChainArray[ichain][0][i]
	Grid[Atom[iatom]["i"]][Atom[iatom]["j"]]["ischain"]=1
 }
 another(false)
}

function getchain(n,iprev,inewbranch,ipath){
  if(Atom[n]["prev"]){return 0}
  Atom[n]["prev"]=iprev
  if(iprev){copyatom(iprev,n)}
  Atom[n]["nch"]++
  Atom[n]["chain"][Atom[n]["nch"]]=n
  if(iprev){
	if(inewbranch){
		Atom[n]["nbr"]++
		var k=Atom[n]["nbr"]
        	Atom[n]["branch"][k]=Atom[n]["branch"][k-1]+1
  	}else{
		Atom[n]["branch"][Atom[iprev]["nbr"]]++		
	}
  }else{
	Atom[n]["nbr"]=1
	Atom[n]["branch"][1]=1		
  }
  var k=Atom[n]["valence"]
  if(iprev && k==1){
	ChainArray[nchains]=new Array()
	ChainArray[nchains][0]=new Array()
	ChainArray[nchains][1]=new Array()
	for(var k=1;k<=Atom[n]["nch"];k++){
		ChainArray[nchains][0][k]=Atom[n]["chain"][k]
	}
	for(var k=1;k<=Atom[n]["nbr"];k++){
		ChainArray[nchains][1][k]=Atom[n]["branch"][k]
	}
  	nchains++
	return 1
  }
  var i=Atom[n]["i"]
  var j=Atom[n]["j"]
  var up=Atom[n]["up"]
  var j2=j+(up?-1:1)
  if(i>1 && Grid[i-1][j]["val"] && Grid[i-1][j]["n"]!=iprev){getchain(Grid[i-1][j]["n"],n,k>2,1)}
  if(j!=(up?0:VMAX) && Grid[i][j2]["val"] && Grid[i][j2]["n"]!=iprev){getchain(Grid[i][j2]["n"],n,k>2,2)}
  if(i<HMAX && Grid[i+1][j]["val"] && Grid[i+1][j]["n"]!=iprev){getchain(Grid[i+1][j]["n"],n,k>2,3)}
  return 1 
}

function copyatom(i,j){
 Atom[j]["nbr"]=Atom[i]["nbr"]
 Atom[j]["nch"]=Atom[i]["nch"]
 for(var k=1;k<=Atom[j]["nbr"];k++){
	Atom[j]["branch"][k]=Atom[i]["branch"][k]
 }
 for(var k=1;k<=Atom[j]["nch"];k++){
	Atom[j]["chain"][k]=Atom[i]["chain"][k]
 }
}

function initializegrid(){

 sanalysis=""
 nC=0
 Atom=new Array()
 var row=0
 var n=0
 var k=0
 for (var j=1;j<=VMAX;j++){
   up=(row?1:0)
   for (var i=1;i<=HMAX;i++){
     if (Grid[i][j]["val"]){
	n++
	Grid[i][j]["n"]=n
	Atom[n]=new Array()
	Atom[n]["i"]=i
	Atom[n]["j"]=j
	Atom[n]["val"]=1
	Atom[n]["up"]=up
	Atom[n]["valence"]=valenceof(i,j,up)
     }
     up=1-up
   }
   row=1-row
 }
 nC=n
}

function valenceof(i,j,up){
 var j2=j+(up?-1:1)
 var n=0
 n+=(i==1?0:(Grid[i-1][j]["val"]?1:0))
 n+=(j==(up?0:VMAX)?0:(Grid[i][j2]["val"]?1:0))
 n+=(i==HMAX?0:(Grid[i+1][j]["val"]?1:0))
 return n
}

/*

Bob Hanson hansonr@stolaf.edu 6/12/2000
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 */
MAXBRANCHES=3 /* Most 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

//MAXLEN=6

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() 
/* 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

EndArray=new Array()
ChainArray=new Array()
nchains=0


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 showthename(){
 if(sanalysis==sanalysis0){another(true)}
 dowrite(parent.fraStatusD.document,"<h2>"+sname+"</h2>")
 sanalysis0=sanalysis
 showanalysis(true)
}
function showanalysis(isanother){
 dowrite(parent.fraAD.document,sanalysis)
 if(isanother){another(false)}
}

function another(isnew){
 //window.location=document.URL
 if (isnew){
  dowrite(parent.fraStatusD.document,"")
  dowrite(parent.fraAD.document,"")
  sanalysis=sanalysis0
  createstructure()
 }
 var s=maketable(isnew)
 if(DEBUG){
  s+=maketable2()
  s+="</center><pre>" + sdebug + "</pre>"
  s= sname + "<P>" + s
 }
 dowrite(parent.fraQD.document,s)
 if(isnew && sanalysis==sanalysis0){another(true)}
}



function initialize(){
 sanalysis=""
 sdebug=""
 sname=""
 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]=new Array()
   Grid[i][j]["val"]=0
  }
 }
}

function createstructure(){
  initialize()
  clen=Math.floor(Math.random()*(MAXLEN-MINLEN)+MINLEN)+1
  newchain(clen)
  sname=Name[clen]+"ane"
  var slist=""
  slist=DigitCodes.substring(2,clen)
  var ilen=Math.floor(Math.random()*MAXBRANCHES)+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)
   addbranch(n,clen)
  }
  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")+" results in the lower number for the first substitutent from the end."
  }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=""
  var m=AlphaOrder.length
  for(var i=0;i<m;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 newchain(l){
 root=0
 sdebug+= "\nchain " + l 
 for (var n=1;n<=l;n++){
   getnextpt(root)
   if(n<l/2)root++
   if(n>l/2)root--
 }
}

function addbranch(iatom,clen){
 ix=Atom[iatom]["i"]
 iy=Atom[iatom]["j"]
 root=Atom[iatom]["root"]
 //if(root>2){root--}
 /* ensures that the first chain is the valid longest chain
    (only important if adding branches to branches)
 */
 up=1-Atom[iatom]["up"]
 var n=Math.floor(Math.random()*root+1)  
 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)
 }
}


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]["val"]){
   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]["val"]){sdebug+=" a";return}
   if(i-1!=ix && i>1 && Grid[i-1][j]["val"]){sdebug+=" b";return}
   if(!up && j<VMAX && Grid[i][j+1]["val"]){sdebug+=" c";return}
   if(up && j>1 && Grid[i][j-1]["val"]){sdebug+=" d";return}

  }else{
   j=j2
//   sdebug+="\ntryingj " +i + " " + j
   if(j<1||j>=VMAX){return}
   if(i<HMAX && Grid[i+1][j]["val"]){return}
   if(i>1 && Grid[i-1][j]["val"]){return}
  } 
 }else{
  if(nC==0){
   i=ORIGIN[0]
   j=ORIGIN[1]
  }else{
   if(Math.random()>0.5 || Grid[ix][j2]["val"]){
    i++
   }else{
    j=j2
   }
  }
 }
 if (Grid[i][j]["val"]){return}
 ix=i
 iy=j
 Grid[ix][iy]["val"]=1
 Grid[ix][iy]["ischain"]=(root>=0)
 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=0
 var a1=0
 var a2=0
 var a3=0
 var j2=0
 var sc=""
 var salt=0
 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?1:0)
    for (var i=1;i<=Cols[1];i++){
      if(i>=Cols[0]){
       if (Grid[i][j]["val"]){
        j2=j+(up?-1:1)
	s+="<td><img src="+(up?"u":"d")
        a1=(i==1?0:(Grid[i-1][j]["val"]?1:0))
        a2=(j==(up?0:VMAX)?0:(Grid[i][j2]["val"]?1:0))
        a3=(i==HMAX?0:(Grid[i+1][j]["val"]?1:0))
	salt=4-a1-a2-a3
	salt="CH"+(salt==1?"":salt)
	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(Grid[i][j]["ischain"])
}

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]["val"]){
      s+="<td>1 src="+(up?"u":"d")
      s+=(i==1?"0":(Grid[i-1][j]["val"]?"1":"0"))
      s+=(j==(up?0:VMAX)?"0":(Grid[i][j+(up?-1:1)]["val"]?"1":"0"))
      s+=(i==HMAX?"0":(Grid[i+1][j]["val"]?"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>"
}


