-
Notifications
You must be signed in to change notification settings - Fork 0
/
cli.py
129 lines (99 loc) · 3.78 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import datetime
import os
import signal
import time
import click
import django
import pygame
from pytz import timezone
import reprlib
from tqdm import tqdm
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pymodoro.settings')
django.setup()
from bouts import models # NOQA
# from django import utils # see utils.timezone.now()
# TODO: switch this over to using UTC.
eastern = timezone('US/Eastern')
@click.group()
def cli():
pass
@cli.command('start-project')
@click.argument('name')
@click.argument('description')
def start_project(name, description):
models.Project.objects.create(name=name, description=description)
click.echo(f"Created new project: {name}\n Go get 'em, champ.")
@cli.command('projects')
def projects():
for project in models.Project.objects.all():
click.echo(f'{project.name}: {reprlib.repr(project.description)}')
@cli.command('project-metrics')
@click.argument('name')
def project_metrics(name):
for metric in models.ProjectMetric.objects.filter(project__name=name):
click.echo(metric)
@cli.command('start-bout')
@click.argument('project')
def start_bout(project):
"""
- Create Bout instance
- Kick off a count down timer
- On timer expiration, retrieve Bout instance, and update with notes,
results and data for associated metrics.
- Ideally
- Collect plan, result and metrics info
- play background, and ending sounds
"""
bout = create_bout(project)
signal.signal(signal.SIGINT, signal.default_int_handler)
try:
bout_in_progress(bout)
except KeyboardInterrupt:
truncate_bout_duration(bout, datetime.datetime.now().astimezone(eastern))
bout_complete(bout)
else:
play_complete_sound()
bout_complete(bout)
def create_bout(project):
return models.Bout.objects.create(
duration=datetime.timedelta(seconds=click.prompt('How many minutes?', default=35) * 60),
plan=click.prompt("What's the plan, stan?"),
project=models.Project.objects.get(name=project),
start_time=datetime.datetime.now().astimezone(eastern),
)
def bout_in_progress(bout):
now = datetime.datetime.now().astimezone(eastern)
bar_format = '{l_bar}{bar}[{elapsed}<{remaining}]'
with tqdm(total=bout.duration.total_seconds(), desc='Bout progress', bar_format=bar_format, leave=False) as pbar:
while datetime.datetime.now().astimezone(eastern) < bout.start_time + bout.duration:
time.sleep(0.1)
increment = (datetime.datetime.now().astimezone(eastern) - now).total_seconds()
now = datetime.datetime.now().astimezone(eastern)
pbar.update(increment)
@cli.command('bouts')
@click.argument('project')
def list_bouts(project):
""" List a project's bouts."""
# TODO: filtering
pass
def bout_complete(bout):
finish_time = datetime.datetime.now().astimezone(eastern)
bout.result = click.prompt("How'd it go?")
bout.focus = click.prompt('Focus level? (Likert scale, 1 - 7, one is very bad, seven is very good)')
extend_bout_duration(bout, finish_time)
bout.save()
def truncate_bout_duration(bout, finish_time):
actual_duration = finish_time - bout.start_time
bout.duration = actual_duration
def extend_bout_duration(bout, finish_time):
two_minutes = datetime.timedelta(seconds=60*2)
time_elapsed = datetime.datetime.now().astimezone(eastern) - finish_time
minutes, seconds = divmod(time_elapsed.total_seconds(), 60)
if time_elapsed > two_minutes and click.prompt(f'Add an extra {minutes:.0f}:{seconds:02.0f} to the bout?', type=click.BOOL):
bout.duration += time_elapsed
def play_complete_sound():
pygame.mixer.init()
pygame.mixer.music.load('/Users/liavkoren/Downloads/applause3.wav')
pygame.mixer.music.play()
if __name__ == '__main__':
cli()