% same as soi2.cls, but with some small changes
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{soiminar}

% Declare options.  E.g. lang=english will result in \def\SOI@lang{english}
\RequirePackage{kvoptions}
\SetupKeyvalOptions{
  family=SOI,
  prefix=SOI@
}
\DeclareStringOption[english]{lang} % the language
\DeclareBoolOption[true]{palatino} % whether to use the palatino font
\DeclareBoolOption[false]{twoside} % whether to use use a two sided book format
\DeclareBoolOption[false]{grayscale} % whether to use grayscale images
\ProcessKeyvalOptions*

%\newcommand{\subtaskmarker}[1]{}

% \soiround is another option, but it needs to accept any markup, so it can't be
% a class option.
%\newif\ifsoi@gotround
%\newcommand{\soi@round}{}
%\newcommand{\soiround}[1]{
%  \ifsoi@gotround
%    \ClassError{soi2}{cannot redefine soiround}
%  \fi
%  \global\soi@gotroundtrue
%  \renewcommand\soi@round{#1}
%}
%\AtBeginDocument{
%  \ifsoi@gotround\else
%  \ClassError{soi2}{macro soiround not defined}
%  \fi
%}

% We use report for the following reasons:
% * Every Task starts on a new line, which is exactly what chapters do in report.
%   This documentclass is optimized for the screen, we don't want the distinction
%   between even/odd pages, which {book} has.
\ifSOI@twoside
  \LoadClass[a4paper,twoside,titlepage,final]{scrartcl}
\else
  \LoadClass[a4paper,final,DIV=calc,fontsize=10pt,final]{scrartcl}
\fi

\RequirePackage{pdftexcmds} % for pdfstrcmp

\ifSOI@grayscale
  \newcommand\soi@cube{cube-small-grayscale.png}
\else
  \newcommand\soi@cube{cube-small.png}
\fi

% Kyrillic symbols need special care.
\ifnum\pdfstrcmp{\SOI@lang}{russian}=0
  \RequirePackage[T1,T2A]{fontenc}
  \RequirePackage[utf8]{inputenc}
\else
  \RequirePackage[T1]{fontenc}
  \RequirePackage[utf8]{inputenc}
  \ifSOI@palatino
    \RequirePackage{newpxtext,newpxmath}
  \else
    \RequirePackage{lmodern}
  \fi
\fi

% Commonly used packages
\RequirePackage{nag}
\RequirePackage[final,babel=true]{microtype}
\RequirePackage{csquotes}
\RequirePackage{amsmath,amssymb}
\RequirePackage[a4paper]{geometry}
\RequirePackage{graphicx}
\RequirePackage[dvipsnames]{xcolor}
\RequirePackage{tabularx}
\RequirePackage{lastpage}
\RequirePackage{enumitem}
\RequirePackage{hyperref}
\RequirePackage{tikz}
\RequirePackage{pgfmath}
\RequirePackage{wrapfig}
\RequirePackage{caption}
\RequirePackage{subcaption}

\setlist[1]{itemsep=0em} % less vertical space in itemize environment

% Needed for this documentclass
\RequirePackage{lastpage,fancybox,calc,etoolbox,xparse}

%\def\logodir{./logo} % configuration: path to the directory with logo images

% As the very last package, load language support
\ifnum\pdfstrcmp{\SOI@lang}{german}=0
  \RequirePackage[ngerman]{babel}
\else
  \RequirePackage[\SOI@lang]{babel}
\fi

%\providecommand{\soi@taskname}{}
%\newcommand\task[2]{\renewcommand\soi@taskname{#2}\chapter{#1}\markboth{Task \texttt{#2}}{Task \texttt{#2}}}
%
%\setlength{\headheight}{3cm}
%\renewcommand*{\chapterpagestyle}{headings}
%\ifSOI@twoside
%\rehead{\parbox[b]{2cm}{\edef\soi@tmp{\noexpand\includegraphics[height=2cm]{\logodir/\soi@cube}}\soi@tmp}
%\parbox[b]{\dimexpr\linewidth-2.2cm\relax}
%  {\noindent\textsf{\textbf{%
%        {\large Swiss Olympiad in Informatics}\vspace{0.75em}\\
%        \soi@round}}\vspace{.85em}}\hfill
%}
%\lehead{}
%\lohead{\hfill\noindent\textsf{\textbf{\rightmark}}\vspace{.85em}}
%\rohead{}
%\ofoot{\thepage/\pageref*{LastPage}}
%\else
%\ihead{\parbox[b]{2cm}{\edef\soi@tmp{\noexpand\includegraphics[height=2cm]{\logodir/\soi@cube}}\soi@tmp}}
%\chead{}
%\ohead{\parbox[b]{\dimexpr\linewidth-2.2cm\relax}
%  {\noindent\textsf{\textbf{%
%        {\large Swiss Olympiad in Informatics}\vspace{0.75em}\\
%        \soi@round \hfill Task \texttt{\soi@taskname}}}}}
%\cfoot{\thepage/\pageref*{LastPage}}
%\fi
%\pagestyle{scrheadings}

%\renewcommand*{\chapterformat}{\thechapter}\renewcommand*\thechapter{}
%\renewcommand*{\sectionformat}{\thesection}\renewcommand*\thesection{}
%\renewcommand*{\subsectionformat}{\thesubsection}\renewcommand*\thesubsection{}
%\renewcommand*{\subsubsectionformat}{\thesubsubsection}\renewcommand*\thesubsubsection{}
%
%\renewcommand*{\chapterheadstartvskip}{\vspace*{0cm}}
%\renewcommand*{\chapterheadendvskip}{\vspace*{\baselineskip}}
%
%\RedeclareSectionCommand[
%  beforeskip=-1sp,
%  afterskip=2\baselineskip]{chapter}
%\RedeclareSectionCommand[
%  beforeskip=-\baselineskip,
%  afterskip=.5\baselineskip]{section}
%\RedeclareSectionCommand[
%  beforeskip=-.75\baselineskip,
%  afterskip=.5\baselineskip]{subsection}
%\RedeclareSectionCommand[
%  beforeskip=-.5\baselineskip,
%  afterskip=.25\baselineskip]{subsubsection}
%\RedeclareSectionCommand[
%  beforeskip=.5\baselineskip,
%  afterskip=-1em]{paragraph}
%\RedeclareSectionCommand[
%  beforeskip=-.5\baselineskip,
%  afterskip=-1em]{subparagraph}

% Sample Input/Output
%
% There's a major difficulty for this in LaTeX: The input gets tokenized and the
% whitespaces (spaces and newlines) removed.  But we want to preserve newlines
% and spaces in our sample input/output.  The commands \obeylines\obeyspaces
% fake a verbatim environment for us.
%
% Another challenge is that the code in the pdf is not copyable from the printer
% because the pdf format doesn't account for whitespaces.  The copy string
% really gets messed up in some cases and the participent has to write it by
% hand.  The following hack replaces whitespaces with the uni2423 character
% (looks like ,_,) which are included in the pdf.  We make it white so that
% nobody notices it.  We give this character a custom copy string, a real space.
\ifSOI@palatino\else
  \input{glyphtounicode}
  \pdfglyphtounicode{uni2423}{A0}
  \pdfgentounicode=1
\fi

\newlength{\samplewidth}
\setlength{\samplewidth}{\textwidth}
\newlength{\iowidth}
\setlength{\iowidth}{0.5\samplewidth-2\tabcolsep-1.3333\arrayrulewidth} % account for padding inside table

% The tabular environment doesn't like verbatim commands (this is a documented
% bug).  We render the input blocks beforehand and save them in boxes.  We then
% put the boxes into the tabular.
\newsavebox{\soi@inputbox}
\newsavebox{\soi@outputbox}

% The syntax for the user is
%
%     \begin{sample}
%       <sample input>
%     \outputdef
%       <sample output>
%     \comment    %optional
%       <comment> %optional
%     \end{sample}
%
% When \outputdef comes, we need to save the current box into soi@inputbox
% and start a new box.  When \comment comes, we need to render the table and
% start a minipage that contains the comment until \end{sample}.
% If \end{sample} comes (without \comment) we need to render the table later.

\newcommand\soi@savebox[1]{\global\soi@gotoutputtrue\global\sbox{#1}{\TheSbox}}
\newcommand\soi@ioblock{\Sbox\minipage[t]{\iowidth}}
\newcommand\soi@endioblock{\endminipage\endSbox}

\newcommand\soi@printiotable{\ifsoi@gotoutput\else%
  % nice error message if someone forgets the \output section.
  \ClassError{soi2}{no output section inside environment ``sample''}
\fi%
\endgroup%
%
{\par\noindent\parskip=0pt\nopagebreak%
  \setlength\extrarowheight{0.3em}%
  \begin{tabularx}{\textwidth}[t]{|X|X|}
\multicolumn{1}{c}{\soi@sampleInputLabel}&%
\multicolumn{1}{c}{\soi@sampleOutputLabel}\\\hline%
% this is where we load the io boxes
% vfill is needed so that tabular can correctly measure the size of the box
\usebox{\soi@inputbox}\vspace{0.4em}&%
\usebox{\soi@outputbox}\vspace{0.4em}\\\hline
\end{tabularx}\par\noindent\ignorespacesafterend}
}


\newenvironment{sample}{\par% start a new paragraph
  % boolean variables for the nicer error message
  \providecommand\comment\relax%
  \providecommand\outputdef\relax%
  \newif\ifsoi@gotoutput%
  \newif\ifsoi@gotcomment%
  \let\soi@old@comment\comment%
  \let\soi@old@outputdef\outputdef%
  \renewcommand*\comment\soi@comment%
  \renewcommand*\outputdef\soi@outputdef%
  % A minipage to prevent page breaks inside a sample
  \noindent%
  \begin{minipage}{\samplewidth}
  % preserve spaces
  \begingroup% inside a group so we can resume the normal parsing in \comment.
  % make all characters to letters except `\', `{' and `}'
  \let\do\@makeother\dospecials\catcode`\\=0\catcode`\{=1\catcode`\}=2%
  \def\@xobeysp{\textcolor{white}{\char32}}%
  \ttfamily\obeylines\obeyspaces\@vobeyspaces%
  \@noligs% disable ligatures
  \begingroup\lccode`~=`\^^M%
  \lowercase{\endgroup\def~}{\nobreak\hfil\break}%
  % start input block
  \soi@ioblock}%
{\ifsoi@gotcomment%
  % if \comment did come before, just close the comment minipage
  \unpenalty\unskip\unpenalty\endminipage\bigskip\par % 1em: substitute for the margin around the table
\else%
  % otherwise end the io block and print the table (which is what \comment does)
  \unpenalty\unskip\unpenalty\soi@endioblock\soi@savebox{\soi@outputbox}%
  \soi@printiotable\bigskip\par%
\fi%
\end{minipage}\par\ignorespacesafterend% end the paragraph
\let\comment\soi@old@comment%
\let\outputdef\soi@old@outputdef%
}
\newcommand\soi@outputdef{%
  % save the inputbox for further processing
  \unpenalty\unskip\unpenalty\soi@endioblock\soi@savebox{\soi@inputbox}\soi@ioblock}
\newcommand\soi@comment{%
  % end the io block and print the table before \end{sample}
  \unpenalty\unskip\unpenalty\soi@endioblock\soi@savebox{\soi@outputbox}\soi@printiotable%
  \global\soi@gotcommenttrue% notify \end{sampe} that we are in comment mode
  % start comment minipage.
  \minipage{\textwidth}\flushleft\itshape\parskip=0.5em\par\nopagebreak}

\newcommand\soi@sampleInputLabel{\small\textbf{\textsf{Input}}}
\newcommand\soi@sampleOutputLabel{\small\textbf{\textsf{Output}}}
\newcommand\soi@sampleInputDir{../testdata}
\newcommand\soi@sampleOutputDir{../testdata}
\newcommand\soi@sampleInputSuffixFake{.fake.in}
\newcommand\soi@sampleInputSuffix{.in}
\newcommand\soi@sampleOutputSuffixFake{.fake.out}
\newcommand\soi@sampleOutputSuffix{.out}

\newcommand\sampleInputLabel[1]{\renewcommand\soi@sampleInputLabel{\small\textbf{\textsf{#1}}}}
\newcommand\sampleOutputLabel[1]{\renewcommand\soi@sampleOutputLabel{\small\textbf{\textsf{#1}}}}
\newcommand\sampleInputDir[1]{\renewcommand\soi@sampleInputDir{#1}}
\newcommand\sampleOutputDir[1]{\renewcommand\soi@sampleOutputDir{#1}}
\newcommand\sampleInputSuffixFake[1]{\renewcommand\soi@sampleInputSuffixFake{#1}}
\newcommand\sampleInputSuffix[1]{\renewcommand\soi@sampleInputSuffix{#1}}
\newcommand\sampleOutputSuffixFake[1]{\renewcommand\soi@sampleOutputSuffixFake{#1}}
\newcommand\sampleOutputSuffix[1]{\renewcommand\soi@sampleOutputSuffix{#1}}
\newcommand\sampleSuffix[1]{\sampleInputSuffixFake{#1}\sampleInputSuffix{#1}\sampleOutputSuffixFake{#1}\sampleOutputSuffix{#1}}

\ifnum\pdfstrcmp{\SOI@lang}{german}=0
  \sampleInputLabel{Eingabe}
  \sampleOutputLabel{Ausgabe}
\fi
\ifnum\pdfstrcmp{\SOI@lang}{french}=0
  \sampleInputLabel{Entrée}
  \sampleOutputLabel{Sortie}
\fi

% input two files:
%   \inputSampleFiles{sample00.in}{sample00.out}{comment}
%   \inputSampleFiles{sample00.in}{sample00.out} % comment is optional
% shorter form:
%   \inputSample{sample00}{comment}
%   \inputSample{sample00} % comment is optional
% even shorter:
%   \Sample{00}{comment}
%   \Sample{00} % comment is optional
\ExplSyntaxOn
\DeclareDocumentCommand\inputSampleFiles{mmG{}}{\tl_if_empty:nTF{#3}{\begin{sample}
\input{#1}
\outputdef
\input{#2}
\end{sample}}{\begin{sample}
\input{#1}
\outputdef
\input{#2}
\comment
#3
\end{sample}}}
\DeclareDocumentCommand\inputSample{mG{}}{%
\IfFileExists{\soi@sampleInputDir/#1\soi@sampleInputSuffixFake}{
\IfFileExists{\soi@sampleOutputDir/#1\soi@sampleOutputSuffixFake}
  {\inputSampleFiles{\soi@sampleInputDir/#1\soi@sampleInputSuffixFake}
                    {\soi@sampleOutputDir/#1\soi@sampleOutputSuffixFake}
                    {#2}}
  {\inputSampleFiles{\soi@sampleInputDir/#1\soi@sampleInputSuffixFake}
                    {\soi@sampleOutputDir/#1\soi@sampleOutputSuffix}
                    {#2}}%
}{%
\IfFileExists{\soi@sampleOutputDir/#1\soi@sampleOutputSuffixFake}
  {\inputSampleFiles{\soi@sampleInputDir/#1\soi@sampleInputSuffix}
                    {\soi@sampleOutputDir/#1\soi@sampleOutputSuffixFake}
                    {#2}}
  {\inputSampleFiles{\soi@sampleInputDir/#1\soi@sampleInputSuffix}
                    {\soi@sampleOutputDir/#1\soi@sampleOutputSuffix}
                    {#2}}%
}}
\DeclareDocumentCommand\Sample{mG{}}{\inputSample{sample#1}{#2}}
\ExplSyntaxOff

% With the above form, the comment part can't have multiple paragraphs.
% It's more robut to specify the comment inside an environment.
%
% input two files:
%   \begin{inputSampleFileComment}{sample01.in}{sample01.out}
%   comment
%   \end{inputSampleFileComment}
% shorter form:
%   \begin{inputSampleComment}{sample01}
%   comment
%   \end{inputSampleComment}
% even shorter:
%   \begin{sampleComment}{01}
%   comment
%   \end{sampleComment}
\newenvironment{inputSampleFileComment}[2]{%
\sample
\input{#1}
\outputdef
\input{#2}
\comment
}{%
\endsample%
}

\newenvironment{inputSampleComment}[1]{%
\begingroup%
\IfFileExists{\soi@sampleInputDir/#1\soi@sampleInputSuffixFake}%
{\edef\theInputFile{\soi@sampleInputDir/#1\soi@sampleInputSuffixFake}}%
{\edef\theInputFile{\soi@sampleInputDir/#1\soi@sampleInputSuffix}}%
\IfFileExists{\soi@sampleOutputDir/#1\soi@sampleOutputSuffixFake}%
{\edef\theOutputFile{\soi@sampleOutputDir/#1\soi@sampleOutputSuffixFake}}%
{\edef\theOutputFile{\soi@sampleOutputDir/#1\soi@sampleOutputSuffix}}%
\inputSampleFileComment{\theInputFile}{\theOutputFile}%
}{\endinputSampleFileComment\endgroup}

\newenvironment{sampleComment}[1]{\inputSampleComment{sample#1}}{\endinputSampleComment}
