diff --git a/app.js b/app.js index f7ccd55..891de36 100644 --- a/app.js +++ b/app.js @@ -17,7 +17,6 @@ document.getElementById('excelFile').addEventListener('change', function(e) { var ws = wb.Sheets[wb.SheetNames[0]]; var rows = XLSX.utils.sheet_to_json(ws, {defval: ''}); if (!rows.length) { document.getElementById('statusMsg').textContent = 'Файл пуст'; return; } - console.log('Данные файла:', rows); build(rows); } catch(err) { document.getElementById('statusMsg').textContent = 'Ошибка: ' + err.message; @@ -56,98 +55,66 @@ function done(s) { function build(raw) { var d = norm(raw); - console.log('Обработанные данные:', d); - console.log('Количество строк:', d.length); - - d.forEach(function(r, i) { - console.log('Строка ' + i + ':\n ФИО:', r.name, '\n Статус:', r.status, '\n Обработанный статус:', r.status ? 'done' : 'not done'); - }); document.getElementById('uploadSection').classList.add('hidden'); document.getElementById('dashboard').classList.remove('hidden'); - var allN = {}, doneN = {}, scores = [], train = {}, divs = {}, trainers = {}; + var allN = {}, scores = [], train = {}, trainers = {}; d.forEach(function(r) { allN[r.name] = true; - if (done(r.status)) doneN[r.name] = true; - var sc = parseFloat(r.score); if (!isNaN(sc) && sc > 0) scores.push(sc); var c = r.course || 'Без темы'; - if (!train[c]) train[c] = {all:{}, ok:{}, sc:[], tr:{}, div:{}}; + if (!train[c]) train[c] = {all:{}, ok:{}, sc:[], tr:{}}; train[c].all[r.name] = true; - if (done(r.status)) train[c].ok[r.name] = true; + if (r.status === 'завершен' || r.status === 'пройден') train[c].ok[r.name] = true; if (!isNaN(sc) && sc > 0) train[c].sc.push(sc); if (r.trainer) train[c].tr[r.trainer] = true; - var dv = r.division || '—'; - if (!train[c].div[dv]) train[c].div[dv] = {all:{}, ok:{}}; - train[c].div[dv].all[r.name] = true; - if (done(r.status)) train[c].div[dv].ok[r.name] = true; - - if (!divs[dv]) divs[dv] = {all:{}, ok:{}}; - divs[dv].all[r.name] = true; - if (done(r.status)) divs[dv].ok[r.name] = true; - var tr = r.trainer || '—'; - if (!trainers[tr]) trainers[tr] = {n:0, sc:[]}; + if (!trainers[tr]) trainers[tr] = {n:0, sc:[], topics:[]}; trainers[tr].n++; if (!isNaN(sc) && sc > 0) trainers[tr].sc.push(sc); + if (c && c !== 'Без темы') trainers[tr].topics.push(c); }); var totalN = Object.keys(allN).length; - var doneNn = Object.keys(doneN).length; document.getElementById('statTotal').textContent = totalN; - document.getElementById('statDone').textContent = doneNn; - document.getElementById('statRate').textContent = totalN ? Math.round(doneNn/totalN*100)+'%' : '0%'; document.getElementById('statAvg').textContent = scores.length ? (scores.reduce(function(a,b){return a+b},0)/scores.length).toFixed(1) : '—'; - var tKeys = Object.keys(train); - var tDone = tKeys.map(function(k){return Object.keys(train[k].ok).length}); - var tAll = tKeys.map(function(k){return Object.keys(train[k].all).length}); - - barH('chartTrainings', tKeys, [ - {label:'Всего', data:tAll, bg:'rgba(33,150,243,0.4)', bc:'#2196F3'}, - {label:'Прошли', data:tDone, bg:'rgba(76,175,80,0.7)', bc:'#4caf50'} - ]); - - var dvNames = Object.keys(divs); - var dvColors = ['#2196F3','#4caf50','#ff9800','#9c27b0','#00bcd4','#ff5722','#8bc34a','#e91e63']; - var divDatasets = dvNames.map(function(dv,i){ - return {label:dv, data:tKeys.map(function(tk){return train[tk].div[dv]?Object.keys(train[tk].div[dv].ok).length:0}), - bg:dvColors[i%dvColors.length]+'cc', bc:dvColors[i%dvColors.length]}; - }); - stacked('chartTrainDiv', tKeys, divDatasets); - - bar('chartDiv', dvNames, [ - {label:'Всего', data:dvNames.map(function(d){return Object.keys(divs[d].all).length}), bg:'rgba(33,150,243,0.6)', bc:'#2196F3'}, - {label:'Прошли', data:dvNames.map(function(d){return Object.keys(divs[d].ok).length}), bg:'rgba(76,175,80,0.6)', bc:'#4caf50'} - ]); - - var trNames = Object.keys(trainers); - bar('chartTrainers', trNames, [ - {label:'Занятий', data:trNames.map(function(t){return trainers[t].n}), bg:'rgba(255,152,0,0.6)', bc:'#ff9800'} - ]); - - var sd = {5:0,4:0,3:0,2:0,1:0}; - scores.forEach(function(s){var r=Math.round(s);if(sd[r]!==undefined)sd[r]++}); - doughnut('chartScores', Object.keys(sd).map(function(k){return 'Оценка '+k}), Object.values(sd), - ['#4caf50','#8bc34a','#ff9800','#ff5722','#f44336']); - - var tAvg = tKeys.map(function(k){var sc=train[k].sc;return sc.length?(sc.reduce(function(a,b){return a+b},0)/sc.length).toFixed(1):0}); - bar('chartTrainScores', tKeys, [{label:'Средняя оценка', data:tAvg, - bg:tAvg.map(function(v){return v>=4?'rgba(76,175,80,0.7)':v>=3?'rgba(255,152,0,0.7)':'rgba(244,67,54,0.7)'}), - bc:tAvg.map(function(v){return v>=4?'#4caf50':v>=3?'#ff9800':'#f44336'})}]); - - document.querySelector('#tblTrainings tbody').innerHTML = tKeys.map(function(k){ + document.querySelector('#tblTrainings tbody').innerHTML = Object.keys(train).map(function(k){ var t=train[k], tot=Object.keys(t.all).length, ok=Object.keys(t.ok).length; var avg=t.sc.length?(t.sc.reduce(function(a,b){return a+b},0)/t.sc.length).toFixed(1):'—'; var trn=Object.keys(t.tr).join(', ')||'—'; return '