# ============================================================
#  Lab 02 Starter Files
#  Comp 111 — Programming 2, Spring 2026
#
#  Each section below is a SEPARATE FILE.
#  Save each one with the filename shown in the header.
# ============================================================


# ════════════════════════════════════════════════════════════
#  FILE: math_tools.py            (Section 6 — Walkthrough)
# ════════════════════════════════════════════════════════════

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

def is_even(n):
    return n % 2 == 0


# ════════════════════════════════════════════════════════════
#  FILE: test_math_tools.py       (Section 6 — Walkthrough)
# ════════════════════════════════════════════════════════════

from math_tools import add, multiply, is_even

def test_add():
    assert add(2, 3) == 5
    assert add(-1, 1) == 0
    assert add(0, 0) == 0
    print("test_add: ALL PASSED")

def test_multiply():
    assert multiply(3, 4) == 12
    assert multiply(-2, 5) == -10
    assert multiply(0, 100) == 0
    print("test_multiply: ALL PASSED")

def test_is_even():
    assert is_even(4) == True
    assert is_even(7) == False
    assert is_even(0) == True
    print("test_is_even: ALL PASSED")

# Run all tests
test_add()
test_multiply()
test_is_even()
print("--- All tests passed! ---")


# ════════════════════════════════════════════════════════════
#  FILE: bug_hunt1.py             (Section 7 — Exercise 3)
# ════════════════════════════════════════════════════════════

def get_last_three(items):
    start = len(items) - 3
    end = len(items) - 1
    return items[start:end]

print(get_last_three([10, 20, 30, 40, 50]))
# Expected: [30, 40, 50]
# Actual:   [30, 40]


# ════════════════════════════════════════════════════════════
#  FILE: bug_hunt2.py             (Section 7 — Exercise 4)
# ════════════════════════════════════════════════════════════

def make_uppercase(text):
    text.upper()
    return text

print(make_uppercase("hello"))
# Expected: "HELLO"
# Actual:   "hello"


# ════════════════════════════════════════════════════════════
#  FILE: bug_hunt3.py             (Section 7 — Exercise 5)
# ════════════════════════════════════════════════════════════

def remove_negatives(numbers):
    for num in numbers:
        if num < 0:
            numbers.remove(num)
    return numbers

print(remove_negatives([1, -2, -3, 4, -5]))
# Expected: [1, 4]
# Actual:   [1, -3, 4]


# ════════════════════════════════════════════════════════════
#  FILE: bug_hunt4.py             (Section 7 — Exercise 6)
# ════════════════════════════════════════════════════════════

def sum_evens(numbers):
    total = 0
    for i in range(len(numbers)):
        if i % 2 == 0:
            total += numbers[i]
    return total

print(sum_evens([1, 2, 3, 4, 5, 6]))
# Expected: 12 (2 + 4 + 6)
# Actual:   9


# ════════════════════════════════════════════════════════════
#  FILE: buggy_first_n.py         (Section 8 — Exercise 3)
# ════════════════════════════════════════════════════════════

def first_n(items, n):
    result = []
    for i in range(1, n):
        result.append(items[i])
    return result

print(first_n([10, 20, 30, 40], 3))
# Expected: [10, 20, 30]
# Actual:   [20, 30]


# ════════════════════════════════════════════════════════════
#  FILE: buggy_tax.py             (Section 8 — Exercise 4)
# ════════════════════════════════════════════════════════════

def total_with_tax(price, tax_rate):
    tax = price * tax_rate
    total = price + tax
    # Meant to return total
    price + tax

print(total_with_tax(100, 0.15))
# Expected: 115.0
# Actual:   None


# ════════════════════════════════════════════════════════════
#  FILE: buggy_reverse.py         (Section 8 — Exercise 5)
# ════════════════════════════════════════════════════════════

def reverse_list(items):
    for i in range(len(items)):
        j = len(items) - 1 - i
        items[i], items[j] = items[j], items[i]
    return items

print(reverse_list([1, 2, 3, 4, 5]))
# Expected: [5, 4, 3, 2, 1]
# Actual:   [1, 2, 3, 4, 5]


# ════════════════════════════════════════════════════════════
#  FILE: grades.py                (Section 9 — Capstone)
# ════════════════════════════════════════════════════════════

def letter_grade(score):
    """Convert a numeric score (0-100) to a letter grade."""
    if score >= 90:
        return "A"
    elif score >= 80:
        return "B"
    elif score >= 70:
        return "C"
    elif score >= 60:
        return "D"
    else:
        return "F"

def class_average(scores):
    """Return the average of a list of scores."""
    total = 0
    for score in scores:
        total = score          # <-- BUG! Should be +=
    return total / len(scores)

def highest_score(scores):
    """Return the highest score in the list."""
    best = 0                   # <-- BUG! Should be scores[0]
    for score in scores:
        if score > best:
            best = score
    return best


# ════════════════════════════════════════════════════════════
#  FILE: test_grades.py           (Section 9 — Capstone)
# ════════════════════════════════════════════════════════════

from grades import letter_grade, class_average, highest_score

def test_letter_grade():
    assert letter_grade(95) == "A"
    assert letter_grade(90) == "A"
    assert letter_grade(85) == "B"
    assert letter_grade(80) == "B"
    assert letter_grade(75) == "C"
    assert letter_grade(65) == "D"
    assert letter_grade(50) == "F"
    assert letter_grade(0)  == "F"
    print("test_letter_grade: ALL PASSED")

def test_class_average():
    assert class_average([100, 80, 60]) == 80.0
    assert class_average([90, 90, 90]) == 90.0
    assert class_average([50]) == 50.0
    print("test_class_average: ALL PASSED")

def test_highest_score():
    assert highest_score([70, 85, 90, 60]) == 90
    assert highest_score([50]) == 50
    assert highest_score([-10, -20, -5]) == -5
    print("test_highest_score: ALL PASSED")

# Run all tests
test_letter_grade()
test_class_average()
test_highest_score()
print("--- All tests passed! ---")