File size: 1,889 Bytes
9438a57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""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]