Obsidian:続・デイリーノートに◯◯メーターを入れる(2)

ツール活用

Image by Stable Diffusion

日々の積み重ね云々は、一ヶ月なり一年なり十年の積み重ねで変化の差を認識できるものだろう。他人ならともかく、特に自分自身の変化は、秒単位で変わり続ける自己を認識できるのか?という話だし。

変わり続ける自分と、変えようという意識を記録することは、自分自身で第三者的に、俯瞰的に眺めるために大切なことかもしれない。
これまでの人生、日記は三日坊主で、そういったことに意味や意義を感じなかった自分が変わってきたなぁと、Obsidianデイリーノートを見返しながら思う。

といっても、文章で綴った変化はパッと見で分かりにくいわけで。
印やカラーを駆使し、そしてグラフや表になれば物事は把握しやすい。

前回、デイリーノートにメーターとチェック欄を設けたが、これを一定期間ごとに見返しやすい仕組みを用意した。

帯に短し襷に長し

私はデイリーノートのほかに、週間・月間・四半期・年間ノートのテンプレートを作ったので、それぞれにメーターとチェック欄も埋め込んで振り返ろうと考えた。

週間7日分、月間30日分は分かるとして、四半期を90日分振り返りは面倒だし冗長すぎる。さすがにそのレベルは月単位にまとめてもいいだろう。

月間30日にしても大きな変化として週間レベルでざっと振り返れたらどうか?
週間7日分の平均を4週分なり表示するのだ。

表示にはDataviewプラグインを利用するが、ノートを表示するたびに処理する項目が多すぎるのもいかがだろうか。
週間平均をマンスリーやクォータリーノートで再利用するのなら、ノート生成時に平均値も記録してしまおう。
もし将来的にDataviewプラグインが使えなくなったり、あるいはObsidianそのものがダメになっても、ノートに平均値が残されていれば再利用も容易いし。

実例

というわけで、見た目ですぐ分かる実例を御覧ください。
現状、プライベートもある意味ルーチン化された日々を送っていますが、それでも変化やゆらぎがあるんだなぁとしみじみ感じています。

デイリーチェック欄は、集計対象期間の半分以上こなしていればチェック、そうでなければチェックがつきません。
判定厳しめですが、理想は毎日チェックされていること(飲酒以外)なので、もっと読書や運動がんばろうね、という話になります。

モチベーションメーターはその日の意気込みではなく結果を記録するようになったので、空白(受動的にダラダラ動画視聴や漫画、ゲーム、SNS閲覧など)も目立ちますね。
まぁ、アクティブに活動できているかの目安にもなるし、空白も含めた平均でしばらくは様子見。

テンプレートサンプル

以下、Templaterプラグインを使っての埋め込み構文例です。

デイリーノート他のファイル置き場所・命名書式が個々人で異なるでしょうから、テンプレートに埋め込まれてる私の仕様も以下に示します。適宜変更してご利用ください。

  • デイリー 例:2_Daily/2024/2024-06/2024-06-30(月).md
  • ウィークリー 例:2_Daily/2024/2024-06/2024-W25_Notes.md
  • マンスリー 例:2_Daily/2024/2024-06_Notes.md
  • クォータリー 例:2_Daily/2024/2024-Q2_Notes.md

各テンプレート最初の変数設定は、チェック欄の各要素平均(5個)、モチベーションメーターの各要素平均(4個)を表しています。

ウィークリーノート

  • Calenderプラグインのウィークリー欄から呼び出しています。
  • そのため tp.hooks を利用して「テンプレートからノート生成後に処理して平均値を割り出し、プロパティに格納」という動きになっています。
  • 正直、マンスリー以降の方法に変更したほうが無難な気がしています。
  • 1週間分のデイリーノートから各要素を読み取って、平均した数値をプロパティに記載しています。
<%*
let w_ebo = 0;
let w_ewa = 0;
let w_eta = 0;
let w_eoy = 0;
let w_esa = 0;
let w_mov = 0;
let w_ais = 0;
let w_obs = 0;
let w_oth = 0;

for (let ii = 0; ii < 7; ii++) {
    let wd = tp.date.now("YYYY-MM-DD(ddd)[.md]", ii, tp.file.title, "gggg-[W]ww[_Notes]");
    // 指定された日付に対応するファイルを探す
    const file = tp.file.find_tfile(wd);
    if (file) {
        const fm = app.metadataCache.getFileCache(file)?.frontmatter;
        if (fm) {
            if (fm.Ex_book)    { w_ebo += 1; }
            if (fm.Ex_walking) { w_ewa += 1; }
            if (fm.Ex_taiso)   { w_eta += 1; }
            if (fm.Ex_oyatsu)  { w_eoy += 1; }
            if (fm.Ex_sake)    { w_esa += 1; }
            w_mov += fm.Mo_mov || 0;
            w_ais += fm.Mo_ais || 0;
            w_obs += fm.Mo_obs || 0;
            w_oth += fm.Mo_oth || 0;
        } else {
            console.log(`File not get: ${file}`);
        }
    } else {
        console.log(`File not found: ${file}`);
    }
}

tp.hooks.on_all_templates_executed(async () => {
  const file = tp.file.find_tfile(tp.file.path(true));
  await app.fileManager.processFrontMatter(file, (frontmatter) => {
    frontmatter.EW_book = Math.round(w_ebo / 7);
    frontmatter.EW_walking = Math.round(w_ewa / 7);
    frontmatter.EW_taiso = Math.round(w_eta / 7);
    frontmatter.EW_oyatsu = Math.round(w_eoy / 7);
    frontmatter.EW_sake = Math.round(w_esa / 7);
    frontmatter.MW_mov = Math.round(w_mov / 7);
    frontmatter.MW_ais = Math.round(w_ais / 7);
    frontmatter.MW_obs = Math.round(w_obs / 7);
    frontmatter.MW_oth = Math.round(w_oth / 7);
  });
});
%>

## Myself Meter
### Motivation
```dataview
TABLE WITHOUT ID  
file.link as Date,  
("🟦" * MW_mov + "🟧" * MW_ais + "🟪" * MW_obs + "🟩" * MW_oth + "⬛" * (10 - MW_mov - MW_obs - MW_ais - MW_oth)) as "🟦動画編集 🟧生成AI 🟪Obsidian 🟩その他"
FROM "<% tp.date.now("[2_Daily]/gggg/gggg-MM/gggg-[W]ww[_Notes]", 0, tp.file.title, "gggg-[W]ww[_Notes]") %>"
```

```dataview
TABLE WITHOUT ID  
file.link as Date,  
("🟦" * Mo_mov + "🟧" * Mo_ais + "🟪" * Mo_obs + "🟩" * Mo_oth + "⬛" * (10 - Mo_mov - Mo_obs - Mo_ais - Mo_oth)) as "🟦動画編集 🟧生成AI 🟪Obsidian 🟩その他"
FROM "2_Daily"
WHERE file.day <= date({{saturday:gggg-MM-DD}}) AND file.day >= date({{sunday:gggg-MM-DD}})
SORT file.day ASC  
```

### Daily Check
```dataview
TABLE WITHOUT ID  
file.link as Date,  
choice(EW_book = 1, "🧡", "🖤") as 📗,
choice(EW_walking = 1, "🧡", "🖤") as 🏃,
choice(EW_taiso = 1, "🧡", "🖤") as 📻,
choice(EW_oyatsu = 1, "🌓", "⚫") as 🍰,
choice(EW_sake = 1, "🍺", "⚫") as 🍺
FROM "<% tp.date.now("[2_Daily]/gggg/gggg-MM/gggg-[W]ww[_Notes]", 0, tp.file.title, "gggg-[W]ww[_Notes]") %>"
```

```dataview
TABLE WITHOUT ID  
file.link as Date,  
choice(Ex_book = True, "🧡", "🖤") as 📗,
choice(Ex_walking = True, "🧡", "🖤") as 🏃,
choice(Ex_taiso = True, "🧡", "🖤") as 📻,
choice(Ex_oyatsu = True, "🌓", "⚫") as 🍰,
choice(Ex_sake = True, "🍺", "⚫") as 🍺
FROM "2_Daily"
WHERE file.day <= date({{saturday:gggg-MM-DD}}) AND file.day >= date({{sunday:gggg-MM-DD}})
SORT file.day ASC  
```

マンスリーノート

  • 「空の」マンスリーノートを手動で作成し、それからTemplaterプラグインのコマンドを呼び出して、マンスリーノートテンプレートを反映しています。
  • テンプレートからの生成時にデイリーノート1ヶ月分を読み込んで各要素の平均を算出、月間平均としてプロパティに記載します。
  • テンプレートのプロパティ欄に直接算出値を記載する形式です。
---
date: <% tp.file.creation_date() %>
AutoNoteMover: disable
uid: <% tp.date.now("YYYYMMDD-HHmmss-SSSS") %>
<%*
let m_ebo = 0;
let m_ewa = 0;
let m_eta = 0;
let m_eoy = 0;
let m_esa = 0;
let m_mov = 0;
let m_ais = 0;
let m_obs = 0;
let m_oth = 0;
const ed = moment(tp.file.title, "gggg-MM[_Notes]").endOf("month").format("D")

for (let ii = 0; ii < ed; ii++) {
    let wd = tp.date.now("YYYY-MM-DD(ddd)[.md]", ii, tp.file.title, "gggg-MM[_Notes]");
    const file = tp.file.find_tfile(wd);
    if (file) {
        const fm = app.metadataCache.getFileCache(file)?.frontmatter;
        if (fm) {
            if (fm.Ex_book)    { m_ebo += 1; }
            if (fm.Ex_walking) { m_ewa += 1; }
            if (fm.Ex_taiso)   { m_eta += 1; }
            if (fm.Ex_oyatsu)  { m_eoy += 1; }
            if (fm.Ex_sake)    { m_esa += 1; }
            m_mov += fm.Mo_mov || 0;
            m_ais += fm.Mo_ais || 0;
            m_obs += fm.Mo_obs || 0;
            m_oth += fm.Mo_oth || 0;
        } else {
            console.log(`File not get: ${file}`);
        }
    } else {
        console.log(`File not found: ${file}`);
    }
}
tR += "EM_book: "    + Math.round(m_ebo / ed) + "\n";
tR += "EM_walking: " + Math.round(m_ewa / ed) + "\n";
tR += "EM_taiso: "   + Math.round(m_eta / ed) + "\n";
tR += "EM_oyatsu: "  + Math.round(m_eoy / ed) + "\n";
tR += "EM_sake: "    + Math.round(m_esa / ed) + "\n";
tR += "MM_mov: " + Math.round(m_mov / ed) + "\n";
tR += "MM_ais: " + Math.round(m_ais / ed) + "\n";
tR += "MM_obs: " + Math.round(m_obs / ed) + "\n";
tR += "MM_oth: " + Math.round(m_oth / ed);
%>
---
ここからノート本文
## Myself Meter
### Motivation
```dataview
TABLE WITHOUT ID  
file.link as Date,  
("🟦" * MM_mov + "🟧" * MM_ais + "🟪" * MM_obs + "🟩" * MM_oth + "⬛" * (10 - MM_mov - MM_obs - MM_ais - MM_oth)) as "🟦動画編集 🟧生成AI 🟪Obsidian 🟩その他"
FROM "<% tp.date.now("[2_Daily]/gggg/gggg-MM[_Notes]", 0, tp.file.title, "gggg-MM[_Notes]") %>"
```

```dataview
TABLE WITHOUT ID  
file.link as Date,  
("🟦" * MW_mov + "🟧" * MW_ais + "🟪" * MW_obs + "🟩" * MW_oth + "⬛" * (10 - MW_mov - MW_obs - MW_ais - MW_oth)) as "🟦動画編集 🟧生成AI 🟪Obsidian 🟩その他"
FROM "<% tp.date.now("[2_Daily]/gggg/gggg-MM", 0, tp.file.title, "gggg-MM[_Notes]") %>"
WHERE contains(file.name, "-W")
```

```dataview
TABLE WITHOUT ID  
file.link as Date,  
("🟦" * Mo_mov + "🟧" * Mo_ais + "🟪" * Mo_obs + "🟩" * Mo_oth + "⬛" * (10 - Mo_mov - Mo_obs - Mo_ais - Mo_oth)) as "🟦動画編集 🟧生成AI 🟪Obsidian 🟩その他"
FROM "2_Daily"
WHERE file.day <= date(<% tp.date.now("YYYY-MM-00", "P+1M", tp.file.title, "YYYY-MM[_Notes]") %>) AND file.day >= date(<% tp.date.now("YYYY-MM-01", 0, tp.file.title, "YYYY-MM[_Notes]") %>)
SORT file.day ASC  
```

### Daily Check
```dataview
TABLE WITHOUT ID  
file.link as Date,  
choice(EM_book = 1, "🧡", "🖤") as 📗,
choice(EM_walking = 1, "🧡", "🖤") as 🏃,
choice(EM_taiso = 1, "🧡", "🖤") as 📻,
choice(EM_oyatsu = 1, "🌓", "⚫") as 🍰,
choice(EM_sake = 1, "🍺", "⚫") as 🍺
FROM "<% tp.date.now("[2_Daily]/gggg/gggg-MM[_Notes]", 0, tp.file.title, "gggg-MM[_Notes]") %>"
```

```dataview
TABLE WITHOUT ID  
file.link as Date,  
choice(EW_book = 1, "🧡", "🖤") as 📗,
choice(EW_walking = 1, "🧡", "🖤") as 🏃,
choice(EW_taiso = 1, "🧡", "🖤") as 📻,
choice(EW_oyatsu = 1, "🌓", "⚫") as 🍰,
choice(EW_sake = 1, "🍺", "⚫") as 🍺
FROM "<% tp.date.now("[2_Daily]/gggg/gggg-MM", 0, tp.file.title, "gggg-MM[_Notes]") %>"
WHERE contains(file.name, "-W")
```

```dataview
TABLE WITHOUT ID  
file.link as Date,  
choice(Ex_book = True, "🧡", "🖤") as 📗,
choice(Ex_walking = True, "🧡", "🖤") as 🏃,
choice(Ex_taiso = True, "🧡", "🖤") as 📻,
choice(Ex_oyatsu = True, "🌓", "⚫") as 🍰,
choice(Ex_sake = True, "🍺", "⚫") as 🍺
FROM "2_Daily"
WHERE file.day <= date(<% tp.date.now("YYYY-MM-00", "P+1M", tp.file.title, "YYYY-MM[_Notes]") %>) AND file.day >= date(<% tp.date.now("YYYY-MM-01", 0, tp.file.title, "YYYY-MM[_Notes]") %>)
SORT file.day ASC  
```

クォータリーノート

  • 四半期平均、年平均は不要かなと思ったので、単純に期間内の月平均結果を並べているだけです。
## Myself Meter
### Motivation
```dataview
TABLE WITHOUT ID  
file.link as Date,  
("🟦" * MM_mov + "🟧" * MM_ais + "🟪" * MM_obs + "🟩" * MM_oth + "⬛" * (10 - MM_mov - MM_obs - MM_ais - MM_oth)) as "🟦動画編集 🟧生成AI 🟪Obsidian 🟩その他"
FROM "2_Daily/<% tp.date.now("YYYY", 0, tp.file.title, "YYYY-[Q]Q[_Notes]") %>"
WHERE contains(file.name, "<% tp.date.now("YYYY-MM_", 0, tp.file.title, "YYYY-[Q]Q[_Notes]") %>") OR contains(file.name, "<% tp.date.now("YYYY-MM_", "P+1M", tp.file.title, "YYYY-[Q]Q[_Notes]") %>") OR contains(file.name, "<% tp.date.now("YYYY-MM_", "P+2M", tp.file.title, "YYYY-[Q]Q[_Notes]") %>")
```

### Daily Check
```dataview
TABLE WITHOUT ID  
file.link as Date,  
choice(EM_book = 1, "🧡", "🖤") as 📗,
choice(EM_walking = 1, "🧡", "🖤") as 🏃,
choice(EM_taiso = 1, "🧡", "🖤") as 📻,
choice(EM_oyatsu = 1, "🌓", "⚫") as 🍰,
choice(EM_sake = 1, "🍺", "⚫") as 🍺
FROM "2_Daily/<% tp.date.now("YYYY", 0, tp.file.title, "YYYY-[Q]Q[_Notes]") %>"
WHERE contains(file.name, "<% tp.date.now("YYYY-MM_", 0, tp.file.title, "YYYY-[Q]Q[_Notes]") %>") OR contains(file.name, "<% tp.date.now("YYYY-MM_", "P+1M", tp.file.title, "YYYY-[Q]Q[_Notes]") %>") OR contains(file.name, "<% tp.date.now("YYYY-MM_", "P+2M", tp.file.title, "YYYY-[Q]Q[_Notes]") %>")
```