From cd285a2c4c890c978956731413233e6cd60ceca9 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Thu, 8 May 2014 12:08:01 -0400 Subject: [PATCH] Extrated a number of rater-general specification logic from dwelling --- raterspec.cls | 126 +++++++++++++++ raterspec/c1import.sty | 32 ++++ raterspec/class.sty | 355 +++++++++++++++++++++++++++++++++++++++++ raterspec/form.sty | 53 ++++++ raterspec/isoclass.sty | 26 +++ raterspec/isoterr.sty | 16 ++ raterspec/param.sty | 269 +++++++++++++++++++++++++++++++ raterspec/question.sty | 62 +++++++ raterspec/rates.sty | 44 +++++ 9 files changed, 983 insertions(+) create mode 100644 raterspec.cls create mode 100644 raterspec/c1import.sty create mode 100644 raterspec/class.sty create mode 100644 raterspec/form.sty create mode 100644 raterspec/isoclass.sty create mode 100644 raterspec/isoterr.sty create mode 100644 raterspec/param.sty create mode 100644 raterspec/question.sty create mode 100644 raterspec/rates.sty diff --git a/raterspec.cls b/raterspec.cls new file mode 100644 index 0000000..31292c2 --- /dev/null +++ b/raterspec.cls @@ -0,0 +1,126 @@ +% LoVullo rater specification class +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec} +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{lvspec}} +\ProcessOptions\relax + +% we're an extension of the base lvspec +\LoadClass[insuranceterms]{lvspec} + +%% +% Default package includes +% +% Note that these are not all the packages that are available; see the +% raterspec/ directory in the lvspec repo +% +\RequirePackage{raterspec/param} +\RequirePackage{raterspec/class} +\RequirePackage{raterspec/question} +\RequirePackage{raterspec/rates} +\RequirePackage{raterspec/form} +\RequirePackage{raterspec/c1import} +\RequirePackage{lvflow} +%\RequirePackage{premcalc} + + +%% +% Formatting +% + +% we gots some big section numbers +\renewcommand\l@subsubsection{\@dottedtocline{3}{7em}{4.6em}} + + +%% +% Rater-specific specification additions +% +% This should be called before beginning the documet environment +% +\def\@RaterProgramName#1{ + \gdef\@lvspec@pretitle{% + #1 Supplier\\Specifications:\\ + \vspace{0.5em}% + } + \gdef\@lvspec@premarktitle{#1:\space} + + \abstract{% + This document is a formal specification for the integration of + \@title@short{} with the Dwelling Program of the Quote Server, Program + UI and~ConceptOne. This document should contain all information + necessary to complete a conforming implementation with minimal + clarification and will serve as a reference for future development, + including bug fixes and feature requests. + } +} + +\terminology{% + \subsection{Rater Terminology} + \input{dfn/rater} +} + + + +%% +% Code generation +% +% Right now the code generation is tightly coupled with the packages that it +% is applicable to; they need to be refactored and hooks added +\newwrite\@@codegen +\immediate\openout\@@codegen=gen.xml + +\def\@codegen{% + \begingroup + % prepare common cases for plain-text output + \def\sref##1{the specification}% + \def~{ }% + \def\emph{}% + \def\nobreakspace{ }% + \def\${}% + \@do@codegen +} +\def\@do@codegen#1{% + \immediate\write\@@codegen{#1}% + \endgroup +} + + +%% +% Misc +% + +\def\@firstchar #1#2||{#1} +\def\@secondchar #1#2#3||{#2} +\def\@ifnumeric#1{{% + \edef\@@chk{\@firstchar#1||}% + % determine if this is a number + \def\@@result{0}% + % strip any negative sign + \ifnum\expandafter`\@@chk=`- + \edef\@@chk{\@secondchar#1--||}% + \fi + % perform number check + \ifnum\expandafter`\@@chk<`0\else + \ifnum\expandafter`\@@chk>`9\else + % is a number + \def\@@result{1}% + \fi + \fi + % use the result to output a conditional that will match a closing \fi + \aftergroup\ifnum + \expandafter\aftergroup\@@result + \aftergroup=% + \aftergroup1% + \aftergroup\relax +}} + + +\def\beginundersletter{% + \begingroup% ended by \@dotypedef + \catcode`\_=11\relax +} +\def\endundersletter{% + \endgroup +} + diff --git a/raterspec/c1import.sty b/raterspec/c1import.sty new file mode 100644 index 0000000..24d7c71 --- /dev/null +++ b/raterspec/c1import.sty @@ -0,0 +1,32 @@ +% LoVullo rater specification c1 import +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/c1import} +\ProcessOptions\relax + + +\newenvironment{c1glclass}[1]% + {% + \sigkeep + \def\@@class{#1}% + \let\basis\@coglclass@basis + \let\prem\@coglclass@prem + }% + {% + \par This class \shall only be applicable when each of the following is + true: + \begin{enumerate} + \@cmatch@enable + \matchin{class}{\@@class}% + \end{enumerate} + \sigunkeep + } + +\def\@coglclass@basis#1{% + \par The premium basis \shall be the~\paramrefd{#1}~(\paramref{#1}). +} +\def\@coglclass@prem#1{% + \par The premium and~rate \shall be derived from~\sref{#1}. +} + diff --git a/raterspec/class.sty b/raterspec/class.sty new file mode 100644 index 0000000..91b96e1 --- /dev/null +++ b/raterspec/class.sty @@ -0,0 +1,355 @@ +% LoVullo rater specification classification +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/class} +\ProcessOptions\relax + +% the first argument (optionally) provides a unique id for this classification +% (see further information on this below) +\newenvironment{classification}[1][]% + {% + \def\@cid{#1}% + \leavevmode + \label{@classify:#1}% + % if a classification id was provided, output it in the left margin (this + % allows us to eyeball summaries or common classifications across + % specifications, as well as match it up to the code) + \if\@cid\empty\else + % typeset id + \llap{{\scriptsize\bf\@cid\hskip4ex\relax}}% + \fi% + % enable rule definitions + \@cmatch@enable + % the first paragraph will constitute the description (and will contain a + % signature line) + \@margin@sig\@class@mkdesc\@cid + } + {% + % this is opened by \@class@mkdesc + \@codegen{}% + \end{@classification@rules}% + } + +\newenvironment{@classification@rules} + {% + {\bf Rules:}% + \penalty1000\relax + \begin{enumerate} + } + {% + \end{enumerate} + } + +\def\@match@formal#1{{% + \\\footnotesize{\bf Formally:}% + \space#1% +}} + +\def\@matchany #1 {% + \@codegen{ }% + \item Any one of the following \must be true: + \begin{enumerate} + #1 + \end{enumerate} + \@codegen{ }% +} + +\def\@matchall #1 {% + \@codegen{ }% + \item Each of the following \must be true: + \begin{enumerate} + #1 + \end{enumerate} + \@codegen{ }% +} + +\def\@matchtodo#1{\item\todo{#1}} + +% determine what ref is appropriate +\def\@magicref#1{{% + % param? + \expandafter\let\expandafter\@@chk\csname param@#1\endcsname + \ifx\@@chk\relax + \expandafter\let\expandafter\@@chk\csname classify@#1\endcsname + \ifx\@@chk\relax + % no known custom type (may be a normal ref) + \PackageWarning{dwspec}{unknown magic ref `#1'}% + \else + \classifyref{#1}% + \fi + \else + \paramref{#1}% + \fi +}} + +\def\@cmatcheq{% + \begingroup + \catcode`\_=11\relax + \@docmatcheq +} +\def\@docmatcheq#1#2{% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \must be a(n)\space + % ensure that the constant exists + \@const@exists@err{#2}% + % typeset + \csname const@#2\endcsname. + \@match@formal{\@magicref{#1} $=$ \constref{#2}}% + \endgroup +} + +\def\@cmatchneq{% + \begingroup + \catcode`\_=11\relax + \@docmatchneq +} +\def\@docmatchneq#1#2{% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \mustnot be a(n)\space + % ensure that the constant exists + \@const@exists@err{#2}% + % typeset + \csname const@#2\endcsname. + \@match@formal{\@magicref{#1} $\neq$ \constref{#2}}% + \endgroup +} + +\def\@cmatchlt{% + \begingroup + \catcode`\_=11\relax + \@docmatchlt +} +\def\@docmatchlt#1#2{% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \must be less than\nobreakspace + % ensure that the constant exists + \@const@exists@err{#2}% + % typeset + \@const@desc{#2}.% + \@match@formal{\@magicref{#1} $<$ \constref{#2}}% + \endgroup +} + +\def\@cmatchleq{% + \begingroup + \catcode`\_=11\relax + \@docmatchleq +} +\def\@docmatchleq#1#2{% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \must be less than or equal to% + % ensure that the constant exists + \@const@exists@err{#2}% + % typeset + \nobreakspace\@const@desc{#2}.% + \@match@formal{\@magicref{#1} $\leq$ \constref{#2}}% + \endgroup +} + + +\def\@cmatchgt{% + \begingroup + \catcode`\_=11\relax + \@docmatchgt +} +\def\@docmatchgt#1#2{% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \must be greater than\nobreakspace + % ensure that the constant exists + \@const@exists@err{#2}% + % typeset + \@const@desc{#2}.% + \@match@formal{\@magicref{#1} $>$ \constref{#2}}% + \endgroup +} + + +\def\@cmatchgeq#1#2{% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \must be greater than or equal to\nobreakspace + % ensure that the constant exists + \@const@exists@err{#2}% + % typeset + \@const@desc{#2}.% + \@match@formal{\@magicref{#1} $\geq$ \constref{#2}}% +} + +\def\@cmatchin#1#2{% + \@codegen{ }% + % whatever we are matching on must exist as either a classification or an + % input field (param) + \item\@cmatch@desc@or@fail{#1}% + \space \must be a defined\space + % ensure that the param type exists + \@type@exists@err{#2}% + % output the param type description + \csname ptype@#2\endcsname. + \@match@formal{\@magicref{#1} $\in$ \typeref{#2}}% +} + +\def\@match#1{% + \@codegen{ }% + \item#1.% +} + +\def\@matchtrue#1{% + \@codegen{ }% + \item\@cmatch@desc@or@fail{#1}.% + \@match@formal{\@magicref{#1} $=\top$}% +} +\def\@matchfalse#1{% + \@codegen{ }% + \item It is not true that: \@cmatch@desc@or@fail{#1}.% + \@match@formal{\@magicref{#1} $=\bot$}% +} + +\def\@cmatch@enable{% + % we're being lazy with this cat code so that it applies to all \match + % invocations grouped between this enable cmd and the disable one; this will + % cause problems if we need math mode, so it may need to be revisited in the + % future + \catcode`_=11\relax + \let\matchany\@matchany + \let\matchall\@matchall + \let\matcheq\@cmatcheq + \let\matchneq\@cmatchneq + \let\matchgt\@cmatchgt + \let\matchgeq\@cmatchgeq + \let\matchlt\@cmatchlt + \let\matchleq\@cmatchleq + \let\matchin\@cmatchin + \let\matchtrue\@matchtrue + \let\matchfalse\@matchfalse + \let\matchtodo\@matchtodo + \let\match\@match +} + +\def\@class@mkdesc#1 #2 \par{% + \@codegen{}% + {\bf Description:}\space#2\par + % record this definition + \index{classification!#1@\texttt{#1}}% + \expandafter\gdef\csname classify@#1\endcsname{#2}% + % place definition into aux file; will be available next pass + \protected@write\@auxout{}{% + \string\expandafter\string\gdef + \string\csname\space classify@#1\string\endcsname{#2}% + }% + % immediately following the description are the rules + \begin{@classification@rules} +} + +\def\@class@desc#1{{% + \expandafter\let\expandafter\@@chk\csname classify@#1\endcsname + \ifx\@@chk\relax + \PackageWarning{dwspec}{unknown classification `#1'}% + \else + \@@chk + \fi +}} + +\def\@cmatch@desc@or@fail#1{{% + % grab tokens to check against for param and class definitions + \expandafter\let\expandafter\@@pchk\csname param@#1\endcsname + \expandafter\let\expandafter\@@cchk\csname classify@#1\endcsname + % fail if neither exists + \ifx\@@pchk\relax + \ifx\@@cchk\relax + \PackageWarning{dwspec}{unknown identifier for classification match: #1} + \else + % output + \@@cchk + \fi + \else + % output + \@@pchk + \fi +}} + +\def\classifyref#1{% + \index{classification!#1@\texttt{#1}}% + \hyperref[@classify:#1]{% + \tt#1% + }% +} +\def\classifyrefd#1{% + \index{classification!#1@\texttt{#1}}% + \hyperref[@classify:#1]{% + \csname classify@#1\endcsname + }% +} +\def\classifyrefalt#1#2{% + \index{classification!#1@\texttt{#1}}% + \hyperref[@classify:#1]{#2}% +} + + +\def\assign#1#2{$#1$ $=$ #2}% +\def\loc{\ifmmode\ell\else$\ell$\fi}% +\def\y{yield}% +\def\prem{{\tt premium}}% + +\newcommand\rate[1][]{% + \begingroup + \ifmmode\aftergroup\mathop\fi + \endgroup + {\tt #1rate}% +} + + +\newenvironment{submission}[2]% + {% + \begin{classification}[submit-#1-#2]% + }% + {% + \end{classification} + } + +\def\when#1{% + \Shall be applicable only when each of the following is true:% + \begin{enumerate} + \@cmatch@enable + \scantokens{#1} + \end{enumerate}% +} +\let\When\when + diff --git a/raterspec/form.sty b/raterspec/form.sty new file mode 100644 index 0000000..0a9bc5e --- /dev/null +++ b/raterspec/form.sty @@ -0,0 +1,53 @@ +% LoVullo rater specification forms +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/form} +\ProcessOptions\relax + + +\newenvironment{forms}[2]% + {% + \let\mandatory\@form@mandatory + \sigkeep + Applicable form code(s): \@formfmt#1,||. + \par The form description \shall read: + \begin{quote} + \sf\hskip-0.52em``#2'' + \end{quote} + % TODO: remove once we're using sPxTeX + \pnumon + The form(s) \shall be applicable only when each of the following conditions + is met:% + \begin{enumerate} + \@cmatch@enable + \ignorespaces + }% + {% + \end{enumerate} + \sigunkeep + } + +\def\@form@mandatory{% + \item Form is mandatory and \shall always be applicable.% +} + +\newcount\@formprev +\def\@formfmt#1,#2||{% + \index{forms!codes!#1}% + \def\@@chk{#2}% + \ifnum\@formprev>0\relax + \ifx\@@chk\empty + \space and~% + \else + ,\space + \fi + \fi + {\sf#1}% + % recurse + \ifx\@@chk\empty\else + \advance\@formprev by 1\relax + \@formfmt#2||% + \fi +} + diff --git a/raterspec/isoclass.sty b/raterspec/isoclass.sty new file mode 100644 index 0000000..b0386b9 --- /dev/null +++ b/raterspec/isoclass.sty @@ -0,0 +1,26 @@ +% LoVullo rater specification iso class abstraction +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/isoclass} +\ProcessOptions\relax + + +\def\isoclassdef#1 #2\par{% + \index{ISO!class code!#1|(}% + % indicate that this has been defined (semantic checking) + \expandafter\gdef\csname isoclass@code@#1\endcsname{}% + % typeset and provide hyperlink (intended for a description env) + \item[\hypertarget{@isoclass:#1}{#1}] #2\par% + \index{ISO!class code!#1|)}% +} +\def\isoclassref#1{% + % ensure that the iso class exists + \expandafter\ifx\csname isoclass@code@#1\endcsname\relax% + \errmessage{unknown ISO class code `#1'} + \fi + \index{ISO!class code!#1}% + \hyperlink{@isoclass:#1}{#1}% +} +\let\isoclass\isoclassref + diff --git a/raterspec/isoterr.sty b/raterspec/isoterr.sty new file mode 100644 index 0000000..01fb8c6 --- /dev/null +++ b/raterspec/isoterr.sty @@ -0,0 +1,16 @@ +% LoVullo rater specification iso territory abstraction +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/isoterr} +\ProcessOptions\relax + +% +% N.B. Expects s:isoterr-zips to be a defined reference +% + + +\def\isoterr#1{% + \hyperref[s:isoterr-zips]{ISO Territory #1}% +} + diff --git a/raterspec/param.sty b/raterspec/param.sty new file mode 100644 index 0000000..7065cd4 --- /dev/null +++ b/raterspec/param.sty @@ -0,0 +1,269 @@ +% LoVullo rater specification params +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/param} +\ProcessOptions\relax + + +% special keywords for base param types +\def\@coreptype{core} +\def\@enumptype{enum} +\def\@unionptype{union} + +\def\typedef{% + \begingroup% ended by \@dotypedef + \catcode`\_=11\relax + \@dotypedef +} +\def\@dotypedef#1 #2: #3 \par{% + \goodbreak% + \index{parameter type!#2@\texttt{#2}|(}% + \begingroup% + % given foo, get foo and bar separately + \edef\@root{\@ptype@root#1<||}% + \edef\@type{\@ptype@type#1<#1>||}% + \expandafter\gdef\csname ptype@#2\endcsname{#3}% + % typeset definition with link + \item[% + \hypertarget{@ptype:#2}{#2}% + \ifx\@root\@coreptype\else% + \ $\in\textrm{\rm\@type}$% + \fi% + ]\hfill\\% + \@margin@sig% + % ensure that the parent type actually exists + \ifx\@root\@coreptype\else% + \expandafter\ifx\csname ptype@\@type\endcsname\relax% + \errmessage{unknown parent param type `\@type' for `#2'} + \fi% + \fi% + % process any keywords + \ifx\@root\@enumptype + \aftergroup\@typedef@enum + \else\ifx\@root\@unionptype + \aftergroup\@typedef@union + \fi\fi + \index{parameter type!#2@\texttt{#2}|)}% + #3\par + \endgroup + \endgroup% from \typedef +} + +% given a type foo, returns foo +\def\@ptype@root#1<#2||{#1} +% given a type foo, returns bar +\def\@ptype@type#1<#2>#3||{#2} + +% strips the description and then puts all enums in an aligned environment +\def\@typedef@enum#1\enumv#2\par{% + #1% + \vskip0em\relax + \begingroup + \small + % provide some extra give to prevent this from appearing on its own line + \vspace{0em plus 0.5\parskip}% + \goodbreak + {\bf Defined values:}\\ + \vspace{0.5\parskip}% + \begin{tabular}{lc|l} + % restore the enumv that we gobbled up + \enumv#2 + \end{tabular} + \endgroup +} +\def\enumv[#1]#2#3{% + % define constant + \expandafter\gdef\csname const@#2\endcsname{#1}% + \expandafter\gdef\csname const@value@#2\endcsname{#3}% + % typeset + \index{constant!{\tt#2}}% + {\tt\hypertarget{@const:#2}{#2}} & $#3$ & #1 \\ +} + +% strips the description and then puts all enums in an aligned environment +\def\@typedef@union#1\unionv#2\par{% + #1% + \vskip0em\relax + \begingroup + \small + {\bf Any defined value of:}% + \vspace{-\parskip}% + \begin{itemize} + \setlength{\itemsep}{-\parskip}% + % restore the unionv that we gobbled up + \unionv#2 + \end{itemize} + \endgroup +} +\def\unionv#1{% + % does this type exist? + \expandafter\ifx\csname ptype@#1\endcsname\relax% + \errmessage{unknown param type `#1' for union} + \fi% + \item{\typeref{#1}} +} + +\def\typeref#1{% + \index{parameter type!#1@\texttt{#1}}% + \hyperlink{@ptype:#1}{\tt#1}% +} +\let\type\typeref + +\def\constref #1{% + \@ifnumeric{#1}% + % numeric constants are simply output with no hyperlink + $#1$% + \else + \index{constant!{\tt#1}}\hyperlink{@const:#1}{\tt#1}% + \fi +} +\let\const\constref + +% constant reference, show description +\def\constrefd#1{% + \@ifnumeric{#1}% + % numeric constants are simply output with no hyperlink + $#1$% + \else + \index{constant!{\tt#1}}% + \hyperlink{@const:#1}% + {\csname const@#1\endcsname}% + \fi +} +\def\constrefdd#1{\constrefd{#1}\dotfill} +% constant reference, show value +\def\constrefv#1{% + \@ifnumeric{#1}% + % numeric constants are simply output with no hyperlink + $#1$% + \else + \index{constant!{\tt#1}}% + \hyperlink{@const:#1}% + {\csname const@value@#1\endcsname}% + \fi +} +% link to constant with alternate text +\def\constrefalt#1#2{% + \index{constant!{\tt#1}}% + \hyperlink{@const:#1}{#2}% +} + +\def\@type@exists@err#1{{% + \expandafter\let\expandafter\@chk\csname ptype@#1\endcsname + \ifx\@chk\relax + \errmessage{parameter `#1' is undefined}% + \fi +}} +\def\@const@exists@err#1{{% + % ignore numeric constants (lazy check; anything that begins with a number) + \@ifnumeric{#1}\else + \expandafter\let\expandafter\@chk\csname const@#1\endcsname + \ifx\@chk\relax + \errmessage{constant `#1' is undefined}% + \fi + \fi +}} + +\def\@const@desc#1{{% + \@ifnumeric{#1}% + % just output the text + $#1$% + \else + % output desc + \csname const@#1\endcsname + \fi +}} + + +% denotes a param that will likely be calculated +\def\metaparamdef{\paramdef} + + +% param definition +% note that the description is included in this input as well; this allows us to +% use this information for code generation/etc +\def\paramdef{% + \begingroup + \catcode`_=11\relax + \@doparamdef +} +\def\@doparamdef#1 #2: #3 \par{% + \goodbreak% + \index{parameter!#2@\texttt{#2}|(}% + \begingroup% + \def\@given{#1}% + % given foo, get foo and bar separately + \edef\@root{\@ptype@root#1<||}% + \edef\@type{\@ptype@type#1<#1>||}% + \expandafter\gdef\csname param@#2\endcsname{#3}% + % does the given type exist (note that this check assumes that the typedef + % appears before the param in the specs, as is currently the case) + \expandafter\ifx\csname ptype@\@type\endcsname\relax% + \errmessage{unknown param type: \@type} + \fi% + % typeset definition with link + \item[% + \hypertarget{@param:#2}{{\tt#2}}% + \ $\in\textrm{% + \rm\typeref{\@type}% + % output root only if provided (if not, then because of how \@type + % called \@ptype@type, it will be equal to #1) + \ifx\@root\@given\else% + \ $\langle$\@root$\rangle$ + \fi + }$% + ]\hfill\\% + \@margin@sig% + % remove mysterious space from margin sig + \hskip-1ex\relax% + #3% + \ifx\@root\@given + \@codegen{}% + \else + \@codegen{% + }% + \fi + \endgroup% + \index{parameter!#2@\texttt{#2}|)}% + \endgroup +} + +\def\paramref{% + \begingroup% ended by \@dotypedef + \catcode`\_=11\relax + \@doparamref +} +\def\@doparamref#1{% + % prevent scantokens from adding a space at the end + \endlinechar-1\relax + \expandafter\let\expandafter\@@chk\csname param@#1\endcsname + \ifx\@@chk\relax + \PackageError{dwspec}{unknown param: #1} + \fi + \index{parameter!#1@\texttt{#1}}% + \hyperlink{@param:#1}% + {\tt\scantokens{#1}}% + \endgroup +} +\let\param\paramref + +\def\paramrefd#1{% + \expandafter\let\expandafter\@@pchk\csname param@#1\endcsname + \ifx\@@pchk\empty + \PackageError{dwspec}{Unknown parameter: #1}% + \else + % output + \@@pchk + \fi +} + +\def\locparam#1{% + \ifmmode + \mathop{\paramref{#1}_\loc} + \else + $\locparam{#1}$% + \fi +} + diff --git a/raterspec/question.sty b/raterspec/question.sty new file mode 100644 index 0000000..263c93e --- /dev/null +++ b/raterspec/question.sty @@ -0,0 +1,62 @@ +% LoVullo rater specification questions +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/question} +\ProcessOptions\relax + + +\newlength\questionparsep +\questionparsep\the\marginparsep +\newenvironment{qgroup}[1]% + {% + \subsubsection{#1}% + \begin{description}% + }% + {% + \end{description}% + } + +\newenvironment{subquestions}% + {% + \begin{description}% + \advance\questionparsep by \leftmargin\relax + } + {% + \end{description}% + } + + +\def\@qtypedesc@text{any string of characters.} +\def\@qtypedesc@number{any whole number.} +\def\@qtypedesc@float{any floating point value.} +\def\@qtypedesc@noyes{one of either {\sl No\/} or~{\sl Yes}.} +\def\@qtypedesc@select{one of the options enumerated below:} +\newcommand\question[5][]{% + \item[% + \beginundersletter + \llap{% + \tt\scriptsize\raisebox{-1em}[0em][0em]{% + \shortstack[r]{% + \scantokens{#2}\\ + {\tiny \scantokens{#4}}% + }% + }% + \hspace{\the\questionparsep}% + }% + \endundersletter + \ignorespaces#5\unskip + ]\hfill\\ + \@margin@sig + \begingroup + \def\@mapsto{#3}% + \ifx\@mapsto\empty + \May not map to any rater input parameter.% + \else + \Shall map to rater input parameter \paramref{#3}.% + \fi + \endgroup + \space Input value \shall be \csname @qtypedesc@#4\endcsname\space + \ignorespaces +} + diff --git a/raterspec/rates.sty b/raterspec/rates.sty new file mode 100644 index 0000000..1ed00ec --- /dev/null +++ b/raterspec/rates.sty @@ -0,0 +1,44 @@ +% LoVullo rater specification rate tables +%% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{raterspec/rates} +\ProcessOptions\relax + + +\newenvironment{ratetable*}[5][]% + {% + \def\@@lotcaption{#1} + \def\@@label{#2} + \def\@@caption{#3} + \ifx\@@lotcaption\empty + \let\@@lotcaption\@@caption + \fi + \begin{table}[#5] + \caption[\@@lotcaption]{\@@caption} + \label{t:\@@label} + \centering\footnotesize\sf + \hspace*{-\marginparwidth}% + \begin{tabular}{#4} + \toprule + } + {% + \bottomrule + \end{tabular} + \hspace*{-\marginparwidth}% + \medskip + \end{table} + } + + +% simplified syntax where a rate table should always appear on a page of floats +% (which is often the case, since many rate tables tend to be within close +% proximity to one-another) +\newenvironment{ratetable}[4][]% + {% + \begin{ratetable*}[#1]{#2}{#3}{#4}{p}% + }% + {% + \end{ratetable*}% + } +