15

Situation

I am planning to take some notes in a 'laboratory book'-ish latex document (compare these templates 1,2). The protocol will span a large time and entries might vary from a few items to several sides.

In order to keep better track of what I did when, I would like to have a calendar (e.g. this or this) that shows section titles (and maybe the page number). These should link to the sections (like done with pictures here).

Obviously one can use hyperref and simply do it by hand. However an TOC in such manner that is generated automatically was preferable.

Question

How can I create a TOC that looks like a calendar?

(or: a calendar that acts like a TOC)

(probably not Minimal) Working Example

Neither looking particularly nice nor quick to create (even if I used a custom command for the entries):

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Monthly Calendar
% LaTeX Template
%
% This template has been downloaded from:
% http://www.latextemplates.com
%
% Original calendar style author:
% Evan Sultanik (http://www.sultanik.com/LaTeX_calendar_style)
%
% Important note:
% This template requires the calendar.sty file to be in the same directory as the
% .tex file. The calendar.sty file provides the necessary structure to create the
% calendar.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   Modified in order to represent the MWE for tex.stackexchange question:
%   https://tex.stackexchange.com/q/356889/74942
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%----------------------------------------------------------------------------------------
%   PACKAGES AND OTHER DOCUMENT CONFIGURATIONS
%----------------------------------------------------------------------------------------

\documentclass[a4paper]{article}
%
\usepackage{filecontents}
\begin{filecontents}{calendar.sty}
\NeedsTeXFormat{LaTeX2e}

\def\CalendarVersion{3.1}
\def\CalendarVersionDate{2009/04/24}

\ProvidesClass{calendar}[\CalendarVersionDate
LaTeX2e class file `calendar' v\CalendarVersion]

\typeout{'calendar' style \CalendarVersion \CalendarVersionDate.}
\typeout{Created by Evan Sultanik}
\typeout{****** Bugs/comments/suggestions/technicalities to Evan Sultanik -- evan@sultanik.com ******}

\RequirePackage{tabularx}

\def\@CALtrue{1}
\newcount\@currentdaynum
\newcounter{calendardate}
\newcount\StartingDayNumber

\def\dayheader#1#2{
    \noindent
    \begin{minipage}[t]{0.87\hsize}
        \noindent
        \raggedright
        \textit{#1}
    \end{minipage}
    \begin{minipage}[t]{0.1\hsize}
        \noindent
        \raggedleft
        \textit{#2}
    \end{minipage}
}
\def\activities#1{
    \parbox{\hsize}{\vspace*{5pt}\raggedright\scriptsize #1}\smallskip
}

\let\@colbreak=&

\def\printdayname#1{\hfil\textsc{#1}\hfil}

\newcommand{\dayname}[1]{
    \ifnum#1=1 Sunday\else
    \ifnum#1=2 Monday\else
    \ifnum#1=3 Tuesday\else
    \ifnum#1=4 Wednesday\else
    \ifnum#1=5 Thursday\else
    \ifnum#1=6 Friday\else
    \ifnum#1=7 Saturday\else
    \PackageError{calendar}{Unrecognized day number: #1!}
    \fi\fi\fi\fi\fi\fi\fi
}

\StartingDayNumber=1
\newenvironment{calendar}[1]{
    \newdimen\@calendarwidth
    \@calendarwidth=#1
    \begingroup
    \def\@calendarmode{\@CALtrue}
    \def\day##1##2{
        \if\@calendarmode\@CALtrue\else\PackageWarning{calendar}{The '\day' macro is expected to be used in the 'calendar' environment!}\fi
        \ifnum\@currentdaynum>7\global\@currentdaynum=1\fi
        \global\advance\@currentdaynum by 1
        \dayheader{##1}{\thecalendardate}\def\daysep{\vskip1pt\hrule\vskip1pt}
        \activities{##2}
        \addtocounter{calendardate}{1}
        \ifnum\@currentdaynum>7\@arraycr\hline\else&\fi
    }
    \def\finishCalendar{
        \ifnum\@currentdaynum=6 &\\\hline\else
        \ifnum\@currentdaynum=5 &&\\\hline\else
        \ifnum\@currentdaynum=4 &&&\\\hline\else
        \ifnum\@currentdaynum=3 &&&&\\\hline\else
        \ifnum\@currentdaynum=2 &&&&&\\\hline\else
        \ifnum\@currentdaynum=1 &&&&&&\\\hline
        \fi\fi\fi\fi\fi\fi
    }
    \def\BlankDay{
        \if\@calendarmode\@CALtrue\else\PackageWarning{calendar}{The '\calendarday' macro is expected to be used in the 'calendar' environment!}\fi
        \ifnum\@currentdaynum>7\global\@currentdaynum=1\fi
        \global\advance\@currentdaynum by 1
        \addtocounter{calendardate}{1}
        \ifnum\@currentdaynum>7\@arraycr\hline\else&\fi
    }

    \setcounter{calendardate}{1}
    \newcount\@currday
    \@currday=\StartingDayNumber
    \newcount\@numdays
    \@numdays=7
    \let\@cbreak=&
    \tabularx{\@calendarwidth}{|X|X|X|X|X|X|X|} \hline
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 &
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 &
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 &
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 &
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 &
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 &
    \ifnum\@currday>\@numdays\@currday=1\fi\printdayname{\dayname{\@currday}} \global\advance\@currday by 1 \\ \hline \hline
    \@currentdaynum=1
    \let\@firstline=\@CALtrue
}{
    \endtabularx
    \endgroup
}
\end{filecontents}
%
\usepackage{calendar} % Use the calendar.sty style
\usepackage[colorlinks=false,linkcolor=black,bookmarks=false]{hyperref}
\usepackage[margin=0.5in]{geometry}



\begin{document}

\pagestyle{empty} % Removes the page number from the bottom of the page

\noindent

\StartingDayNumber=1 % Calendar starting day, default of 1 means Sunday, 2 for Monday, etc

%----------------------------------------------------------------------------------------
%   MONTH AND YEAR SECTION
%----------------------------------------------------------------------------------------
\setcounter{section}{-1}
\section{Table of Contents}
\begin{center}
\textsc{\LARGE january}\\ % Month
\textsc{\large 2017} % Year
\end{center}

%----------------------------------------------------------------------------------------

\begin{calendar}{\hsize}

%----------------------------------------------------------------------------------------
%   BLANK DAYS BEFORE THE BEGINNING OF THE CALENDAR
%----------------------------------------------------------------------------------------

% This part is very finicky. It defines the number of blank days at the beginning of the calendar before the first of the month starts. If you need this to be more than 4 (i.e. the first starts on a Friday or Saturday in a 31 day month), then you have two options: 
% 1) You can uncomment another one or two \BlankDay's below which will make a new week (6 total) which makes the calendar too big for one page, remedy this by decreasing the size of each day by replacing 2.5cm below with a smaller number. 
% 2) Make the spill-over days start at the top left of the calendar (i.e. the calendar starts with 31 then a few days blank then 1, 2, 3, etc). The second option can be configured by uncommenting the below:

%\setcounter{calendardate}{31} % Begin the count with 31 so the top left day is 31; this can be changed to 29 or 30 as required
%\day{}{\vspace{2.5cm}} % 31 - add another line identical to this if starting at 30 or earlier

% You will need to comment out the 31 in the NUMBERED DAYS AND CALENDAR CONTENT section below for this as well as commenting out one of the \BlankDay's below. Play around with it and you will get it.

%\BlankDay
%\BlankDay
%\BlankDay
%\BlankDay
%\BlankDay
%\BlankDay

%----------------------------------------------------------------------------------------
%   NUMBERED DAYS AND CALENDAR CONTENT
%----------------------------------------------------------------------------------------

% These are the numbered days in the template - if there are less than 31 days simply comment out the bottom lines.

% \vspace{2.5cm} is only there to provide an even look to the calendar where each day is 2.5cm tall, it can be changed or removed to automatically adjust to the day in the week with the most content

\setcounter{calendardate}{1} % Start the date counter at 1

\day{}{
            \hyperref[01012017]{\nameref{01012017}} \hfill \pageref{01012017} \\
            \hyperref[01012017_h]{\nameref{01012017_h}} \hfill \pageref{01012017_h} \\
            \hyperref[01012017_s]{\nameref{01012017_s}} \hfill \pageref{01012017_s}
            } % 1 - Example of content
\day{}{
    \hyperref[02012017]{\nameref{02012017}} \hfill \pageref{02012017} \\
    \hyperref[02012017_a]{\nameref{02012017_a}} \hfill \pageref{02012017_a} \\
    \hyperref[02012017_b]{\nameref{02012017_b}} \hfill \pageref{02012017_b}
} % 2 
\day{}{\vspace{2.5cm}} % 3
\day{}{\vspace{2.5cm}} % 4
\day{}{\vspace{2.5cm}} % 5
\day{}{\vspace{2.5cm}} % 6
\day{}{\vspace{2.5cm}} % 7
\day{}{\vspace{2.5cm}} % 8
\day{}{
    \hyperref[09012017]{\nameref{09012017}} \hfill \pageref{09012017} \\
} % 9
\day{}{\vspace{2.5cm}} % 10
\day{}{\vspace{2.5cm}} % 11
\day{}{\vspace{2.5cm}} % 12
\day{}{\vspace{2.5cm}} % 13
\day{}{\vspace{2.5cm}} % 14
\day{}{\vspace{2.5cm}} % 15
\day{}{\vspace{2.5cm}} % 16
\day{}{\vspace{2.5cm}} % 17
\day{}{\vspace{2.5cm}} % 18
\day{}{\vspace{2.5cm}} % 19
\day{}{\vspace{2.5cm}} % 20 
\day{}{\vspace{2.5cm}} % 21
\day{}{\vspace{2.5cm}} % 22
\day{}{\vspace{2.5cm}} % 23
\day{}{\vspace{2.5cm}} % 24
\day{}{\vspace{2.5cm}} % 25
\day{}{\vspace{2.5cm}} % 26
\day{}{\vspace{2.5cm}} % 27
\day{}{\vspace{2.5cm}} % 28
\day{}{\vspace{2.5cm}} % 29 
\day{}{\vspace{2.5cm}} % 30 
\day{}{\vspace{2.5cm}} % 31

% Un-comment the \BlankDay below if the bottom line of the calendar is missing
%\BlankDay

% Un-comment to start counting again after 31
%\setcounter{calendardate}{1}
%\day{}{\vspace{2.5cm}} % 1
%\day{}{\vspace{2.5cm}} % 2
%\day{}{\vspace{2.5cm}} % 3

%----------------------------------------------------------------------------------------

\finishCalendar
\end{calendar}

\newpage
\section{day1 - 01.01.2017}\label{01012017}
\begin{itemize}
    \item did some setup things
    \item $\dots$
\end{itemize}

\subsection{hardware}\label{01012017_h}
My tedious written composition of annoying hardware setup.
\newpage
~
\newpage
\subsection{software}\label{01012017_s}
The fun part: software!


\newpage
\section{day2 - 02.01.2017}\label{02012017}
\section{first test project}\label{02012017_a}
some text
\newpage
\section{video shoot}\label{02012017_b}
notes on my video log recording
\newpage
~
\newpage
\section{something important}\label{09012017}

\end{document}

(I did not want to remove too much information so no-one would confuse this with not being from latextemplates.com. Moreover I am not aware what is actually minimally required)

produces: enter image description here



edit2:

first outsourced question: Bake '\today' into source file (or custom aux-file)

edit1:

I am still investigating on this issue, hence ... Helpful information, e.g. on generation of ToCs, deeper TeX(-programming) necessary for this project or anything else would be much appreciated also!

8
  • Make a ToC that look like a calendar-table will be not trivial, I guess. Among others issues, how determine in which day should appear each section? (i.e. why "hardware" is in 1st tuesday, for instance?) So...why not simply make a empty calendar, put a label in each section (e.g.: \section{First test proyect\label{sec:firstp}}) and insert a cross-reference in the calendar? I mean some like \nameref{sec:firstp}\dotfill\pageref{sec:firstp}? (not very automatic, but probably a lot faster that try to do magic).
    – Fran
    Mar 5, 2017 at 0:00
  • @Fran well, that is obviously an option, though I am explicitly asking for some TeX magician. The parts are all existent (ToC, calendars, linking, sectioning, ...). The day or place to insert could either be an additional option for section or automatically extracted from current date (like \today). However, when its done automatically one cannot insert things that cover several days so in the end a manual option was needed anyways I guess. Mar 5, 2017 at 15:42
  • @hillbilly Please include a Minimum Working Example in the form of LaTeX in the post, rather than supplying links. Mar 6, 2017 at 13:56
  • 1
    @MusséRedi I dont know what minimal means in this context. I have no knowledge of deep TeX and creating ToCs. I tried to create something like the desired result in the example. (@Fran the added working example is not convenient to use due to the manual work necessary.) Mar 8, 2017 at 12:05
  • 1
    See tex.meta.stackexchange.com/questions/228/…. You are looking for a very dedicated helper if you expect somebody to follow all those links. Try breaking the task down into one step at a time. Ask about steps you get stuck on, rather than asking for the whole caboodle, whicj is way too much for this format.
    – cfr
    Jun 21, 2017 at 1:19

1 Answer 1

1

I think this may be able to achieve what you want.

result

Before spamming my code, please be advised that following requirements need to be met:

  • The compiler must be LuaLaTeX.
  • Download md5.lua and place it in your source folder. This is for creating valid labels for sections/subsections.
  • Place mycode.lua into source folder.

mycode.lua

-- for debugging
-- https://github.com/kikito/inspect.lua
-- inspect = require("inspect")

-- https://github.com/kikito/md5.lua/blob/master/md5.lua
md5 = require("md5")

function strip(str)
    return string.gsub(str, "^%s*(.-)%s*$", "%1")
end

function split_strip(inputstr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={}
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
        local stripped = strip(str)
        table.insert(t, stripped)
    end
    return t
end

function parse_time(time_str)
    local tab = split_strip(time_str, "%-")
    assert(#tab == 2, "invalid section format")

    local day_str = string.gsub(tab[1], "day%s+", "")
    local day_ind = tonumber(day_str)
    assert(day_ind ~= nil, "invalid day index")

    -- day/month/year format
    local tab_mdy = split_strip(tab[2], "%.")
    assert(#tab_mdy == 3, "invalid date format")
    local month = tab_mdy[2]
    local day = tab_mdy[1]
    local year = tab_mdy[3]
    
    local tp = os.time{year=year, month=month, day=day, hour=0, sec=1}
    local date = os.date("*t", tp)
    return {
        day_ind=day_ind,
        date=date
    }
end

function label_section(storage, section_str)
    return md5.sumhexa(section_str)
end

function label_subsection(storage, subsection_str)
    local offset = storage["offset"]
    local subsec_size = 0
    if storage["subsection"][offset] ~= nil then
        subsec_size = #storage["subsection"][offset]
    end
    local full_str = storage["section"][offset][1] .. subsection_str .. tostring(subsec_size)
    return md5.sumhexa(full_str)
end

-- no integrity check for section headings
-- avoid duplicated dates
-- must have day 1
function register_section(storage, date_str)
    local parse_res = parse_time(date_str)
    local offset = parse_res["day_ind"]
    if offset == 1 then
        storage["num_blanks"] = parse_res["date"]["wday"] - 1
    end
    storage["offset"] = offset
    local label = label_section(storage, date_str)
    local t_in = {date_str, label}
    storage["section"][offset] = t_in
    storage["subsection"][offset] = {}
    return t_in
end

function register_subsection(storage, subsection_str)
    local offset = storage["offset"]
    local label = label_subsection(storage, subsection_str)
    local t_in = {subsection_str, label}
    table.insert(storage["subsection"][offset], t_in)
    return t_in
end

function new_storage()
    local t = {}
    t["section"] = {}
    t["subsection"] = {}
    t["num_days"] = 31
    t["empty_fill"] = [[\vspace{2.5cm}]]
    return t
end

function create_toc(storage)
    local t = {}
    table.insert(t, [[\begin{calendar}{\hsize}]])

    local j = storage["num_blanks"]
    for i=1,j do
        table.insert(t, [[\BlankDay]])
    end
    table.insert(t, [[\setcounter{calendardate}{1}]])

    j = storage["num_days"]
    for i=1,j do
        local tt = {}
        if storage["section"][i] ~= nil then
            local sec_label = storage["section"][i][2]
            table.insert(tt, string.format([[\hyperref[%s]{\nameref{%s} \hfill \pageref{%s}}\newline]], 
                sec_label, sec_label, sec_label))
            if storage["subsection"][i] ~= nil then
                local subsec = storage["subsection"][i]
                for _, val in pairs(subsec) do
                    local subsec_label = val[2]
                    table.insert(tt, string.format([[\hyperref[%s]{\nameref{%s} \hfill \pageref{%s}}\newline]], 
                        subsec_label, subsec_label, subsec_label))
                end
            end
        end

        local str = ""
        if #tt == 0 then
            str = storage["empty_fill"]
        else
            str = table.concat(tt, "\n")
        end
        local day_str = string.format([[\day{}{%s}]], str)
        table.insert(t, day_str)
    end

    table.insert(t, [[\finishCalendar]])
    table.insert(t, [[\end{calendar}]])

    return table.concat(t, "\n")
end

main document

\documentclass[a4paper]{article}
\usepackage{calendar} % Use the calendar.sty style
\usepackage[colorlinks=false,linkcolor=black,bookmarks=false]{hyperref}
\usepackage[margin=0.5in]{geometry}
\usepackage{luacode}

\begin{document}

\pagestyle{empty} % Removes the page number from the bottom of the page

\noindent

\setcounter{section}{-1}
\section{Table of Contents}
\begin{center}
\textsc{\LARGE january}\\ % Month
\textsc{\large 2020} % Year
\end{center}

\directlua{
    require("mycode")
    % declare new global storage
    storage = new_storage()
}

\let\oldsection\section
\let\oldsubsection\subsection

\renewcommand{\section}[1]{
    \directlua{
        cur_sec = register_section(storage, "\luaescapestring{#1}")
    }
    \oldsection{#1}\label{\directlua{tex.print(cur_sec[2])}}
}

\renewcommand{\subsection}[1]{
    \directlua{
        cur_subsec = register_subsection(storage, "\luaescapestring{#1}")
    }
    \oldsubsection{#1}\label{\directlua{tex.print(cur_subsec[2])}}
}

% update calendar source file
\AtEndDocument{
    \directlua{
        local out = create_toc(storage)
        local file = io.open("\jobname.calendar", "w")
        file:write(out)
        file:close()
    }
}

% read the calendar from file
\InputIfFileExists{\jobname.calendar}


\newpage
\section{day 1 - 01.01.2020}
\begin{itemize}
    \item did some setup things
    \item $\dots$
\end{itemize}

\subsection{hardware}
My tedious written composition of annoying hardware setup.
\newpage
~
\newpage
\subsection{software}
The fun part: software!


\newpage
\section{day 2 - 02.01.2020}
\section{day 5 - 05.01.2020}
some text
\newpage

\section{day 10 - 10.01.2020}
\subsection{notes on my video log recording}
\newpage
% test identical section heading
\subsection{notes on my video log recording}

\newpage
~
\newpage
\section{day 20 - 20.01.2020}

\end{document}

More details

The core processing is completely done in Lua. I overrode default \section and \subsection commands to achieve automatically labeling. With Lua's date function, the number of \BlankDay's can be computed automatically. By the end of each compilation, the generated calendar source will be stored in \jobname.calendar and used in next run.

example generated calendar source

\begin{calendar}{\hsize}
\BlankDay
\BlankDay
\BlankDay
\setcounter{calendardate}{1}
\day{}{\hyperref[457625da265eeceb803943ba0808c2aa]{\nameref{457625da265eeceb803943ba0808c2aa} \hfill \pageref{457625da265eeceb803943ba0808c2aa}}\newline
\hyperref[de221fb236d079c07b5af80cf9ecef34]{\nameref{de221fb236d079c07b5af80cf9ecef34} \hfill \pageref{de221fb236d079c07b5af80cf9ecef34}}\newline
\hyperref[17592e2d9eafe348603ebdcc29dcb4ad]{\nameref{17592e2d9eafe348603ebdcc29dcb4ad} \hfill \pageref{17592e2d9eafe348603ebdcc29dcb4ad}}\newline}
\day{}{\hyperref[96f35bbca7ba14a54c2730705f376746]{\nameref{96f35bbca7ba14a54c2730705f376746} \hfill \pageref{96f35bbca7ba14a54c2730705f376746}}\newline}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\hyperref[69cc2168ce348de7a0d82d6f597cd274]{\nameref{69cc2168ce348de7a0d82d6f597cd274} \hfill \pageref{69cc2168ce348de7a0d82d6f597cd274}}\newline}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\hyperref[a402e6830c5d12dbda9ca2fb80398cd4]{\nameref{a402e6830c5d12dbda9ca2fb80398cd4} \hfill \pageref{a402e6830c5d12dbda9ca2fb80398cd4}}\newline
\hyperref[831be6085cb90cfa125282e6b78ac8d5]{\nameref{831be6085cb90cfa125282e6b78ac8d5} \hfill \pageref{831be6085cb90cfa125282e6b78ac8d5}}\newline
\hyperref[2df3994fff21c52f583af09d414f5d2e]{\nameref{2df3994fff21c52f583af09d414f5d2e} \hfill \pageref{2df3994fff21c52f583af09d414f5d2e}}\newline}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\hyperref[4c03bdd9c0e81f64cf961a4c48199e97]{\nameref{4c03bdd9c0e81f64cf961a4c48199e97} \hfill \pageref{4c03bdd9c0e81f64cf961a4c48199e97}}\newline}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\day{}{\vspace{2.5cm}}
\finishCalendar
\end{calendar}

Miscellaneous reminders

  1. Section titles must strictly follow a specific format. Otherwise, the parsing mechanism will not work. Despite that fact that there are day number and date in a section title, only the date of day 1 is used. As a result, the dates in subsequent titles are somehow redundant!
  2. The date format is dd/mm/yyyy by default.
2
  • Wow! This seems to perfectly create what I did manually. I will need to play around a bit to see how everything works. Could you add an example for the "specific [section] format"? (Is it \section{something - dd.mm.yyy} ?) Aug 7, 2020 at 22:03
  • @BadAtLaTeXProgramming Wow! I didn't notice the date of this question when I encountered it and I wasn't expecting a reply. The section format is restricted to day n - dd.mm.yy format. In reality, only the dd.mm.yy date of the first day is used, later days rely on day n (but you still need to enter full date for the parser to work correctly, you can try to fix that). I hope it is still helpful after all these years.
    – Alan Xiang
    Aug 8, 2020 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.