Evidence Inventory
Apologetic question: "Did the Resurrection happen?"
Project 7 — Evidence Inventory
“For I delivered to you as of first importance what I also received: that Christ died for our sins in accordance with the Scriptures, that he was buried, that he was raised on the third day in accordance with the Scriptures, and that he appeared…” — 1 Corinthians 15:3–5
(One of the earliest dated creeds in the New Testament — by scholarly consensus, formulated within roughly five years of the events. Use that as one piece of evidence in your inventory.)
Chapter: 7 — Grouping Memory: Structs
Due: End of Week 7
Submit: A link to your code — an OnlineGDB project URL or a public GitHub repo URL — with evidence.cpp as the main source file. See Appendix D for the full workflow.
Allowed tools: Everything through Chapter 7 — types, conditionals, loops, functions, arrays, strings, structs.
Not yet allowed: Classes, dynamic memory.
The Setup
Christian historical apologetics — especially around the central claim of the Resurrection — has, since at least the 1970s, made heavy use of what Gary Habermas calls the “minimal facts” approach. The idea: rather than relying on the inerrancy of the Gospels (which is its own argument), identify a small set of facts that the overwhelming majority of historians of all persuasions accept as historically credible, and then ask what best explains them.
The standard set varies a little by author, but the canonical list includes things like:
- Jesus’ death by crucifixion. Accepted by essentially every historian.
- The empty tomb tradition. Disputed by some, but the tradition itself (early, multiply-attested) is broadly accepted.
- The post-mortem appearances. That the disciples reported having seen the risen Jesus is broadly accepted (whether the appearances were real is what’s debated).
- The early Christian creed of 1 Corinthians 15:3–7. Dated by most scholars to within ~5 years of the events — strikingly early.
- The transformation and martyrdom of the disciples. People who could have walked away from the claim chose not to, often at great personal cost.
- The conversion of Paul. A persecutor of the church becomes its most active missionary, on the strength of a claimed encounter.
- The conversion of James. Jesus’ brother, who was a skeptic during the ministry, becomes a leader of the Jerusalem church.
You can find longer lists. Wright’s three-volume Christian Origins and the Question of God is the heavyweight academic case. McGrew’s Bayesian analysis pushes the formal probability work. Habermas’s The Risen Jesus and Future Hope is the accessible summary. None of these are required reading for this project — but if any of them are in your library or your university’s library, browse them while you build this. The data shape will feel familiar.
This project: build an inventory of evidence. Each piece is a struct. Add, remove, list, search, filter, weigh. By the end you will have, in code, a small structured representation of the case you might one day be asked to make over a coffee.
Coach’s Note (confessional Lutheran framing) — The minimal-facts approach is one mode of intellectual engagement, not the foundation of Christian faith. In the Lutheran tradition (Augsburg Confession V), saving faith is created and sustained by the Word and the Sacraments — not by a sufficient stack of historical probabilities. The evidence is real, the data is striking, and you should know it. But the inventory in this project is a tool for the conversation, not a proof that converts. Sources of the same data: Habermas (Evangelical), Wright (Anglican), Plantinga (Reformed). For an explicitly Lutheran take on apologetics, see John Warwick Montgomery’s History, Law, and Christianity or Rod Rosenbladt’s lectures.
Learning Targets
By completing this project, you will demonstrate that you can:
- Define a non-trivial struct with multiple field types.
- Maintain an array of structs with a count variable.
- Pass structs to functions by value and by reference (and
const &). - Implement add, remove, search, filter operations on a struct array.
- Compute aggregate statistics over a struct array.
- Use a
charfield for category-style data.
Normal Tier
Goal: A menu-driven inventory of up to 25 pieces of evidence, each a struct.
Required features
-
Define the
Evidencestruct with at least these fields:struct Evidence { string claim; // a short statement of the evidence string source; // who/where attests it string type; // e.g., "textual", "historical", "archaeological", "experiential" int strength_rating; // 1-10 int year; // earliest credibly attested year }; -
Seed data: Pre-populate the inventory with at least 6 real pieces of evidence. Use the canonical Resurrection minimal-facts list above (or another carefully-chosen historical claim — apologetics for the historical reliability of the Gospels, for the existence of God via the moral argument, for the early dating of NT documents — any one would work). The data must be real: don’t make up sources or invent claims. The grader will check.
-
Menu loop with these options:
1. Add a piece of evidence— prompt for all fields. Reject ifstrength_ratingis outside 1–10. Reject if the inventory is full.2. Remove by claim— prompt for the claim string, find it (case-insensitive), shift others down.3. List all— prints a formatted table of all current entries (withstrength_ratingandyear).4. Find by claim— case-insensitive search.5. Exit
-
Functions, not inline code. Each operation lives in a named function (
add_evidence,remove_evidence,list_evidence,find_evidence).mainis the menu loop. -
Compiles cleanly with
-Wall -Wextraenabled. No warnings.
Example table output
=== Evidence Inventory (6 entries) ===
# Claim Source Type Strength Year
1 Jesus' death by crucifixion Multiple Gospels, Tacitus historical 10 AD 30
2 Empty tomb tradition All four Gospels textual 8 AD 35
3 Post-mortem appearance tradition 1 Cor 15:3-7 creed textual 9 AD 35
4 Conversion of Paul Acts, Pauline epistles historical 10 AD 35
5 Conversion of James 1 Cor 15:7, Acts historical 8 AD 35
6 Martyrdom of multiple eyewitnesses Patristic sources historical 7 AD 60
Aim for well-formatted output; column alignment is appreciated but not required. Tabs and a consistent field order are enough. (Pixel-perfect alignment usually means reaching for <iomanip>::setw, which we’ll cover later — for now, readable beats ruler-straight.)
Grading rubric — Normal (out of 100)
| Criterion | Points |
|---|---|
Compiles cleanly with -Wall -Wextra | 10 |
Evidence struct correctly declared with 5+ fields | 10 |
| Seed data: at least 6 real entries, sources verifiable | 15 |
add_evidence validates strength_rating (1-10) | 10 |
remove_evidence works with shift-down | 10 |
list_evidence prints a formatted table | 10 |
find_evidence case-insensitive | 10 |
Functions take structs by value or const & appropriately | 10 |
main is menu + dispatch — no business logic | 10 |
| OnlineGDB/GitHub link + reflection comment block | 5 |
Medium Tier (+up to 25% extra credit)
M1. Freshness and review
Add a freshness field (int, starts at 100) to the Evidence struct. Add a menu option Review evidence by claim. Reviewing decrements freshness by, say, 10. When freshness reaches 0, the evidence is automatically removed from the inventory and a message printed:
[The evidence "X" has not been re-examined recently and has been moved to a needs-attention queue.]
(For Medium tier you don’t actually need a separate queue — just remove it and print the message. The “needs attention” framing is for the user.)
This is the analog to a Resurrection-tradition lecture: scholarship moves, sources get reconsidered, and any piece of evidence benefits from being re-checked periodically.
M2. Case strength total
Add a menu option Show case strength. Compute the sum of strength_rating across all current entries. Print:
Case strength: 52 (across 7 pieces of evidence; average 7.4)
Use a function int total_strength(const Evidence[], int count) and a function double average_strength(const Evidence[], int count). No business logic in main — push computation into functions.
M3. Filter by type
Add a menu option Filter by type. Prompts for a type string (textual, historical, etc.) and prints all entries of that type. Show the case-strength subtotal for that type.
Hard Tier (+up to 25% additional extra credit)
The Hard tier foreshadows polymorphism with category-specific behaviors.
H1. Category char and dispatch
Add a char category field to the Evidence struct:
'T'— textual'H'— historical'A'— archaeological'E'— experiential
Implement category-specific review functions:
void review_textual(Evidence& e)— decrements freshness by 5 (textual evidence ages slowly).void review_historical(Evidence& e)— decrements by 10.void review_archaeological(Evidence& e)— toggles abool currently_disputedfield. (Add this field to the struct too.)void review_experiential(Evidence& e)— decrementsstrength_ratingby 1 if it’s above 3, otherwise leaves it alone. (Experiential evidence is the most volatile.)
Then write void review_evidence(Evidence& e) that dispatches based on category:
void review_evidence(Evidence& e) {
switch (e.category) {
case 'T': review_textual(e); break;
case 'H': review_historical(e); break;
case 'A': review_archaeological(e); break;
case 'E': review_experiential(e); break;
default: break;
}
}
Coach’s Note — This switch-based dispatch is what polymorphism replaces. Hold this code in your head — in two weeks (Chapter 12) you’ll write the same logic without any
switch, usingvirtualmethods on a class hierarchy. The compiler will dispatch for you. This is the foreshadowing the project arc keeps mentioning.
H2. Save and load
Use file I/O — <fstream> — to save the inventory to a text file and reload it next session. Each line of the file is one piece of evidence, with fields separated by |:
Jesus' death by crucifixion|Tacitus, Annals 15.44|historical|10|30|H
Empty tomb tradition|Mark 16; Matthew 28; Luke 24; John 20|textual|8|35|T
Implement:
void save_inventory(string filename, const Evidence[], int count)— writes the file.int load_inventory(string filename, Evidence[], int max)— reads the file, returns the count loaded.
getline with a custom delimiter character is the trick. Look it up.
Coach’s Note — File I/O isn’t formally covered in this course (it’s a Chapter 12-equivalent topic in many curricula). Adding it here is genuinely a stretch — that’s why it’s Hard. If it takes you longer than 4 hours, ship without it.
H3. The flex move
Find one C++ feature not covered this chapter. Strong candidates:
std::vector<Evidence>— dynamic array.- Operator overloading: define
bool operator<(const Evidence& a, const Evidence& b)so you can usestd::sortwith built-in comparison. - A
staticcounter inside a function (e.g., total reviews performed across the session).
Document per Project 1 H4 rules.
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 —
evidence.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 struct is getting cluttered.” Six fields is fine. Eight is the upper end of comfortable. If you’re at twelve, you may be modeling too much in one type — break it up.
- “Comparing strings in
find_evidenceis annoying.” Reuse your case-insensitive helper from Project 6. - “Removing from the middle keeps a hole.” Shift down:
for (int j = i; j < count - 1; j++) { inv[j] = inv[j + 1]; }thencount--;. The whole struct is copied per iteration; no parallel-array drift possible. - “My case-strength computation is wrong.” Make sure you’re iterating only up to
count, not to the array’s full size. Empty slots may have garbage values. - “I want to use a class instead of a struct.” Hold off until Chapter 9. The point of this week is to feel structs working — and to feel the absence of methods. Project 9 introduces classes, and you can revisit then.
- “How long should this take me?” Normal: 3–5 hours. Medium: 5–9 hours. Hard: 8–14 hours (file I/O is the time sink).
What Mastery Looks Like
A great Project 7 has honest data. Every piece of evidence corresponds to something a real scholar has actually argued. Sources are real (Tacitus is real; “TacitusBook15.44” is a real citation; “Tacitus said the disciples saw Jesus” is not real, because he didn’t say that). Dates are real (the 1 Corinthians 15 creed really does date to ~AD 35 by most scholars; you didn’t make that up).
A great Project 7 has bundled data. Removing a piece of evidence doesn’t risk leaving its source or strength dangling somewhere. The struct does the bundling. The functions operate on bundled data.
A great Project 7 has short, sharp functions. Each one does a single thing. total_strength returns an int. review_textual modifies an Evidence&. find_by_claim returns an int. Combined in main, they form a small, readable database engine.
A great Project 7 is something you might actually use. Run it. Look at your inventory. Could you imagine showing this to a friend who asked the question? If so — and if the data is real — you’ve done something genuinely apologetic. Not by winning an argument. By being able to point at the data.
When You’re Done
- Read your
evidence.cppaloud. Each function does one thing. The struct’s fields are clearly named. - Run a stress test: add 5 entries, remove 1, list, filter by type, review. Anything break?
- Update README. Verify your sources.
- Submit.
- Prepare for the midterm. Chapter 8 / Project 8 is next — a 75-minute live exam over everything in Chapters 1–7.
Coach’s Note — This is the last project before the midterm. If you can ship a clean Normal here, you have all the procedural C++ chops the midterm tests. If Medium and Hard worked too, you’ll cruise. Use this weekend to consolidate. Read your code from Projects 1–7 side by side. The patterns repeat. By the time you sit down to the midterm, the patterns should feel familiar.
See you in the exam room.