chem.Struct.Atom.prototype.calcValence = function()

in gsoc2022/seagrid-rich-client/molview/src/js/chem/chem/struct_valence.js [49:369]


chem.Struct.Atom.prototype.calcValence = function (conn)
{
	var atom = this;
	var charge = atom.charge;
	var label = atom.label;
	if(atom.isQuery())
	{
		this.implicitH = 0;
		return true;
	}
	var elem = chem.Element.getElementByLabel(label);
	if(elem == null)
	{
		this.implicitH = 0;
		return true;
	}

	var groupno = chem.Element.elements.get(elem).group;
	var rad = chem.Struct.radicalElectrons(atom.radical);

	var valence = conn;
	var hyd = 0;
	var absCharge = Math.abs(charge);

	if(groupno == 1)
	{
		if(label == 'H' ||
			label == 'Li' || label == 'Na' || label == 'K' ||
			label == 'Rb' || label == 'Cs' || label == 'Fr')
		{
			valence = 1;
			hyd = 1 - rad - conn - absCharge;
		}
	}
	else if(groupno == 3)
	{
		if(label == 'B' || label == 'Al' || label == 'Ga' || label == 'In')
		{
			if(charge == -1)
			{
				valence = 4;
				hyd = 4 - rad - conn;
			}
			else
			{
				valence = 3;
				hyd = 3 - rad - conn - absCharge;
			}
		}
		else if(label == 'Tl')
		{
			if(charge == -1)
			{
				if(rad + conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else
				{
					valence = 4;
					hyd = 4 - rad - conn;
				}
			}
			else if(charge == -2)
			{
				if(rad + conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn;
				}
			}
			else
			{
				if(rad + conn + absCharge <= 1)
				{
					valence = 1;
					hyd = 1 - rad - conn - absCharge;
				}
				else
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
			}
		}
	}
	else if(groupno == 4)
	{
		if(label == 'C' || label == 'Si' || label == 'Ge')
		{
			valence = 4;
			hyd = 4 - rad - conn - absCharge;
		}
		else if(label == 'Sn' || label == 'Pb')
		{
			if(conn + rad + absCharge <= 2)
			{
				valence = 2;
				hyd = 2 - rad - conn - absCharge;
			}
			else
			{
				valence = 4;
				hyd = 4 - rad - conn - absCharge;
			}
		}
	}
	else if(groupno == 5)
	{
		if(label == 'N' || label == 'P')
		{
			if(charge == 1)
			{
				valence = 4;
				hyd = 4 - rad - conn;
			}
			else if(charge == 2)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				if(label == 'N' || rad + conn + absCharge <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
				else // ELEM_P && rad + conn + absCharge > 3
				{
					valence = 5;
					hyd = 5 - rad - conn - absCharge;
				}
			}
		}
		else if(label == 'Bi' || label == 'Sb' || label == 'As')
		{
			if(charge == 1)
			{
				if(rad + conn <= 2 && label != 'As')
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else
				{
					valence = 4;
					hyd = 4 - rad - conn;
				}
			}
			else if(charge == 2)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				if(rad + conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn - absCharge;
				}
			}
		}
	}
	else if(groupno == 6)
	{
		if(label == 'O')
		{
			if(charge >= 1)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				valence = 2;
				hyd = 2 - rad - conn - absCharge;
			}
		}
		else if(label == 'S' || label == 'Se' || label == 'Po')
		{
			if(charge == 1)
			{
				if(conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn;
				}
			}
			else
			{
				if(conn + rad + absCharge <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
				else if(conn + rad + absCharge <= 4)
				// See examples in PubChem
				// [S] : CID 16684216
				// [Se]: CID 5242252
				// [Po]: no example, just following ISIS/Draw logic here
				{
					valence = 4;
					hyd = 4 - rad - conn - absCharge;
				}
				else
				// See examples in PubChem
				// [S] : CID 46937044
				// [Se]: CID 59786
				// [Po]: no example, just following ISIS/Draw logic here
				{
					valence = 6;
					hyd = 6 - rad - conn - absCharge;
				}
			}
		}
		else if(label == 'Te')
		{
			if(charge == -1)
			{
				if(conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
			}
			else if(charge == 0 || charge == 2)
			{
				if(conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
				else if(conn <= 4)
				{
					valence = 4;
					hyd = 4 - rad - conn - absCharge;
				}
				else if(charge == 0 && conn <= 6)
				{
					valence = 6;
					hyd = 6 - rad - conn - absCharge;
				}
				else
					hyd = -1;
			}
		}
	}
	else if(groupno == 7)
	{
		if(label == 'F')
		{
			valence = 1;
			hyd = 1 - rad - conn - absCharge;
		}
		else if(label == 'Cl' || label == 'Br' ||
			label == 'I' || label == 'At')
		{
			if(charge == 1)
			{
				if(conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else if(conn == 3 || conn == 5 || conn >= 7)
					hyd = -1;
			}
			else if(charge == 0)
			{
				if(conn <= 1)
				{
					valence = 1;
					hyd = 1 - rad - conn;
				}
				// While the halogens can have valence 3, they can not have
				// hydrogens in that case.
				else if(conn == 2 || conn == 4 || conn == 6)
				{
					if(rad == 1)
					{
						valence = conn;
						hyd = 0;
					}
					else
						hyd = -1; // will throw an error in the end
				}
				else if(conn > 7)
					hyd = -1; // will throw an error in the end
			}
		}
	}

	this.valence = valence;
	this.implicitH = hyd;
	if(this.implicitH < 0)
	{
		this.valence = conn;
		this.implicitH = 0;
		this.badConn = true;
		return false;
	}
	return true;
};