-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathscript.js
105 lines (94 loc) · 4.74 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// https://esr.phy.bme.hu/~tif/molecular_weight_calculator.html
const formFormula = document.getElementById('formula')
const formDigits = document.getElementById('digits')
const calculateButton = document.getElementById('calculateButton')
const results = document.getElementById('results')
const examples = document.getElementById('examples')
calculateButton.addEventListener('click', function () {
results.value = showResults(formFormula.value, formDigits.value) + '\n' + results.value
})
examples.addEventListener('input', function () {
formFormula.value = examples.value
})
// Atomic mass per element
atom = { H: 1.00794, He: 4.0026, Li: 6.941, Be: 9.01218, B: 10.811, C: 12.011, N: 14.0067, O: 15.9994, F: 18.9984, Ne: 20.1797, Na: 22.98977, Mg: 24.305, Al: 26.98154, Si: 28.0855, P: 30.97376, S: 32.066, Cl: 35.4527, Ar: 39.948, K: 39.0983, Ca: 40.078, Sc: 44.9559, Ti: 47.88, V: 50.9415, Cr: 51.996, Mn: 54.938, Fe: 55.847, Co: 58.9332, Ni: 58.6934, Cu: 63.546, Zn: 65.39, Ga: 69.723, Ge: 72.61, As: 74.9216, Se: 78.96, Br: 79.904, Kr: 83.8, Rb: 85.4678, Sr: 87.62, Y: 88.9059, Zr: 91.224, Nb: 92.9064, Mo: 95.94, Tc: 98, Ru: 101.07, Rh: 102.9055, Pd: 106.42, Ag: 107.868, Cd: 112.41, In: 114.82, Sn: 118.71, Sb: 121.757, Te: 127.6, I: 126.9045, Xe: 131.29, Cs: 132.9054, Ba: 137.33, La: 138.9055, Hf: 178.49, Ta: 180.9479, W: 183.85, Re: 186.207, Os: 190.2, Ir: 192.22, Pt: 195.08, Au: 196.9665, Hg: 200.59, Tl: 204.383, Pb: 207.2, Bi: 208.9804, Po: 209, At: 210, Rn: 222, Fr: 223, Ra: 226.0254, Ac: 227, Rf: 261, Db: 262, Sg: 263, Bh: 262, Hs: 265, Mt: 266, Uun: 269, Uuu: 272, Uub: 277, Ce: 140.12, Pr: 140.9077, Nd: 144.24, Pm: 145, Sm: 150.36, Eu: 151.965, Gd: 157.25, Tb: 158.9253, Dy: 162.5, Ho: 164.9303, Er: 167.26, Tm: 168.9342, Yb: 173.04, Lu: 174.967, Th: 232.0381, Pa: 231.0359, U: 238.029, Np: 237.0482, Pu: 244, Am: 243, Cm: 247, Bk: 247, Cf: 251, Es: 252, Fm: 257, Md: 258, No: 259, Lr: 262 }
function addMolecules(molecA, molecB, molecBqty) {
for (let [elem, atoms] of Object.entries(molecB)) {
molecA[elem] ? molecA[elem] += molecBqty * atoms : molecA[elem] = molecBqty * atoms
}
return molecA
}
function chemEval(formula) {
const element = /[A-Z][a-z]{0,2}/
const numberAfterElement = /\d+$/
let molec = {}
chemArray = formula.match(/[A-Z][a-z]*\d*/g)
chemArray.forEach(x => {
ele = x.match(element)[0]
elemNumMatch = x.match(numberAfterElement)
elemNumMatch ? atoms = parseInt(elemNumMatch[0]) : atoms = 1
elem = {}
elem[ele] = atoms
molec = addMolecules(molec, elem, 1)
})
return molec
}
function calculateMolecule(formula) {
// Creates an object with properties of the molecule specified by the chemical formula
const elementAndNumber = /[A-Z][a-z]{0,2}\d*/
const element = /[A-Z][a-z]{0,2}/
const numberAfterElement = /\d+$/
const simpleFormula = /^([A-Z][a-z]{0,2}\d*)+/
const validFormula = /([A-Z][a-z]{0,2}\d*)+|\(|\)\d*|\.\d*([A-Z][a-z]{0,2}\d*)+/g
const formulaAfterDot = /\.\d*([A-Z][a-z]{0,2}\d*)+/
const closingParenthesis = /^\)\d*$/
const openingParenthesis = /^\($/
const chemArray = formula.match(validFormula)//splits string into valid values
let ele = ""
let elmass = [{}]
let level = 0
let atoms = 0
let parenNum = 0
let multiplier = 0
let total = 0
let numMatch = null
formula = formula.replace(/\s/g, '');
chemArray.forEach(x => {
if (simpleFormula.test(x)) {
elmass[level] = addMolecules(elmass[level], chemEval(x), 1)
}
else if (openingParenthesis.test(x)) {
elmass[++level] = {}
}
else if (closingParenthesis.test(x)) {
numMatch = x.match(/\d+$/)
numMatch ? multiplier = parseInt(numMatch[0]) : multiplier = 1
elmass[level - 1] = addMolecules(elmass[level - 1], elmass[level], multiplier)
elmass[level--] = null
}
else if (formulaAfterDot.test(x)) {
numMatch = x.match(/\.(\d+)[A-Z]/)
numMatch ? multiplier = parseInt(numMatch[1]) : multiplier = 1
elmass[level] = addMolecules(elmass[level], chemEval(x), multiplier)
}
})
for ([ele, atoms] of Object.entries(elmass[0])) {
total += atom[ele] * atoms
}
return { elements: elmass[0], totalMass: total, formula: chemArray.join('') }
}
function showResults(formula, digits) {
const molecule = calculateMolecule(formula)
const elements = molecule.elements
const usedFormula = molecule.formula
const total = molecule.totalMass
const fix = (x) => x.toFixed(digits)
let allResults = usedFormula + "\n" + "-".repeat(60) + '\n';
for (let [ele, atoms] of Object.entries(elements)) {
eltotal = atoms * atom[ele]
allResults += `${atoms} ${ele} * ${fix(atom[ele])} = ${fix(eltotal)} (${fix(eltotal / total * 100)}% of mass)` + "\n";
}
allResults += "=".repeat(60) + '\n'
allResults += `Total: ${fix(total)} g/mol`+"\n";
return allResults
}