Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Combustion: Difference between revisions

From Stationeers Community Wiki
RA2lover (talk | contribs)
mNo edit summary
RA2lover (talk | contribs)
Evaporate liquid hypergols on combustion enthalpy calculation
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
local GasData = mw.loadData("Module:Gas/data")
local GasData = mw.loadData("Module:Gas/data")
local CombustionData = mw.loadData("Module:Combustion/data")
local Gas = require("Module:Gas")
local Gas = require("Module:Gas")


local function GetRepresentation(gas, frame)
local function GetRepresentation(gas, frame)
     mw.log("GetRepresentation called. gas:")
     --mw.log("GetRepresentation called. gas:")
     mw.logObject(gas)
     --mw.logObject(gas)
     mw.log("Frame: ")
     --mw.log("Frame: ")
     mw.logObject(frame)
     --mw.logObject(frame)
     return frame:expandTemplate({title = "GasIcon", args = {gas.Name} }) -- Embeds a Not-yet-implemented template.
     return frame:expandTemplate({title = "GasIcon", args = {gas.Name} }) -- Embeds a Not-yet-implemented template.
end
end
Line 12: Line 13:
local p={}
local p={}
local function RenderCombustionTemplate(frame, Fuel, Oxidizer, Reagents)
local function RenderCombustionTemplate(frame, Fuel, Oxidizer, Reagents)
    mw.log("RenderCombustionTemplate called. Fuel:")
    mw.logObject(Fuel)
    mw.log("Oxidizer:")
    mw.logObject(Oxidizer)
    mw.log("Reagents:")
    mw.logObject(Reagents)
     --TODO: Add actual formatting into a box or something.
     --TODO: Add actual formatting into a box or something.
     local InputReagents = {}
     local InputReagents = {}
Line 49: Line 57:


function p.GetCombustionEnergy(Fuel, Oxidizer)
function p.GetCombustionEnergy(Fuel, Oxidizer)
     if Fuel.Gas.IsHypergol then return Fuel.Gas.Enthalpy*Fuel.Amount end
     if Fuel.Gas.IsHypergol then
    local LatentHeat
    if Fuel.Gas.State=="Liquid" then LatentHeat = Fuel.Gas.LatentHeat else LatentHeat = 0 end
    return (Fuel.Gas.Enthalpy-Fuel.Gas.LatentHeat)*Fuel.Amount
    end
 
     if not Oxidizer or not Oxidizer.Gas then Oxidizer = {Gas = Gas.GetGas("Oxygen"), Amount = 1} end
     if not Oxidizer or not Oxidizer.Gas then Oxidizer = {Gas = Gas.GetGas("Oxygen"), Amount = 1} end
      
      
Line 70: Line 83:
     local gas, amount, remainder = string.match(str, "^[,;:-]?%s*([%a%s]+)%s*[,;:-]?%s*(%d+)(.*)$")
     local gas, amount, remainder = string.match(str, "^[,;:-]?%s*([%a%s]+)%s*[,;:-]?%s*(%d+)(.*)$")
     --"-Liquid Sodium Chloride , 2; Hydrochloric Acid = 1" should result in "Liquid Sodium Chloride", 2, "; Hydrochloric Acid = 1"
     --"-Liquid Sodium Chloride , 2; Hydrochloric Acid = 1" should result in "Liquid Sodium Chloride", 2, "; Hydrochloric Acid = 1"
     if not gas then return nil end
     if not gas then
     mw.log("Gas parsed:")
        local match = string.match(str,"^[,;:-]?%s*([%a%s]+)%s*[,;:-]?.*")
     mw.logObject(gas)
        if match then return Gas.GetGas(match) else return nil end
     mw.log("Amount parsed:")
     end
     mw.logObject(amount)
    --mw.log("Gas parsed:")
     mw.log("Remainder:")
     --mw.logObject(gas)
     mw.logObject(remainder)
     --mw.log("Amount parsed:")
     --mw.logObject(amount)
     --mw.log("Remainder:")
     --mw.logObject(remainder)
     return Gas.GetGas(gas), amount, remainder
     return Gas.GetGas(gas), amount, remainder
end
end
Line 85: Line 101:
     if not frame.args.Fuel then error("Missing 'Fuel' parameter") end
     if not frame.args.Fuel then error("Missing 'Fuel' parameter") end
     local fuel, fuelAmount = ParseInput(frame.args.Fuel)
     local fuel, fuelAmount = ParseInput(frame.args.Fuel)
     if not fuelAmount then error("Missing quantity for 'Fuel' parameter") end
     --if not fuelAmount then error("Missing quantity for 'Fuel' parameter") end


     local oxidizer, oxidizerAmount
     local oxidizer, oxidizerAmount
     if not fuel.IsHypergol then
     if not fuel.IsHypergol then
         if not frame.args.Oxidizer then error("Missing 'Oxidizer' parameter") end
         if not frame.args.Oxidizer then error("Missing 'Oxidizer' parameter") end
         local oxidizer, oxidizerAmount = ParseInput(frame.args.Oxidizer)
         oxidizer, oxidizerAmount = ParseInput(frame.args.Oxidizer)
     end
     end
      
      
Line 100: Line 116:
             outputsCount = outputsCount + 1
             outputsCount = outputsCount + 1
             local output, outputAmount = ParseInput(v)
             local output, outputAmount = ParseInput(v)
             if not outputAmount then error ("Missing quantity for '"..k.."' parameter") end
             --if not outputAmount then error ("Missing quantity for '"..k.."' parameter") end
             outputs[outputsCount] = {Gas = output, Amount = outputAmount}
             outputs[outputsCount] = {Gas = output, Amount = outputAmount}
         end
         end
     end
     end
    -- Attempt to autofill inputs from combustion data table if they're absent
    mw.log ("FuelName: "..fuel.Name)
    if not oxidizer and not fuelAmount then fuelAmount = CombustionData[fuel.Name].FuelAmount end
    if oxidizer and not fuelAmount then fuelAmount = CombustionData[fuel.Name][oxidizer.Name].FuelAmount end
    if oxidizer and not oxidizerAmount then oxidizerAmount = CombustionData[fuel.Name][oxidizer.Name].OxidizerAmount end
   
   
    if outputsCount == 0 and not frame.args.DontAutofillOutputs then
        if not oxidizer then outputs = CombustionData[fuel.Name].Outputs end
        if oxidizer then outputs = CombustionData[fuel.Name][oxidizer.Name].Outputs end
    end
     return RenderCombustionTemplate(frame, {Gas = fuel, Amount = fuelAmount}, {Gas = oxidizer, Amount = oxidizerAmount}, outputs)
     return RenderCombustionTemplate(frame, {Gas = fuel, Amount = fuelAmount}, {Gas = oxidizer, Amount = oxidizerAmount}, outputs)
end
end


return p
return p

Latest revision as of 23:57, 18 March 2026

Documentation for this module may be created at Module:Combustion/doc

local GasData = mw.loadData("Module:Gas/data")
local CombustionData = mw.loadData("Module:Combustion/data")
local Gas = require("Module:Gas")

local function GetRepresentation(gas, frame)
    --mw.log("GetRepresentation called. gas:")
    --mw.logObject(gas)
    --mw.log("Frame: ")
    --mw.logObject(frame)
    return frame:expandTemplate({title = "GasIcon", args = {gas.Name} }) -- Embeds a Not-yet-implemented template.
end

local p={}
local function RenderCombustionTemplate(frame, Fuel, Oxidizer, Reagents)
    mw.log("RenderCombustionTemplate called. Fuel:")
    mw.logObject(Fuel)
    mw.log("Oxidizer:")
    mw.logObject(Oxidizer)
    mw.log("Reagents:")
    mw.logObject(Reagents)

    --TODO: Add actual formatting into a box or something.
    local InputReagents = {}
   
    local FuelRepresentation = GetRepresentation(Fuel.Gas, frame)
    table.insert (InputReagents, Fuel.Amount.."x "..FuelRepresentation)
    if Oxidizer and Oxidizer.Gas then
        local OxidizerRepresentation = GetRepresentation(Oxidizer.Gas, frame)
        table.insert (InputReagents, Oxidizer.Amount.."x "..OxidizerRepresentation)
    end
   
    local OutputReagents = {}
    for n=1,#Reagents do
        local ReagentRepresentation = GetRepresentation(Reagents[n].Gas, frame)
        table.insert(OutputReagents, Reagents[n].Amount.."x "..ReagentRepresentation)
    end    

    local Autoignition=""
    if frame.args.ShowAutoignition then
        local T = 0

        if Fuel.Gas.IsHypergol then
             T = Fuel.Gas.AutoignitionTemperature
        else T = Fuel.Gas.AutoignitionTemperature + Oxidizer.Gas.AutoignitionOffset end

        Autoignition = " (Autoignites at "..frame:expandTemplate({title="Temperature", args={T}})..")"
    end
    return table.concat(InputReagents, " + ").." = "..table.concat(OutputReagents, " + ")..p.FormattedCombustionEnergy(Fuel, Oxidizer)..Autoignition
end

function p.FormattedCombustionEnergy(...)
    local Energy = p.GetCombustionEnergy(...)
    if Energy==0 then return "" end
    if Energy<0 then return " - ".. -Energy/1000 .." kJ" end
    if Energy>0 then return " + ".. Energy/1000 .." kJ" end
end

function p.GetCombustionEnergy(Fuel, Oxidizer)
    if Fuel.Gas.IsHypergol then
    local LatentHeat
    if Fuel.Gas.State=="Liquid" then LatentHeat = Fuel.Gas.LatentHeat else LatentHeat = 0 end
    return (Fuel.Gas.Enthalpy-Fuel.Gas.LatentHeat)*Fuel.Amount
    end

    if not Oxidizer or not Oxidizer.Gas then Oxidizer = {Gas = Gas.GetGas("Oxygen"), Amount = 1} end
    
    local TotalEnthalpy = Fuel.Gas.Enthalpy * Fuel.Amount * Oxidizer.Gas.EnthalpyMultiplier

    if Fuel.Gas.State == "Liquid" then --vaporize liquid fuels
        TotalEnthalpy = TotalEnthalpy - (Fuel.Gas.LatentHeat * Fuel.Amount)
    end

    if Oxidizer.Gas.State == "Liquid" then --vaporize liquid oxidizers
        TotalEnthalpy = TotalEnthalpy - (Oxidizer.Gas.LatentHeat * Oxidizer.Amount)
    end

    return TotalEnthalpy

end

local function ParseInput(str)
    mw.log("ParseInput called on "..str) 
    local gas, amount, remainder = string.match(str, "^[,;:-]?%s*([%a%s]+)%s*[,;:-]?%s*(%d+)(.*)$")
    --"-Liquid Sodium Chloride , 2; Hydrochloric Acid = 1" should result in "Liquid Sodium Chloride", 2, "; Hydrochloric Acid = 1"
    if not gas then
        local match = string.match(str,"^[,;:-]?%s*([%a%s]+)%s*[,;:-]?.*")
        if match then return Gas.GetGas(match) else return nil end
    end
    --mw.log("Gas parsed:")
    --mw.logObject(gas)
    --mw.log("Amount parsed:")
    --mw.logObject(amount)
    --mw.log("Remainder:")
    --mw.logObject(remainder)
    return Gas.GetGas(gas), amount, remainder
end

function p.Template(frame)
    frame = frame:getParent(frame)

    if not frame.args.Fuel then error("Missing 'Fuel' parameter") end
    local fuel, fuelAmount = ParseInput(frame.args.Fuel)
    --if not fuelAmount then error("Missing quantity for 'Fuel' parameter") end

    local oxidizer, oxidizerAmount
    if not fuel.IsHypergol then
        if not frame.args.Oxidizer then error("Missing 'Oxidizer' parameter") end
        oxidizer, oxidizerAmount = ParseInput(frame.args.Oxidizer)
    end
    
    
    local outputs = {}
    local outputsCount = 0
    for k,v in pairs(frame.args) do
        if string.match(k, "^Output") then
            outputsCount = outputsCount + 1
            local output, outputAmount = ParseInput(v)
            --if not outputAmount then error ("Missing quantity for '"..k.."' parameter") end
            outputs[outputsCount] = {Gas = output, Amount = outputAmount}
        end
    end

    -- Attempt to autofill inputs from combustion data table if they're absent
    mw.log ("FuelName: "..fuel.Name)

    if not oxidizer and not fuelAmount then fuelAmount = CombustionData[fuel.Name].FuelAmount end
    if oxidizer and not fuelAmount then fuelAmount = CombustionData[fuel.Name][oxidizer.Name].FuelAmount end
    if oxidizer and not oxidizerAmount then oxidizerAmount = CombustionData[fuel.Name][oxidizer.Name].OxidizerAmount end
 
    if outputsCount == 0 and not frame.args.DontAutofillOutputs then 
        if not oxidizer then outputs = CombustionData[fuel.Name].Outputs end
        if oxidizer then outputs = CombustionData[fuel.Name][oxidizer.Name].Outputs end
    end

    return RenderCombustionTemplate(frame, {Gas = fuel, Amount = fuelAmount}, {Gas = oxidizer, Amount = oxidizerAmount}, outputs)
end

return p