Skip to content

Commit 2e3050b

Browse files
committed
Validate user input and convert to constrained types
1 parent 87966be commit 2e3050b

1 file changed

Lines changed: 104 additions & 0 deletions

File tree

prep_exercise/8_enums.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from dataclasses import dataclass
2+
from enum import Enum
3+
from typing import List, Dict
4+
import sys
5+
6+
class OperatingSystem(Enum):
7+
MACOS = "macOS"
8+
ARCH = "Arch Linux"
9+
UBUNTU = "Ubuntu"
10+
11+
@dataclass(frozen=True)
12+
class Person:
13+
name: str
14+
age: int
15+
preferred_operating_system: OperatingSystem
16+
17+
18+
@dataclass(frozen=True)
19+
class Laptop:
20+
id: int
21+
manufacturer: str
22+
model: str
23+
screen_size_in_inches: float
24+
operating_system: OperatingSystem
25+
26+
# =====define parse age======
27+
def parse_age(raw: str) -> int:
28+
try:
29+
age= int(raw)
30+
except ValueError:
31+
print("Error: age must be asn integer.", file=sys.stderr)
32+
sys.exit(1)
33+
34+
if age <= 0:
35+
print("Error: age must be a positive integer.", file=sys.stderr)
36+
sys.exit(1)
37+
38+
return age
39+
40+
# =====define parse operating system======
41+
def parse_operating_system(raw: str) -> OperatingSystem:
42+
normalized = raw.strip().lower()
43+
44+
aliases = {
45+
"macos": OperatingSystem.MACOS,
46+
"mac": OperatingSystem.MACOS,
47+
"arch": OperatingSystem.ARCH,
48+
"arch linux": OperatingSystem.ARCH,
49+
"ubuntu": OperatingSystem.UBUNTU,
50+
}
51+
52+
if normalized not in aliases:
53+
valid = ", ".join(sorted(aliases.keys()))
54+
print(f"Error: invalid operating system. Try one of: {valid}", file=sys.stderr)
55+
sys.exit(1)
56+
57+
return aliases[normalized]
58+
59+
60+
# =======count laptops by os============
61+
def count_laptops_by_os(laptops: List[Laptop]) -> Dict[OperatingSystem, int]:
62+
counts: Dict[OperatingSystem, int] = {os: 0 for os in OperatingSystem}
63+
for laptop in laptops:
64+
counts[laptop.operating_system] +=1
65+
return counts
66+
67+
68+
# ======define main ================
69+
def main() -> None:
70+
laptops = [
71+
Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13.0, operating_system=OperatingSystem.ARCH),
72+
Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15.0, operating_system=OperatingSystem.UBUNTU),
73+
Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15.0, operating_system=OperatingSystem.UBUNTU),
74+
Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13.0, operating_system=OperatingSystem.MACOS),
75+
]
76+
77+
name = input("Enter your name: ").strip()
78+
if not name:
79+
print("Error: name cannot be empty.", file=sys.stderr)
80+
sys.exit(1)
81+
82+
age = parse_age(input("Enter your age: "))
83+
preferred_os = parse_operating_system(input("preferred OS(Ubuntu / Arch / macOS): "))
84+
85+
person = Person(name=name, age=age, preferred_operating_system=preferred_os)
86+
87+
counts = count_laptops_by_os(laptops)
88+
preferred_count = counts[person.preferred_operating_system]
89+
90+
print(f"\nHi {person.name} (age {person.age})")
91+
print(f"Laptops available with {person.preferred_operating_system.value}: {preferred_count}")
92+
93+
# Find the OS with maximum availability
94+
best_os = max(counts, key=lambda os:counts[os])
95+
best_count = counts[best_os]
96+
97+
if best_os != person.preferred_operating_system and best_count > preferred_count:
98+
print(
99+
f"If you are willing to accept {best_os.value} instead,"
100+
f"You're more likely to get a laptop. {best_count} available)."
101+
)
102+
103+
if __name__ == "__main__":
104+
main()

0 commit comments

Comments
 (0)