"""Not defteri: ağırlıklı ortalama, harf notu ve sıralama.""" LETTERS = [(90, "AA"), (85, "BA"), (80, "BB"), (75, "CB"), (70, "CC"), (60, "DC"), (50, "DD")] class GradeError(ValueError): pass def letter(score): """0–100 arası puanı harf notuna çevirir; 50 altı FF. Eşik değerleri dahildir (90 → AA).""" if not 0 <= score <= 100: raise GradeError("puan 0-100 aralığında olmalı") for limit, name in LETTERS: if score >= limit: return name return "FF" def weighted_average(scores, weights): """Ağırlıklı ortalama (2 ondalık); ağırlıkların toplamı 1 olmak zorunda değildir.""" if len(scores) != len(weights): raise GradeError("puan ve ağırlık sayısı eşit olmalı") if not scores: raise GradeError("en az bir puan gerekli") total_w = sum(weights) if total_w <= 0: raise GradeError("ağırlık toplamı pozitif olmalı") return round(sum(s * w for s, w in zip(scores, weights)) / total_w, 2) class Gradebook: def __init__(self, weights): self.weights = list(weights) self.students = {} def add(self, name, scores): if name in self.students: raise GradeError(f"{name} zaten kayıtlı") if len(scores) != len(self.weights): raise GradeError("eksik ya da fazla puan") self.students[name] = list(scores) def average(self, name): return weighted_average(self.students[name], self.weights) def ranking(self): """Ortalamaya göre azalan; eşitlikte isme göre alfabetik sıralama.""" return sorted(self.students, key=lambda n: (-self.average(n), n)) def passed(self, threshold=50): """Ortalaması eşik değerine eşit ya da üstünde olanlar, sıralamaya göre.""" return [n for n in self.ranking() if self.average(n) >= threshold]