';
document.getElementById('wro-suggestions-list').innerHTML = '
Not enough data to generate suggestions.';
document.getElementById('wro-analysis-output-section').style.display = 'block';
return;
}
// By Hour of Day
const energyByHour = Array(24).fill(null).map(() => ({ sum: 0, count: 0, avg: 0 }));
filteredLogs.forEach(log => {
const hour = log.timestamp.getHours();
energyByHour[hour].sum += log.energyLevel;
energyByHour[hour].count++;
});
energyByHour.forEach(h => { if (h.count > 0) h.avg = h.sum / h.count; });
wro_renderBarChart('wro-hourly-focus-chart', energyByHour, (hour) => `${String(hour).padStart(2, '0')}:00`);
// By Day of Week
const energyByDay = Array(7).fill(null).map(() => ({ sum: 0, count: 0, avg: 0 }));
const DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
filteredLogs.forEach(log => {
const day = log.timestamp.getDay(); // 0=Sun, 6=Sat
energyByDay[day].sum += log.energyLevel;
energyByDay[day].count++;
});
energyByDay.forEach(d => { if (d.count > 0) d.avg = d.sum / d.count; });
wro_renderBarChart('wro-daily-focus-chart', energyByDay, (dayIndex) => DAY_NAMES[dayIndex]);
// Suggestions
wro_generateSuggestions(energyByHour, energyByDay);
document.getElementById('wro-analysis-output-section').style.display = 'block';
}
function wro_renderBarChart(elementId, dataArray, labelFormatter) {
const chartDiv = document.getElementById(elementId);
chartDiv.innerHTML = '';
const maxAvg = Math.max(...dataArray.map(d => d.avg), 0) || 1; // Ensure maxAvg is at least 1 to avoid div by zero
dataArray.forEach((item, index) => {
if (item.count > 0) {
const percentage = maxAvg > 0 ? (item.avg / maxAvg * 100) : 0;
let barClass = "energy-medium";
if (item.avg >= 4) barClass = "energy-high";
else if (item.avg < 2.5) barClass = "energy-low";
const barItem = document.createElement('div');
barItem.className = 'bar-item';
barItem.innerHTML = `
${labelFormatter(index)}
${item.avg.toFixed(1)}
`;
chartDiv.appendChild(barItem);
}
});
if (chartDiv.innerHTML === '') chartDiv.innerHTML = "
Not enough data for this chart.
";
}
function wro_generateSuggestions(hourlyData, dailyData) {
const suggestionsUl = document.getElementById('wro-suggestions-list');
suggestionsUl.innerHTML = '';
let suggestions = [];
// Hourly suggestions
let peakStart = -1;
for(let i=0; i < 24; i++) {
if (hourlyData[i].avg >= 4) { // High focus
if (peakStart === -1) peakStart = i;
} else {
if (peakStart !== -1) {
suggestions.push(`You seem to have peak energy/focus between ${peakStart}:00 and ${i}:00. Schedule demanding tasks here.`);
peakStart = -1;
}
}
}
if(peakStart !== -1) suggestions.push(`You seem to have peak energy/focus between ${peakStart}:00 and 24:00.`);
let lowStart = -1;
for(let i=0; i < 24; i++) {
if (hourlyData[i].count > 0 && hourlyData[i].avg <= 2) { // Low focus
if (lowStart === -1) lowStart = i;
} else {
if (lowStart !== -1) {
suggestions.push(`Energy might be lower between ${lowStart}:00 and ${i}:00. Consider breaks or lighter tasks.`);
lowStart = -1;
}
}
}
if(lowStart !== -1) suggestions.push(`Energy might be lower between ${lowStart}:00 and 24:00.`);
// Daily suggestions
const productiveDays = []; const lessProductiveDays = [];
const DAY_NAMES_FULL = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
dailyData.forEach((day, index) => {
if (day.count > 0) {
if (day.avg >= 3.5) productiveDays.push(DAY_NAMES_FULL[index]);
else if (day.avg <= 2.5) lessProductiveDays.push(DAY_NAMES_FULL[index]);
}
});
if(productiveDays.length > 0) suggestions.push(`You tend to have higher energy on: ${productiveDays.join(', ')}.`);
if(lessProductiveDays.length > 0) suggestions.push(`Consider lighter schedules or more breaks on: ${lessProductiveDays.join(', ')}.`);
if (suggestions.length === 0) {
suggestionsUl.innerHTML = '
Log more data (e.g., over several days) to get personalized suggestions.';
} else {
suggestions.forEach(s => suggestionsUl.innerHTML += `
${s}`);
}
}
// PDF and Clear All
function wro_clearAllEnergyLogs() {
if (confirm("Are you sure you want to clear ALL logged energy entries? Profile settings will remain.")) {
wro_energyLogs = []; wro_logIdCounter = 0;
wro_renderTodaysLog();
wro_renderFullLog();
wro_analyzeEnergyLogs(); // Will show empty analysis
}
}
function wro_downloadPDF() {
if (!tpc_jsPDF_loaded_WRO || !tpc_autoTable_loaded_WRO) { alert("WRO Error: PDF libraries not loaded."); return; }
const fromDateStr = document.getElementById('wro-analyze-from-date').value;
const toDateStr = document.getElementById('wro-analyze-to-date').value;
const fromDate = fromDateStr ? new Date(fromDateStr + "T00:00:00") : null;
const toDate = toDateStr ? new Date(toDateStr + "T23:59:59") : null;
const filteredLogs = wro_energyLogs.filter(log => log.timestamp >= fromDate && log.timestamp <= toDate);
if (filteredLogs.length === 0) { alert("No data in the selected period to export."); return; }
const doc = new TPC_jsPDF_WRO();
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim();
const darkColor = getComputedStyle(document.documentElement).getPropertyValue('--dark-color').trim();
let finalY = 15;
const reportDateStr = new Date().toLocaleDateString();
doc.setFontSize(18); doc.setTextColor(primaryColor);
doc.text("Work Rhythm Analysis Report", doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center' });
finalY += 8; doc.setFontSize(10); doc.setTextColor(darkColor);
doc.text(`Report Date: ${reportDateStr} | Analysis Period: ${fromDate.toLocaleDateString()} to ${toDate.toLocaleDateString()}`, doc.internal.pageSize.getWidth() / 2, finalY, { align: 'center'});
finalY += 10;
// Profile Summary
doc.setFontSize(12); doc.setTextColor(primaryColor);
doc.text("My Daily Profile:", 14, finalY); finalY += 6;
doc.setFontSize(9); doc.setTextColor(darkColor);
doc.text(`Wake-up: ${wro_profile.wakeUpTime}, Bedtime: ${wro_profile.bedTime}`, 14, finalY); finalY += 5;
doc.text(`Breakfast: ${wro_profile.meals.breakfast.start}-${wro_profile.meals.breakfast.end} | Lunch: ${wro_profile.meals.lunch.start}-${wro_profile.meals.lunch.end} | Dinner: ${wro_profile.meals.dinner.start}-${wro_profile.meals.dinner.end}`, 14, finalY); finalY+=7;
// Analysis Summary (Tables for Hourly and Daily Avg Focus)
// Hourly
const energyByHour = Array(24).fill(null).map(() => ({ sum: 0, count: 0, avg: 0 }));
filteredLogs.forEach(log => { const hour = log.timestamp.getHours(); energyByHour[hour].sum += log.energyLevel; energyByHour[hour].count++; });
energyByHour.forEach(h => { if (h.count > 0) h.avg = h.sum / h.count; });
const hourlyTableBody = energyByHour.map((data, hour) => data.count > 0 ? [`${String(hour).padStart(2,'0')}:00`, data.avg.toFixed(1), data.count] : null).filter(r => r);
if(hourlyTableBody.length > 0){
doc.setFontSize(11); doc.setTextColor(primaryColor); doc.text("Average Energy by Hour of Day:", 14, finalY); finalY+=5;
doc.autoTable({ startY: finalY, head: [['Hour', 'Avg. Energy (1-5)', 'Log Count']], body: hourlyTableBody, theme: 'striped', headStyles:{fillColor:primaryColor, textColor:'#fff', fontSize:9}, styles:{fontSize:8}});
finalY = doc.lastAutoTable.finalY + 7;
}
// Daily
const energyByDay = Array(7).fill(null).map(() => ({ sum: 0, count: 0, avg: 0 }));
const DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
filteredLogs.forEach(log => { const day = log.timestamp.getDay(); energyByDay[day].sum += log.energyLevel; energyByDay[day].count++; });
energyByDay.forEach(d => { if (d.count > 0) d.avg = d.sum / d.count; });
const dailyTableBody = energyByDay.map((data, day) => data.count > 0 ? [DAY_NAMES[day], data.avg.toFixed(1), data.count] : null).filter(r => r);
if(dailyTableBody.length > 0){
if (finalY > 240) { doc.addPage(); finalY = 15; }
doc.setFontSize(11); doc.setTextColor(primaryColor); doc.text("Average Energy by Day of Week:", 14, finalY); finalY+=5;
doc.autoTable({ startY: finalY, head: [['Day', 'Avg. Energy (1-5)', 'Log Count']], body: dailyTableBody, theme: 'striped', headStyles:{fillColor:primaryColor, textColor:'#fff', fontSize:9}, styles:{fontSize:8}});
finalY = doc.lastAutoTable.finalY + 7;
}
// Suggestions for PDF
const suggestionsList = document.getElementById('wro-suggestions-list').innerText;
if (finalY > 250) { doc.addPage(); finalY = 15; }
doc.setFontSize(11); doc.setTextColor(primaryColor); doc.text("Personalized Suggestions:", 14, finalY); finalY+=5;
doc.setFontSize(9); doc.setTextColor(darkColor);
const suggestionLines = doc.splitTextToSize(suggestionsList, doc.internal.pageSize.width - 28);
doc.text(suggestionLines, 14, finalY);
finalY += suggestionLines.length * 4 + 7;
// Detailed Log for PDF
if (finalY > 220) { doc.addPage(); finalY = 15; }
doc.setFontSize(11); doc.setTextColor(primaryColor); doc.text("Detailed Energy Log (Filtered Period):", 14, finalY); finalY += 6;
const logTableBody = filteredLogs.map(entry => [
entry.timestamp.toLocaleString(), entry.energyLevel, entry.activity || '-'
]);
doc.autoTable({
startY: finalY, head: [['Timestamp', 'Energy (1-5)', 'Activity Logged']],
body: logTableBody, theme: 'grid',
headStyles: { fillColor: primaryColor, textColor: '#ffffff', fontSize: 9 },
styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' }
});
doc.save(`Work_Rhythm_Analysis_${new Date().toISOString().slice(0,10)}.pdf`);
}