Skip to content

Latest commit

 

History

History
209 lines (155 loc) · 9.98 KB

File metadata and controls

209 lines (155 loc) · 9.98 KB

AGENTS.md - DragonSort

This file is the authoritative source for DragonSort architecture, commands, and development patterns. For cross-cutting workspace rules, see the root ../AGENTS.md.

DragonSort Overview

DragonSort is a highly configurable bag sorter for World of Warcraft. It supports multiple sorting algorithms, can sort bags, bank, reagent bag, and warbank, and consolidates partial stacks before sorting.

Target Versions

Version Interface TOC Directive
Retail 110207, 120001, 120000 ## Interface: 120001, 120000, 110207
TBC Anniversary 20505 ## Interface-BCC: 20505
MoP Classic 50503 ## Interface-Mists: 50503

Version-specific files load via BigWigsMods packager comment directives in the TOC.


Architecture

Strict inward dependency: SlashCommands/Listeners -> Sorter -> Stacker/Algorithms/BagUtils -> WoW API.

Project Layout

Layer Directory Responsibility
Core DragonSort/Core/ Addon lifecycle, config, slash commands, minimap, engine modules
Locales DragonSort/Locales/ 11 locale files (enUS + 10 stubs)
Options DragonSort_Options/ Companion LoadOnDemand options UI (DragonWidgets)
Libs DragonSort/Libs/ Embedded Ace3 + utility libraries

File Map

File Purpose
DragonSort/Core/Init.lua AceAddon bootstrap, namespace, constants, OnInitialize/OnEnable/OnDisable
DragonSort/Core/Config.lua AceDB defaults, schema migration
DragonSort/Core/BagUtils.lua Bag ID computation, SnapshotBags, BuildSortKey, FindStackTargets
DragonSort/Core/Algorithms.lua CycleSort, SelectionSort, InsertionSort, ShellSort, Sort dispatcher
DragonSort/Core/Stacker.lua Async partial stack consolidation via coroutine + OnUpdate
DragonSort/Core/Sorter.lua Orchestration: bank state, combat deferral, item preloading, move execution
DragonSort/Core/MinimapIcon.lua LibDataBroker + LibDBIcon minimap button
DragonSort/Core/ConfigWindow.lua LoadOnDemand loader for DragonSort_Options
DragonSort/Core/SlashCommands.lua /dragonsort and /ds command router
DragonSort/Locales/enUS.lua Base English locale (86 keys, value = true)
DragonSort/Locales/*.lua 10 non-English stub files (all keys commented out)
DragonSort_Options/Core/Core.lua DragonWidgets bridge, tab registry, global DragonSort_Options API
DragonSort_Options/Core/OptionsWindow.lua Reserved stub for future helpers
DragonSort_Options/Tabs/GeneralTab.lua Sort Options + Sort Keys sections

Namespace Pattern

local ADDON_NAME, ns = ...

All modules attach to ns. The namespace is exposed globally as DragonSortNS for the companion options addon.

Sub-table Set by
ns.Addon Core/Init.lua
ns.BagUtils Core/BagUtils.lua
ns.Algorithms Core/Algorithms.lua
ns.Stacker Core/Stacker.lua
ns.Sorter Core/Sorter.lua
ns.MinimapIcon Core/MinimapIcon.lua
ns.ConfigWindow Core/ConfigWindow.lua
ns.Print Core/Init.lua (helper)
ns.DebugPrint Core/Init.lua (helper)
ns.L Core/Init.lua (AceLocale)

Sorting Engine

Two-Phase Sort

  1. Phase 1 (Virtual): Pure Lua sort using table.sort() to build a target order in memory.
  2. Phase 2 (Physical): Async cursor-based moves using cycle decomposition to minimize swaps, executed via coroutine + OnUpdate.

Stacking Pass

  • Runs BEFORE sorting when enabled.
  • Consolidates partial stacks of the same item into full stacks.
  • Async via coroutine + OnUpdate.

Algorithms

Algorithm Key Characteristic
Cycle Sort "cycle" Optimal: minimum moves (n-c swaps for n items). Default.
Selection Sort "selection" O(n^2) comparisons, O(n) swaps.
Insertion Sort "insertion" O(n^2) worst case, O(n) nearly-sorted.
Shell Sort "shell" O(n log^2 n) with Ciura gap sequence.

Key API Usage

  • ns.Sorter.StartSort(scope): Public entry point.
  • C_Container.GetContainerItemInfo(bagID, slot): Canonical empty check.
  • C_Container.PickupContainerItem(): Called twice to execute a swap.
  • ITEM_UNLOCKED: Event used to gate the async move loop to avoid slot corruption.
  • C_Item.GetItemInfoInstant(): Used for preloading; must be nil-guarded.

Config Schema

Sort Config (db.profile.sort)

Key Type Default Description
algorithm string "cycle" Sorting algorithm: cycle/selection/insertion/shell
scope string "bags" What to sort: bags/bank/reagent/warbank/all
stackBeforeSort boolean true Consolidate partial stacks before sorting
deferInCombat boolean true Queue sort during combat, run after
respectDisableFlag boolean true Skip bags marked as non-sortable

Sort Key Config (db.profile.sortKey)

Key Type Default Description
primary string "type" First sort criterion: type/quality/ilvl/name/quantity
secondary string "quality" Second criterion (tie-break for primary)
tertiary string "ilvl" Third criterion (tie-break for secondary)
junkPosition string "end" Where to place junk-quality items: end/beginning

Options UI

DragonSort_Options is a LoadOnDemand companion addon.

  • Triggered by /ds config or minimap right-click.
  • Uses DragonWidgets (git submodule at DragonSort_Options/Libs/DragonWidgets/).
  • Global API: DragonSort_Options.Open(), .Close(), .Toggle().
  • Locales: Uses GetLocale("DragonSort") (main addon name).

Development Commands

# Lint (must pass with 0 warnings)
luacheck .

# Manual verification steps:
# 1. /ds sort (verify bags sort correctly)
# 2. /ds stack (verify partial stacks merge)
# 3. /ds config (verify options window opens)
# 4. /ds help (verify help output)

# Mise tasks
mise run lint

Known Gotchas

  1. C_Item.GetItemInfoInstant() may return nil: Always nil-guard for uncached items.
  2. Bank State: No WoW API queries bank state; tracked via BANKFRAME_OPENED/CLOSED events into ns.Sorter.bankIsOpen.
  3. Cycle decomposition bug: The pivot must track its new position through multi-element cycles.
  4. Classic bank bag IDs: Use NUM_BANKBAGSLOTS (not NUM_BAG_SLOTS_BANK_BAG) for Classic bank bags.
  5. Move mechanics: PickupContainerItem must be called twice; wait for ITEM_UNLOCKED between swaps.
  6. AceAddon Lifecycle: Use :Enable() / :Disable() (public API), not internal hooks.
  7. TOC Directives: Use packager comment directives (#@retail@) for version-gating, never ## Interface: mid-file.

CI/CD and GitHub Workflow

  • lint.yml: Runs on pull_request_target.
  • release.yml: Handles release-please automation.
  • packager.yml: Builds and uploads artifacts on release.

Branching and PRs

  • Branch from master: feat/<number>-short-desc, fix/<number>-short-desc, etc.
  • Reference Closes #N in PR body.
  • Squash merge only.
  • Never merge release-please PRs (e.g., chore(master): release X.Y.Z).

Labels

  • Category: C-Bug, C-Feature, C-Performance, C-Usability, C-Code-Quality, C-Documentation, C-Localization
  • Area: A-Core, A-Sorter, A-Stacker, A-Algorithms, A-Options, A-Config, A-Appearance, A-Localization, A-CI
  • Difficulty: D-Good-First-Issue, D-Straightforward, D-Complex, D-Expert
  • Platform: P-Retail, P-TBC-Anniversary, P-MoP-Classic, P-All-Versions

Communication Style

As the repo owner, always write in first-person singular ("I").

  • Direct and solution-driven.
  • Think in systems and frameworks.
  • Bias toward concrete, copy-paste-ready solutions.
  • Calm, rational, and focused.

Working Agreement for Agents

  • Addon-level AGENTS.md overrides root rules.
  • Run luacheck . before and after every change.
  • No automated tests: Provide detailed manual verification steps in PRs.
  • Use the wow-addon agent for API research; do not guess signatures.
  • Follow the root ../AGENTS.md skill-loading matrix for coder delegations.