Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- """Using dictionary of letter grades, calculate mean GPA from list
- of letter grades converted to points"""
- # https://gist.github.com/reagle/9cc2f4e2f98446528128d1f6edfe3d73
- # add results to e-statement-1b-teaching-trace-table.xlsx
- __author__ = "Joseph Reagle"
- __copyright__ = "Copyright (C) 2021-2024 Joseph Reagle"
- __license__ = "GLPv3"
- __version__ = "1.1"
- import statistics
- from collections import Counter
- try:
- import asciietch.graph as ag # type:ignore
- asciietch_imported = True
- except ImportError:
- asciietch_imported = False
- print("`pip install asciietch` if you want nice graphs ▁▅█▂▁▃▁▂▁▁▁▂▁")
- print(" https://github.com/linkedin/asciietch\n")
- # https://registrar.northeastern.edu/article/how-to-calculate-your-gpa/
- POINTS = {
- "A+": 4.0,
- "A": 4.0,
- "A-": 3.667,
- "B+": 3.333,
- "B": 3.0,
- "B-": 2.667,
- "C+": 2.333,
- "C": 2.0,
- "C-": 1.667,
- "D+": 1.333,
- "D": 1.0,
- "D-": 0.667,
- "F": 0,
- }
- def calc_gpa(grades: list[str]) -> float:
- """Calculate mean GPA from list of letter grades converted to points."""
- return statistics.mean([POINTS[grade] for grade in grades])
- def print_header():
- """Print a header for the output."""
- print(f"{'COURSE':<15} {'N':<5} {'MEAN':<10}", end="")
- print(" ".join(f"{letter:<2}" for letter in POINTS.keys()))
- def print_course(title: str, grades: list[str]) -> None:
- """Print single-line information for a course."""
- print(f"{title:<15} N={len(grades):02d} μ={calc_gpa(grades):.2f}", end=" ")
- distribution = [grades.count(letter) for letter in POINTS]
- counter = Counter(grades)
- for letter in POINTS.keys():
- if letter in counter:
- print(f"{counter[letter]:<3}", end="")
- else:
- print(" ", end="")
- if asciietch_imported:
- grapher = ag.Grapher()
- print(grapher.asciihist(distribution), end="")
- print()
- COURSES = { # Target: B+ / 3.33 average
- ################### 2024 Spring
- # 3.17 unusually weak work
- "2024_CDA_1SP": "B+ A C+ C B- A- A- B B+ B+ A B- A D- A B C+ A A- B+ A- B A- B B",
- # 3.74 unusually excellent work
- "2024_OC_1SP": "B+ A A- B+ A B+ A A- A- A A- A A A-",
- ################### 2023 Fall
- # 3.35 unprecedented drops at start, leaving mostly strong students
- "2023_CDA_2FA": "A- A A- B- A- A- A- C A A A- A A- D- A B- A- A- B- B+",
- # 3.33 first time teaching public speaking (includes F no show; 3.52 without him)
- "2023_PS_2FA": "B+ A- B A- A A- B- A B A- B+ A- A- A F B+ A A- B",
- ################### 2023 Spring
- # 3.31
- "2023_CDA_1SP": (
- "B B A A- A A- A- A- B+ A- A- A- A- A- A- F A B B+ A F A C+ A- A A A- B+ A- C+"
- ),
- # 3.60 excellent work from mature students
- "2023_OC_1SP": "B+ A A B- B+ A- A- A A A- B A A B",
- ################### 2022 Fall
- # 3.44
- "2022_CDA_2FA": (
- "D+ A A B+ A- A- A- A B+ B+ A- A- A A- A- B+ A A B+ B B B+ A- B B B+ A C+"
- ),
- # 3.48
- "2022_OC_2FA": "A- A B+ A C B+ B+ A- A",
- ################### 2022 Spring
- # 3.42
- "2022_CDA_1SP": (
- "C- A- A A- C- B A- A- A- B+ A B+ B+ A B+ B A- A- A A B+ A A- B A- B+ B"
- ),
- # 3.61, excellent students
- "2022_PC_1SP": "B+ B+ A A- B+ B+ A B A- A A- A A A- A- A- B",
- # "TEST": "A B B C C C D D D D F F F F F",
- }
- print_header()
- for title, grades in COURSES.items():
- print_course(title, grades.split(" "))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement