答案1
下面定义了一个question
环境,它将使用键检查其 key=value 输入date
,points
并将它们与您可以定义的一些过滤器列表进行比较。
过滤器列表接受键include
和exclude
。如果您使用include
不带值的,则初始行为是包含所有问题,如果您使用exclude
不带值的,则所有问题都将被排除。
include
和都exclude
接受一个值,该值可以包含points
和date
。您可以经常任意使用这些键,这将向筛选器列表添加规则。并且两者可以与=
(仅匹配的)、>=
(分数相等或更高/该日期或更晚的)和<=
(分数相等或更低/该日期或更早的)一起使用。作为特殊键,两者include
和exclude
都接受all
,这将清除筛选器列表并包含/排除所有问题。
如果你使用include
一个值前您使用的include
不带值或(带或不带)表示排除所有问题(除匹配给定值中的规则的问题外)。 (除匹配规则的问题外全部包括)exclude
也一样。exclude
例如
\questionFilter{exclude={points<=2, date<=2019-12-31}}
表示除给出 2 分或更少分数的问题,或早于 2020-01-01 的问题外,所有问题均包括在内。
如果您愿意,您还可以在文档中间更改过滤规则。
如果环境question
本身不符合过滤规则points
,则它会吞噬其内容date
。吞噬是通过将其内容排版到不输出的框中来完成的。
\question@start
您很可能希望根据您的需要定制代码\question@end
以获得所需的输出。
对于新问题,points
默认为 0,对于新问题,date
默认为 0000-00-00。
question
所有这些的结果是,无论是在文件中还是在主文档中都并不重要,因为排除是基于环境完成的。
\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}
答案2
使用包可以很容易地过滤问题dbshow
。带有日期和分数的问题将保存到名为的数据库中ques-db
。然后您可以使用自定义过滤器和样式显示它们。
\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}