Parser of berki style problems and generator of latex file
Samo Penic
2018-10-28 cc53f368889148dc0c706c895dd22d5f03f736e3
Template adapted for problem with subproblems.
1 files modified
4 files added
361 ■■■■■ changed files
tools/Template.py 40 ●●●● patch | view | raw | blame | history
tools/textemplates/problemintrotemplate.tpl 2 ●●●●● patch | view | raw | blame | history
tools/textemplates/sizif.sty 314 ●●●●● patch | view | raw | blame | history
tools/textemplates/subproblemtemplate.tpl 4 ●●●● patch | view | raw | blame | history
tools/textemplates/subproblemtemplateend.tpl 1 ●●●● patch | view | raw | blame | history
tools/Template.py
@@ -6,13 +6,16 @@
class TemplateEngine:
    def __init__(self, path=None):
        if path is None:
            raise(Exceptions.TemplatePathError("No path to templates"))
            raise (Exceptions.TemplatePathError("No path to templates"))
        self.template_filenames = {
            "head": os.path.join(path, "headtemplate.tpl"),
            "paper": os.path.join(path, "newpolatemplate.tpl"),
            "paper_sid": os.path.join(path, "newpaperwithSIDtemplate.tpl"),
            "problem": os.path.join(path, "problemtemplate.tpl"),
            "problem_intro": os.path.join(path, "problemintrotemplate.tpl"),
            "subproblem": os.path.join(path, "subproblemtemplate.tpl"),
            "subproblem_end": os.path.join(path, "subproblemtemplateend.tpl"),
        }
        self.template = {}
@@ -25,12 +28,31 @@
        return template
    def put_problem_into_template(self, problem_dict):
        retstr=""
        retstr+=Template(self.template['problem']).substitute({'problem_number': 0,
                                                               'text': problem_dict['introduction'],
                                                               'ans1': str(problem_dict['solutions'][0]['correct'][0]),
                                                               'ans2': str(problem_dict['solutions'][0]['wrong'][0]),
                                                               'ans3': str(problem_dict['solutions'][0]['wrong'][1]),
                                                               'ans4': str(problem_dict['solutions'][0]['wrong'][2])
                                                               })
        retstr = ""
        if len(problem_dict["solutions"]) > 1:
            retstr += Template(self.template["problem_intro"]).substitute(
                {"problem_number": 0, "text": problem_dict["introduction"]}
            )
            for sp, sol in zip(problem_dict["subproblems"], problem_dict["solutions"]):
                retstr += Template(self.template["subproblem"]).substitute(
                    {
                        "text": sp,
                        "ans1": str(sol["correct"][0]),
                        "ans2": str(sol["wrong"][0]),
                        "ans3": str(sol["wrong"][1]),
                        "ans4": str(sol["wrong"][2]),
                    }
                )
            retstr += Template(self.template["subproblem_end"]).substitute()
        else:
            retstr += Template(self.template["problem"]).substitute(
                {
                    "problem_number": 0,
                    "text": problem_dict["introduction"],
                    "ans1": str(problem_dict["solutions"][0]["correct"][0]),
                    "ans2": str(problem_dict["solutions"][0]["wrong"][0]),
                    "ans3": str(problem_dict["solutions"][0]["wrong"][1]),
                    "ans4": str(problem_dict["solutions"][0]["wrong"][2]),
                }
            )
        return retstr
tools/textemplates/problemintrotemplate.tpl
New file
@@ -0,0 +1,2 @@
%this is a template for text
\problemtext{$problem_number}{$text}
tools/textemplates/sizif.sty
New file
@@ -0,0 +1,314 @@
\usepackage{marginnote}
\usepackage{qrcode}
\newcommand{\marker}[1]{\raisebox{0.3ex}{\marginnote{ #1}}}
%\newcommand{\marker}[1]{\normalmarginpar\marginpar{\hskip0.0cm\raisebox{0ex}{#1}}}
%\usepackage{titleps}
\usepackage{amsmath}%
\usepackage{MnSymbol}%
\usepackage{wasysym}%
\usepackage{a4wide}
\usepackage[slovene]{babel}
\usepackage[utf8]{inputenc}
\usepackage{upgreek}  % Za pokoncne grske crke
\usepackage{graphicx}
\usepackage{rotating}
%\usepackage{a4wide,everyshi,keyval}
%\usepackage{textcomp}
%\usepackage{calc}
%\usepackage{refcount}
%\usepackage{xstring}
%\usepackage{ragged2e}
\usepackage{tikz}
\usepackage{ifthen}
\usetikzlibrary{calc}
%ADD PACKAGES HERE
\setlength{\topmargin}{0mm} %-17mm
\setlength{\hoffset}{0mm}
\setlength{\voffset}{-22mm}
\setlength{\headheight}{14mm}
\setlength{\headsep}{20mm}
\setlength{\footskip}{8mm}
\setlength{\oddsidemargin}{-15mm}
\setlength{\evensidemargin}{-15mm}
\setlength{\marginparwidth}{5mm}
\setlength{\textwidth}{190mm}
\setlength{\textheight}{232mm}
%some useful counters
\newcounter{problemsetid}
\newcounter{pageinproblemset}
\newcounter{firstinproblemset}
\newcounter{subproblem}
%We are not using newpagestyle from titleps, but we define it here:
\newcommand{\newpagestyle}[3]{%
\expandafter\newcommand\csname ps@#1\endcsname{\def\@oddhead{#2}\let\@evenhead\@oddhead
\def\@oddfoot{#3}\let\@evenfoot\@oddfoot}}
%this creates the qr code and a human name for the header (in first and in all subsequent pages)
\newcommand{\idlinewithname}[9]{\vskip3mm
\begin{minipage}[c]{0.09\textwidth} %place for QR Code
\qrcode[height=1.5cm]{#1,#2,#3,#4,#5}
\end{minipage}%
\begin{minipage}[c]{0.91\textwidth} %place for name and other info
%\settowidth{\namelength}{#6}
\hfill{\scriptsize\rm Študent/ka:\hskip3ex} \fbox{\parbox[c][7mm]{50mm}{\vspace{0mm}\hfil\Large{#6}\hfil\\\vspace{0mm}\hfil\small{\studentid}\hfil}}
\vskip1.5mm{\scriptsize\rm #7 }
\vskip-2mm\rule{\textwidth}{1pt}
\end{minipage}
\vskip2mm
\parbox{\textwidth}{
{\bfseries\large #8}\hfill #9}
}
%footer
\newcommand{\makefooter}[1]{
    \vskip1mm\rule{\textwidth}{1pt}{
        \parbox{\textwidth}{
            \parbox{\textwidth}{\rm #1}\vskip3mm
        \parbox{\textwidth}{\scriptsize\rm \productname~{\the\year}.~Razvijalci=$\left\{\parbox{9.5mm}{{\tiny{Fo\v{s}nari\v{c}}\\ \vskip-2.5mm{Peni\v{c}}\\ \vskip-3.3mm{Berkopec}}}\right.$\text{ver.}~\productversion%
        %\hfill\if\thelastintest1{\rm $\star$ $\longleftrightarrow$ $\star$ }\else\fi
        %\parbox{\textwidth}
    \setcounter{pageinproblemset}{-\value{firstinproblemset}}
    \addtocounter{pageinproblemset}{\value{page}}
    \addtocounter{pageinproblemset}{1}
    \hfill Podpis: \rule{40mm}{0.2pt}\hskip1cm Stran \thepageinproblemset, pola \theproblemsetid, rok \examid. }
        }
    }
}
%a style for first page. Header (see above) and the name of the faculty and the exam.
\newpagestyle{firstpagewithname}{%
%upper markers
\parbox{\textwidth}{
\setcounter{firstinproblemset}{\thepage}
\stepcounter{problemsetid}
\parbox{\textwidth}{\hskip1mm\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}}
%the header of the exam
\idlinewithname{\facultyid}{\examid}{\theproblemsetid}{1}{\studentid}{\studentname}{\facultyname}{\examtitle}{\examdate}
}
}{\parbox{\textwidth}{\makefooter{\footertext}}}
\newpagestyle{otherswithname}{%
%upper markers
\parbox{\textwidth}{
\parbox{\textwidth}{\hskip1mm\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}}
%the header of the exam
%
\setcounter{pageinproblemset}{-\value{firstinproblemset}}
\addtocounter{pageinproblemset}{\value{page}}
\addtocounter{pageinproblemset}{1}
\idlinewithname{\facultyid}{\examid}{\theproblemsetid}{\thepageinproblemset}{\studentid}{\studentname}{\facultyname}{\ }{\ }
}
}{\parbox{\textwidth}{\makefooter{\footertext}}}
%OLD STYLE PAGES
%this creates the qr code and SID for the header (in first and in all subsequent pages)
%
%
\def\xloop<#1#2>{%
  \ifx\relax#1
    \else
      \sevensegnum{#1}\hskip1mm\xloop<#2>% here you can set the distance between the numbers
  \fi}
\def\markletters#1{\xloop<#1\relax>}
\newcommand{\sid}[1]{
\markletters{#1}
}
\newcommand{\idlinewithsid}[8][]{\vskip3mm
\begin{minipage}[c]{0.09\textwidth} %place for QR Code
\qrcode[height=1.5cm]{#2,#3,#4,#5}
\end{minipage}%
\begin{minipage}[c]{0.91\textwidth} %place for name and other info
\ifx&#1&
\phantom{
\hfill{\scriptsize\rm Ime in priimek:\hskip3ex \fbox{\parbox[c][7mm]{50mm}{\vspace{0mm}\hspace{50mm}}}\hfill\rm Vpisna \v{s}t.:\hskip3ex\hskip0mm\raisebox{-4mm}{#1}}
}
\else
\hfill{\scriptsize\rm Ime in priimek:\hskip3ex \fbox{\parbox[c][7mm]{50mm}{\vspace{0mm}\hspace{50mm}}}\hfill\rm Vpisna \v{s}t.:\hskip3ex\hskip0mm\raisebox{-4mm}{#1}}
\fi
\vskip1.5mm{\scriptsize\rm #6 }
\vskip-2mm\rule{\textwidth}{1pt}
\end{minipage}
\vskip2mm
\parbox{\textwidth}{
{\bfseries\large #7}\hfill #8}
}
\newpagestyle{firstpagewithsid}{%
%upper markers
\parbox{\textwidth}{
\setcounter{firstinproblemset}{\thepage}
\stepcounter{problemsetid}
\parbox{\textwidth}{\hskip1mm\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}}
%the header of the exam
\idlinewithsid[\sidprefill]{\facultyid}{\examid}{\theproblemsetid}{1}{\facultyname}{\examtitle}{\examdate}
}
}{\parbox{\textwidth}{\makefooter{\footertext}}}
\newpagestyle{otherswithsid}{%
%upper markers
\parbox{\textwidth}{
\parbox{\textwidth}{\hskip1mm\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}\parbox[t]{48mm}{$\blacksquare$}}
%the header of the exam
%
\setcounter{pageinproblemset}{-\value{firstinproblemset}}
\addtocounter{pageinproblemset}{\value{page}}
\addtocounter{pageinproblemset}{1}
\idlinewithsid{\facultyid}{\examid}{\theproblemsetid}{\thepageinproblemset}{\facultyname}{\ }{\ }
}
}{\parbox{\textwidth}{\makefooter{\footertext}}}
%
%
%
%%%%% END OLD STYLE
\newcommand{\problemtext}[3][]{%
\setcounter{subproblem}{0}%
\noindent{\hskip1mm\parbox[t]{4mm}{\bfseries\rightline{#2. }}}%
\noindent\parbox[t]{0.95\textwidth}{ #3  \ifx&#1& \else $\mathbf{[}$\textbf{#1}$\mathbf{]}$ \fi}%
}
\newcommand{\subproblemtext}[1]{%
\addtocounter{subproblem}{1}%
\parbox[t]{0.95\textwidth}{\alph{subproblem}) #1}%
}
\newcommand{\answersinline}[4]{\noindent%
\parbox[t][][t]{180mm}{
\makebox[48mm][l]{\textcircled{\scriptsize{\rm{A}}}\hskip2pt\begin{minipage}[t][][t]{42mm}{{\small\begin{flushleft} #1\end{flushleft}}}\end{minipage}}%
\makebox[48mm][l]{\textcircled{\scriptsize{\rm{B}}}\hskip2pt\begin{minipage}[t][][t]{42mm}{{\small\begin{flushleft} #1\end{flushleft}}}\end{minipage}}%
\makebox[48mm][l]{\textcircled{\scriptsize{\rm{C}}}\hskip2pt\begin{minipage}[t][][t]{42mm}{{\small\begin{flushleft} #1\end{flushleft}}}\end{minipage}}%
\makebox[48mm][l]{\textcircled{\scriptsize{\rm{D}}}\hskip2pt\begin{minipage}[t][][t]{42mm}{{\small\begin{flushleft} #1\end{flushleft}}}\end{minipage}}%
\marker{$\blacksquare$}
}
}
%Answer multiline template
\newcommand{\answersmultiline}[4]{\noindent%
\parbox[t][][t]{180mm}{
\marker{$\blacktriangledown$}\textcircled{\scriptsize{\rm{A}}}\hskip4pt{\parbox[t][][t]{0.95\textwidth}{\small #1}}%
\vskip\multilinesep
\marker{$\blacktriangle$}\textcircled{\scriptsize{\rm{B}}}\hskip4pt{\parbox[t][][t]{0.95\textwidth}{\small #2}}%
\vskip\multilinesep
\marker{$\blacktriangle$}\textcircled{\scriptsize{\rm{C}}}\hskip4pt{\parbox[t][][t]{0.95\textwidth}{\small #3}}%
\vskip\multilinesep
\marker{$\blacktriangle$}\textcircled{\scriptsize{\rm{D}}}\hskip4pt{\parbox[t][][t]{0.95\textwidth}{\small #4}}%
}
}
%%7-segment display
%from: http://www.texample.net/tikz/examples/segment-display/
\pgfkeys{
  /sevenseg/.is family, /sevenseg,
  slant/.estore in      = \sevensegSlant,     % vertical slant in degrees
  size/.estore in       = \sevensegSize,      % length of a segment
  shrink/.estore in     = \sevensegShrink,    % avoids overlapping of segments
  line width/.estore in = \sevensegLinewidth, % thickness of the segments
  line cap/.estore in   = \sevensegLinecap,   % end cap style rect, round, butt
  oncolor/.estore in    = \sevensegOncolor,   % color of an ON segment
  offcolor/.estore in   = \sevensegOffcolor,  % color of an OFF segment
}
\pgfkeys{
  /sevenseg,
  default/.style = {slant = 0, size = 0.4cm, shrink = 0.1,
                    line width = 0.9mm, line cap = round,
                    oncolor = black, offcolor = gray!10}
}
%===============================================
%                     a b c d e f g - segment values
% \sevenseg[options]{{1,1,1,1,1,1,0,}}
%
\newcommand{\sevenseg}[2][]% options values
{%
\pgfkeys{/sevenseg, default, #1}%
\def\sevensegarray{#2}%
  \begin{tikzpicture}%
    % first define the position of the 6 corner points
    \path (0,0) ++(0,0)                             coordinate (P1);
    \path (0,0) ++(\sevensegSize,0)                 coordinate (P2);
    \path (0,0) ++(90-\sevensegSlant:\sevensegSize) coordinate (P3);
    \path (P2)  ++(90-\sevensegSlant:\sevensegSize) coordinate (P4);
    \path (P3)  ++(90-\sevensegSlant:\sevensegSize) coordinate (P5);
    \path (P4)  ++(90-\sevensegSlant:\sevensegSize) coordinate (P6);
    % then step through the 1/0 values in the segment array
    \foreach \i in {0,...,6}%
    {
      \pgfmathparse{\sevensegarray[\i]}
      \ifthenelse{\equal{\pgfmathresult}{1}}%
        {\let\mycolor=\sevensegOncolor}%  segment is on
        {\let\mycolor=\sevensegOffcolor}% segment is off
      \tikzstyle{segstyle} = [draw=\mycolor, line width = \sevensegLinewidth,
                              line cap = \sevensegLinecap]
      %-----------------------
      \ifthenelse{\equal{\i}{0}}{\path[segstyle]
        (${1-\sevensegShrink}*(P5)+\sevensegShrink*(P6)$)
        -- ($\sevensegShrink*(P5)+{1-\sevensegShrink}*(P6)$);}{} % a
      \ifthenelse{\equal{\i}{1}}{\path[segstyle]
        (${1-\sevensegShrink}*(P6)+\sevensegShrink*(P4)$)
        -- ($\sevensegShrink*(P6)+{1-\sevensegShrink}*(P4)$);}{} % b
      \ifthenelse{\equal{\i}{2}}{\path[segstyle]
        (${1-\sevensegShrink}*(P4)+\sevensegShrink*(P2)$)
        -- ($\sevensegShrink*(P4)+{1-\sevensegShrink}*(P2)$);}{} % c
      \ifthenelse{\equal{\i}{3}}{\path[segstyle]
        (${1-\sevensegShrink}*(P1)+\sevensegShrink*(P2)$)
        -- ($\sevensegShrink*(P1)+{1-\sevensegShrink}*(P2)$);}{} % d
      \ifthenelse{\equal{\i}{4}}{\path[segstyle]
        (${1-\sevensegShrink}*(P1)+\sevensegShrink*(P3)$)
        -- ($\sevensegShrink*(P1)+{1-\sevensegShrink}*(P3)$);}{} % e
      \ifthenelse{\equal{\i}{5}}{\path[segstyle]
        (${1-\sevensegShrink}*(P3)+\sevensegShrink*(P5)$)
        -- ($\sevensegShrink*(P3)+{1-\sevensegShrink}*(P5)$);}{} % f
      \ifthenelse{\equal{\i}{6}}{\path[segstyle]
        (${1-\sevensegShrink}*(P3)+\sevensegShrink*(P4)$)
        -- ($\sevensegShrink*(P3)+{1-\sevensegShrink}*(P4)$);}{} % g
    }
  \end{tikzpicture}%
}
\newcommand{\sevensegnum}[2][]% sample characvters
{%
  \ifthenelse{\equal{#2}{0}}{\sevenseg[#1]{{1,1,1,1,1,1,0,}}}{%
  \ifthenelse{\equal{#2}{1}}{\sevenseg[#1]{{0,1,1,0,0,0,0,}}}{%
  \ifthenelse{\equal{#2}{2}}{\sevenseg[#1]{{1,1,0,1,1,0,1,}}}{%
  \ifthenelse{\equal{#2}{3}}{\sevenseg[#1]{{1,1,1,1,0,0,1,}}}{%
  \ifthenelse{\equal{#2}{4}}{\sevenseg[#1]{{0,1,1,0,0,1,1,}}}{%
  \ifthenelse{\equal{#2}{5}}{\sevenseg[#1]{{1,0,1,1,0,1,1,}}}{%
  \ifthenelse{\equal{#2}{6}}{\sevenseg[#1]{{1,0,1,1,1,1,1,}}}{%
  \ifthenelse{\equal{#2}{7}}{\sevenseg[#1]{{1,1,1,0,0,0,0,}}}{%
  \ifthenelse{\equal{#2}{8}}{\sevenseg[#1]{{1,1,1,1,1,1,1,}}}{%
  \ifthenelse{\equal{#2}{9}}{\sevenseg[#1]{{1,1,1,1,0,1,1,}}}{%
  \ifthenelse{\equal{#2}{A}}{\sevenseg[#1]{{1,1,1,0,1,1,1,}}}{%
  \ifthenelse{\equal{#2}{B}}{\sevenseg[#1]{{0,0,1,1,1,1,1,}}}{%
  \ifthenelse{\equal{#2}{C}}{\sevenseg[#1]{{0,0,0,1,1,0,1,}}}{%
  \ifthenelse{\equal{#2}{D}}{\sevenseg[#1]{{0,1,1,1,1,0,1,}}}{%
  \ifthenelse{\equal{#2}{E}}{\sevenseg[#1]{{1,0,0,1,1,1,1,}}}{%
  \ifthenelse{\equal{#2}{F}}{\sevenseg[#1]{{1,0,0,0,1,1,1,}}}{%
  \ifthenelse{\equal{#2}{x}}{\sevenseg[#1]{{0,0,0,0,0,0,0,}}}{%
  {\sevenseg[#1]{{0,0,0,0,0,0,0,}}}}}}}}}}}}}}}}}}}}%
}
tools/textemplates/subproblemtemplate.tpl
New file
@@ -0,0 +1,4 @@
\vskip\texttoanswerskip
\subproblemtext{$text}
\vskip\texttoanswerskip
\answersinline{$ans1}{$ans2}{$ans3}{$ans4}
tools/textemplates/subproblemtemplateend.tpl
New file
@@ -0,0 +1 @@
\vskip\answertotextskip