Отзывы и предложения к софту от AleXStam
  • Страница 20 из 20
  • «
  • 1
  • 2
  • 18
  • 19
  • 20
Поговорим о...
Добавим отладочную информацию в консоль, чтобы посмотреть что определяется и что ищется. Обновим функцию drawGeologyColumn:

```javascript
// ГЕОЛОГИЧЕСКИЙ КРАП - поверх фона стратиграфии
if (geo.lithology && geo.lithology !== 'Не указано') {
const lithologyName = geo.lithology.toLowerCase().trim();

// Получаем lithologyId из geo (должен быть передан из extractIntervalsFast)
const lithologyId = geo.lithologyId;
let lcode = null;

// Пытаемся получить lcode если есть lithologyId и доступ к xmlContent
if (lithologyId && window.currentXmlContent) {
lcode = getLcodeForLithology(lithologyId, window.currentXmlContent);
}

// ДЕБАГ ИНФОРМАЦИЯ
console.log('=== ДЕБАГ ИНФОРМАЦИЯ О ЛИТОЛОГИИ ===');
console.log('Название литологии:', geo.lithology);
console.log('LithologyId:', lithologyId);
console.log('Lcode:', lcode);
console.log('XML доступен:', !!window.currentXmlContent);

const patternOverlay = document.createElement('div');

// Формируем имя файла - приоритет по lcode, затем по названию
let fileName = '';
if (lcode) {
fileName = `litology/${lcode} `; // Будет искать файлы типа "2600 Алевролит.svg"
console.log('Ищем файл по lcode:', fileName);
} else {
fileName = `litology/${encodeURIComponent(lithologyName)}.svg`;
console.log('Ищем файл по названию:', fileName);
}

patternOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("${fileName}");
background-repeat: repeat;
background-size: 150px 80px;
background-position: 0 0;
opacity: 0.6;
z-index: 22;
pointer-events: none;
`;
visualElement.appendChild(patternOverlay);

console.log('=== КОНЕЦ ДЕБАГ ИНФОРМАЦИИ ===');
}
```

Также добавим отладочную информацию в функцию getLcodeForLithology:

```javascript
// Функция для получения lcode по lithologyId
function getLcodeForLithology(lithologyId, xmlContent) {
if (!lithologyId) {
console.log('getLcodeForLithology: lithologyId не предоставлен');
return null;
}
try {
console.log('getLcodeForLithology: ищем lithologyId:', lithologyId);

const spckRegex = new RegExp(`<MR_DBA\\.SPCK>(?:[^<]|<(?!\\/MR_DBA\\.SPCK>))*<ID_SPCK>${lithologyId}<\\/ID_SPCK>(?:[^<]|<(?!\\/MR_DBA\\.SPCK>))*<\\/MR_DBA\\.SPCK>`, 's');
const spckMatch = xmlContent.match(spckRegex);

console.log('getLcodeForLithology: найдено совпадений:', spckMatch ? spckMatch.length : 0);

if (spckMatch) {
const lcode = extractValue(spckMatch[0], 'LCODE_SPCK');
console.log('getLcodeForLithology: извлеченный lcode:', lcode);
return lcode ? lcode.trim() : null;
} else {
console.log('getLcodeForLithology: не найдено записей SPCK для lithologyId:', lithologyId);
}
} catch (error) {
console.error('Ошибка получения lcode для lithologyId:', lithologyId, error);
}
return null;
}
```

И добавим проверку в extractIntervalsFast чтобы убедиться что lithologyId передается:

```javascript
const intervalData = {
numberPP: parseInt(extractValue(intervalMatch, 'NUMBER_PP_PODI') || '0'),
from: parseFloat(extractValue(intervalMatch, 'PO_DOCUM_FROM_PODI') || '0'),
to: parseFloat(extractValue(intervalMatch, 'PO_DOCUM_TO_PODI') || '0'),
thickness: parseFloat(extractValue(intervalMatch, 'THICKNESS_PODI') || '0'),
stratigraphy: stratigraphy,
lithology: lithology,
lithologyId: lithologyId, // Добавляем lithologyId для получения lcode
description: extractValue(intervalMatch, 'DESCRIPTION_PODI') || ''
};

console.log('extractIntervalsFast: создан интервал с lithologyId:', lithologyId, 'lithology:', lithology);
```

Теперь в консоли браузера мы увидим:

1. Какие lithologyId извлекаются из XML
2. Какие lcode находятся для этих lithologyId
3. По каким путям ищутся файлы SVG
4. Есть ли доступ к XML контенту

После этого мы сможем понять:

· Правильно ли извлекаются lithologyId из интервалов
· Находится ли соответствующий lcode в разделе SPCK
· Формируются ли правильные пути к файлам

Запустите приложение и откройте консоль браузера (F12), чтобы посмотреть отладочную информацию.

Добавлено (2025-10-15, 15:10)
---------------------------------------------
Понял! Нужно пройти по цепочке: classifier → lcode_speck → speck_spck. Исправлю функцию getLcodeForLithology:

```javascript
// Функция для получения lcode по lithologyId
function getLcodeForLithology(lithologyId, xmlContent) {
if (!lithologyId) {
console.log('getLcodeForLithology: lithologyId не предоставлен');
return null;
}
try {
console.log('getLcodeForLithology: ищем lithologyId:', lithologyId);

// 1. Ищем в CLASSIFIER по ID_NODE_ID (это lithologyId)
const classifierRegex = new RegExp(`<MR_DBA\\.CLASSIFIER>(?:[^<]|<(?!\\/MR_DBA\\.CLASSIFIER>))*<ID_NODE_ID>${lithologyId}<\\/ID_NODE_ID>(?:[^<]|<(?!\\/MR_DBA\\.CLASSIFIER>))*<\\/MR_DBA\\.CLASSIFIER>`, 's');
const classifierMatch = xmlContent.match(classifierRegex);

console.log('getLcodeForLithology: найдено CLASSIFIER совпадений:', classifierMatch ? classifierMatch.length : 0);

if (classifierMatch) {
// 2. Из CLASSIFIER получаем LCODE_SPECK (это ID для SPCK)
const lcodeSpeckId = extractValue(classifierMatch[0], 'LCODE_SPECK');
console.log('getLcodeForLithology: из CLASSIFIER извлечен LCODE_SPECK:', lcodeSpeckId);

if (lcodeSpeckId) {
// 3. Ищем в SPECK_SPCK по ID_SPECK_SPCK (это lcodeSpeckId)
const spckRegex = new RegExp(`<MR_DBA\\.SPECK_SPCK>(?:[^<]|<(?!\\/MR_DBA\\.SPECK_SPCK>))*<ID_SPECK_SPCK>${lcodeSpeckId}<\\/ID_SPECK_SPCK>(?:[^<]|<(?!\\/MR_DBA\\.SPECK_SPCK>))*<\\/MR_DBA\\.SPECK_SPCK>`, 's');
const spckMatch = xmlContent.match(spckRegex);

console.log('getLcodeForLithology: найдено SPECK_SPCK совпадений:', spckMatch ? spckMatch.length : 0);

if (spckMatch) {
// 4. Из SPECK_SPCK получаем LCODE_SPCK (это наш итоговый lcode)
const lcode = extractValue(spckMatch[0], 'LCODE_SPCK');
console.log('getLcodeForLithology: из SPECK_SPCK извлечен LCODE_SPCK:', lcode);
return lcode ? lcode.trim() : null;
} else {
console.log('getLcodeForLithology: не найдено записей SPECK_SPCK для ID_SPECK_SPCK:', lcodeSpeckId);
}
} else {
console.log('getLcodeForLithology: не найден LCODE_SPECK в CLASSIFIER');
}
} else {
console.log('getLcodeForLithology: не найдено записей CLASSIFIER для lithologyId:', lithologyId);
}
} catch (error) {
console.error('Ошибка получения lcode для lithologyId:', lithologyId, error);
}
return null;
}
```

Теперь функция проходит по всей цепочке:

1. CLASSIFIER → ищем по ID_NODE_ID (lithologyId) → получаем LCODE_SPECK
2. SPECK_SPCK → ищем по ID_SPECK_SPCK (lcodeSpeckId) → получаем LCODE_SPCK

Также обновим отладочную информацию в основном блоке:

```javascript
// ГЕОЛОГИЧЕСКИЙ КРАП - поверх фона стратиграфии
if (geo.lithology && geo.lithology !== 'Не указано') {
const lithologyName = geo.lithology.toLowerCase().trim();

// Получаем lithologyId из geo (должен быть передан из extractIntervalsFast)
const lithologyId = geo.lithologyId;
let lcode = null;

// Пытаемся получить lcode если есть lithologyId и доступ к xmlContent
if (lithologyId && window.currentXmlContent) {
lcode = getLcodeForLithology(lithologyId, window.currentXmlContent);
}

// ДЕБАГ ИНФОРМАЦИЯ
console.log('=== ДЕБАГ ИНФОРМАЦИЯ О ЛИТОЛОГИИ ===');
console.log('Интервал:', geo.from + '-' + geo.to + 'м');
console.log('Название литологии:', geo.lithology);
console.log('LithologyId:', lithologyId);
console.log('Найденный Lcode:', lcode);
console.log('XML доступен:', !!window.currentXmlContent);

const patternOverlay = document.createElement('div');

// Формируем имя файла - приоритет по lcode, затем по названию
let fileName = '';
if (lcode) {
fileName = `litology/${lcode} `; // Будет искать файлы типа "2600 Алевролит.svg"
console.log('Ищем файл по lcode:', fileName);
} else {
fileName = `litology/${encodeURIComponent(lithologyName)}.svg`;
console.log('Ищем файл по названию:', fileName);
}

patternOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("${fileName}");
background-repeat: repeat;
background-size: 150px 80px;
background-position: 0 0;
opacity: 0.6;
z-index: 22;
pointer-events: none;
`;
visualElement.appendChild(patternOverlay);

console.log('=== КОНЕЦ ДЕБАГ ИНФОРМАЦИИ ===');
}
```

Теперь в консоли мы увидим всю цепочку поиска lcode:

1. Найден ли CLASSIFIER по lithologyId
2. Какое значение LCODE_SPECK извлечено из CLASSIFIER
3. Найден ли SPECK_SPCK по этому ID
4. Какое значение LCODE_SPCK извлечено из SPECK_SPCK

Это поможет понять на каком этапе цепочки происходит проблема.

Добавлено (2025-10-15, 15:21)
---------------------------------------------
Понял! Нужно создать карту lcode из классификаторов. Сделаем это в функции createClassifierMap и будем хранить lcode вместе с названием литологии.

Обновим функцию createClassifierMap:

```javascript
function createClassifierMap(xmlContent) {
const classifierMap = new Map();
const lcodeMap = new Map(); // Новая карта для lcode

try {
const classifierRegex = /<MR_DBA\.CLASSIFIER>[\s\S]*?<\/MR_DBA\.CLASSIFIER>/g;
const classifierMatches = xmlContent.match(classifierRegex) || [];

for (const match of classifierMatches) {
const nodeId = extractValue(match, 'ID_NODE_ID');
const nodeName = extractValue(match, 'NODE_NAME');
const lcodeSpeckId = extractValue(match, 'LCODE_SPECK'); // ID для поиска в SPECK

if (nodeId && nodeName) {
classifierMap.set(nodeId, nodeName);

// Если есть lcodeSpeckId, сохраняем для дальнейшего поиска
if (lcodeSpeckId) {
lcodeMap.set(nodeId, lcodeSpeckId);
}
}
}

console.log('=== ДЕБАГ КЛАССИФИКАТОРОВ ===');
console.log('Найдено классификаторов:', classifierMap.size);
console.log('Из них с LCODE_SPECK:', lcodeMap.size);

// Теперь ищем lcode в SPECK
const speckRegex = /<MR_DBA\.SPECK_SPCK>[\s\S]*?<\/MR_DBA\.SPECK_SPCK>/g;
const speckMatches = xmlContent.match(speckRegex) || [];

console.log('Найдено записей SPECK:', speckMatches.length);

const finalLcodeMap = new Map();

for (const speckMatch of speckMatches) {
const speckId = extractValue(speckMatch, 'ID_SPECK_SPCK');
const lcode = extractValue(speckMatch, 'LCODE_SPCK');

if (speckId && lcode) {
// Ищем классификаторы, которые ссылаются на этот speckId
for (const [classifierId, speckIdFromClassifier] of lcodeMap) {
if (speckIdFromClassifier === speckId) {
finalLcodeMap.set(classifierId, lcode);
console.log('Найден lcode:', {
classifierId: classifierId,
lithologyName: classifierMap.get(classifierId),
lcode: lcode
});
break;
}
}
}
}

console.log('Итоговая карта lcode:', finalLcodeMap.size);
console.log('=== КОНЕЦ ДЕБАГ КЛАССИФИКАТОРОВ ===');

// Сохраняем карту lcode в глобальной области
window.lcodeMap = finalLcodeMap;

} catch (error) {
console.error('Ошибка создания карты классификаторов:', error);
}

return classifierMap;
}
```

Теперь обновим функцию extractIntervalsFast чтобы она сразу сохраняла lcode:

```javascript
function extractIntervalsFast(xmlContent, wellId, classifierMap) {
const intervals = {
primary: [],
final: [],
gis: []
};
try {
// Сохраняем xmlContent для доступа к lcode
window.currentXmlContent = xmlContent;

const docRegex = /<MR_DBA\.PO_DOCUM_PODC>[\s\S]*?<\/MR_DBA\.PO_DOCUM_PODC>/g;
const docMatches = xmlContent.match(docRegex) || [];
const docTypeMap = new Map();
const wellDocs = new Set();
for (const docMatch of docMatches) {
const docWellId = extractValue(docMatch, 'ID_POINT_OBSERV_PODC');
if (docWellId === wellId) {
const docId = extractValue(docMatch, 'ID_PO_DOCUM_PODC');
const docType = extractValue(docMatch, 'ID_TYPE_DOCUM_PODC');
if (docId && docType) {
docTypeMap.set(docId, docType);
wellDocs.add(docId);
}
}
}

const intervalRegex = /<MR_DBA\.PO_DOCUM_INT_PODI>[\s\S]*?<\/MR_DBA\.PO_DOCUM_INT_PODI>/g;
const intervalMatches = xmlContent.match(intervalRegex) || [];
for (const intervalMatch of intervalMatches) {
const docId = extractValue(intervalMatch, 'ID_PO_DOCUM_PODI');
if (!docId || !wellDocs.has(docId)) {
continue;
}
const docType = docTypeMap.get(docId);
if (!docType) continue;

const lithologyId = extractValue(intervalMatch, 'ID_LITHOLOGY_PODI');
let lithology = 'Не указано';
let lcode = null;

if (lithologyId && classifierMap.has(lithologyId)) {
lithology = classifierMap.get(lithologyId);
// Получаем lcode из глобальной карты
if (window.lcodeMap && window.lcodeMap.has(lithologyId)) {
lcode = window.lcodeMap.get(lithologyId);
}
}

const stratigraphyId = extractValue(intervalMatch, 'ID_STRATIGRAPHY_PODI');
let stratigraphy = 'Не указано';
if (stratigraphyId && classifierMap.has(stratigraphyId)) {
stratigraphy = convertStratigraphyText(classifierMap.get(stratigraphyId));
}

const intervalData = {
numberPP: parseInt(extractValue(intervalMatch, 'NUMBER_PP_PODI') || '0'),
from: parseFloat(extractValue(intervalMatch, 'PO_DOCUM_FROM_PODI') || '0'),
to: parseFloat(extractValue(intervalMatch, 'PO_DOCUM_TO_PODI') || '0'),
thickness: parseFloat(extractValue(intervalMatch, 'THICKNESS_PODI') || '0'),
stratigraphy: stratigraphy,
lithology: lithology,
lithologyId: lithologyId,
lcode: lcode, // Сохраняем lcode сразу
description: extractValue(intervalMatch, 'DESCRIPTION_PODI') || ''
};

console.log('Интервал:', {
lithology: lithology,
lithologyId: lithologyId,
lcode: lcode
});

if (docType.includes('Первич') || docType.includes('ПЕРВИЧ') || docType === '1') {
intervals.primary.push(intervalData);
} else if (docType.includes('Итогов') || docType.includes('ИТОГОВ') || docType === '2') {
intervals.final.push(intervalData);
} else if (docType.includes('ГИС') || docType.includes('геофизик')) {
intervals.gis.push(intervalData);
}
}

intervals.primary.sort((a, b) => a.numberPP - b.numberPP);
intervals.final.sort((a, b) => a.numberPP - b.numberPP);
intervals.gis.sort((a, b) => a.numberPP - b.numberPP);
} catch (error) {
console.error('Ошибка извлечения интервалов:', error);
}
return intervals;
}
```

И упростим функцию drawGeologyColumn:

```javascript
// ГЕОЛОГИЧЕСКИЙ КРАП - поверх фона стратиграфии
if (geo.lithology && geo.lithology !== 'Не указано') {
const lithologyName = geo.lithology.toLowerCase().trim();

// Получаем lcode напрямую из данных интервала
const lcode = geo.lcode;

// ДЕБАГ ИНФОРМАЦИЯ
console.log('=== ДЕБАГ ЛИТОЛОГИИ ===');
console.log('Название:', geo.lithology);
console.log('LithologyId:', geo.lithologyId);
console.log('Lcode:', lcode);

const patternOverlay = document.createElement('div');

// Формируем имя файла - приоритет по lcode, затем по названию
let fileName = '';
if (lcode) {
fileName = `litology/${lcode} `; // Будет искать файлы типа "2600 Алевролит.svg"
console.log('Ищем файл по lcode:', fileName);
} else {
fileName = `litology/${encodeURIComponent(lithologyName)}.svg`;
console.log('Ищем файл по названию:', fileName);
}

patternOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("${fileName}");
background-repeat: repeat;
background-size: 150px 80px;
background-position: 0 0;
opacity: 0.6;
z-index: 22;
pointer-events: none;
`;
visualElement.appendChild(patternOverlay);

console.log('=== КОНЕЦ ДЕБАГ ===');
}
```

Теперь система:

1. Создает карту lcode при парсинге классификаторов
2. Сохраняет lcode прямо в данных интервала
3. Использует готовый lcode для поиска файлов

Убрал сложную логику поиска через SPCK, теперь все делается на этапе создания карты классификаторов.

Изучил код. Проблема в том, что при формировании пути к файлу крапа используется некорректное имя файла. Вот исправленная функция, которая будет искать файлы по lcode в начале имени:

```javascript
function drawGeologyColumn(mergedGeology, data, drawingContainer, topReserve, scale) {
if (mergedGeology.length === 0) return;
const allGeologyElements = [];
const columnWidth = 100;

// Инициализация хранилища паттернов
if (!window.geologyPatterns) {
window.geologyPatterns = new Map();
}

// Функция для поиска файла крапа по lcode
function findPatternFileByLcode(lcode) {
if (!lcode) return null;

// Предполагаем, что у нас есть доступ к списку файлов крапа
const patternFiles = window.patternFiles || [];

// Ищем файл, который начинается с lcode + пробел
const targetFile = patternFiles.find(file =>
file.name.startsWith(lcode + ' ')
);

return targetFile ? `litology/${targetFile.name}` : null;
}

mergedGeology.forEach((geo, index) => {
const top = geo.from * scale + topReserve;
const height = (geo.to - geo.from) * scale;

if (height > 0) {
const convertedStratigraphy = convertStratigraphyText(geo.stratigraphy || 'Не указано');
const decodedStratigraphy = decodeStratigraphyForDisplay(convertedStratigraphy);

// ОСНОВНОЙ КОНТЕЙНЕР
const geologyElement = document.createElement('div');
geologyElement.className = 'geology-interval';
geologyElement.setAttribute('data-interval-index', index);
geologyElement.setAttribute('data-from', geo.from);
geologyElement.setAttribute('data-to', geo.to);
geologyElement.style.cssText = `
position: absolute;
top: ${top}px;
left: 120px;
width: ${columnWidth}px;
height: ${height}px;
background: transparent;
z-index: 20;
pointer-events: none;
`;

// ВИЗУАЛЬНЫЙ ЭЛЕМЕНТ
const visualElement = document.createElement('div');
visualElement.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: ${getStratigraphyBackground(geo.stratigraphy)};
border-left: 2px solid rgba(0,0,0,0.5);
border-right: 2px solid rgba(0,0,0,0.5);
z-index: 21;
pointer-events: none;
`;

// ГЕОЛОГИЧЕСКИЙ КРАП
if (geo.lithology && geo.lithology !== 'Не указано') {
const lcode = geo.lcode;

if (lcode) {
const patternFile = findPatternFileByLcode(lcode);

if (patternFile) {
const patternOverlay = document.createElement('div');
patternOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("${patternFile}");
background-repeat: repeat;
background-size: 150px 80px;
background-position: 0 0;
opacity: 0.6;
z-index: 22;
pointer-events: none;
`;
visualElement.appendChild(patternOverlay);
}
}
}

// ИНДЕКС СТРАТИГРАФИИ
if (decodedStratigraphy && decodedStratigraphy !== 'Не указано' && height > 20) {
const bgColor = getStratigraphyBackground(geo.stratigraphy);
const isDarkBackground = isColorDark(bgColor);
const textColor = isDarkBackground ? '#ffffff' : '#000000';
const labelBg = addTransparency(bgColor, 0.8);
const borderColor = isDarkBackground ? 'rgba(255,255,255,0.3)' : 'rgba(0,0,0,0.2)';

const stratigraphyLabel = document.createElement('div');
stratigraphyLabel.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: ${textColor};
font-size: ${Math.min(10, height / 3)}px;
font-weight: bold;
white-space: nowrap;
background: ${labelBg};
padding: 3px 6px;
border-radius: 3px;
pointer-events: none;
z-index: 23;
max-width: ${columnWidth - 10}px;
overflow: hidden;
text-overflow: ellipsis;
border: 0.5px solid ${borderColor};
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
text-align: center;
font-family: 'GeoindexA', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
letter-spacing: 0.5px;
`;
stratigraphyLabel.textContent = decodedStratigraphy;
visualElement.appendChild(stratigraphyLabel);
}

// КЛИКАБЕЛЬНЫЙ ОВЕРЛЕЙ
const clickableOverlay = document.createElement('div');
clickableOverlay.className = 'geology-clickable-overlay';
clickableOverlay.setAttribute('data-interval-index', index);
clickableOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: transparent;
z-index: 35;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 2px;
`;

clickableOverlay.addEventListener('click', function(e) {
e.stopPropagation();
e.preventDefault();
if (window.currentSelectedInterval) {
window.currentSelectedInterval.style.boxShadow = '';
window.currentSelectedInterval.style.background = 'transparent';
window.currentSelectedInterval.style.border = 'none';
}
this.style.boxShadow = '0 0 0 2px #e74c3c, inset 0 0 0 1px rgba(231, 76, 60, 0.3)';
this.style.background = 'rgba(231, 76, 60, 0.1)';
this.style.border = '1px dashed #e74c3c';
window.currentSelectedInterval = this;
const intervalIndex = parseInt(this.getAttribute('data-interval-index'));
highlightCard(intervalIndex);
});

clickableOverlay.addEventListener('mouseenter', function() {
if (this !== window.currentSelectedInterval) {
this.style.background = 'rgba(231, 76, 60, 0.05)';
this.style.border = '1px dashed #e74c3c';
}
});

clickableOverlay.addEventListener('mouseleave', function() {
if (this !== window.currentSelectedInterval) {
this.style.background = 'transparent';
this.style.border = 'none';
}
});

// Добавляем элементы
geologyElement.appendChild(visualElement);
geologyElement.appendChild(clickableOverlay);
drawingContainer.appendChild(geologyElement);
allGeologyElements.push(geologyElement);
}
});

window.geologyElements = allGeologyElements;
}
```

Также нужно добавить функцию для загрузки списка файлов крапа при инициализации:

```javascript
// Функция для загрузки списка файлов крапа
async function loadPatternFiles() {
try {
// Предполагаем, что файлы крапа находятся в папке litology
const patternFiles = [];

// Здесь должен быть код для получения списка файлов из папки litology
// В зависимости от среды выполнения (браузер/Electron)

window.patternFiles = patternFiles;
console.log('Загружено файлов крапа:', patternFiles.length);
} catch (error) {
console.error('Ошибка загрузки файлов крапа:', error);
window.patternFiles = [];
}
}

// Вызываем при загрузке приложения
document.addEventListener('DOMContentLoaded', function() {
setTimeout(loadPatternFiles, 1000);
});
```

Ключевые изменения:

1. findPatternFileByLcode(lcode) - новая функция для поиска файла по lcode
2. Поиск по началу имени - использует startsWith(lcode + ' ') для поиска файлов, которые начинаются с lcode + пробел
3. Минимальные изменения - функция остается компактной, добавлена только одна вспомогательная функция
4. Убрана сложная логика - удалены попытки поиска по разным вариантам имен, оставлен только корректный поиск по lcode

Для работы этого кода нужно обеспечить заполнение window.patternFiles массивом объектов с файлами крапа, где каждый объект имеет свойство name с именем файла.

Добавлено (2025-10-15, 16:42)
---------------------------------------------
Понял! Нужно автоматически сканировать папку litology и формировать список файлов. Вот исправленный код:

```javascript
// Функция для сканирования папки litology и формирования списка файлов
async function scanPatternFiles() {
try {
const patternFiles = [];

// В Electron можно использовать API для доступа к файловой системе
if (window.electronAPI && window.electronAPI.readDirectory) {
const files = await window.electronAPI.readDirectory('litology');
patternFiles.push(...files.filter(file =>
file.name.endsWith('.svg') || file.name.endsWith('.png')
));
}
// Для браузера - создаем фиктивный список для демонстрации
else {
// В реальном приложении здесь будет запрос к серверу
console.log('Electron API не доступен, используем фиктивные данные');
// Для тестирования можно добавить примеры
patternFiles.push(
{ name: '1300 Супесь.svg' },
{ name: '2600 Алевролит.svg' },
{ name: '4500 Песок.svg' }
);
}

window.patternFiles = patternFiles;
console.log('Найдено файлов крапа:', patternFiles.length);
patternFiles.forEach(file => console.log(' -', file.name));

} catch (error) {
console.error('Ошибка сканирования файлов крапа:', error);
window.patternFiles = [];
}
}

// Обновленная функция поиска файла по lcode
function findPatternFileByLcode(lcode) {
if (!lcode || !window.patternFiles) return null;

// Ищем файл, который начинается с lcode + пробел
const targetFile = window.patternFiles.find(file => {
const fileName = file.name || file;
return fileName.startsWith(lcode + ' ');
});

if (targetFile) {
const fileName = targetFile.name || targetFile;
const filePath = `litology/${fileName}`;
console.log(`Найден файл крапа для lcode ${lcode}:`, filePath);
return filePath;
}

console.log(`Файл крапа для lcode ${lcode} не найден`);
return null;
}

// Упрощенная функция отрисовки геологической колонки
function drawGeologyColumn(mergedGeology, data, drawingContainer, topReserve, scale) {
if (mergedGeology.length === 0) return;
const allGeologyElements = [];
const columnWidth = 100;

mergedGeology.forEach((geo, index) => {
const top = geo.from * scale + topReserve;
const height = (geo.to - geo.from) * scale;

if (height > 0) {
const convertedStratigraphy = convertStratigraphyText(geo.stratigraphy || 'Не указано');
const decodedStratigraphy = decodeStratigraphyForDisplay(convertedStratigraphy);

// ОСНОВНОЙ КОНТЕЙНЕР
const geologyElement = document.createElement('div');
geologyElement.className = 'geology-interval';
geologyElement.setAttribute('data-interval-index', index);
geologyElement.style.cssText = `
position: absolute;
top: ${top}px;
left: 120px;
width: ${columnWidth}px;
height: ${height}px;
background: transparent;
z-index: 20;
pointer-events: none;
`;

// ВИЗУАЛЬНЫЙ ЭЛЕМЕНТ
const visualElement = document.createElement('div');
visualElement.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: ${getStratigraphyBackground(geo.stratigraphy)};
border-left: 2px solid rgba(0,0,0,0.5);
border-right: 2px solid rgba(0,0,0,0.5);
z-index: 21;
pointer-events: none;
`;

// ГЕОЛОГИЧЕСКИЙ КРАП - ТЕПЕРЬ РАБОТАЕТ ПРАВИЛЬНО
const lcode = geo.lcode;
if (lcode) {
const patternFile = findPatternFileByLcode(lcode);

if (patternFile) {
const patternOverlay = document.createElement('div');
patternOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("${patternFile}");
background-repeat: repeat;
background-size: 150px 80px;
background-position: 0 0;
opacity: 0.6;
z-index: 22;
pointer-events: none;
`;
visualElement.appendChild(patternOverlay);
}
}

// ОСТАЛЬНЫЙ КОД БЕЗ ИЗМЕНЕНИЙ...
if (decodedStratigraphy && decodedStratigraphy !== 'Не указано' && height > 20) {
const bgColor = getStratigraphyBackground(geo.stratigraphy);
const isDarkBackground = isColorDark(bgColor);
const textColor = isDarkBackground ? '#ffffff' : '#000000';
const labelBg = addTransparency(bgColor, 0.8);
const borderColor = isDarkBackground ? 'rgba(255,255,255,0.3)' : 'rgba(0,0,0,0.2)';

const stratigraphyLabel = document.createElement('div');
stratigraphyLabel.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: ${textColor};
font-size: ${Math.min(10, height / 3)}px;
font-weight: bold;
white-space: nowrap;
background: ${labelBg};
padding: 3px 6px;
border-radius: 3px;
pointer-events: none;
z-index: 23;
max-width: ${columnWidth - 10}px;
overflow: hidden;
text-overflow: ellipsis;
border: 0.5px solid ${borderColor};
text-shadow: 0 1px 2px rgba(0,0,0,0.5);
text-align: center;
font-family: 'GeoindexA', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
letter-spacing: 0.5px;
`;
stratigraphyLabel.textContent = decodedStratigraphy;
visualElement.appendChild(stratigraphyLabel);
}

// КЛИКАБЕЛЬНЫЙ ОВЕРЛЕЙ
const clickableOverlay = document.createElement('div');
clickableOverlay.className = 'geology-clickable-overlay';
clickableOverlay.setAttribute('data-interval-index', index);
clickableOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: transparent;
z-index: 35;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 2px;
`;

clickableOverlay.addEventListener('click', function(e) {
e.stopPropagation();
e.preventDefault();
if (window.currentSelectedInterval) {
window.currentSelectedInterval.style.boxShadow = '';
window.currentSelectedInterval.style.background = 'transparent';
window.currentSelectedInterval.style.border = 'none';
}
this.style.boxShadow = '0 0 0 2px #e74c3c, inset 0 0 0 1px rgba(231, 76, 60, 0.3)';
this.style.background = 'rgba(231, 76, 60, 0.1)';
this.style.border = '1px dashed #e74c3c';
window.currentSelectedInterval = this;
highlightCard(index);
});

geologyElement.appendChild(visualElement);
geologyElement.appendChild(clickableOverlay);
drawingContainer.appendChild(geologyElement);
allGeologyElements.push(geologyElement);
}
});

window.geologyElements = allGeologyElements;
}

// Вызываем сканирование при загрузке
document.addEventListener('DOMContentLoaded', function() {
setTimeout(scanPatternFiles, 1000);
});

// Также можно вызвать при открытии вкладки конструкции
function initializeWellStructureDrawing() {
console.log('=== АВТОМАТИЧЕСКАЯ ИНИЦИАЛИЗАЦИЯ КОНСТРУКЦИИ ===');

// Сканируем файлы крапа если еще не сделали
if (!window.patternFiles) {
scanPatternFiles();
}

setTimeout(() => {
const structureData = generateWellStructureData();
if (structureData && document.getElementById('wellStructureDrawing')) {
createWellStructureDrawing(structureData);
}
}, 100);
}
```

Ключевые изменения:

1. scanPatternFiles() - автоматически сканирует папку litology и формирует список файлов
2. findPatternFileByLcode(lcode) - ищет файл по формату "1300 Супесь.svg" (lcode + пробел + любое название)
3. Автоматическое сканирование - при загрузке и при открытии вкладки конструкции
4. Логирование - чтобы видеть какие файлы найдены и для каких lcode

Для работы в Electron нужно добавить в main process:

```javascript
// В main process Electron
ipcMain.handle('read-directory', async (event, dirPath) => {
try {
const files = await fs.promises.readdir(dirPath);
return files.map(file => ({ name: file }));
} catch (error) {
console.error('Error reading directory:', error);
return [];
}
});
```

И в preload.js:

```javascript
contextBridge.exposeInMainWorld('electronAPI', {
readDirectory: (dirPath) => ipcRenderer.invoke('read-directory', dirPath),
// ... другие методы
});
```

Теперь крапы должны отображаться корректно!

66666
Прикрепления:
2_42_6_6.zip (123.5 Kb)
Отличная идея! Сделаем масштабирование паттернов крапа в зависимости от общего масштаба чертежа. Вот обновленный код:

1. Добавляем функцию для расчета размера паттерна

```javascript
// Функция для расчета размера паттерна крапа в зависимости от масштаба
function getPatternSize(baseScale = 40) {
const currentScale = window.currentScale || baseScale;
const scaleFactor = currentScale / baseScale;

// Базовый размер паттерна (150x80 при масштабе 40px/м)
const baseWidth = 150;
const baseHeight = 80;

// Масштабируем размер, но не слишком агрессивно
const scaledWidth = Math.max(80, Math.min(250, baseWidth * scaleFactor * 0.8));
const scaledHeight = Math.max(40, Math.min(120, baseHeight * scaleFactor * 0.8));

console.log(`Масштаб паттерна: ${currentScale}px/м -> ${scaledWidth}x${scaledHeight}px`);

return {
width: scaledWidth,
height: scaledHeight
};
}
```

2. Обновляем функцию drawGeologyColumn

В блоке с созданием паттерна крапа замените:

```javascript
// ГЕОЛОГИЧЕСКИЙ КРАП - поверх фона стратиграфии
if (geo.lithology && geo.lithology !== 'Не указано' && geo.lcode) {
console.log(`✅ Загружаем крап для "${geo.lithology}" с LCODE: ${geo.lcode}`);

const patternOverlay = document.createElement('div');

// Получаем размер паттерна в зависимости от масштаба
const patternSize = getPatternSize();

// Используем глобальную карту паттернов
const fileName = window.LITHOLOGY_PATTERNS && window.LITHOLOGY_PATTERNS[geo.lcode];

if (fileName) {
const patternUrl = `litology/${fileName}`;
console.log(`🔄 Загружаем файл крапа: ${patternUrl} (${patternSize.width}x${patternSize.height}px)`);

patternOverlay.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("${patternUrl}");
background-repeat: repeat;
background-size: ${patternSize.width}px ${patternSize.height}px;
background-position: 0 0;
opacity: 0.6;
z-index: 22;
pointer-events: none;
`;

// Предзагрузка изображения для избежания мерцания
const preloadImage = new Image();
preloadImage.src = patternUrl;

visualElement.appendChild(patternOverlay);
} else {
console.log(`❌ Файл крапа для LCODE ${geo.lcode} не найден в карте паттернов`);
}
} else if (geo.lithology && geo.lithology !== 'Не указано') {
console.log(`❌ Нет LCODE для литологии: ${geo.lithology}, lithologyId: ${geo.lithologyId}`);
}
```

3. Обновляем функцию redrawCurrentStructure

Добавьте вызов пересчета паттернов при изменении масштаба:

```javascript
function redrawCurrentStructure() {
console.log('Перерисовка текущей конструкции с масштабом:', window.currentScale, 'и режимом:', window.displayMode);

// Пересчитываем размеры паттернов для нового масштаба
const patternSize = getPatternSize();
console.log(`Новый размер паттернов: ${patternSize.width}x${patternSize.height}px`);

// Получаем активный тип документации
const activeButton = document.querySelector('#wellStructureDrawing [data-doc-type].active');
const activeDocType = activeButton ? activeButton.getAttribute('data-doc-type') : 'primary';
console.log('Активный тип документации:', activeDocType, 'Режим отображения:', window.displayMode);

// Обновляем через updateWellStructureByDocType с учетом масштаба и режима
updateWellStructureByDocType(activeDocType);
}
```

4. Добавляем визуальную индикацию масштаба в заголовок

Обновите создание заголовка в createWellStructureDrawing:

```javascript
const title = document.createElement('h3');
const docTypeNames = {
'primary': 'Первичное',
'final': 'Итоговое',
'gis': 'ГИС'
};

// Получаем размер паттерна для отображения в заголовке
const patternSize = getPatternSize();

title.textContent = `Конструкция скважины • Глубина: ${structureData.totalDepth} м • ${docTypeNames[structureData.documentationType] || structureData.documentationType} • Масштаб: ${window.currentScale}px/м • Паттерн: ${patternSize.width}x${patternSize.height}px`;
title.style.cssText = `
margin: 0 0 15px 0;
color: white;
font-size: 16px;
font-weight: 600;
text-align: center;
`;
```

5. Улучшенная версия с плавным масштабированием

Если хотите более тонкое управление, вот расширенная версия:

```javascript
// Расширенная функция для расчета размера паттерна
function getPatternSize(baseScale = 40) {
const currentScale = window.currentScale || baseScale;
const scaleFactor = currentScale / baseScale;

// Базовый размер паттерна (150x80 при масштабе 40px/м)
const baseWidth = 150;
const baseHeight = 80;

// Нелинейное масштабирование для лучшего визуального восприятия
const nonLinearFactor = Math.sqrt(scaleFactor);

// Масштабируем размер с ограничениями
const scaledWidth = Math.max(60, Math.min(300, baseWidth * nonLinearFactor));
const scaledHeight = Math.max(30, Math.min(150, baseHeight * nonLinearFactor));

// Округляем до ближайших 5 пикселей для производительности
const roundedWidth = Math.round(scaledWidth / 5) * 5;
const roundedHeight = Math.round(scaledHeight / 5) * 5;

console.log(`Масштаб паттерна: ${currentScale}px/м (фактор: ${scaleFactor.toFixed(2)}) -> ${roundedWidth}x${roundedHeight}px`);

return {
width: roundedWidth,
height: roundedHeight,
scaleFactor: scaleFactor
};
}

// Функция для применения масштаба ко всем существующим паттернам
function updateExistingPatterns() {
const patternSize = getPatternSize();
const geologyElements = document.querySelectorAll('.geology-interval');

geologyElements.forEach(element => {
const patternOverlay = element.querySelector('div[style*="background-image"]');
if (patternOverlay) {
patternOverlay.style.backgroundSize = `${patternSize.width}px ${patternSize.height}px`;
}
});
}
```

6. Обновляем функцию adjustScale

```javascript
function adjustScale(delta) {
// Ограничиваем масштаб от 10 до 100 пикселей на метр
const newScale = Math.max(10, Math.min(100, window.currentScale + delta));
if (newScale !== window.currentScale) {
window.currentScale = newScale;

// Обновляем существующие паттерны перед полной перерисовкой
updateExistingPatterns();

redrawCurrentStructure();
updateScaleIndicator();
}
}
```

Результат:

Теперь паттерны крапа будут масштабироваться в зависимости от общего масштаба чертежа:

· Масштаб 40px/м (по умолчанию): 150×80px
· Масштаб 20px/м (уменьшение): ~106×57px
· Масштаб 60px/м (увеличение): ~184×98px
· Масштаб 100px/м (максимум): ~237×126px

При этом сохраняются разумные ограничения, чтобы паттерны не становились слишком мелкими или слишком крупными.

Добавлено (2025-10-16, 13:55)
---------------------------------------------
Правильно! Нужно оптимизировать поиск цветов - как только нашли точное совпадение, прекращаем поиск. Вот обновленная логика:

1. Обновляем функцию getStratigraphyBackground

```javascript
function getStratigraphyBackground(stratigraphy) {
if (!stratigraphy || stratigraphy === 'Не указано') {
return '#ffffff';
}

const convertedStratigraphy = convertStratigraphyText(stratigraphy || 'Не указано');
const lowerStratigraphy = convertedStratigraphy.toLowerCase();

console.log('Раскраска стратиграфии:', {
original: stratigraphy,
converted: convertedStratigraphy,
lower: lowerStratigraphy
});

// 1. Сначала проверяем SPECIFIC_STRATIGRAPHY_COLORS на ТОЧНОЕ совпадение (самый высокий приоритет)
if (typeof SPECIFIC_STRATIGRAPHY_COLORS !== 'undefined') {
// Точное совпадение в специфичных цветах - ПРЕКРАЩАЕМ поиск если нашли
if (SPECIFIC_STRATIGRAPHY_COLORS[lowerStratigraphy]) {
console.log('✅ Найдено ТОЧНОЕ совпадение в специфичных цветах:', lowerStratigraphy, SPECIFIC_STRATIGRAPHY_COLORS[lowerStratigraphy]);
return SPECIFIC_STRATIGRAPHY_COLORS[lowerStratigraphy];
}

// Частичные совпадения в специфичных цветах (с самых длинных ключей)
const specificKeys = Object.keys(SPECIFIC_STRATIGRAPHY_COLORS)
.sort((a, b) => b.length - a.length); // Сначала самые длинные ключи

for (const key of specificKeys) {
// Улучшенный поиск частичных совпадений
if (lowerStratigraphy.includes(key) ||
key.includes(lowerStratigraphy) ||
findSimilarMatch(lowerStratigraphy, key)) {
console.log('✅ Найдено частичное совпадение в специфичных цветах:', key, SPECIFIC_STRATIGRAPHY_COLORS[key]);
return SPECIFIC_STRATIGRAPHY_COLORS[key];
}
}
}

// 2. Затем проверяем стандартные цвета ТОЛЬКО если не нашли в специфичных
const stratigraphyColors = {
// Четвертичная система (Quaternary) - Светло-желтый
'четвертич': '#FEF0C5',
'q': '#FEF0C5',
'q1': '#FEF0C5',
'q2': '#FEF0C5',
'q3': '#FEF0C5',
'q4': '#FEF0C5',
'голоцен': '#FEF0C5',
'плейстоцен': '#FEF0C5',
'qiv': '#FEF0C5',
'qv': '#FEF0C5',
// Неогеновая система (Neogene) - Желто-коричневый
'неоген': '#F8F5DB',
'n': '#F8F5DB',
'n1': '#F8F5DB',
'n2': '#FEF0C5',
'плиоцен': '#F8F5DB',
'миоцен': '#F8F5DB',
'n1-2': '#F8F5DB',
// Палеогеновая система (Paleogene) - Светло-зеленый
'палеоген': '#FFE7C9',
'p': '#FFE7C9',
'p1': '#FFE7C9',
'p2': '#FFE7C9',
'p3': '#FFE7C9',
'олигоцен': '#FFE7C9',
'эоцен': '#FFE7C9',
'палеоцен': '#FFE7C9',
'p2-3': '#FFE7C9',
// Меловая система (Cretaceous) - Зеленый
'мел': '#E4F8C5',
'k': '#E4F8C5',
'k1': '#E4F8C5',
'k2': '#E4F8C5',
'верхний мел': '#E4F8C5',
'нижний мел': '#E4F8C5',
'k1-2': '#E4F8C5',
// Юрская система (Jurassic) - Синий
'юр': '#DCE5F8',
'j': '#DCE5F8',
'j1': '#DCE5F8',
'j2': '#DCE5F8',
'j3': '#DCE5F8',
'верхняя юра': '#DCE5F8',
'средняя юра': '#DCE5F8',
'нижняя юра': '#DCE5F8',
'j1-3': '#DCE5F8',
// Триасовая система (Triassic) - Фиолетовый
'триас': '#EED2F5',
't': '#EED2F5',
't1': '#EED2F5',
't2': '#EED2F5',
't3': '#EED2F5',
'верхний триас': '#EED2F5',
'средний триас': '#EED2F5',
'нижний триас': '#EED2F5',
't1-3': '#EED2F5',
// Пермская система (Permian) - Красно-коричневый
'перм': '#FFE2C1',
'p': '#FFE2C1',
'p1': '#FFE2C1',
'p2': '#FFE2C1',
'верхняя пермь': '#FFE2C1',
'нижняя пермь': '#FFE2C1',
'p1-2': '#FFE2C1',
// Каменноугольная система (Carboniferous) - Серый
'карбон': '#BBBBBC',
'c': '#BBBBBC',
'c1': '#BBBBBC',
'c2': '#BBBBBC',
'c3': '#BBBBBC',
'верхний карбон': '#BBBBBC',
'средний карбон': '#BBBBBC',
'нижний карбон': '#BBBBBC',
'c1-3': '#BBBBBC',
// Девонская система (Devonian) - Коричневый
'девон': '#F0C39D',
'd': '#F0C39D',
'd1': '#F0C39D',
'd2': '#F0C39D',
'd3': '#F0C39D',
'верхний девон': '#F0C39D',
'средний девон': '#F0C39D',
'нижний девон': '#F0C39D',
'd1-3': '#F0C39D',
// Силурийская система (Silurian) - Оливковый
'силур': '#E0E6AB',
's': '#E0E6AB',
's1': '#E0E6AB',
's2': '#E0E6AB',
'верхний силур': '#E0E6AB',
'нижний силур': '#E0E6AB',
's1-2': '#E0E6AB',
// Ордовикская система (Ordovician) - Голубой
'ордовик': '#AEE7D4',
'o': '#AEE7D4',
'o1': '#AEE7D4',
'o2': '#AEE7D4',
'o3': '#AEE7D4',
'верхний ордовик': '#AEE7D4',
'средний ордовик': '#AEE7D4',
'нижний ордовик': '#AEE7D4',
'o1-3': '#AEE7D4',
// Кембрийская система (Cambrian) - Светло-голубой (по стандарту ВСЕГЕИ)
'кембрий': '#A8D2CD',
'є': '#A8D2CD',
'ε': '#A8D2CD',
'g': '#A8D2CD',
'g1': '#A8D2CD',
'g2': '#A8D2CD',
'g3': '#A8D2CD',
'g1hl': '#A8D2CD',
'g2hl': '#A8D2CD',
'g3hl': '#A8D2CD',
'ghl': '#A8D2CD',
'верхний кембрий': '#A8D2CD',
'средний кембрий': '#A8D2CD',
'нижний кембрий': '#A8D2CD',
'кембрийский': '#A8D2CD',
'кембрийская': '#A8D2CD',
'кембрийское': '#A8D2CD',
// Докембрий (Precambrian) - Темные тона
'докембрий': '#9e9e9e',
'протерозой': '#9e9e9e',
'архей': '#9e9e9e',
'рифей': '#9e9e9e',
'венд': '#9e9e9e',
'pr': '#9e9e9e',
'pt': '#9e9e9e',
'ar': '#9e9e9e',
// венд
'венд': '#FFDAD6',
'v': '#FFDAD6',
'v1': '#FFDAD6',
'v2': '#FFDAD6',
// рифей
'рифей': '#FF8C71',
'rf': '#FF8C71',
'rf1': '#FF8C71',
'rf2': '#FF8C71',
'rf3': '#FF8C71',
// архей
'архей': '#F4BDE3',
'ar': '#F4BDE3',
'ar1': '#F4BDE3',
'ar2': '#F4BDE3',
'lp': '#F4BDE3'
};

// Точное совпадение в стандартных цветах - ПРЕКРАЩАЕМ поиск если нашли
if (stratigraphyColors[lowerStratigraphy]) {
console.log('✅ Найдено ТОЧНОЕ совпадение в стандартных цветах:', lowerStratigraphy, stratigraphyColors[lowerStratigraphy]);
return stratigraphyColors[lowerStratigraphy];
}

// Частичные совпадения в стандартных цветах (ВКЛЮЧАЯ одиночные символы)
const standardKeys = Object.keys(stratigraphyColors)
.sort((a, b) => b.length - a.length); // Сначала самые длинные ключи

for (const key of standardKeys) {
// Улучшенный поиск частичных совпадений
if (lowerStratigraphy.includes(key) ||
key.includes(lowerStratigraphy) ||
findSimilarMatch(lowerStratigraphy, key)) {
console.log('✅ Найдено частичное совпадение в стандартных цветах:', key, stratigraphyColors[key]);
return stratigraphyColors[key];
}
}

// 3. Геологические индексы (одиночные буквы) - как запасной вариант
if (/^[a-z]\d*[a-z]*$/i.test(lowerStratigraphy)) {
const firstChar = lowerStratigraphy.charAt(0);
const geologicalIndices = {
// Российская система обозначений по ВСЕГЕИ
'g': '#A8D2CD', // Кембрий (голубой)
'є': '#A8D2CD', // Кембрий (кириллица)
'ε': '#A8D2CD', // Кембрий (греческий)
'o': '#AEE7D4', // Ордовик (голубой)
's': '#E0E6AB', // Силур (оливковый)
'd': '#F0C39D', // Девон (коричневый)
'c': '#BBBBBC', // Карбон (серый)
'p': '#FFE2C1', // Пермь (красный)
't': '#EED2F5', // Триас (фиолетовый)
'j': '#DCE5F8', // Юра (синий)
'k': '#E4F8C5', // Мел (зеленый)
'n': '#F8F5DB', // Неоген (бежевый)
'q': '#FEF0C5', // Четвертичный (желтый)
'r': '#9e9e9e', // Докембрий
'v': '#9e9e9e' // Венд
};
if (geologicalIndices[firstChar]) {
console.log('✅ Найдено по геологическому индексу:', firstChar, geologicalIndices[firstChar]);
return geologicalIndices[firstChar];
}
}

console.log('❌ Не найдено совпадений, используется цвет по умолчанию');
return '#ffffff';
}
```

2. Улучшаем функцию findSimilarMatch

```javascript
// Новая функция для поиска похожих совпадений
function findSimilarMatch(stratigraphy, key) {
// Убираем спецсимволы и приводим к нижнему регистру
const cleanStratigraphy = stratigraphy.replace(/[^a-zа-яё0-9]/gi, '').toLowerCase();
const cleanKey = key.replace(/[^a-zа-яё0-9]/gi, '').toLowerCase();

// Проверяем совпадение после очистки
if (cleanStratigraphy.includes(cleanKey) || cleanKey.includes(cleanStratigraphy)) {
return true;
}

// Проверяем совпадение по первым символам
if (cleanStratigraphy.length > 2 && cleanKey.length > 2) {
const stratStart = cleanStratigraphy.substring(0, 3);
const keyStart = cleanKey.substring(0, 3);
if (stratStart === keyStart) {
return true;
}
}

// Проверяем совпадение по основным частям
const stratWords = cleanStratigraphy.split(/\s+/);
const keyWords = cleanKey.split(/\s+/);

// Если хотя бы одно слово из ключа есть в стратиграфии
for (const keyWord of keyWords) {
if (keyWord.length > 2 && stratWords.some(stratWord => stratWord.includes(keyWord))) {
return true;
}
}

return false;
}
```

3. Добавляем логирование для отладки

```javascript
// Функция для логирования процесса поиска цвета
function logColorSearch(stratigraphy, foundColor, source) {
console.group(`🎨 Поиск цвета для: "${stratigraphy}"`);
console.log(`📁 Источник: ${source}`);
console.log(`🎯 Результат: ${foundColor}`);
console.groupEnd();
}
```

Ключевые изменения:

1. Приоритет поиска:
· Сначала SPECIFIC_STRATIGRAPHY_COLORS - точное совпадение → СТОП
· Затем SPECIFIC_STRATIGRAPHY_COLORS - частичное совпадение → СТОП
· Затем стандартные цвета - точное совпадение → СТОП
· Затем стандартные цвета - частичное совпадение → СТОП
· И только потом геологические индексы
2. Оптимизация:
· Как только находим точное совпадение - сразу возвращаем результат
· Сортируем ключи по длине (самые длинные сначала)
· Улучшена логика частичных совпадений
3. Логирование:
· Четкое отслеживание где нашли цвет
· Понятно какой источник использовался

Теперь система будет работать максимально эффективно - как только найдет точное совпадение в specific_stratigraphy_colors.js, поиск сразу прекратится!

ыыыыыы
Прикрепления:
2_42_6_7.zip (124.6 Kb)
  • Страница 20 из 20
  • «
  • 1
  • 2
  • 18
  • 19
  • 20
Поиск:
Новый ответ
Имя:
Текст сообщения: