Аудитории: из описания показываем только то, чего нет в атрибутах
Раньше описание выводилось целиком, и у аудиторий вида 405 («пк») получался дубль: «ПК» в атрибутах и «пк» строкой ниже. Теперь описание разбирается по частям: вместимость вырезается, а куски, которые целиком состоят из типа/оснащения/дней/номера, не показываются. Остаются только реальные дополнения: «без проектора», «МО и СТ», «амфитиатром». Слова не режутся по частям (раньше появлялись осколки вида «а», «-», «мелова»); короткие теги («ПК») учитываются, регистр сохраняется.
This commit is contained in:
@@ -449,13 +449,53 @@ function daysPhrase(days) {
|
|||||||
return `по ${forms.slice(0, -1).join(", ")} и ${forms[forms.length - 1]}`;
|
return `по ${forms.slice(0, -1).join(", ")} и ${forms[forms.length - 1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Описание из таблицы, если оно не сводится к номеру и дням (иначе не показываем). */
|
/**
|
||||||
|
* Дополнение из таблицы: оставляем только фразы, которых нет в разобранных
|
||||||
|
* атрибутах («без проектора», «МО и СТ»), не разрезая слова. Если описание
|
||||||
|
* целиком сводится к типу/оснащению/вместимости/номеру/дням — не показываем.
|
||||||
|
*/
|
||||||
function roomInfoText(room) {
|
function roomInfoText(room) {
|
||||||
const info = (room.info || "").trim();
|
const info = (room.info || "").trim();
|
||||||
if (!info) return "";
|
if (!info) return "";
|
||||||
let rest = info.replace(/\d+/g, "");
|
|
||||||
(room.available_days || []).forEach((day) => { rest = rest.split(day).join(""); });
|
const known = new Set();
|
||||||
return rest.replace(/[\s;,.]+/g, "") ? info : "";
|
const addText = (text) =>
|
||||||
|
(text || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.split(/[\s;,.:()\/-]+/)
|
||||||
|
.forEach((word) => { if (word.length >= 2) known.add(word); });
|
||||||
|
addText(room.type);
|
||||||
|
addText(room.type_group);
|
||||||
|
(room.equipment || []).forEach(addText);
|
||||||
|
(room.available_days || []).forEach(addText);
|
||||||
|
|
||||||
|
const STOP = new Set(["и", "в", "на", "для", "по", "с", "из", "до", "за", "от", "к", "о", "об", "при", "под", "над", "у"]);
|
||||||
|
const CAPACITY = /\d+\s*(?:мест[а-яё]*|раб\.?|осн\.?)/gi;
|
||||||
|
const isKnown = (token) => {
|
||||||
|
const clean = token.toLowerCase().replace(/[^а-яёa-z0-9]+/g, "");
|
||||||
|
if (!clean || !/[а-яёa-z]/.test(clean)) return true; // числа и знаки
|
||||||
|
if (clean.length < 2) return true;
|
||||||
|
if (STOP.has(clean)) return true;
|
||||||
|
if (/^(мест|раб|осн)/.test(clean)) return true; // «место», «раб.»
|
||||||
|
return [...known].some(
|
||||||
|
(k) => clean.startsWith(k.slice(0, 4)) || k.startsWith(clean.slice(0, 4)),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return info
|
||||||
|
.replace(CAPACITY, " ")
|
||||||
|
.split(/[;,]/)
|
||||||
|
.map((part) => part.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((part) => {
|
||||||
|
const tokens = part.split(/\s+/);
|
||||||
|
if (tokens.every(isKnown)) return "";
|
||||||
|
const rest = [...tokens];
|
||||||
|
while (rest.length && isKnown(rest[0])) rest.shift(); // убираем ведущие известные слова
|
||||||
|
return rest.join(" ");
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("; ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Русское склонение существительного при числе. */
|
/** Русское склонение существительного при числе. */
|
||||||
|
|||||||
Reference in New Issue
Block a user