fixes 3 pairs подряд, etc
This commit is contained in:
100
parser.py
100
parser.py
@@ -1,7 +1,11 @@
|
||||
# Copyright Stanislav Mironov
|
||||
|
||||
PAIR_NUMS = [
|
||||
"1-2", "3-4", "5-6", "7-8", "9-10", "11-12", "13-14", "15-16"
|
||||
]
|
||||
|
||||
import json
|
||||
|
||||
import xlrd
|
||||
|
||||
import uuid
|
||||
import aigenerated
|
||||
from coord import Coord, Merged
|
||||
from translations import ExcelSheetReader
|
||||
@@ -13,13 +17,13 @@ def pprint(*args, **kwargs):
|
||||
if LOGGING:
|
||||
print(*args, **kwargs)
|
||||
|
||||
|
||||
class Parser:
|
||||
def __init__(self, reader: ExcelSheetReader):
|
||||
self.reader = reader
|
||||
self.groups = {}
|
||||
self.teachers = set()
|
||||
self.places = set()
|
||||
self.parser_error = None
|
||||
pprint("Parser created for '{0}'".format(reader.info()))
|
||||
|
||||
def parse(self):
|
||||
@@ -27,6 +31,7 @@ class Parser:
|
||||
if monday is None:
|
||||
print(" -- Failed parse! -- ")
|
||||
print("ПОНЕДЕЛЬНИК НЕ НАЙДЕН!")
|
||||
self.parser_error = "'ПОНЕДЕЛЬНИК' не найден в таблице."
|
||||
return
|
||||
|
||||
head_rx = monday.row - 1 # выше первого понидельника
|
||||
@@ -59,7 +64,7 @@ class Parser:
|
||||
# location
|
||||
location = merged.high.shift(down=1).cell(self.reader).value
|
||||
|
||||
return {"loc": str(location), "leader": str(speaker), "name": str(merged.cell(self.reader).value)}
|
||||
return {"loc": str(location).strip(), "leader": str(speaker).strip(), "name": str(merged.cell(self.reader).value).strip()}
|
||||
|
||||
def process_group(self, group, monday):
|
||||
"""
|
||||
@@ -71,13 +76,13 @@ class Parser:
|
||||
pprint(group_name)
|
||||
row = group['position'][0] + 1 # counter for while, +1 for shift down; также номер строки в таблице (вроде с нуля)
|
||||
weeknum = 1 # номер недели, щёлкнет +1 при каком-то условии.
|
||||
previous_pair = None
|
||||
while row < self.reader.get_row_count(): # 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 = self.reader.get_merged_coord(pos)
|
||||
right_cell = pos_right.cell(self.reader)
|
||||
merged_cell = merged.cell(self.reader)
|
||||
cv = merged_cell.value
|
||||
# В конце (12 пара:>) название группы, можно использовать как якорь
|
||||
@@ -89,6 +94,16 @@ class Parser:
|
||||
weekday = utils.unspace(weekday_mr.cell(self.reader).value)
|
||||
pair_mr = self.reader.get_merged_coord(pair_pos)
|
||||
pair = utils.unspace(pair_mr.cell(self.reader).value)
|
||||
fuck_empty_pair_in_excel = pair == ""
|
||||
previous_dump = previous_pair
|
||||
if fuck_empty_pair_in_excel:
|
||||
if previous_pair is None or previous_pair == "":
|
||||
pair = f"EMPTY_IN_EXCEL_{uuid.uuid4()}"
|
||||
else:
|
||||
pair = utils.next_element(PAIR_NUMS, previous_pair)
|
||||
|
||||
if pair != "":
|
||||
previous_pair = pair
|
||||
|
||||
skip = 0
|
||||
if weekday == "":
|
||||
@@ -99,26 +114,25 @@ class Parser:
|
||||
row += 1
|
||||
else:
|
||||
break
|
||||
|
||||
if not skip:
|
||||
next = 3 # на сколько пыгнуть для следующего шага?
|
||||
|
||||
is_empty_lesson = right_cell.is_empty() and merged_cell.is_empty()
|
||||
dispname = ""
|
||||
is_empty_lesson = len(utils.parse_all_dirt(self.reader, pos, 4, 3)) == 0 # если в поле не найдено ничего..
|
||||
parsed_discipline_name = None
|
||||
parsed_location = None
|
||||
parsed_leader = None
|
||||
is_2pair = False
|
||||
pairs = 1
|
||||
is_solid = pos_right in merged
|
||||
parsed_uncotigorized = []
|
||||
is_wide_maybe_potokoviy = merged.width() > 4 # потоковая ли лекция (занимает несколько групп.)
|
||||
if is_empty_lesson:
|
||||
dispname = "<no lesson>"
|
||||
|
||||
if not is_empty_lesson:
|
||||
may_prepod = merged.low.shift(down=2)
|
||||
if utils.has_no_bottom_border(self.reader, may_prepod):
|
||||
next = 6
|
||||
is_2pair = True
|
||||
cur = merged.low.shift(down=2)
|
||||
while utils.has_no_bottom_border(self.reader, cur):
|
||||
next += 3
|
||||
pairs += 1
|
||||
cur = cur.shift(down=3)
|
||||
|
||||
if is_wide_maybe_potokoviy:
|
||||
ret = self.parse_potokoviy(merged)
|
||||
@@ -127,45 +141,37 @@ class Parser:
|
||||
parsed_discipline_name = ret['name']
|
||||
parsed_uncotigorized = list(utils.parse_all_dirt(self.reader, merged.low, merged.width(), next))
|
||||
|
||||
|
||||
else:
|
||||
if (is_solid):
|
||||
parsed_discipline_name = cv
|
||||
|
||||
dispname = cv
|
||||
dispname += (" SOLD" if is_solid else " SPLIT")
|
||||
dispname += (" [ДВУПАРНЫЙ]" if is_2pair else "")
|
||||
|
||||
parsed_uncotigorized = list(utils.parse_all_dirt(self.reader, merged.low, 4, next))
|
||||
|
||||
|
||||
if parsed_leader: dispname += f" [{parsed_leader}]"
|
||||
if parsed_location: dispname += f" [{parsed_location}]"
|
||||
dispname = dispname.replace("\n", "\\n")
|
||||
pprint(f"[{group_name}] row={row}; {pos} {pos_right} {pair} {weekday}: {'[ПОТОКОВЫЙ] ' if is_wide_maybe_potokoviy else ''}{dispname} {parsed_uncotigorized}")
|
||||
|
||||
# пытаемся из некотегорезированных данных выцепить место и лидера (препода)
|
||||
prepods = set()
|
||||
if parsed_leader is not None: prepods.add(aigenerated.extract_last_name(parsed_leader))
|
||||
if parsed_leader is not None: prepods.add(parsed_leader.strip())
|
||||
|
||||
locations = set()
|
||||
if parsed_location is not None: locations.add(parsed_location.replace(" ", "").replace("-", ""))
|
||||
if parsed_location is not None: locations.add(parsed_location.strip().replace(" ", ""))
|
||||
|
||||
for x in list(parsed_uncotigorized):
|
||||
if aigenerated.is_surname_string(x):
|
||||
prepods.add(aigenerated.extract_last_name(x))
|
||||
prepods.add(x.strip())
|
||||
|
||||
if aigenerated.is_room_number(x):
|
||||
locations.add(x.replace(" ", "").replace("-", "") if x is not None else None)
|
||||
locations.add(x.strip().replace(" ", "") if x is not None else None)
|
||||
|
||||
# оставшееся в дисциплину (костыль)
|
||||
# попытка починить пустую дисциплину
|
||||
if parsed_discipline_name is None:
|
||||
parsed_discipline_name = " ".join(parsed_uncotigorized)
|
||||
l = utils.remove_from_list(list(parsed_uncotigorized), [parsed_leader, parsed_location])
|
||||
parsed_discipline_name = " ".join(l)
|
||||
|
||||
prepods.discard(None)
|
||||
prepods.discard("")
|
||||
locations.discard(None)
|
||||
locations.discard("")
|
||||
# чистим сеты от мусора
|
||||
utils.discards_list(prepods, nones=True, emptystrings=True)
|
||||
utils.discards_list(locations, nones=True, emptystrings=True)
|
||||
utils.discards_list(parsed_uncotigorized, nones=True, emptystrings=True)
|
||||
|
||||
# если не пустой предмет то записываем его
|
||||
if not is_empty_lesson:
|
||||
slots = group['slots']
|
||||
w = weekday + ("_1" if weeknum == 1 else "_2")
|
||||
@@ -174,22 +180,30 @@ class Parser:
|
||||
|
||||
today = slots[w]
|
||||
today[pair] = {
|
||||
"pos": str(pos),
|
||||
"discipline": parsed_discipline_name,
|
||||
"excel_pos": str(pos),
|
||||
"discipline_name": parsed_discipline_name.strip(),
|
||||
"locations": list(locations),
|
||||
"leads": list(prepods),
|
||||
"is_solid": is_solid,
|
||||
"is_2pair": is_2pair,
|
||||
"time_coeff": pairs,
|
||||
"is_flow": is_wide_maybe_potokoviy,
|
||||
"lefttopmerged": {
|
||||
"width": merged.width(),
|
||||
"height": merged.height(),
|
||||
"excel_range": utils.merged_humanize(merged.as_numbers())
|
||||
},
|
||||
"raw": parsed_uncotigorized,
|
||||
"weeday": utils.weekday_to_num(weekday),
|
||||
"weekday": utils.weekday_to_num(weekday),
|
||||
"weeknum": weeknum
|
||||
}
|
||||
if fuck_empty_pair_in_excel:
|
||||
today[pair]['pair_num_empty'] = {
|
||||
"prev": previous_dump,
|
||||
"restoted": pair != "",
|
||||
"pair": pair
|
||||
}
|
||||
|
||||
|
||||
self.teachers.add(aigenerated.extract_last_name(parsed_leader))
|
||||
|
||||
|
||||
# INCREMENT на next и конец цикла.
|
||||
row += next
|
||||
|
||||
|
||||
Reference in New Issue
Block a user