Добавьте источники для расчета
'; + return; + } + + let totalEmission = 0; + let maxSourceConcentration = 0; + + state.sources.forEach(source => { + totalEmission += source.emissionRate; + const concentration = calculateGaussianConcentration(source, 1, 0); + if (concentration > maxSourceConcentration) { + maxSourceConcentration = concentration; + } + }); + + const avgEmission = totalEmission / state.sources.length; + const maxPdkPercent = ((maxConcentration || maxSourceConcentration) / CONFIG.PDK_H2S) * 100; + + let dispersionModeName = ''; + switch(state.dispersionMode) { + case 'anisotropic': dispersionModeName = 'Анизотропный (ветер)'; break; + default: dispersionModeName = state.dispersionMode; + } + + let html = ` +Параметры расчета:
+Класс устойчивости: ${state.stabilityClass}
+Режим рассеивания: ${dispersionModeName}
+Ветер: ${state.windSpeed.toFixed(1)} м/с, направление: ${state.windDirection}° (${getWindDirectionName(state.windDirection)})
+Влияние ветра: ${Math.round(state.windEffectStrength * 100)}%
+Шаг сетки: ${state.gridStep} м (постоянный)
+Порог визуализации: ${(state.visualizationThreshold * 100).toFixed(4)}% ПДК (постоянный)
+Радиус влияния: ${state.heatmapRadius}px (зависит от зума)
+Текущий масштаб: ${map ? map.getZoom() : 'N/A'}
+Результаты:
+Количество источников: ${state.sources.length}
+Суммарный выброс: ${totalEmission.toFixed(2)} г/с
+Средний выброс: ${avgEmission.toFixed(2)} г/с
+Макс. концентрация: ${(maxConcentration || maxSourceConcentration).toExponential(3)} мг/м³
+Макс. % ПДК: ${maxPdkPercent.toFixed(4)}%
+ `; + + if (maxPdkPercent > 100) { + html += `Превышение ПДК в ${(maxPdkPercent/100).toFixed(2)} раз!
`; + } else if (maxPdkPercent > 80) { + html += `Концентрация близка к ПДК
`; + } else if (maxPdkPercent > 0) { + html += `Концентрация в допустимых пределах
`; + } + + html += `Модель: гауссово рассеивание с коэффициентами Пасквилла-Гиффорда и учетом ветра
`; + html += `${message}
+ + `; + errorMessage.style.display = 'block'; + } + updateDebugStatus("Ошибка: " + message); +} + +async function apiCall(url, options = {}) { + try { + const response = await fetch(url, { + headers: { 'Content-Type': 'application/json', ...options.headers }, + ...options + }); + return await response.json(); + } catch (error) { + console.error('API Error:', error); + return null; + } +} + +async function loadSourcesFromDB() { + const sources = await apiCall('/api/sources'); + if (sources) { + state.sources = sources.map(source => ({ + ...source, + id: source.id, + lat: source.latitude, + lng: source.longitude, + emissionRate: source.emission_rate, + height: source.height + })); + updateSourcesList(); + updateSourceMarkers(); + + if (state.sources.length > 0) { + setTimeout(() => { + updateHeatmapData(); + }, 1500); + } + } +} + +async function addSourceToDB(sourceData) { + return await apiCall('/api/sources', { + method: 'POST', + body: JSON.stringify(sourceData) + }); +} + +async function deleteSourceFromDB(sourceId) { + return await apiCall(`/api/sources/${sourceId}`, { method: 'DELETE' }); +} + +function updateSourcesList() { + const sourcesList = document.getElementById('sources-list'); + if (!sourcesList) return; + + sourcesList.innerHTML = ''; + state.sources.forEach(source => { + const sourceEl = document.createElement('div'); + sourceEl.className = 'enterprise-source-item'; + sourceEl.innerHTML = ` +Нет данных для отображения.
'; + return; + } + + let html = ''; + results.forEach((result, index) => { + const pdkPercent = (result.concentration / CONFIG.PDK_H2S) * 100; + const pdkClass = pdkPercent > 100 ? 'style="color: red; font-weight: bold;"' : pdkPercent > 80 ? 'style="color: orange;"' : ''; + html += ` +Источник #${index + 1}
+Выброс: ${result.emission.toFixed(3)} г/с, Высота: ${result.height} м
+Макс. концентрация: ${result.concentration.toFixed(6)} мг/м³ (${pdkPercent.toFixed(1)}% ПДК)
+На расстоянии: ${(result.distance / 1000).toFixed(1)} км
+Нет источников
' + : ''; + + monitoringState.sources.forEach(source => { + const sourceEl = document.createElement('div'); + sourceEl.className = 'source-item'; + sourceEl.innerHTML = ` + ${source.name}
+
+
+
+
+
+