import json import xlrd from coord import Coord, Merged import utils class Parser: def __init__(self, sheet: "xlrd.sheet.Sheet"): self.sh: "xlrd.sheet.Sheet" = sheet self.groups = {} print("Parser created for '{0}': size: {1}x{2}".format(self.sh.name, self.sh.nrows, self.sh.ncols)) def parse(self): monday = utils.find(self.sh, "ПОНЕДЕЛЬНИК") head_rx = monday[0] - 1 # выше первого понидельника if head_rx < 0: raise Exception("head_rx < 0: Программа пыталась найти 'ПОНЕДЕЛЬНИК', но по всей видимости не нашла.") head = self.sh.row(head_rx) # get all ROW (months, groups) print(f"head={head}") self.groups = parse_groups(self.sh, head, monday, head_rx) # parse groups to self.groups print(f'self.groups={json.dumps(self.groups, indent=2, ensure_ascii=False)}') print("\n\n\n") for group in self.groups.values(): print("\nSTART OF PROCESS GROUP\n") self.process_group(group, monday) print("\nEND OF PROCESS GROUP\n") def parse_potokoviy(self, merged: Merged): speaker = None location = None # speaker low = merged.low speaker_pos = low.shift(down=merged.height()) speaker = speaker_pos.cell(self.sh).value # location location = merged.high.shift(down=1).cell(self.sh).value return {"loc": location, "leader": speaker, "name": merged.cell(self.sh).value} def process_group(self, group, monday): """ Обработать группы, выполняется для каждой группы, после того как они распарены (parse_groups) group = {'name': 'ИВТ-260', 'position': [5, 6], 'position_human': 'G6:J6'} """ print(f"process_group group={group}") group_name = group['name'] print(group_name) row = group['position'][0] + 1 # counter for while, +1 for shift down; также номер строки в таблице (вроде с нуля) weeknum = 1 # номер недели, щёлкнет +1 при каком-то условии. while row < self.sh.nrows: # maybe условие чтобы не уйти ниже чем есть строк pos = Coord(row, group['position'][1]) # текущая позиция, верхний правый угол (=low) pos_right = pos.shift(right=3) pair_pos = pos.replace(col=5) weekday_pos = pos.replace(col=4) merged = utils.get_merged_coord(self.sh, pos) right_cell = pos_right.cell(self.sh) merged_cell = merged.cell(self.sh) cv = merged_cell.value # В конце (12 пара:>) название группы, можно использовать как якорь if utils.unspace(cv) == group_name: print("Lesson == group name; ending group loop.") break weekday_mr = utils.get_merged_coord(self.sh, weekday_pos) weekday = utils.unspace(weekday_mr.cell(self.sh).value) pair_mr = utils.get_merged_coord(self.sh, pair_pos) pair = utils.unspace(pair_mr.cell(self.sh).value) skip = 0 if weekday == "": if weeknum == 1: weeknum += 1 print("------") skip = 1 row += 1 else: break if not skip: next = 3 # на сколько пыгнуть для следующего шага? is_empty_lesson = right_cell.ctype in utils.EMPTY_CTYPES and merged_cell.ctype in utils.EMPTY_CTYPES dispname = "" parsed_location = None parsed_leader = None parsed_uncotigorized = [] is_wide_maybe_potokoviy = merged.width() > 4 # потоковая ли лекция (занимает несколько групп.) if is_empty_lesson: dispname = "" if not is_empty_lesson: if is_wide_maybe_potokoviy: ret = self.parse_potokoviy(merged) parsed_location = ret['loc'] parsed_leader = ret['leader'] dispname = ret['name'] else: is_solid = pos_right in merged is_2pair = False may_prepod = merged.low.shift(down=2) if utils.border_bottom(self.sh, may_prepod) == 0 and utils.border_top(self.sh, may_prepod.shift(down=1)) == 0: next = 6 is_2pair = True dispname = cv dispname += (" SOLD" if is_solid else " SPLIT") dispname += (" [ДВУПАРНЫЙ]" if is_2pair else "") parsed_uncotigorized = utils.parse_all_dirt(self.sh, merged.low, 2, next-1) if parsed_leader: dispname += f" [{parsed_leader}]" if parsed_location: dispname += f" [{parsed_location}]" dispname = dispname.replace("\n", "\\n") print(f"[{group_name}] row={row}; {pos} {pos_right} {pair} {weekday}: {'[ПОТОКОВЫЙ] ' if is_wide_maybe_potokoviy else ''}{dispname} {parsed_uncotigorized}") # INCREMENT на next и конец цикла. row += next def parse_groups(sh, head, monday, head_rx): """Распознать список групп и метаданные к ним, по сути получить список названий группы и координат её верхнего header-а (AQ6:AT6)""" groups = {} i = 0 while i < len(head): x = head[i] print(f"while i={i} head[i]={x}") merged = utils.get_merged(sh, head_rx, i) if i > monday[1] + 1: if merged is None or x.value == "": break name = utils.unspace(x.value) groups[name] = { "name": name, "position": [head_rx, i], "position_human": utils.merged_humanize(merged) } if merged is None: i += 1 else: i += (merged[3] - merged[1] + 1) return groups def get_weekday_left(sh, rowx, colx): m = utils.get_merged(sh, rowx, colx) return sh.cell(m[0], m[1]).value