HotOrNot

:placard: Summary Adds an ELO based ranking system for performers and images.
:link: Repository https://github.com/lowgrade12/hot-or-not/tree/main/plugins/hotornot
:information_source: Source URL https://lowgrade12.github.io/hot-or-not/main/index.yml
:open_book: Install How to install a plugin?

HotOrNot Plugin

A plugin for Stash that uses an ELO-style rating system to rank performers and images through head-to-head comparisons.

Features

Comparison Modes:

  • Swiss :balance_scale: – Fair matchups between similarly-rated items with recency weighting to reduce repetition (available for performers and images)

  • Gauntlet :bullseye: – Place a performer in your rankings by climbing from the bottom until they lose (performers only)

  • Champion :trophy: – Winner stays on, with reduced rating changes for stable rankings (performers only)

Smart Tracking:

  • Comprehensive statistics: wins, losses, streaks, win rates, and match history

  • Adaptive K-factor: new performers adjust faster, established performers maintain stable rankings

  • Dynamic filter support: respects your active Stash filters (tags, studios, favorites, etc.)

Performance Optimized:

  • Performers: Full dataset for accurate ranking across all library sizes

  • Images: Intelligent sampling (500) for libraries >1000 images

Installation

:warning: Backup your database first (Settings → Interface → Editing)

  1. Download the /plugins/hotornot/ folder to your Stash plugins directory

  2. Optional: Change Rating System Type to “Decimal” for better precision (Settings → Interface → Editing)

Usage

For Performers:

  1. Navigate to the Performers page in Stash

  2. Optional: Apply filters (tags, studios, favorites, etc.) - the plugin respects your active filters

  3. Click the :fire: button in the bottom-right corner

  4. Choose your comparison mode (Swiss/Gauntlet/Champion)

  5. Click a performer (or use arrow keys) to pick the winner

  6. Click “:bar_chart: View All Stats” to see comprehensive statistics

For Images:

  1. Navigate to the Images page in Stash

  2. Click the :fire: button in the bottom-right corner

  3. Click an image (or use arrow keys) to pick the winner

How It Works

ELO Rating System:

  • Ratings stored in Stash’s native rating100field (1-100 scale)

  • Beating higher-rated items earns more points

  • Losing to lower-rated items costs more points

Adaptive K-Factor:

  • New performers (<10 matches): K=16 for fast initial positioning

  • Moderately established (10-30 matches): K=12 for balanced adjustments

  • Well-established (>50 matches): K=8 for stable rankings

Statistics Tracking: Tracks wins, losses, streaks, win rates, and match history in the hotornot_stats custom field.

Mode-Specific Behavior:

  • Swiss: Full stats and normal rating changes for both participants

  • Gauntlet: Full stats for active challenger; defenders get participation tracking only

  • Champion: Full stats for both, but 50% reduced K-factor for gradual evolution

Recency Weighting (Swiss Mode): Recently matched performers are less likely to reappear:

  • 0-1 hours ago: ~4% chance

  • 1-6 hours ago: ~12% chance

  • 6-24 hours ago: ~25% chance

  • 24+ hours ago: ~50% chance

Requirements

  • Stash v0.27 or later

  • At least 2 performers or images in your library

Credits

Inspired by stash-battle by dtt-git

License

See LICENCE for details.

5 Likes

With almost every performer in my current db being either 4 or 5 stars, I’m probably not making the most out of the rating, so I think I’ll give this sort of approach a try.

EDIT: Spent some time with this tonight, and it is pretty fun. There is room for improvement, but it’s a great foundation. Immediately more usable than some of the other plugins that I’ve tried out that attempted a similar ranking system. Thanks to you and @dtt.

EDIT 2: I can see that you’re using AI and making commits pretty frequently, so I’m not going to try making a pull request or my own fork at the moment. I do have a couple of suggestions though:

  • Since Performers support custom metadata fields, I would suggest to track wins and losses in custom fields so that this can be factored into the ELO rating deltas.
    • If the performer’s total matches (wins + losses) is less than some benchmark, maybe 10 total matches, then double the rating delta. This will help new unrated performers reach the appropriate range more quickly.
    • With swiss matchups, if the performer’s win percentage is high (maybe 70% or higher) bias towards matching them against a higher rated performer. Or another simpler approach may be to just increase the points won if the performer has a high percentage (if player with 70% or higher win rate and wins, multiply point gain by some small factor). If a performer is favorited, you could also apply a similar small boost to point gain to keep them higher in the ratings - although I could also see that causing issues for people with a lot of favorites by pushing too many performers high on the rating scale rather than maintaining a more even distribution.
  • There is some room for improvement with the way new matchups are fetched.
    • Fetching the entire list every time is not optimal and can be quite slow with a larger database. For me, it’s not really a problem with performers even with a relatively large database, but I see that you also tried adding in image rating and that is not functional at all for me because of how long it takes to load that full image list.
  • Improve randomization of matchups in gauntlet style. Right now, you will typically see the same performers show up repeatedly because they are the first person found with a specific score. It might also be possible to factor in the wins/losses in here as well (someone with a higher number of total matches is more likely to be a good benchmark for comparison as opposed to a performer with few matches).
  • For gauntlet style matchups, it would be nice if you could just select a specific performer to start with. Maybe this could be initiated with a button on the performer page or some sort of dropdown list added to the rating UI.
  • It would be nice to be able to filter the pool of possibly selected performers. It’s suggested in the Stash Battle plugin thread, but one way to do this would be to just use whatever filter is currently applied when the user clicks the button to open the Hot or Not rating UI.
    • I could however see this leading to some confusion if the user doesn’t realize a filter is being applied, so you would maybe need something in the UI to call out that a filter is applied along with a button to either toggle filtering off or to just clear the filter.
3 Likes

thanks for the feedback.

i was thinking about adding a custom field to track wins and losses, have not dug into it yet.

yeah i tried the image thing just to see. it works but is very slow because of the number of images.

i did add an option that gives 5 performers to pick from to take through gauntlet. if you haven’t pulled the latest, try that out and see what you think.

1 Like

FYI there is a similar performer rating plugin @Valkyr made based on the Glicko rating system.

It stores rating data in custom performer fields, includes a leaderboard, and shows Glicko ratings/rank on performer cards. But it lacks some of those comparison modes yours has.

Latest release: Release v0.0.1-alpha.3 · Valkyr-JS/glicko · GitHub

1 Like

@JAVegeta420 made some updates today. if you get around to messing with it, let me know what you think.

added stat tracking and updated the logic to use the stats
added the rank randomization to gauntlet mode
simplified image battles to only swiss mode. added some limiting on the initial query to improve performance

might try to dig into some filtering stuff tonight

nice. i’ll check it out

Cool. I will give it a look later.

EDIT: Some nice updates. Gauntlet flow seems better with fewer repeats showing up. Image matchups are still slow but it is functional now.

One minor issue I see is with the stat updates in the gauntlet - the initially selected performer is always updated with +1 win and +0 losses after the gauntlet and anyone they faced receives no stat update.

stat persistence issue. should be fixed now.

also made an update to make champion mode kind of it’s own thing now. updates both performers and keeps stats but a lower ± ranking.

1 Like

Thank you it helps alot to find a good rating for performers!

It would be great to be able to filter. especially I find it hard to rate a trans vs straight performers

1 Like

i believe i have filters working now. it is checking the active filters on the page, including multiple active filters. i’ve tested a lot of them and they seem to be working ok but there may be edge cases that still fail.

Seems to not be working for me with gender and tag criteria. The filter looks like it’s malformed. The performer filter that I see in your graphql call is this:

{
  "performer_filter": {
    "gender": {
      "value": [
        "Female"
      ],
      "modifier": "EQUALS"
    },
    "tags": {
      "value": [
        {
          "id": 1,
          "label": "JAV"
        }
      ],
      "modifier": "INCLUDES_ALL",
      "depth": 0
    }
  }
}

But it needs to be formatted like this to actually work:

{
  "performer_filter": {
    "gender": {
      "value": 
        "FEMALE",
      "modifier": "EQUALS"
    },
    "tags": {
      "value": [1],
      "modifier": "INCLUDES_ALL",
      "depth": 0
    }
  }
}

EDIT: This actually made me realize that tag filter parsing was also broken in one of my plugins, so I guess I also have some work to do.

thanks. i think i got them fixed now.

Yes. Seems to be working now.

1 Like

hello i love so much your extension ! It’s very fun to play !

I have to report just one thing for the moment.

Bug Report - hotornot

Summary: The “Favorite Performer” filter does not appear to be functioning correctly when searching for matches. Matches are not being filtered to only show performers marked as favorites.

Expected Result:

The search results should only display matches featuring performers who have been marked as “favorites” within the extension.

Actual Result:

The search results display matches featuring all performers, including those who have not been marked as favorites. The “Favorite Performer” filter appears to have no effect.

Environment:

  • Stash Version: 30.1

Extension version :1.0.0-d3ca484

1 Like

Favorites are fixed now

1 Like

Installed the plugin and tried it out.
Getting error message in the dialog: `Error loading scenes: Cannot query field “customFields” on type “Performer”. Did you mean “custom_fields”?`

Stash version: v0.30.1
Plugin version**: 1.0.0-ecbd71d

Any idea what the root cause for this could be?

try pulling the current version. i believe those are already fixed and should be working ok

Unlike in the instruction I added the plugin via adding a source (with https://raw.githubusercontent.com/lowgrade12/hot-or-not/refs/heads/main/_site/index.yml as the Source URL) and installed it that way.
So with that way I can’t get the newest version (the one used by me seems to be 4 days old).

So https://github.com/lowgrade12/hot-or-not/blob/main/\_site/index.yml needs to be updated, right?

in your screenshot, use https://lowgrade12.github.io/hot-or-not/main/index.yml for your Source URL

Ah, nice!
Thanks, it’s working now.

1 Like