0

I'm making Test sheet.
Let I have a lot of .tex files.
And each .tex files are consist of question, points, date.

For example,
file1.tex -> question, 1 point, 2020-1-01
file2.tex -> question, 1 point, 2020-1-12
file3.tex -> question, 2 point, 2021-2-12
file4.tex -> question, 2 point, 2021-3-3

What I want is making different version of test paper easily.
version 1 : only contains question
version 2 : only contains question which is 2 points.

file list
file1
file2

7
  • 2
    So the points should be contained in the file itself. What exactly is the format of your subfiles? Or can we decide which format we'd like?
    – Skillmon
    Commented Dec 4, 2021 at 9:06
  • Thanks for your comment. I think of file like this. \begin{question} question \end{question} point=3 date=2020-1-12
    – Dooly
    Commented Dec 4, 2021 at 9:13
  • May I suggest another format: \begin{question}[point=3,date=2020-1-12] ...\end{question}. This way the question environment can just evaluate its key=value list for point or date and act accordingly.
    – Skillmon
    Commented Dec 4, 2021 at 9:16
  • but I have no idea that my format is feasible. If you have some recommendations, I'm so grateful.
    – Dooly
    Commented Dec 4, 2021 at 9:18
  • Wow, your format is very simple and it fit to what I want. If you don't mind , could you show some example about conditional import??
    – Dooly
    Commented Dec 4, 2021 at 9:22

2 Answers 2

3

The following defines a question environment that will check its key=value input with the keys date and points and compare those to some filter list you can define.

The filter list accepts the keys include and exclude. If you use include without a value the initial behaviour is to include all questions, if you use exclude without a value all questions are excluded.

Both include and exclude accept a value as well, the value can contain points and date. You can use these keys arbitrary often, which will add a rule to the filter list. And both can be used with either = (just those matching), >= (those with equal or more points/that date or later), and <= (those with equal or less points/that date or earlier). As a special key both include and exclude accept all, which will clear the filter list and include/exclude all questions.

If you use include with a value before you used include without a value or exclude (with or without), this means that all questions are excluded except those matching the rules in the given value. The same is true for exclude (all included except those matching the rules).

So for instance

\questionFilter{exclude={points<=2, date<=2019-12-31}}

means that all questions are included except those giving two or less points, or those being older than 2020-01-01.

You can also change filter rules mid-document, if you want to.

The question environment itself will gobble its contents if its points and/or date don't match the filter rules. The gobbling is done by typesetting its contents into a box that isn't output.

You'll most likely want to tailor the code in \question@start and \question@end to your needs to get the output you want.

For new questions the points default to 0, and the date defaults to 0000-00-00.

The result of all of this is, that it doesn't matter whether a question is in a file or in your main document, since the exclusion is done on an environment basis.

\documentclass[]{article}

\usepackage{expkv-def}

\makeatletter
% initial values of internals
\let\question@\relax
\newcommand*\question@check@{}

% internals for the filter definition 
\newcommand\question@check[1]
  {%
    \edef\question@check@
      {%
        \unexpanded\expandafter{\question@check@#1}%
        {\unexpanded\expandafter{\question@action}}%
      }%
  }
\newcommand*\question@datetonum[1]
  {\numexpr\expandafter\question@datetonum@#1\relax}
\def\question@datetonum@#1-#2-{31*(12*#1+#2)+}
\newcommand*\question@check@points[4]
  {\ifnum\question@points#1#2 #3#4\fi}
\newcommand*\question@check@date[4]
  {\ifnum\question@datetonum\question@date#1\question@datetonum{#2} #3#4\fi}

% key=value setup for the filter
\ekvdefinekeys{qh23570filter-internal}
  {
     code  date    = \question@check{\question@check@date={#1}{}}
    ,code  date   >= \question@check{\question@check@date<{#1}\else}
    ,code  date   <= \question@check{\question@check@date>{#1}\else}
    ,code  points  = \question@check{\question@check@points={#1}{}}
    ,code  points >= \question@check{\question@check@points<{#1}\else}
    ,code  points <= \question@check{\question@check@points>{#1}\else}
    ,noval all     = \let\question@check@\@empty\question@action
  }
\ekvdefinekeys{qh23570filter}
  {
     noval include = \let\question@check@\@empty\let\question@\question@start
    ,code  include =
      \ifx\question@\relax\let\question@\question@remove\fi
      \def\question@action{\let\question@\question@start}%
      \questionFilter@{#1}%
    ,noval exclude = \let\question@check@\@empty\let\question@\question@remove
    ,code  exclude =
      \ifx\question@\relax\let\question@\question@start\fi
      \def\question@action{\let\question@\question@remove}
      \questionFilter@{#1}%
  }
\ekvletkv{qh23570filter-internal}{date>}  {qh23570filter-internal}{date >}
\ekvletkv{qh23570filter-internal}{date<}  {qh23570filter-internal}{date <}
\ekvletkv{qh23570filter-internal}{points>}{qh23570filter-internal}{points >}
\ekvletkv{qh23570filter-internal}{points<}{qh23570filter-internal}{points <}
\ekvsetdef\questionFilter{qh23570filter}
\ekvsetdef\questionFilter@{qh23570filter-internal}

% key=value setup for the environment
\ekvdefinekeys{qh23570question}
  {
     store   points = \question@points
    ,initial points = 0
    ,store   date   = \question@date
    ,initial date   = 0000-00-00
  }
\ekvsetdef\question@kv{qh23570question}
\newenvironment{question}[1][]
  {%
    \ifx\question@\relax
      \PackageError{question}{Initial behaviour unset. Defaulting to include}{}%
      \global\let\question@\question@start
    \fi
    \question@kv{#1}%
    \question@check@
    \question@
  }
  {\question@end}
\newcommand*\question@remove
  {%
    \setbox0\vbox\bgroup
    \edef\question@end{\unexpanded\expandafter{\question@end\egroup}}%
    \question@start
  }

% TODO: Add the start and end code you need for questions that are included here
\newcommand*\question@start{\par\bigskip\section{Question}}
\newcommand*\question@end{}
\makeatother

% just to create many questions with less effort
\newcommand\testquestion[2]
  {%
    \begin{question}[points=#1, date=#2]
      This is a question giving #1 points and created on #2.
    \end{question}
  }

% set the rules which questions are used
\questionFilter
  {
     include={points >= 2, points <= 0}
    ,exclude={points = 3, date <= 2020-10-09}
  }

\begin{document}
\begin{question}[points=15, date=2021-12-04]
  Does this answer your question?
\end{question}

% just to create many questions with less effort
\testquestion{0}{2020-10-08}
\testquestion{1}{2020-10-08}
\testquestion{2}{2020-10-08}
\testquestion{3}{2020-10-08}
\testquestion{4}{2020-10-08}
\testquestion{0}{2020-10-09}
\testquestion{1}{2020-10-09}
\testquestion{2}{2020-10-09}
\testquestion{3}{2020-10-09}
\testquestion{4}{2020-10-09}
\testquestion{0}{2020-10-10}
\testquestion{1}{2020-10-10}
\testquestion{2}{2020-10-10}
\testquestion{3}{2020-10-10}
\testquestion{4}{2020-10-10}
\end{document}

enter image description here

1
  • I couldn’t have done it without you. I really appreciate everything you’ve done. Thanks you so so much!!!
    – Dooly
    Commented Dec 4, 2021 at 13:08
0

It is easy to filter questions with the package dbshow. Questions with dates and points are save to a database named ques-db. Then you can display them with custom filters and styles.

enter image description here

\documentclass{article}
\usepackage{dbshow}

\dbNewDatabase{ques-db}{
  ques  = tl,
  date  = date,
  point = int,
}
\begin{dbFilters}{ques-db}
  \dbNewConditional{point-cond}{point}{\dbval > 2}
  \dbNewConditional {date-cond}{date} {\dbval > 2022/01/01}
\end{dbFilters}
\dbNewStyle{base-style}{ques-db}{
  before-code     = \section{All Questions},
  item-code       = {%
    \par\noindent\dbuse{date}~(\dbuse{point} points)
    \par\noindent\dbarabic.~\dbuse{ques},
  },
  item-after-code = \medskip,
}
\dbNewStyle[base-style]{point-style}{ques-db}{
  before-code = \section{Questions with Points Greater than 2},
  raw-filter  = point-cond,
}
\dbNewStyle[base-style] {date-style}{ques-db}{
  before-code = \section{Questions after 2022/01/01},
  raw-filter  = date-cond,
}
\dbNewStyle[base-style]  {mix-style}{ques-db}{
  before-code = \section{Questions with Mix Conditionals},
  raw-filter  = {point-cond && date-cond},
}

\begin{document}

\begin{dbitem}{ques-db}[date=2022/01/01, point=2]
  \dbsave{ques}{$x + y =$}
\end{dbitem}

\begin{dbitem}{ques-db}[date=2022/01/02, point=1]
  \dbsave{ques}{$z^2 =$}
\end{dbitem}

\begin{dbitem}{ques-db}[date=2022/01/03, point=3]
  \dbsave{ques}{$x / \alpha =$}
\end{dbitem}

\dbshow {base-style}{ques-db}
\dbshow{point-style}{ques-db}
\dbshow {date-style}{ques-db}
\dbshow  {mix-style}{ques-db}

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .