From f5f69a70c25af4f59f9caa5f0d24e46b7fbd9871 Mon Sep 17 00:00:00 2001
From: "Douglas B. Rumbaugh" <doug@douglasrumbaugh.com>
Date: Sun, 11 Jan 2026 12:19:10 -0500
Subject: Initial commit of schedule class

---
 weekschedule.cls | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 257 insertions(+)
 create mode 100644 weekschedule.cls

(limited to 'weekschedule.cls')

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
-- 
cgit v1.2.3

