Аудитории 223: видимый столбец важнее скрытого дубля
В листе «аудитории» два столбца с номером 223: видимый («комп.класс Linux/Windows; интерактивная панель; маркер; 20 мест») и скрытый («компьютерный класс для МО и СТ; 24 места»). Парсер читал скрытый, потому что скрытые столбцы пропускались только при поиске групп, а в описаниях аудиторий нет — и он затирал видимый: у 223 не было ни панели, ни 20 мест. Теперь в описаниях аудиторий скрытые столбцы обрабатываются после видимых и не перекрывают их (аудитория, у которой есть только скрытый столбец, как 415/405/402, по-прежнему разбирается). Заодно тип понимает «комп.класс Linux/Windows». Проверено на таблице: 223 -> 20 мест, оснащение ПК + интерактивная панель + маркер, тип «комп.класс linux/windows». Тесты: 170.
This commit is contained in:
@@ -351,8 +351,11 @@ def build_room_schedule(rooms: dict, label: str, day_times: dict | None = None)
|
|||||||
|
|
||||||
# Тип берём фразой как в таблице (порядок — от специфичных к общим).
|
# Тип берём фразой как в таблице (порядок — от специфичных к общим).
|
||||||
_ROOM_TYPE_PATTERNS = [
|
_ROOM_TYPE_PATTERNS = [
|
||||||
re.compile(r"комп\.?\s*класс(?:\s+(?:Linux|Windows|OS))?", re.I),
|
re.compile(r"комп\.?\s*класс(?:\s+(?:Linux|Windows|OS)(?:\s*[/,]\s*(?:Linux|Windows|OS))*)?", re.I),
|
||||||
re.compile(r"компьютерн\w*\s+класс(?:\s+(?:Linux|Windows|OS))?", re.I),
|
re.compile(
|
||||||
|
r"компьютерн\w*\s+класс(?:\s+(?:Linux|Windows|OS)(?:\s*[/,]\s*(?:Linux|Windows|OS))*)?",
|
||||||
|
re.I,
|
||||||
|
),
|
||||||
re.compile(r"кабинет\s+англ\w*", re.I),
|
re.compile(r"кабинет\s+англ\w*", re.I),
|
||||||
re.compile(r"лекционно-практическая", re.I),
|
re.compile(r"лекционно-практическая", re.I),
|
||||||
re.compile(r"лекционная", re.I),
|
re.compile(r"лекционная", re.I),
|
||||||
@@ -475,15 +478,17 @@ def parse_rooms_info(sheets: dict[str, Worksheet]) -> dict:
|
|||||||
return {}
|
return {}
|
||||||
header, desc = sheet.rows[0], sheet.rows[1]
|
header, desc = sheet.rows[0], sheet.rows[1]
|
||||||
info: dict = {}
|
info: dict = {}
|
||||||
for col in range(_FIRST_GROUP_COL, max(len(header), len(desc))):
|
|
||||||
|
def add(col: int) -> None:
|
||||||
m = re.search(r"(\d+)", str(header[col]))
|
m = re.search(r"(\d+)", str(header[col]))
|
||||||
if not m:
|
if not m:
|
||||||
continue
|
return
|
||||||
number = m.group(1)
|
label = f"ауд. {m.group(1)}"
|
||||||
|
if label in info:
|
||||||
|
return # видимый столбец важнее скрытого дубля с тем же номером
|
||||||
text = _strip_marks(
|
text = _strip_marks(
|
||||||
" ".join(ln.strip() for ln in str(desc[col]).split("\n") if ln.strip())
|
" ".join(ln.strip() for ln in str(desc[col]).split("\n") if ln.strip())
|
||||||
)
|
)
|
||||||
label = f"ауд. {number}"
|
|
||||||
room_kind = room_type(text)
|
room_kind = room_type(text)
|
||||||
info[label] = {
|
info[label] = {
|
||||||
"room": label,
|
"room": label,
|
||||||
@@ -494,6 +499,14 @@ def parse_rooms_info(sheets: dict[str, Worksheet]) -> dict:
|
|||||||
"equipment": room_equipment(text),
|
"equipment": room_equipment(text),
|
||||||
"available_days": room_weekdays(text),
|
"available_days": room_weekdays(text),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
columns = range(_FIRST_GROUP_COL, max(len(header), len(desc)))
|
||||||
|
for col in columns: # сначала видимые
|
||||||
|
if col not in sheet.hidden_cols:
|
||||||
|
add(col)
|
||||||
|
for col in columns: # потом скрытые: аудитория без видимого столбца тоже нужна
|
||||||
|
if col in sheet.hidden_cols:
|
||||||
|
add(col)
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -299,3 +299,40 @@ def test_lowercase_except_abbreviations():
|
|||||||
assert parsing.room_type("Кабинет Английского") == "кабинет английского"
|
assert parsing.room_type("Кабинет Английского") == "кабинет английского"
|
||||||
assert parsing.room_equipment("ПК, Проектор, интернет МО") == ["ПК", "проектор"]
|
assert parsing.room_equipment("ПК, Проектор, интернет МО") == ["ПК", "проектор"]
|
||||||
assert parsing.lower_except_abbr("МО и СТ; без проектора") == "МО и СТ; без проектора"
|
assert parsing.lower_except_abbr("МО и СТ; без проектора") == "МО и СТ; без проектора"
|
||||||
|
|
||||||
|
|
||||||
|
def test_room_visible_column_wins_over_hidden_duplicate():
|
||||||
|
"""У 223 в таблице два столбца: видимый (с панелью) и скрытый (без). Берём видимый."""
|
||||||
|
from xlsx_builder import SheetSpec
|
||||||
|
|
||||||
|
spec = SheetSpec(
|
||||||
|
rows=[
|
||||||
|
[None] * 6 + ["223", "223"],
|
||||||
|
[None] * 6 + [
|
||||||
|
"комп.класс Linux/Windows; интерактивная панель; маркер; 20 мест",
|
||||||
|
"компьютерный класс для МО и СТ; 24 места",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
hidden_cols=[(7, 7)],
|
||||||
|
)
|
||||||
|
info = parsing.parse_rooms_info(make_sheets({parsing.ROOMS_SHEET: spec}))
|
||||||
|
room = info["ауд. 223"]
|
||||||
|
assert room["capacity"] == 20
|
||||||
|
assert "интерактивная панель" in room["equipment"]
|
||||||
|
assert room["type"] == "комп.класс linux/windows"
|
||||||
|
|
||||||
|
|
||||||
|
def test_room_only_in_hidden_column_still_parsed():
|
||||||
|
"""Аудитория, у которой есть только скрытый столбец, не пропадает."""
|
||||||
|
from xlsx_builder import SheetSpec
|
||||||
|
|
||||||
|
spec = SheetSpec(
|
||||||
|
rows=[
|
||||||
|
[None] * 6 + ["402", "410"],
|
||||||
|
[None] * 6 + ["402 четверг пятница", "проектор; 30 мест"],
|
||||||
|
],
|
||||||
|
hidden_cols=[(6, 7)],
|
||||||
|
)
|
||||||
|
info = parsing.parse_rooms_info(make_sheets({parsing.ROOMS_SHEET: spec}))
|
||||||
|
assert info["ауд. 402"]["available_days"] == ["четверг", "пятница"]
|
||||||
|
assert info["ауд. 410"]["capacity"] == 30
|
||||||
|
|||||||
Reference in New Issue
Block a user