Skip to content

Latest commit

 

History

History
executable file
·
84 lines (62 loc) · 5.28 KB

File metadata and controls

executable file
·
84 lines (62 loc) · 5.28 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Wheelson is a World of Warcraft addon (Lua, WoW API) that forms balanced Mythic+ dungeon groups from guild members using a wheel-spin reveal animation. It uses AceAddon-3.0 framework and communicates between guild members via AceComm.

Commands

Lint

luacheck src/ tests/

Test

busted

Tests use the busted framework. Config is in .busted — tests live in tests/ with the test_ prefix pattern.

Run a single test file

busted tests/test_models.lua

Build validation

bash scripts/build.sh

Checks that the .toc file exists and all source files listed in it are present on disk.

Architecture

Global namespace pattern

The addon registers itself as Wheelson via AceAddon in src/Config.lua, stored in _G.Wheelson. Every other source file accesses it via local WHLSN = _G.Wheelson and attaches methods/data to it. There is no module system — all files share the single WHLSN table.

File load order (defined by Wheelson.toc)

  1. Config.lua — Creates the addon object, defines constants (roles, spec→role mapping, session states, saved variable defaults)
  2. Models.luaWHLSN.Player and WHLSN.Group classes (metatables with :New(), :ToDict(), .FromDict() serialization)
  3. GroupCreator.lua — Group formation algorithm (port of parallelGroupCreator.ts). Assigns tanks → lust → brez → healers → ranged → remaining DPS with duplicate-avoidance across runs
  4. Core.lua — Addon lifecycle (OnInitialize/OnEnable), slash commands (/wheelson), session state machine (lobby → spinning → completed), addon comm message handling, session timeout
  5. Services/SpecService (local player spec detection, realm name stripping), GuildService (roster queries), PartyService (party invites)
  6. UI/MainFrame.xml + MainFrame.lua (window shell, view switching), Lobby.lua (player list + join/spin), Wheel.lua (animated group reveal), GroupDisplay.lua (final results with invite/post/copy actions)

Session state machine

WHLSN.session.status: nil"lobby""spinning""completed". The host broadcasts state to guild via AceComm (GUILD channel, prefix WHLSN). Non-hosts send JOIN_REQUEST/LEAVE_REQUEST messages.

Group creation algorithm

GroupCreator.lua is a direct port of parallelGroupCreator.ts from a companion TypeScript project. It fills groups in priority order: tanks, lust providers, brez providers, healers, ranged DPS, remaining DPS. It tracks previous group compositions per guild to avoid repeat teammate assignments.

Test structure

Tests stub WoW APIs and LibStub at the top of each file, then dofile() the source files in load order. Only non-UI logic is tested (Models, GroupCreator, GuildService, SpecService). The test stubs pattern is consistent across all test files — copy from an existing test when adding new ones.

Git Workflow

  • Never push directly to main. Always create a feature branch, push there, and open a PR.
  • When using /commit-push, push to the current feature branch (not origin main).
  • Use /ship-it to create the PR, get reviews, and merge.

WoW API Version

This addon targets WoW 12.0 (Midnight) (## Interface: 120001). Use the modern C_ namespaced APIs — do not use their deprecated predecessors:

Deprecated (do NOT use) Use instead
GetSpecialization() C_SpecializationInfo.GetSpecialization()
GetSpecializationInfo() C_SpecializationInfo.GetSpecializationInfo()
SendChatMessage() C_ChatInfo.SendChatMessage()
InviteUnit() C_PartyInfo.InviteUnit()

When adding new WoW API calls, check Warcraft Wiki API changes to confirm the function hasn't been removed or moved to a C_ namespace in 12.0.

Key Conventions

  • Lua 5.1 target (std = "lua51" in .luacheckrc), 120 char line limit
  • Roles are strings: "tank", "healer", "ranged", "melee"
  • Utilities are strings: "brez", "lust"
  • Player identity comparison uses Player:Equals() (name-based)
  • Serialization for addon comms uses :ToDict() / .FromDict() pattern on model classes
  • Table append idiom: t[#t + 1] = value (not table.insert)
  • External libraries (Ace3, LibStub, etc.) are fetched at release time by BigWigsMods packager per .pkgmeta — the libs/ dir is gitignored except .gitkeep
  • CI job naming constraint: .github/workflows/ci-shared.yml is a reusable workflow (workflow_call only) that defines three jobs: Lint, Build, Test. It is called by .github/workflows/ci.yml (trigger: pull_request only) via a calling job with ID CI. GitHub Actions names reusable workflow checks as <calling_job_id> / <reusable_job_id>, producing CI / Lint, CI / Build, CI / Test — which branch protection requires. Do not rename the calling job ID in ci.yml or the job IDs in ci-shared.yml, and do not add extra triggers to ci.yml.
  • Never git add -f gitignored files. If a path is in .gitignore (e.g. docs/superpowers/), respect that — do not force-add or force-commit it. Those files are local-only by design.