class Grade(): def __init__(self, username=None, password=None): from QingQiz.netreq.aoxiang import Aoxiang self.aoxiang = Aoxiang(username, password) def output(self, *terms): ''' :param terms: terms to get grade ''' from rich.console import Console from rich.table import Table grades = self.aoxiang.grade(*terms) console = Console() # grade: [{head: value, head: value}, {...}] for grade in grades: # grade: [([head], [value]), (...)] grade = list(map(lambda x: list(zip(*x.items())), grade)) # header: # 学年学期 ┃ 课程代码 ┃ 课程序号 ┃ 课程名称 ┃ 课程类别 ┃ 学分 ┃ 平时成绩 ┃ 期中成绩 ┃ 实验成绩 ┃ 期末成绩 ┃ 总评成绩 ┃ 最终 ┃ 绩点 header = grade[0][0] title = grade[0][1][0] if terms else 'All Terms' grade = list(sorted(map(lambda x: x[1][3:], grade), reverse=True)) table = Table(title=title, width=120) for h in header[3:]: table.add_column(h.replace('成绩', '')) for g in grade: table.add_row(*g) table.row_styles = ['none', 'dim'] console.print(table)
class Exam(): def __init__(self, username=None, password=None): from QingQiz.netreq.aoxiang import Aoxiang self.aoxiang = Aoxiang(username, password) def output(self, *terms): ''' :param terms: terms to exam information ''' from datetime import datetime from rich.console import Console from rich.table import Table exams = self.aoxiang.examInformations(*terms) console = Console() for term in exams: # exam: [([head], [value]), (...)] exam = list(map(lambda x: list(zip(*x.items())), exams[term])) # exam[0][0]: # 课程序号 ┃ 课程名称 ┃ 考试类型 ┃ 考试日期 ┃ 考试时间 ┃ 考场校区 ┃ 考场教学… ┃ 考场教室 ┃ 考试情况 ┃ 其它说明 # remove 课程序号 and 其它说明 header = exam[0][0][1:-1] exam = list(sorted(map(lambda x: x[1][1:-1], exam), reverse=True)) table = Table(title=term, width=120) rowStyles = [] for h in header: table.add_column(h) for e in exam: table.add_row(*e) if e[2] is None or e[3] is None: rowStyles.append('dim') continue examDate = e[2] + ' ' + e[3].split('~')[-1] + ':00' examDate = datetime.strptime(examDate, '%Y-%m-%d %H:%M:%S') if datetime.now() > examDate: rowStyles.append('dim') else: rowStyles.append('none') table.row_styles = rowStyles console.print(table)
def __init__(self, username=None, password=None): from QingQiz.netreq.aoxiang import Aoxiang self.aoxiang = Aoxiang(username, password)
class Grade(): def __init__(self, username=None, password=None): from QingQiz.netreq.aoxiang import Aoxiang self.aoxiang = Aoxiang(username, password) def output(self, *terms): ''' :param terms: terms to get grade ''' from rich.console import Console from rich.table import Table from rich.markdown import Markdown grades = self.aoxiang.grade(*terms) grade_sum = 0 score_sum = 0 gpa_exclude = [] console = Console() def is_number(num): import re pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$') return bool(pattern.match(num)) # grade: [{head: value, head: value}, {...}] for grade in grades: # grade: [([head], [value]), (...)] grade = list(map(lambda x: list(zip(*x.items())), grade)) # header: # 学年学期 ┃ 课程代码 ┃ 课程序号 ┃ 课程名称 ┃ 课程类别 ┃ 学分 ┃ 平时成绩 ┃ 期中成绩 ┃ 实验成绩 ┃ 期末成绩 ┃ 总评成绩 ┃ 最终 ┃ 绩点 header = grade[0][0] title = grade[0][1][0] if terms else 'All Terms' grade = list(sorted(map(lambda x: x[1][3:], grade), reverse=True)) table = Table(title=title, width=120) for h in header[3:]: table.add_column(h.replace('成绩', '')) for g in grade: g = list(g) # 修复sb教务乱显示的成绩 g[-2] = g[-2][:2] if g[-2] != '100' else g[-2] g[-2] = '95' if g[-2] == 'A' else g[-2] table.add_row(*g) if (is_number(g[-2][:2])) and is_number(g[-1]): grade_sum += float(g[2]) score_sum += float(g[-2])*float(g[2]) else: gpa_exclude.append((g[0], g[-2][:2], g[-1])) table.row_styles = ['none', 'dim'] console.print(table) md = "GPA **排除**:\n" + "\n\n".join(map(lambda x: f'- **{x[0]}**: *{x[1]}*, *{x[2]}*', gpa_exclude)) md += f"\n\n共 **{len(grade)}** 门课程,学分绩估算: **{score_sum / grade_sum :.4f}**" console.print(Markdown(md)) console.print("\n")
class ClassTable(): def __init__(self, username, password): from QingQiz.netreq.aoxiang import Aoxiang self.aoxiang = Aoxiang(username, password) def export(self, timeStart, timeEnd, **kwargs): '''export classTable in ics format :param timeStart: :param timeEnd: :param **kwargs: :output str: output file :alarm int: alarm before event ''' import os from .ics import ICS from QingQiz import log classTable = self.aoxiang.classTable(timeStart, timeEnd) header = ICS.header(f'{timeStart} - {timeEnd} 课表') body = [] for ct in classTable: body.append( ICS.body(name=ct['title'], start=ct['startTime'][:8] + 'T' + ct['startTime'][8:], end=ct['stopTime'][:8] + 'T' + ct['stopTime'][8:], location=ct['location'], description='', alarm=kwargs['alarm'], alarmDescription='')) body = '\n'.join(body) footer = ICS.footer() with open(kwargs['output'], 'w') as f: print(header, file=f) print(body, file=f) print(footer, file=f) def output(self, term): '''output current courses :param term: term, for example: 19 ''' import functools from rich.console import Console from rich.table import Table console = Console() table = Table(title=f'20{term} 我的课程') myCourses = self.aoxiang.myCourses(term) # header: # 0 1 2 3 4 5 6 7 8 9 10 11 12 # 序号 ┃ 课程序号 ┃ 课程代码 ┃ 课程名称 ┃ 教师 ┃ 学分 ┃ 校区 ┃ 课程安排 ┃ 起止周 ┃ 课程介绍 ┃ 教学大纲 ┃ 考试类型 ┃ 操作 header = list(map(lambda x: x[0], myCourses[0].items())) # only pick up [3, 5, ..] header = functools.reduce(lambda zero, x: zero + [header[x]], [3, 5, 6, 7, 8, 9, 11], []) for h in header: table.add_column(h) for course in myCourses: table.add_row(*[course[h] for h in header]) table.row_styles = ['none', 'dim'] console.print(table)