Skip to content

Commit 6aac5ca

Browse files
committed
Problem 19 solution
1 parent 19f151e commit 6aac5ca

File tree

4 files changed

+355
-21
lines changed

4 files changed

+355
-21
lines changed

19_wod/test.py

+21-21
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,34 @@
77
import string
88
from subprocess import getstatusoutput
99

10-
prg = './wod.py'
11-
input1 = 'inputs/exercises.csv'
12-
input2 = 'inputs/silly-exercises.csv'
10+
PRG = "./wod.py"
11+
INPUT_1 = "inputs/exercises.csv"
12+
INPUT_2 = "inputs/silly-exercises.csv"
1313

1414

1515
# --------------------------------------------------
1616
def test_exists():
1717
"""exists"""
1818

19-
assert os.path.isfile(prg)
19+
assert os.path.isfile(PRG)
2020

2121

2222
# --------------------------------------------------
2323
def test_usage():
2424
"""usage"""
2525

26-
for flag in ['-h', '--help']:
27-
rv, out = getstatusoutput(f'{prg} {flag}')
26+
for flag in ["-h", "--help"]:
27+
rv, out = getstatusoutput(f"python {PRG} {flag}")
2828
assert rv == 0
29-
assert out.lower().startswith('usage')
29+
assert out.lower().startswith("usage")
3030

3131

3232
# --------------------------------------------------
3333
def test_bad_num():
3434
"""Dies on bad --num"""
3535

3636
bad = random.choice(range(-10, 0))
37-
rv, out = getstatusoutput(f'{prg} -n {bad}')
37+
rv, out = getstatusoutput(f"python {PRG} -n {bad}")
3838
assert rv != 0
3939
assert re.search(f'--num "{bad}" must be greater than 0', out)
4040

@@ -44,7 +44,7 @@ def test_bad_file():
4444
"""Dies on bad file"""
4545

4646
bad = random_string()
47-
rv, out = getstatusoutput(f'{prg} -f {bad}')
47+
rv, out = getstatusoutput(f"python {PRG} -f {bad}")
4848
assert rv != 0
4949
assert re.search(f"No such file or directory: '{bad}'", out)
5050

@@ -62,8 +62,8 @@ def test_seed1():
6262
Burpees 35
6363
"""
6464

65-
seed_flag = '-s' if random.choice([0, 1]) else '--seed'
66-
rv, out = getstatusoutput(f'{prg} {seed_flag} 1')
65+
seed_flag = "-s" if random.choice([0, 1]) else "--seed"
66+
rv, out = getstatusoutput(f"python {PRG} {seed_flag} 1")
6767
assert rv == 0
6868
assert out.strip() == expected.strip()
6969

@@ -81,9 +81,9 @@ def test_seed1_easy():
8181
Burpees 17
8282
"""
8383

84-
seed_flag = '-s' if random.choice([0, 1]) else '--seed'
85-
easy_flag = '-e' if random.choice([0, 1]) else '--easy'
86-
rv, out = getstatusoutput(f'{prg} {easy_flag} {seed_flag} 1')
84+
seed_flag = "-s" if random.choice([0, 1]) else "--seed"
85+
easy_flag = "-e" if random.choice([0, 1]) else "--easy"
86+
rv, out = getstatusoutput(f"python {PRG} {easy_flag} {seed_flag} 1")
8787
assert rv == 0
8888
assert out.strip() == expected.strip()
8989

@@ -105,9 +105,9 @@ def test_seed2_num8():
105105
Lunges 32
106106
"""
107107

108-
seed_flag = '-s' if random.choice([0, 1]) else '--seed'
109-
num_flag = '-n' if random.choice([0, 1]) else '--num'
110-
cmd = f'{prg} {num_flag} 8 {seed_flag} 2 -f {input1}'
108+
seed_flag = "-s" if random.choice([0, 1]) else "--seed"
109+
num_flag = "-n" if random.choice([0, 1]) else "--num"
110+
cmd = f"python {PRG} {num_flag} 8 {seed_flag} 2 -f {INPUT_1}"
111111
rv, out = getstatusoutput(cmd)
112112
assert rv == 0
113113
assert out.strip() == expected.strip()
@@ -125,9 +125,9 @@ def test_seed4_num3_input2():
125125
Squatting Chinups 35
126126
"""
127127

128-
seed_flag = '-s' if random.choice([0, 1]) else '--seed'
129-
num_flag = '-n' if random.choice([0, 1]) else '--num'
130-
rv, out = getstatusoutput(f'{prg} {num_flag} 3 {seed_flag} 4 -f {input2}')
128+
seed_flag = "-s" if random.choice([0, 1]) else "--seed"
129+
num_flag = "-n" if random.choice([0, 1]) else "--num"
130+
rv, out = getstatusoutput(f"python {PRG} {num_flag} 3 {seed_flag} 4 -f {INPUT_2}")
131131
assert rv == 0
132132
assert out.strip() == expected.strip()
133133

@@ -137,4 +137,4 @@ def random_string():
137137
"""generate a random string"""
138138

139139
k = random.randint(5, 10)
140-
return ''.join(random.choices(string.ascii_letters + string.digits, k=k))
140+
return "".join(random.choices(string.ascii_letters + string.digits, k=k))

19_wod/wod.py

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Author : Luke McGuire <[email protected]>
4+
Date : 2024-07-01
5+
Purpose: Create Workout Of (the) Day (WOD)
6+
"""
7+
8+
import argparse
9+
import csv
10+
import io
11+
from pprint import pprint
12+
import random
13+
import re
14+
import sys
15+
from tabulate import tabulate
16+
17+
18+
# --------------------------------------------------
19+
def get_args():
20+
"""Get command-line arguments"""
21+
22+
parser = argparse.ArgumentParser(
23+
description="Create Workout Of (the) Day (WOD)",
24+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
25+
)
26+
27+
parser.add_argument(
28+
"-f",
29+
"--file",
30+
help="CSV input file of exercises",
31+
metavar="FILE",
32+
type=argparse.FileType("rt"),
33+
default="inputs/exercises.csv",
34+
)
35+
36+
parser.add_argument(
37+
"-s", "--seed", help="Random seed", metavar="int", type=int, default=None
38+
)
39+
40+
parser.add_argument(
41+
"-n",
42+
"--num",
43+
help="Number of exercises",
44+
metavar="exercises",
45+
type=int,
46+
default=4,
47+
)
48+
49+
parser.add_argument("-e", "--easy", help="Halve the reps", action="store_true")
50+
51+
args = parser.parse_args()
52+
53+
if args.num < 1:
54+
parser.error(f'--num "{args.num}" must be greater than 0')
55+
56+
return args
57+
58+
59+
# --------------------------------------------------
60+
def read_csv(fh):
61+
"""Read the CSV input"""
62+
63+
exercises = []
64+
for row in csv.DictReader(fh, delimiter=","):
65+
name, reps = row.get("exercise"), row.get("reps")
66+
if name and reps:
67+
match = re.match(r"(\d+)-(\d+)", reps)
68+
if match:
69+
low, high = map(int, match.groups())
70+
exercises.append((name, low, high))
71+
72+
return exercises
73+
74+
75+
# --------------------------------------------------
76+
def test_read_csv():
77+
"""Test read_csv"""
78+
text = io.StringIO("exercise,reps\nBurpees,20-50\nSitups,40-100")
79+
assert read_csv(text) == [("Burpees", 20, 50), ("Situps", 40, 100)]
80+
81+
82+
# --------------------------------------------------
83+
def main():
84+
"""Make a jazz noise here"""
85+
86+
args = get_args()
87+
random.seed(args.seed)
88+
89+
exercises = read_csv(args.file)
90+
91+
if not exercises:
92+
sys.exit(f'No usable data in --file "{args.file.name}"')
93+
94+
num_exercises = len(exercises)
95+
if args.num > num_exercises:
96+
sys.exit(f'--num "{args.num}" > exercises "{num_exercises}"')
97+
98+
workout = [("Exercise", "Reps")]
99+
100+
for exercise, low, high in random.sample(exercises, k=args.num):
101+
reps = random.randint(low, high)
102+
if args.easy:
103+
reps = reps // 2
104+
workout.append((exercise, reps))
105+
106+
print(tabulate(workout, headers="firstrow"))
107+
108+
109+
# --------------------------------------------------
110+
if __name__ == "__main__":
111+
main()

19_wod/wod_csv.py

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Author : Luke McGuire <[email protected]>
4+
Date : 2024-07-01
5+
Purpose: Create Workout Of (the) Day (WOD)
6+
"""
7+
8+
import argparse
9+
import csv
10+
import io
11+
from pprint import pprint
12+
import random
13+
import re
14+
from tabulate import tabulate
15+
16+
17+
# --------------------------------------------------
18+
def get_args():
19+
"""Get command-line arguments"""
20+
21+
parser = argparse.ArgumentParser(
22+
description="Create Workout Of (the) Day (WOD)",
23+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
24+
)
25+
26+
parser.add_argument(
27+
"-f",
28+
"--file",
29+
help="CSV input file of exercises",
30+
metavar="FILE",
31+
type=argparse.FileType("rt"),
32+
default="inputs/exercises.csv",
33+
)
34+
35+
parser.add_argument(
36+
"-s", "--seed", help="Random seed", metavar="int", type=int, default=None
37+
)
38+
39+
parser.add_argument(
40+
"-n",
41+
"--num",
42+
help="Number of exercises",
43+
metavar="exercises",
44+
type=int,
45+
default=4,
46+
)
47+
48+
parser.add_argument("-e", "--easy", help="Halve the reps", action="store_true")
49+
50+
args = parser.parse_args()
51+
52+
if args.num < 1:
53+
parser.error(f'--num "{args.num}" must be greater than 0')
54+
55+
return args
56+
57+
58+
# --------------------------------------------------
59+
def read_csv(fh):
60+
"""Read the CSV input"""
61+
62+
reader = csv.DictReader(fh, delimiter=",")
63+
exercises = []
64+
for rec in reader:
65+
name, reps = rec["exercise"], rec["reps"]
66+
# low, high = map(int, reps.split("-"))
67+
low, high = map(int, re.match(r"(\d+)-(\d+)", reps).groups())
68+
# low, high = map(int, re.findall(r"\d+", reps))
69+
exercises.append((name, low, high))
70+
71+
return exercises
72+
73+
74+
# --------------------------------------------------
75+
def test_read_csv():
76+
"""Test read_csv"""
77+
text = io.StringIO("exercise,reps\nBurpees,20-50\nSitups,40-100")
78+
assert read_csv(text) == [("Burpees", 20, 50), ("Situps", 40, 100)]
79+
80+
81+
def test_read_csv_empty():
82+
assert True
83+
84+
85+
def test_read_csv_bad_headers():
86+
assert True
87+
88+
89+
def test_read_csv_headers_only():
90+
assert True
91+
92+
93+
def test_read_csv_bad_reps():
94+
assert True
95+
96+
97+
# --------------------------------------------------
98+
def main():
99+
"""Make a jazz noise here"""
100+
101+
args = get_args()
102+
random.seed(args.seed)
103+
104+
exercises = read_csv(args.file)
105+
workout = [("Exercise", "Reps")]
106+
107+
for exercise, low, high in random.sample(exercises, k=args.num):
108+
reps = random.randint(low, high)
109+
if args.easy:
110+
reps = reps // 2
111+
workout.append((exercise, reps))
112+
113+
print(tabulate(workout, headers="firstrow"))
114+
115+
116+
# --------------------------------------------------
117+
if __name__ == "__main__":
118+
main()

0 commit comments

Comments
 (0)