Java(3 分)

Java(3 分)

我们有一个用于考试的合作设计模板。缺点是,我们必须手动计算每个任务的分数。我的想法是使用计数器自动计算。

我正在寻找:

\task{Java}
Hello World \points{2}
for-each \points{1}

\task{C++}
Bla bla \points{2}
Blub blub \points{4}

\task{Latex}
Foo foo \points{2}
bar bar \points{2}

我想要一个编译后如下所示的文档:


Java(3 分)

你好,世界(2 分)

for-each(1 分)

C++(6 分)

啦啦啦(2 分)

Blub blub (4 分)

乳胶(4 分)

Foo foo(2 分)

酒吧 酒吧 (2 分)


我的想法是在 -command 中创建一个计数器,并在 -command 中将\task其与 -command 一起使用。实际上,我没能动态更改每个计数器的名称。\addtocounter\points

这里是从我们的模板中提取的 MWE,我们在 `\task`` 命令中手动计算点数:

\documentclass[12pt,oneside,a4paper,final]{scrartcl}

\newcounter{task}
\setcounter{task}{0}

\newcommand{\points}[1]{
    (#1~Points)
}

\newcommand{\task}[2]{
    \refstepcounter{task}
    \begin{flushleft}
        {\LARGE\bf Task \arabic{task}}
    \end{flushleft}
    {\Large \textbf{#1}}
    \leavevmode\hfill ({#2}~Points)\\
}

\begin{document}

    \task{Java}{3}

    Hello World \points{2}

    for-each \points{1}

    \task{C++}{5}

    Bla bla \points{2}

    Blub blub \points{4}

    \task{Latex}{4}

    Foo foo \points{2}

    bar bar \points{2}

\end{document}

从:https://github.com/boldt/tex.stackexchange.com-186897/blob/master/exam.tex

答案1

看起来用户 cslstr 和我有相同的想法 ;-) 我使用了我以前的问题中更改的命令将标签写入文件.aux,然后使用 读取它\nameref*

然而,如果在环境内部,任务的结束就会容易得多。

\documentclass[12pt,oneside,a4paper,final]{scrartcl}
\usepackage{nameref}

\newcounter{task}
\setcounter{task}{0}


\newcounter{creditspertask}[task]
\setcounter{creditspertask}{0}%

\newcommand{\points}[1]{
    (#1~Points)
\addtocounter{creditspertask}{#1}%
}


\makeatletter
\newcommand{\WriteCreditsToFile}[1]{%
\immediate\write\@auxout{%
\string\newlabel{credits::\number\value{task}}{{\thesection}{\thepage}{#1}{}}
}% End of writing to AUX file
}%
\makeatother


\AtEndDocument{% For the last one only
\WriteCreditsToFile{\number\value{creditspertask}}%
}%

% 

\newcommand{\task}[1]{
  \WriteCreditsToFile{\number\value{creditspertask}}
    \refstepcounter{task}
    \begin{flushleft}
        {\LARGE\bfseries Task \arabic{task}}
    \end{flushleft}
    {\Large \textbf{#1}}
    \leavevmode\hfill ({\nameref*{credits::\number\value{task}}}~Points)\\
}

\begin{document}

    \task{Java}

    Hello World \points{2}

    for-each \points{1}

    \task{C++}

    Bla bla \points{2}

    Blub blub \points{4}

    \task{Latex}

    Foo foo \points{2}

    bar bar \points{2}

\end{document}

编辑更新版本,并附0.5有积分,也是可能的和基本的\listofcredits

\documentclass[12pt,oneside,a4paper,final]{scrartcl}
\usepackage{nameref}
\usepackage{calculator}%
\usepackage{calc}%
\usepackage{totcount}%
\usepackage{forloop}


\newcounter{task}
\setcounter{task}{0}


\xdef\TotalCredits{0}%
\xdef\TaskCredits{0}%
\xdef\SubCredits{0}%

\newcommand{\points}[2]{
\item #1   (#2~Points)
\ADD{\TaskCredits}{#2}{\SubCredits}%
\xdef\TaskCredits{\SubCredits}%
}%


\makeatletter
\newcommand{\WriteCreditsToFile}[1]{%
\immediate\write\@auxout{%
\string\newlabel{credits::\number\value{task}}{{\thesection}{\thepage}{#1}{}}
}% End of writing to AUX file
}%
\makeatother
%

\makeatletter
\AtEndDocument{%
\immediate\write\@auxout{%
\string\newlabel{totalcredits}{{\thesection}{\thepage}{\TotalCredits}{}}
}
}
\makeatother


\newenvironment{Task}[1]{%
\xdef\TaskCredits{0}%
\xdef\SubCredits{0}%
\xdef\CreditsSoFar{0}%
    \refstepcounter{task}
    \begin{flushleft}
        {\LARGE\bfseries Task \arabic{task}}
    \end{flushleft}
    {\Large \textbf{#1}}
    \leavevmode\hfill ({\nameref*{credits::\number\value{task}}}~Points)\\
    \begin{itemize} % Just for 'better' typography
}{% Close it
\end{itemize}
\WriteCreditsToFile{\TaskCredits}%
% Count all credits for the summary%
\ADD{\TotalCredits}{\TaskCredits}{\CreditsSoFar}%
\xdef\TotalCredits{\CreditsSoFar}%
}%


\regtotcounter{task}%

\makeatletter%

\newcounter{loop@@counter}%

\newcounter{totaltask@@counter}%
\newcommand{\listofcredits}{%
\setcounter{totaltask@@counter}{\number\totvalue{task}+1}%
\begin{tabular}{lll}
Task number & Total credits & Achieved\tabularnewline
\hline
\forloop{loop@@counter}{1}{\number\value{loop@@counter} < \number\value{totaltask@@counter}}{%
Task \number\value{loop@@counter} & \nameref*{credits::\number\value{loop@@counter}} & \tabularnewline% 
} %
& \tabularnewline
\hline
\multicolumn{1}{r}{Total:} & \nameref*{totalcredits} & \tabularnewline%
\end{tabular}
}%
\makeatother


\begin{document}

\listofcredits
\newpage

    \begin{Task}{Java}
      \points{Hello World}{2.5}
      \points{for-each}{2}
  \end{Task}%

    \begin{Task}{C++}
     \points{Bla bla}{2}
     \points{blub blub}{4}
    \end{Task}

    \begin{Task}{Latex}
     \points{Foo}{2}
     \points{bar}{2}
    \end{Task}

\begin{Task}{Fortran54} % ;-)
  \points{Write a Fortran 54 code to  \LaTeX ;-)}{100}
  \points{Write a Babbage machine  code to replace \LaTeX ;-)}{1000}
\end{Task}




\end{document}

编辑新版本

由于\nameref*{}不可扩展,因此必须使用另一种方法进行总结等。新版本将每个任务的总积分写入外部文件,然后再次读取该文件以完成顶部位置和命令的总任务积分\listoftask

代码

  • 如果所有任务都写入\jobname.credits文件则有效
  • 如果有真实数字而不是学分的数学表达式,则有效

  • 需要运行

  • 不适用于按部分任务编号

  • 如果在某处添加了另一个任务,则会失败,因为\jobname.credits仅在第一次运行期间写入。在这种情况下,删除\jobname.aux\jobname.credits,然后再次运行两次。

当然,我无法检查所有内容,输出格式等只是一个主张,我从 OP 答案中借用了代码,这是对我的第一个版本的直接反应,所以我认为这是可以的。

\documentclass[paper=a4,12pt]{scrbook}

\usepackage{calculator}
\usepackage{morewrites}

\usepackage{etoolbox}%
\usepackage{xcolor}%
\usepackage{calc}%
\usepackage{forloop}%
\usepackage{totcount}%
\usepackage{ifthen}%
\usepackage{tikz}%




\newwrite\CreditsFileHandle%

\newcounter{NumberOfLaTeXRuns}%
\newcommand{\WriteFileThreshold}{2}%


\newcommand{\CounterValue}[1]{%
\ifltxcounter{#1}{%
\number\value{#1}}{%
#1}%
}%



\xdef\tempsum{0}%
\xdef\othersum{0}%

\newcommand{\sumup}[1]{%
\ADD{\tempsum}{#1}{\othersum}%
\xdef\tempsum{\othersum}%
}%


\makeatletter

\newcommand{\WriteToFile}[2][\CreditsFileHandle]{%
\immediate\write#1{%
#2%
}%
}%


\newcommand{\CloseForReading}[1][\CreditsFileHandle]{%
\immediate\closein#1%
}%

\newcommand{\CloseForWriting}[1][\CreditsFileHandle]{%
\immediate\closeout#1%
}%


\newcommand{\OpenForReading}[2][\CreditsFileHandle]{%
\immediate\openin#1=#2%
}%

\newcommand{\OpenForWriting}[2][\CreditsFileHandle]{%
\immediate\openout#1=#2%
}%





\xdef\@@TotalCreditsValue{1}%
\listgadd{\CreditsSumList}{}%

\newcommand{\DisplayQuestionAndCredits}[2]{%
\item #1 (\DisplayCredits{#2})% 
\listgadd{\CreditsSumList}{#2}%
}%


\newcommand{\CreditsName}{point}%
\newcommand{\CreditsNamePlural}{points}%

\newcommand{\DisplayCredits}[1]{%
\pgfmathequal{#1}{1}%
\ifnumequal{\pgfmathresult}{1}{
#1 \CreditsName%
}{%
#1 \CreditsNamePlural%
}%%
}%



\newcommand{\ReadCreditValueWithSumUp}[2][\CreditsFileHandle]{%
\ReadCreditValue[#1]{#2}%
#2\sumup{#2}%
}%

\newcommand{\ReadCreditValue}[2][\CreditsFileHandle]{%
\read#1 to #2% Read in from file
}%



\newcounter{task}%
\newenvironment{Task}[1]{%
\refstepcounter{task}%
\ifnumequal{\CounterValue{NumberOfLaTeXRuns}}{\WriteFileThreshold}{%
\ReadCreditValue{\@@TotalCreditsValue}%
}{}%
\begin{flushleft}
{\Large \textbf{Task} \textbf{\thetask} -- \textbf{#1}}%%
\hfill  \fcolorbox{black}{yellow}{\DisplayCredits{\@@TotalCreditsValue}}% 
\end{flushleft}%
\begin{itemize}
}{%
\end{itemize}
\ifnumless{\CounterValue{NumberOfLaTeXRuns}}{\WriteFileThreshold}{%
%Do only sum up when not in final output mode 
\sumuplist{\CreditsSumList}%
\WriteToFile{\tempsum}%
}{% No, the number of runs is greater than zero, so ... do nothing
}% 
\xdef\CreditsSumList{}%
}%



\newcommand{\sumuplist}[1]{%
\xdef\tempsum{0}%
\forlistloop{\sumup}{#1}%
}%




\regtotcounter{task}%
\newcounter{totaltask@@counter}%
\newcounter{last@@counter}%
\newcounter{loop@@counter}%


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





\newcommand{\listoftasks}{%
\gdef\CurrentSumValue{0.0}%
\IfFileExists{\jobname.credits}{%
\CloseForWriting% 
\OpenForReading{\jobname.credits}%
\begin{center}
  \setcounter{totaltask@@counter}{\number\totvalue{task}+1}%
  \setcounter{last@@counter}{\number\totvalue{task}}%
  \Huge \textbf{List of Tasks}\normalsize 

  \vspace{\baselineskip} %
  \begin{tabular}{|c||r|c|c|}
    \hline
    Task number & Total credits & Achieved credits\\
    \hline
    \hline
    \forloop{loop@@counter}{1}{\CounterValue{loop@@counter} < \CounterValue{totaltask@@counter}}{%
      \CounterValue{loop@@counter} & %
      \ReadCreditValueWithSumUp{\CurrentSumValue}% Do not delete that % character before!
      & %
      \ifnum\number\value{loop@@counter}<\CounterValue{last@@counter}%  %\number\value{last@@counter}
      \tabularnewline\hline
      \fi%
      \xdef\CurrentSumValue{0}%
    }%
    \tabularnewline%
    \hline%
    \hline\hline%
    \multicolumn{1}{|l||}{Total:} & \tempsum & \tabularnewline%
    \hline%
  \end{tabular}%
\end{center}%
\newpage% Well, later an \clearpage?
% Now close the handle than open it again for reading total values in the individual tasks to complete
%the values.
\CloseForReading%
\OpenForReading{\jobname.credits}%
}{}%
}%



\AtBeginDocument{%
  \refstepcounter{NumberOfLaTeXRuns}%
  \ifnumequal{\CounterValue{NumberOfLaTeXRuns}}{\WriteFileThreshold}{%
    \CloseForWriting%
    \OpenForReading{\jobname.credits}%
  }{%
    \OpenForWriting{\jobname.credits}%
  }%
}%

\AtEndDocument{%
  \immediate\closeout\CreditsFileHandle%
  \ifnumequal{\CounterValue{NumberOfLaTeXRuns}}{\WriteFileThreshold}{%
    \setcounter{NumberOfLaTeXRuns}{1}}{}%
  \immediate\write\@auxout{%
    \string\setcounter{NumberOfLaTeXRuns}{\number\value{NumberOfLaTeXRuns}}%
  }%
}%
\makeatother


\begin{document}


\listoftasks


\begin{Task}{Java}%
\DisplayQuestionAndCredits{Hello World in Java}{10}%
\end{Task}%


\begin{Task}{C++}%
\DisplayQuestionAndCredits{Virtual methods}{10}%
\DisplayQuestionAndCredits{Operator overloading}{15}%
\end{Task}%

\begin{Task}{\LaTeXe}
\DisplayQuestionAndCredits{Reproduce this document ;-)}{2000}%
\DisplayQuestionAndCredits{Are there better sites than TeX.SX?}{10000.14159}%
\end{Task}


\begin{Task}{Fortran 54}
\DisplayQuestionAndCredits{Write a Fortran program better than \LaTeXe }{100}
\DisplayQuestionAndCredits{Write code for a Babbage machine with objects}{200}
\end{Task}


\end{document}

在此处输入图片描述

在此处输入图片描述

答案2

使用当前版本的exsheets该包提供了这种可能性。exsheets有一个命令\addpoints可以打印保存当前环境的分数{question}。问题的分数总和可用作问题属性可以points通过以下方式检索\GetQuestionProperty{<property>}{<question ID>}

结合exsheets“创建自定义标题实例的可能性”和命令,\CurrentQuestionID可以定义一种标题类型,打印正文\addpoints中保存的点的总和{question}

\documentclass{article}
\usepackage{exsheets}

% custom headings instance:
\DeclareInstance{exsheets-heading}{custom}{default}{
  % write the sum of points after the title of the question:
  title-post-code =
    \bfseries~(\GetQuestionProperty{points}{\CurrentQuestionID} Points) ,
  % print the title:
  attach = { main[l,vc]title[l,vc](0pt,0pt) }
}

% use the newly defined heading instance:
\SetupExSheets{
  headings = custom ,
  points/name = Point/s
}

\begin{document}

\begin{question}[name=Java]
  \begin{enumerate}
    \item Hello World (\addpoints{2})
    \item for-each (\addpoints{1})
  \end{enumerate}
\end{question}

\begin{question}[name=C++]
  \begin{enumerate}
    \item Bla bla (\addpoints{2})
    \item Blub blub (\addpoints{4})
  \end{enumerate}
\end{question}

\begin{question}[name=\LaTeX]
  \begin{enumerate}
    \item Foo foo (\addpoints{2})
    \item bar bar (\addpoints{2})
  \end{enumerate}
\end{question}

\end{document}

在此处输入图片描述

间距看起来有点奇怪,但可以进行调整,例如,通过添加below = .5\baselineskip标题实例的定义。


使用更新的版本exsheets(v0.14 2014/06/28,已经在 CTAN 和 TeX Live 2014 中),只需稍加努力就可以定义分级表。诀窍是使用问题属性。为此,我使用已由定义的属性subtitlecounter和。命令和}我循环遍历所有问题并检索所需的数据:pointsexsheets\GetQuestionProperty{<property>}{<question id>}\ForEachQuestion{<code where #1 refers to the question id>

\documentclass{article}
\usepackage{exsheets}[2014/06/28]

% a custom headings instance that uses the `subtitle' property:
\DeclareInstance{exsheets-heading}{custom}{default}{
  subtitle-format = \bfseries ,
  subtitle-post-code =
    \bfseries~(\GetQuestionProperty{points}{\CurrentQuestionID} Points) ,
  join = {
    title[r,B]number[l,B](.333em,0pt) ;
    title[r,B]subtitle[l,B](.333em,0pt)
  } ,
  attach = { main[l,vc]title[l,vc](0pt,0pt) } ,
  below  = .5\baselineskip
}

% use the new instance, other settings:
\SetupExSheets{
  question/name = Task ,
  headings = custom ,
  points/name = Point/s
}

% define a grading table that retrieves subtitles and points:
\newcommand*\gradingtable{%
  \begin{tabular}{|l|*{3}{c|}c|}\hline
    Task &
      \ForEachQuestion{%
        \GetQuestionProperty{counter}{##1}
        \GetQuestionProperty{subtitle}{##1}\iflastquestion{}{&}%
      }
      & Total \\ \hline
    Points   &
     \ForEachQuestion{\GetQuestionProperty{points}{##1}\iflastquestion{}{&}} &
       \pointssum* \\ \hline
    Reached  &
      \ForEachQuestion{\iflastquestion{}{&}} &
      \\ \hline
  \end{tabular}%
}

\begin{document}

\begin{center}
  \gradingtable
\end{center}

\begin{question}[subtitle=Java,ID=Java]
  \begin{enumerate}
    \item Hello World (\addpoints{2})
    \item for-each (\addpoints{1})
  \end{enumerate}
\end{question}

\begin{question}[subtitle=C++,ID=C++]
  \begin{enumerate}
    \item Bla bla (\addpoints{2})
    \item Blub blub (\addpoints{4})
  \end{enumerate}
\end{question}

\begin{question}[subtitle=\LaTeX,ID=LaTeX]
  \begin{enumerate}
    \item Foo foo (\addpoints{2})
    \item bar bar (\addpoints{2})
  \end{enumerate}
\end{question}

在此处输入图片描述

答案3

此答案利用现有的\labeling 功能将总数写入辅助文件。然后可以在\ref{}需要的地方使用标签值。

正如评论中提到的那样,需要两次传递才能正常工作。

还要注意,\AtEndDocument用于调用最终\closetask命令。如果您从不使用,这可能会导致问题\task...这可以放入带有在第一次使用时设置的标志的条件中\task,也\task可以变成使用的环境\begin{task}...\end{task}。使用环境实际上可能在语义上更有意义,尽管子任务不会得到开箱即用的支持。

\documentclass[12pt,oneside,a4paper,final]{scrartcl}

\newcounter{task}
\setcounter{task}{0}

% Create a new counter to keep track of points for each task
\newcounter{taskpoints}
\setcounter{taskpoints}{0}

% Create \pointslabel{}{} for saving the points total as a label
\makeatletter
\@ifpackageloaded{hyperref}{%
\newcommand{\pointslabel}[2]{%
   \protected@write \@auxout {}{\string \newlabel {#1}{{#2}{\thepage}{#2}{#1}{}} }%
   \hypertarget{#1}{#2}
}}{%
\newcommand{\pointslabel}[2]{%
\protected@write \@auxout {}{\string \newlabel {#1}{{#2}{}}}}}
\makeatother

% Call \closetask at the end of each task, before beginning next task
\def\closetask{%
\pointslabel{taskpoints:\arabic{task}}{\arabic{taskpoints}}}
\AtEndDocument{\closetask} % Automatically close the last task

% Reset the taskpoints whenever the task increments
\usepackage{chngcntr}
\counterwithin{taskpoints}{task}


\newcommand{\points}[1]{
    % Add #1 points to the taskpoints counter
    \addtocounter{taskpoints}{#1}
    (#1~Points)
}

\newcommand{\task}[1]{
    \closetask % Close out previous task
    \refstepcounter{task}
    \begin{flushleft}
        {\LARGE\bf Task \arabic{task}}
    \end{flushleft}
    {\Large \textbf{#1}}
    % Addition of points with \ref to label
    \leavevmode\hfill (\ref{taskpoints:\arabic{task}} Points)\\
}

\begin{document}

    \task{Java}

    Hello World \points{2}

    for-each \points{1}

    \task{C++}

    Bla bla \points{2}

    Blub blub \points{4}

    \task{Latex}

    Foo foo \points{2}

    bar bar \points{2}


\end{document}

答案4

这个改进的版本基于 Christian Huper 的回答:

  • 它有一个更精美的表格来打印任务列表(修复了表格中的换行)
  • 它打印的是“1 point”而不是“1 points”

\documentclass[12pt,oneside,a4paper,final]{scrartcl}
\usepackage{nameref}
\usepackage{calculator}%
\usepackage{calc}%
\usepackage{totcount}%
\usepackage{forloop}
\usepackage{tikz}

\newcounter{task}
\setcounter{task}{0}


\xdef\TotalCredits{0}%
\xdef\TaskCredits{0}%
\xdef\SubCredits{0}%

\newcommand{\printpoints}[1]{#1~\pgfmathequal{#1}{1}\ifnum\pgfmathresult=1 point\else points\fi}

\newcommand{\points}[2]{
\item #1 (\printpoints{#2})
\ADD{\TaskCredits}{#2}{\SubCredits}%
\xdef\TaskCredits{\SubCredits}%
}%


\makeatletter
\newcommand{\WriteCreditsToFile}[1]{%
\immediate\write\@auxout{%
\string\newlabel{credits::\number\value{task}}{{\thesection}{\thepage}{#1}{}}
}% End of writing to AUX file
}%
\makeatother
%

\makeatletter
\AtEndDocument{%
\immediate\write\@auxout{%
\string\newlabel{totalcredits}{{\thesection}{\thepage}{\TotalCredits}{}}
}
}
\makeatother


\newenvironment{Task}[1]{%
\xdef\TaskCredits{0}%
\xdef\SubCredits{0}%
\xdef\CreditsSoFar{0}%
    \refstepcounter{task}
    \begin{flushleft}
        {\LARGE\bfseries Task \arabic{task}}
    \end{flushleft}
    {\Large \textbf{#1}}
    \leavevmode\hfill (\nameref*{credits::\number\value{task}}~Points)\\
    \begin{itemize} % Just for 'better' typography
}{% Close it
\end{itemize}
\WriteCreditsToFile{\TaskCredits}%
% Count all credits for the summary%
\ADD{\TotalCredits}{\TaskCredits}{\CreditsSoFar}%
\xdef\TotalCredits{\CreditsSoFar}%
}%


\regtotcounter{task}%

\makeatletter%

\newcounter{loop@@counter}%

\newcounter{totaltask@@counter}%
\newcounter{last@@counter}%

\newcommand{\listoftasks}{%
    \begin{center}
    \setcounter{totaltask@@counter}{\number\totvalue{task}+1}%
    \setcounter{last@@counter}{\number\totvalue{task}}%
    \begin{tabular}{|c||r|c|c|}
    \hline
    Task number & Total credits & Achieved credits\\
    \hline
    \hline
    \forloop{loop@@counter}{1}{\number\value{loop@@counter} < \number\value{totaltask@@counter}}{
        \number\value{loop@@counter} & \nameref*{credits::\number\value{loop@@counter}} Points &
        \ifnum\number\value{loop@@counter}<\number\value{last@@counter}
            \tabularnewline\hline
        \fi
    }
    \tabularnewline
    \hline
    \hline\hline
    Total: & \nameref*{totalcredits} Points & \tabularnewline%
    \hline
    \end{tabular}
    \end{center}
}%

\makeatother


\begin{document}

\listoftasks
\newpage

    \begin{Task}{Java}
      \points{Hello World}{1}
  \end{Task}%

    \begin{Task}{C++}
      \points{for-each}{0.5}
     \points{blub blub}{0.5}
    \end{Task}

    \begin{Task}{Latex}
     \points{Foo}{2}
     \points{bar}{2}
    \end{Task}

\begin{Task}{Fortran54} % ;-)
  \points{Write a Fortran 54 code to  \LaTeX ;-)}{100}
  \points{Write a Babbage machine  code to replace \LaTeX ;-)}{1000}
\end{Task}

\end{document}

相关内容