/*

Copyright Robert M. Hanson, St. Olaf College, Northfield, MN

 hansonr@stolaf.edu 6/14/2000
 bh: updated 1:52 PM 05/09/2005 for iso...

*/

testing=0   /* =1 for debugging */

Examples=new Array(""
        ,"3-methylpentane"
        ,"2-(4-methylhexyl)undecane"
        ,"3-methylidene-1-heptyne"
        ,"1,3-dimethylcyclopentane"
	,"2-hexene"
	,"2,4-hexadiene"
	,"2,4-octadien-6-yne"
        ,"3-methyl-2-phenylnaphthylene"
        ,"1,2-dibromopentane"
        ,"iodobenzene"
        ,"dichloromethane"
        ,"methyl bromide"
        ,"methylene chloride"
        ,"2-pentanol"
        ,"methanol"
        ,"isopropyl alcohol"
        ,"2-hydroxy-3-pentanone"
        ,"2,3-pentanediol"
        ,"3-methylphenol"
        ,"methoxymethanol"
        ,"diethyl ether"
        ,"methyl ether"
        ,"methyl ethyl ether"
        ,"triethylamine"
        ,"isopropylamine"
        ,"2-amino-3-pentanone"
        ,"N,N-diethylmethylamine"
        ,"4-(N,N-dimethylamino)pyridine"
        ,"2-pentanone"
        ,"3-hexen-2-one"
        ,"2-oxopentanoic acid"
        ,"methyl ethyl ketone"
        ,"benzoic acid"
        ,"2-methylbutyl benzoate"
        ,"1-acetoxy-2-methylbenzene"
        ,"methyl formate"
        ,"isopropyl acetate"
        ,"propanoyl chloride"
)

Replace=new Array([]
,["sec-","sec_"]
,["tert-","tert_"]
,["amine","Amino"]
,["amino","Amino"]
,["thiane","Thiane"]
,["thiol","Thiane"]
,["thio","Thio"]
,["allene","1,2-propadiene"]
,["carbon tetra","methane-1,1,1,1-tetra"]
,["methylene ","methane-1,1-di"]
,["methylene","methyliden"]
,["benzene","phenane"]
,["benzoic","phenanecarboxylic"]
,["naphthylene","naphthane"]
,["acetone","Acetylmethane"]
,["acetaldehyde","ethanal"]
,["formal","methanal"]
,["aldehyde","al"]
,[" alcohol_","-1-ol_"]
,["aceto","Aceto"]
,["formo","Formo"]
,["acet","ethano"]
,["form","methano"]
,["carbon ","methane"]
,["carboxylic acid","COOH"]
,["oic acid","OOH"]
,["carbonyl ","&CO-1-"]
,["oyl ","O-1-"]
,["ene","en"]
,["yne","yn"]
,["anone","on"]
,["al_","1-one_"]
,["one","on"]
,["nitrile","Nitrile"]
,["N-","0-"]
,["N,","0,"]
,["[,","(,"]
,["],","),"]
)

Roots=new Array([]
,["ether","Rad","O"]
,["keton","Rad","C(=O)"]
,["isoprop","yl","C(C)C"]
,["isobut","yl", "CC(C)C"]
,["isopent","yl","CCC(C)C"]
,["isohex","yl", "CCCC(C)C"]
,["sec_but","yl", "C(C)CC"]
,["tert_but","yl",  "C(C)(C)C"]
,["tert_pent","yl", "C(C)(C)CC"]
,["neopent","yl",   "CC(C)(C)C"]
,["Amin","o","N"]
,["Thi","o","S"]
,["meth","yl","C"]
,["eth","yl", "CC"]
,["prop","yl","CCC"]
,["but","yl", "CCCC"]
,["pent","yl","CCCCC"]
,["hex","yl", "CCCCCC"]
,["hept","yl","CCCCCCC"]
,["oct","yl", "CCCCCCCC"]
,["non","yl", "CCCCCCCCC"]
,["undec","yl","CCCCCCCCCCC"]
,["dodec","yl","CCCCCCCCCCCC"]
,["dec","yl", "CCCCCCCCCC"]
,["vin","yl","C=C"]
,["Acet","yl","C(=O)C"]
,["Form","yl","C(=O)"]
,["all","yl","CC=C"]
,["naphth","yl","8,2:c%1_!1_c!2_c!3_c!4_c%2_c!5_c!6_c!7_c!8_c%2_%1_"]
,["phen","yl","6,1:c%1_!1_c!2_c!3_c!4_c!5_c%1_!6_"]
,["benz","yl","6,1:C!1_c%1_c!2_c!3_c!4_c!5_c%1_!6_"]
,["pyridine","XX","6,1:n%1_!1_c!2_c!3_c!4_c!5_c%1_!6_"]
,["isopropen","yl","C(C)=C"]//purposely after isopropyl
//parent roots stop here
,["en","","="]
,["yn","","#"]
,["ol","","O"]
,["on","","=O"]
,["fluor","o","F"]
,["chlor","o","Cl"]
,["brom","o","Br"]
,["iod","o","I"]
,["Amin","o","N"]
,["hydrox","y","O"]
,["ox","o","=O"]
,["COOH","","C(=O)O"]
,["OOH","","=O)(O"]
,["&te_","","(=O)(O("]
,["&COO","","C(=O)(O("]
,["&CO","","C(=O)("]
,["O","","=O"]
,["carboNitrile","","C#N"]
,["Nitrile","","#N"]
,["cyan","o","C#N"]
,["mercapt","o","S"]
)

Endings=new Array(["yl",""]
,["oxy","O"]
,["oxycarbonyl","C(=O)O"]
)

Todo=new Array()
Cyclo=new Array()
Parent=new Array()
Substs=new Array()
Smiles=new Array()
Locants=new Array()
Links=new Array()
smilesname=""
branchname=""
parentname=""
sthisop=""
stoken=""
sformula=""
iparent=0
iscyclo=0
havenum=0
linktype=0
icycle=10
iparentlen=0
imayhaveendings=0
Linklist=new Array("","=","#")

/*

 You may add more examples, roots, replacements, and prefixes.
 For a new prefixe, 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")
Prename2=new Array("","","bis","tris","tetrakis","pentakis","hexakis","heptalkis")
Prenamechar1=" dtphonub"

function loadx(){
 var s="<select name=examples onchange=getexample()>"
 for(var i=1;i<Examples.length;i++){s+="<option>"+Examples[i]}
 return s+"</select>"
}

function random(){
 createstructure()
 document.frm.sname.value=sname
 drawthestructure()
}

function getexample(){
 document.frm.sname.value=document.frm.examples[document.frm.examples.selectedIndex].text
 drawthestructure()
}


//constants--don't change

    operators=" -(),"          //the ' ' here is important
   			   	//because s.indexOf("") returns 0!
//# 180
     numerals=" N0123456789"   //N will be turned into 0

function drawthestructure(smilename){
 if(!smilename){
	sname=document.frm.sname.value
	ToDo=new Array()
 	icycle=10
 	iparentlen=0
 	sname=strclean(sname)
 	smilename=getsmiles(sname)
 }

 if(smilename=="")return
 var s="<body>Sending SMILES request to www.daylight.com"
	s+="<FORM name=frm METHOD='POST' ACTION='http://www.daylight.com/daycgi/depictform'>"
	s+="<INPUT NAME='smiles' size=50 value='"+smilename+"'></FORM></body>"
 dowrite(parent.fraQW.document,s)
 dowrite(parent.fraStatusW.document,"<center><b>"+sname+"</b></center>")
 if(testing){alert(smilename)}else{parent.fraQW.document.frm.submit()}
}


function getsmiles(snam){
 if(testing)alert2("getsmiles",snam)
 Cyclo=new Array()
 Substs=new Array()
 Smiles=new Array()
 Locants=new Array()
 Links=new Array()
 smilesname=""
 branchname=""
 parentname=""
 iparent=0
 iscyclo=0
 for(var i=0;i<=MAXLEN;i++){
  Substs[i]=new Array()
  Smiles[i]=new Array()
  Links[i]=new Array()
  Cyclo[i]=false
 }
 sformula=replaceall(snam+"_")
 parentname=extractparent()
 if(parentname==""){alert("Can't determine root name of parent chain in "+snam);return ""}
 /* Locant 99 indicates an implied 1 only if no other numbers are present */
 while(getnamedbranch()){
  for(var i=0;i<Locants.length;i++){
   var l=Locants[i]
   if(l==99)l=(Locants.length==1?1:MAXLEN+1)
   Substs[l][Substs[l].length]=branchname
   Smiles[l][Smiles[l].length]=smilesname   
   Links[l][Links[l].length]=Linklist[linktype]   
  }   
 }
 setparent()
 if(testing)alert(makeparenttable())
 while(checktodo()){}
 smilesname=strsub(smilesname,"(=)","=")
 smilesname=strsub(smilesname,"(#)","#")
 smilesname=strsub(smilesname,"((","")
 smilesname=strsub(smilesname,"()","")
 return smilesname
}

function replaceall(snam){
 var s=snam
 for(var i=1;i<Replace.length;i++){s=strsub(s,Replace[i][0],Replace[i][1])}
 return s
}

function extractparent(){

 var i=0
 var s=sformula
 var iptlast=-1
 var ipt=0
 var slast=""
 var sn=""
 var ssub="--------------------"
 var isradico=0
 iparent=0
 if(testing)alert("Extracting parent name from:" + sformula)

//special problems-"chloroform"

 if(s.indexOf("omethano_")>=0)s="1,1,1-tri"+s

 sformula=s
 ipt=0
 while(ipt>=0){
  for(var i=1;i<Roots.length;i++){
   if(Roots[i][1].length==0)break
   ipt=s.indexOf(Roots[i][0])
   if (ipt>=0){
	sn=Roots[i][0]
	if(ipt>iptlast){
	 iparent=i
	 iptlast=ipt
	 slast=sn
	}
        s=s.substring(0,ipt)+ssub.substring(0,sn.length)+s.substring(ipt+sn.length,s.length)
	break
   }
  }
 }
 if(iptlast<0)return ""
 sformula=sformula.substring(0,iptlast)+"--"+sformula.substring(iptlast+slast.length,sformula.length)
 s=sformula
 if(s.charAt(0)=="(")s="1-"+s
 isradico=(Roots[iparent][1]=="Rad")
 if(!isradico && Prenamechar1.indexOf(s.charAt(0))>0){
  sn=""
  for(var i=2;i<Prename.length;i++){
   if(s.indexOf(Prename[i])==0){
    for(var j=0;j<i;j++)sn+="1,"
   }
  }
  for(var i=2;i<Prename2.length;i++){
   if(s.indexOf(Prename2[i])==0){
    for(var j=0;j<i;j++)sn+="1,"
   }
  }
  if(sn.length)s=sn.substring(0,sn.length-1)+"-"+s
 }

 s=strsub(s," _","_")
 sformula=s
 iscyclo=(sformula.indexOf("cyclo--")>=0)
 sformula=strsub(sformula,"cyclo--","--")


// handle amines
 if(slast=="Amin"){
	sformula=strsub(sformula,"yl","Yl")
	sformula=strsub(sformula,"Yl","yl-0-")
	sformula=strsub(sformula,"yl-0--0-","yl-0-")
 }

// handle radicofunctional parent<space>suffix 

 i=sformula.indexOf(" ")
 if(i>=0){
	if(sformula.indexOf("ate_")>=0)sformula="1-("+sformula.substring(0,i)+")"+sformula.substring(i+1,sformula.length)
	if(isradico){
		if(sformula.indexOf(" --")==i){
			if(sformula.indexOf("di")<0){sformula="bis("+sformula}
		}
		sformula=strsub(sformula," ",")-1-(")
		sformula=strsub(sformula,"-1-(--","--")
		sformula="1-("+sformula
		sformula=strsub(sformula,"1-(di","1,1-di")
		sformula=strsub(sformula,"1-(bis","1,1-bis")
	}
 }

// clean various endings:

 sformula=strsub(sformula,"oate_","&te_")
 sformula=strsub(sformula,"ate_","&te_")
 sformula=strsub(sformula,"--a-","-")
 sformula=strsub(sformula,"--ane","--")
 sformula=strsub(sformula,"--an","--")
 sformula=strsub(sformula,"--a","--")
 sformula=strsub(sformula,"--oo","--")

//radico-functional type 'methyl bromide' or 'phenylamine':

 sformula=strsub(sformula,"--yl ","-1-")
 sformula=strsub(sformula,"--yl","-1-")
 sformula=strsub(sformula,"ide_","o_")

// implicit initial 1 as in 2-bromoethylcyclohexane causes problems

 if(numerals.indexOf(sformula.charAt(0))<1)sformula="1-"+sformula

// adjust for explicit 2-hexanone types:

 sformula=strsub(sformula,"---","-")

// add implicit 1- for suffixes

 sformula=strsub(sformula,"--","-99-")
 sformula=strsub(sformula,"-","-99-")


 s=""
 imayhaveendings=false
 for(var i=1;i<Endings.length;i++){
  imayhaveendings|=(sformula.indexOf(Endings[i][0])>=0)
 }
 if(testing)alert(sformula+" extractparent: " + slast + " iscyclic: "+iscyclo)
 return slast
}

function setparent()
{
 var s=Roots[iparent][2]
 var ss=""
 var ssx=""
 var ic=iscyclo
 var i=0
 var na=s.indexOf(",")
 var isexplicit=(na>=0)
 var sm=""
 if(isexplicit){  //#subst,#rings:
  i=parseInt(s.substring(0,na))
  s=s.substring(na+1,s.length)
  iparentlen=i
  na=s.indexOf(":")
  ic=parseInt(s.substring(0,na))
  s=s.substring(na+1,s.length)
  s=fixsmiles(s,ic)
  smilesname=s
 }else{
  smilesname=""
  iparentlen=s.length
 }
 for(var i=1;i<=iparentlen;i++){
  if(isexplicit){
   ss=""
  }else{
   ss=s.charAt(i-1)
   if(ic && (i==1 || i==iparentlen)){
    ss+="%"+icycle
    icycle+=(i==1?0:1)
   }
  }
  ssx=""
  for(var j=0;j<Smiles[i].length;j++){
   sm=Links[i][j]+fixsmiles(Smiles[i][j],0)
   if(Substs[i][j].charAt(0)=="&"){
	ssx=sm+ssx
   }else{
	ssx+="("+sm+")"
   }
  }
  ss+=ssx
  if(isexplicit){
   smilesname=strsub(smilesname,"!"+i+"_",ss)
  }else{
   smilesname+=ss
  }
 }
 s=""
 for(var j=0;j<Smiles[0].length;j++){s+="("+Links[0][j]+Smiles[0][j]+")"}
 if(s!=""){
  smilesname=strsub(smilesname,"N","_n_")
  smilesname=strsub(smilesname,"_n_","N"+s)
 }
}

function fixsmiles(smileinfo,ic0){
 var i=0
 var isubs=0
 var ic=ic0
 var na=smileinfo.indexOf(",")
 if(ic==0 && na<0)return smileinfo
 var s=smileinfo
 if(na>=0){
  isubs=parseInt(s.substring(0,na))
  s=s.substring(na+1,s.length)
  na=s.indexOf(":")
  ic=parseInt(s.substring(0,na))
  s=s.substring(na+1,s.length)
  for(var i=1;i<=isubs;i++){s=strsub(s,"!"+i+"_","")}
 }
 if(ic==0)return s
 for(var i=1;i<=ic;i++){s=strsub(s,"%"+i+"_","%"+icycle);icycle++}
 return s
}


function checktodo(){
 var n=ToDo.length
 var agin=0
 for(var i=0;i<n;i++){
   var s=smilesname
   var sn=ToDo[i]
   if(sn!="" && s.indexOf("*"+i+"*")>=0){
	smilesname=getsmiles(sn)
	s=strsub(s,"*"+i+"*",smilesname)
	smilesname=s
	ToDo[i]=""
	agin=1
   }
 }
 return(agin) 
}

function getnamedbranch(){
 Locants=new Array()
 sformula=strchop(sformula,"-")
 if(sformula=="" || sformula=="_"){return 0}
 if(testing)alert(sformula)
 smilesname=""
 branchname=""
 havenum=1
 var stoken=""
 var icount=0
 while(havenum){
  stoken=gettoken(true)
  if(havenum){
   if(sthisop!="-" && sthisop!=","){
     alert("Missing '-' before "+sformula)
     return 0
   }    
   var i=(stoken=="N"?0:parseInt(stoken))
   icount+=(i==99?0:1)
   Locants[Locants.length]=i
   //if(testing)alert("Parsing "+stoken + " " +Locants)
   havenum=(sthisop==",")
  }
 }
 if(testing)alert("getnamed branch:" + Locants + " token: " + stoken + " formula:" + sformula)

 if(icount>1){
	var s1=Prename[icount]
	var s2=Prename2[icount]
	if(sformula.indexOf(s1)==0){
		sformula=strchop(sformula,s1)
	}else{
		if(sformula.indexOf(s2)==0){
			sformula=strchop(sformula,s2)
                        if(sformula.indexOf("(")!=0){
				alert("Missing '(' after "+s2)
				return 0 
			}
		}else{
			alert("Missing "+s1+" or "+s2+" before "+sformula)
			return 0 
		}
	}
 }
 if(sformula=="")sformula=stoken
 if(sformula.indexOf("(")==0){
	branchname=ptokenof(sformula)+"ane"
	branchname=strsub(branchname,"ylane","ane")
	smilesname="*"+ToDo.length+"*"
	ToDo[ToDo.length]=branchname
	return 1
 }
 getroot() 
 if(testing)alert("getnamed branch1:" + Locants + " token: " + stoken + " formula:" + sformula +" smilesname:"+smilesname)
 return Locants.length
}

function getroot(){
 branchname=""
 smilesname=""
 linktype=0 
 var s=sformula
 var ipt=0
 var spre=""
 var nend=(imayhaveendings?Endings.length:1)
 var n=0
 if(testing)alert("getroot: "+s)
 iscyc=(sformula.indexOf("cyclo")==0)
 if(iscyc)s=strchop(s,"cyclo")
 for(var i=1;i<Roots.length;i++){
  n=(Roots[i][1]=="yl"?nend:1)
  for(var ii=0;ii<n;ii++){
   spre=Roots[i][0]+(ii==0?Roots[i][1]:Endings[ii][0])
   ipt=s.indexOf(spre)
   if(ipt==0){
	s=strchop(s,spre)
	branchname=spre
        if(testing)alert("found: "+spre)
        smilesname=(ii>0?Endings[ii][1]:"")+Roots[i][2]
        if(s.indexOf("iden")==0 || s.indexOf("idyn")==0){
                linktype=(s.indexOf("iden")==0?1:2)
                s=s.substring(4,s.length)
        }
	if(iscyc){
                smilesname="C%"+icycle+smilesname.substring(1,smilesname.length)+"%"+icycle
		icycle++
	}
	sformula=s
        return
   }
  }
 }
}


function makeparenttable(){
 var s="<center><table border=1>"
  s+="\n<tr><td>j<td>Substs[j]<td>Smiles[j]<td>Links[j]"
 for (var j=0;j<=iparentlen;j++){
  s+="\n<tr><td>"+j+"<td>"+Substs[j]+"<td>"+Smiles[j]+"<td>"+Links[j]
 }
 return s+"</table></center>"
 
}


function gettoken(dochopoperator) //next token in sformula; sthisop is next operator
{ 
 //if (testing) alert ("getting token for " + sformula)
 sthisop=""
 var isexp=0
 var stoken=""
 havenum=0
 if (sformula.length==0) return ""
 var sch=sformula.charAt(0)
 havenum=(numerals.indexOf(sch)>0?1:0)
//# 780
 var i=0
 while (i<sformula.length)
 {
  sch=sformula.charAt(i)
  if (operators.indexOf(sch)>0)  
  {
   sthisop=sch
   if (i>0){stoken=sformula.substring(0,i)}
   sformula=sformula.substring(i+dochopoperator,sformula.length)
//# 790
   if (testing) alert ("token: " + stoken + "   " + sthisop + "   " + sformula)
   return stoken
  }
//# 810
  i++
 }
 stoken=sformula
 sformula=""
 if (testing) alert (stoken + " " + sthisop + " " + sformula)
 return stoken      
}


function ptokenof()// get next parenthetical expression in sformula
{
 if (sformula.length==0){return ""}
 var spnew=""
 var ipt=0
 if (sformula.charAt(ipt)!="("){return ""}
 ipt=findparen(sformula,ipt,1)
 spnew=sformula.substring(1,ipt)
 sformula=sformula.substring(ipt+1,sformula.length)      
 return spnew
} 

function findparen(s,ipt0,idirect) //returns ptr to ")" or "("
{
 var ipt=ipt0
 var schar=(idirect==1?"(":")")
 var i=(s.charAt(ipt)==schar?0:idirect)
 while (ipt<s.length && ipt>=0) 
//# 760
 {
  if (s.charAt(ipt)=="("){i=i+1}
  if (s.charAt(ipt)==")"){i=i-1}
  if (i==0) {return ipt}
  ipt=ipt+idirect
 }
 return ipt  //-1 or s.length on failure to close
}

function strclean(sclean) 
{
 //tabs and commas to space and leading spaces removed
 var s=sclean
 s=strsub(s,"\n","")
 s=strsub(s,"\r","")
//# 240
 s=strsub(s,"\f","")
 s=strsub(s,"\t","")
 s=strsub(s,"\q","")
 s=strsub(s,"  "," ")
 return s
}

function strsub(ssub,ch1,ch2)
{
 if(ch2!=""){if(ch2.indexOf(ch1)>=0) return ssub}
 var s=ssub
 var i=s.indexOf(ch1)
 while (i>=0)
 {
  s=s.substring(0,i)+ch2+s.substring(i+ch1.length,s.length)
  i=s.indexOf(ch1)
 }
 return s
}

function strchop(s,swhat){ //chops off swhat
 return((s.indexOf(swhat)==0?s.substring(swhat.length,s.length):s))
} 

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 alert2(s1,s2){alert(s1+"\n"+s2)}


/*

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


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
schain="" /* (1,2)(1,3) etc */


function createstructure(){
  initialize()
  clen=Math.floor(Math.random()*(MAXLEN-MINLEN)+MINLEN)+1
  getchain(clen)
  sname=Name[clen]+"ane"
  var slist=""
  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)
   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 first-different number."
  }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 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 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){
 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(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){
 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
}



