[end time, start time, step amt, name, desc, finished]
Multiple events will be stored in a master list and sorted by increasing end time.
Part Three: Get Events on a Specific Day
Returns a list of event indices and event times
First Check: Did this group of events already end
Second Check: Did this group of events start yet
Third Check: Is there an event TODAY.
Let k be the smallest integer where
Start + k * Step > Date
The event is TODAY if
Start + k * step < Date + 86400
Calculate the time of the event on that day
Event Time = Start + k * step – Date
Add tuple to a list
(Event Index, Event Time)
Return this list
Part Four: Get and Update Inputs of Mouse and Keyboard
Save Inputs from Previous Frame
Save Inputs from Current Frame
Save Mouse Position
Part Five: Query Inputs of Mouse and Keyboard
Parameters: Mode (String), Key (id)
Key identifies which specific input we are querying.
“down” Mode: Return if the specific input is on
“press” Mode: Return if the specific input was turned on this frame
“release” Mode: Return if the specific input was turned off this frame
Part Six: Add Event
Get Inputs: Start Time, End Time, Step, Name, and Description
Insert Event into Events list while maintaining sorted by end time. (USE LOAD EVENT FORMAT)
Part Seven: Remove Event
Delete event from events list.
Note: All times will be saved using seconds since epoch.
Flowchart
The following flowchart shows the structure and logic of how the above is implemented.
Flowchart
Code
File Loader Class To save and load events and get events on a specific day. (See parts One to Three)
class CalendarLoader:
def __init__(self, filename):
self.events = []
self.filename = filename
def set_file(self, filename):
self.filename = filename
def load_events(self, filepath=None):
if filepath is None:
filepath = self.filename
self.events = []
infile = open(filepath, "r")
lines = [] # all the lines between previous and next "#" markings
for line in infile:
if line[0] == '#':
# gets event settings based on above format
b = int(lines[0])
end = int(lines[1])
start = int(lines[2])
step = int(lines[3])
name = lines[4]
desc = "\n".join(lines[5:])
self.events.append([end, start, step, name, desc, b])
lines = [] # reset lines
else:
# add line to lines list.
lines.append(line[1:-1])
infile.close()
def save_events(self, filepath=None):
if filepath is None:
filepath = self.filename
s = ""
for event in self.events:
# Saves each event based on the above format
s += f"-{int(event[5])}\n"
s += f"-{int(event[0])}\n"
s += f"-{int(event[1])}\n"
s += f"-{int(event[2])}\n"
s += f"-{event[3]}\n"
s += f"-{event[4]}\n"
s += "#\n"
outfile = open(filepath, "w")
outfile.write(s)
outfile.close()
def search(self, time):
# Basic Binary Search
low = -1
high = len(self.events) - 1
while low < high:
mid = low + (high - low + 1) // 2
if self.events[mid][0] <= time:
low = mid
else:
high = mid - 1
return low + 1
def getDay(self, date):
# Follows the above Instructions to get all the events that happen on that day.
events = []
for i in range(len(self.events) - 1, -1, -1):
event = self.events[i]
if event[0] < date:
break
k = (date - event[1] - 1) // event[2] + 1
t = event[1] + k * event[2] - date
if k >= 0 and t < 86400:
events.append((t, i))
return events
def getEvent(self, idx):
return self.events[idx]
Pygame Input Handler To handle updating and querying inputs from the mouse and keyboard. (See parts Four to Five)
import pygame
class InputHandler:
# Get Modes: "down", "press", and "release"
def __init__(self):
self.keyDown = pygame.key.get_pressed()
self.prevKeyDown = pygame.key.get_pressed()
self.mouseDown = pygame.mouse.get_pressed(3)
self.prevMouseDown = pygame.mouse.get_pressed(3)
self.mousePos = pygame.mouse.get_pos()
def update(self):
# Set Previous Mouse and Key Downs
self.prevKeyDown = self.keyDown
self.prevMouseDown = self.mouseDown
# Set Current Mouse and Key Downs
self.keyDown = pygame.key.get_pressed()
self.mouseDown = pygame.mouse.get_pressed(3)
self.mousePos = pygame.mouse.get_pos()
def getKey(self, key, mode="down"):
match mode:
case "down": # Is Key Down
return self.keyDown[key]
case "press": # Was Key Pressed this frame
return self.keyDown[key] and not self.prevKeyDown[key]
case "release": Was Key Released this frame
return self.prevKeyDown[key] and not self.keyDown[key]
case _:
print(f"Unknown Mode {mode}")
return False
def getMouse(self, mouse, mode="down"):
match mode:
case "down": # Is Mouse Button Down
return self.mouseDown[mouse]
case "press": # Was Mouse Button Pressed this frame
return self.mouseDown[mouse] and not self.prevMouseDown[mouse]
case "release": # Was Mouse Button Release this frame
return self.prevMouseDown[mouse] and not self.mouseDown[mouse]
case _:
print(f"Unknown Mode {mode}")
return False
Primary Calendar Class To Add and Remove events. (See parts Six to Seven)
import datetime
import time
import pygame
from CalendarLoader import *
utc = datetime.timezone.utc
class Calendar:
def __init__(self, filename):
self.loader = CalendarLoader(filename)
self.loader.load_events()
# Floor "now" to 00:00 on the same day
now = (time.time() // 86400) * 86400
self.line = 20
self.date = now
self.start = now
self.end = now
self.step = 86400
self.addIdx = 0
self.selected = 0
def set_filename(self, filename):
self.loader.set_file(filename)
def render(self, font, inHand, offset):
# Get all the events on the current date
events = sorted(self.loader.getDay(self.date))
relx, rely = inHand.mousePos[0] - offset[0], inHand.mousePos[1] - offset[1]
idx = -1
if 20 < relx < 250 and 5 + 1.5 * self.line < rely:
idx = int((rely - 5) / self.line - 1.5)
if idx >= len(events):
idx = -1
if inHand.getMouse(0, "press") and idx != -1:
self.selected = idx # Check if any events where clicked
if inHand.getKey(pygame.K_UP, "press"):
self.addIdx = (self.addIdx - 1 + 3) % 3 # decrease add index
if inHand.getKey(pygame.K_DOWN, "press"):
self.addIdx = (self.addIdx + 1) % 3 # increase add index
# Calendar Window
surf = pygame.Surface((600, 400))
surf.fill((0, 255, 255))
surf.blit(font.render(datetime.datetime.fromtimestamp(self.date, utc).strftime("%A %B %d, %Y"), True, (0, 0, 0)), (20, 5))
for i, (t, eventIdx) in enumerate(events):
event = self.loader.getEvent(eventIdx)
timing = datetime.datetime.fromtimestamp(t, utc).strftime("%I:%M %p")
colour = ((0, 0, 0) if event[5] != 1 else (0, 180, 0)) if i != self.selected else (0, 0, 127)
status = "[]" if event[5] == 1 else "X"
surf.blit(font.render(f"{status} {timing}: {event[3]}", True, colour), (20, 5 + (i + 1.5) * self.line))
if i == self.selected:
surf.blit(font.render(datetime.datetime.fromtimestamp(event[1], utc).strftime("Start: %A %B %d, %Y - %H"), True, (0, 0, 0)), (270, 5 + 9 * self.line))
surf.blit(font.render(datetime.datetime.fromtimestamp(event[0], utc).strftime("End: %A %B %d, %Y - %H"), True, (0, 0, 0)), (270, 5 + 10 * self.line))
surf.blit(font.render(datetime.datetime.fromtimestamp(event[2] - 86400, utc).strftime("Step: %d days; %H hours"), True, (0, 0, 0)), (270, 5 + 11 * self.line))
surf.blit(font.render("=== Description ===", True, (0, 0, 0)), (270, 5 + 12 * self.line))
surf.blit(font.render(f"{event[4]}", True, (0, 0, 0)), (270, 5 + 13 * self.line))
if inHand.getKey(pygame.K_f, "press") and 0 <= self.selected < len(events):
self.loader.events[events[self.selected][1]][5] = 1 - self.loader.events[events[self.selected][1]][5]
colours = [(0, 0, 0), (0, 0, 0), (0, 0, 0)]
colours[self.addIdx] = (0, 0, 127)
surf.blit(font.render(datetime.datetime.fromtimestamp(self.start, utc).strftime("Start: %A %B %d, %Y - %H"), True, colours[0]), (270, 5))
surf.blit(font.render(datetime.datetime.fromtimestamp(self.end, utc).strftime("End: %A %B %d, %Y - %H"), True, colours[1]), (270, 5 + self.line))
surf.blit(font.render(datetime.datetime.fromtimestamp(self.step - 86400, utc).strftime("Step: %d days; %H hours"), True, colours[2]), (270, 5 + 2 * self.line))
surf.blit(font.render(("START", "END", "STEP")[self.addIdx], True, (0, 127, 0)), (300, 5 + 4 * self.line))
clickIdx = (-1, -1)
for t in range(2):
for i in range((4, 4, 2)[self.addIdx]):
bx = 370 + i * 25
by = 5 + 4 * self.line + t * 25
pygame.draw.rect(surf, (0, 0, 0), (bx - 10, by - 10, 20, 20), 2, 4)
symbol = "+" if t == 0 else "-"
surf.blit(font.render(symbol, True, (0, 0, 0)), (bx - 3, by - 13))
if abs(relx - bx) < 10 and abs(rely - by) < 10:
clickIdx = (i, t)
if inHand.getMouse(0, "press") and clickIdx[0] != -1:
m = (1, -1)[clickIdx[1]]
i = clickIdx[0]
match self.addIdx:
case 0:
if i == 1:
self.start += m * 86400
else:
dt = datetime.datetime.fromtimestamp(self.start, utc)
para = [dt.month, dt.day, dt.year, dt.hour]
if i == 0:
para[i] = (para[i] + m + 11) % 12 + 1
elif i == 3:
para[i] = (para[i] + m + 24) % 24
else:
para[i] += m
self.start = datetime.datetime(para[2], para[0], para[1], para[3], tzinfo=utc).timestamp()
case 1:
if i == 1:
self.end += m * 86400
else:
dt = datetime.datetime.fromtimestamp(self.end, utc)
para = [dt.month, dt.day, dt.year, dt.hour]
if i == 0:
para[i] = (para[i] + m + 11) % 12 + 1
elif i == 3:
para[i] = (para[i] + m + 24) % 24
else:
para[i] += m
self.end = datetime.datetime(para[2], para[0], para[1], para[3], tzinfo=utc).timestamp()
case 2:
self.step += m * (86400, 3600)[i]
self.start = max(self.start, 0)
self.step = max(self.step, 86400)
self.end = max(self.end, 0)
clickIdx = -1
surf.blit(font.render("Events: Add Remove Save", True, (0, 0, 0)), (270, 7 * self.line - 8))
for t in range(3):
bx = 340 + t * 55
by = 5 + 8 * self.line
pygame.draw.rect(surf, (0, 0, 0), (bx - 10, by - 10, 20, 20), 2, 4)
symbol = "+-S"[t]
o = 2 if t == 2 else 0
surf.blit(font.render(symbol, True, (0, 0, 0)), (bx - 3 - o, by - 13 + o))
if abs(relx - bx) < 10 and abs(rely - by) < 10:
clickIdx = t
if inHand.getMouse(0, "press") and clickIdx != -1:
if clickIdx == 0:
print("Name Of Event: ")
name = input()
desc = ""
print("Description: ")
while True:
add = input()
if add == "":
break
desc += add + '\n'
index = self.loader.search(time.time() - 2073600)
self.loader.events = self.loader.events[index:]
self.loader.events.insert(self.loader.search(self.end), [self.end, self.start, self.step, name, desc[:-1], 0])
elif clickIdx == 1:
if 0 <= self.selected < len(events):
self.loader.events.pop(events[self.selected][1])
elif clickIdx == 2:
self.loader.save_events()
return surf
Pygame Main Loop To integrate all parts.
import pygame
from InputHandler import *
from Calendar import *
# Basic Pygame Setup
pygame.init()
pygame.font.init()
high_score = 0
score = 0
fps = 60
fpsClock = pygame.time.Clock()
width, height = 840, 480
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Calendar App")
font = pygame.font.SysFont("comicsans", 25)
inHand = InputHandler()
calendar = Calendar("event.txt")
# print(calendar.loader.events)
# Main Game Loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
if not running:
break
inHand.update()
# White Background
screen.fill((255, 255, 255))
# Handles Click Detection for the Calendar Date Controller
clickIdx = (-1, -1)
screen.blit(font.render("Calendar Date Controller", True, (0, 0, 0)), (630, 18))
for i in range(3):
by = 55 + i * 25
label = ("Year", "Month", "Day")[i]
screen.blit(font.render(f"{label}: ", True, (0, 0, 0)), (630, by - 12))
for t in range(2):
bx = 700 + t * 25
pygame.draw.rect(screen, (0, 0, 0), (bx - 10, by - 10, 20, 20), 2, 4)
symbol = "+" if t == 0 else "-"
screen.blit(font.render(symbol, True, (0, 0, 0)), (bx - 3, by - 13))
if abs(inHand.mousePos[0] - bx) < 10 and abs(inHand.mousePos[1] - by) < 10:
clickIdx = (i, t)
if inHand.getMouse(0, "press") and clickIdx[0] != -1:
m = (1, -1)[clickIdx[1]]
i = clickIdx[0]
if i == 2:
calendar.date += m * 86400
else:
dt = datetime.datetime.fromtimestamp(calendar.date, utc)
para = [dt.year, dt.month, dt.day]
if i == 1:
para[i] = (para[i] + m + 11) % 12 + 1
else:
para[i] += m
calendar.date = datetime.datetime(para[0], para[1], para[2], tzinfo=utc).timestamp()
calendar.date = max(calendar.date, 0)
screen.blit(calendar.render(font, inHand, (20, 20)), (20, 20))
pygame.display.flip()
fpsClock.tick(fps)
# Closed the game
print("App Closed Successfully")
Single-File Full Code
import time
import pygame
import datetime
# ============ FILE LOADER ============
class CalendarLoader:
def __init__(self, filename):
self.events = []
self.filename = filename
def set_file(self, filename):
self.filename = filename
def load_events(self, filepath=None):
if filepath is None:
filepath = self.filename
self.events = []
infile = open(filepath, "r")
lines = []
for line in infile:
if line[0] == '#':
b = int(lines[0])
end = int(lines[1])
start = int(lines[2])
step = int(lines[3])
name = lines[4]
desc = "\n".join(lines[5:])
self.events.append([end, start, step, name, desc, b])
lines = []
else:
lines.append(line[1:-1])
infile.close()
def save_events(self, filepath=None):
if filepath is None:
filepath = self.filename
s = ""
for event in self.events:
s += f"-{int(event[5])}\n"
s += f"-{int(event[0])}\n"
s += f"-{int(event[1])}\n"
s += f"-{int(event[2])}\n"
s += f"-{event[3]}\n"
s += f"-{event[4]}\n"
s += "#\n"
outfile = open(filepath, "w")
outfile.write(s)
outfile.close()
def search(self, time):
# Basic Binary Search
low = -1
high = len(self.events) - 1
while low < high:
mid = low + (high - low + 1) // 2
if self.events[mid][0] <= time:
low = mid
else:
high = mid - 1
return low + 1
def getDay(self, date):
# Follows the above Instructions to get all the events that happen on that day.
events = []
for i in range(len(self.events) - 1, -1, -1):
event = self.events[i]
if event[0] < date:
break
k = (date - event[1] - 1) // event[2] + 1
t = event[1] + k * event[2] - date
if k >= 0 and t < 86400:
events.append((t, i))
return events
def getEvent(self, idx):
return self.events[idx]
# ============ PYGAME INPUT HANDLER ============
class InputHandler:
def __init__(self):
self.keyDown = pygame.key.get_pressed()
self.prevKeyDown = pygame.key.get_pressed()
self.mouseDown = pygame.mouse.get_pressed(3)
self.prevMouseDown = pygame.mouse.get_pressed(3)
self.mousePos = pygame.mouse.get_pos()
def update(self):
self.prevKeyDown = self.keyDown
self.prevMouseDown = self.mouseDown
self.keyDown = pygame.key.get_pressed()
self.mouseDown = pygame.mouse.get_pressed(3)
self.mousePos = pygame.mouse.get_pos()
def getKey(self, key, mode="down"):
match mode:
case "down":
return self.keyDown[key]
case "press":
return self.keyDown[key] and not self.prevKeyDown[key]
case "release":
return self.prevKeyDown[key] and not self.keyDown[key]
case _:
print(f"Unknown Mode {mode}")
return False
def getMouse(self, mouse, mode="down"):
match mode:
case "down":
return self.mouseDown[mouse]
case "press":
return self.mouseDown[mouse] and not self.prevMouseDown[mouse]
case "release":
return self.prevMouseDown[mouse] and not self.mouseDown[mouse]
case _:
print(f"Unknown Mode {mode}")
return False
# ============ CALENDAR CLASS ============
utc = datetime.timezone.utc
class Calendar:
def __init__(self, filename):
self.loader = CalendarLoader(filename)
self.loader.load_events()
now = (time.time() // 86400) * 86400
self.line = 20
self.date = now
self.start = now
self.end = now
self.step = 86400
self.addIdx = 0
self.selected = 0
def set_filename(self, filename):
self.loader.set_file(filename)
def render(self, font, inHand, offset):
events = sorted(self.loader.getDay(self.date))
relx, rely = inHand.mousePos[0] - offset[0], inHand.mousePos[1] - offset[1]
idx = -1
if 20 < relx < 250 and 5 + 1.5 * self.line < rely:
idx = int((rely - 5) / self.line - 1.5)
if idx >= len(events):
idx = -1
if inHand.getMouse(0, "press") and idx != -1:
self.selected = idx
if inHand.getKey(pygame.K_UP, "press"):
self.addIdx = (self.addIdx - 1 + 3) % 3
if inHand.getKey(pygame.K_DOWN, "press"):
self.addIdx = (self.addIdx + 1) % 3
surf = pygame.Surface((600, 400))
surf.fill((0, 255, 255))
surf.blit(font.render(datetime.datetime.fromtimestamp(self.date, utc).strftime("%A %B %d, %Y"), True, (0, 0, 0)), (20, 5))
for i, (t, eventIdx) in enumerate(events):
event = self.loader.getEvent(eventIdx)
timing = datetime.datetime.fromtimestamp(t, utc).strftime("%I:%M %p")
colour = ((0, 0, 0) if event[5] != 1 else (0, 180, 0)) if i != self.selected else (0, 0, 127)
status = "[]" if event[5] == 1 else "X"
surf.blit(font.render(f"{status} {timing}: {event[3]}", True, colour), (20, 5 + (i + 1.5) * self.line))
if i == self.selected:
surf.blit(font.render(datetime.datetime.fromtimestamp(event[1], utc).strftime("Start: %A %B %d, %Y - %H"), True, (0, 0, 0)), (270, 5 + 9 * self.line))
surf.blit(font.render(datetime.datetime.fromtimestamp(event[0], utc).strftime("End: %A %B %d, %Y - %H"), True, (0, 0, 0)), (270, 5 + 10 * self.line))
surf.blit(font.render(datetime.datetime.fromtimestamp(event[2] - 86400, utc).strftime("Step: %d days; %H hours"), True, (0, 0, 0)), (270, 5 + 11 * self.line))
surf.blit(font.render("=== Description ===", True, (0, 0, 0)), (270, 5 + 12 * self.line))
surf.blit(font.render(f"{event[4]}", True, (0, 0, 0)), (270, 5 + 13 * self.line))
if inHand.getKey(pygame.K_f, "press"):
self.loader.events[events[self.selected][1]][5] = 1 - self.loader.events[events[self.selected][1]][5]
colours = [(0, 0, 0), (0, 0, 0), (0, 0, 0)]
colours[self.addIdx] = (0, 0, 127)
surf.blit(font.render(datetime.datetime.fromtimestamp(self.start, utc).strftime("Start: %A %B %d, %Y - %H"), True, colours[0]), (270, 5))
surf.blit(font.render(datetime.datetime.fromtimestamp(self.end, utc).strftime("End: %A %B %d, %Y - %H"), True, colours[1]), (270, 5 + self.line))
surf.blit(font.render(datetime.datetime.fromtimestamp(self.step - 86400, utc).strftime("Step: %d days; %H hours"), True, colours[2]), (270, 5 + 2 * self.line))
surf.blit(font.render(("START", "END", "STEP")[self.addIdx], True, (0, 127, 0)), (300, 5 + 4 * self.line))
clickIdx = (-1, -1)
for t in range(2):
for i in range((4, 4, 2)[self.addIdx]):
bx = 370 + i * 25
by = 5 + 4 * self.line + t * 25
pygame.draw.rect(surf, (0, 0, 0), (bx - 10, by - 10, 20, 20), 2, 4)
symbol = "+" if t == 0 else "-"
surf.blit(font.render(symbol, True, (0, 0, 0)), (bx - 3, by - 13))
if abs(relx - bx) < 10 and abs(rely - by) < 10:
clickIdx = (i, t)
if inHand.getMouse(0, "press") and clickIdx[0] != -1:
m = (1, -1)[clickIdx[1]]
i = clickIdx[0]
match self.addIdx:
case 0:
if i == 1:
self.start += m * 86400
else:
dt = datetime.datetime.fromtimestamp(self.start, utc)
para = [dt.month, dt.day, dt.year, dt.hour]
if i == 0:
para[i] = (para[i] + m + 11) % 12 + 1
elif i == 3:
para[i] = (para[i] + m + 24) % 24
else:
para[i] += m
self.start = datetime.datetime(para[2], para[0], para[1], para[3], tzinfo=utc).timestamp()
case 1:
if i == 1:
self.end += m * 86400
else:
dt = datetime.datetime.fromtimestamp(self.end, utc)
para = [dt.month, dt.day, dt.year, dt.hour]
if i == 0:
para[i] = (para[i] + m + 11) % 12 + 1
elif i == 3:
para[i] = (para[i] + m + 24) % 24
else:
para[i] += m
self.end = datetime.datetime(para[2], para[0], para[1], para[3], tzinfo=utc).timestamp()
case 2:
self.step += m * (86400, 3600)[i]
self.start = max(self.start, 0)
self.step = max(self.step, 86400)
self.end = max(self.end, 0)
clickIdx = -1
surf.blit(font.render("Events: Add Remove Save", True, (0, 0, 0)), (270, 7 * self.line - 8))
for t in range(3):
bx = 340 + t * 55
by = 5 + 8 * self.line
pygame.draw.rect(surf, (0, 0, 0), (bx - 10, by - 10, 20, 20), 2, 4)
symbol = "+-S"[t]
o = 2 if t == 2 else 0
surf.blit(font.render(symbol, True, (0, 0, 0)), (bx - 3 - o, by - 13 + o))
if abs(relx - bx) < 10 and abs(rely - by) < 10:
clickIdx = t
if inHand.getMouse(0, "press") and clickIdx != -1:
if clickIdx == 0:
print("Name Of Event: ")
name = input()
desc = ""
print("Description: ")
while True:
add = input()
if add == "":
break
desc += add + '\n'
index = self.loader.search(time.time() - 2073600)
self.loader.events = self.loader.events[index:]
self.loader.events.insert(self.loader.search(self.end), [self.end, self.start, self.step, name, desc[:-1], 0])
elif clickIdx == 1:
if 0 <= self.selected < len(events):
self.loader.events.pop(events[self.selected][1])
elif clickIdx == 2:
self.loader.save_events()
return surf
# ============ PRIMARY PYGAME LOOP ============
pygame.init()
pygame.font.init()
high_score = 0
score = 0
fps = 60
fpsClock = pygame.time.Clock()
width, height = 840, 480
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Calendar App")
font = pygame.font.SysFont("comicsans", 25)
inHand = InputHandler()
calendar = Calendar("event.txt")
# print(calendar.loader.events)
# Main Game Loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
if not running:
break
inHand.update()
screen.fill((255, 255, 255))
clickIdx = (-1, -1)
screen.blit(font.render("Calendar Date Controller", True, (0, 0, 0)), (630, 18))
for i in range(3):
by = 55 + i * 25
label = ("Year", "Month", "Day")[i]
screen.blit(font.render(f"{label}: ", True, (0, 0, 0)), (630, by - 12))
for t in range(2):
bx = 700 + t * 25
pygame.draw.rect(screen, (0, 0, 0), (bx - 10, by - 10, 20, 20), 2, 4)
symbol = "+" if t == 0 else "-"
screen.blit(font.render(symbol, True, (0, 0, 0)), (bx - 3, by - 13))
if abs(inHand.mousePos[0] - bx) < 10 and abs(inHand.mousePos[1] - by) < 10:
clickIdx = (i, t)
if inHand.getMouse(0, "press") and clickIdx[0] != -1:
m = (1, -1)[clickIdx[1]]
i = clickIdx[0]
if i == 2:
calendar.date += m * 86400
else:
dt = datetime.datetime.fromtimestamp(calendar.date, utc)
para = [dt.year, dt.month, dt.day]
if i == 1:
para[i] = (para[i] + m + 11) % 12 + 1
else:
para[i] += m
calendar.date = datetime.datetime(para[0], para[1], para[2], tzinfo=utc).timestamp()
calendar.date = max(calendar.date, 0)
screen.blit(calendar.render(font, inHand, (20, 20)), (20, 20))
pygame.display.flip()
fpsClock.tick(fps)
# Closed the game
print("App Closed Successfully")