Spaces:
Running
Running
| // Data Literacy Dashboard Application | |
| class DataLiteracyApp { | |
| constructor() { | |
| this.currentPage = 'home'; | |
| this.currentProfession = ''; | |
| this.testCurrentQuestion = 0; | |
| this.testAnswers = []; | |
| // Application data | |
| this.data = { | |
| statistics: { | |
| dataImportant: "87% співробітників вважають базові навички роботи з даними важливими", | |
| dataTrained: "Тільки 40% співробітників почуваються підготовленими", | |
| dataLiteracy: "64% керівників повідомляють про нестачу розуміння даних" | |
| }, | |
| professions: { | |
| marketing: { | |
| title: "Маркетинг та продажі", | |
| icon: "📊", | |
| uses: [ | |
| "Аналіз поведінки клієнтів", | |
| "Оптимізація рекламних кампаній", | |
| "Персоналізація повідомлень", | |
| "Прогнозування продажів", | |
| "Аналіз ROI" | |
| ], | |
| example: "DirectTV використовує USPS дані для персоналізації сторінок для людей, які переїжджають", | |
| metrics: ["CTR", "Conversion Rate", "CAC", "LTV", "ROAS"], | |
| interactive: "roi_calculator" | |
| }, | |
| hr: { | |
| title: "Людські ресурси", | |
| icon: "👥", | |
| uses: [ | |
| "Планування робочої сили", | |
| "Оптимізація рекрутингу", | |
| "Аналіз плинності кадрів", | |
| "Оцінка ефективності навчання", | |
| "Прогнозування продуктивності" | |
| ], | |
| example: "Credit Suisse використовує HR аналітику для прогнозування ризику звільнення", | |
| metrics: ["Turnover Rate", "Time to Hire", "Employee Satisfaction", "Training ROI"], | |
| interactive: "turnover_simulator" | |
| }, | |
| finance: { | |
| title: "Фінанси", | |
| icon: "💰", | |
| uses: [ | |
| "Фінансові коефіцієнти", | |
| "Аналіз прибутковості", | |
| "Управління ризиками", | |
| "Бюджетування та прогнозування", | |
| "Контроль витрат" | |
| ], | |
| example: "Банки використовують аналітику для категоризації клієнтів за кредитними ризиками", | |
| metrics: ["ROI", "NPV", "Liquidity Ratio", "Debt-to-Equity", "Profit Margin"], | |
| interactive: "financial_calculator" | |
| }, | |
| operations: { | |
| title: "Операції та логістика", | |
| icon: "🚚", | |
| uses: [ | |
| "Оптимізація ланцюга поставок", | |
| "Прогнозне обслуговування", | |
| "Управління запасами", | |
| "Планування маршрутів", | |
| "Контроль якості" | |
| ], | |
| example: "Walmart використовує аналітику для оптимізації запасів та зменшення витрат на 20%", | |
| metrics: ["Inventory Turnover", "Order Fulfillment Rate", "Lead Time", "Quality Score"], | |
| interactive: "inventory_simulator" | |
| }, | |
| customer_service: { | |
| title: "Клієнтський сервіс", | |
| icon: "📞", | |
| uses: [ | |
| "Аналіз задоволеності клієнтів", | |
| "Оптимізація часу відповіді", | |
| "Прогнозування навантаження", | |
| "Персоналізація підтримки", | |
| "Аналіз відгуків" | |
| ], | |
| example: "Компанії використовують аналітику для моніторингу в реальному часі та покращення досвіду клієнтів", | |
| metrics: ["CSAT", "NPS", "First Call Resolution", "Average Handle Time"], | |
| interactive: "service_dashboard" | |
| }, | |
| manufacturing: { | |
| title: "Виробництво", | |
| icon: "🏭", | |
| uses: [ | |
| "Прогнозне обслуговування обладнання", | |
| "Контроль якості", | |
| "Оптимізація виробничих процесів", | |
| "Управління ресурсами", | |
| "Планування виробництва" | |
| ], | |
| example: "United Airlines використовує прогнозну аналітику для технічного обслуговування літаків", | |
| metrics: ["OEE", "Downtime", "Quality Rate", "Production Cost", "Throughput"], | |
| interactive: "equipment_monitor" | |
| }, | |
| healthcare: { | |
| title: "Охорона здоров'я", | |
| icon: "🏥", | |
| uses: [ | |
| "Прогнозування захворюваності", | |
| "Оптимізація розкладу персоналу", | |
| "Управління запасами ліків", | |
| "Аналіз ефективності лікування", | |
| "Планування ресурсів" | |
| ], | |
| example: "Лікарні використовують ML для прогнозування кількості пацієнтів у відділенні невідкладної допомоги", | |
| metrics: ["Patient Satisfaction", "Readmission Rate", "Average Length of Stay", "Resource Utilization"], | |
| interactive: "hospital_predictor" | |
| }, | |
| it: { | |
| title: "IT та технології", | |
| icon: "💻", | |
| uses: [ | |
| "Моніторинг системи", | |
| "Аналіз продуктивності", | |
| "Прогнозування відмов", | |
| "Оптимізація ресурсів", | |
| "Безпека даних" | |
| ], | |
| example: "Компанії використовують аналітику для прогнозування та попередження системних збоїв", | |
| metrics: ["Uptime", "Response Time", "Security Incidents", "Resource Utilization"], | |
| interactive: "system_monitor" | |
| } | |
| }, | |
| literacyLevels: [ | |
| { | |
| level: 1, | |
| name: "Conversational", | |
| description: "Розуміння базових термінів та концепцій", | |
| skills: ["Читання графіків", "Розуміння основних метрик", "Участь в обговореннях даних"] | |
| }, | |
| { | |
| level: 2, | |
| name: "Literacy", | |
| description: "Здатність працювати з простими наборами даних", | |
| skills: ["Фільтрація даних", "Створення базових звітів", "Інтерпретація результатів"] | |
| }, | |
| { | |
| level: 3, | |
| name: "Competency", | |
| description: "Впевнене використання аналітичних інструментів", | |
| skills: ["Складні запити", "Візуалізація даних", "Статистичний аналіз"] | |
| }, | |
| { | |
| level: 4, | |
| name: "Fluency", | |
| description: "Експертний рівень аналітики", | |
| skills: ["Машинне навчання", "Прогнозування", "Комплексне моделювання"] | |
| }, | |
| { | |
| level: 5, | |
| name: "Multilingual", | |
| description: "Лідерство в data-driven організаціях", | |
| skills: ["Стратегія даних", "Управління командами", "Інновації в аналітиці"] | |
| } | |
| ], | |
| testQuestions: [ | |
| { | |
| question: "Як часто ви використовуєте дані у своїй роботі?", | |
| options: [ | |
| { text: "Щодня", value: 4 }, | |
| { text: "Кілька разів на тиждень", value: 3 }, | |
| { text: "Кілька разів на місяць", value: 2 }, | |
| { text: "Рідко або ніколи", value: 1 } | |
| ] | |
| }, | |
| { | |
| question: "Наскільки впевнено ви створюєте графіки та діаграми?", | |
| options: [ | |
| { text: "Дуже впевнено", value: 4 }, | |
| { text: "Достатньо впевнено", value: 3 }, | |
| { text: "Базово", value: 2 }, | |
| { text: "Не вмію", value: 1 } | |
| ] | |
| }, | |
| { | |
| question: "Чи можете ви виявити тренди в даних?", | |
| options: [ | |
| { text: "Легко виявляю складні тренди", value: 4 }, | |
| { text: "Виявляю основні тренди", value: 3 }, | |
| { text: "Іноді помічаю очевидні тренди", value: 2 }, | |
| { text: "Важко виявити тренди", value: 1 } | |
| ] | |
| }, | |
| { | |
| question: "Як ви ставитеся до статистичних понять?", | |
| options: [ | |
| { text: "Вільно використовую статистику", value: 4 }, | |
| { text: "Розумію базові концепції", value: 3 }, | |
| { text: "Знаю лише основи", value: 2 }, | |
| { text: "Статистика складна для мене", value: 1 } | |
| ] | |
| }, | |
| { | |
| question: "Чи маєте ви досвід з аналітичними інструментами?", | |
| options: [ | |
| { text: "Використовую професійні інструменти", value: 4 }, | |
| { text: "Працюю з Excel та подібними", value: 3 }, | |
| { text: "Базове використання таблиць", value: 2 }, | |
| { text: "Мінімальний досвід", value: 1 } | |
| ] | |
| } | |
| ] | |
| }; | |
| this.init(); | |
| } | |
| init() { | |
| this.renderProfessionNavigation(); | |
| this.renderLiteracyLevels(); | |
| this.bindEvents(); | |
| } | |
| bindEvents() { | |
| // Modal events | |
| document.getElementById('interactiveModal').addEventListener('click', (e) => { | |
| if (e.target.id === 'interactiveModal') { | |
| this.closeModal(); | |
| } | |
| }); | |
| document.getElementById('testModal').addEventListener('click', (e) => { | |
| if (e.target.id === 'testModal') { | |
| this.closeTestModal(); | |
| } | |
| }); | |
| // Escape key to close modals | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'Escape') { | |
| this.closeModal(); | |
| this.closeTestModal(); | |
| } | |
| }); | |
| } | |
| renderProfessionNavigation() { | |
| const navContainer = document.getElementById('professionNav'); | |
| navContainer.innerHTML = ''; | |
| Object.entries(this.data.professions).forEach(([key, profession]) => { | |
| const navItem = document.createElement('button'); | |
| navItem.className = 'nav-item'; | |
| navItem.onclick = () => this.showProfession(key); | |
| navItem.innerHTML = ` | |
| <span class="nav-icon">${profession.icon}</span> | |
| <span>${profession.title}</span> | |
| `; | |
| navContainer.appendChild(navItem); | |
| }); | |
| } | |
| renderLiteracyLevels() { | |
| const container = document.getElementById('literacyLevels'); | |
| container.innerHTML = ''; | |
| this.data.literacyLevels.forEach(level => { | |
| const levelElement = document.createElement('div'); | |
| levelElement.className = 'literacy-level'; | |
| levelElement.innerHTML = ` | |
| <div class="level-number">${level.level}</div> | |
| <div class="level-info"> | |
| <div class="level-name">${level.name}</div> | |
| <div class="level-description">${level.description}</div> | |
| <div class="level-skills"> | |
| ${level.skills.map(skill => `<span class="skill-tag">${skill}</span>`).join('')} | |
| </div> | |
| </div> | |
| `; | |
| container.appendChild(levelElement); | |
| }); | |
| } | |
| showHome() { | |
| this.setActivePage('home'); | |
| this.setActiveNavItem(0); | |
| } | |
| showFirstProfession() { | |
| const firstProfession = Object.keys(this.data.professions)[0]; | |
| this.showProfession(firstProfession); | |
| } | |
| showProfession(professionKey) { | |
| this.currentProfession = professionKey; | |
| const profession = this.data.professions[professionKey]; | |
| this.setActivePage('professionPages'); | |
| this.setActiveNavItem(Object.keys(this.data.professions).indexOf(professionKey) + 1); | |
| const content = document.getElementById('professionContent'); | |
| content.innerHTML = ` | |
| <div class="profession-header"> | |
| <div class="profession-icon">${profession.icon}</div> | |
| <div> | |
| <h2 class="profession-title">${profession.title}</h2> | |
| </div> | |
| </div> | |
| <div class="uses-section"> | |
| <h3>🎯 Способи використання даних</h3> | |
| <div class="uses-list"> | |
| ${profession.uses.map(use => ` | |
| <div class="use-item">${use}</div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| <div class="example-section"> | |
| <h3>💡 Реальний приклад</h3> | |
| <div class="example-card"> | |
| ${profession.example} | |
| </div> | |
| </div> | |
| <div class="metrics-section"> | |
| <h3>📊 Ключові метрики</h3> | |
| <div class="metrics-grid"> | |
| ${profession.metrics.map(metric => ` | |
| <div class="metric-tag">${metric}</div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| <div class="interactive-section"> | |
| <h3>🎮 Інтерактивний інструмент</h3> | |
| <p>Спробуйте практичний інструмент для цієї професії</p> | |
| <button class="btn btn--primary" onclick="app.openInteractive('${profession.interactive}')"> | |
| Запустити інструмент | |
| </button> | |
| </div> | |
| `; | |
| } | |
| showLiteracyLevels() { | |
| this.setActivePage('literacyPage'); | |
| this.setActiveNavItem(Object.keys(this.data.professions).length + 1); | |
| } | |
| setActivePage(pageId) { | |
| // Hide all pages | |
| document.querySelectorAll('.page').forEach(page => { | |
| page.classList.remove('active'); | |
| }); | |
| // Show selected page | |
| document.getElementById(pageId).classList.add('active'); | |
| this.currentPage = pageId; | |
| } | |
| setActiveNavItem(index) { | |
| // Remove active class from all nav items | |
| document.querySelectorAll('.nav-item').forEach(item => { | |
| item.classList.remove('active'); | |
| }); | |
| // Add active class to selected item | |
| const navItems = document.querySelectorAll('.nav-item'); | |
| if (navItems[index]) { | |
| navItems[index].classList.add('active'); | |
| } | |
| } | |
| openInteractive(type) { | |
| const modal = document.getElementById('interactiveModal'); | |
| const modalTitle = document.getElementById('modalTitle'); | |
| const modalBody = document.getElementById('modalBody'); | |
| modalTitle.textContent = this.getInteractiveTitle(type); | |
| modalBody.innerHTML = this.getInteractiveContent(type); | |
| modal.classList.add('active'); | |
| this.bindInteractiveEvents(type); | |
| } | |
| getInteractiveTitle(type) { | |
| const titles = { | |
| 'roi_calculator': 'Калькулятор ROI кампанії', | |
| 'turnover_simulator': 'Симулятор плинності кадрів', | |
| 'financial_calculator': 'Калькулятор фінансових коефіцієнтів', | |
| 'inventory_simulator': 'Симулятор управління запасами', | |
| 'service_dashboard': 'Дашборд метрик клієнтського сервісу', | |
| 'equipment_monitor': 'Монітор стану обладнання', | |
| 'hospital_predictor': 'Прогнозувач навантаження лікарні', | |
| 'system_monitor': 'Системний монітор' | |
| }; | |
| return titles[type] || 'Інтерактивний інструмент'; | |
| } | |
| getInteractiveContent(type) { | |
| switch (type) { | |
| case 'roi_calculator': | |
| return ` | |
| <div class="calculator-grid"> | |
| <div class="form-group"> | |
| <label class="form-label">Витрати на кампанію (₴)</label> | |
| <input type="number" class="form-control" id="campaignCost" value="10000"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Дохід від кампанії (₴)</label> | |
| <input type="number" class="form-control" id="campaignRevenue" value="25000"> | |
| </div> | |
| </div> | |
| <button class="btn btn--primary" onclick="app.calculateROI()">Розрахувати ROI</button> | |
| <div id="roiResult" class="result-card" style="display: none;"> | |
| <div class="result-value" id="roiValue"></div> | |
| <div>Рентабельність інвестицій</div> | |
| </div> | |
| `; | |
| case 'turnover_simulator': | |
| return ` | |
| <div class="simulator-controls"> | |
| <div class="slider-group"> | |
| <label class="form-label">Розмір зарплати: <span id="salaryValue">50000</span> ₴</label> | |
| <input type="range" class="slider" id="salarySlider" min="30000" max="100000" value="50000" step="5000"> | |
| </div> | |
| <div class="slider-group"> | |
| <label class="form-label">Задоволеність роботою: <span id="satisfactionValue">7</span>/10</label> | |
| <input type="range" class="slider" id="satisfactionSlider" min="1" max="10" value="7"> | |
| </div> | |
| <div class="slider-group"> | |
| <label class="form-label">Можливості розвитку: <span id="growthValue">6</span>/10</label> | |
| <input type="range" class="slider" id="growthSlider" min="1" max="10" value="6"> | |
| </div> | |
| </div> | |
| <div id="turnoverResult" class="result-card"> | |
| <div class="result-value" id="turnoverRate">15%</div> | |
| <div>Прогнозований рівень плинності</div> | |
| </div> | |
| `; | |
| case 'financial_calculator': | |
| return ` | |
| <div class="calculator-grid"> | |
| <div class="form-group"> | |
| <label class="form-label">Чистий прибуток (₴)</label> | |
| <input type="number" class="form-control" id="netProfit" value="500000"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Загальні активи (₴)</label> | |
| <input type="number" class="form-control" id="totalAssets" value="2000000"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Власний капітал (₴)</label> | |
| <input type="number" class="form-control" id="equity" value="1200000"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Дохід (₴)</label> | |
| <input type="number" class="form-control" id="revenue" value="3000000"> | |
| </div> | |
| </div> | |
| <button class="btn btn--primary" onclick="app.calculateFinancials()">Розрахувати коефіцієнти</button> | |
| <div id="financialResults" style="display: none; margin-top: 20px;"> | |
| <div class="metrics-grid"> | |
| <div class="metric-tag">ROA: <span id="roaValue"></span></div> | |
| <div class="metric-tag">ROE: <span id="roeValue"></span></div> | |
| <div class="metric-tag">Profit Margin: <span id="marginValue"></span></div> | |
| </div> | |
| </div> | |
| `; | |
| case 'inventory_simulator': | |
| return ` | |
| <div class="simulator-controls"> | |
| <div class="slider-group"> | |
| <label class="form-label">Поточний запас: <span id="currentStock">100</span> одиниць</label> | |
| <input type="range" class="slider" id="stockSlider" min="0" max="500" value="100" step="10"> | |
| </div> | |
| <div class="slider-group"> | |
| <label class="form-label">Щоденне споживання: <span id="dailyDemand">15</span> одиниць</label> | |
| <input type="range" class="slider" id="demandSlider" min="5" max="50" value="15"> | |
| </div> | |
| <div class="slider-group"> | |
| <label class="form-label">Час поставки: <span id="leadTime">7</span> днів</label> | |
| <input type="range" class="slider" id="leadSlider" min="1" max="30" value="7"> | |
| </div> | |
| </div> | |
| <div id="inventoryResult" class="result-card"> | |
| <div class="result-value" id="stockDays">7</div> | |
| <div>Днів запасу залишилось</div> | |
| </div> | |
| `; | |
| case 'service_dashboard': | |
| return ` | |
| <div class="metrics-grid"> | |
| <div class="metric-tag">CSAT: <span id="csatMetric">4.2/5</span></div> | |
| <div class="metric-tag">NPS: <span id="npsMetric">67</span></div> | |
| <div class="metric-tag">FCR: <span id="fcrMetric">82%</span></div> | |
| <div class="metric-tag">AHT: <span id="ahtMetric">3.5 хв</span></div> | |
| </div> | |
| <button class="btn btn--primary" onclick="app.refreshServiceMetrics()">Оновити метрики</button> | |
| <div style="margin-top: 20px; padding: 15px; background: var(--color-secondary); border-radius: 8px;"> | |
| <h4>📊 Тренд задоволеності клієнтів</h4> | |
| <p>📈 Зростання на 12% за останній місяць</p> | |
| <p>⚡ Час відповіді покращився на 25%</p> | |
| <p>🎯 85% звернень вирішено з першого разу</p> | |
| </div> | |
| `; | |
| case 'equipment_monitor': | |
| return ` | |
| <div class="metrics-grid"> | |
| <div class="metric-tag">Температура: <span id="tempMetric">72°C</span></div> | |
| <div class="metric-tag">Вібрація: <span id="vibrMetric">Норма</span></div> | |
| <div class="metric-tag">Ефективність: <span id="effMetric">94%</span></div> | |
| <div class="metric-tag">Час роботи: <span id="uptimeMetric">99.2%</span></div> | |
| </div> | |
| <button class="btn btn--primary" onclick="app.refreshEquipmentData()">Оновити дані</button> | |
| <div style="margin-top: 20px; padding: 15px; background: var(--color-success); color: var(--color-btn-primary-text); border-radius: 8px;"> | |
| <h4>✅ Прогнозна аналітика</h4> | |
| <p>🔧 Наступне ТО через 15 днів</p> | |
| <p>⚠️ Рекомендується заміна фільтра через 7 днів</p> | |
| <p>📊 Ризик поломки: Низький (5%)</p> | |
| </div> | |
| `; | |
| case 'hospital_predictor': | |
| return ` | |
| <div class="simulator-controls"> | |
| <div class="slider-group"> | |
| <label class="form-label">День тижня: <span id="dayValue">Понеділок</span></label> | |
| <input type="range" class="slider" id="daySlider" min="1" max="7" value="1"> | |
| </div> | |
| <div class="slider-group"> | |
| <label class="form-label">Година: <span id="hourValue">12</span>:00</label> | |
| <input type="range" class="slider" id="hourSlider" min="0" max="23" value="12"> | |
| </div> | |
| <div class="slider-group"> | |
| <label class="form-label">Сезон: <span id="seasonValue">Зима</span></label> | |
| <input type="range" class="slider" id="seasonSlider" min="1" max="4" value="1"> | |
| </div> | |
| </div> | |
| <div id="hospitalResult" class="result-card"> | |
| <div class="result-value" id="patientCount">23</div> | |
| <div>Прогнозована кількість пацієнтів</div> | |
| </div> | |
| `; | |
| case 'system_monitor': | |
| return ` | |
| <div class="metrics-grid"> | |
| <div class="metric-tag">CPU: <span id="cpuMetric">45%</span></div> | |
| <div class="metric-tag">RAM: <span id="ramMetric">67%</span></div> | |
| <div class="metric-tag">Disk: <span id="diskMetric">23%</span></div> | |
| <div class="metric-tag">Network: <span id="netMetric">12 Mbps</span></div> | |
| </div> | |
| <button class="btn btn--primary" onclick="app.refreshSystemData()">Оновити статус</button> | |
| <div style="margin-top: 20px; padding: 15px; background: var(--color-success); color: var(--color-btn-primary-text); border-radius: 8px;"> | |
| <h4>🚨 Системні події</h4> | |
| <p>✅ Всі сервіси працюють нормально</p> | |
| <p>📊 Середній час відповіді: 120ms</p> | |
| <p>🔒 Останній інцидент безпеки: 30 днів тому</p> | |
| </div> | |
| `; | |
| default: | |
| return '<p>Інтерактивний контент недоступний.</p>'; | |
| } | |
| } | |
| bindInteractiveEvents(type) { | |
| switch (type) { | |
| case 'turnover_simulator': | |
| ['salary', 'satisfaction', 'growth'].forEach(param => { | |
| const slider = document.getElementById(`${param}Slider`); | |
| const valueDisplay = document.getElementById(`${param}Value`); | |
| slider.addEventListener('input', () => { | |
| valueDisplay.textContent = slider.value; | |
| this.updateTurnoverRate(); | |
| }); | |
| }); | |
| this.updateTurnoverRate(); | |
| break; | |
| case 'inventory_simulator': | |
| ['stock', 'demand', 'lead'].forEach(param => { | |
| const slider = document.getElementById(`${param}Slider`); | |
| const valueDisplay = document.getElementById(`${param === 'stock' ? 'currentStock' : param === 'demand' ? 'dailyDemand' : 'leadTime'}Value`); | |
| slider.addEventListener('input', () => { | |
| valueDisplay.textContent = slider.value; | |
| this.updateInventoryDays(); | |
| }); | |
| }); | |
| this.updateInventoryDays(); | |
| break; | |
| case 'hospital_predictor': | |
| const daySlider = document.getElementById('daySlider'); | |
| const hourSlider = document.getElementById('hourSlider'); | |
| const seasonSlider = document.getElementById('seasonSlider'); | |
| daySlider.addEventListener('input', () => { | |
| const days = ['Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'ятниця', 'Субота', 'Неділя']; | |
| document.getElementById('dayValue').textContent = days[daySlider.value - 1]; | |
| this.updatePatientCount(); | |
| }); | |
| hourSlider.addEventListener('input', () => { | |
| document.getElementById('hourValue').textContent = hourSlider.value; | |
| this.updatePatientCount(); | |
| }); | |
| seasonSlider.addEventListener('input', () => { | |
| const seasons = ['Зима', 'Весна', 'Літо', 'Осінь']; | |
| document.getElementById('seasonValue').textContent = seasons[seasonSlider.value - 1]; | |
| this.updatePatientCount(); | |
| }); | |
| this.updatePatientCount(); | |
| break; | |
| } | |
| } | |
| calculateROI() { | |
| const cost = parseFloat(document.getElementById('campaignCost').value) || 0; | |
| const revenue = parseFloat(document.getElementById('campaignRevenue').value) || 0; | |
| const roi = cost > 0 ? ((revenue - cost) / cost * 100) : 0; | |
| document.getElementById('roiResult').style.display = 'block'; | |
| document.getElementById('roiValue').textContent = `${roi.toFixed(1)}%`; | |
| } | |
| calculateFinancials() { | |
| const profit = parseFloat(document.getElementById('netProfit').value) || 0; | |
| const assets = parseFloat(document.getElementById('totalAssets').value) || 0; | |
| const equity = parseFloat(document.getElementById('equity').value) || 0; | |
| const revenue = parseFloat(document.getElementById('revenue').value) || 0; | |
| const roa = assets > 0 ? (profit / assets * 100).toFixed(1) + '%' : '0%'; | |
| const roe = equity > 0 ? (profit / equity * 100).toFixed(1) + '%' : '0%'; | |
| const margin = revenue > 0 ? (profit / revenue * 100).toFixed(1) + '%' : '0%'; | |
| document.getElementById('financialResults').style.display = 'block'; | |
| document.getElementById('roaValue').textContent = roa; | |
| document.getElementById('roeValue').textContent = roe; | |
| document.getElementById('marginValue').textContent = margin; | |
| } | |
| updateTurnoverRate() { | |
| const salary = parseInt(document.getElementById('salarySlider').value); | |
| const satisfaction = parseInt(document.getElementById('satisfactionSlider').value); | |
| const growth = parseInt(document.getElementById('growthSlider').value); | |
| // Simple turnover calculation formula | |
| const baseTurnover = 30; | |
| const salaryFactor = (100000 - salary) / 100000 * 20; | |
| const satisfactionFactor = (10 - satisfaction) * 3; | |
| const growthFactor = (10 - growth) * 2; | |
| const turnover = Math.max(0, baseTurnover + salaryFactor + satisfactionFactor + growthFactor); | |
| document.getElementById('turnoverRate').textContent = `${turnover.toFixed(1)}%`; | |
| } | |
| updateInventoryDays() { | |
| const stock = parseInt(document.getElementById('stockSlider').value); | |
| const demand = parseInt(document.getElementById('demandSlider').value); | |
| const days = demand > 0 ? Math.floor(stock / demand) : 0; | |
| document.getElementById('stockDays').textContent = days; | |
| } | |
| updatePatientCount() { | |
| const day = parseInt(document.getElementById('daySlider').value); | |
| const hour = parseInt(document.getElementById('hourSlider').value); | |
| const season = parseInt(document.getElementById('seasonSlider').value); | |
| // Simple patient count prediction | |
| let baseCount = 20; | |
| // Day factor (weekends are busier) | |
| if (day === 6 || day === 7) baseCount += 10; | |
| // Hour factor (peak hours) | |
| if (hour >= 9 && hour <= 17) baseCount += 15; | |
| if (hour >= 18 && hour <= 22) baseCount += 8; | |
| // Season factor (winter is busier) | |
| if (season === 1) baseCount += 12; // Winter | |
| if (season === 4) baseCount += 5; // Fall | |
| document.getElementById('patientCount').textContent = baseCount; | |
| } | |
| refreshServiceMetrics() { | |
| const metrics = { | |
| csat: (3.8 + Math.random() * 1.2).toFixed(1) + '/5', | |
| nps: Math.floor(50 + Math.random() * 40), | |
| fcr: Math.floor(75 + Math.random() * 20) + '%', | |
| aht: (2.5 + Math.random() * 2).toFixed(1) + ' хв' | |
| }; | |
| document.getElementById('csatMetric').textContent = metrics.csat; | |
| document.getElementById('npsMetric').textContent = metrics.nps; | |
| document.getElementById('fcrMetric').textContent = metrics.fcr; | |
| document.getElementById('ahtMetric').textContent = metrics.aht; | |
| } | |
| refreshEquipmentData() { | |
| const metrics = { | |
| temp: Math.floor(65 + Math.random() * 20) + '°C', | |
| vibr: Math.random() > 0.2 ? 'Норма' : 'Увага', | |
| eff: Math.floor(85 + Math.random() * 15) + '%', | |
| uptime: (98 + Math.random() * 2).toFixed(1) + '%' | |
| }; | |
| document.getElementById('tempMetric').textContent = metrics.temp; | |
| document.getElementById('vibrMetric').textContent = metrics.vibr; | |
| document.getElementById('effMetric').textContent = metrics.eff; | |
| document.getElementById('uptimeMetric').textContent = metrics.uptime; | |
| } | |
| refreshSystemData() { | |
| const metrics = { | |
| cpu: Math.floor(20 + Math.random() * 60) + '%', | |
| ram: Math.floor(40 + Math.random() * 40) + '%', | |
| disk: Math.floor(15 + Math.random() * 30) + '%', | |
| net: Math.floor(5 + Math.random() * 20) + ' Mbps' | |
| }; | |
| document.getElementById('cpuMetric').textContent = metrics.cpu; | |
| document.getElementById('ramMetric').textContent = metrics.ram; | |
| document.getElementById('diskMetric').textContent = metrics.disk; | |
| document.getElementById('netMetric').textContent = metrics.net; | |
| } | |
| startLiteracyTest() { | |
| this.testCurrentQuestion = 0; | |
| this.testAnswers = []; | |
| this.showTestQuestion(); | |
| document.getElementById('testModal').classList.add('active'); | |
| } | |
| showTestQuestion() { | |
| const question = this.data.testQuestions[this.testCurrentQuestion]; | |
| const modalBody = document.getElementById('testModalBody'); | |
| modalBody.innerHTML = ` | |
| <div class="test-question"> | |
| <h4>Питання ${this.testCurrentQuestion + 1} з ${this.data.testQuestions.length}</h4> | |
| <p>${question.question}</p> | |
| <div class="test-options"> | |
| ${question.options.map((option, index) => ` | |
| <div class="test-option" onclick="app.selectTestOption(${index}, ${option.value})"> | |
| ${option.text} | |
| </div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| <div class="test-navigation"> | |
| <div class="test-progress"> | |
| Питання ${this.testCurrentQuestion + 1} з ${this.data.testQuestions.length} | |
| </div> | |
| <div> | |
| ${this.testCurrentQuestion > 0 ? '<button class="btn btn--secondary" onclick="app.previousQuestion()">Назад</button>' : ''} | |
| <button class="btn btn--primary" id="nextBtn" onclick="app.nextQuestion()" disabled>Далі</button> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| selectTestOption(optionIndex, value) { | |
| // Remove previous selection | |
| document.querySelectorAll('.test-option').forEach(option => { | |
| option.classList.remove('selected'); | |
| }); | |
| // Select current option | |
| document.querySelectorAll('.test-option')[optionIndex].classList.add('selected'); | |
| // Store answer | |
| this.testAnswers[this.testCurrentQuestion] = value; | |
| // Enable next button | |
| document.getElementById('nextBtn').disabled = false; | |
| } | |
| nextQuestion() { | |
| if (this.testCurrentQuestion < this.data.testQuestions.length - 1) { | |
| this.testCurrentQuestion++; | |
| this.showTestQuestion(); | |
| } else { | |
| this.showTestResults(); | |
| } | |
| } | |
| previousQuestion() { | |
| if (this.testCurrentQuestion > 0) { | |
| this.testCurrentQuestion--; | |
| this.showTestQuestion(); | |
| } | |
| } | |
| showTestResults() { | |
| const totalScore = this.testAnswers.reduce((sum, score) => sum + score, 0); | |
| const averageScore = totalScore / this.data.testQuestions.length; | |
| let level, recommendations; | |
| if (averageScore >= 3.5) { | |
| level = 4; | |
| recommendations = "Ви маєте експертний рівень! Розвивайте лідерські навички в data-driven проектах."; | |
| } else if (averageScore >= 2.5) { | |
| level = 3; | |
| recommendations = "Ваш рівень - впевнений користувач. Вивчайте статистичні методи та машинне навчання."; | |
| } else if (averageScore >= 1.5) { | |
| level = 2; | |
| recommendations = "Базовий рівень. Рекомендуємо вивчити Excel та основи візуалізації даних."; | |
| } else { | |
| level = 1; | |
| recommendations = "Початковий рівень. Почніть з основ: читання графіків та базових метрик."; | |
| } | |
| const modalBody = document.getElementById('testModalBody'); | |
| modalBody.innerHTML = ` | |
| <div style="text-align: center;"> | |
| <h3>🎯 Ваш рівень Data Literacy</h3> | |
| <div class="result-card"> | |
| <div class="result-value">Рівень ${level}</div> | |
| <div>${this.data.literacyLevels[level - 1].name}</div> | |
| </div> | |
| <p><strong>Оцінка:</strong> ${averageScore.toFixed(1)} з 4.0</p> | |
| <p><strong>Рекомендації:</strong> ${recommendations}</p> | |
| <button class="btn btn--primary" onclick="app.closeTestModal()">Закрити</button> | |
| </div> | |
| `; | |
| } | |
| closeModal() { | |
| document.getElementById('interactiveModal').classList.remove('active'); | |
| } | |
| closeTestModal() { | |
| document.getElementById('testModal').classList.remove('active'); | |
| } | |
| } | |
| // Initialize the application when the page loads | |
| let app; | |
| document.addEventListener('DOMContentLoaded', () => { | |
| app = new DataLiteracyApp(); | |
| }); |