169 lines
5.4 KiB
JavaScript
Executable File
169 lines
5.4 KiB
JavaScript
Executable File
document.addEventListener("DOMContentLoaded", () => {
|
|
const labels = ['Energy','Calm','Relax','Sleep','Focus','Inspire'];
|
|
let userData = [...window.appData.initialUserData];
|
|
const profiles = window.appData.profiles;
|
|
|
|
const youLineColor = 'rgba(255,255,255,0.69)';
|
|
const pointBgColor = 'rgba(0,0,0,0.1)';
|
|
const youFillColor = 'rgba(255,255,255,0.1)';
|
|
const matchLineColor = 'rgb(191,181,49)';
|
|
const matchFillColor = 'rgba(191,181,49,0.420)';
|
|
const radialLineColor= 'rgba(255,255,255,0.420)';
|
|
|
|
function distance(a,b){ return Math.sqrt(a.reduce((s,v,i)=>s+(v-b[i])**2,0)); }
|
|
|
|
function getTopMatches() {
|
|
return Object.entries(profiles)
|
|
.sort((a,b)=>distance(userData,a[1].values)-distance(userData,b[1].values))
|
|
.slice(0,3);
|
|
}
|
|
|
|
function getFontSize(){ return window.innerWidth < 600 ? 10 : 39; }
|
|
function getBottomChartFontSize(){ return window.innerWidth < 600 ? 8 : 24; }
|
|
function getPointRadius(){ return window.innerWidth < 600 ? 11 : 24; }
|
|
function getPointHoverRadius(){ return window.innerWidth < 600 ? 12 : 39; }
|
|
function getPointBorderColor(){ return '#BFB531'; }
|
|
|
|
// === Initialize charts ===
|
|
const charts = [1,2,3].map(i => {
|
|
const ctx = document.getElementById(`chart-${i}`).getContext('2d');
|
|
const isBest = i === 1;
|
|
|
|
const datasets = isBest ? [
|
|
{
|
|
label:'You',
|
|
data:[...userData],
|
|
fill:true,
|
|
borderColor: youLineColor,
|
|
backgroundColor: youFillColor,
|
|
pointBackgroundColor: pointBgColor,
|
|
pointBorderColor: getPointBorderColor(),
|
|
pointRadius: getPointRadius(),
|
|
pointHoverRadius: getPointHoverRadius()
|
|
},
|
|
{
|
|
label:'Match',
|
|
data:[],
|
|
fill:true,
|
|
borderColor: matchLineColor,
|
|
backgroundColor: matchFillColor,
|
|
pointBackgroundColor: matchLineColor,
|
|
pointRadius:0
|
|
}
|
|
] : [
|
|
{
|
|
label:'Match',
|
|
data:[],
|
|
fill:true,
|
|
borderColor: matchLineColor,
|
|
backgroundColor: matchFillColor,
|
|
pointBackgroundColor: matchLineColor,
|
|
pointRadius:0
|
|
}
|
|
];
|
|
|
|
return new Chart(ctx,{
|
|
type:'radar',
|
|
data:{ labels, datasets },
|
|
options:{
|
|
responsive:true,
|
|
maintainAspectRatio:false,
|
|
scales:{
|
|
r:{
|
|
min:0, max:80,
|
|
ticks:{ display:false, stepSize:20 },
|
|
pointLabels:{ font:{ size:isBest?getFontSize():getBottomChartFontSize(), weight:'bold' }, color:'#FFF' },
|
|
angleLines:{ color:radialLineColor },
|
|
grid:{ drawticks:false, drawOnChartArea:false, circular:false }
|
|
}
|
|
},
|
|
plugins:{
|
|
tooltip:{ enabled:false },
|
|
legend:{ display:false }
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// === Update charts & DOM ===
|
|
function updateCharts(){
|
|
const matches = getTopMatches();
|
|
|
|
matches.forEach(([name, prof], idx)=>{
|
|
const chart = charts[idx];
|
|
if(idx===0){
|
|
chart.data.datasets[0].data = [...userData];
|
|
chart.data.datasets[1].data = prof.values;
|
|
chart.data.datasets[1].label = name;
|
|
} else {
|
|
chart.data.datasets[0].data = prof.values;
|
|
chart.data.datasets[0].label = name;
|
|
}
|
|
chart.options.scales.r.pointLabels.font.size = idx===0 ? getFontSize() : getBottomChartFontSize();
|
|
chart.update('none');
|
|
|
|
// Update main card
|
|
document.getElementById(`name-${idx+1}`).textContent = name;
|
|
for (let i = 0; i <= 4; i++) {
|
|
const el = document.getElementById(`info${i}-${idx+1}`);
|
|
if (el) el.textContent = prof[`info_text${i}`] || '';
|
|
}
|
|
|
|
// Update popup
|
|
const popupName = document.getElementById(`popup-name-${idx+1}`);
|
|
if (popupName) popupName.textContent = name;
|
|
|
|
for (let i = 0; i <= 4; i++) {
|
|
const popupEl = document.getElementById(`popup-info${i}-${idx+1}`);
|
|
if (popupEl) popupEl.textContent = prof[`info_text${i}`] || '';
|
|
}
|
|
});
|
|
}
|
|
|
|
updateCharts();
|
|
|
|
// === Reset button ===
|
|
document.getElementById('resetBtn').addEventListener('click', ()=>{
|
|
userData = [...window.appData.initialUserData];
|
|
updateCharts();
|
|
});
|
|
|
|
// === Dragging top chart ===
|
|
const topChart = charts[0];
|
|
const topCanvas = document.getElementById('chart-1');
|
|
topCanvas.style.touchAction = 'none';
|
|
let draggingIndex = null;
|
|
|
|
topCanvas.addEventListener('pointerdown', e => {
|
|
const points = topChart.getElementsAtEventForMode(e, 'nearest', {intersect:true}, true);
|
|
if(points.length && points[0].datasetIndex===0) draggingIndex = points[0].index;
|
|
});
|
|
|
|
topCanvas.addEventListener('pointermove', e => {
|
|
if(draggingIndex===null) return;
|
|
const rect = topCanvas.getBoundingClientRect();
|
|
const x = e.clientX - rect.left;
|
|
const y = e.clientY - rect.top;
|
|
const cx = rect.width/2;
|
|
const cy = rect.height/2;
|
|
const dx = x-cx;
|
|
const dy = cy-y;
|
|
const dist = Math.sqrt(dx*dx + dy*dy);
|
|
const rMax = Math.min(rect.width, rect.height)/2 * 0.9;
|
|
let value = (dist/rMax)*80;
|
|
value = Math.min(Math.max(Math.round(value),0),80);
|
|
userData[draggingIndex] = value;
|
|
updateCharts();
|
|
});
|
|
|
|
topCanvas.addEventListener('pointerup', ()=> draggingIndex=null);
|
|
topCanvas.addEventListener('pointerleave', ()=> draggingIndex=null);
|
|
|
|
// bottom charts scroll normally
|
|
[2,3].forEach(i => {
|
|
document.getElementById(`chart-${i}`).style.touchAction='auto';
|
|
});
|
|
|
|
window.addEventListener('resize', updateCharts);
|
|
});
|