Collect duplicates of all environments of certain type

amsthmenvironmentstcolorboxthmtools

I'm writing a workbook for students with homework exercises and their solutions contained. For the ´´homework-exercise´´ and homework-exercise-solution I defined custom environments using amsthm.

Ultimately, I'm looking for a way to solve this my other question myself, by wrapping the ´´homework-exercise´´ and homework-exercise-solution into colorbox environments from tcolorbox package using the options invisible to have empty phantom boxes displayed by a custom package switch. (I'll answer my own question once I got everything more polished.)

Right now, this means that homework exercises and solutions are scattered throughout the workbook, which is okay since they are placed next to the relevant content.

However, I would like to additionaly print pages with duplicates of all the homework-exercise and homework-exercise-solution environments at the end of the document, to ensure students have a nice short overview over which tasks have to be done (and my tutors have a nice short way of checking the filled-in solution sheets).

How can I produce copies of all the environments of certain types, while keeping the numbers they were assigned on their first occurrance? (However, the labels of the duplicates must be adapted as to not rewrite references to the originally placed environments)

Attached is a MWE with a screenshot of the output produced
screenshot with options showsolutions

% 
% 
% 
\documentclass{article}

\begin{filecontents*}{testpackage.sty}
    \NeedsTeXFormat{LaTeX2e}
    \ProvidesPackage{mw88-script}[2021/08/25 LaTeX package for toggling solutions]
    
    \RequirePackage{tcolorbox}
    
    \newcommand{\visibility}{invisible}
    
    \DeclareOption{showsolutions}{\renewcommand{\visibility}{visible}}
    \DeclareOption*{\PackageWarning{examplepackage}{Unknown ‘\CurrentOption’}}
    \ProcessOptions\relax
    
    
    \tcolorboxenvironment{exercise-homework}{
    }
    \tcolorboxenvironment{exercise-homework-solution}{
    \visibility
    }
    \end{filecontents*}

\usepackage{mwe}
\usepackage{amssymb, amsmath, amsthm, mathtools}
% \usepackage{testpackage}
\usepackage[showsolutions]{testpackage}



\theoremstyle{plain}{
\newtheorem{exercise-homework}{Hausaufgabe}
}

\theoremstyle{plain}{
\newtheorem{exercise-homework-solution}{Lösung}
}
% 
% 
% 
\begin{document}
\section{This is the guided workflow}
    Here are explanatory things and prerequisites necessary to solve the exercise.
    \begin{exercise-homework}
        Show that $(\mathbb{R}, +, \cdot)$ is a field.
    \end{exercise-homework}

    \begin{exercise-homework-solution}%
        Let $a, b, c \in \mathbb{R}$ arbitrary. Then, we show the following properties:
        \begin{description}
            \item[Commutativity of addition]  $a + b = b+ a$.
            \item[Associativity of addition] $a +(b + c) = (a+b) +c$.
            \item[Additive identity] $0 \in \mathbb{R}$, and $a +0 = a $.
            \item[Additive inverse] for each $a \in \mathbb{R}$, there exists $-a \in \mathbb{R}$, sch that $a + (-a) = 0$.
            \item[Commutativity of multiplication] $a \cdot b = b \cdot a$.
            \item[Associativity of multiplications] $a \cdot (b \dot c) = (a \cdot b) \cdot c$.
            \item[Multiplicative identity] $1 \in \mathbb{R}$, such that $1 \cdot a = a$.
            \item[Multiplicative inverse] for each $a \in \mathbb{R}$, there exists $a^{-1}\in \mathbb{R}$, such that $a \cdot a^{-1} = 1$.      
            \item[Distributivity] $a\cdot (b + c) = (a \cdot b) + (a \cdot c)$. 
        \end{description}
        These are the necessary and sufficient properties of a field, hence $(\mathbb{R}, +, \cdot)$ is a field.
    \end{exercise-homework-solution}

    From here, the workbook content continues. There are going to be more exercises and solutions.

    \section*{Appendix}
        Here I want duplicates of the exercise and solutions from above.
\end{document}

The display of solution contents can be toggled within the package option.

Update 1:

Further investigation revealed, that I should be able to use the thm-restate package from thmtools to restate theorem-like environments. However, thm-restate does not play nicely with tcolorbox out of the box. See the MWE and attached screenshots below: The restated environment is not wrapped inside a tcolorbox.

\documentclass[a4paper]{article}

\usepackage{thmtools}
\usepackage{thm-restate}
\usepackage[dvipsnames]{xcolor}
\usepackage[many]{tcolorbox}





\declaretheorem[name=Exercise, style=remark]{exercise}
\tcolorboxenvironment{exercise}{colframe=red!75!black}

\begin{document}

\noindent We start using the {\ttfamily exercise}-environment:
\begin{exercise}[restate=restatekey]
  This is a demonstrational exercise.
\end{exercise}

\noindent and try to restate this:
\restatekey*

\noindent then follow it up with a {\ttfamily restatable}-environment
\begin{restatable}{exercise}{extest}\label{ex:test}
  This is a restatable exercise.
\end{restatable}


\noindent In the following, there's the restated {\ttfamily restatable}-exercise:
\extest*

MWE output for Update 1: colorbox is only wrapping around the original exercise environment, not the restated one and not the restatable environment

\end{document}

Best Answer

Solution in steps

Solving the missing tcolorbox around restatable-environments:

Thanks to the insightful answer on this only slightly related question, I was able to make restated restatable-environments share the tcolorbox keys with the original occurance:

\documentclass[a4paper]{article}

\usepackage{thmtools}
\usepackage{thm-restate}
\usepackage[dvipsnames]{xcolor}
\usepackage[many]{tcolorbox}

\makeatletter
\define@key{thmdef}{tcolorbox}[{}]{%
\thmt@trytwice{}{%
\RequirePackage{tcolorbox}%
\RequirePackage{thm-patch}%
\addtotheorempreheadhook[\thmt@envname]{%
\begin{tcolorbox}[#1]}%
\addtotheorempostfoothook[\thmt@envname]{\end{tcolorbox}}%
}%
}
\makeatother


\declaretheorem[name=Exercise,
style=remark,
tcolorbox={
    colframe={red!75!black},
    }]{exercise}


\begin{document}


\noindent A {\ttfamily restatable}-environment
\begin{restatable}{exercise}{extest}\label{ex:test}
This is a restatable exercise.
\end{restatable}


\noindent In the following, there's the restated {\ttfamily restatable}-exercise:
\extest*



\end{document}

The output looks like this: tcolorboxed restated theorem environments

You can, however, not use the following form to insert restatable environments:

\begin{exercise}[restate=restatekey]
    This is a demonstrational exercise.
\end{exercise}

\restatekey*

Put everything together into the final solution

I hope this helps others. My heavily commented MWE code

\begin{filecontents*}[overwrite]{testpackage.sty}
  \NeedsTeXFormat{LaTeX2e}
  \ProvidesPackage{testpackage}[2021/08/25 LaTeX package for toggling solutions]

  \RequirePackage{tcolorbox}
  \RequirePackage{ifthen}
  \RequirePackage{comment}
  \RequirePackage{environ}
  \RequirePackage{verbatim}


  % process the options regarding solution visibility
  \newcommand{\visibility}{visible}
  \DeclareOption{hidesolutions}{\renewcommand{\visibility}{hidden}}
  \DeclareOption{nosolutions}{\renewcommand{\visibility}{empty}}

  %  process all unknown options
  \DeclareOption*{\PackageWarning{testpackage}{Unknown ‘\CurrentOption’}}
  \ProcessOptions\relax


  % this is the colorbox fix from first part of the solution
  \define@key{thmdef}{tcolorbox}[]{%
    \thmt@trytwice{}{%
      \RequirePackage{tcolorbox}%
      \RequirePackage{thm-patch}%
      \addtotheorempreheadhook[\thmt@envname]{%
      \begin{tcolorbox}[#1]}%
      \addtotheorempostfoothook[\thmt@envname]{\end{tcolorbox}}%
      }%
    }

  %  define a list for storing the exercises
\def\exercises@list{}
%  define a list for storing the exercises with their solutions
\def\exercisesandsolutions@list{}
%  define a list for storing the exercises with their solutions set invivible
\def\exercisesandsolutionsinvisible@list{}
%  define a list to store only the solutions
\def\solutions@list{}

\newcounter{exercise@cnt}
\newcounter{solution@cnt}
%  define the exercise theorem environment (for inner use)
\declaretheorem[name={Exercise},numberwithin=section, tcolorbox={
  colframe={red!75!black},
  }]{thmexercise}
%  define the solution theorem environment (for inner use)
\declaretheorem[name={Solution},numberwithin=section, tcolorbox={
  colframe={black},
  }]{thmsolution}
  %  define the invisible solution theorem environment (for inner use)
\declaretheorem[name={Solution},numberwithin=section, tcolorbox={
  colframe={black},
  invisible
  }]{thmsolutionhidden}


%  define the actual exercise environment
\newenvironment{exercise}[1][]{%
  \stepcounter{exercise@cnt}%
  % fully expand the counter representation
  % before calling \restatable
  \begingroup\edef\x{\endgroup
    \noexpand\restatable[{#1}]{thmexercise}{exercise-\Alph{exercise@cnt}}%
  }\x
}{\endrestatable
  \xappto\exercises@list{%
    \expandafter\noexpand\csname exercise-\Alph{exercise@cnt}\endcsname*%
  }%
  % append the exercise also to all other relevant lists
  \xappto\exercisesandsolutions@list{%
    \expandafter\noexpand\csname exercise-\Alph{exercise@cnt}\endcsname*%
  }%
  \xappto\exercisesandsolutionsinvisible@list{%
    \expandafter\noexpand\csname exercise-\Alph{exercise@cnt}\endcsname*%
  }%
}

%  define the actual solution environment
\newenvironment{solution}[1][]{%
  \stepcounter{solution@cnt}%
  % fully expand the counter representation
  % before calling \restatable
  \def\x{}
  \ifthenelse{\equal{\visibility}{visible}}{
      \begingroup\edef\x{\endgroup
        \noexpand\restatable[{#1}]{thmsolution}{solution-\Alph{solution@cnt}}%
      }}{}

  \ifthenelse{\equal{\visibility}{hidden}}{
      \begingroup\edef\x{\endgroup
        \noexpand\restatable[{#1}]{thmsolutionhidden}{solution-\Alph{solution@cnt}}%
      }}{}

  \ifthenelse{\equal{\visibility}{empty}}{
    \setbox0\vbox\bgroup
  }{
    \x%
  }
}{
  \ifthenelse{{\equal{\visibility}{visible}}\OR{\equal{\visibility}{hidden}}}{
    \endrestatable
      \xappto\solutions@list{%
        \expandafter\noexpand\csname solution-\Alph{solution@cnt}\endcsname*%
      }%
      % append the exercise also to all other relevant lists
      \xappto\exercisesandsolutions@list{%
        \expandafter\noexpand\csname solution-\Alph{solution@cnt}\endcsname*%
      }%
    }{
      \egroup
    }
}



% define shortcuts for displaying the lists
\newcommand{\allexercises}{\exercises@list}
\newcommand{\allsolutions}{\solutions@list}
\newcommand{\allexercisesandsolutions}{\exercisesandsolutions@list}

\end{filecontents*}

\documentclass{article}




\usepackage[a4paper, margin=1in]{geometry}

\usepackage{thmtools}
\usepackage{thm-restate}
\usepackage[dvipsnames]{xcolor}
\usepackage[many]{tcolorbox}

\usepackage[]{testpackage}
% \usepackage[hidesolutions]{testpackage}
% \usepackage[nosolutions]{testpackage}







\begin{document}



\section{Originals}

Some text.

\begin{exercise}[Title?]
  This is the first recommendation.
\end{exercise}

We can of course have text between solution and exercise.

\begin{solution}[A named solution]
  This is the solution after the first exercise.
\end{solution}

Some text.

\begin{exercise}
  This is the second recommendation.
\end{exercise}

And even more text.

\begin{solution}
  This is the solution after the second exercise.
\end{solution}

Some text.

\section{All Exercises}
\allexercises
\section{All Solutions}
\allsolutions
\section{All Exercises with Solutions}
\allexercisesandsolutions




\end{document}

produces the following outputs(based on the package options):

testpackage: no option provided: show all solutions testpackage: option hidesolutions: show all solutions as empty boxes testpackage: option emptysolutions: don't show solutions

I can now use testpackage with options | hidesolutions | emptysolutions to produce the different desired outcomes.