# %% About
# - Name: While Recap Grades
# - Difficulty: hard
# - Lines: 14
# - Minutes: 13
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 1. Create a student grade book, to which user can add grades
# 2. Allow the user to enter grades as long as they want
# 3. If the user presses Enter (without entering a grade),
# end the data entry and proceed to the summary
# 4. Only grades that are in the `GRADE_SCALE` can be added to the grade book
# 5. At the end, display the arithmetic mean of the grade book to the user
# 6. Non-functional requirements:
# - The user will always enter only one grade at a time
# - The user will not enter any invalid characters or longer numbers
# - Use the `input()` function as normal
# - `Mock` will simulate the user entering grades
# 7. Run doctests - all must succeed
# %% Polish
# 1. Stwórz dzienniczek ucznia, do którego użytkownik może dopisywać oceny
# 2. Pozwól użytkownikowi podawać oceny tak długo jak będzie chciał
# 3. Jeżeli użytkownik wcisnął Enter (bez wpisywania oceny),
# zakończ wprowadzanie danych i przejdź do podsumowania
# 4. Do dzienniczka można dopisywać tylko takie oceny,
# które znajdują się na skali ocen `GRADE_SCALE`
# 5. Na koniec wyświetl użytkownikowi średnią arytmetyczną dzienniczka
# 6. Wymagania niefunkcjonalne:
# - Użytkownik zawsze wpisze tylko jedną ocenę na raz
# - Użytkownik nie wpisze żadnych nieprawidłowych znaków lub dłuższych liczb
# - Skorzystaj z funkcji `input()` tak jak normalnie
# - `Mock` zasymuluje wpisanie liczb przez użytkownika
# 7. Uruchom doctesty - wszystkie muszą się powieść
# %% Example
# grades = [2.0, 3.0, 3.5, 4.0, 5.0]
# average = 3.5
# %% Hints
# - `Stop` or `Ctrl+C` kills infinite loop
# - `/` - true division operator
# - `while True` - infinite loop
# - `if ... else ...` - conditional
# - `not obj` - logically inverts object
# - `float(obj)` - convert obj to float
# - `x in obj` - membership operator
# - `list.append()` - add something at the end of a list
# - `break` - will exit the loop
# - `input(prompt)` - ask user the prompt and wait for answer
# - `input(prompt)` will return empty string (``''``), if user hit enter key without typing anything
# - `sum(iterable)` - sum of iterable
# - `len(object)` - length of an object
# - `mean = sum(...) / len(...)`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> from statistics import mean
>>> type(result)
<class 'float'>
>>> result
3.5
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
from unittest.mock import Mock
# %% Types
result: float
# %% Data
GRADE_SCALE = (2.0, 3.0, 3.5, 4.0, 4.5, 5.0)
input = Mock(side_effect=['2', '2.5', '3', '3.5', '4', '5', '6', ''])
# %% Result
result = ...