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 admin and the access code is A1337;
  • 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:

RoleCodeAgeExpected
adminA133715ADMIN
adminwrong15USER
useranything15USER
useranything10GUEST
adminwrong10GUEST

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 <= 10STOP: LOW BATTERY;
  • otherwise obstacle distance < 20STOP: 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 and condition;
  • 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.