5.4 KiB
🎲 Dota Random
"I-it's not like I made a whole randomizer just so YOU could have chaotic fun in your games or anything... b-baka."
Fine, FINE. Since you're making me explain it: this is a Dota 2 hero + item build randomizer. You pick how much chaos you want — scope it to melee heroes, lock item tags, disable half the randomness if you're a coward — and it rolls you a hero, a full item build (slot 1 is always boots, don't argue with me about it), neutral item candidates per stage, enchantments, and tells you when you're allowed to buy your Aghanim's. Not that I care if you actually use it properly.
It's not a toy. ...Okay it's kind of a toy. Shut up.
What it actually does
- Hero scope — filter by attack type and/or primary attribute, or leave it wide open if you're feeling brave
- Item scope — restrict rolls to items carrying specific purpose tags (Physical Damage, Disable, Sustain, etc.)
- Slot 1 is always boots — every existing boots item in the game is eligible, including separate grades like Boots of Travel / Boots of Travel 2 and Dagon's five levels, each rolled as its own distinct outcome
- Neutral items, honestly modeled — each active tier suggests 2 real candidates, because the app can't actually control what drops in your match. You click whichever one you got, or browse the full tier if neither matches
- Enchantments, guaranteed — no RNG-within-RNG nonsense here. If enchantment rolling is on, you get one, scoped correctly to your hero's primary attribute (including the "works on literally any hero" ones — yes, those exist, no I didn't forget about them)
- Aghanim's Scepter & Shard roll as normal items now — no special-cased fake probability. You also get to say whether you're "allowed" to buy them mid-build or only after your 6 slots are full, for whenever they don't get rolled naturally
- Reroll anything — hero, a single item slot, a specific neutral tier, a specific enchantment tier. Rerolling your hero also refreshes your neutral items and enchantments, since a new hero deserves a fresh itemization pass, o-obviously
- Manual override, always available — disable randomness for any slot/dimension and pick it yourself instead
Stack
Not that you need to know this to use it, but since you're being nosy:
| Layer | Tech |
|---|---|
| Backend | Rust, axum, sqlx (Postgres) |
| Frontend | React, TypeScript, Vite, Tailwind CSS |
| Database | PostgreSQL |
| Data source | Scraped live from Liquipedia via Python scripts (no hardcoded/stale game data, thank you very much) |
| Deployment | Docker Compose + a Gitea Actions CI/CD pipeline |
Getting it running (pay attention, I'm not repeating myself)
1. Database
Spin up a Postgres instance however you like — there's a docker-compose.yml in here that already knows how to do it. Then fill in .env at the project root:
DATABASE_URL=postgres://user:password@host:port/dbname
NEUTRAL_TIER_GATE_CHANCE=0.5 # optional, defaults to 0.5 -- the odds of the "can I even change my neutral item this tier" gate
Migrations run automatically on startup (sqlx::migrate!() — it's embedded in the binary, you don't need to run anything by hand). But the tables start empty — the actual hero/item/enchantment data isn't hardcoded anywhere, it's scraped:
pip install requests beautifulsoup4
# edit USER_AGENT at the top of each script first -- Liquipedia's API
# terms require a real, identifying User-Agent, not a generic one
python scripts/scrape_heroes.py
python scripts/scrape_items.py
sqlx migrate run
Yes, this means the roster stays current with whatever patch Liquipedia reflects. Rerun the scripts whenever you want fresh data. I'm not doing that part for you.
2. Backend
cargo run
Serves the API on :8080.
3. Frontend
cd frontend
npm install
npm run dev
Runs on :5173 with a dev proxy to the backend, so it just works. You're welcome.
4. Or just use Docker Compose
docker compose up
...if the images are actually built and pushed, which they will be, because there's a whole CI pipeline for it. I didn't half-ass this.
Project layout, since you'll get lost otherwise
src/ Rust backend (axum handlers, roll logic, models)
migrations/ sqlx migrations (schema + scraped seed data)
scripts/ Python scrapers (Liquipedia -> migration files)
frontend/ React + TypeScript SPA
.gitea/ CI/CD workflow
A note on the data
Heroes, items, and enchantments are scraped from Liquipedia's Dota 2 wiki, not hand-typed or pulled from memory — patches change too fast for that to stay accurate, and I refuse to ship stale data. The scrapers check each item's actual current status (active / removed / unreleased / hidden) rather than trusting whatever list happens to mention it, because apparently even wikis get this wrong sometimes.
Disclaimer
Part of this project — the whole frontend, a chunk of the Rust backend, the data scrapers, the CI/CD setup — was written with AI assistance. It's not like every line was hand-crafted by a lone genius at 3am. Mostly. I just don't like writing boilerplate code or code I already know how to write! Baka!
Author
ItzYumeii
...I guess if you actually enjoy using this, that's... fine. Not that it matters to me or anything.