// Данные по городам const CITIES = { "Алматы": { price: 650, year1: 7.2, year2: 18.4, count: 12450 }, "Астана": { price: 580, year1: 5.8, year2: 15.1, count: 8920 }, "Шымкент": { price: 390, year1: 6.1, year2: 14.7, count: 4560 }, "Караганда": { price: 320, year1: 4.2, year2: 12.3, count: 3210 }, "Актобе": { price: 340, year1: 5.1, year2: 13.8, count: 2180 }, "Тараз": { price: 290, year1: 3.9, year2: 11.2, count: 1540 }, "Павлодар": { price: 310, year1: 4.5, year2: 12.9, count: 1890 }, "Усть-Каменогорск": { price: 360, year1: 5.3, year2: 14.1, count: 1670 }, "Семей": { price: 280, year1: 3.7, year2: 10.8, count: 1230 }, "Атырау": { price: 420, year1: 6.8, year2: 16.2, count: 1980 }, "Костанай": { price: 300, year1: 4.1, year2: 11.5, count: 1450 }, "Кызылорда": { price: 330, year1: 4.8, year2: 13.1, count: 1120 } }; // История цен по Алматы (24 месяца) const ALMATY_HISTORY = [ { month: "Янв 2024", price: 550 }, { month: "Фев 2024", price: 555 }, { month: "Мар 2024", price: 560 }, { month: "Апр 2024", price: 565 }, { month: "Май 2024", price: 572 }, { month: "Июн 2024", price: 578 }, { month: "Июл 2024", price: 585 }, { month: "Авг 2024", price: 590 }, { month: "Сен 2024", price: 598 }, { month: "Окт 2024", price: 605 }, { month: "Ноя 2024", price: 612 }, { month: "Дек 2024", price: 620 }, { month: "Янв 2025", price: 625 }, { month: "Фев 2025", price: 630 }, { month: "Мар 2025", price: 635 }, { month: "Апр 2025", price: 640 }, { month: "Май 2025", price: 645 }, { month: "Июн 2025", price: 648 }, { month: "Июл 2025", price: 650 }, { month: "Авг 2025", price: 652 }, { month: "Сен 2025", price: 655 }, { month: "Окт 2025", price: 658 }, { month: "Ноя 2025", price: 660 }, { month: "Дек 2025", price: 665 } ]; // Генерация истории для других городов (на основе Алматы) function generateHistory(basePrice, growthRate) { const base = ALMATY_HISTORY.map((h, i) => ({ month: h.month, price: Math.round(basePrice * (h.price / 650) * (1 + growthRate / 100)) })); return base; } // Инициализация при загрузке document.addEventListener('DOMContentLoaded', () => { renderCitiesTable(); renderCitiesCards(); initMainChart(); initAnalyticsCharts(); }); // Рендер таблицы городов function renderCitiesTable() { const tbody = document.getElementById('cities-table'); const sorted = Object.entries(CITIES).sort((a, b) => b[1].price - a[1].price); tbody.innerHTML = sorted.map(([city, data]) => { const trendClass = data.year1 > 5 ? 'trend-up' : data.year1 < 3 ? 'trend-down' : ''; return ` ${city} ${data.price.toLocaleString('ru-RU')} тыс. ₸ ${data.year1 > 0 ? '+' : ''}${data.year1}% ${data.year2 > 0 ? '+' : ''}${data.year2}% ${data.count.toLocaleString('ru-RU')} `; }).join(''); } // Рендер карточек городов function renderCitiesCards() { const container = document.getElementById('cities-cards'); const sorted = Object.entries(CITIES).sort((a, b) => b[1].price - a[1].price); container.innerHTML = sorted.map(([city, data]) => `

${city}

${data.price.toLocaleString('ru-RU')} тыс. ₸
за м²
+${data.year1}% за год | +${data.year2}% за 2 года
`).join(''); } // Показ аналитики function showAnalytics() { const city = document.getElementById('filter-city').value; const rooms = parseInt(document.getElementById('filter-rooms').value); const areaFrom = parseInt(document.getElementById('filter-area-from').value) || 40; const areaTo = parseInt(document.getElementById('filter-area-to').value) || 80; const avgArea = (areaFrom + areaTo) / 2; const cityData = CITIES[city]; const avgPriceM2 = cityData.price; const avgFlatPrice = Math.round(avgPriceM2 * avgArea / 1000); document.getElementById('stat-avg-price').textContent = `${avgFlatPrice.toLocaleString('ru-RU')} млн ₸`; document.getElementById('stat-price-m2').textContent = `${avgPriceM2.toLocaleString('ru-RU')} тыс. ₸`; document.getElementById('stat-year2').textContent = `+${cityData.year2}%`; document.getElementById('stat-year1').textContent = `+${cityData.year1}%`; document.getElementById('results').classList.remove('hidden'); document.getElementById('results').scrollIntoView({ behavior: 'smooth', block: 'start' }); updateMainChart(city); } // Обновление главного графика let mainChart = null; function initMainChart() { const ctx = document.getElementById('priceChart').getContext('2d'); mainChart = new Chart(ctx, { type: 'line', data: { labels: ALMATY_HISTORY.map(h => h.month), datasets: [{ label: 'Цена за м², тыс. ₸', data: ALMATY_HISTORY.map(h => h.price), borderColor: 'var(--accent)', backgroundColor: 'rgba(0, 184, 204, 0.1)', tension: 0.4, fill: true, pointRadius: 2, pointHoverRadius: 4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { callbacks: { label: (ctx) => `${ctx.raw.toLocaleString('ru-RU')} тыс. ₸` } } }, scales: { y: { beginAtZero: false, ticks: { callback: (v) => v + ' тыс.' } } } } }); } function updateMainChart(city) { const cityData = CITIES[city]; const history = generateHistory(cityData.price, cityData.year2); mainChart.data.labels = history.map(h => h.month); mainChart.data.datasets[0].data = history.map(h => h.price); mainChart.update(); } // Калькулятор сравнения function calculateComparison() { const city = document.getElementById('calc-city').value; const price = parseFloat(document.getElementById('calc-price').value); const area = parseFloat(document.getElementById('calc-area').value); const rooms = parseInt(document.getElementById('calc-rooms').value); if (!price || !area) { alert('Введите цену и площадь'); return; } const cityData = CITIES[city]; const priceM2Flat = (price * 1000000) / area; const priceM2Market = cityData.price * 1000; const diff = ((priceM2Flat / priceM2Market) - 1) * 100; const resultEl = document.getElementById('calc-result'); const diffEl = document.getElementById('calc-diff'); const msgEl = document.getElementById('calc-message'); resultEl.classList.remove('hidden'); diffEl.textContent = `${diff > 0 ? '+' : ''}${diff.toFixed(1)}%`; if (diff > 5) { diffEl.className = 'text-4xl font-bold mb-2 trend-down'; msgEl.textContent = 'дороже средней цены рынка'; } else if (diff < -5) { diffEl.className = 'text-4xl font-bold mb-2 trend-up'; msgEl.textContent = 'дешевле средней цены рынка 🟢'; } else { diffEl.className = 'text-4xl font-bold mb-2'; msgEl.textContent = 'соответствует рыночной цене'; } } // Графики аналитики let almatyChart = null; let citiesChart = null; function initAnalyticsCharts() { // График Алматы const almatyCtx = document.getElementById('almatyChart').getContext('2d'); almatyChart = new Chart(almatyCtx, { type: 'line', data: { labels: ALMATY_HISTORY.map(h => h.month), datasets: [{ label: 'Алматы', data: ALMATY_HISTORY.map(h => h.price), borderColor: 'var(--accent)', tension: 0.4, pointRadius: 0, pointHoverRadius: 4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { ticks: { callback: (v) => v + ' тыс.' } } } } }); // Сравнение городов const citiesCtx = document.getElementById('citiesChart').getContext('2d'); const topCities = Object.entries(CITIES) .sort((a, b) => b[1].price - a[1].price) .slice(0, 5); citiesChart = new Chart(citiesCtx, { type: 'bar', data: { labels: topCities.map(c => c[0]), datasets: [{ label: 'Цена за м², тыс. ₸', data: topCities.map(c => c[1].price), backgroundColor: 'var(--accent)', borderRadius: 4 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true } } } }); } // Навигация document.querySelectorAll('.nav-link').forEach(link => { link.addEventListener('click', (e) => { document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active')); e.target.classList.add('active'); }); });