Skip to content

CT 301 — Homework 1 Walkthrough

CT 301 · C++ Fundamentals

Homework 1
NUI Hardware Inventory

What you're building and how the pieces fit
The assignment

An inventory system for lab hardware

  • Track equipment, consumables, and gear borrowed from others.
  • Items can be loaned (and returned), sold, or surplused (retired).
  • The program reads two files, applies the changes, writes results to a file, and prints reports.

One idea runs through it all: select a collection of items, then print or act on it.

Running it

Three files, in order

make
./inventory <inventory_file> <transactions_file> <output_file>
  • inventory file → the starting items, one per line.
  • transactions file → the commands to apply, in order.
  • output file → where the final inventory is written (created for you).

PRINT/REPORT/GROUP_BY go to the screen; the final state goes to the output file.

The three item types

Same base, different behavior

TypeLoanable?ValueNotes
EquipmentYes (unless broken)DepreciatesOwned hardware; has conditions
ConsumableNounit × quantityBulk supplies
BorrowedNo0Ours? No. Only returnable

Each derives from Item and answers the same calls (canLoan, currentValue, attribute, printTo) its own way.

Equipment conditions

obsolete, broken, and the dates

  • obsolete: end-of-life but still works. Informational only, value and loanability unchanged (a Magic Leap 1 still runs).
  • broken: doesn't work. Value becomes 0.00 and it can't be loaned.
  • warranty_end / support_end: vendor dates. Past warranty → NoRMA (no return path).
  • surplus candidate = broken AND NoRMA (computed): worth retiring.
Value rules

currentValue() must match exactly

// reference "today" = 2026-06-01
Equipment:  broken → 0.00
            else base × (1 − 0.20 × fullYears), floor = base × 0.10
Consumable: unit × quantity
Borrowed:   0.00

Grading compares your output exactly, so the value math has to be precise. The obsolete flag and dates do not change value.

How the pieces fit

Inventory owns; selections borrow

  • The Inventory owns every item as unique_ptr<Item>, in four lists, one per state.
  • Selection returns borrowed Item* pointers. Action moves items between lists. Output prints them.
  • Commands wrap each transaction verb; they call the matching inventory operation.
transactions file → Command objects → execute() → Inventory ops
The transaction model

A "current selection" carried line to line

  • A selection verb sets the current selection (e.g. BY brand Razer).
  • An output verb (PRINT) shows it; an action verb (SURPLUS) acts on it.
  • After an action, the selection becomes the rejects, what it could not do, so a following PRINT shows them.
OLDER_THAN 2021-01-01   # select old items
SURPLUS                 # retire them; rejects become the selection
IN_STATE OnLoan
PRINT                   # list what is still on loan
The pattern you'll repeat

Every action looks like this

for (Item* p : items) {
  if (p->state() != State::InStock || !p->canSurplus()) {
    rejects.push_back(p); continue;        // not allowed
  }
  auto owned = extract(inStock_, p->id());     // take ownership out
  owned->setState(State::Surplus);
  surplus_.push_back(std::move(owned));         // move into new list
}
return rejects;

surplus is done for you. sell, loan, return follow the same shape.

Rules you must enforce

What the system must refuse

  • A Consumable can never be loaned.
  • A broken item can't be loaned.
  • An item OnLoan can't be sold or surplused.
  • A Borrowed item can't be loaned, sold, or surplused, only returned.
  • An item is in exactly one state at a time.

These hold on their own if each action accepts only items in the right starting state and type.

The starter code

What's provided vs. what you write

Provided

  • All headers, the input layer, main, the makefile.
  • The three inventory helpers + one worked example (surplus).
  • PrintCommand as the command example.
  • Sample data + a starter test file.

You write

  • Date operators.
  • All of items.cpp.
  • The rest of inventory.cpp.
  • The remaining command execute() bodies.

Stubs compile and run out of the box; each has a // remove when you implement this line.

Tooling

Build clean, run clean

  • C++26, GCC 15.2, built with the provided makefile.
  • Flags include -Wall -Wextra -Wpedantic: your code must compile with no warnings.
  • Sanitizers (-fsanitize=address,undefined) must report zero issues.
  • No raw owning pointers, new, delete, malloc, calloc, realloc, or free.

With correct unique_ptr use, the sanitizers pass on their own, you write no delete.

Checking your work

Testing is part of the assignment

  • A small sample ships with its expected output. Run it and diff to compare.
  • A larger sample ships without expected output, reason about correctness yourself.
  • student_tests.cpp has a few example tests and a TODO list, you add more.
./inventory data/appx_inventory.txt data/appx_transactions.txt myout.txt > mystd.txt
diff myout.txt   data/appx_output.txt
diff mystd.txt   data/appx_stdout.txt
Grading

100 points, automated

ComponentPts
Compiles cleanly (no warnings)5
Runs clean under ASan/UBSan10
Bookkeeping actions (add, loan, return, sell, surplus)15
Selection, grouping, aggregation25
Invariants enforced15
Type behavior & value rules15
Output & report format15
Penalty: raw new/delete/malloc/free−20
The professor reserves the right to award or deduct points for any aspect of the assignment not explicitly listed above.
How to start

A sensible order of attack

  • 1. Date operators, then run the build.
  • 2. items.cpp: currentValue, attribute, printTo per type. Match the sample output.
  • 3. Inventory selections, then aggregations.
  • 4. Actions (copy the surplus pattern), then report and write.
  • 5. Command execute() bodies (each is one line).

Build and diff against the sample after each step. Read the spec, Appendix A is your target output.

Start early. Test often.

The ownership rules from Part 1 are the whole game. Move, don't copy; borrow, don't own.