Clazz.declarePackage("JS");
Clazz.load(null, "JS.SmilesAromatic", ["java.util.Hashtable", "JU.BS", "$.Lst", "$.Measure", "$.V3", "JS.SmilesRing", "$.SmilesRingSet", "JU.BSUtil", "$.Logger"], function(){
var c$ = Clazz.declareType(JS, "SmilesAromatic", null);
c$.setAromatic = Clazz.defineMethod(c$, "setAromatic", 
function(n, jmolAtoms, bsSelected, vR, bsAromatic, strictness, isOpenSMILES, justCheckBonding, checkExplicit, v, vOK, lstSP2, eCounts, doTestAromatic){
var doCheck = (isOpenSMILES || strictness > 0);
if (!doTestAromatic) {
for (var r = vR.size(); --r >= 0; ) {
var bs = JU.BSUtil.copy(vR.get(r));
bs.and(bsAromatic);
if (bs.cardinality() == n) vOK.addLast(bs);
}
return;
}for (var r = vR.size(); --r >= 0; ) {
var bs = vR.get(r);
var isOK = JS.SmilesAromatic.isSp2Ring(n, jmolAtoms, bsSelected, bs, (justCheckBonding ? 3.4028235E38 : 0.1), checkExplicit, strictness == 0);
if (!isOK) continue;
bsAromatic.or(bs);
if (doCheck) {
var edges =  new JU.Lst();
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
var a = jmolAtoms[i];
var aedges = a.getEdges();
var ai = a.getIndex();
for (var j = aedges.length; --j >= 0; ) {
var a2 = aedges[j].getOtherNode(a);
var a2i = a2.getIndex();
if (a2i > ai && bs.get(a2i)) edges.addLast(aedges[j]);
}
}
switch (JS.SmilesAromatic.checkHueckelAromatic(n, jmolAtoms, bsAromatic, bs, strictness, eCounts)) {
case -1:
continue;
case 0:
isOK = false;
case 1:
if (lstSP2 != null) lstSP2.addLast( new JS.SmilesRing(n, bs, edges, isOK));
if (!isOK) continue;
}
}vOK.addLast(bs);
}
}, "~N,~A,JU.BS,JU.Lst,JU.BS,~N,~B,~B,~B,JS.VTemp,JU.Lst,JU.Lst,~A,~B");
c$.checkAromaticDefined = Clazz.defineMethod(c$, "checkAromaticDefined", 
function(jmolAtoms, bsSelected, bsAromatic){
for (var i = bsSelected.nextSetBit(0); i >= 0; i = bsSelected.nextSetBit(i + 1)) {
var bonds = jmolAtoms[i].getEdges();
for (var j = 0; j < bonds.length; j++) {
switch (bonds[j].getBondType()) {
case 515:
case 514:
case 513:
bsAromatic.set(bonds[j].getAtomIndex1());
bsAromatic.set(bonds[j].getAtomIndex2());
}
}
}
}, "~A,JU.BS,JU.BS");
c$.isSp2Ring = Clazz.defineMethod(c$, "isSp2Ring", 
function(n, atoms, bsSelected, bs, cutoff, checkExplicit, allowSOxide){
if (checkExplicit) {
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) if (atoms[i].getCovalentBondCount() > 3) return false;

} else {
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) if (atoms[i].getCovalentBondCountPlusMissingH() > 3) return false;

}if (cutoff == 3.4028235E38) return true;
if (cutoff <= 0) cutoff = 0.01;
var vNorm = null;
var vTemp = null;
var vMean = null;
var nPoints = bs.cardinality();
var vNorms =  new Array(nPoints * 2);
var nNorms = 0;
var maxDev = (1 - cutoff * 5);
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
var ringAtom = atoms[i];
var bonds = ringAtom.getEdges();
var iSub = -1;
var r1 = -1;
var r2 = -1;
for (var k = bonds.length; --k >= 0; ) {
var iAtom = ringAtom.getBondedAtomIndex(k);
if (!bsSelected.get(iAtom)) continue;
if (!bs.get(iAtom)) {
if (ringAtom.getElementNumber() == 16) {
if (!allowSOxide) return false;
iAtom = -1;
}iSub = iAtom;
} else if (r1 < 0) {
r1 = iAtom;
} else {
r2 = iAtom;
}}
if (vMean == null) {
vMean =  new JU.V3();
vNorm =  new JU.V3();
vTemp =  new JU.V3();
}for (var k = 0, j = i; k < 2; k++) {
JU.Measure.getNormalThroughPoints(atoms[r1], atoms[j], atoms[r2], vNorm, vTemp);
if (!JS.SmilesAromatic.addNormal(vNorm, vMean, maxDev)) return false;
vNorms[nNorms++] = JU.V3.newV(vNorm);
if ((j = iSub) < 0) break;
}
}
return JS.SmilesAromatic.checkStandardDeviation(vNorms, vMean, nNorms, cutoff);
}, "~N,~A,JU.BS,JU.BS,~N,~B,~B");
c$.addNormal = Clazz.defineMethod(c$, "addNormal", 
function(vTemp, vMean, maxDev){
var similarity = vMean.dot(vTemp);
if (similarity != 0 && Math.abs(similarity) < maxDev) return false;
if (similarity < 0) vTemp.scale(-1);
vMean.add(vTemp);
vMean.normalize();
return true;
}, "JU.V3,JU.V3,~N");
c$.checkStandardDeviation = Clazz.defineMethod(c$, "checkStandardDeviation", 
function(vNorms, vMean, n, cutoff){
var sum = 0;
var sum2 = 0;
for (var i = 0; i < n; i++) {
var v = vNorms[i].dot(vMean);
sum += v;
sum2 += (v) * v;
}
sum = Math.sqrt((sum2 - sum * sum / n) / (n - 1));
return (sum < cutoff);
}, "~A,JU.V3,~N,~N");
c$.checkHueckelAromatic = Clazz.defineMethod(c$, "checkHueckelAromatic", 
function(nAtoms, jmolAtoms, bsAromatic, bsRing, strictness, eCounts){
var npi = 0;
var n1 = 0;
for (var i = bsRing.nextSetBit(0); i >= 0 && npi >= 0; i = bsRing.nextSetBit(i + 1)) {
var atom = jmolAtoms[i];
var z = atom.getElementNumber();
var n = atom.getCovalentBondCountPlusMissingH();
n += atom.getValence();
n -= 4;
if (z == 6) {
var fc = atom.getFormalCharge();
if (fc != -2147483648) n += fc;
}var pt = (z >= 5 && z <= 8 ? z - 5 : z == 15 ? 2 : z == 34 ? 3 : z == 33 ? 4 : z == 16 ? 5 : -1);
if (pt >= 0) {
var a = JS.SmilesAromatic.OS_PI_COUNTS[pt];
if (n < 0 || n >= a.length) return -1;
switch (n = a[n]) {
case -2:
return -1;
case -1:
var bonds = atom.getEdges();
n = 0;
for (var j = bonds.length; --j >= 0; ) {
var b = bonds[j];
if (b.getCovalentOrder() != 2) continue;
var het = b.getOtherNode(atom);
n = (het.getElementNumber() == 6 || bsAromatic.get(het.getIndex()) ? 1 : strictness > 0 ? -100 : 0);
break;
}
default:
if (n < 0) return -1;
if (eCounts != null) eCounts[i] = n;
npi += n;
if (n == 1) n1++;
if (JU.Logger.debuggingHigh) JU.Logger.info("atom " + atom + " pi=" + n + " npi=" + npi);
continue;
}
}}
return ((npi - 2) % 4 == 0 && (strictness < 2 || nAtoms == 5 || n1 == 6) ? 1 : 0);
}, "~N,~A,JU.BS,JU.BS,~N,~A");
c$.finalizeAromatic = Clazz.defineMethod(c$, "finalizeAromatic", 
function(jmolAtoms, bsAromatic, lstAromatic, lstSP2, eCounts, isOpenNotStrict, isStrict){
if (isStrict) JS.SmilesAromatic.removeBridgingRings(lstAromatic, lstSP2);
JS.SmilesAromatic.checkFusedRings(lstSP2, eCounts, lstAromatic);
bsAromatic.clearAll();
for (var i = lstAromatic.size(); --i >= 0; ) bsAromatic.or(lstAromatic.get(i));

if (isStrict || isOpenNotStrict) {
for (var i = bsAromatic.nextSetBit(0); i >= 0; i = bsAromatic.nextSetBit(i + 1)) {
var bonds = jmolAtoms[i].getEdges();
var naro = 0;
for (var j = bonds.length; --j >= 0; ) {
var otherAtom = bonds[j].getOtherNode(jmolAtoms[i]);
var order = bonds[j].getCovalentOrder();
var ai2 = otherAtom.getIndex();
var isJAro = bsAromatic.get(ai2);
if (isJAro) {
if (order == 2) {
var isOK = false;
for (var k = lstSP2.size(); --k >= 0; ) {
var r = lstSP2.get(k);
if (r.get(i) && r.get(ai2)) {
isOK = true;
break;
}}
if (!isOK) {
naro = -1;
break;
}}naro++;
} else if (isStrict && otherAtom.getElementNumber() == 6 && order == 2) {
naro = -1;
break;
}}
if (naro < 2) {
bsAromatic.clear(i);
i = -1;
}}
}}, "~A,JU.BS,JU.Lst,JU.Lst,~A,~B,~B");
c$.removeBridgingRings = Clazz.defineMethod(c$, "removeBridgingRings", 
function(lstAromatic, lstSP2){
var bs =  new JU.BS();
var bsBad =  new JU.BS();
var bsBad2 =  new JU.BS();
JS.SmilesAromatic.checkBridges(lstAromatic, bsBad, lstAromatic, bsBad, bs);
JS.SmilesAromatic.checkBridges(lstSP2, bsBad2, lstSP2, bsBad2, bs);
JS.SmilesAromatic.checkBridges(lstAromatic, bsBad, lstSP2, bsBad2, bs);
for (var i = lstAromatic.size(); --i >= 0; ) if (bsBad.get(i)) lstAromatic.removeItemAt(i);

for (var i = lstSP2.size(); --i >= 0; ) if (bsBad2.get(i)) lstSP2.removeItemAt(i);

}, "JU.Lst,JU.Lst");
c$.checkBridges = Clazz.defineMethod(c$, "checkBridges", 
function(lst, bsBad, lst2, bsBad2, bs){
var isSameList = (lst === lst2);
for (var i = lst.size(); --i >= 0; ) {
var bs1 = lst.get(i);
for (var j0 = (isSameList ? i + 1 : 0), j = lst2.size(); --j >= j0; ) {
var bs2 = lst2.get(j);
if (bs2.equals(bs1)) continue;
bs.clearAll();
bs.or(bs1);
bs.and(bs2);
var n = bs.cardinality();
if (n > 2) {
bsBad.set(i);
bsBad2.set(j);
}}
}
}, "JU.Lst,JU.BS,JU.Lst,JU.BS,JU.BS");
c$.checkFusedRings = Clazz.defineMethod(c$, "checkFusedRings", 
function(rings, eCounts, lstAromatic){
var htEdgeMap =  new java.util.Hashtable();
for (var i = rings.size(); --i >= 0; ) {
var r = rings.get(i);
var edges = r.edges;
for (var j = edges.size(); --j >= 0; ) {
var set = JS.SmilesRing.getSetByEdge(edges.get(j), htEdgeMap);
if (set == null || set === r.$set) continue;
if (r.$set != null) set.addSet(r.$set, htEdgeMap);
 else set.addRing(r);
}
(r.$set == null ? r.$set =  new JS.SmilesRingSet() : r.$set).addRing(r);
r.addEdges(htEdgeMap);
}
var set;
var r;
for (var i = rings.size(); --i >= 0; ) {
if ((r = rings.get(i)).isOK || (set = r.$set) == null || set.isEmpty()) continue;
if ((set.getElectronCount(eCounts) % 4) == 2) for (var j = set.size(); --j >= 0; ) if (!(r = set.get(j)).isOK) lstAromatic.addLast(r);

set.clear();
}
}, "JU.Lst,~A,JU.Lst");
c$.OS_PI_COUNTS =  Clazz.newArray(-1, [ Clazz.newIntArray(-1, [-2, 1, 0]),  Clazz.newIntArray(-1, [1, 2, 1, -1]),  Clazz.newIntArray(-1, [2, 1, 2, 1, 1]),  Clazz.newIntArray(-1, [2, 1]),  Clazz.newIntArray(-1, [-2, 1, 2, 1, -2]),  Clazz.newIntArray(-1, [2, 1, 2, 2])]);
});
;//5.0.1-v7 Wed Jun 03 09:22:38 CDT 2026
