diff options
author | Karl Berry <karl@freefriends.org> | 2017-12-28 00:27:05 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-12-28 00:27:05 +0000 |
commit | 406a9917ddb39261b7b5e712eae26d9cb9719531 (patch) | |
tree | c3b3fc2bc240bf5a60dfa9b5b3757e0aff3bb325 /Master/texmf-dist/doc/latex/mcexam | |
parent | 857e62559a016c0a5df2da631a430afc57cdc4a4 (diff) |
mcexam (27dec17)
git-svn-id: svn://tug.org/texlive/trunk@46155 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/latex/mcexam')
-rw-r--r-- | Master/texmf-dist/doc/latex/mcexam/README.md | 2 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/mcexam/mcexam.pdf | bin | 226175 -> 229715 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/mcexam/mcexam.tex | 44 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/mcexam/mcexam_example.r | 118 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/mcexam/mcexam_example.tex | 13 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/mcexam/mcexam_example_dataset.r | 42 |
6 files changed, 168 insertions, 51 deletions
diff --git a/Master/texmf-dist/doc/latex/mcexam/README.md b/Master/texmf-dist/doc/latex/mcexam/README.md index 25b7148e087..1170e6f689a 100644 --- a/Master/texmf-dist/doc/latex/mcexam/README.md +++ b/Master/texmf-dist/doc/latex/mcexam/README.md @@ -1,4 +1,4 @@ -mcexam package v0.3 +mcexam package v0.4 The mcexam package is a LaTeX package that automatically randomly permutes the order of questions and answer options in different versions of a multiple choice exam/test. Next to the exam versions themselves, the package also allows printing a concept version of the exam, a key table with the correct answers or points, and a document with solutions and explanation per exam version. The package also allows writing an R code which processes the results of the exam and calculates the grades. diff --git a/Master/texmf-dist/doc/latex/mcexam/mcexam.pdf b/Master/texmf-dist/doc/latex/mcexam/mcexam.pdf Binary files differindex ce0ee651f84..c5ec1775362 100644 --- a/Master/texmf-dist/doc/latex/mcexam/mcexam.pdf +++ b/Master/texmf-dist/doc/latex/mcexam/mcexam.pdf diff --git a/Master/texmf-dist/doc/latex/mcexam/mcexam.tex b/Master/texmf-dist/doc/latex/mcexam/mcexam.tex index c903a4d92d6..c97e86f3a87 100644 --- a/Master/texmf-dist/doc/latex/mcexam/mcexam.tex +++ b/Master/texmf-dist/doc/latex/mcexam/mcexam.tex @@ -656,6 +656,50 @@ in the preamble of your script file. + + + + + + + + + + + + + + + + + +\section{Revision History} + + +\subsection{Versions} + +\begin{description} + +\item[2017/05/02 v0.3:] First published version. + +\item[2017/12/26 v0.4:] Added \texttt{pgffor} package to fix bug. + +\end{description} + + + +\subsection{Planned modifications} + +\begin{itemize} + \item Add an error message when you only have one question and the option randomizequestions=true. Now, you should change this option explicitly to randomizequestions=false for one question. + \item Find an alternative for longtable which is now the default for tables in the package. Longtable doesn't work with twocolumn. + \item Add a function to reproduce the questions in another permutation/version within the same document. + \item Add the option to continue the question counter over several mcquestions environments. +\end{itemize} + + + + diff --git a/Master/texmf-dist/doc/latex/mcexam/mcexam_example.r b/Master/texmf-dist/doc/latex/mcexam/mcexam_example.r new file mode 100644 index 00000000000..736cd501616 --- /dev/null +++ b/Master/texmf-dist/doc/latex/mcexam/mcexam_example.r @@ -0,0 +1,118 @@ +mcprocessanswers <- function(ID,versions,answers,path=getwd()) { + +tol <- .Machine$double.eps^0.5 +if(! is.numeric(answers)) stop("non-numeric value(s) in answers, mcprocessanswers stopped") +if(min(answers > tol)==0) stop("non-positive value(s) in answers, mcprocessanswers stopped") +if(min(abs(answers - round(answers)) < tol)==0) stop("non-integer value(s) in answers, mcprocessanswers stopped") +if(! is.numeric(versions)) stop("non-numeric value(s) in versions, mcprocessanswers stopped") +if(min(versions > tol)==0) stop("non-positive value(s) in versions, mcprocessanswers stopped") +if(min(abs(versions - round(versions)) < tol)==0) stop("non-integer value(s) in versions, mcprocessanswers stopped") +if(min(versions-4< tol)==0) stop("value(s) in versions too large, maximum possible value is 4, mcprocessanswers stopped") + +questiondictionary=list(c(11,3,14,15,16,17,12,2,6,4,7,8,5,9,10,13,1),c(8,10,3,4,5,15,11,16,2,12,7,6,17,9,1,13,14),c(7,11,8,9,10,3,1,15,4,2,12,17,16,13,14,5,6),c(13,12,3,4,5,9,2,11,16,17,14,15,1,6,7,8,10)) + +randomizedanswersdictionary=list( + list(c(3,1,2,4,5),c(3,4,1,2),c(4,1,2,3),c(1,2,3,4,5),c(2,1,3,4),c(2,1,4,3),c(4,1,3,2),c(4,3,2,1),c(3,4,1,2),c(4,3,2,1),c(4,2,1,3),c(4,3,1,2),c(4,3,2,1),c(4,3,2,1),c(2,4,1,3),c(1,2,3,4),c(1,2)) + ,list(c(4,3,1,2,5),c(3,4,2,1),c(1,2,3,4),c(5,4,3,2,1),c(1,2,3,4),c(3,4,1,2),c(2,1,3,4),c(4,3,2,1),c(2,1,3,4),c(4,3,2,1),c(3,1,2,4),c(4,2,3,1),c(4,2,3,1),c(1,2,3,4),c(3,4,2,1),c(2,1,3,4),c(1,2)) + ,list(c(3,2,1,4,5),c(3,1,2,4),c(3,4,1,2),c(5,4,3,2,1),c(2,1,3,4),c(1,2,3,4),c(4,1,2,3),c(1,2,3,4),c(3,4,1,2),c(2,1,3,4),c(1,4,3,2),c(3,2,4,1),c(1,3,2,4),c(4,3,2,1),c(1,4,3,2),c(2,1,3,4),c(1,2)) + ,list(c(2,4,1,3,5),c(2,3,1,4),c(4,1,2,3),c(1,2,3,4,5),c(2,1,3,4),c(4,3,2,1),c(2,4,3,1),c(1,2,3,4),c(3,2,4,1),c(4,1,2,3),c(1,4,2,3),c(3,2,4,1),c(1,2,3,4),c(1,2,3,4),c(1,4,3,2),c(1,2,3,4),c(1,2)) + ) + +correctiondictionary=list(c(1,0,0,0,0),c(0,0,1,0),c(1,0,0,0),c(0,1,0,0,0),c(0,1,0,0),c(0,0,0,1),c(1,0,0,0),c(0,0,1,0),c(1,0,0,0),c(0,1,0,0),c(0,0,1,0),c(1,0,0,0),c(0,0,1,0),c(0,0,0,1),c(0,1,0,0),c(0,1,0,0),c(1,0)) + +Nversions=4; +Nquestions=17; +Nanswers=c(5,4,4,5,4,4,4,4,4,4,4,4,4,4,4,4,2); +Nstudents=nrow(answers); + +Q <- matrix(NA,nrow=Nstudents,ncol=Nquestions); +P <- matrix(NA,nrow=Nstudents,ncol=Nquestions); +for ( student in 1:Nstudents ){ + for (question in 1:Nquestions){ + R <- randomizedanswersdictionary[[versions[student]]][[question]]; + Q[student,question] <- R[answers[student,questiondictionary[[versions[student]]][question]]]; + P[student,question] <- correctiondictionary[[question]][Q[student,question]]; + P[student,question] <- ifelse(is.na(P[student,question]),0,P[student,question]); + }} +Points=apply(P,1,sum); +outputdata <- data.frame(ID=ID,versions=versions,originalQuestion=Q,pointsQuestion=P,total=Points); + +p <- apply(P,2,mean); +p.cor <- apply(P,2,mean) - (1-apply(P,2,mean))/(Nanswers-unlist(lapply(correctiondictionary,sum))); +r.cor <- NULL; +for (i in 1:Nquestions){ + r.cor[i] <- ifelse(var(P[,i])==0,0,cor(P[,i],apply(P[,-i],1,sum))); + } + +Nquestions.cor <- sum(apply(P,2,var)>0); +alpha <- (Nquestions.cor/(Nquestions.cor-1))*(1-(sum(apply(P,2,var))/var(Points))); + +outputfilename=file.path(path,"mcexam_example.ana"); +write("\\makeatletter",outputfilename) ; + +formatnumber <- function(x) { + y <- gsub("(?<![0-9.])0+","", sprintf("%.3f",x),perl = TRUE) + n <- nchar(y) + y <- gsub(" ","\\\\phantom{-}",y) + y <- paste0(strrep("\\phantom{0}",max(n)-n),y) + y + }; +write(c( + "\\gdef\\mc@questionAnalysisTable{", + " \\begin{setmcquestionanalysistable}", + " \\begin{longtable}{cccc}", + " & \\mc@babel@Proportion & \\mc@babel@Corrected & \\mc@babel@Item@rest \\\\", + " & \\mc@babel@correct & \\mc@babel@proportion & \\mc@babel@correlation \\\\", + " \\hline", + " \\mc@babel@Question \\\\", + " \\endhead", + " \\hline", + " \\endfoot", + " \\hline", + paste0(" \\multicolumn{4}{l}{\\mc@babel@Number@of@students\\ = ",Nstudents,"}\\\\"), + paste0(" \\multicolumn{4}{l}{Cronbach's alpha = ",sprintf("%.3f",alpha),"}\\\\"), + " \\endlastfoot ", + paste0(" \\setcounter{mc@counter}{",1:ncol(answers),"}\\mcquestionlabelfmt{mc@counter}& " + ,formatnumber(p)," & ",formatnumber(p.cor)," & ",formatnumber(r.cor)," \\\\"), + " \\end{longtable}", + " \\end{setmcquestionanalysistable}", + " }" + ),outputfilename,append=TRUE) ; + +versions.factor <- factor(versions); +levels(versions.factor) <- 1:Nversions; +for (i in 1:Nquestions) { + X <- factor(Q[,i],1:Nanswers[i]); + props <- cbind(prop.table(table(X,versions.factor,useNA="ifany"),2),prop.table(table(X,useNA="ifany"))); + dims <- dim(props); + props <- lapply(props,function(x) ifelse(is.na(x),"N.A.",gsub(" ","\\\\phantom{0}",paste0(sprintf("%5.1f",x*100),"\\%")))); + dim(props) <- dims; + props <- apply(props, 1, paste, collapse=" & "); + labels <- paste0(" \\setcounter{mc@counter}{",1:Nanswers[i],"}\\mcanswerlabelfmt{mc@counter}"); + labels <- ifelse(is.na(labels[1:dims[1]])," invalid",labels[1:dims[1]]) +write(c( + paste0("\\csgdef{mc@answerAnalysisTable",i,"}{"), + paste0(" \\begin{tabular}{c",strrep("c",Nversions),"c}"), + paste0(" \\multicolumn{1}{r}{\\mc@babel@Version}&" + ,paste(paste0("\\setcounter{mc@counter}{",1:Nversions, + "}\\mcversionlabelfmt{mc@counter}"),collapse="&") + ," & \\mc@babel@total \\\\"), + " \\hline", + " \\mc@babel@Answer \\\\", + paste0(labels," & ",props,"\\\\"), + " \\hline", + paste0(" \\multicolumn{",Nversions+2,"}{l}{\\mc@babel@Proportion@correct\\ = ", + sprintf("%.3f",p[i]),"}\\\\"), + paste0(" \\multicolumn{",Nversions+2,"}{l}{\\mc@babel@Corrected@proportion\\ = ", + sprintf("%.3f",p.cor[i]),"}\\\\"), + paste0(" \\multicolumn{",Nversions+2,"}{l}{\\mc@babel@Item@rest@correlation\\ = ", + sprintf("%.3f",r.cor[i]),"}\\\\"), + " \\end{tabular}", + " }" + ),outputfilename,append=TRUE) ; + } + +write("\\makeatother",outputfilename,append=TRUE) ; + +outputdata ; + } diff --git a/Master/texmf-dist/doc/latex/mcexam/mcexam_example.tex b/Master/texmf-dist/doc/latex/mcexam/mcexam_example.tex index 64b4c3a9176..dbd3e4866cc 100644 --- a/Master/texmf-dist/doc/latex/mcexam/mcexam_example.tex +++ b/Master/texmf-dist/doc/latex/mcexam/mcexam_example.tex @@ -12,9 +12,9 @@ \documentclass[a4paper]{article} -\usepackage[output=exam +\usepackage[output=concept ,numberofversions=4 - ,version=3 + ,version=1 ,seed=1 ,randomizequestions=true ,randomizeanswers=true @@ -38,11 +38,9 @@ \renewenvironment{setmcquestion}{\begin{minipage}[t]{\linewidth-\labelwidth}}{\end{minipage}\par} - - - + \begin{document} @@ -79,9 +77,9 @@ + - -\begin{mcquestions} +\begin{mcquestions} @@ -162,7 +160,6 @@ Questions \ref{ref1} to \ref{ref2} are about maths. \answer none of the above \end{mcanswerslist} - \question Which statement is correct? diff --git a/Master/texmf-dist/doc/latex/mcexam/mcexam_example_dataset.r b/Master/texmf-dist/doc/latex/mcexam/mcexam_example_dataset.r deleted file mode 100644 index 9fa54e062da..00000000000 --- a/Master/texmf-dist/doc/latex/mcexam/mcexam_example_dataset.r +++ /dev/null @@ -1,42 +0,0 @@ -### mcexam_example_dataset.r -### This code contains some test data for the example of mcexam. First run -### mcexam_example.tex through LaTeX, then process this file with R. Next, -### you can make an analysis version of the exam in LaTeX. Make sure the -### working directory is the folder where mcexam_example.tex resorts. -### -### Copyright (c) 2017 Jorre Vannieuwenhuyze. -### -### Permission is granted to copy, distribute and/or modify this -### software under the terms of the LaTeX Project Public License -### (LPPL), version 1.3c or any later version. -### -### This software is provided 'as is', without warranty of any kind, -### either expressed or implied, including, but not limited to, the -### implied warranties of merchantability and fitness for a -### particular purpose. - -rm(list = ls()) - -ID <- c(1,2,3,4,5,6,7,8,9,10) -versions <- c(1,1,1,2,2,2,2,3,3,3) -answers <- rbind(c(1,2,1,4,2, 3,4,3,1,1, 2,2,2,5,2, 1,3) #17 - ,c(1,1,2,4,3, 2,2,3,1,2, 2,3,2,5,2, 2,3) #9 - ,c(1,2,1,3,2, 3,4,2,1,1, 2,2,3,5,1, 1,3) #8 - ,c(3,2,5,4,2, 4,1,3,4,1, 2,3,1,1,2, 2,3) #11 - ,c(2,2,5,3,2, 3,1,2,4,2, 2,3,1,1,1, 2,3) #0 - ,c(3,2,5,4,2, 4,1,3,3,1, 2,2,1,1,2, 1,4) #7 - ,c(3,2,5,4,2, 3,1,3,4,2, 2,3,2,1,1, 2,1) #2 - ,c(2,1,4,2,1, 1,3,5,4,1, 1,3,1,4,3, 2,4) #6 - ,c(2,1,3,3,1, 1,3,5,4,1, 1,2,1,4,3, 2,4) #11 - ,c(1,1,3,3,2, 1,2,5,4,3, 2,3,4,3,3, 1,3) #4 - ) - -source("mcexam_example.r") -data <- mcprocessanswers(ID,versions,answers) - - - - - - -
\ No newline at end of file |