Creating habit tracker for summation of values from YAML in Daily notes

What I’m trying to do


The main functionality is to track habits from daily notes and see some summaries in weekly notes. The habits I want to track include deep_work, mood and gym etc… These will be represented by integer values indicating the time spent daily or mood from 0 to 10.
I want to have a table where there is the sum of all of these habits across the current week.
And also have a tracker of each of them plotted each day that automatically shows me each month in daily notes. Finally, I want to gamify it so like setting goals daily and weekly with some progress bar and have like special points for each habit that give me xp or smth to keep myself on track. Probably also add heatmap.

Things I have tried

I tried dataview but cant fin syntax to do it in doc, so now I am looking for youtube sources.I think it could be done in js but I need to learn it and I am a bit confused how to use it. I Started to program smth like this in python with pyQT but it seems like will take some time and i would love to have everything in one system like obsidian. I used tracker before but i create these daily templates like year ago, so I am refreshing memory how it will work here.

You may want to check Tracker plugin. I personally use it to track my habits.

Yeah i use it her but can we use it to just operate on numbers like i know i can plot them but I would like to have operatation like summing last 7 days every habit value and so on

You should check its documentation. It has the ability to sum your values. This is the format that I use for example in my running tracker. Just change the values as you see fit

```tracker
searchType: frontmatter
searchTarget: distance
folder: targetFolder
startDate: YYYY-MM-DD
endDate: YYYY-MM-DD
summary:
   template: "Total: {{sum()}} km\nAverage: {{average()}} km"
1 Like

Ohh I will try to implement it today or tomorrow thanks

1 Like

Btw do you have any ideas why this does not work? I used it before and after some updates to Obsidian, but I can’t make it work again. I got No valid Y value found in the notes.


Maybe it has something to do with the capitalization of the metadata “Mood”? And your search target is mood? I am not sure though.

It started working today with same code lol xd

1 Like

can you tell me how can i do like your template task i like it

This is what i have so far I use templates, calendar, dataview, periodic notes, trackerI think. Still working on it


const goals = {
    DeepWork: 240, // minutes
    Mood: 6,       // scale from 1-10
    Gym: 60,       // minutes
    Language: 30,  // minutes
    Cardio: 30,    // minutes
    Courses: 10,   // number of courses
    Meditation: 1, // boolean, 0 or 1
    Sleep: 1       // boolean, 0 or 1
};

// Retrieve current values from frontmatter
const currentValues = {
    DeepWork: dv.current().file.frontmatter["DeepWork"] || 0,
    Mood: dv.current().file.frontmatter["Mood"] || 0,
    Gym: dv.current().file.frontmatter["Gym"] || 0,
    Language: dv.current().file.frontmatter["Language"] || 0,
    Cardio: dv.current().file.frontmatter["Cardio"] || 0,
    Courses: dv.current().file.frontmatter["Courses"] || 0,
    Meditation: dv.current().file.frontmatter["Meditation"] ? 1 : 0,
    Sleep: dv.current().file.frontmatter["Sleep"] ? 1 : 0
};

// Function to create progress bar and percentage
function progress(current, goal) {
    let value;
    // Check if the goal is a boolean, if so, the progress is either 0 or 100%
    if (typeof goal === 'boolean') {
        value = current ? 100 : 0;
    } else {
        // Calculate the progress percentage
        value = (current / goal) * 100;
    }
    // Cap the value at 100% and round it
    value = Math.min(value, 100);
    let roundedValue = Math.round(value);
    return `<progress value="${roundedValue}" max="100"></progress> ${roundedValue}%`;
}

// Generate the table content
let tableContent = "| Activity | Progress |\n|---|---|\n";
Object.entries(goals).forEach(([activity, goal]) => {
    const current = currentValues[activity];
    tableContent += `| **${activity}** | ${progress(current, goal)} |\n`;
});

dv.span(tableContent);
const today = DateTime.now();
const lifespan = { years: 80 }; 
const birthday = DateTime.fromObject({
    year: 1997,
    month: 6,
    day: 14
});
const deathday = birthday.plus(lifespan);

// Calculate weeks left until deathday
const weeksLeft = deathday.diff(today, 'weeks').weeks;

function progress(type) {
    let value;
    
    switch(type) {
        case "lifespan": 
            value = (today.year - birthday.year) / lifespan.years * 100;
            break;
        case "year":
            value = today.month / 12 * 100;
            break;
        case "month":
            value = today.day / today.daysInMonth * 100;
            break;
        case "day":
            value = today.hour / 24 * 100;
            break;
    }
    return `<progress value="${parseInt(value)}" max="100"></progress> | ${parseInt(value)} %`;
}

dv.span(`
|  | Progress  | Percentage |
| --- | --- |:---:| 
| **Year** | ${progress("year")} | 
| **Month**| ${progress("month")} | 
| **Day**| ${progress("day")} | 
| **Life** | ${progress("lifespan")} | 
| **Weeks Left**| ${Math.floor(weeksLeft)} | weeks left |
`);

Streaks

searchType: frontmatter
searchTarget: Mood
folder: Journal/Daily
startDate: <% moment(tp.file.title, "YYYY-MM-DD").startOf("week").format("YYYY-MM-DD") %>
endDate: <% moment(tp.file.title, "YYYY-MM-DD").endOf("week").format("YYYY-MM-DD") %>
line: 
	title: "Mood"
	yAxisLabel: Mood
	lineColor: "#d65d0e"
	yAxisTickInterval: 1
    yMin: 0

[[Journal/Daily/<% tp.date.now(“YYYY-MM-DD”, -1, tp.file.title, “YYYY-MM-DD dddd”) %>| :arrow_left: Yesterday ]] ----- [[Journal/Daily/<% tp.date.now(“YYYY-MM-DD”, 1, tp.file.title, “YYYY-MM-DD dddd”) %>| Tomorrow :arrow_right:]]