Sunday, 11 August 2013

expandable unit conversion

expandable unit conversion

I'm writing a package to assist typesetting documents for some special Pen
& Paper Fantasy RPG.
In this fantasy setting, there are three types of coins: gold, silver and
copper pieces, which convert 10:1 each. However, many groups play with a
different conversion factor (100:1). Because I want to make things as
flexible as possible, I define a command '\gold' that will just take the
number of copper pieces and convert into the appropriate pricing string.
However, as an additional gimmick, I want to support writing out the data
of all purchasable items into an external file (using '\addcontentsline')
which can then be re-read to produce a table with all the pricing
information collected in one spot. Here is my solution:
\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\def\makedatalines#1{
\AtEndDocument{
\clearpage
\if@filesw
\expandafter\newwrite\csname tf@#1.data\endcsname
\immediate\openout\expandafter\csname tf@#1.data\endcsname%
\jobname.#1.data\relax
\fi
}
}
\def\adddataline#1#2{\expandafter\addtocontents{#1.data}{#2}}
\newcommand{\copperpiecesAlias}{CP}
\newcommand{\silverpiecesAlias}{SP}
\newcommand{\goldpiecesAlias}{GP}
\numgdef{\CopperPerSilver}{10}
\numgdef{\SilverPerGold }{10}
\newcommand {\setCopperPerSilver}[1]{\numgdef{\CopperPerSilver}{#1}}
\newcommand {\setSilverPerGold}[1]{\numgdef{\SilverPerGold}{#1}}
\newcommand{\gold}[1]{%
\numdef{\copperpieces}{#1}%
\ifnumless{\copperpieces}{\CopperPerSilver}{%
\numdef{\silverpieces}{0}%
}{%
\numdef{\silverpieces}{(10*\copperpieces/\CopperPerSilver - 5)/10}%
\numdef{\copperpieces}{\copperpieces - (\CopperPerSilver *
\silverpieces)}%
}%
\ifnumless{\silverpieces}{\SilverPerGold}{%
\numdef{\goldpieces}{0}%
}{%
\numdef{\goldpieces}{(10*\silverpieces /\SilverPerGold - 5)/10}%
\numdef{\silverpieces}{\silverpieces - (\SilverPerGold * \goldpieces)}%
}%
\ifnumgreater{\goldpieces }{0}{%
\goldpieces\,\goldpiecesAlias%
\ifnumgreater{\silverpieces}{0}{ }{%
\ifnumgreater{\copperpieces}{0}{ }{}%
}%
}{}%
\ifnumgreater{\silverpieces}{0}{%
\silverpieces\,\silverpiecesAlias%
\ifnumgreater{\copperpieces}{0}{ }{}%
}{}%
\ifnumgreater{\copperpieces}{0}{%
\copperpieces\,\copperpiecesAlias%
}{}%
}
\makedatalines{prices}
\newcommand\purchasable[2]{\textit{#1} (#2)\adddataline{prices}{#1: #2}}
\makeatother
\begin{document}
\purchasable{Longsword} {\gold{1000}}
\purchasable{Broadsword} {\gold{500}}
\purchasable{Magic Staff} {\gold{50000}}
\purchasable{Loaf of Bread}{\gold{5}}
\purchasable{Chicken} {\gold{10}-\gold{50}}
\end{document}
The conversion works nicely - however: the external file now contains
lines like
Longsword: \numdef {0}{1000}\numdef {0}{0}\numdef {10}{0}10\,GP
Broadsword: \numdef {0}{500}\numdef {0}{0}\numdef {5}{0}5\,GP
Magic Staff: \numdef {0}{50000}\numdef {0}{0}\numdef {500}{0}500\,GP
Loaf of Bread: \numdef {5}{5}\numdef {0}{0}\numdef {0}{0}5\,CP
Chicken: \numdef {0}{10}\numdef {5}{0}\numdef {0}{0}5\,SP-\numdef
{0}{50}\numdef {5}{0}\numdef {0}{0}5\,SP
which is clearly not what I was hoping for (please note especially how
messed-up the last line is - these are not even the correct numbers). I
would need to external file to contain lines like
Longsword: 10\,GP
Broadsword: 5\,GP
Magic Staff: 500\,GP
Loaf of Bread: 5\,CP
Chicken: 1\,SP-5\,SP
After a bit of research, I concluded that the problem is that the '\gold'
command is not fully expandable. Can anybody help me write a fully
expandable variant of the '\gold', or else help me to achieve what I want
by other means and enlighten my quest to write this package? Also, I would
be very greatful for a more compact and elegant way to write the
'\gold'-function, which looks quite bloated to me.

No comments:

Post a Comment