Daily Practice Tracker
Apologetic question: "Is faith just intellectual?"
Project 4 — Daily Practice Tracker
“He who began a good work in you will bring it to completion at the day of Jesus Christ.” — Philippians 1:6
Chapter: 4 — Repetition I: Loops
Due: End of Week 4
Submit: A link to your code — an OnlineGDB project URL or a public GitHub repo URL — with practice_tracker.cpp as the main source file. See Appendix D for the full workflow.
Allowed tools: Everything through Chapter 4 — types, arithmetic, cin/cout, conditionals, while/do…while/for loops, counters, accumulators, sentinels, nested loops.
Not yet allowed: Functions you define yourself, arrays.
The Setup
There’s a thing your Christian tradition has known about for a very long time and that modern productivity culture has rediscovered with great surprise: what you become is what you do, day after day.
Discipline is the formal name for that. Christian disciplines — Scripture reading, prayer, memorization, fasting, almsgiving, service, worship, examen — are not arbitrary religious chores. They are practices that form a person. Done with intention over years, they form a Christian. Done with no intention at all, your culture forms you anyway, and not always in the direction you’d choose.
This project doesn’t ask you to commit to any particular practice. It asks you to track one. You pick. Scripture reading is the easy default. Prayer is harder to quantify but works (you can count minutes or count practices). Memorization works well (chapters memorized, verses reviewed). So does Bible study, daily examen, journaling, or — yes — physical training. The point isn’t which practice. The point is the loop.
You’re going to build a small program that records reps across days, computes stats, and produces a small picture of your week. By Friday afternoon you’ll have run it once. By Sunday night you’ll have run it seven times. You’ll see what a week of intention actually looks like, from data. That’s worth more than most apologetics arguments.
Learning Targets
By completing this project, you will demonstrate that you can:
- Use a
forloop with a known iteration count. - Use a
whileloop with a sentinel value. - Compute running counters and accumulators.
- Compute averages, max, min from a sequence of inputs.
- Use nested loops to model two-dimensional iteration.
- Render structured visual output to the terminal (rows of characters representing reps).
Normal Tier
Goal: A program that takes a practice name and a number of days, then takes one input per day, and reports back with totals, average, and a small bar-chart visualization.
Required features
-
Prompt the user for:
practice_name— astring(one word, e.g.,"Scripture","Prayer").num_days— anint.- Then loop
num_daystimes, each iteration:- Prompt for that day’s reps (an
int). - Print a “day N: **** (reps)” line where the number of
*(or#if you prefer) characters matches the rep count. Hint: this is a nested loop — outer over days, inner over reps to draw the bar.
- Prompt for that day’s reps (an
-
After the loop, print a summary:
- Total reps across all days.
- Average reps per day (a
double, no integer-division bugs). - The practice name in a one-line header.
-
Compiles cleanly with
-Wall -Wextraenabled in OnlineGDB compiler settings (org++ -Wall -Wextraif you build locally). No warnings, no errors. -
Reasonable input validation — if the user enters a negative rep count, you can either treat it as 0 or re-prompt. Crashes are not acceptable.
Example output (with practice=“Scripture”, num_days=5, reps=3 5 2 8 4)
=== Scripture: 5-day log ===
Day 1: *** (3 reps)
Day 2: ***** (5 reps)
Day 3: ** (2 reps)
Day 4: ******** (8 reps)
Day 5: **** (4 reps)
Total: 22 reps over 5 days.
Average: 4.4 reps per day.
Grading rubric — Normal (out of 100)
| Criterion | Points |
|---|---|
Compiles cleanly with -Wall -Wextra | 10 |
| Reads practice name and num_days | 5 |
Outer loop runs exactly num_days times | 10 |
| Inner loop renders bar chart of correct length | 15 |
| Total reps computed correctly | 10 |
| Average computed correctly (no integer-division bug) | 15 |
| Header includes practice name | 5 |
| Each day line is formatted clearly | 10 |
| Negative input handled gracefully | 10 |
| OnlineGDB/GitHub link + reflection comment block | 10 |
Medium Tier (+up to 25% extra credit)
M1. Sentinel-controlled loop
Replace the “ask num_days, then loop num_days times” pattern with a sentinel loop. The user enters reps one day at a time and types -1 to stop. Compute the same stats, but additionally:
- Track and report the best day (highest reps, and which day number it was).
- Track and report the worst day (lowest reps, and which day number).
- Ask the user up-front for a target rep count (say,
5). After the sentinel loop completes, report the longest streak of consecutive days at or above that target. Print which day the streak started.
Coach’s Note — Computing a streak relative to a user-supplied target is the right shape for this rep. You’d think you could compute “consecutive days above the average,” but without arrays you don’t have the data to walk twice — and asking the user to re-type a week of numbers is bad design (don’t do that in real software). The target version is honest single-pass code: maintain a running streak counter; reset to 0 when a day falls below target; track the max streak seen so far. That’s exactly the streak pattern from §4.2.
M2. Verbose mode toggle
Add a bool verbose_mode that, when true, prints additional per-day insight:
Day 3: ** (2 reps) — below average (-1.33 from mean so far)
Day 4: ******** (8 reps) — above average (+3.5 from mean so far)
Ask the user up front whether they want verbose mode (y/n). Use if inside the loop.
This forces you to compute the running mean inside the loop, not just after. (Or accept that “average so far” includes the current day’s reps — which is a defensible design choice; document it in your README.)
M3. Cleaner output
Add structure to the summary. Header + body + footer with borders. Use blank lines between sections. The summary should look intentional, not slapdash.
Hard Tier (+up to 25% additional extra credit)
The Hard tier brings in nested loops for a real reason: a weekly calendar grid with multiple practice types.
H1. Weekly calendar grid
Track a week (7 days) of multiple practice types. Pick at least 3 (e.g., Scripture, prayer, memorization, service).
The user enters reps day-by-day for each practice. Then your program prints a calendar grid with days as columns and practices as rows:
Practice Mon Tue Wed Thu Fri Sat Sun | Total
---------------------------------------------|-------
Scripture 5 7 4 10 6 2 8 | 42
Prayer 2 2 2 2 2 2 2 | 14
Memorization 5 0 0 3 0 0 0 | 8
---------------------------------------------|-------
Daily total 12 9 6 15 8 4 10 | 64
Render this with nested loops. Use string concatenation, \t, or careful spaces for alignment. (You don’t have arrays, so you’ll need to use multiple variables per practice. Painful — and that pain is the point. Chapter 6 fixes this.)
H2. Imbalance flag
After printing the grid, compute the total reps for the week. Then check: does any single practice exceed 60% of the week’s total? If so, print a one-line note:
Note: Scripture made up 66% of your week — your training is leaning hard
on one discipline. Worth checking whether that's intentional.
This isn’t a moral judgment from your program. It’s a flag to you, the user. Discipline that’s all-of-one-thing-no-other-things may or may not be the right balance — you decide. The program just makes it visible.
Implementation: after computing each practice’s total, divide by the week total (watch integer division), check against 0.6, and print the note conditionally. If multiple practices exceed 60%, print only the worst offender.
H3. The flex move
Find one C++ feature we haven’t covered and use it deliberately. Strong candidates:
std::setwandstd::setfillfrom<iomanip>for clean column alignment.std::string(n, '*')to build a string of N repeated characters without an inner loop. (Yes, this exists. Look it up — it’s beautiful.)- A
constfor the week-length, so you don’t have7s sprinkled throughout your code.
Document per the same rules as previous flex moves.
Submission
Submit one URL via the course portal:
- OnlineGDB project link (recommended for Coding 1 and Coding 2). Create your project at onlinegdb.com, set compiler flags to
-Wall -Wextrain the project settings, build your solution, and share the link. See Appendix D for the full workflow. - GitHub repo link (optional). If you’ve set up local development on your own, push the source to a public repo and submit that URL. You’re responsible for making sure the code compiles when the grader checks it out.
What the linked project must contain
- The main source file —
practice_tracker.cpp— containing your full solution. - A reflection comment block at the very top of that file:
/*
* Tier targeted: Normal / Medium / Hard
* Features done: list each feature you completed
* What I learned: one short paragraph (no bullets)
* What I'd change: one sentence
* AI usage: where and how, if any. Be honest.
*/
- The program left in a “demonstrable” state — when the grader presses Run, the features for your targeted tier should be exercised. Hard-code inputs at the top of
main()(or pre-fill OnlineGDB’s Stdin panel) so the grader doesn’t have to guess what to type.
That’s it. No separate demo.txt. No screenshots. The instructor will open your link, read the comment block, run the program, and grade against the rubric.
Coach’s Note — Coding 1 and Coding 2 focus on writing code, not managing development environments. If something behaves oddly, you and the grader are looking at the exact same browser-hosted environment — there are no “works on my machine” defenses by design. Coding 3 will introduce a local toolchain properly.
Hints
- “My bars don’t line up.” Different rep counts produce different line widths. Either accept that (Normal tier doesn’t require alignment past the bar), or add padding spaces to align the “(N reps)” label.
setwfrom<iomanip>is the clean fix. - “My average is always a whole number.” Integer division. Cast one operand to
doublebefore dividing. - “My streak count is off-by-one.” The most common bug is initializing the streak counter to 1 instead of 0 (or vice versa). Trace one example by hand to find which.
- “How do I track ‘best day’ without arrays?” Maintain two variables:
best_repsandbest_day_number. Inside the loop, whenever the current day’s reps beatbest_reps, update both. That’s it. - “This is annoying without arrays.” Yes. That’s intentional. Chapter 6 brings arrays. Suffer through it.
- “How long should this take me?” Normal: 2–4 hours if you did the Reps. Medium: 3–5 hours. Hard: 5–8 hours (the calendar grid is where the time goes).
What Mastery Looks Like
A great Project 4 prints data that means something. The numbers correspond to actual days you actually practiced something actual. The week summary tells you something true about your week — not “Day 1: 3 reps” of generic placeholder, but specific data you wrote yourself.
A great Project 4 handles the integer-division trap silently — your average is always a clean double, computed correctly, even when the totals are weird.
A great Project 4’s bar chart is readable. A stranger glancing at the output can tell which day was busy and which day was light without reading numbers.
A great Project 4 survives running it seven days in a row. Run it on Monday with one day of data. Run it Tuesday with two. Run it Sunday with seven. The program should handle every case cleanly.
When You’re Done
- Read your own
practice_tracker.cppaloud. Could you predict the output before running it? - Run it three times — with 1 day, 4 days, and 7 days of input. Anything break?
- Update your README with what you actually tracked.
- Submit.
- Read Chapter 5. We package up repeatable thought into functions.
Coach’s Note — This is the project where the apologetics frame stops being theoretical. You can argue all day that Christianity is “lived, not just thought.” This project is the receipt. If you tracked something real this week — anything, even small — you have a small piece of evidence that the question can be answered with data. That’s not the whole apologetic case for lived faith, but it’s a piece. Save the file. You’re going to want it later.
See you on Monday.