Created
June 29, 2016 14:26
-
-
Save pvieito/e7571cf42b28d4541966d7221ea8139e to your computer and use it in GitHub Desktop.
Compute marks from diferent subjects in YMARK format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
'''ymark.py - Pedro José Pereira Vieito © 2016 | |
Compute marks from diferent subjects in YMARK format. | |
Usage: | |
ymark.py [-adeghow] [<search>...] | |
Options: | |
-a, --all Show all subjects, not only active | |
-d, --details Show subject details | |
-e, --edit Edit mark files | |
-g, --guide Open subject guide | |
-o, --open Open subject folder | |
-w, --web Open subject web | |
-h, --help Show this help | |
''' | |
import yaml | |
import subprocess | |
import numbers | |
import os.path | |
from docopt import docopt | |
from pathlib import Path | |
from colorama import Fore, Back, Style | |
__author__ = "Pedro José Pereira Vieito" | |
__email__ = "[email protected]" | |
args = docopt(__doc__) | |
status_array = [{"name": "Passed", "color": Fore.GREEN}, | |
{"name": "Active", "color": Fore.CYAN}, | |
{"name": "Future", "color": Fore.MAGENTA}, | |
{"name": "Failed", "color": Fore.RED}, | |
{"name": "Unknown", "color": Fore.YELLOW}] | |
courses = {} | |
def get_status(property, status): | |
if status < len(status_array): | |
return status_array[status][property] | |
else: | |
return status_array[5][property] | |
def compute_subject(subject, *, force=False): | |
# Args Options | |
if not force and not args['--all'] and "status" in subject and \ | |
not subject["status"] == 1: | |
return | |
if args['--edit']: | |
subprocess.call("open '" + subject["file"] + "'", shell=True) | |
if args['--open']: | |
subject_dir = Path(subject["file"]).parent.parent | |
subprocess.call("open '" + str(subject_dir) + "'", shell=True) | |
if args['--guide']: | |
guides = Path(subject["file"]).parent.glob("*.pdf") | |
for guide in guides: | |
subprocess.call("open '" + str(guide) + "'", shell=True) | |
if args['--web']: | |
if "web" in subject and subject["web"]: | |
subprocess.call("open '" + str(subject["web"]) + "'", shell=True) | |
post_mark = None | |
course_progress = None | |
# Mark computation | |
if "assessment" in subject and subject["assessment"] and \ | |
"status" in subject and not subject["status"] == 2: | |
final_mark = 0 | |
course_progress = 0 | |
for item in subject["assessment"]: | |
if "mark" in item and isinstance(item["mark"], numbers.Number): | |
item_mark = item["mark"] | |
if "weight" in item: | |
item_mark *= item["weight"] | |
course_progress += item["weight"] * 100 | |
else: | |
course_progress = 100 | |
if "fullscale" in item: | |
item_mark = item_mark / item["fullscale"] * 10 | |
final_mark += item_mark | |
course_progress = round(course_progress) | |
if course_progress < 100: | |
post_mark = " (" + str(course_progress) + "%)" | |
else: | |
final_mark = None | |
# Course computation | |
if args['--all'] and "status" in subject and \ | |
subject["status"] == 0 and "credits" in subject and final_mark: | |
credits = subject["credits"] | |
ponderated_mark = final_mark * credits | |
if subject["course"] in courses: | |
courses[subject["course"]]["credits"] += subject["credits"] | |
courses[subject["course"]]["ponderated_mark"] += ponderated_mark | |
else: | |
courses[subject["course"]] = {"credits": subject["credits"], | |
"ponderated_mark": ponderated_mark} | |
status_color = get_status("color", subject["status"]) | |
if "codename" in subject: | |
text = status_color + subject["codename"] + Fore.RESET | |
else: | |
text = status_color + "………" + Fore.RESET | |
optional = None | |
if "name" in subject: | |
optional = str(subject["name"]) | |
# Subject | |
print_mark(text, final_mark, optional, post_mark, extra_width=5) | |
# Print details | |
if args["--details"]: | |
if "course" in subject: | |
print(" Course:", subject["course"]) | |
if "institution" in subject: | |
print(" Institution:", subject["institution"]) | |
if "year" in subject: | |
print(" Year:", subject["year"]) | |
if "term" in subject: | |
print(" Term:", subject["term"]) | |
if "type" in subject: | |
print(" Type:", subject["type"]) | |
if "status" in subject: | |
print(" Status:" + status_color, | |
get_status("name", subject["status"]), Fore.RESET) | |
if "credits" in subject: | |
print(" Credits:", subject["credits"], "ECTS") | |
if "code" in subject: | |
print(" Code:", subject["code"]) | |
if "web" in subject: | |
print(" Web:", subject["web"]) | |
if isinstance(course_progress, numbers.Number): | |
print(" Progress:", str(course_progress) + "%") | |
if "assessment" in subject and subject["assessment"]: | |
if len(subject["assessment"]) == 1 and \ | |
not "weight" in subject["assessment"][0]: | |
print(" Assesment: Final Mark") | |
else: | |
print(" Assesment:", len(subject["assessment"]), "items") | |
i = 1 | |
for item in subject["assessment"]: | |
if "mark" in item: | |
if "description" in item: | |
description = str(item["description"]) | |
else: | |
description = "Mark #" + str(i) | |
if "fullscale" in item: | |
mark = item["mark"] / item["fullscale"] * 10 | |
else: | |
mark = item["mark"] | |
if "weight" in item: | |
weight = str(round(item["weight"] * 100, 2)) + "%" | |
else: | |
weight = "100.0%" | |
print_mark(" - " + description, mark, | |
optional=weight, text_color=True) | |
i += 1 | |
print() | |
def print_course(course): | |
credits = courses[course]["credits"] | |
ponderated_mark = courses[course]["ponderated_mark"] / credits | |
optional = str(credits) + " ECTS" | |
print_mark(course, ponderated_mark, optional, extra_width=-5) | |
def print_mark(text, mark=None, optional=None, post_note=None, *, | |
extra_width=0, text_color=False): | |
text = (text[:50] + '…') if len(text) > 50 else text | |
if isinstance(mark, numbers.Number): | |
if round(mark, 1) < 5: | |
color = Fore.RED | |
else: | |
color = Fore.GREEN | |
else: | |
color = Fore.WHITE | |
if text_color: | |
text_color = color | |
text_color_optional = color | |
else: | |
text_color = Style.BRIGHT | |
text_color_optional = "" | |
if optional: | |
optional = (optional[:50] + '…') if len(optional) > 50 else optional | |
text += Style.RESET_ALL + text_color_optional + " (" + optional + ")" | |
else: | |
text += Style.RESET_ALL | |
text += " " | |
print(text_color + text.ljust(75 + extra_width, "…"), | |
Style.RESET_ALL, end="") | |
if isinstance(mark, numbers.Number): | |
print(text_color + color, "{0:0.1f}".format(mark), end="") | |
else: | |
print(text_color + color, "………", end="") | |
print(Style.RESET_ALL, end="") | |
if post_note: | |
print(post_note, end="") | |
print() | |
if __name__ == '__main__': | |
results = subprocess.check_output("mdfind 'kMDItemFSName=*.ymark' \ | |
-onlyin ~/Dropbox/Universitat", | |
shell=True) | |
results = results.decode().splitlines() | |
results.sort() | |
marks = [] | |
subjects = {} | |
for marks_file in results: | |
try: | |
marks_dict = yaml.safe_load(open(marks_file)) | |
marks_dict.update({"file": marks_file}) | |
marks.append(marks_dict) | |
except AttributeError: | |
pass | |
for subject in marks: | |
index = "" | |
if "status" in subject: | |
index += str(subject["status"]) + "_" + \ | |
get_status("name", subject["status"]) + "_" | |
if "course" in subject: | |
index += subject["course"] + "_" | |
if "year" in str(subject): | |
index += str(subject["year"]) + "_" | |
if "term" in subject: | |
index += str(subject["term"]) + "_" | |
if "type" in subject: | |
index += str(subject["type"]) + "_" | |
if "codename" in subject: | |
index += str(subject["codename"]) + "_" | |
if "name" in subject: | |
index += str(subject["name"]) + "_" | |
if "code" in subject: | |
index += str(subject["code"]) + "_" | |
if "institution" in subject: | |
index += str(subject["institution"]) + "_" | |
subjects[index] = subject | |
for subject in sorted(subjects): | |
if args['<search>'] and not args['--all']: | |
input = list(map(str.upper, args['<search>'])) | |
match = False | |
for search_term in input: | |
if search_term in subject.upper(): | |
match = True | |
if match: | |
compute_subject(subjects[subject], force=True) | |
else: | |
compute_subject(subjects[subject]) | |
if args['--all']: | |
if courses: | |
print() | |
for course in sorted(courses): | |
print_course(course) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment