## Daily
```dataviewjs
// User-defined variables
const currentPage = dv.current();
const numDaysBack = 30;
const fields = ["Physical", "Mental"];
const calculationType = "default";
const today = new Date();
const dailyData = {};
// Enhanced debug function
const debug = (message, data) => {
console.log(`DEBUG: ${message}`, JSON.stringify(data, null, 2));
};
// Helper function to validate and parse values
const parseValue = (value) => {
if (value === undefined || value === null || value === '') return 0;
if (typeof value === 'number') return value;
if (typeof value === 'string') {
const parsed = parseFloat(value.replace(/[^\d.-]/g, ''));
return isNaN(parsed) ? 0 : parsed;
}
return 0;
};
// Initialize data structure
for (let i = 0; i < numDaysBack; i++) {
const date = new Date(today);
date.setDate(date.getDate() - i);
const dateStr = date.toISOString().split('T')[0];
dailyData[dateStr] = {};
fields.forEach(field => {
dailyData[dateStr][field] = 0;
});
}
// Get pages and validate data
const pages = dv.pages("#reviews/daily")
.sort(p => p.file.name, "desc")
.where(p => {
try {
const pageDate = new Date(p.file.name);
if (isNaN(pageDate.getTime())) {
debug("Invalid date in filename", p.file.name);
return false;
}
const daysAgo = Math.floor((today - pageDate) / (1000 * 60 * 60 * 24));
return daysAgo <= numDaysBack;
} catch (e) {
debug("Error processing page date", {
filename: p.file.name,
error: e.message
});
return false;
}
});
debug("Total pages found", pages.length);
// Process each page
pages.forEach(page => {
try {
const pageDate = new Date(page.file.name);
const dateStr = pageDate.toISOString().split('T')[0];
debug("Processing page", {
date: dateStr,
availableFields: Object.keys(page)
});
fields.forEach(field => {
try {
const rawValue = page[field];
debug(`Raw ${field} value`, rawValue);
const parsedValue = parseValue(rawValue);
debug(`Parsed ${field} value`, parsedValue);
dailyData[dateStr][field] = parsedValue;
} catch (e) {
debug(`Error processing field ${field}`, {
error: e.message,
page: page.file.name
});
dailyData[dateStr][field] = 0;
}
});
} catch (e) {
debug("Error processing page", {
page: page.file.name,
error: e.message
});
}
});
debug("Final daily data", dailyData);
// Prepare chart data
const dates = Object.keys(dailyData).sort();
const series = fields.map(field => {
let runningSum = 0;
const data = dates.map(date => {
if (calculationType === "sum") {
runningSum += dailyData[date][field];
return runningSum;
}
return dailyData[date][field];
});
return {
title: field,
data: data
};
});
// Generate colors
const colors = fields.map((_, index) => {
const hue = (index * 360 / fields.length);
return `hsl(${hue}, 70%, 50%)`;
});
// Create chart
const chartConfig = `\`\`\`chart
type: bar
labels: [${dates.map(d => `"${d}"`)}]
series: [
${series.map((s, i) => ` {
title: "${s.title}",
data: [${s.data}],
backgroundColor: "${colors[i]}",
borderColor: "${colors[i]}"
}`).join(',\n')}
]
width: 100%
stacked: false
fill: true
beginAtZero: true
legend: true
legendPosition: top
xAxisLabel: Date
yAxisLabel: ${calculationType === "sum" ? "Cumulative Value" : "Daily Value"}
\`\`\``;
dv.paragraph(chartConfig);
// Display statistics
fields.forEach((field, index) => {
const values = dates.map(date => dailyData[date][field]);
const sum = values.reduce((a, b) => a + b, 0);
const avg = (sum / values.length).toFixed(1);
dv.paragraph(`<span style="color: ${colors[index]}">${field} - Total: ${sum.toFixed(1)} | Average: ${avg}</span>`);
});
```
## Sum
```dataviewjs
// User-defined variables
const currentPage = dv.current();
const numDaysBack = 30;
const fields = ["Physical", "Mental"];
const calculationType = "sum";
const today = new Date();
const dailyData = {};
// Enhanced debug function
const debug = (message, data) => {
console.log(`DEBUG: ${message}`, JSON.stringify(data, null, 2));
};
// Helper function to validate and parse values
const parseValue = (value) => {
if (value === undefined || value === null || value === '') return 0;
if (typeof value === 'number') return value;
if (typeof value === 'string') {
const parsed = parseFloat(value.replace(/[^\d.-]/g, ''));
return isNaN(parsed) ? 0 : parsed;
}
return 0;
};
// Initialize data structure
for (let i = 0; i < numDaysBack; i++) {
const date = new Date(today);
date.setDate(date.getDate() - i);
const dateStr = date.toISOString().split('T')[0];
dailyData[dateStr] = {};
fields.forEach(field => {
dailyData[dateStr][field] = 0;
});
}
// Get pages and validate data
const pages = dv.pages("#reviews/daily")
.sort(p => p.file.name, "desc")
.where(p => {
try {
const pageDate = new Date(p.file.name);
if (isNaN(pageDate.getTime())) {
debug("Invalid date in filename", p.file.name);
return false;
}
const daysAgo = Math.floor((today - pageDate) / (1000 * 60 * 60 * 24));
return daysAgo <= numDaysBack;
} catch (e) {
debug("Error processing page date", {
filename: p.file.name,
error: e.message
});
return false;
}
});
debug("Total pages found", pages.length);
// Process each page
pages.forEach(page => {
try {
const pageDate = new Date(page.file.name);
const dateStr = pageDate.toISOString().split('T')[0];
debug("Processing page", {
date: dateStr,
availableFields: Object.keys(page)
});
fields.forEach(field => {
try {
const rawValue = page[field];
debug(`Raw ${field} value`, rawValue);
const parsedValue = parseValue(rawValue);
debug(`Parsed ${field} value`, parsedValue);
dailyData[dateStr][field] = parsedValue;
} catch (e) {
debug(`Error processing field ${field}`, {
error: e.message,
page: page.file.name
});
dailyData[dateStr][field] = 0;
}
});
} catch (e) {
debug("Error processing page", {
page: page.file.name,
error: e.message
});
}
});
debug("Final daily data", dailyData);
// Prepare chart data
const dates = Object.keys(dailyData).sort();
const series = fields.map(field => {
let runningSum = 0;
const data = dates.map(date => {
if (calculationType === "sum") {
runningSum += dailyData[date][field];
return runningSum;
}
return dailyData[date][field];
});
return {
title: field,
data: data
};
});
// Generate colors
const colors = fields.map((_, index) => {
const hue = (index * 360 / fields.length);
return `hsl(${hue}, 70%, 50%)`;
});
// Create chart
const chartConfig = `\`\`\`chart
type: bar
labels: [${dates.map(d => `"${d}"`)}]
series: [
${series.map((s, i) => ` {
title: "${s.title}",
data: [${s.data}],
backgroundColor: "${colors[i]}",
borderColor: "${colors[i]}"
}`).join(',\n')}
]
width: 100%
stacked: false
fill: true
beginAtZero: true
legend: true
legendPosition: top
xAxisLabel: Date
yAxisLabel: ${calculationType === "sum" ? "Cumulative Value" : "Daily Value"}
\`\`\``;
dv.paragraph(chartConfig);
// Display statistics
fields.forEach((field, index) => {
const values = dates.map(date => dailyData[date][field]);
const sum = values.reduce((a, b) => a + b, 0);
const avg = (sum / values.length).toFixed(1);
dv.paragraph(`<span style="color: ${colors[index]}">${field} - Total: ${sum.toFixed(1)} | Average: ${avg}</span>`);
});
```