123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- --- Code related to LaTeX generation.
- -- @module advtrains_doc_integration.latex
- local latex = {}
- local utils = advtrains_doc_integration.utils
- --- Escape string in LaTeX.
- -- @tparam string str The string to escape.
- -- @treturn string The escaped string.
- function latex.escape(str)
- return (string.gsub(str, ".", {
- ["&"] = [[\&]],
- ["%"] = [[\%]],
- ["$"] = [[\$]],
- ["#"] = [[\#]],
- ["_"] = [[\_]],
- ["{"] = [[\{]],
- ["}"] = [[\}]],
- ["~"] = [[\textasciitilde]],
- ["^"] = [[\textasciicircum]],
- ["\\"] = [[\textbackslash]],
- }))
- end
- --- Escape a translated string in LaTeX.
- -- @tparam string lang The language to use for server-side translation
- -- @tparam string str The string to escape.
- -- @treturn The escaped string.
- function latex.escape_translated(lang, str)
- return latex.escape(minetest.get_translated_string(lang, str))
- end
- local function SL(str)
- return latex.escape_translated("en", str)
- end
- --- Describe a color in LaTeX.
- -- @tparam string cstr The color string.
- -- @treturn string The string describing the color.
- function latex.describe_color(cstr)
- local color = string.match(cstr,"^#(%x%x%x%x%x%x)$")
- cstr = SL(cstr)
- if color then
- color = SL(string.upper(color))
- return string.format([[\tikz \definecolor{c}{HTML}{%s} \draw[fill=c] (0,0) rectangle (1em,1em); \texttt{%s}]], color, cstr)
- else
- return string.format([[\texttt{%s}]], cstr)
- end
- end
- --- Describe a coupler in LaTeX.
- -- @tparam string coupler The name of the coupler.
- -- @treturn string The string describing the coupler.
- function latex.describe_coupler(coupler)
- local name = utils.get_coupler_name(coupler)
- if name then
- return ([[%s (\texttt{%s})]]):format(SL(name), SL(coupler))
- else
- return ([[\texttt{%s}]]):format(SL(coupler))
- end
- end
- --- Describe a wagon prototype in LaTeX.
- -- @tparam string itemname The item name of the wagon prototype.
- -- @treturn string The description of the prototype.
- function latex.describe_wagon_prototype(itemname)
- local prototype = advtrains_doc_integration.prototypes[itemname]
- local wname = ItemStack(itemname):get_short_description()
- local st = {string.format([[
- \documentclass{article}
- \usepackage[a4paper,margin=1in,bottom=1.5in]{geometry}
- \usepackage[T1]{fontenc}
- \usepackage{tikz}
- \usepackage{booktabs,multirow,tabularx}
- \renewcommand{\arraystretch}{1.5}
- \usepackage{hyperref}
- \hypersetup{pdftitle={Wagon Datasheet: %s}}
- \title{Wagon Datasheet}
- \author{%s}
- \setlength{\parindent}{0pt}
- \begin{document}
- \maketitle
- ]], SL(wname), SL(wname))}
- table.insert(st, [[\section{Basic Information}]])
- if prototype.longdesc then
- table.insert(st, SL(prototype.longdesc) .. "\n")
- end
- table.insert(st, [[\begin{tabularx}{\textwidth}{l X}]])
- table.insert(st, string.format([[Itemstring & \texttt{%s}\\]], SL(itemname)))
- if prototype.drives_on then
- local i0 = #st+1
- local count = 0
- for k in pairs(prototype.drives_on) do
- table.insert(st, string.format([[& \texttt{%s}\\]], SL(k)))
- count = count + 1
- end
- if count > 0 then
- st[i0] = string.format([[Drives on %s]], st[i0])
- end
- end
- if prototype.wagon_span then
- table.insert(st, string.format([[Wagon span & %d mm\\]], prototype.wagon_span*2000))
- end
- if prototype.max_speed then
- table.insert(st, string.format([[Maximum speed & %d m/s\\]], prototype.max_speed))
- end
- table.insert(st, string.format([[Motive power & %s\\]], prototype.is_locomotive and "Present" or "Absent"))
- if prototype.horn_sound then
- table.insert(st, string.format([[Horn sound & \texttt{%s}\\]], SL(prototype.horn_sound.name)))
- else
- table.insert(st, [[Horn sound & Undefined\\]])
- end
- if prototype.mesh then
- table.insert(st, string.format([[Mesh & \texttt{%s}\\]], SL(prototype.mesh)))
- end
- if prototype.textures then
- local i0 = #st+1
- local count = 0
- for _, i in pairs(prototype.textures) do
- table.insert(st, string.format([[& \texttt{%s}\\]], SL(i)))
- count = count + 1
- end
- if count > 0 then
- st[i0] = string.format([[Textures %s]], st[i0])
- end
- end
- do
- local i0 = #st+1
- local count = 0
- for _, i in ipairs(prototype.drops or {}) do
- local item = ItemStack(i)
- if not item:is_empty() then
- local desc = string.format([[\texttt{%s}]], SL(item:get_name()))
- if item:is_known() then
- desc = SL(item:get_short_description())
- end
- table.insert(st, string.format([[& %s: %d\\]], desc, item:get_count()))
- count = count + 1
- end
- end
- if count > 0 then
- st[i0] = [[Drops ]] .. st[i0]
- else
- table.insert(st, [[Drops & Nothing \\]])
- end
- end
- table.insert(st, [[\end{tabularx}]])
- table.insert(st, [[\section{Coupler Compatibility}]])
- do
- local fcouplers = prototype.coupler_types_front
- local rcouplers = prototype.coupler_types_back
- local ccouplers = {}
- local lcouplers = {}
- local couplerid = {}
- local flim, rlim
- for k in pairs(fcouplers or {}) do
- flim = true
- ccouplers[k] = true
- end
- for k in pairs(rcouplers or {}) do
- rlim = true
- ccouplers[k] = true
- end
- for k in pairs(ccouplers) do
- local desc = latex.describe_coupler(k)
- table.insert(lcouplers, desc)
- couplerid[desc] = k
- end
- table.sort(lcouplers)
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c c}
- \toprule
- \multirow[t]{2}{*}{\bfseries Coupler Type} & \multicolumn{2}{c}{\bfseries Compatibility}\\
- \cmidrule(lr){2-3}
- & {\bfseries Front Coupler} & {\bfseries Rear Coupler}\\\midrule
- ]])
- if not (fcouplers and rcouplers) then
- local fd = fcouplers and "" or [[$\bullet$]]
- local rd = rcouplers and "" or [[$\bullet$]]
- table.insert(st, string.format([[\textit{Universal}&%s&%s\\]], fd, rd))
- end
- for i = 1, #lcouplers do
- local cdesc = lcouplers[i]
- local cid = couplerid[cdesc]
- local fd, rd = "", ""
- if flim then
- fd = fcouplers[cid] and [[$\bullet$]] or ""
- elseif not fcouplers then
- fd = [[$\Uparrow$]]
- end
- if rlim then
- rd = rcouplers[cid] and [[$\bullet$]] or ""
- elseif not rcouplers then
- rd = [[$\Uparrow$]]
- end
- table.insert(st, string.format([[%s&%s&%s\\]], cdesc, fd, rd))
- end
- table.insert(st, [[\bottomrule]])
- table.insert(st, [[\end{tabularx}]])
- end
- local hasinv = prototype.has_inventory
- local hasseats = prototype.max_seats>0
- local taliquid = prototype.techage_liquid_capacity or 0
- if hasinv or hasseats or taliquid>0 then
- table.insert(st, [[\section{Wagon Capacity}]])
- if hasseats then
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c c}
- \toprule
- {\bfseries Seat Group} & {\bfseries Driver Stand} & {\bfseries Seat Count}\\\midrule
- ]])
- for _, d in pairs(prototype.seat_groups) do
- table.insert(st, string.format([[%s & %s & %d\\]], SL(d.name), d.driving_ctrl_access and [[$\bullet$]] or "", d.count))
- end
- table.insert(st, [[\bottomrule]])
- table.insert(st, [[\end{tabularx}]])
- end
- if hasinv then
- if next(prototype.inventory_list_sizes or {}) ~= nil then
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c}
- \toprule
- {\bfseries Inventory Name} & {\bfseries Capacity}\\\midrule
- ]])
- for k, v in pairs(prototype.inventory_list_sizes) do
- table.insert(st, string.format([[\texttt{%s} & %d\\]], SL(k), v))
- end
- table.insert(st, [[\bottomrule]])
- table.insert(st, [[\end{tabularx}]])
- else
- table.insert(st, [[This wagon has an inventory of unknown size.]])
- end
- end
- if taliquid > 0 then
- table.insert(st, string.format([[
- \begin{tabularx}{\textwidth}{X l}
- {Liquid Capacity (Techage)} & %d
- \end{tabularx}
- ]], taliquid))
- end
- end
- if prototype.set_livery then
- if prototype.livery_definition then
- table.insert(st, [[\section{Multi-Component Liveries}]])
- local components = prototype.livery_definition.components
- local presets = prototype.livery_definition.presets
- table.insert(st, [[\subsection*{Components}]])
- table.insert(st, [[\begin{itemize}]])
- for _, c in ipairs(components) do
- table.insert(st, string.format([[\item %s]], SL(c.description)))
- end
- table.insert(st, [[\end{itemize}]])
- for _, p in ipairs(presets) do
- table.insert(st, string.format([[\subsection*{Preset: %s}]], SL(p.description)))
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c}
- \toprule
- {\bfseries Component} & {\bfseries Color} \\\midrule
- ]])
- for _, c in ipairs(p.livery_stack.layers) do
- local cdesc = SL(components[c.component].description)
- table.insert(st, string.format([[%s & %s\\]], cdesc, latex.describe_color(c.color)))
- end
- table.insert(st, [[
- \bottomrule
- \end{tabularx}
- ]])
- end
- else
- table.insert(st, [[\section{Livery System (Bike Painter)}]])
- table.insert(st, [[This wagon can be painted by the bike painter.]])
- end
- end
- local dlxlivdef = prototype.dlxtrains_livery
- if dlxlivdef then
- table.insert(st, [[
- \section{DlxTrains Livery Sytem}
- This wagon can be customized with DlxTrains' livery system.
- ]])
- end
- local atlivdef = prototype.advtrains_livery_tools
- if atlivdef then
- table.insert(st, [[\section{Advtrains Livery Tool (Marnack)}]])
- for _, tname in ipairs(atlivdef.template_names) do
- local tdef = atlivdef.templates[tname]
- table.insert(st, string.format([[\subsection*{Template: %s}]], SL(tname)))
- table.insert(st, SL(tdef.notes))
- table.insert(st, "")
- if #tdef.overlays > 0 then
- table.insert(st, "This template contains the following components:")
- table.insert(st, [[\begin{itemize}]])
- for _, overlay in ipairs(tdef.overlays) do
- table.insert(st, string.format([[\item %s]], SL(overlay.name)))
- end
- table.insert(st, [[\end{itemize}]])
- else
- table.insert(st, "This template does not appear to contain any (customizable) component.")
- end
- end
- for _, lname in ipairs(atlivdef.livery_names) do
- local ldef = atlivdef.liveries[lname]
- local tname = ldef.livery_template_name
- table.insert(st, string.format([[\subsection*{Preset: %s}]], SL(lname)))
- table.insert(st, string.format([[Template: %s]], SL(tname)))
- table.insert(st, "")
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c}
- \toprule
- {\bfseries Component} & {\bfseries Color}\\\midrule]])
- for _, overlay in pairs(ldef.overlays) do
- local cname = atlivdef.templates[tname].overlays[overlay.id].name
- table.insert(st, string.format([[%s & %s\\]], SL(cname), latex.describe_color(overlay.color)))
- end
- table.insert(st, [[
- \bottomrule
- \end{tabularx}
- ]])
- end
- end
- table.insert(st, [[
- \end{document}
- ]])
- return table.concat(st, "\n")
- end
- return latex
|