Project 4

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 for loop with a known iteration count.
  • Use a while loop 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

  1. Prompt the user for:

    • practice_name — a string (one word, e.g., "Scripture", "Prayer").
    • num_days — an int.
    • Then loop num_days times, 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.
  2. 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.
  3. Compiles cleanly with -Wall -Wextra enabled in OnlineGDB compiler settings (or g++ -Wall -Wextra if you build locally). No warnings, no errors.

  4. 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)

CriterionPoints
Compiles cleanly with -Wall -Wextra10
Reads practice name and num_days5
Outer loop runs exactly num_days times10
Inner loop renders bar chart of correct length15
Total reps computed correctly10
Average computed correctly (no integer-division bug)15
Header includes practice name5
Each day line is formatted clearly10
Negative input handled gracefully10
OnlineGDB/GitHub link + reflection comment block10

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::setw and std::setfill from <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 const for the week-length, so you don’t have 7s 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 -Wextra in 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

  1. The main source filepractice_tracker.cpp — containing your full solution.
  2. 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.
 */
  1. 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. setw from <iomanip> is the clean fix.
  • “My average is always a whole number.” Integer division. Cast one operand to double before 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_reps and best_day_number. Inside the loop, whenever the current day’s reps beat best_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

  1. Read your own practice_tracker.cpp aloud. Could you predict the output before running it?
  2. Run it three times — with 1 day, 4 days, and 7 days of input. Anything break?
  3. Update your README with what you actually tracked.
  4. Submit.
  5. 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.