From 0304ff33935daa92efc6b1687f2ba3fb66d9d421 Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Thu, 26 Mar 2026 01:37:44 +1100 Subject: [PATCH] Condense README for clarity and approachability --- README.md | 135 +++++++++++----------------------------- docs/images/eleven.webp | Bin 9860 -> 0 bytes 2 files changed, 36 insertions(+), 99 deletions(-) delete mode 100644 docs/images/eleven.webp diff --git a/README.md b/README.md index 2a610d9..8211325 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,32 @@ # Pairwise Glicko ranking for your notes -Easily sort notes by any subjective criteria using the **Glicko rating system**. +Easily sort notes by any subjective criteria. -It's basically "which one wins?" instead of trying to assign absolute scores. Rather than asking "how does this note compare to every other note?", you only answer: "which of these two do I prefer?" +Rating something on an arbitrary five-star scale is hard - what happens when you find something better? Do you have to readjust your old ratings? + +Pairwise comparisons avoid the ambiguity of absolute ratings and create a dynamic ranking that adjusts as you add more comparisons. Just ask yourself "which of these two notes wins?" and the rest is calculated for you. ### Learn more about yourself and your preferences by seeing how you rank your own notes. Try these ideas in seconds: -- Which book or movie is really your favourite? Rank your **Books#Read** or **Movies#Watched** Base views. +- Which book or movie is really your favourite? Rank your **Books#Read** or **Movies#Watched** Bases. - Which project ideas are most worth pursuing? Rank your **#idea** tag. - Which purchase is the highest priority for you right now? Rank your **#to-buy** tag. -- Which recipes should become your go-to staples? Rank your **Recipes** Base. -- Which museums, hikes, or travel destinations should you explore next? Rank your **Places** Base. -- Which research papers are most relevant to your work? Rank your **sources** folder. +- Which experiences, restaurants, hikes, or travel destinations should you explore next? Rank your **Places** Base. - Which people should you cut from your life?\* Rank your **People** Base. _Ooh, spicy!_ ![colour_base_example](docs/images/colour_base_example.webp) _Other comparison arena UI options are available in Settings - shown here is **right-split**, useful if you'd like to watch your Base update as your ranks change, but I personally use **new window/popout**_. Mobile devices are supported by an additional single-note layout type for phones with smaller screens. -## Try it in two minutes +## How it works: Try it in two minutes 1. Install: Not yet in the Community Plugins list, so first install [BRAT](https://obsidian.md/plugins?id=obsidian42-brat) 2. Add the Pairwise Glicko Ranking repo - `https://github.com/WilliamsJack/pairwise-glicko-ranking` and enable the plugin 3. Run the **Pairwise Glicko Ranking: Start rating session** command (or click the trophy icon) -4. Pick a small cohort (10 notes is perfect) -5. Do ~10-20 comparisons and you'll see an order emerge surprisingly fast - -## How it works - -- Pick a **cohort** of notes to rank (vault, folder, tags, or (my favourite way) - Bases). -- The plugin opens **two notes side-by-side** and you choose a winner (keyboard shortcuts supported). -- Optionally write stats to frontmatter (property names are configurable, including per-cohort): **Rank** (1 = best in cohort), **Rating**, **Matches**, **Wins**. -- Your Bases can then sort or filter by those properties, so you can rank by subjective criteria without having to decide what star rating a note "deserves". + - Pick a **cohort** of notes to rank (vault, folder, tags, or (my favourite way) - Bases). + - The plugin opens **two notes side-by-side** and you choose a winner. + - The plugin (optionally) writes stats like **Rank** (1 = best in cohort), **Rating** , or **Wins** to frontmatter (property names are configurable). + - Your Bases can then sort or filter by those properties, so you can rank notes by subjective criteria without having to decide what star rating a note "deserves". ## Overview @@ -41,37 +36,27 @@ _Other comparison arena UI options are available in Settings - shown here is **r - Information-gain matchmaking that automatically picks the most useful pairs to compare - A stability progress bar that shows how close your rankings are to converging - Glicko-1 rating updates - uncertainty (sigma) governs step sizes automatically, so new notes converge fast and experienced notes stay stable -- Robust to renames and moves via stable per-note IDs +- Robust to note renames and moves via stable per-note IDs - Cohorts are saved so you can resume ranking sessions, picking up where you left off -## Motivation - -I originally built this because I had a Base of photos I'd taken and wanted to sort them by quality, showing the best photos first. But that's a subjective sorting system - a computer can't do it for me. - -It can be difficult to give a note a rating in a vacuum. What happens if you rate it ten stars, and then find something better later? Do you have to readjust your previous ratings? Do you have to add an eleventh star? - -![eleven](docs/images/eleven.webp) - -_"Why don't you just make ten better and make ten be the top number and make that a little better?"_ - -That's essentially what this plugin does. Given two notes, it's much easier to choose a preference between them than to rate them on their own. By comparing notes directly, you avoid the ambiguity of absolute ratings and create a dynamic ranking that adjusts as you add more comparisons. - ## Workflow -### Start a session +### 1. Start a session ![cohort_creator](docs/images/cohort_creator.webp) - Click the trophy icon in the left ribbon, or run the command **"Pairwise Glicko Ranking: Start rating session"**. -- Create a cohort in the picker: - - Vault: all notes - - From a Base (.base file + view) - - Active folder (with or without recursive subfolders) - - Pick a folder... - - Tag cohort (match Any or All of selected tags) +- Create a cohort (the set of notes you're ranking together) in the picker: + - Vault: all Markdown notes + - Base: notes returned by a specific **Base** and a specific **view** + - Folder: a single folder, with or without recursive subfolders + - Tag (any): notes that match any of the selected tags + - Tag (all): notes that match all of the selected tags - Previously saved cohorts appear here too -### Compare two notes +Saved cohorts can be renamed and reconfigured in Settings. If the folder or Base that defines a cohort is later moved or renamed, the plugin will prompt you to point it to the new location to safely migrate your saved ratings. + +### 2. Compare two notes ![arena](docs/images/arena.webp) @@ -85,82 +70,27 @@ Two notes open side-by-side in Reading mode for you to compare. Use the arrow ke A toast shows the winner after each comparison (toggle in Settings). -### End the session +### 3. End the session Press Escape or run **"Pairwise Glicko Ranking: End current session"**. If you've enabled a Rank property for this cohort, the plugin recomputes ranks across the cohort and writes them to frontmatter. -### Configurable frontmatter output - -![cohort_options](docs/images/cohort_options.webp) - -Use the values computed by the plugin however you want. Choose which values get written to frontmatter and what their property names are. - -## Mobile support - -The plugin is fully functional on mobile devices, with support for all desktop layouts on tablets (except popout/new window), and an additional single-leaf layout for phones that allows comparison between two notes using a switch button. - -![colour_base_example_mobile](docs/images/colour_base_example_mobile.webp) - -## What's a cohort? - -A cohort is the set of notes you're ranking together. Supported cohort types: - -- Vault: all Markdown notes -- Folder: a single folder only -- Folder (recursive): a folder and all subfolders -- Tag (any): notes that match any of the selected tags -- Tag (all): notes that match all of the selected tags -- Manual list of notes (advanced; not created from the picker yet) -- Base: notes returned by a specific **Base** and a specific **view** - -Saved cohorts can be renamed and reconfigured in Settings. - -If a folder cohort is later moved or renamed, the plugin will prompt you to point it to the new location and will suggest likely folders based on the notes it can still find. - -If a Base cohort's **.base file** is moved/renamed, or the **view name** no longer exists, the plugin will prompt you to pick the Base and/or view again and will migrate the cohort's saved ratings to the updated definition. +Optionally, the plugin can generate a **post-session report** - a Markdown note summarising the session (biggest gains, losses, surprises, leaderboard snapshot, match log, and more). Reports use a template with `{{glicko:...}}` placeholders that you can customise, or you can use the built-in default. Run the command **"Generate example report template"** to create a starting template you can edit. Report generation is configurable per-cohort and globally in Settings. ## Frontmatter -### Note IDs - -Each note that participates in a session gets a stable note ID so your ratings survive file moves and renames. - -- Where: by default in frontmatter as `glickoId`; you can choose to store it at the end of the note as an HTML comment instead. The property name is configurable in Settings. -- When: IDs are created lazily the first time a note is shown in a session. - -Example (frontmatter): - -```yaml ---- -glickoId: 123e4567-e89b-12d3-a456-426614174000 ---- -``` - -Example (anywhere in the body of a note, but appended to the end by default): - -```markdown - -``` - -### Stored properties - The plugin can write the following properties to frontmatter (configurable per-cohort, all optional, names customisable): - Rating - Rank (1 = highest within the cohort) - Matches - Wins +- Uncertainty (sigma) -Stats are written to just the two notes involved after each match. Rank across the whole cohort is recomputed and written when you end the session (if enabled for that cohort). +You can then use the values computed by the plugin however you want. For example, enable the Rank property and then sort a Base by it to see your notes in ranked order, or use the Rating property to filter for your best notes with a rating above a certain threshold. -**Tip:** Configure global defaults in Settings, and (optionally) set per-cohort overrides when creating or editing a cohort. When you change property names or enable/disable them, the plugin can bulk-update, rename or remove the affected properties across the cohort with a confirmation preview. +**Tip:** Configure global defaults in Settings, and (optionally) set per-cohort overrides when creating or editing a cohort. -## Data and integrity - -- Ratings are stored per cohort in the plugin's data; no network calls. -- Notes are tracked by note ID, not by path, so renames and moves are fine. -- On session start, the plugin prunes any players that no longer have a corresponding note in the cohort. -- Only Markdown files are included. You need at least two notes to start. +![cohort_options](docs/images/cohort_options.webp) ## Settings overview @@ -170,7 +100,14 @@ Stats are written to just the two notes involved after each match. Rank across t - Progress bar settings (stability threshold, surprise highlight) - Default frontmatter properties (names and which to write) - Ask for per-cohort overrides when creating a cohort (on by default) -- Cohorts section: rename a cohort and change its frontmatter overrides. The plugin can preview and perform bulk updates (write, rename, remove) across the cohort. +- Post-session reports: enable/disable, report folder, file name template, and custom report template path +- Cohorts section: rename a cohort and change its frontmatter, scroll, and report overrides. The plugin can preview and perform bulk updates (write, rename, remove) across the cohort. + +## Mobile support + +The plugin is fully functional on mobile devices, with support for all desktop layouts on tablets (except popout/new window), and an additional single-leaf layout for phones that allows comparison between two notes using a switch button. + +![colour_base_example_mobile](docs/images/colour_base_example_mobile.webp) --- diff --git a/docs/images/eleven.webp b/docs/images/eleven.webp deleted file mode 100644 index adb825b0e40dda20c709958c7021215e4e58959f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9860 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