aboutsummaryrefslogtreecommitdiffstats
path: root/weekschedule.cls
diff options
context:
space:
mode:
Diffstat (limited to 'weekschedule.cls')
-rw-r--r--weekschedule.cls257
1 files changed, 257 insertions, 0 deletions
diff --git a/weekschedule.cls b/weekschedule.cls
new file mode 100644
index 0000000..7fccb80
--- /dev/null
+++ b/weekschedule.cls
@@ -0,0 +1,257 @@
+% weekschedule.cls - A LaTeX class for creating weekly schedule calendars
+% Usage:
+% \documentclass{weekschedule}
+% \scheduletitle{Weekly Schedule - Spring 2026}
+% \scheduleauthor{Dr. Smith}
+% \timefrom{8:00}
+% \timeto{18:00}
+% \twelvehourtime % or \twentyfourhourtime
+% \eventclass{Courses}{173,216,230} % RGB values
+% \event{Courses}{MATH 101}{Monday,Wednesday,Friday}{9:00}{10:00}
+% \begin{document}
+% \printschedule
+% \end{document}
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesClass{weekschedule}[2026/01/11 Weekly Schedule Class]
+
+% Load base class
+\LoadClass[landscape,11pt]{article}
+
+% Required packages
+\RequirePackage[margin=0.5in]{geometry}
+\RequirePackage{tikz}
+\RequirePackage{xcolor}
+\RequirePackage{pgfmath}
+
+\pagestyle{empty}
+
+% ============================================
+% Configuration variables with defaults
+% ============================================
+\newcommand{\@scheduletitle}{Weekly Schedule}
+\newcommand{\@scheduleauthor}{}
+\newcommand{\@starthour}{8}
+\newcommand{\@endhour}{18}
+\newif\if@usetwentyfourhour
+\@usetwentyfourhourfalse
+
+% Layout parameters
+\newcommand{\@daywidth}{4.5}
+\newcommand{\@hourheight}{1.5}
+\newcommand{\@padding}{0.08}
+
+% ============================================
+% User-facing configuration commands
+% ============================================
+\newcommand{\scheduletitle}[1]{\renewcommand{\@scheduletitle}{#1}}
+\newcommand{\scheduleauthor}[1]{\renewcommand{\@scheduleauthor}{#1}}
+
+% Parse time string like "8:00" or "13:30" and store hour
+\newcommand{\timefrom}[1]{%
+ \@parsetime{#1}%
+ \pgfmathtruncatemacro{\@temph}{\@parsedtime}%
+ \edef\@starthour{\@temph}%
+}
+
+\newcommand{\timeto}[1]{%
+ \@parsetime{#1}%
+ \pgfmathtruncatemacro{\@temph}{\@parsedtime}%
+ \edef\@endhour{\@temph}%
+}
+
+% Time format toggles
+\newcommand{\twentyfourhourtime}{\@usetwentyfourhourtrue}
+\newcommand{\twelvehourtime}{\@usetwentyfourhourfalse}
+
+% Layout customization
+\newcommand{\setdaywidth}[1]{\renewcommand{\@daywidth}{#1}}
+\newcommand{\sethourheight}[1]{\renewcommand{\@hourheight}{#1}}
+\newcommand{\setpadding}[1]{\renewcommand{\@padding}{#1}}
+
+% ============================================
+% Internal time parsing
+% ============================================
+% Parse time to decimal (e.g., "9:30" -> 9.5)
+\def\@parsetime#1{\@@parsetime#1\@nil}
+\def\@@parsetime#1:#2\@nil{%
+ \pgfmathparse{#1 + #2/60}%
+ \edef\@parsedtime{\pgfmathresult}%
+}
+
+% ============================================
+% Event class definitions (colors)
+% ============================================
+\newcounter{@numclasses}
+\setcounter{@numclasses}{0}
+
+% Define an event class with RGB color
+% Usage: \eventclass{ClassName}{R,G,B}
+\newcommand{\eventclass}[2]{%
+ \definecolor{class@#1}{RGB}{#2}%
+ \stepcounter{@numclasses}%
+ \expandafter\def\csname @classname\the@numclasses\endcsname{#1}%
+}
+
+% ============================================
+% Event storage
+% ============================================
+\newcounter{@numevents}
+\setcounter{@numevents}{0}
+
+% Store an event
+% Usage: \event{ClassName}{Event Name}{Days}{Start}{End}
+% Days can be: Monday, Tuesday, Wednesday, Thursday, Friday (comma-separated)
+\newcommand{\event}[5]{%
+ \stepcounter{@numevents}%
+ \expandafter\def\csname @eventclass\the@numevents\endcsname{#1}%
+ \expandafter\def\csname @eventname\the@numevents\endcsname{#2}%
+ \expandafter\def\csname @eventdays\the@numevents\endcsname{#3}%
+ \expandafter\def\csname @eventstart\the@numevents\endcsname{#4}%
+ \expandafter\def\csname @eventend\the@numevents\endcsname{#5}%
+}
+
+% ============================================
+% Main schedule rendering
+% ============================================
+\newcommand{\printschedule}{%
+ % Title and author
+ \begin{center}
+ \LARGE\textbf{\@scheduletitle}%
+ \ifx\@scheduleauthor\empty\else\\[0.2cm]\Large\@scheduleauthor\fi%
+ \end{center}
+ \vspace{0.05cm}
+
+ \begin{tikzpicture}[x=1cm, y=1cm]
+ % Store parameters
+ \pgfmathsetmacro{\daywidth}{\@daywidth}
+ \pgfmathsetmacro{\hourheight}{\@hourheight}
+ \pgfmathsetmacro{\padding}{\@padding}
+ \pgfmathtruncatemacro{\starthour}{\@starthour}
+ \pgfmathtruncatemacro{\endhour}{\@endhour}
+
+ % Draw column headers (days)
+ \foreach \day/\dayname in {0/Monday, 1/Tuesday, 2/Wednesday, 3/Thursday, 4/Friday} {
+ \node[anchor=south, font=\large\bfseries] at (\day*\daywidth+\daywidth/2, -\starthour*\hourheight+0.2) {\dayname};
+ }
+
+ % Draw row headers (times)
+ \foreach \hour in {\starthour,...,\endhour} {
+ \pgfmathtruncatemacro{\displayhour}{mod(\hour-1,12)+1}
+ \if@usetwentyfourhour
+ \node[anchor=east, font=\small] at (-0.1, -\hour*\hourheight) {\hour:00};
+ \else
+ \ifnum\hour<12
+ \def\@ampm{AM}
+ \else
+ \def\@ampm{PM}
+ \fi
+ \node[anchor=east, font=\small] at (-0.1, -\hour*\hourheight) {\displayhour:00 \@ampm};
+ \fi
+ }
+
+ % Draw vertical lines (day separators)
+ \foreach \day in {0,...,5} {
+ \draw[gray] (\day*\daywidth, -\starthour*\hourheight) -- (\day*\daywidth, -\endhour*\hourheight);
+ }
+
+ % Draw horizontal lines (hour separators)
+ \foreach \hour in {\starthour,...,\endhour} {
+ \draw[gray] (0, -\hour*\hourheight) -- (5*\daywidth, -\hour*\hourheight);
+ }
+
+ % Draw half-hour lines (dashed)
+ \pgfmathtruncatemacro{\lasthour}{\endhour-1}
+ \foreach \hour in {\starthour,...,\lasthour} {
+ \draw[gray, dashed, line width=0.25pt] (0, -\hour*\hourheight-0.5*\hourheight) -- (5*\daywidth, -\hour*\hourheight-0.5*\hourheight);
+ }
+
+ % Draw all events
+ \foreach \evnum in {1,...,\the@numevents} {
+ \@drawevent{\evnum}
+ }
+
+ \end{tikzpicture}
+
+ \vspace{0.2cm}
+
+ % Legend
+ \begin{center}
+ \begin{tikzpicture}
+ \foreach \clnum in {1,...,\the@numclasses} {
+ \pgfmathsetmacro{\xpos}{(\clnum-1)*3.5}
+ \edef\@clname{\csname @classname\clnum\endcsname}
+ \fill[class@\@clname] (\xpos,0) rectangle (\xpos+0.4,0.3);
+ \node[anchor=west] at (\xpos+0.5,0.15) {\@clname};
+ }
+ \end{tikzpicture}
+ \end{center}
+}
+
+% ============================================
+% Event drawing helper
+% ============================================
+\newcommand{\@drawevent}[1]{%
+ \edef\@evclass{\csname @eventclass#1\endcsname}%
+ \edef\@evname{\csname @eventname#1\endcsname}%
+ \edef\@evdays{\csname @eventdays#1\endcsname}%
+ \edef\@evstart{\csname @eventstart#1\endcsname}%
+ \edef\@evend{\csname @eventend#1\endcsname}%
+ % Parse times
+ \expandafter\@parsetime\expandafter{\@evstart}%
+ \let\@startdec\@parsedtime
+ \expandafter\@parsetime\expandafter{\@evend}%
+ \let\@enddec\@parsedtime
+ % Draw for each day
+ \@drawforeachday{\@evclass}{\@evname}{\@evdays}{\@startdec}{\@enddec}%
+}
+
+\newcommand{\@drawforeachday}[5]{%
+ % #1=class, #2=name, #3=days, #4=start, #5=end
+ \@checkandrawday{#1}{#2}{#3}{#4}{#5}{Monday}{0}%
+ \@checkandrawday{#1}{#2}{#3}{#4}{#5}{Tuesday}{1}%
+ \@checkandrawday{#1}{#2}{#3}{#4}{#5}{Wednesday}{2}%
+ \@checkandrawday{#1}{#2}{#3}{#4}{#5}{Thursday}{3}%
+ \@checkandrawday{#1}{#2}{#3}{#4}{#5}{Friday}{4}%
+}
+
+\newcommand{\@checkandrawday}[7]{%
+ % #1=class, #2=name, #3=days string, #4=start, #5=end, #6=dayname, #7=daynum
+ \@checkdayinlist{#3}{#6}%
+ \if@daymatched
+ \@draweventbox{#1}{#2}{#7}{#4}{#5}%
+ \fi
+}
+
+\newif\if@daymatched
+
+\newcommand{\@checkdayinlist}[2]{%
+ % #1 = comma-separated day list, #2 = day to check
+ \@daymatchedfalse
+ \def\@daytocheck{#2}%
+ \@for\@testday:=#1\do{%
+ \edef\@trimmedday{\@testday}%
+ \ifx\@trimmedday\@daytocheck
+ \@daymatchedtrue
+ \fi
+ }%
+}
+
+\newcommand{\@draweventbox}[5]{%
+ % #1 = class, #2 = name, #3 = day number, #4 = start decimal, #5 = end decimal
+ \pgfmathsetmacro{\daywidth}{\@daywidth}
+ \pgfmathsetmacro{\hourheight}{\@hourheight}
+ \pgfmathsetmacro{\padding}{\@padding}
+ \pgfmathsetmacro{\xstart}{#3*\daywidth+\padding}
+ \pgfmathsetmacro{\xend}{#3*\daywidth+\daywidth-\padding}
+ \pgfmathsetmacro{\ystart}{-#4*\hourheight-\padding}
+ \pgfmathsetmacro{\yend}{-#5*\hourheight+\padding}
+ \pgfmathsetmacro{\ymid}{(\ystart+\yend)/2}
+ \pgfmathsetmacro{\xcenter}{#3*\daywidth+\daywidth/2}
+ % Draw the box
+ \fill[class@#1, rounded corners] (\xstart, \ystart) rectangle (\xend, \yend);
+ % Draw the label
+ \node[font=\small, align=center] at (\xcenter, \ymid) {#2};
+}
+
+\endinput