Skip to content

Commit 68a08f8

Browse files
travisjneumanclaude
andcommitted
feat: add 15 interactive concept quizzes
Terminal-based quizzes testing understanding of each concept doc. No external dependencies — pure Python input()/print(). Immediate feedback with explanations and concept doc references. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7e0ba8a commit 68a08f8

16 files changed

Lines changed: 2630 additions & 0 deletions

concepts/quizzes/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Concept Quizzes
2+
3+
Interactive terminal quizzes that test your understanding of each concept doc in `concepts/`.
4+
5+
## How to Run
6+
7+
Each quiz is a standalone Python script with zero dependencies. Run any quiz from the repo root or the `concepts/quizzes/` directory:
8+
9+
```bash
10+
python concepts/quizzes/what-is-a-variable-quiz.py
11+
python concepts/quizzes/how-loops-work-quiz.py
12+
python concepts/quizzes/functions-explained-quiz.py
13+
# ... etc.
14+
```
15+
16+
No virtual environment or pip install needed -- every quiz uses only the Python standard library.
17+
18+
## What They Test
19+
20+
Each quiz matches one concept doc and tests *understanding*, not memorization. You will see questions like "What will this code print?" and "Which approach is correct?" rather than "What page covers X?"
21+
22+
## Quiz List
23+
24+
| Quiz Script | Concept Doc | Topics |
25+
|---|---|---|
26+
| `what-is-a-variable-quiz.py` | `what-is-a-variable.md` | Naming rules, assignment vs comparison, scope |
27+
| `how-loops-work-quiz.py` | `how-loops-work.md` | for/while loops, range(), common pitfalls |
28+
| `functions-explained-quiz.py` | `functions-explained.md` | def, return, parameters, default values |
29+
| `collections-explained-quiz.py` | `collections-explained.md` | Lists, dicts, sets, tuples, mutability |
30+
| `files-and-paths-quiz.py` | `files-and-paths.md` | open(), with, read/write modes, pathlib |
31+
| `errors-and-debugging-quiz.py` | `errors-and-debugging.md` | Error types, tracebacks, debugging strategy |
32+
| `types-and-conversions-quiz.py` | `types-and-conversions.md` | str/int/float/bool, truthy/falsy, conversion |
33+
| `how-imports-work-quiz.py` | `how-imports-work.md` | import, from, packages, search path |
34+
| `classes-and-objects-quiz.py` | `classes-and-objects.md` | self, __init__, methods, inheritance |
35+
| `decorators-explained-quiz.py` | `decorators-explained.md` | @syntax, wrapping, functools.wraps |
36+
| `virtual-environments-quiz.py` | `virtual-environments.md` | venv, activate, requirements.txt |
37+
| `the-terminal-deeper-quiz.py` | `the-terminal-deeper.md` | Pipes, redirects, env vars, shortcuts |
38+
| `http-explained-quiz.py` | `http-explained.md` | Methods, status codes, headers, JSON |
39+
| `api-basics-quiz.py` | `api-basics.md` | REST conventions, requests, auth |
40+
| `async-explained-quiz.py` | `async-explained.md` | async/await, event loop, gather |
41+
42+
## Format
43+
44+
Each quiz has 5-8 questions mixing multiple choice and short answer. You get immediate feedback after every question with a brief explanation, plus a final score and percentage.
45+
46+
## Recommended Order
47+
48+
Follow the concept docs in curriculum order:
49+
50+
1. Variables
51+
2. Loops
52+
3. Functions
53+
4. Collections
54+
5. Files and Paths
55+
6. Errors and Debugging
56+
7. Types and Conversions
57+
8. Imports
58+
9. Classes and Objects
59+
10. Decorators
60+
11. Virtual Environments
61+
12. The Terminal (Deeper)
62+
13. HTTP
63+
14. API Basics
64+
15. Async
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"""
2+
Quiz: API Basics
3+
Review: concepts/api-basics.md
4+
"""
5+
6+
7+
def run_quiz():
8+
print("=" * 60)
9+
print(" QUIZ: API Basics")
10+
print(" Review: concepts/api-basics.md")
11+
print("=" * 60)
12+
print()
13+
14+
score = 0
15+
total = 7
16+
17+
# Question 1
18+
print("Question 1/7: What does API stand for?")
19+
print()
20+
print(" a) Advanced Programming Interface")
21+
print(" b) Application Programming Interface")
22+
print(" c) Automated Program Integration")
23+
print(" d) Application Process Integration")
24+
print()
25+
answer = input("Your answer: ").strip().lower()
26+
if answer == "b":
27+
score += 1
28+
print("Correct! Application Programming Interface — a way for")
29+
print("programs to talk to each other.")
30+
else:
31+
print("Incorrect. The answer is b) Application Programming Interface.")
32+
print()
33+
34+
# Question 2
35+
print("Question 2/7: In REST, what HTTP method and URL pattern")
36+
print("would you use to get a specific user with ID 42?")
37+
print()
38+
print(" a) POST /users/42")
39+
print(" b) GET /users/42")
40+
print(" c) GET /users?id=42")
41+
print(" d) FETCH /users/42")
42+
print()
43+
answer = input("Your answer: ").strip().lower()
44+
if answer == "b":
45+
score += 1
46+
print("Correct! GET /users/42 follows REST conventions.")
47+
print("The URL identifies the resource, GET reads it.")
48+
else:
49+
print("Incorrect. The answer is b) GET /users/42.")
50+
print("REST uses the URL path to identify resources and HTTP")
51+
print("methods to specify the action.")
52+
print()
53+
54+
# Question 3
55+
print("Question 3/7: What does response.json() do in Python?")
56+
print()
57+
print(" a) Sends JSON to the server")
58+
print(" b) Parses the JSON response body into a Python dictionary")
59+
print(" c) Converts a dict to JSON")
60+
print(" d) Checks if the response is valid JSON")
61+
print()
62+
answer = input("Your answer: ").strip().lower()
63+
if answer == "b":
64+
score += 1
65+
print("Correct! .json() parses the response body from JSON")
66+
print("into a Python dict (or list), so you can work with the data.")
67+
else:
68+
print("Incorrect. The answer is b).")
69+
print(".json() converts the JSON response into Python objects.")
70+
print()
71+
72+
# Question 4
73+
print("Question 4/7: What status code indicates a new resource")
74+
print("was successfully created?")
75+
print()
76+
print(" a) 200")
77+
print(" b) 201")
78+
print(" c) 204")
79+
print(" d) 301")
80+
print()
81+
answer = input("Your answer: ").strip().lower()
82+
if answer == "b":
83+
score += 1
84+
print("Correct! 201 Created is the standard response for")
85+
print("successful POST requests that create new resources.")
86+
else:
87+
print("Incorrect. The answer is b) 201 Created.")
88+
print("200 = OK (general success), 201 = Created (new resource).")
89+
print()
90+
91+
# Question 5
92+
print("Question 5/7: Why is it bad practice to hardcode API URLs?")
93+
print()
94+
print(' requests.get("https://api.example.com/v2/users")')
95+
print()
96+
print(" a) It makes the code run slower")
97+
print(" b) If the URL changes, you have to find and update every")
98+
print(" occurrence throughout your code")
99+
print(" c) Python does not allow string URLs")
100+
print(" d) It is not bad practice")
101+
print()
102+
answer = input("Your answer: ").strip().lower()
103+
if answer == "b":
104+
score += 1
105+
print("Correct! Store the base URL in a variable or config.")
106+
print("That way you change it in one place if it ever changes.")
107+
else:
108+
print("Incorrect. The answer is b).")
109+
print("Use a variable: BASE_URL = 'https://api.example.com/v2'")
110+
print("then requests.get(f'{BASE_URL}/users').")
111+
print()
112+
113+
# Question 6
114+
print("Question 6/7: What does response.raise_for_status() do?")
115+
print()
116+
print(" a) Prints the status code")
117+
print(" b) Returns the status code as a string")
118+
print(" c) Raises an exception if the response is a 4xx or 5xx error")
119+
print(" d) Sets the status code to 200")
120+
print()
121+
answer = input("Your answer: ").strip().lower()
122+
if answer == "c":
123+
score += 1
124+
print("Correct! raise_for_status() throws an exception for error")
125+
print("responses, making it easy to catch failures.")
126+
else:
127+
print("Incorrect. The answer is c).")
128+
print("It is a convenient way to check for errors instead of")
129+
print("manually checking response.status_code.")
130+
print()
131+
132+
# Question 7
133+
print("Question 7/7: What is the difference between an API key")
134+
print("and a Bearer token?")
135+
print()
136+
print(" a) They are the same thing")
137+
print(" b) An API key is a static secret string; a Bearer token")
138+
print(" is typically obtained by logging in and may expire")
139+
print(" c) API keys are more secure")
140+
print(" d) Bearer tokens do not work with Python")
141+
print()
142+
answer = input("Your answer: ").strip().lower()
143+
if answer == "b":
144+
score += 1
145+
print("Correct! API keys are simple static secrets. Bearer tokens")
146+
print("(like JWTs) are obtained through authentication and often")
147+
print("have expiration times.")
148+
else:
149+
print("Incorrect. The answer is b).")
150+
print("API keys are static. Bearer tokens are dynamic and often")
151+
print("include user identity and expiration information.")
152+
print()
153+
154+
# Final score
155+
print("=" * 60)
156+
pct = round(score / total * 100)
157+
print(f" Final Score: {score}/{total} ({pct}%)")
158+
print()
159+
if pct == 100:
160+
print(" Perfect! You understand API fundamentals.")
161+
elif pct >= 70:
162+
print(" Good work! Review the questions you missed.")
163+
else:
164+
print(" Keep practicing! Re-read concepts/api-basics.md")
165+
print(" and try again.")
166+
print("=" * 60)
167+
168+
169+
if __name__ == "__main__":
170+
run_quiz()

0 commit comments

Comments
 (0)