\ProvidesClass{QUTexam}

%options: code= exam code (printed in footer)
%provided commands:
% \begin{questions}\question[points] \question \end{questions}
% \totalPoints
% \numberOfQuestions
% \fullWidth (to put pictures over the entire page, disregarding indentations)
% \begin{answers} \item \end{answers}
% in any environment, you can call \printPointsA or \printPointsB to print the number of points on the same line (like for QED's in proofs)

%options: code=exam code (printed in footer)
%options: seed=seed integer (used for answer randomisation, keep secret if you don't also randomise answers yourself, as this will be predictable)
	\RequirePackage{kvoptions}
	\DeclareStringOption[0]{code}
	\DeclareStringOption[1]{seed}
	\DeclareLocalOptions{code,seed}
	\ProcessKeyvalOptions*

	\LoadClass[a4paper,12pt]{article}
	
%put ``end of paper'' automatically, either just before the appendices or at end of document
	\newcommand{\QUTendOfPaper}{%
		\begin{center}%
			\textbf{END OF PAPER}%
		\end{center}%
		\pagestyle{lastPage}%
	}
	
	\newif\ifinappendix
	\let\oldappendix\appendix
	\inappendixfalse
	\renewcommand{\appendix}{% Update \appendix
		\QUTendOfPaper
		\oldappendix% Default \appendix
		\inappendixtrue% Set switch to true
		\clearpage
		\pagestyle{appendixPage}
		\pagenumbering{roman}% set roman page numbering
	}
	
	\AtEndDocument{\ifinappendix {} \else \QUTendOfPaper \fi}
	
%font, margins
	\RequirePackage{fontspec}
	\setmainfont{Times New Roman}
	\RequirePackage[a4paper,includeheadfoot,top=2cm, bottom=1cm, left=2.54cm, right=2cm]{geometry}
	\RequirePackage[normalem]{ulem}
	
%fullwidth (to jump out of enumerate margins)
	\def\fullWidth#1{{\relax \setlength{\parindent}{-\leftmargin}#1}}

%set the header and footer
	\RequirePackage{fancyhdr,lastpage}
	
	\fancypagestyle{middlePage}{%
		\renewcommand{\headrulewidth}{0pt}%
		\setlength{\headheight}{0mm}%
		\fancyfoot{}%
		\fancyhead{}%
		\chead{\thepage{}}%
		\lfoot{\QUTexam@code}%
		\rfoot{cont/$...$}%
	}
	
	\fancypagestyle{appendixPage}{%
		\pagestyle{middlePage}%
		\chead{(\thepage{})}%
		\rfoot{}%
	}
	
	\fancypagestyle{lastPage}{%
		\pagestyle{middlePage}%
		\rfoot{}%
	}
	
	\pagestyle{middlePage}
	
	%patch maketitle to use the new page style
	\let\oldmaketitle\maketitle
	\renewcommand{\maketitle}[0]{\oldmaketitle\thispagestyle{middlePage}}
	
%questions
	\RequirePackage{enumitem}
	
	%count questions
	\DeclareRobustCommand{\countQuestion}{\refstepcounter{questionCounter}}
	\RequirePackage{totcount}
	\newtotcounter{questionCounter}
	\newtotcounter{pointsCounter}
	\newcommand{\totalPoints}{\total{pointsCounter}}
	\newcommand{\numberOfQuestions}{\total{questionCounter}}
	
	\let\oldItem\item %store the value of item

	%question environment
		\def\printPointsA{%process the points of the -previous- \item
			\ifnum \pointsA=0%
				\null%
			\else {%
				\leavevmode\unskip\penalty9999 \hbox{}\nobreak\hfill\quad\hbox{(\pointsA{} \ifnum \pointsA=1 mark\else marks\fi)}} 
				\gdef\pointsA{0}%reset points for if this is called twice
			\fi%
		} 
		\def\addPointsA#1{%
			\def\pointsA{#1}%
			\addtocounter{pointsCounter}{#1}%
		}
		\newlist{questions}{enumerate}{2}
		\setlist[questions,1]{
			label=\uline{\countQuestion QUESTION \arabic*},
			font=\bfseries,
			ref=\arabic*,
			align=left,
			beginpenalty=5000,
			midpenalty=-5000,
			endpenalty=-1,
			wide,
			labelwidth=!,
			labelindent=0pt,
			before*={%
				%keep track of points. 0 means that there are no points
				\def\pointsA{0}%
				%
				%redefine item
				\newcommand{\question}[1][0]{\printPointsA\addPointsA{########1}\oldItem ~\vskip 0pt \noindent}%
			},
			after*={\printPointsA}
		}
	
	%subquestion environment
		\gdef\pointsB{0}
		\def\printPointsB{%process the points of the -previous- \item
			\ifnum \pointsB=0%
			\else {%
				\leavevmode\unskip\penalty9999 \hbox{}\nobreak\hfill\quad\hbox{(\pointsB{} \ifnum \pointsB=1 mark\else marks\fi)}%
				\gdef\pointsB{0}%reset points for if this is called twice
			}\fi%
		}
		\def\addPointsB#1{%
			\gdef\pointsB{#1}%
			\addtocounter{pointsCounter}{#1}%
		}
		\setlist[questions,2]{
			label=(\alph*),
			ref=\alph*,
			align=left, labelindent=0pt, labelwidth=1.25cm, labelsep*=0pt, leftmargin=!,
			beginpenalty=8000,
			endpenalty=-1,
			midpenalty=-1,			
			before={%
				\gdef\pointsB{0}% keep track of points. 0 means that there are no points
				\renewcommand{\question}[1][0]{\printPointsB\addPointsB{########1}\oldItem}% redefine item
			},
			after*={%
				\printPointsB%
			}
		}
		
	%answers
	\newlist{answers}{enumerate}{1}
	\setlist[answers]{
		label=(\alph*),
		beginpenalty=10000,
		midpenalty=10000,
		endpenalty=4000,
		align=left, labelindent=0pt, labelwidth=1.25cm, labelsep*=0pt, leftmargin=!,
		before={\def\item{\oldItem}}
	}	
	
	%randomised answers
	\def\randomanswerseed{201}
	
	\RequirePackage{lcg}
	\RequirePackage{pgffor,xstring,fp}
	\usepgflibrary{fpu}
	\pgfkeys{/pgf/fpu/output format=sci}
	\pgfkeys{/pgf/number format/.cd, sci, sci e, sci zerofill, precision = 3}

	\pgfkeys{/pgf/fpu=true} % this breaks pgfmathsetseed
	
	\newcounter{randomseed}
	
	\newcommand\lengthof[1]{\csname pgfmath@randomlist@#1\endcsname}
	\newcommand\nthof[2]{\csname pgfmath@randomlist@#2@#1\endcsname}
	
	\def\orderedanswers#1{
		\pgfmathdeclarerandomlist{answeroptions}{#1}
		\begin{answers}
			\foreach \x in {1,...,\lengthof{answeroptions}}{%
				\item \nthof{\x}{answeroptions}
			}
		\end{answers}
	}
	
	\def\randomanswers#1{		
		\pgfmathdeclarerandomlist{answeroptions}{#1}
		\pgfmathdeclarerandomlist{keeplength}{#1}
		\def\myshuffle{}
		\def\answeroptions{#1}
		
		\begin{answers}
			%\@for \el:=#1\do{\item \el }%
			
			%\foreach \el in {#1} {\item \pgfmathrandomitem\elem{answeroptions}\elem}%
			
			\foreach \x in {1,...,\lengthof{keeplength}}{%
				\item 
				
				%get a new seed based on the question
				\FPeval{\seed}{clip(\QUTexam@seed+\thequestionCounter+\x)}

				% pick one from the list
				\reinitrand[counter=randomseed, seed=\seed, first=1, last=\lengthof{answeroptions}]
				\rand
				
				\def\answeroption{\nthof{\therandomseed}{answeroptions}}
				\answeroption
				
				% Pick one from that list
				%\pgfmathrandomitem{\answeroption}{answeroptions}\answeroption
  				
  				% place in the new list
  				\xdef\myshuffle{\myshuffle\ifnum\x>1,\fi\answeroption}                
  				
  				% Delete that entry
				\StrSubstitute{\answeroptions}{{\answeroption}}{}[\sublist]    
				
				% Update the main list
 				\global\let\answeroptions\sublist                           
  
				% Redefine the list				
				\pgfmathdeclarerandomlist{answeroptions}{\answeroptions}
			}
		\end{answers}
	}