Compare commits

..
6 Commits
3 changed files with 65 additions and 68 deletions

No files matched your search

+3
View File
@@ -1 +1,4 @@
Program to generate a csv for importing calendar events Program to generate a csv for importing calendar events
If using python 3.12 + need to `pip install --upgrade setuptools`
+4 -4
View File
@@ -16,17 +16,17 @@ EVENT_LIST = ( # ------------- --------
(SUNDAY, [4 ], 10, 00, 12, 00, "Main Campus", "Sunday Service", "Sunday Service 10:00am", "Prayer Room open from 8:30 AM to 9:30 AM. Worship Service starts at 10:00 AM. Fourth Sunday of the month is Coins for Kids Sunday"), (SUNDAY, [4 ], 10, 00, 12, 00, "Main Campus", "Sunday Service", "Sunday Service 10:00am", "Prayer Room open from 8:30 AM to 9:30 AM. Worship Service starts at 10:00 AM. Fourth Sunday of the month is Coins for Kids Sunday"),
(SUNDAY, [5 ], 10, 00, 12, 00, "Main Campus", "Sunday Service", "Sunday Service 10:00am", "Prayer Room open from 8:30 AM to 9:30 AM. Worship Service starts at 10:00 AM. Fifth Sunday of the month is Potluck Sunday"), (SUNDAY, [5 ], 10, 00, 12, 00, "Main Campus", "Sunday Service", "Sunday Service 10:00am", "Prayer Room open from 8:30 AM to 9:30 AM. Worship Service starts at 10:00 AM. Fifth Sunday of the month is Potluck Sunday"),
(SUNDAY, [1, 2, 3, 4, 5, 6], 18, 00, 19, 00, "Main Campus", "Sunday Service", "Sunday Eventing Service", ""), (SUNDAY, [1, 2, 3, 4, 5, 6], 18, 00, 19, 00, "Main Campus", "Sunday Service", "Sunday Eventing Service", ""),
(MONDAY, [1 ], 18, 00, 19, 30, "Main Campus", "Connecting Point", "Level Up 6:00pm", ""), (MONDAY, [1 ], 18, 00, 19, 30, "Main Campus", "Woman's Meeting", "Level Up 6:00pm", ""),
(MONDAY, [2 ], 18, 00, 19, 30, "Main Campus", "Woman's Meeting", "Ladies Night Out 6:00pm", "Come join us for a time of fun and fellowship\n\nBabysitting will be provided."), (MONDAY, [2 ], 18, 00, 19, 30, "Main Campus", "Woman's Meeting", "Ladies Night Out 6:00pm", "Come join us for a time of fun and fellowship\n\nBabysitting will be provided."),
(MONDAY, [4 ], 16, 00, 17, 00, "Main Campus", "Dementia Support", "Dementia Support Group 4:00pm", "Dementia and Alzheimer's Support Group"),
(TUESDAY, [1, 2, 3, 4, 5, 6], 18, 00, 20, 00, "Main Campus", "Grief Share", "Grief Share 6:00pm", ""), (TUESDAY, [1, 2, 3, 4, 5, 6], 18, 00, 20, 00, "Main Campus", "Grief Share", "Grief Share 6:00pm", ""),
(WEDNESDAY, [1, 2, 3, 4, 5 ], 7, 00, 8, 00, "SOCO", "Youth Group", "Youth Bible Study 7:00am", "Coffee and bible study for high school age youth"), (WEDNESDAY, [1, 2, 3, 4, 5 ], 18, 00, 20, 00, "Main Campus", "Youth Group", "Youth Group 6:00pm", ""),
(WEDNESDAY, [2 ], 8, 00, 12, 00, "Main Campus", "Connecting Point", "Connecting Point 8:00am", ""),
(WEDNESDAY, [3 ], 11, 30, 14, 00, "Main Campus", "Silver Seekers", "Silver Seekers 11:30am", "For those 60 and up. Join us for some food and some exciting events and fellowship."), (WEDNESDAY, [3 ], 11, 30, 14, 00, "Main Campus", "Silver Seekers", "Silver Seekers 11:30am", "For those 60 and up. Join us for some food and some exciting events and fellowship."),
(WEDNESDAY, [1, 2, 3, 4, 5 ], 18, 00, 20, 00, "Main Campus", "Youth Group", "Youth Group 6:00pm", ""),
(WEDNESDAY, [1, 2, 3, 4, 5 ], 18, 00, 20, 00, "Main Campus", "Mid Week Service", "Mid Week Service 6:00pm", ""), (WEDNESDAY, [1, 2, 3, 4, 5 ], 18, 00, 20, 00, "Main Campus", "Mid Week Service", "Mid Week Service 6:00pm", ""),
(THURSDAY, [1, 2, 3, 4, 5 ], 10, 00, 12, 00, "Main Campus", "Woman's Meeting", "Woman's Meeting 10:00am", "Woman 2 Woman Bible Study"), (THURSDAY, [1, 2, 3, 4, 5 ], 10, 00, 12, 00, "Main Campus", "Woman's Meeting", "Woman's Meeting 10:00am", "Woman 2 Woman Bible Study"),
(FRIDAY, [1, 2, 3, 4 ], 18, 30, 20, 30, "Main Campus", "Men's Meeting", "For Men Only 6:30pm", "Men's Bible Study"), (FRIDAY, [1, 2, 3, 4 ], 18, 30, 20, 30, "Main Campus", "Men's Meeting", "For Men Only 6:30pm", "Men's Bible Study"),
(FRIDAY, [5 ], 19, 00, 21, 00, "Main Campus", "Movie Night", "Family Movie Night 7:00pm", "To Be Announced"), (FRIDAY, [5 ], 19, 00, 21, 00, "Main Campus", "Movie Night", "Family Movie Night 7:00pm", "To Be Announced"),
(SATURDAY, [1 ], 9, 00, 12, 00, "Main Campus", "Cleanup", "Church Cleanup 9:00am", "Working hearts and hands for God's House"),
(SATURDAY, [2 ], 8, 00, 10, 00, "Main Campus", "Men's Meeting", "Men's Breakfast 8:00am", ""), (SATURDAY, [2 ], 8, 00, 10, 00, "Main Campus", "Men's Meeting", "Men's Breakfast 8:00am", ""),
# (--------, [- ], 18, 00, 20, 00, "Main Campus", "Youth Group", "South County Youth Group 6:00pm", ""), # (--------, [- ], 18, 00, 20, 00, "Main Campus", "Youth Group", "South County Youth Group 6:00pm", ""),
) )
+58 -64
View File
@@ -6,31 +6,11 @@ CHURCH CALENDAR CSV GENERATOR
import calendar import calendar
from dataclasses import dataclass from dataclasses import dataclass
from datetime import date, datetime from datetime import date, datetime
from pprint import pprint
import sys import sys
import click import click
from dataclass_csv import DataclassWriter from dataclass_csv import DataclassWriter
from events import EVENT_LIST from events import EVENT_LIST
"""
build a list of months / weeks / day of the month in those weeks
months 1-12, weeks 0-5 days of week 5 6 are the 1st and 2nd of month
MONTHS[1] [0] [ 0 0 0 0 0 1 2 ]
due to how months work
week 0 can have null days (represented by 0's)
weeks 1 - 4 will have all 7 days present
week 5 may have 7 days or nulls
week 6 can have a monday and/or tuesday in them if the 1st falls on a
saturday or sunday in week 0
EVENT_LIST has weeks as 1-6 while MONTHS has weeks as 0-5, offsetting will
be necessary
"""
def initalize_events(event_list): def initalize_events(event_list):
""" convert EVENT_LIST into monthly_events """ """ convert EVENT_LIST into monthly_events """
monthly_events = [[] for _ in range(7)] monthly_events = [[] for _ in range(7)]
@@ -38,14 +18,8 @@ def initalize_events(event_list):
monthly_events[event[0]].append(event[1:]) monthly_events[event[0]].append(event[1:])
return monthly_events return monthly_events
def debug_print(data, condition=True, end="\n"): def debug_print(data, condition=True, end="\n"):
"""Conditionally print data using pprint. """Conditionally print data."""
Args:
data: The data to be printed.
condition: A boolean value. If True, the data will be printed.
"""
if condition: if condition:
print(data, end=end) print(data, end=end)
@@ -58,7 +32,6 @@ def initalize_year(year: int) -> dict[int, list[list[int]]]:
@dataclass @dataclass
class Event(): class Event():
"""Event for CSV export""" """Event for CSV export"""
# pylint: disable=too-many-instance-attributes
event_name: str event_name: str
venue_name: str venue_name: str
organizer_name: str organizer_name: str
@@ -86,20 +59,13 @@ def suffix(day: int) -> str:
result = 'rd' result = 'rd'
return result return result
def sort_events(events: list[Event]) -> list[Event]:
"""sort events"""
events = sorted(events, key=lambda k: (k.start_date, k.start_time))
return events
def create_event(name: str, def create_event(name: str,
location: str, location: str,
categories: str, categories: str,
description: str, description: str,
start, start,
finish) -> None: finish) -> Event:
"""create event""" """create event object"""
# pylint: disable=too-many-arguments
event = Event(name, event = Event(name,
location, location,
"", "",
@@ -116,13 +82,11 @@ def create_event(name: str,
"", "",
description) description)
return event return event
# events.append(event)
def write_calendar(events: list[Event], filename) -> None: def write_calendar(events: list[Event], filename) -> None:
"""write calendar to csv file""" """write calendar to csv file"""
with open(filename, "w", encoding="utf-8") as handle: with open(filename, "w", encoding="utf-8", newline="") as handle:
writer =DataclassWriter(handle, events, Event) writer = DataclassWriter(handle, events, Event)
writer.map("event_name").to("EVENT NAME") writer.map("event_name").to("EVENT NAME")
writer.map("venue_name").to("VENUE NAME") writer.map("venue_name").to("VENUE NAME")
writer.map("organizer_name").to("ORGANIZER NAME") writer.map("organizer_name").to("ORGANIZER NAME")
@@ -140,7 +104,6 @@ def write_calendar(events: list[Event], filename) -> None:
writer.map("event_description").to("EVENT DESCRIPTION") writer.map("event_description").to("EVENT DESCRIPTION")
writer.write() writer.write()
def process_day(events, year, month, day, day_events): def process_day(events, year, month, day, day_events):
"""process all events for one day""" """process all events for one day"""
for event_item in day_events: for event_item in day_events:
@@ -151,47 +114,78 @@ def process_day(events, year, month, day, day_events):
events.append(event) events.append(event)
return events return events
def process_month(months, monthly_events, year, month, week_of_month, week, events): def process_month(monthly_events, year, month, week, events, weekday_counters):
"""process one months of events""" """process one week of events using weekday occurrence counters"""
for day_of_week, day in enumerate(week): for day_of_week, day in enumerate(week):
if day > 0: if day > 0:
""" # Increment the occurrence count for this specific weekday (0=Mon, 6=Sun)
month, week_of_month, day_of_week, day weekday_counters[day_of_week] += 1
use monthly_events[day_of_week] current_occurrence = weekday_counters[day_of_week]
"""
debug_print(f" {day_of_week}-{day:02d}", DEBUG) debug_print(f" {day_of_week}-{day:02d} (Occurrence: {current_occurrence})", DEBUG)
day_events = [x[1:] for x in monthly_events[day_of_week] if week_of_month + 1 in x[0]]
# Filter events matching this day of week and this specific occurrence (e.g., 2nd Monday)
day_events = [x[1:] for x in monthly_events[day_of_week] if current_occurrence in x[0]]
events = process_day(events, year, month, day, day_events) events = process_day(events, year, month, day, day_events)
debug_print("", DEBUG)
return events return events
def process_months(months_dict, monthly_events, year, month_range):
def process_months(months, monthly_events, year): """process selected months and return list of events"""
"""process full year of months and return list of events"""
events = [] events = []
for month in range(1, 13): for month in range(1, 13):
if month not in month_range:
continue
debug_print(f"MONTH: {month}", DEBUG) debug_print(f"MONTH: {month}", DEBUG)
for week_of_month, week in enumerate(months[month]):
# Initialize counters for the month to track 1st, 2nd, etc. occurrence of each weekday
weekday_counters = [0] * 7
for week_of_month, week in enumerate(months_dict[month]):
debug_print(f"{week_of_month} {week}", DEBUG) debug_print(f"{week_of_month} {week}", DEBUG)
events = process_month(months, monthly_events, year, month, week_of_month, week, events) events = process_month(monthly_events, year, month, week, events, weekday_counters)
return events return events
# @click.argument('filename', type=click.File('w'), default="calendar.csv", required=False) def validate_months(ctx, param, value):
"""Validates and processes the --months option."""
if value is None:
return list(range(1, 13))
parts = value.split('-')
if len(parts) == 1:
try:
month = int(parts[0])
if 1 <= month <= 12:
return [month]
raise click.BadParameter("Month must be between 1 and 12.")
except ValueError:
raise click.BadParameter("Invalid month format.")
elif len(parts) == 2:
try:
start, end = int(parts[0]), int(parts[1])
if 1 <= start <= 12 and 1 <= end <= 12 and start <= end:
return list(range(start, end + 1))
raise click.BadParameter("Invalid month range.")
except ValueError:
raise click.BadParameter("Invalid range format.")
raise click.BadParameter("Use a single number or a range (e.g., 1-3).")
@click.command() @click.command()
@click.option("--debug", "-d", is_flag=True, default=False, help="Print debug output") @click.option("--debug", "-d", is_flag=True, default=False, help="Print debug output")
@click.option('--year', "-y", type=int, default=date.today().year, help='Specify the year.') @click.option('--year', "-y", type=int, default=date.today().year, help='Specify the year.')
@click.option('--months', '-m', 'month_range', callback=validate_months, default=None,
help='A single month (1-12) or a range (e.g., 1-3).')
@click.argument('filename', default="calendar.csv", required=False) @click.argument('filename', default="calendar.csv", required=False)
def main(debug, year, filename): def main(debug, year, month_range, filename):
"""Create a .csv file of church events for the year. Modify events.py to change events""" """Create a .csv file of church events for the year."""
global DEBUG global DEBUG
DEBUG = debug DEBUG = debug
months = initalize_year(year) months_dict = initalize_year(year)
monthly_events = initalize_events(EVENT_LIST) monthly_events = initalize_events(EVENT_LIST)
events = process_months(months, monthly_events, year) events = process_months(months_dict, monthly_events, year, month_range)
# events = sort_events(events)
write_calendar(events, filename) write_calendar(events, filename)
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
main() # pylint: disable=E1120 main()