Unit 04 · lesson
Build an Access Control Simulator
Core path: 35 minutes
A decision system is only useful if the rules are clear enough that two different people can test the same inputs and expect the same result.
This build gives you a small fictional access-control system with three outcomes: GUEST, USER, and ADMIN.
Do not treat this as a security product. It is a control-flow exercise. The point is to make branch priority, compound conditions, and boundary cases visible.
Collect the inputs
username = input("Username: ")
age = int(input("Age: "))
role = input("Role: ")
access_code = input("Access code: ")
Normalize the role:
role = role.lower()
That turns values such as Admin, ADMIN, and admin into one predictable representation.
The system rules are:
- ADMIN — role is
adminand the access code isA1337; - USER — age is at least 13;
- GUEST — everyone else.
Before writing the branches, ask which rule has to win if more than one condition could be true.
Build the branch order deliberately
A sensible version starts with the most specific rule:
if role == "admin" and access_code == "A1337":
print("ADMIN ACCESS GRANTED")
elif age >= 13:
print("USER ACCESS GRANTED")
else:
print("GUEST ACCESS")
The order matters because Python stops at the first true branch in an if/elif/else chain.
This version is valid Python but wrong for our rule set:
if age >= 13:
print("USER ACCESS GRANTED")
elif role == "admin" and access_code == "A1337":
print("ADMIN ACCESS GRANTED")
else:
print("GUEST ACCESS")
A 30-year-old administrator with the correct code becomes USER because age >= 13 is already true. Python never reaches the administrator check.
That is a logic bug. The program runs. The decision is wrong.
Test from a table, not from vibes
Create these cases before you run the program:
| Role | Code | Age | Expected |
|---|---|---|---|
| admin | A1337 | 15 | ADMIN |
| admin | wrong | 15 | USER |
| user | anything | 15 | USER |
| user | anything | 10 | GUEST |
| admin | wrong | 10 | GUEST |
Run every case.
When one fails, do not immediately rewrite the whole branch chain. Trace the conditions in order.
Add a rule that outranks everything else
New requirement:
If the username is blank, deny access.
A blank username is represented by:
username == ""
Put the denial check before the normal access rules:
if username == "":
print("ACCESS DENIED")
elif role == "admin" and access_code == "A1337":
print("ADMIN ACCESS GRANTED")
elif age >= 13:
print("USER ACCESS GRANTED")
else:
print("GUEST ACCESS")
Why first?
Because branch priority is part of the policy. A later branch does not get a chance once an earlier one succeeds.
Explain one complete decision
Choose one test case and write the trace:
Input values:
username =
age =
role =
access_code =
blank username check → True / False
admin rule → True / False
age rule → True / False
branch executed →
why Python stopped there →
If you can only tell me the final output, you have not explained the decision system yet.
Optional robot version
Build the same idea with robot state:
- battery
<= 10→STOP: LOW BATTERY; - otherwise obstacle distance
< 20→STOP: OBSTACLE; - otherwise manual override enabled →
MANUAL CONTROL; - otherwise →
CONTINUE AUTONOMOUSLY.
Notice the same design problem: priority.
Low battery must win even if manual override is enabled. The ordering of the code is part of the behavior.
Success evidence
Your finished program should include:
- normalized role input;
- at least three access outcomes plus denial;
- one compound
andcondition; - a test table with expected results;
- one intentionally broken branch order and an explanation of the wrong outcome; and
- one complete condition-by-condition trace.
The code is not done because the happy path works. It is done when you can predict the awkward cases too.