fitness/fitness.py

171 lines
6.3 KiB
Python

#!/usr/bin/python3
'''
┌──────────────────────┤ Fitness App ├─────────────────────┐
│ │
│ Application to help with a workout routine │
│ │
├──────────────────────────────────────────────────────────┤
│ │
│ Version: 0.1 Date: 2023-03-05 │
│ │
│ License: GPL3+NIGGER (C) 2023 Colttaine │
│ │
└──────────────────────────────────────────────────────────┘
'''
import csv
import os
import pygame
import sys
import time
file_path = os.path.dirname(os.path.abspath(__file__)) + "/"
routine_file = os.path.expanduser("~") + '/.local/share/fitness/routine.csv'
routine = []
pygame.init()
screen = pygame.display.set_mode(( 1280, 720 ))
fontLarge = pygame.font.SysFont("myriadProFont", 320)
fontMid = pygame.font.SysFont("myriadProFont", 128)
fontSmall = pygame.font.SysFont("myriadProFont", 72)
fontTiny = pygame.font.SysFont("myriadProFont", 48)
soundDing = pygame.mixer.Sound(file_path + "ding.flac")
soundDong = pygame.mixer.Sound(file_path + "dong.flac")
#pygame.display.toggle_fullscreen()
#--------[ LOAD CSV FILE ]--------#
with open( routine_file ) as csvDataFile: # Load the exercise routine CSV file
csvReader = csv.reader(csvDataFile) # Start CSV reader
csvHeader = next(csvReader) # Read first line of CSV file as header information
for row in csvReader: # For each subsequent row of CSV file read information
routine.append( row )
#--------[ CONVERT SECONDS TO CLOCK STRING ]--------#
def secToTime(_time):
tmpStr = ""
tmpStr += str(int(_time/3600)).zfill(2)
tmpStr += ":"
tmpStr += str(int(_time/60)).zfill(2)
tmpStr += ":"
tmpStr += str(_time%60).zfill(2)
return tmpStr
#--------[ CONVERT CLOCK STRING TO SECONDS ]--------#
def timeToSec(_time):
hours = int( _time[0:2] )
minutes = int( _time[3:5] )
seconds = int( _time[6:9] )
return (hours*3600) + (minutes*60) + seconds
#--------[ MAIN LOOP ]--------#
pause = False
timer = 0
while timer < timeToSec(routine[-1][0]):
#--------[ GET CURRENT TIME INFO ]--------#
time_start = time.time()
#--------[ CLEAR SCREEN TO BLACK ]--------#
screen.fill((0,0,0))
#--------[ LOOK FOR INPUT EVENTS ]--------#
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
pause = not pause
#--------[ GET EXERCISE BASED ON TIME ]--------#
exercise_current = []
exercise_next = []
for i in range(len(routine)):
if timeToSec(routine[i][0]) <= timer:
exercise_current = routine[i]
exercise_next = routine[i+1]
#--------[ DRAW EXERCISE NAME ]--------#
if int(exercise_current[3]) > 0:
infoTextStr = '{0}kg {1}'.format(exercise_current[3], exercise_current[2])
else:
infoTextStr = '{0}'.format(exercise_current[2])
infoText = fontMid.render(infoTextStr, 1, (255,255,255,255))
screen.blit(infoText, infoText.get_rect(center=( screen.get_rect().centerx, screen.get_rect().centery*0.45 )))
#--------[ DRAW MAIN STOPWATCH ]--------#
if timer < timeToSec(exercise_current[0]) + int(exercise_current[1]):
color = (255, 0, 0, 255)
else:
color = (255, 255, 255, 255)
timerText = fontLarge.render(secToTime(timer), 1, color)
screen.blit(timerText, timerText.get_rect(center=screen.get_rect().center))
#--------[ DRAW SET AND REP NUMBERS ]--------#
infoTextStr = 'Set: {0} Reps: {1}'.format(exercise_current[4], exercise_current[5])
infoText = fontSmall.render(infoTextStr, 1, (255,255,255,255))
screen.blit(infoText, infoText.get_rect(center=( screen.get_rect().centerx, screen.get_rect().centery*1.5 )))
#--------[ DRAW NEXT EXERCISE ]--------#
if int(exercise_next[3]) > 0:
infoTextStr = 'Next: {0}kg {1}'.format(exercise_next[3], exercise_next[2])
else:
infoTextStr = 'Next: {0}'.format(exercise_next[2])
infoText = fontTiny.render(infoTextStr, 1, (255,255,255,255))
screen.blit(infoText, infoText.get_rect(center=( screen.get_rect().centerx*1.5, screen.get_rect().centery*1.8 )))
if pause:
color = (255,255,255,128)
pygame.draw.rect(screen, color, pygame.Rect(32, 32, 64, 128))
pygame.draw.rect(screen, color, pygame.Rect(128, 32,64, 128))
pass
#--------[ UPDATE DISPLAY BUFFER ]--------#
pygame.display.flip()
#--------[ PLAY DING SOUNDS ]--------#
if not pause and exercise_next != routine[-1]:
if timer == timeToSec(exercise_current[0]):
pygame.mixer.Sound.play(soundDong)
if timer >= timeToSec(exercise_next[0])-4:
pygame.mixer.Sound.play(soundDing)
#--------[ WAIT FOR NEXT FRAME ]--------#
time.sleep(1.0 - (time_start-time.time()))
if not pause:
timer +=1
#--------[ END FRAME ]--------#
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
sys.exit()
screen.fill((0,0,0))
infoTextStr = 'Total Volume:'
infoText = fontMid.render(infoTextStr, 1, (255,255,255,255))
screen.blit(infoText, infoText.get_rect(center=( screen.get_rect().centerx, screen.get_rect().centery*0.45 )))
volume = 0
for i in range(len(routine)):
volume += int(routine[i][3]) * int(routine[i][5])
timerTextStr = '{0}kg'.format(volume)
timerText = fontLarge.render(timerTextStr, 1, (255,255,255,255))
screen.blit(timerText, timerText.get_rect(center=screen.get_rect().center))
pygame.display.flip()
time.sleep(0.5)