Sebastian Walz 860d31cee1
Tohu vaBohu
2023-04-21 00:22:52 +02:00

662 lines
22 KiB
Lua

substances
= {
counter = 0,
list = { },
extension = "subs",
noNumber = false,
}
local function texOrPDFstring ( label, texString, pdfString )
local output
= "\\relax"
.. "\\texorpdfstring{"
.. "\\hyperref[substance:" .. label .. "]"
.. "{" .. texString .. "}}"
.. "{" .. pdfString .. "}"
log.debug( "texOrPDFstring", output)
return output
end
local function getMass ( input, identifier )
if not input
then
log.warn
(
"getMass",
"Substance »" .. identifier .. "« does not have a mass."
)
end
local mass = tostring ( input or "???" )
if type ( input ) == "table"
then
mass = ""
for index, weight in pairs ( input )
do
mass = mass .. "+" .. weight .. "·" .. index
end
mass = "(" .. mass:sub(2) .. ")"
end
return "\\Physical[2]{" .. mass .. "}{}{gram}{}\\Unit{mol}{-1}"
end
local function getNumberCode ( substance )
if substances.noNumber
then
log.error("getNumberCode", "This will print a number for »"..substance.identifier.."«")
end
if substance.code.texString ~= ""
then
return "\\textbf{" .. tostring ( substance.number ) .. "};~" .. substance.code.texString,
tostring ( substance.number ) .. "; " .. substance.code.pdfString
else
return "\\textbf{" .. tostring ( substance.number ) .. "}",
tostring ( substance.number )
end
end
local function sortByDefault ( this, that )
local this = substances.list [ this ]
local that = substances.list [ that ]
if this.sortedBy ~= that.sortedBy
then
return this.sortedBy < that.sortedBy
else
return this.identifier < that.identifier
end
end
local function sortByNumber ( this, that )
local this = substances.list [ this ]
local that = substances.list [ that ]
return ( this.number or this.oldNumber or -1 ) < ( that.number or that.oldNumber or -1 )
end
function substances.declare ( identifier, object )
if type ( identifier ) == "string"
and type ( object ) == "table"
then
local name = { }
local acronym = object.acronym
if acronym
then
local entry = acronyms.getEntry ( acronym )
if entry
then
-- log.debug
-- (
-- "substances.declare",
-- "got: »" .. tostring ( entry.long [ 1 ] ) .. "«"
-- )
name
= {
texString
= acronyms.getLink
(
acronym,
entry.long [ 1 ]
),
pdfString = entry.long [ 2 ],
}
else
log.fatal
(
{ "substances", "declare", },
"cannot find acronym with identifier -»" .. acronym .. "«!"
)
end
else
local texString, pdfString = chem.compounds.parse ( object.name or "" )
name
= {
texString = texString,
pdfString = pdfString,
}
end
local texString, pdfString, sortBy = chem.parseSimple ( object.simple or "" )
local simple
= {
texString = texString,
pdfString = pdfString,
}
local code = object.code
if code
then
local texString, pdfString, sorty = chem.parseSimple ( code or "" )
code
= {
texString = texString,
pdfString = pdfString,
}
sortBy = sorty
else
if object.acronym
then
local entry = acronyms.getEntry ( object.acronym, true )
if entry
then
code
= {
texString = entry.short [ 1 ],
pdfString = entry.short [ 2 ],
}
sortBy = entry.sortedBy
end
else
code = simple
end
end
local structure = object.structure or { }
if type ( structure ) == "table"
then
structure
= {
figPart = tostring ( structure.figPart or "" ),
movPart = tostring ( structure.movPart or "" ),
}
else
structure
= {
figPart = tostring ( structure ),
movPart = "",
}
end
-- log.debug
-- (
-- "substances.declare",
-- "name: »" .. name.texString .. "« | »" .. name.pdfString .. "«",
-- "code: »" .. code.texString .. "« | »" .. code.pdfString .. "«",
-- "simple: »" .. simple.texString .. "« | »" .. simple.pdfString .. "«",
-- "structure: »" .. structure.figPart .. "« | »" .. structure.movPart .. "«",
-- "mass: »" .. tostring ( object.mass or "???" ) .. "«"
-- )
log.debug
(
"substances.declare",
"Sort by: »" .. sortBy .. "«"
)
substances.list [ identifier ]
= {
identifier = identifier,
name = name,
code = code,
simple = simple,
structure = structure,
mass = object.mass,
sortedBy = sortBy,
oldNumber = tonumber ( substances.list [ identifier ] ),
}
else
log.fatal
(
{ "substances", "declare", },
"Invalid Input Types: string for identifier and table for object expected"
)
end
end
function substances.getAs ( identifier, texString, pdfString )
local substance, identifier = substances.use ( "getAs", identifier, false, false )
log.info
(
"substance.getAs",
"identifier: »"..identifier.."«",
"tex: »"..texString.."«",
"pdf: »"..pdfString.."«"
)
return texOrPDFstring
(
identifier,
texString,
pdfString
)
end
function substances.getCode ( identifier )
local substance, identifier = substances.use ( "getCode", identifier, false, false )
--log.info("substance.getCode", "pdf: »"..substance.simple.pdfString.."«")
return texOrPDFstring
(
identifier,
substance.code.texString,
substance.code.pdfString
)
end
function substances.getCodeID ( identifier )
local substance, identifier = substances.use ( "getCodeID", identifier, false, true )
return texOrPDFstring
(
identifier,
substance.code.texString .. " (\\textbf{" .. tostring ( substance.number ) .. "})",
substance.code.pdfString .. " (" .. tostring ( substance.number ) .. ")"
)
end
function substances.getFull ( identifier )
local substance, identifier = substances.use ( "getFull", identifier, true, true )
local texCode, pdfCode = getNumberCode ( substance )
return texOrPDFstring
(
identifier,
substance.name.texString .. " (" .. texCode .. ")",
substance.name.pdfString .. " (" .. pdfCode .. ")"
)
end
function substances.getLabel ( identifier )
local substance, identifier = substances.use ( "getLabel", identifier, false, false )
return "\\label{substance:" .. identifier .. "}"
end
function substances.getList ( byNumber )
local identifiers = { }
for identifier, entry in pairs ( substances.list )
do
table.insert ( identifiers, identifier )
end
local config = "l@{\\quad}X"
if byNumber
then
table.sort ( identifiers, sortByNumber )
config = "c@{\\quad}" .. config
else
table.sort ( identifiers, sortByDefault )
end
local output = ""
for index, identifier in ipairs ( identifiers )
do
local entry = substances.list [ identifier ]
if entry.number
or entry.oldNumber
then
if byNumber
then
output
= output .. "\\textbf{" .. tostring ( entry.oldNumber ) .. "} & " .. entry.code.texString .. " & " .. entry.name.texString .. "\\\\"
else
output
= output .. entry.code.texString .. " & " .. entry.name.texString .. "\\\\"
end
end
end
local header = "Kürzel & Name \\\\"
if byNumber
then
header = "\\# & "..header
end
result = "\\begin{longtabu}{" .. config .. "}"
.. output
.. "\\end{longtabu}"
.. "\\addtocounter{table}{-1}"
log.warn("substance", "Result: "..result)
return result
end
function substances.getMass ( identifier, monomer )
local substance, identifier = substances.use ( "getMass", identifier, true, false )
if monomer
and monomer ~= ""
then
if substance.mass
and type ( substance.mass ) == "table"
then
return getMass ( substance.mass [ monomer ], identifier )
else
log.error
(
"substances.getMass",
"Substance does not have a monomere with index »" .. monomer .. "«"
)
return getMass ( "¿¿" .. monomer .. "??", identifier )
end
else
return getMass ( substance.mass, identifier )
end
end
function substances.getMolecule ( identifier )
local substance, identifier = substances.use ( "getMolecule", identifier, false, false )
if substance.structure.movPart ~= ""
then
return "\\relax"
.. "\\chemfig{" .. substance.structure.figPart .. "}"
.. "\\chemmove{" .. substance.structure.movPart .. "}"
else
return "\\relax"
.. "\\chemfig{" .. substance.structure.figPart .. "}"
end
end
function substances.getMoleculeWithCode ( identifier )
local substance, identifier = substances.use ( "getMoleculeWithCode", identifier, false, false )
local text
= "\\relax"
.. "\\chemname{\\chemfig{"
.. substance.structure.figPart
.. "}}{\\tiny"
.. ( ( substance.code or { texString = "?????" } ).texString or "???" )
.. "}"
if substance.structure.movPart ~= ""
then
return text .. "\\chemmove{" .. substance.structure.movPart .. "}"
else
return text
end
end
function substances.getMoleculeWithMass ( identifier )
local substance, identifier = substances.use ( "getMoleculeWithMass", identifier, false, false )
local text
= "\\relax"
.. "\\chemname{\\chemfig{"
.. substance.structure.figPart
.. "}}{\\tiny"
.. getMass ( substance.mass, identifier )
.. "}"
if substance.structure.movPart ~= ""
then
return text .. "\\chemmove{" .. substance.structure.movPart .. "}"
else
return text
end
end
function substances.getMoleculeWithNumber ( identifier )
local substance, identifier = substances.use ( "getMoleculeWithNumber", identifier, false, false )
local text
= "\\relax"
.. "\\chemname{\\chemfig{"
.. substance.structure.figPart
.. "}}{\\tiny"
.. "\\textbf{"..tostring(substance.number).."}"
.. "}"
log.info("substances.getMoleculeWithNumber", text)
if substance.structure.movPart ~= ""
then
return text .. "\\chemmove{" .. substance.structure.movPart .. "}"
else
return text
end
end
function substances.getMoleculeWithNumberYield ( identifier, yield )
local substance, identifier = substances.use ( "getMoleculeWithNumberYield", identifier, false, false )
local text
= "\\relax"
.. "\\chemname{\\chemfig{"
.. substance.structure.figPart
.. "}}{\\tiny"
.. "\\textbf{"..tostring(substance.number)..", \\Physical{"..yield.."}{}{percent}{}}"
.. "}"
if substance.structure.movPart ~= ""
then
return text .. "\\chemmove{" .. substance.structure.movPart .. "}"
else
return text
end
end
function substances.getMoleculeWithNumberCode ( identifier )
local substance, identifier = substances.use ( "getMoleculeWithNumberCode", identifier, false, false )
local texCode, pdfCode = getNumberCode ( substance )
local text
= "\\relax"
.. "\\chemname{\\chemfig{"
.. substance.structure.figPart
.. "}}{\\tiny"
.. texCode
.. "}"
if substance.structure.movPart ~= ""
then
return text .. "\\chemmove{" .. substance.structure.movPart .. "}"
else
return text
end
end
function substances.getName ( identifier )
local substance, identifier = substances.use ( "getName", identifier, true, false )
return texOrPDFstring
(
identifier,
substance.name.texString,
substance.name.pdfString
)
end
function substances.getNumber ( identifier )
local substance, identifier = substances.use ( "getNumber", identifier, false, true )
if substances.noNumber
then
log.error("substance.getNumber", "This will print a number for »"..substance.identifier.."«")
end
return texOrPDFstring
(
identifier,
"\\textbf{" .. tostring ( substance.number ) .. "}",
tostring ( substance.number )
)
end
function substances.getSimple ( identifier )
local substance, identifier = substances.use ( "getSimple", identifier, false, false )
return texOrPDFstring
(
identifier,
substance.simple.texString,
substance.simple.pdfString
)
end
function substances.getWithID ( identifier )
local substance, identifier = substances.use ( "getWithCode", identifier, true, true )
if substances.noNumber
then
log.error("substance.getWithID", "This will print a number for »"..substance.identifier.."«")
end
return texOrPDFstring
(
identifier,
substance.name.texString .. " (\\textbf{" .. tostring ( substance.number ) .. "})",
substance.name.pdfString .. " (\\textbf{" .. tostring ( substance.number ) .. "})"
)
end
function substances.getWithCode ( identifier )
local substance, identifier = substances.use ( "getWithCode", identifier, false, true )
--log.info("substance.getCode", "pdf: »"..substance.simple.pdfString.."«")
if substances.noNumber
then
log.error("substance.getWithCode", "This will print a number for »"..substance.identifier.."«")
end
return texOrPDFstring
(
identifier,
"\\textbf{" .. tostring ( substance.number ) .. "} (" .. substance.simple.texString .. ")",
tostring ( substance.number ) .. " (" .. substance.simple.pdfString .. ")"
)
end
function substances.init ( )
local file = buildFiles.open ( substances.extension )
if file
then
local counter = 0
for identifier in file:lines ( )
do
if identifier ~= ""
then
counter = counter + 1
substances.list [ identifier ] = substances.list [ identifier ] or counter
end
end
file:close ( )
end
end
function substances.load ( path )
loadLuaFile ( path )
end
function substances.printAs ( identifier, texString, pdfString )
tex.print ( substances.getAs ( identifier, texString, pdfString ) )
end
function substances.printCode ( identifier )
tex.print ( substances.getCode ( identifier ) )
end
function substances.printCodeID ( identifier )
tex.print ( substances.getCodeID ( identifier ) )
end
function substances.printFull ( identifier )
tex.print ( substances.getFull ( identifier ) )
end
function substances.printLabel ( identifier )
tex.print ( substances.getLabel ( identifier ) )
end
function substances.printList ( byNumber )
tex.print ( substances.getList ( byNumber ) )
end
function substances.printMass ( identifier, monomer )
tex.print ( substances.getMass ( identifier, monomer ) )
end
function substances.printMolecule ( identifier )
tex.print ( substances.getMolecule ( identifier ) )
end
function substances.printMoleculeWithCode ( identifier )
tex.print ( substances.getMolecule ( identifier ) )
end
function substances.printMoleculeWithMass ( identifier )
tex.print ( substances.getMoleculeWithMass ( identifier ) )
end
function substances.printMoleculeWithNumberCode ( identifier )
tex.print ( substances.getMoleculeWithNumberCode ( identifier ) )
end
function substances.printMoleculeWithNumber ( identifier )
tex.print ( substances.getMoleculeWithNumber ( identifier ) )
end
function substances.printMoleculeWithNumberYield ( identifier, yield )
tex.print ( substances.getMoleculeWithNumberYield ( identifier, yield ) )
end
function substances.printName ( identifier )
tex.print ( substances.getName ( identifier ) )
end
function substances.printNumber ( identifier )
tex.print ( substances.getNumber ( identifier ) )
end
function substances.printSimple ( identifier )
tex.print ( substances.getSimple ( identifier ) )
end
function substances.printWithCode ( identifier )
tex.print ( substances.getWithCode ( identifier ) )
end
function substances.printWithID ( identifier )
tex.print ( substances.getWithID ( identifier ) )
end
function substances.save ( )
local identifiers = { }
for identifier, entry in pairs ( substances.list )
do
table.insert ( identifiers, identifier )
end
table.sort ( identifiers, sortByNumber )
local file = buildFiles.create ( substances.extension )
if file
then
for index, identifier in ipairs ( identifiers )
do
if substances.list [ identifier ].number
then
file:write ( identifier .. "\n" )
end
end
file:close ( )
else
log.error
(
"substances.save",
"Could not save Substances!",
"Listing substances might result in unexpected output."
)
end
end
function substances.useIt ( identifier)
local substance, identifier = substances.use ( "useIt", identifier, true, true )
end
function substances.use ( source, identifier, withName, withNumber )
local entry = substances.list [ identifier ]
if entry
then
--log.info({ source, "useSubstance", }, "Use Subtance with Identifier »" .. identifier .. "«")
if entry.number == nil
then
substances.counter = substances.counter + 1
entry.number = substances.counter
end
entry.nameUsed = entry.nameUsed or withName
entry.numberUsed = entry.numberUsed or withNumber
if not entry.nameUsed
then
log.warn
(
{ source, "useSubstance", },
"Substance was used, but not the Name.",
"Consider to use \\substanceFull{"..identifier.."}"
.." to tell the reader the Name of the substance before refering to it"
)
end
if not entry.numberUsed
and not noNumber
then
log.warn
(
{ source, "useSubstance", },
"Substance was used, but not the Number.",
"Consider to use \\substanceFull{"..identifier.."}"
.." to tell the reader the Name of the substance before refering to it"
)
end
else
log.fatal
(
{ source, "useSubstance", },
"Unknown Substance with Identifier »" .. identifier .. "«"
)
end
return entry, tostring ( identifier )
end
substances.init ( )