100 lines
2.9 KiB
Markdown
100 lines
2.9 KiB
Markdown
# 🗂 NPC Influence Dashboard
|
||
|
||
> Scale: −10 … 0 … +10 (0 = Neutral; positive = more influential, negative = less)
|
||
|
||
---
|
||
|
||
## 😡 Hostile (−10 to −7)
|
||
```dataview
|
||
TABLE link(file.name) AS NPC, Faction, Level_of_Influence
|
||
FROM "NPCs"
|
||
WHERE Level_of_Influence <= -7
|
||
SORT Level_of_Influence ASC
|
||
```
|
||
|
||
## 😕 Unfriendly (-6 to -1)
|
||
```dataview
|
||
TABLE link(file.name) AS NPC, Faction, Level_of_Influence
|
||
FROM "NPCs"
|
||
WHERE Level_of_Influence >= -6 AND Level_of_Influence <= -1
|
||
SORT Level_of_Influence ASC
|
||
```
|
||
|
||
## 😐 Neutral (0)
|
||
```dataview
|
||
TABLE link(file.name) AS NPC, Faction, Level_of_Influence
|
||
FROM "NPCs"
|
||
WHERE Level_of_Influence = 0
|
||
SORT file.name ASC
|
||
```
|
||
|
||
## 🙂 Friendly (+1 to +6)
|
||
```dataview
|
||
TABLE link(file.name) AS NPC, Faction, Level_of_Influence
|
||
FROM "NPCs"
|
||
WHERE Level_of_Influence >= 1 AND Level_of_Influence <= 6
|
||
SORT Level_of_Influence DESC
|
||
```
|
||
|
||
## 🛡 Allied (+7 to +10)
|
||
```dataview
|
||
TABLE link(file.name) AS NPC, Faction, Level_of_Influence
|
||
FROM "NPCs"
|
||
WHERE Level_of_Influence >= 7
|
||
SORT Level_of_Influence DESC
|
||
```
|
||
|
||
## 📊 Visual Bands (Emoji + Bipolar Progress Bars)
|
||
```dataview
|
||
// ===== Settings =====
|
||
const FOLDER = "NPCs";
|
||
const MAX = 10; // absolute max in either direction
|
||
|
||
// ===== Helpers =====
|
||
const tier = s =>
|
||
s === 0 ? "Neutral" :
|
||
s < 0 ? (s <= -7 ? "Hostile" : "Unfriendly") :
|
||
(s >= 7 ? "Allied" : "Friendly");
|
||
|
||
const face = s =>
|
||
s === 0 ? "😐" :
|
||
s < 0 ? (s <= -7 ? "😡" : "😕") :
|
||
(s >= 7 ? "🛡️" : "🙂");
|
||
|
||
// Bipolar bar: [LLLLL|RRRRR]
|
||
function bipolarBar(score) {
|
||
const leftFilled = Math.min(MAX, Math.max(0, -score));
|
||
const rightFilled = Math.min(MAX, Math.max(0, score));
|
||
const leftEmpty = MAX - leftFilled;
|
||
const rightEmpty = MAX - rightFilled;
|
||
const L = "█".repeat(leftFilled) + "░".repeat(leftEmpty);
|
||
const R = "█".repeat(rightFilled) + "░".repeat(rightEmpty);
|
||
return `[${L}|${R}]`;
|
||
}
|
||
|
||
// ===== Fetch =====
|
||
const pages = dv.pages(`"${FOLDER}"`)
|
||
.where(p => Number.isFinite(+p.Level_of_Influence))
|
||
.map(p => ({
|
||
name: p.file.link,
|
||
faction: p.Faction ?? "",
|
||
score: +p.Level_of_Influence
|
||
}));
|
||
|
||
const groups = {
|
||
"😡 Hostile (−10 to −7)": pages.filter(p => p.score <= -7).sort((a,b)=>a.score-b.score),
|
||
"😕 Unfriendly (−6 to −1)": pages.filter(p => p.score >= -6 && p.score <= -1).sort((a,b)=>a.score-b.score),
|
||
"😐 Neutral (0)": pages.filter(p => p.score === 0).sort((a,b)=>String(a.name).localeCompare(String(b.name))),
|
||
"🙂 Friendly (+1 to +6)": pages.filter(p => p.score >= 1 && p.score <= 6).sort((a,b)=>b.score-a.score),
|
||
"🛡 Allied (+7 to +10)": pages.filter(p => p.score >= 7).sort((a,b)=>b.score-a.score),
|
||
};
|
||
|
||
for (const [title, rows] of Object.entries(groups)) {
|
||
dv.header(2, title);
|
||
if (!rows.length) { dv.paragraph("_None yet._"); continue; }
|
||
dv.table(
|
||
["NPC", "Faction", "Score", "Bar", "Tier"],
|
||
rows.map(r => [r.name, r.faction, r.score, bipolarBar(r.score), `${face(r.score)} ${tier(r.score)}`])
|
||
);
|
||
}
|
||
``` |