Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
15f2d8d
Age Calculator: fix leap-year function and add time summary (days→hou…
Ericbutler1209 Sep 18, 2025
db19bc8
Digital Clock: add separate date label below time
Ericbutler1209 Sep 18, 2025
0173fc9
Digital Clock: add 12/24-hour toggle button and 'f' shortcut
Ericbutler1209 Sep 18, 2025
026b56e
Digital Clock: consolidate update loop and refresh every second
Ericbutler1209 Sep 18, 2025
0a32153
Geographic Distance: add validate_coordinates() helper and use it in …
Ericbutler1209 Sep 19, 2025
392a9e6
Geographic Distance: add km_to_miles() and show distance in km and miles
Ericbutler1209 Sep 19, 2025
672129d
Geographic Distance: format travel time as hours and minutes
Ericbutler1209 Sep 19, 2025
d4f80b8
Resume Builder: add interactive internships collector
Ericbutler1209 Sep 19, 2025
56dff0e
Resume Builder: include internships section in generated PDF
Ericbutler1209 Sep 19, 2025
8dc8667
Resume Builder: add Internships menu option and handler
Ericbutler1209 Sep 19, 2025
2b0e978
Resume Builder: add internships list to resume_data
Ericbutler1209 Sep 19, 2025
d43108c
Resume Builder: add interactive internships collector
Ericbutler1209 Sep 19, 2025
fd67603
Resume Builder: include interships section in generated PDF
Ericbutler1209 Sep 19, 2025
06a24bf
Countdown Timer: display time as mm:ss and initialize lavel to 00.00
Ericbutler1209 Sep 20, 2025
592db06
CountDown Timer: play alarm when coutdown reaches 0
Ericbutler1209 Sep 20, 2025
b6a6460
Pomodoro: add CLI timer with countdown and pause/stop controls
Ericbutler1209 Sep 20, 2025
aa00fc0
Movie Scraper: improve resilience, add error handling, CLI, and CSV e…
Ericbutler1209 Sep 21, 2025
c7cb790
Password Generator: add length input, strength indicator, and copy-to…
Ericbutler1209 Sep 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions Age Calculator/calculate.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import time
from calendar import isleap

def judge_leap_year(year):
if isleap(year):
return True
else:
return False
# Check if a year is a leap year
def judge_leap(year: int) -> bool:
return isleap(year)

def month_days(month, leap_year):
# Return number of days in a month, considering leap years
def month_days(month: int, leap_year: bool) -> int:
if month in [1, 3, 5, 7, 8, 10, 12]:
return 31
elif month in [4, 6, 9, 11]:
return 30
elif month == 2 and leap_year:
return 29
elif month == 2 and (not leap_year):
else:
return 28


# User input
name = input("Please enter your name: ")
age = input("Please enter your age: ")
age = int(input("Please enter your age: "))

localtime = time.localtime(time.time())

year = int(age)
Expand All @@ -29,16 +29,25 @@ def month_days(month, leap_year):
begin_year = int(localtime.tm_year) - year
end_year = begin_year + year

# Count days in past years
for y in range(begin_year, end_year):
if (judge_leap_year(y)):
day = day + 366
if judge_leap(y):
day += 366
else:
day = day + 365
day += 365

leap_year = judge_leap_year(localtime.tm_year)
# Add days from current year
leap_year = judge_leap(localtime.tm_year)
for m in range(1, localtime.tm_mon):
day = day + month_days(m, leap_year)

day = day + localtime.tm_mday
print("\n\t%s's age is %d years or " % (name, year), end="")
print("%d months or %d days" % (month, day))
day += month_days(m, leap_year)

# Approximate breakdown (ignores time of day)
hours = day * 24
minutes = hours * 60
seconds = minutes * 60

print(f"\nHello {name}, you are approximately:")
print(f" {day:,} days")
print(f" {hours:,} hours")
print(f" {minutes:,} minutes")
print(f" {seconds:,} seconds old!")
35 changes: 31 additions & 4 deletions CountDown Timer/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
from tkinter import *
import tkinter as tk

def fmt_time(seconds: int) -> str:
seconds = max(0, int(seconds))
m, s = divmod(seconds, 60)
return f"{m:02d}:{s:02d}"

try:
import winsound # Windows
except Exception:
winsound = None

def play_alarm():
try:
if winsound:
winsound.Beep(880, 300)
winsound.Beep(988, 300)
winsound.Beep(1047, 300)
else:
# macOS/Linux fallback: terminal bell
print("\a", end="", flush=True)
except Exception:
pass



class Application(Frame):
def __init__(self,master):
super(Application,self).__init__(master)
Expand Down Expand Up @@ -39,7 +63,9 @@ def createWidgets(self):
self.someFrame.pack(side=TOP)

self.labelvariable = StringVar()
self.labelvariable.set("")
self.labelvariable.set(fmt_time(0))



self.thelabel = Label(self,textvariable = self.labelvariable,font=('Helvetica',50))
self.thelabel.pack(side=TOP)
Expand Down Expand Up @@ -80,14 +106,15 @@ def closeApp(self):
def countdown(self, timeInSeconds, start=True):
if timeInSeconds == 0:
self._starttime=0
self.labelvariable.set("0")
return
self.labelvariable.set(fmt_time(0))
play_alarm()
return
if start:
self._starttime = timeInSeconds
if self._paused:
self._alarm_id = self.master.after(1000, self.countdown, timeInSeconds, False)
else:
app.labelvariable.set(timeInSeconds)
app.labelvariable.set(fmt_time(timeInSeconds))
self._alarm_id = self.master.after(1000, self.countdown, timeInSeconds-1, False)


Expand Down
39 changes: 33 additions & 6 deletions Digital Clock/main.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,50 @@
from time import strftime
from tkinter import Label, Tk
from tkinter import Label, Tk , Button

window = Tk()
window.title("Digital Clock")
window.geometry("300x100")
window.configure(bg="green")
window.resizable(False, False)

use_24h = True

clock_label = Label(
window, bg="black", fg="green", font=("Arial", 30, "bold"), relief="flat"
)
clock_label.place(x=50, y=50)


date_label = Label(
window, bg="black", fg="white", font=("Arial", 14)
)
date_label.pack(pady=(0, 10), anchor="center")



def toggle_format(_evt=None):
global use_24h
use_24h = not use_24h
fmt_btn.config(text="Switch to 24-hour" if not use_24h else "Switch to 12-hour")

fmt_btn = Button(window, text="Switch to 12-hour", command=toggle_format)
fmt_btn.pack(pady=(0, 8))
window.bind("<f>", toggle_format) # press 'f' to toggle



def update_label():
current_time = strftime("%H: %M: %S\n %d-%m-%Y ")
clock_label.configure(text=current_time)
clock_label.after(80, update_label)
clock_label.pack(anchor="center")

if use_24h:
time_text = strftime("%H:%M:%S")
else:
# strip leading zero in 12h mode for a cleaner look
time_text = strftime("%I:%M:%S %p").lstrip("0")
clock_label.configure(text=time_text)
date_label.configure(text=strftime("%A, %b %d, %Y"))
window.after(1000, update_label)

update_label()
window.mainloop()
window.mainloop()


26 changes: 26 additions & 0 deletions Geographic Distance/geographic_distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,32 @@ def calculate_distance_and_time(coord1, coord2, avg_speed):

return distance, travel_time

def validate_coordinates(coord):
"""Ensure latitude and longitude are within valid ranges."""
lat, lon = coord
if not (-90 <= lat <= 90):
raise ValueError(f"Latitude {lat} out of range (-90..90)")
if not (-180 <= lon <= 180):
raise ValueError(f"Longitude {lon} out of range (-180..180)")
return coord

def km_to_miles(km: float) -> float:
"""Convert kilometers to miles."""
return km * 0.621371

def format_travel_time(hours: float) -> str:
"""Format fractional hours as 'Hh Mm'."""
h = int(hours)
m = int(round((hours - h) * 60))
if m == 60:
h += 1
m = 0
return f"{h}h {m}m"






def main():
# Coordinates (latitude, longitude)
Expand Down
16 changes: 15 additions & 1 deletion Password Generator/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from tkinter import *
from random import choice
import string
import pyperclip

class App:
def __init__(self):
Expand All @@ -13,7 +14,8 @@ def __init__(self):

self.label()
self.entry()
self.button()
self.options()
self.buttons()

def label(self):
label_title = Label(self.window, text='Welcome to password generator', font=('Courrier', 20), bg='gray', fg='black')
Expand All @@ -34,6 +36,18 @@ def generate_password(self):
password+=choice(characters)
self.password_entry.delete(0, END)
self.password_entry.insert(0, password)

if length < 8:
strength = "Weak"
elif length < 12:
strength = "Medium"
else:
strength = "Strong"
self.strength_label.config(text=f"Strength: {strength}")

def copy_password(self):
pyperclip.copy(self.password_entry.get())
self.strength_label.config(text="Copied to clipboard!")

app = App()
app.window.mainloop()
17 changes: 10 additions & 7 deletions Pomodoro Timer/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import time


def countdown(minutes, label):
def countdown(minutes: int, label: str) -> None:
"""Print a mm:ss countdown once per second for the given label."""
total_seconds = minutes * 60
while total_seconds:
while total_seconds >= 0:
mins, secs = divmod(total_seconds, 60)
timer = f"{mins:02d}:{secs:02d}"
print(f"{label} Timer: {timer}", end="\r")
print(f"{label} Timer: {mins:02d}:{secs:02d}", end="\r")
time.sleep(1)
total_seconds -= 1
print(f"\n{label} finished!")


def handle_pause_stop():
def handle_pause_stop() -> bool:
while True:
user_input = input(
"\nPress 'p' to pause, 's' to stop, or 'Enter' to continue: "
Expand Down Expand Up @@ -69,4 +68,8 @@ def get_valid_input(prompt):
long_break_minutes = get_valid_input("Enter long break interval in minutes: ")
cycles = get_valid_input("Enter the number of cycles: ")

pomodoro_timer(work_minutes, short_break_minutes, long_break_minutes, cycles)
while True:
pomodoro_timer(work_minutes, short_break_minutes, long_break_minutes, cycles)
# If user chose to repeat at the end, loop continues; otherwise we break here.
if not repeat_or_end():
break
75 changes: 75 additions & 0 deletions Pomodoro Timer/pomodoro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import time


def countdown(minutes: int, label: str) -> None:
"""Print a mm:ss countdown once per second for the given label."""
total_seconds = minutes * 60
while total_seconds >= 0:
mins, secs = divmod(total_seconds, 60)
print(f"{label} Timer: {mins:02d}:{secs:02d}", end="\r")
time.sleep(1)
total_seconds -= 1
print(f"\n{label} finished!")

def handle_pause_stop() -> bool:
while True:
user_input = input(
"\nPress 'p' to pause, 's' to stop, or 'Enter' to continue: "
).lower()
if user_input == "p":
print("Timer paused. Press 'Enter' to resume.")
input()
elif user_input == "s":
print("Timer stopped.")
return True # Return True to signal that the timer should stop
else:
return False # Return False to continue with the timer


def pomodoro_timer(work_min, short_break_min, long_break_min, cycles):
for i in range(cycles):
print(f"\nCycle {i+1} of {cycles}")
countdown(work_min, "Work")
if i < cycles - 1:
print("\nStarting short break...")
if handle_pause_stop():
return
countdown(short_break_min, "Short Break")
else:
print("\nStarting long break...")
if handle_pause_stop():
return
countdown(long_break_min, "Long Break")
if not repeat_or_end():
return


def repeat_or_end():
user_input = input(
"\nCycle finished. Would you like to repeat the cycle? (y/n): "
).lower()
return user_input == "y"


def get_valid_input(prompt):
while True:
try:
value = int(input(prompt))
if value <= 0:
raise ValueError
return value
except ValueError:
print("Invalid input. Please enter a positive integer.")


if __name__ == "__main__":
work_minutes = get_valid_input("Enter work interval in minutes: ")
short_break_minutes = get_valid_input("Enter short break interval in minutes: ")
long_break_minutes = get_valid_input("Enter long break interval in minutes: ")
cycles = get_valid_input("Enter the number of cycles: ")

while True:
pomodoro_timer(work_minutes, short_break_minutes, long_break_minutes, cycles)
# If user chose to repeat at the end, loop continues; otherwise we break here.
if not repeat_or_end():
break
Loading