Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.

Bug Fixes
(97fc2b0) ~John KauffmanFix for reset trigger color
(75343da) ~John KauffmanFix duplicate tree on trigger import
- Replay early quick-shares, batch import state writes, retune Core analyzers
(a24cf14) ~John KauffmanQuick Share lost anything accepted before the window existed. GinaUtil now feeds
QuickShareState (Core cannot see the WPF manager) while the manager mirrors records into the
bound collection from its constructor, so a GINA share seen before the window was ever opened never
appeared in that list, even though OpenQuickShareStatusAsync, which reads the state directly,
still showed it. QuickShareState.Subscribe attaches and replays under one lock, so a view created late
cannot miss a record; replay runs oldest-first to match the manager's Insert(0). The legacy share
flow kept working because it touches QuickShareManager.Instance itself — that asymmetry is what
hid the bug. Two tests pin the replay order and the empty-history case.
Import wrote each character state document once per merged node, re-serializing the whole Enabled
dictionary every time: quadratic in import size. 600 triggers for 8 characters measured 752ms and
measures 27ms after collecting the touched documents and writing them once at the end of the import
(300 for 8: 169ms -> 20ms). The flush stays inside the caller's transaction, so nodes and state
still commit as one unit.
Also fixed in the files above:
- GetAllOverlays handed back a deferred LiteDB cursor that its callers enumerated after the queue
callback returned, i.e. off-queue against a handle another transaction may be holding.
- A node without an id — which UpgradeTree elsewhere explicitly tolerates — took down the whole
view build, because the badge dictionaries and the enabled-state lookup throw on a null key.
SetStateFromParentInternal likewise walked every root folder when asked about no node at all.
- GinaUtil.CheckGina dereferenced the trusted-player list, which TriggerProcessor may legitimately
set to null from a TrustedPlayers update; it now matches TriggerUtil's tolerant check.
- A dead store in the heal-window loop, and ValidateOverlays resolving the overlay id set once per
element instead of once per import.
EQLogParser.Core gains the AnalysisLevel/EnforceCodeStyleInBuild settings the app project has; the
assembly split had silently dropped them for the ~40 moved files. The fallout is fixed rather than
ignored (culture-sensitive EndsWith/ToLower, IndexOf-for-Contains, default-valued initializers,
culture-bound AppendLine in the NAG report), and the three process-lifetime singletons carry a
documented CA1001 suppression pointing at the teardown that actually owns them.
Removed code nothing could reach: AdpsTracker.UpdateLandsOnYou/SetCritRateMods (Recalculate owns
those values), PlayerRegistry.GetPetPlayerMappings, TriggerLogManager.ClearCharacter, two
ViewOptionRegistry accessors plus the write-only field behind them, and 62 commented-out lines in
HitFreqChart that referenced a type no longer in the repository.
Reduced duplicated code to one copy: QuickShareRecord.FromChat (both share producers carried the
same ownership and "To" rules verbatim), GinaUtil.TryGetGinaKey (its marker arithmetic existed
twice), and TestWorkspace — five fixtures each kept their own temp-dir list, [TestCleanup] delete
loop and CreateDirectory(Guid) line, two of them also their own FindRepoFile.
Left alone for a decision: EventsNodeCheckChanged and its tree walk (redundant on every current
path, but asserted by a test), the full GINA/legacy pipeline merge, the stats-builder and WPF
grid-editor duplication.
Build clean in Debug and Release with no code warnings; 849 tests pass (was 847).
- Keep the GINA chunk download off the dispatcher
(36505d5) ~John KauffmanRunGinaTaskAsync is async but its body is synchronous HTTP: up to 100 sequential
DownloadPackageChunk round trips through HttpClient.Send / ReadAsStream / CopyTo,
with no cancellation token and the default 100 second timeout. Only the leading
Task.Delay awaited — so where that continuation resumed decided where the whole
download ran.
From TriggerProcessor's chat task there is no context to capture and the transfer
merely occupies a thread-pool thread. But QuickShareWindow's Import button calls
ImportQuickShare from the UI thread, so await captured the WPF dispatcher and
resumed the download on it: the window stops painting and overlays stop updating
until the transfer ends. Resuming on the thread pool is safe because nothing in
the method touches WPF directly — the GinaPlatform hooks marshal themselves and
TriggerStateDB has its own queue.
The GINA service is effectively gone, so today this path fails fast and the freeze
is mostly theoretical; ConfigureAwait(false) is a one-word guarantee rather than a
dependency on how quickly eq.gimasoft.com answers. Verified the resume behaviour in
a throwaway harness with a dispatcher-like SynchronizationContext: without it the
continuation runs on the owner thread (13 == 13), with it on a pool thread.
- Bind node ids instead of interpolating them into commands
(f750b9b) ~John KauffmanSetExpanded built "… WHERE _id = '<id>'" and SetAllExpanded built the same
statement without a predicate. Execute() feeds LiteDB's command parser, so an id
carrying a quote broke the text: every expand/collapse of that node threw
LiteException ("Unexpected token `id` in position 53") and its state was never
saved, for as long as the node exists — the id is stored in the database.
Such ids are reachable because an imported overlay keeps the id from its file
(that is what makes re-export round-trips work), so a shared .ogf / Quick Share
payload chooses that string. The UI hides it: the throw escapes the async void
NodeExpanded handler into AppDispatcherUnhandledException, which logs it and sets
Handled, so the symptom is one node that will not remember being expanded plus a
growing error log.
Both values are now bound as @0/@1 parameters (LiteDB 5 rejects the "?" form).
The stored document is identical — Boolean True either way — so normal ids behave
exactly as before; Execute() runs a single statement, so nothing worse than a
failure could ever be smuggled in.
- Never lose a failed dispatcher post; read quick-share state safely
(f70ac45) ~John Kauffman- UIUtil.InvokeAsyncLogged continued only with OnlyOnFaulted, so it observed neither an
already-completed faulted task (the inline path) nor a dispatcher post cancelled by shutdown:
the callback simply never ran and nothing was logged. The continuation now fires for anything
that did not run to completion — faults at Error, cancellation at Debug because it only happens
during teardown, and on TaskScheduler.Default so logging does not depend on the dispatcher that
may itself be shutting down.
- OpenQuickShareStatusAsync enumerated the window's bound ObservableCollection from a background
thread; it now takes QuickShareState.Snapshot(), which is lock-guarded and WPF-free.
- QuickShareManager.Instance had a public-ish setter and an internal constructor even though the
constructor subscribes to QuickShareState.Accepted: constructing a second manager would mirror
every accepted record twice. Setter and constructor are now private.
- Keep folder media badge across siblings; never reuse a taken _id
(76c6d37) ~John Kauffman- Import assigned the per-node CheckMissingMedia() result instead of OR-ing it, so a clean
sibling imported after a broken one cleared the running flag and the containing folder lost its
missing-media badge. Both call sites now accumulate with |=.
- Overlay insert reused the exported node id unconditionally. _id is unique across the whole
collection, so importing the same share into a second folder threw on insert and rolled back the
entire import. The exported id is now used only while it is free (its re-export match case);
otherwise Insert() generates one. This is routine expected behaviour, so nothing is logged.
- Two store tests pin both behaviours; both fail against the pre-fix code.
(51d0b0a) ~John KauffmanFix litedb serialize
- Blank line before lists so python-markdown renders them
(87bc5a0) ~John KauffmanPython-markdown does not let a list interrupt a paragraph (unlike
CommonMark), so lists placed directly after an intro sentence were
swallowed into the <p> and rendered as inline text. Add the required
blank line in 4 places in getting-started.md and 4 in triggers.md.
Documentation
- Add DesignNotes for trigger and overlay import, referenced from CodingStandards
(6c73382) ~John KauffmanRecords the import behaviour we settled on so it is not rediscovered or quietly reversed: what each
producer (tgf.gz, ogf.gz, gtp, EQLP quick share, GINA share, NAG migration) puts on the wire and what
identity it carries; why the overlay tree is flat and must be treated as such; the overlay matching
contract (Id when present, Source only when there is none, never the name) with the reason — NAG mints
overlay ids per install, so Source is a same-lineage migration key rather than a cross-user identity;
id reuse on insert; threading rules for the share pipeline; media validation and badge accumulation;
name trimming because LiteDB trims stored strings. Plus the warts we reviewed and left alone, and the
alternatives we rejected (name matching, Source before Id, logging routine collisions).
CodingStandards now points at it from the top, and gains the rule that design rationale belongs in
DesignNotes instead of long paragraphs of code comments: the comment states the constraint and links
to the note.
- Bind values in LiteDB commands instead of building them in
(6a4ed88) ~John KauffmanAdds a short Data Access section: IDatabase.Execute parses command text, so values
belong in @0/@1 parameters (LiteDB 5 has no "?" placeholder) while collection and
column names, being constants, may still be interpolated. Imported payloads decide
some of those values — an overlay keeps the _id from the shared .ogf — which is
exactly how SetExpanded came to throw on a node id containing a quote.
- Logging is for exceptions and session milestones, not expected behaviour
(e29e740) ~John Kauffman
- Fix mislabeled store defaults and re-attach orphaned NagUtil comment
(1a2f809) ~John Kauffman
(ca7cb28) ~John KauffmanDoc updates
- Restructure Getting Started - parser first, triggers second
(5805e55) ~John Kauffman- 'What is EQLogParser?' now states the parser-first, triggers-optional split
- New '2. Open Your First Log': File -> Open and Monitor Log File flow with
the Auto Monitor Last Log tip (parser value with zero configuration)
- '3. Audio Triggers and Overlays' covers Trigger Manager basics and the
basic-mode master switch; OBS link points at the FAQ entry
- New '4. Have More Than One Character?' explains Switch to Advanced,
Manage Characters (New -> New Character + Select Log), and per-character
enable states - replaces the old Configure Your Character section which
referenced the Advanced-mode-only character pane without mentioning it
- GINA/NAG import sections renumbered 5/6; FAQ NAG link follows to
#6-migrating-from-nag
- Flatten Getting Start - drop redundant Quick Start heading
(4d0f768) ~John KauffmanThe page itself is the getting started guide, so promote the five
numbered steps from H3 to H2 and remove the 'Quick Start' wrapper.
Point the FAQ's NAG cross-reference at the new 5-migrating-from-nag
anchor (replaces the removed quick-start anchor).
- Add 'Moving to a New PC' section covering backup/restore
(f1f19a1) ~John KauffmanExplains the Tools -> Create Backup File and Tools -> Restore From
Backup workflow for migrating settings (characters, triggers,
custom variables, overlays) to a new machine.
Features
- Replace empty release notes TOC with browse-by-year nav
(9bc2ab1) ~John KauffmanThe release notes TOC was removed long ago because 60+ entries were
too many, leaving an unused 200px column. Group releases by year
instead (2026 / 2025 / older versions) so the left sidebar is useful.
Existing H1 slug ids are untouched so the version-hash anchor
compatibility script keeps working.
Refactor
- Drop the now-tautological FindIndex guard
(4f03880) ~John Kauffman
- Drop dead branches, extract shared capture-group naming
(8e07a85) ~John Kauffman- remove the comment-only 'if (hasClassLevels)' block and the unreachable
isSequential arm of the reason ternary (the skip returns before it is read)
- extract FindFirstUnnamedGroup/NameFirstUnnamedGroup: the same while-loop was
written three times (HasUnnamedCaptureGroup + both set-variable loops)
- merged end-early phrases are already unique by phrase, count them directly
- drop the redundant second _audioFileMap reset in LoadAudioFileMap
Styling
- Link the notes instead of restating them in comments
(e26ac4f) ~John KauffmanPractices the new rule on the same branch that introduced it: three comment blocks written this
session (the load-bearing ConfigureAwait in GinaUtil, parameter binding in SetExpanded, overlay id
reuse on import) became paragraphs whose content now lives in docs/DesignNotes.md and
docs/CodingStandards.md. Each is reduced to the constraint plus a pointer, so there is one place to
update when the reasoning changes. No code change; build and tests unchanged (847 passed).
- Prefer pattern matching, plain comments for Core utility members
(6a3fa58) ~John Kauffman- x != null / x == null -> is not null / is null outside LiteDB predicates
(TriggerImportPlanner, QuickShareState, TriggerTreeViewBuilder, and the
SetState/SetExpanded/CopyState guards in TriggerStateDB)
- FirstOrDefault(...) != null -> Any(...) in QuickShareState.IsMine
- /// headers on internal utility members -> // per CodingStandards (XML docs
are for WPF component class headers): CombatRecordLookup, GinaPlatform,
QuickShareState, NagUtil, TriggerStateDB.Dispose
Commits
(70ad189) ~John KauffmanV2.3.61
(6a8d0ef) ~John KauffmanUpdated spell data and some library versions
(34a5ec6) ~John KauffmanRestore the first-versioned-run bootstrap gate and document db versioning
The isNewDb (empty-file) gate silently skipped the first-run default overlays
and pre-upgrade 'last db file' backup for populated databases that were never
version-stamped (pre-2024 builds). Capture the missing-version-document signal
before ApplyDatabaseMigrations runs - matching the old fixVersions.Count()==0
semantics - so those databases get bootstrapped, while already-versioned user
databases still never are (new tests pin both directions).
also:
- type the legacy 'Version' cleanup as BsonDocument; it is count/delete-only and
legacy documents may be unreadable System.Version values
- record the versioning history (System.Version 'Version' -> string 'FixVersion'
chain) in comments at the constants and call sites so the why survives
(f446e77) ~John KauffmanRework NAG overlay identity and drop the unused trigger metadata
nag import:
- overlay node ids stay store-generated UUIDs; the NAG overlayId now travels in
OverlayData.Source ("nag:{overlayId}") instead
- re-importing an existing NAG overlay updates it in place (TriggerStateDB.Import
matches by Source among siblings) rather than adding a duplicate copy
- trigger SelectedOverlays references are remapped from NAG ids to stored uuids
(NagUtil.BuildOverlayIdRemap/RemapOverlayReferences) before the triggers import,
so an import never references dead ids
- remove NagTriggerMetadata: nothing consumed it; per-trigger report data already
lives on NagImportResult (ConvertTriggers now returns nodes + results)
standards:
- reorder NagUtil members by visibility (fields -> internal -> private)
- fix CovertToTriggerNodes typo in GinaUtil (+ call sites)
- CombatRecordLookup hook back to unannotated Func<string, string> (Core is
Nullable-disabled); the test fallback becomes "", which both consumers treat
identically to null via IsNullOrEmpty
- drop the empty ItemGroup from EQLogParser.Wpf.Test
(5b1954d) ~John KauffmanAddress code review findings for the Core split branch
store:
- create the task queue before migrations and isolate migration failures so a
throw cannot NRE the cached singleton; version stamp only after a fully
successful run so partial migrations retry
- fail fast with InvalidOperationException when TriggerStorePlatform.GetDbFile
is unwired instead of building a no-op store over a null path
- kind-safe matching on the OriginalId import path: a folder wrapper can no
longer reach the overwrite branch and erase a stored trigger's data
- validate SelectedOverlays on both insert and update-in-place; the id set is
loaded once per import instead of one collection scan + N seeks per trigger
- load siblings/subtrees once per import and state walk (GetTree,
FixEnabledState, UpdateChildState, Import) instead of one query per node
- FixColor fallback is now #FFFFFFFF (opaque white, AARRGGBB like all other
paths; bare #FFFFFF binds as transparent black in WPF)
nag import:
- tolerant JSON readers (ReadNumber/ReadInt/ReadLong/ReadBool) at every
numeric/boolean site: string, fractional and out-of-range tokens no longer
abort a trigger and report it Skipped
- NagImportStatus enum replaces the Imported/Partial/Skipped magic strings;
NagImportResult/NagTriggerMetadata back to internal
host/ui:
- GinaUtil: dispose the request/response chain (it owns the socket) and use
CopyTo for the chunk payload - a single Stream.Read could return short and
truncate the download
- non-blocking InvokeAsyncLogged posts for EventsNodeCheckChanged and quick-
share mirroring: no dispatcher wait from inside an open transaction, no
unobserved task exceptions
- trigger tree builder tolerates an orphan node with null Parent
- NodeCheckChanged renamed to EventsNodeCheckChanged per the Events prefix
standard
cleanup and tests:
- LegacyOverlay.ToOverlay uses the generated Mapperly deep clone; new
OverlayCloneTest asserts every Overlay field survives the port
- drop dead separator constants; ParseDamage classAbility string -> bool flag
- [DoNotParallelize] + save/restore for every test class that mutates
process-wide state; regression tests for kind-mismatched OriginalId import,
stringy/fractional/out-of-range JSON, overlay re-import and unwired db path
docs: README desktop runtime bumped to 8.0.30; ReleaseChecklist requires
MeasureLoadedAssemblies for both the app and BackupUtil before release
(20dc505) ~John KauffmanAdded damage shields as melee adps
(2b50a40) ~John KauffmanUpdated download link for dotnet
(f560297) ~John KauffmanMerge branch 'master' into develop
(2741f25) ~John KauffmanUpdate bottles with new label for dotnet8
(9a832d4) ~John KauffmanMerge branch 'docs/site-fixes' into develop
# Conflicts:
# .gitignore
(a3dedb2) ~John KauffmanRemove orphaned documentation.md (superseded by getting-started/triggers/faq)
(0977945) ~John KauffmanAdded release checker to verify DLLs needed for install and some nag import bug fixes
(d4aea91) ~John KauffmanCode cleanup
(9ee7f17) ~John KauffmanNAG import: plainer report wording for no-duration timers
'Indefinite timer duration' was jargon for the one line users actually
read when triaging a Partial row, and 'end-early phrases' mixed in EQLP
naming. Reworded to plain language:
No set timer duration: this NAG timer has no fixed length; it runs
until its stop phrase matches. Imported disabled (placeholder
duration) with its stop-phrase, warning and end data populated —
set the real duration on the timer and enable it.
Internal dropped-feature note renamed to 'no set timer duration (timer
left disabled)' to match; test assertion updated.
(984c66a) ~John KauffmanAdd real-export import validation + checked-in mini fixtures
Validated against the user's full exports (kept under gitignored local/):
- allraid.tgf.gz: 467 trigger leaves / 249 folders, depth-9 nesting —
Import_AllraidTgfGz_RoundTrips checks exact node count, byte-for-byte
re-import idempotency, the B4 no-same-name-leaf invariant at depth and
regex patterns with escaped dots
- cooldownOverlay.ogf.gz: real timer overlay — stored id survives insert
and re-import is duplicate-free on top of the bootstrap defaults
Both are CI-safe skips when the files are absent (same convention as
wizard.tgf.gz).
Checked-in subsets for deterministic coverage on every machine:
- EQLogParser.Test/data/mini.tgf.gz — the real '25th Anniversary' raid
section from allraid (14 nodes, timers/warning slots/Comments,
same-name leaves under different parents)
- EQLogParser.Test/data/mini.ogf.gz — the real Cooldown Overlay plus one
text overlay
Copied to bin as mini-data\ by the test csproj; MiniFixtureImportTest
hard-fails (no skip) if a checked-in fixture is missing and pins
import/re-import idempotency, id preservation and pattern fidelity.
(28f2778) ~John KauffmanPin the standard .ogf overlay import contract with a regression test
Standard (file-based) overlay re-import matches leaves by stored id —
exports carry it for overlays only, folders export with Id null — and
updates data in place without touching the display name. This path has
no fixture-driven test on CI (wizard.ogf.gz is local-only), so add a
synthetic round-trip that pins: id survives insert, re-import by id is
duplicate-free, data updates in place, name unchanged (master behavior).
Standard .tgf path stays covered by the real wizard.tgf.gz round-trip
plus the B4 collision invariants.
(44b1a6a) ~John KauffmanFix re-import corruption for NAG triggers with shared-OriginalId fan-out nodes
A single NAG trigger can export several siblings that share one OriginalId
(phrase + timer variants, counter resets). FindExisting matched by source id
alone (FirstOrDefault), so on re-import EVERY incoming family member
overwrote the first stored sibling found in collection order: the last
incoming node's data won and the other stored members stayed stale.
Matching is now family-aware in TriggerImportPlanner.FindExisting:
- more than one stored sibling carries the id -> name must disambiguate
- the incoming batch itself carries the id more than once (first import: an
earlier member was already inserted into the live sibling set) -> name
must disambiguate too
- exactly one stored sibling, id unique in the batch -> id alone, so a user
rename still updates in place instead of inserting a duplicate (B4)
A renamed member of a shared-id family now inserts as a new, visible sibling
instead of silently overwriting another member. The store computes the
batch's shared-id set per parent level and passes it to the planner.
Adds regression tests: planner-level family/batch cases plus an end-to-end
store re-import test (both members receive their own data). 817/817 green.
(b0e0e64) ~John KauffmanReview cleanup: member ordering in GinaPlatform, drop no-op self-assignment
Final branch review pass (master vs develop):
- GinaPlatform: move the internal ImportChoice enum after the public hooks
to match the CodingStandards visibility ordering (public -> internal)
- TriggerStateDB: remove pre-existing dead line
'newNode.OverlayData = newNode.OverlayData;'
(f8f9e4a) ~John KauffmanRoute the marker migration through the intended FixVersion version chain
The previous fix added a separate boolean stamp document to FixVersion,
which bypassed the collection's actual purpose: a stored version number
gating one-time upgrades (no version -> oldest upgrades; 1.0.x -> next
set; current -> nothing).
ApplyDatabaseMigrations now owns the chain: it reads the version from
the existing {Id:"1"} document older builds wrote, applies every
migration step below CurrentDbVersion (1.0.2 = strip the stale
ExportTriggerNode type marker), and upserts that same document to the
current version only after all steps ran, so an interrupted run retries
next launch. Fresh databases are stamped at CurrentDbVersion directly;
the bootstrap block no longer writes its own 1.0.1 seed (single writer).
Future migrations append as ordered steps: bump CurrentDbVersion, add
'else if (stored < ...)' - exactly the no-version/1.0/1.1 scheme this
collection was designed for. Tests now assert the version bump instead
of the removed stamp.
(6f11ad4) ~John KauffmanFix all nullable reference type warnings in tests and Core
19 CS86xx warnings were being emitted by files added during the refactor,
contrary to docs/CodingStandards.md (Nullable Reference Types section):
proper annotations, never suppression.
- NagUtil (Core, project has NRT disabled): drop the two 'List<string>?'
annotations from the phrase-routing methods - they can only carry
meaning in a nullable-enabled context and produced CS8632 here
- test helpers that legitimately take or produce null: annotate the
parameters/returns ('string? originalId = null', 'QuickShareRecord?',
'out string?' on TryLoadNagDump) instead of passing null literals to
non-nullable parameters (CS8625/CS8603/CS8604)
- read-only guards where a null must be impossible: ReadExport throws
on an un-deserializable fixture; LoadFixture guards the manifest name
before GetManifestResourceStream; Store() guards GetDirectoryName
- GinaQuickShare lookups now bind via '?? throw' so the compiler can
track non-nullness at the use sites (old Assert.IsNotNull + deref
pattern left them untracked)
Full solution build is now warning-free.
(e58445f) ~John KauffmanMake the marker-strip sweep a true one-time migration
As shipped in commit # [d6f1ca1](https://github.com/kauffman12/EQLogParser/commit/d6f1ca1a) the cleanup re-scanned every document in every
collection on every launch. It was always a no-op after the first run,
but on a database with thousands of nodes that is wasted startup work
forever.
Gate the sweep on a stamp in the existing FixVersion collection (where
the old host already keeps its one-time upgrade stamps): while the stamp
is missing, run the full sweep; once it is written, startups pay only
for a tiny FindAll on FixVersion and skip. The stamp is written only
after a complete pass, so an interrupted run retries next launch.
The bootstrap block used an empty FixVersion as its "brand-new file"
signal - now that the stamp can live there, capture true freshness (no
collections at all) before the sweep runs instead.
Regression tests: stamp present after a clean sweep; a fresh stale
marker in an untouched collection survives a second open (sweep really
did not re-run).
(d6f1ca1) ~John KauffmanMake the legacy marker cleanup actually survive a real database run
The previous pass aborted on the first write: the store opens its LiteDB
file with ConnectionType.Shared, where starting a write invalidates any
still-open query cursor ("no more active transaction for this cursor").
FindAll() is lazy, so per-document Update calls killed the cleanup loop
mid-sweep; the constructor catch swallowed it and only ~one document got
cleaned per launch - which is why old databases kept crashing.
- materialize the read before writing (FindAll().ToList())
- sweep every collection, not just Tree, with per-collection error
containment so one bad collection cannot block the rest or startup
- run the sweep first thing after opening the file, before any typed
query, so no earlier failure can skip it
- log which database file is opened and log open failures at Error level
with the exception (previously Warn, easily missed)
- null-safe Dispose for constructors that failed early
Regression test now seeds markers in Tree (top-level + nested child)
and in Config and asserts every collection comes out clean.
(25245c7) ~John KauffmanFix unreadable legacy trigger databases (stale LiteDB type marker)
Databases written by pre-refactor builds carry LiteDB's polymorphic type
marker "_type": "EQLogParser.ExportTriggerNode, EQLogParser" on imported
nodes. ExportTriggerNode now lives in EQLogParser.Core, so resolving the
marker throws 'Type ... not found in current domain' on the first tree
query — the whole database becomes unreadable (ctor, GetTree,
FixEnabledState, LoadOverlayStyles all crash).
The marker is inert: nodes were always stored flat via Parent/Id links and
the export type persisted nothing beyond TriggerNode itself. The constructor
now strips the stale marker from any tree document before the first query —
an idempotent no-op for databases the current build writes, so no data is
touched otherwise. Cleanup reports a single summary line (databases hold
thousands of nodes) and only on the first launch after an upgrade.
Regression test seeds a legacy-marker document into a real LiteDB file and
opens it: without the migration it reproduces the exact LiteException, with
it the store opens and the node survives intact.
(612c4ae) ~John KauffmanNAG import: null-duration timers import disabled instead of a guessed 60s
Neither NAG nor we can say what an indefinite timer's real duration is, so
stop inventing one. A NAG timer action with duration: null now imports with
EnableTimer = false and the model's default duration (0.2s), while every
other field still populates as before: end-early phrases, warning text/
sound/duration, end texts, label, colors, overlays. A user who knows the
real duration sets it and flips the timer on — no re-import needed.
- TimerActionData gains an explicit Enabled flag; the fan-out derives
EnableTimer from Enabled && DurationSeconds > 0 (previously just
DurationSeconds > 0).
- Dropped-feature note renamed to 'indefinite timer duration (timer left
disabled)'; report friendly text updated. Status is still Partial — the
duration really is unknown.
(67731a3) ~John KauffmanNAG import: route phrase-scoped actions to their own phrase triggers
NAG actions target specific capture phrases via their "phrases" array (or a
single "phraseId"), but the import merged every non-timer action into one
shared set cloned onto all phrase nodes — so a multi-phrase trigger showed
the last-scoped action's sound/text/speech on every phrase, and one phrase's
audio replaced another's text. Unscoped actions still merge globally (last
wins, as before); scoped actions' display/speak/sound/share values now apply
only to their own phrase nodes (RouteActionValue -> PhraseScopedValues),
layered on top of the unscoped merge and only on each phrase's first timer
variant, matching the no-double-fire rule.
- Case 7 (clear variable) display-text routing is unified onto the same
mechanism; it now also honors single-field "phraseId" scoping like every
other action type.
- The "per-phrase action scoping" dropped-feature note now fires only for
action types without routing (timers, counters); routable actions instead
get "action targets phrase(s) missing from trigger" when their scope is
stale NAG data, with the values dropped rather than merged globally.
Sample DB: ~190 flagged triggers included every scoped text/audio/TTS
action; those are now routed correctly.
(e66198a) ~John KauffmanNAG import: keep the author's comment on every split trigger
A multi-timer (or multi-phrase) NAG trigger fans out into several EQLP
triggers, each a full trigger in its own right. The author's comment was
kept only on the first timer variant because it rode along with the shared
non-timer actions — but unlike those actions, a comment is inert metadata
that cannot double-fire, so every split node should carry it and stand on
its own. Test updated from pinning the old behavior to the new one.
(0612380) ~John KauffmanNAG import: honor case-sensitive end-early phrases
End-early phrase collection (trigger-level and per-timer-action) ignored the
per-phrase ignoreCase flag, so all 56 case-sensitive end-early phrases in the
sample DB were silently imported as case-insensitive (EQLP compiles every
regex pattern with IgnoreCase). Opted-out regex phrases now get the (?-i)
prefix like capture phrases; non-regex case-sensitive ones get a
dropped-feature note instead of being guessed at.
(c3613fa) ~John KauffmanNAG import: map timer ending/ended audio to warning/end sound slots
Timer actions' endingPlayAudioFileId and endedPlayAudioFileId were silently
dropped. EQLP has exactly matching slots (WarningSoundToPlay for the
ending-soon state, EndSoundToPlay at end), so map them with the same file
resolution and missing-file reporting as regular action audio.
Also extracts the duplicated id-resolution logic (files-database map,
'Speech ding' -> alert1.wav, existence check) into ResolveAudioFile, now
shared by action audio, timer end audio, and the dev-only scan.
(e7a8ee3) ~John KauffmanNAG import: map timer endingDuration to 'Warn With Time Remaining'
NAG timer actions carry endingDuration — the seconds before the end at which
the timer enters its ending state and warning text/sound fire. EQLP has the
matching WarningSeconds field (property grid: 'Warn With Time Remaining',
consumed by the timer runtime), but the import never read it, so all 326
affected timers in the sample DB lost their warning threshold.
Also adds an extraJson escape hatch to the test's action builder for fields
without a dedicated parameter.
(3d31128) ~John KauffmanDrop the UTF-8 BOM accidentally re-added to the solution file
(89d4e61) ~John KauffmanKeep GINA failure dialogs sequential and fix the misleading allowCancel name
Two review findings in the GINA platform seam:
1. ShowMessage was fire-and-forget (Action), so 'NextGinaTask' could run
while the error dialog was still open. The original WPF flow blocked on
ShowDialog() before scheduling the next task. ShowMessage is now
Func<string,string,Task> and GinaUtil awaits it; the host wiring awaits
the UI-thread dispatch.
2. The AskImportChoice bool was named allowCancel, but the original dialog
always had a Cancel button — the flag feeds MessageWindow's 'extra'
argument, which shows the auto-merge option row (originally passed
characterIds.Count > 0). Renamed to showMergeOption with a doc that says
what it actually does.
(b046e7c) ~John KauffmanNAG uniquify: skip suffixes already used by a literal sibling
When siblings are A, A, "A (2)", the old scheme renamed the duplicate to
"A (2)" — colliding with the existing node and re-introducing the same-name
sibling collision the uniquification exists to remove. Generated "Name (n)"
suffixes now step past any name already taken by a sibling. Also recurse into
null-named nodes so their children are still de-duplicated.
Adds a conversion test: A, A, "A (2)" -> A, A (2), A (3).
(9e4c1f9) ~John KauffmanMirror every accepted quick-share record into the WPF window's collection
The GINA flow moved to QuickShareState (Core) during the extraction, but
only the legacy share path still went through QuickShareManager — so
received GINA quick-shares were accepted into the state yet never
appeared in the QuickShare window (which binds solely to the manager's
collection).
QuickShareState now raises an Accepted event on the accepting thread
(after the lock, at most once per unique record) and QuickShareManager
subscribes once, mirroring accepted records into its bound collection on
the UI thread. Both producers (GINA via the state directly, legacy shares
via the manager) flow through that single mirror path; manager.Add is a
pass-through again.
(d5bb442) ~John KauffmanSilence nullable warnings in the new stats/data-store tests
Pure annotations: nullable event-capture locals, nullable Hit()
default args, string? CWD field, null! at the two parser callbacks
whose documented contract is 'return null for no match'.
(ab20693) ~John KauffmanAdd Linux-runnable tests for the FileSearcher log scanner
The last Utils file without any test coverage: a generic async
multi-file line scanner used by the search window, which posts
matched-line batches with stream positions and drives progress.
Four scenarios, each against temp files (CI-safe):
- start==0 scans any time; batches post in file-list order despite
parallel scanning, one batch per matching file, no-match files
post nothing
- timestamps outside the given TimeRange are skipped, and lines past
the last segment end abort that file's scan early
- a missing file completes silently and progress still reaches 100
- a full scan with zero matches posts nothing but reports progress
Notes pinned by the tests: parser returns (line, null) for non-matches
which the searcher converts to null; LinePosition values are buffered-read
positions so they are non-decreasing, not strictly increasing.
(6752673) ~John KauffmanAdd Linux-runnable tests for EQDataStore and ConfigUtil.ReadList
Eleven direct tests: ParseCustomSpellData column mapping (all 20 fields incl. duration ticks, resistance, ambiguity and lands-on text), rank-stripped abbreviations, short-line rejection; class registration through the host label hook (IsValidClassName/GetClassEnum/list); real-data lookups (healing filter by damaging<0 with a negative control, NPC/old-spell databases, parenthesized-title mapping); missing-file degradation (no throw, empty knowledge); AddUnknownSpell dedupe.
Also pins the ConfigUtil.ReadList separator regression: backslash data paths must resolve on non-Windows hosts, and missing files return empty without throwing.
(93e4b6d) ~John KauffmanAdd Linux-runnable tests for the healing, cast and misc line parsers
24 tests exercising Process(LineData) end-to-end: heal lines (direct/HoT/over-heal/self-heal pronoun normalization/negative), cast lines (you/others, old-style angled names, interrupt marking of the matching cast, zone-enter records), misc lines (corpse loot, master-looter and split currency copper conversion, resists, die rolls, mez breaks, need-roll wins, left-on-chest), and PreLineParser player/merc routing + FindPossiblePlayerName bounds/cross-server dots.
Two fixture quirks documented in the tests: zone lines are consumed before the cast pass so Process returns false; 'Targeted (Player)' carries two spaces. Behavior was not changed.
(37f844f) ~John KauffmanAdd Linux-runnable tests for the stats builders + formatter
Ten direct tests over DamageStatsBuilder/HealingStatsBuilder/TankingStatsBuilder/DamageOverlayStatsBuilder/StatsFormatter: raid totals, DPS rounding, rankings, pet aggregation (+Pets, percent-of-parent, Children map), MaxSeconds windowing, no-data (NONPC) event contract, healing per-healer/sub-stat breakdowns (including the PlayerRegistry name gate), tanking per-defender totals, overlay empty-state, and formatter line/title composition for DamageParse.
Notes from the work: builders group blocks with a lastTime==0 sentinel, so a block at exactly t==0 is dropped — real log timestamps never hit 0, left as-is. The healing test also exposed the first-heal off-by-one (fixed separately).
- Don't skip the first heal record when grouping
(e8f59b4) ~John KauffmanThe per-segment heal scan called FindIndex with a start index of 1, but FindIndex is 0-based — so the very first in-range heal was never examined and dropped from every full stats build. Off by one; now starts at 0.
(3ac5c4a) ~John KauffmanAdd Linux-runnable GINA/quick-share tests (chat detection, state rules, E2E import)
- CheckGina scenarios: trusted group chat adds a history record, tell is
addressed to the receiving character, own tells are marked IsMine, say
channel is recorded but auto-import ineligible — no network involved
(auto-processing stays gated behind TriggersWatchForQuickShare)
- QuickShareState rules in isolation: insert-once-at-top dedup + IsMine
(Snapshot added to the state for non-UI readers)
- End-to-end: a synthetic GINA zip package converts via GinaUtil and
imports into a temp TriggerStateDB through the same call GINA's flow
makes, asserting the folder/trigger land with their data
753/753 Core tests pass on Linux; full solution builds clean.
(9fdd3e5) ~John KauffmanMove the GINA download/convert/import flow into cross-platform Core
GinaUtil moves wholesale: XML conversion, the chunked SOAP download, the
chat-detection cache (CheckGina/ImportQuickShare) and the store import all
run in Core. The only WPF needs it had were windows:
- failure MessageWindows and the merge/new-folder question are replaced by
GinaPlatform hooks (ShowMessage + AskImportChoice); App.xaml.cs wires them
back to the same MessageWindow dialogs (same buttons, same allow-cancel
rule) on the UI thread
- the borrowed MainActions.TheHttpClient becomes a local client with
identical defaults; QuickShareManager.Instance is replaced by the Core
QuickShareState singleton from the previous commit
Behavior preserved: same download loop, same message texts, same import
calls, same NextGinaTask ordering. Callers (TriggerProcessor, TriggerUtil,
QuickShareWindow) now resolve GinaUtil through IVT unchanged.
(56f5e7c) ~John KauffmanMove quick-share domain (records, CharacterData, state rules) into Core
QuickShareRecord and CharacterData are plain data used by both the GINA
flow and the legacy share flow; the history dedup/ownership logic moves to
a thread-safe QuickShareState singleton so it is testable without WPF.
The WPF QuickShareManager becomes a thin UI adapter: same ObservableCollection
binding, same UI-thread marshaling of view updates, but the insert-once-at-top
decision now happens in the shared state. Behavior preserved.
(4c45aaf) ~John KauffmanRun the NAG conversion test suite on Linux + add real-dump round-trips
- NagUtilTriggerImportTest (80+ cases) moves out of Wpf.Test, including its
three NAG fixtures (now embedded resources of EQLogParser.Test; the
manifest-name lookup is suffix-based since RootNamespace differs)
- New NagStoreRealDataTest drives ConvertTriggers/ConvertOverlays against a
real NAG database dump under local/nag/ (gitignored, CI-safe skip) and
imports the result into a temp TriggerStateDB: conversion shape, import
idempotency, zero same-name sibling collisions, overlay round-trip
The real-dump run is what exposed the two import-fidelity fixes in the
previous commits. 747/747 Core tests pass on Linux.
- Uniquify same-name siblings when converting NAG databases
(b5c4d1e) ~John KauffmanReal NAG trigger databases contain multiple children with identical names
under one parent (e.g. several 'Fireball' triggers in one folder). The
trigger store keys children by (kind, name), so those duplicates merge into
or shadow each other — re-importing the same dump added more duplicates on
every pass and left indistinguishable siblings in the tree. Uniquifying at
the conversion boundary ('X', 'X' -> 'X', 'X (2)') matches the shape the
app's own .tgf exports already have, making NAG imports idempotent.
Verified by a real-dump round-trip test (next commit): import x2 is
stable and leaves zero same-name sibling collisions.
- Reset the audio-file map on every ConvertTriggers call
(3b14ef5) ~John KauffmanThe map was only rebuilt when a database directory was supplied, so a call
without one inherited the previous caller's map — stale fileId→path
resolution corrupted SoundToPlay and missing-audio tracking (surfaced by
running the NAG conversion tests in one process with a real files-database).
Production passes the same directory every time, so behavior is unchanged
there; the reset makes each call self-contained.
(510a237) ~John KauffmanMatch re-imported NAG triggers by OriginalId alone, not name+id
The importer does not rename same-name collisions, so with duplicate NAG
trigger names the stored sibling set contains identical names; the old
name+OriginalId match still worked for those — but combined with folder
merges of same-named folders (which the planner matches by name), re-imports
of real NAG databases accumulated duplicate children on every pass. OriginalId
is the stable source identity and survives on the stored node, so matching on
it alone is both more precise and resilient to any future rename behavior.
Covered by a new planner case (renamed existing node still matches by id)
and, from the next commit, by a real-dump re-import test.
(458a341) ~John KauffmanMove NagUtil (NAG trigger/overlay import) into cross-platform Core
Its only WPF coupling was two TriggerUtil.SoundFileExists calls, now
routed through the existing TriggerStorePlatform.SoundExists hook —
App.xaml.cs already wires that delegate to the same method, so this is
an identity swap. NagImportResult/NagTriggerMetadata travel with it.
The NAG import pipeline (ConvertTriggers/ConvertOverlays/skip reports)
is now testable on Linux, including against real NAG database dumps.
633/633 Core tests pass; WPF host and Wpf.Test compile clean.
(712a000) ~John KauffmanMove stats builders into Core, run validator tests on Linux
- control/builders: IStatsBuilder, DamageStatsBuilder, HealingStatsBuilder,
TankingStatsBuilder, DamageOverlayStatsBuilder, SpellCountBuilder, plus
StatsFormatter — all WPF-free; the one resx label use
(Resource.ANY_CLASS) routes through CombatRecordLookup.AnyClass
- DamageValidatorTest/HealingValidatorTest (44 tests) move out of
Wpf.Test; HealingValidatorTest wires the healing-spell seam to a real
EQDataStore so AOE rejection is tested against real spell data
Fixes a cross-platform bug the move exposed: ConfigUtil.ReadList passed
Windows-style paths (data\spells.txt) straight to File.Exists, which is
a literal name on Linux — every data file load silently returned empty,
so the spell/proc/NPC databases were never populated outside Windows.
ReadList now normalizes separators (no-op on Windows).
633/633 Core tests pass on Linux; WPF host and Wpf.Test compile clean.
(f547e31) ~John KauffmanRun the parser test suite on Linux (out of Wpf.Test)
Moves ChatLineParserTest, DamageLineParserTest and
LineModifiersParserTest (126 tests) from EQLogParser.Wpf.Test to
EQLogParser.Test so they execute on any OS:
- namespace rewritten to match the project
- test csproj copies the app's data/ files (spells.txt, npcs.txt, ...)
to the output where EQDataStore loads them
- Core gains IVT for DynamicProxyGenAssembly2 (Moq proxy generation of
internal IFightManager)
All 604 Core tests pass on Linux; WPF host and Wpf.Test still compile
clean.
(d4bc65b) ~John KauffmanMove parsing layer, EQDataStore and fight management into cross-platform Core
- All 9 parsing files (line parsers, ParserUtil, LineData,
ChatLineParser with its public ChatType/ChatChannels models)
- dao/store/EQDataStore (spell knowledge store). Its two resx lookups
route through a new CombatRecordLookup.ClassLabelByEnumName seam
wired in App.xaml.cs (identity to the previous ResourceManager call)
- control/managers: FightManager (+IFightManager), AdpsTracker, and
dao/store/RaidRosterStore — all BCL-only, pulled forward from later
phases because parsers/stores depend on them; hooking each call site
would have meant a dozen seams for types with zero WPF coupling
- Core csproj gains AllowUnsafeBlocks (ParserUtil's stackalloc join)
Pure relocation plus one seam, no behavior change. Core builds on
Linux; WPF host and Wpf.Test compile clean; 478/478 Core tests pass.
(c1c85d2) ~John KauffmanMove validators, stats util, record collections and session stores into Core
Follows the model split; everything moved is WPF-free (verified by usings):
- control/util: DamageValidator, HealingValidator, StatsUtil
- dao/util: RecordGroupCollections (+ nested RecordWrapper)
- util/AppSettings, parsing/LineModifiersParser
- dao/store: RecordsStore, PlayerRegistry (831 lines), plus the small
pure LifecycleManager registry they register with
- Extracted Labels, SpellTarget and SpellClass constants from
EQDataStore.cs into Core model files (verbatim).
EQDataStore stays in WPF for now; the handful of cross-cuts are routed
through a new CombatRecordLookup seam (healing spell lookup, player-spell
and class-name validation, class bitmask, resx class labels) wired in
App.xaml.cs — each entry is an identity delegate to the previous call
site. Utils gains IVT to Core for StringCache.
Pure relocation plus seam swaps, no behavior change. Core builds on
Linux; WPF host and Wpf.Test compile clean; 478/478 Core tests pass.
(7d35c30) ~John KauffmanMove combat log record and stats models into cross-platform Core project
Splits dao/model/DataModel.cs by dependency role (member-for-member,
verified line-level against the original):
- RecordModels.cs/StatsModel.cs into Core: IAction, hit/spell records,
timed actions, all *Record/*Event payloads, Fight, PlayerStats tree,
CombinedStats and related stats containers (INotifyPropertyChanged is
plain BCL, so these are platform-pure).
- Attempt.cs, parsing/SpellData.cs, parsing/HitRecord.cs moved whole.
- WPF keeps only the UI-facing types: IDocumentContent,
ComboBoxItemDetails, ParseData, PlayerStatsSelectionChangedEventArgs,
DataPointEvent (the last moves once its RecordGroupCollection does).
- LootRecord.Clone mapper moves to Core's ModelMapper; Riok.Mapperly
dropped from the WPF project.
- FightTable.xaml now resolves {x:Type core:Fight} via an explicit
clr-namespace/assembly xmlns (XAML does not search referenced
assemblies for unqualified local: types).
Pure relocation, no behavior change. Core builds on Linux; WPF host and
Wpf.Test compile clean; 478/478 Core tests pass.
(180e57a) ~John KauffmanAdd Linux-runnable store-level tests for TriggerStateDB (import, state, persistence)
(f76da18) ~John KauffmanMove TriggerStateDB and trigger store models into cross-platform Core project
(8cc1ff9) ~John KauffmanExtract trigger import matching into cross-platform TriggerImportPlanner with unit tests
(3964136) ~John KauffmanMove trigger store models into new cross-platform EQLogParser.Core project
(576aa82) ~John KauffmanFix re-import matching so same-named folder/trigger siblings can't erase each other
(3df9bc4) ~John KauffmanNAG import: skip malformed triggers instead of aborting and report overlay fidelity notes
(4ea5527) ~John KauffmanIgnore local nag sample data directory
(710b821) ~John KauffmanFix CS0103: zero DurationSeconds in per-node timer block else-branch
durationSeconds is a TimerActionData field, not a ParseTrigger local;
the timerless-zeroing belongs in the node loop's else branch instead.
(aa58201) ~John KauffmanFix EEP leak assertion and zero duration for timerless imports
The sibling-timer EEP test asserted the inverse of its own intent
(IsFalse on IsNullOrEmpty requires the leak). Separately, NAG
triggers without any timer action inherited the model's 0.2s
DurationSeconds default and exported a phantom timer; zero it out
at import time.
(3fbc8dd) ~John KauffmanAttach shared non-timer actions only to first timer variant
A NAG trigger's non-timer actions (text, TTS, audio, clipboard,
counters, set/clear variables) fire once per execution in NAG, but
every node of a multi-timer fan-out matches the same log line and
would re-run them (TTS spoken twice, counter incremented twice).
They now attach to each phrase's first timer variant only; sibling
variants carry just their own timer plus per-node import notes. The
NAG author's trigger comment rides with the shared actions.
(48719c4) ~John KauffmanIgnore pi-subagents session artifacts
(e5fffb1) ~John KauffmanIgnore local working documents directory
(caf0e18) ~John KauffmanFix NAG import: one node per timer action and route timer labels to AltTimerName
- ParseActions now collects one TimerActionData per NAG timer action (3/4/6/10)
instead of merging into shared locals where the last action overwrote earlier
ones' duration, label, and restart behavior.
- ParseTrigger fans out one node per capture phrase x timer action, named
'Name #i (Timer j)' when a trigger has multiple timers; non-timer actions
stay shared across nodes.
- Timer displayText maps to AltTimerName (the EQLP timer-bar label) instead of
TextToDisplay; text-overlay text keeps TextToDisplay.
- An action's own endEarlyPhrases merge into its timer variant's node list only
(max 3 slots, overflow reported as dropped).
- DotTimer (6) imports as a filling Progress timer and per-target types report
their lost per-target grouping in the import notes.
- Update real-data Bard Epic tests to the fan-out shape; add multi-timer,
label-routing, end-early scoping, and draw-direction tests.
Bug Fixes
(d8d14d2) ~John KauffmanFix stale action type 6 label in code comment
(ada2a23) ~John KauffmanFix negated equality double parens and stale nag test expectations
(3dd4e3b) ~John KauffmanFix tests
(f9550bf) ~John KauffmanFix multiple phrase trigger
(adec5da) ~John KauffmanFix import multiple phrases
- Phrase-specific clear-variable (actionType 7) creates VariableAction
(46943c2) ~John KauffmanNAG actionType 7 with a phraseId means 'when this specific phrase matches,
clear the variable'. Previously, all clear-variable actions were mapped to
EndTimerClearVariables, which only fires when a timer ends. For triggers
like 'Capture spell casting' where the clear action has no co-occurring
timer, EndTimerClearVariables would never fire — leaving SpellBeingCast
uncleared when a spell is interrupted.
- Skip blank template actions with missing actionType
(7ac14f3) ~John KauffmanNAG data contains empty template action objects with no actionType field
and all null/default values. These were falling through to the default
switch case and being logged as 'action type -1' dropped features,
causing valid triggers to be marked as Partial. Now skipped silently.
(c84aec8) ~John KauffmanFix variable format tests
(8b92d1e) ~John KauffmanFix MatchVariableCondition description to plain sentence form
Remove \n escape sequences that display literally in the UI. Keep
description as a single flowing sentence consistent with other
property grid descriptions.
(923536d) ~John KauffmanFix NAG pipe-separated contains conditions not matching
NAG uses pipe-separated values in contains conditions (e.g.
{SpellBeingCast} contains "Fireball|Flame Strike") to mean 'contains
any of'. But EQLP's contains operator does a literal substring check,
so the entire string 'Fireball|Flame Strike' was being searched for as
a single value — which never matches.
Fix: split on | and create separate contains clauses joined by ||,
e.g. {SpellBeingCast} contains "Fireball" || {SpellBeingCast} contains
"Flame Strike". Single values (no pipe) remain unchanged.
Updated existing test to use single value; added new test for
pipe-separated multi-value case.
(4b3372e) ~John KauffmanFix NAG trigger overlay assignments lost during import
Root cause: triggers were imported BEFORE overlays, so
ValidateOverlays() in TriggerStateDB.Import() found no matching
overlay nodes and stripped all SelectedOverlays references to [].
Fix: swap import order — call ImportNagOverlays() before
ImportTriggers() so that overlay nodes exist in the tree when
triggers are validated.
(9eba9aa) ~John KauffmanFix TextOverlayWrap not updating live when changed in property grid
The ValueChanged handler updates Application.Current.Resources for each
overlay property as the user edits it, but was missing a case for
TextOverlayWrap. This meant changing 'Text Wrap' in the property grid
updated the data model but didn't update the resource dictionary that
the TextBlocks are bound to via SetResourceReference.
Added noTextWrapItem.PropertyName case that updates
TextOverlayTextWrapping-{node.Id} resource and enables save button,
following the same pattern as fontFamilyItem, fontWeightItem, etc.
(76dafc7) ~John KauffmanFix TextOverlayWrap not updating when changed via property grid
Root cause: CreateBlock() set TextWrapping as a local value from
NoTextWrap, so changing it in the property grid didn't propagate to
existing TextBlocks. Other overlay properties (font family, size, etc.)
work because they use SetResourceReference with named resources that
get updated in Application.Current.Resources.
Fix:
- Rename NoTextWrap → TextOverlayWrap (default true = wrap enabled)
across data model, NagUtil parsing, TriggerUtil sync, property grid,
and tests
- Add TextOverlayTextWrapping-{node.Id} resource reference pattern
following the same approach as TextOverlayFontFamily etc.
- Set the resource in TriggerUtil.Copy() when loading/syncing overlays
- Use SetResourceReference(TextBlock.TextWrappingProperty, ...) in
CreateBlock() instead of direct local value assignment
- Rename property grid display from 'No Text Wrap' to 'Text Wrap'
(default on)
- Update NagUtil tests: NoTextWrap → TextOverlayWrap, assertions
inverted (nowrap → false, default → true)
(9a88fd8) ~John KauffmanFix backup filename showing 1.0.0 instead of real version
typeof(FileUtil).Assembly returns EQLogParser.Utils.dll (always 1.0.0)
instead of the main EQLP executable. Use Assembly.GetEntryAssembly() to
get the actual application assembly, falling back to typeof(FileUtil).Assembly
when null (e.g., in test contexts).
(5e255bc) ~John KauffmanFix NAG trigger folder hierarchy lost during import
ConvertTriggers returned a flat list of folder-wrapped nodes, but the
first Import() overload strips the top-level wrapper (designed for GINA's
single root node). This caused single-level folders like 'Orphaned Triggers'
to lose their folder entirely, and multi-level folders like 'Raids/...' to
lose their top-level 'Raids' parent.
Fix: wrap all NAG trigger nodes in a root ExportTriggerNode, consistent with
GINA's export format, so the first Import() correctly skips the root and
processes each folder/trigger node through the second Import() overload.
(49d4395) ~John KauffmanFix NAG overlay imports being silently skipped
ConvertOverlays returns flat leaf nodes (OverlayData, no child Nodes),
but the first Import() overload only recursed into nodes with child Nodes.
Added else-if branch to process overlay leaf nodes directly via the second
Import() overload which handles OverlayData.
(885d39e) ~John KauffmanFix import boolean NAG
(caf6a57) ~John KauffmanFix for correcting missing path
(0588b01) ~John KauffmanFix to avoid opening file chooser when selecting file programatically
(d847fdf) ~John KauffmanFix test
(846ebd7) ~John KauffmanFix alt timername and custom variables
(e6313bd) ~John KauffmanFix style issues and improved locking
(b683819) ~John KauffmanFix trigger tester
(3cd8171) ~John KauffmanFix tests
(e74f100) ~John KauffmanFix typo
(641efa0) ~John KauffmanFix resource leak and added tests
(2b714f0) ~John KauffmanFix for end clear variable not saving
(cbc3219) ~John KauffmanFix description for end clear variables
(a587729) ~John KauffmanFix formatting
(dbdd7ab) ~John KauffmanFix variable TTS related to timeout
(de2dad7) ~John KauffmanFix variable expiration
(e6d5f50) ~John KauffmanFix loading variable settings
(ae1e351) ~John KauffmanFixed matches variable validator
(ef6f33b) ~John KauffmanFix for text value being cut short
(c29c418) ~John KauffmanFix event handling and more UI updates
Documentation
(03437d1) ~John KauffmanDoc updates
(0b13cb6) ~John KauffmanDoc updates
(7a04dd4) ~John KauffmanDoc updates
Performance
(81d9d24) ~John KauffmanPerformance cleanup
(9aa7e9c) ~John KauffmanPerformance updates for variables
Styling
(2476c7f) ~John KauffmanStyle cleanup
Testing
(9160985) ~John KauffmanTest updates
(458b326) ~John KauffmanTest fixes
(6d7332b) ~John KauffmanTest updates
Commits
(3b5b72f) ~John KauffmanV2.3.60
(b8ed54c) ~John KauffmanHide tree expander gutter when there are no folders
(e8e6c0b) ~John KauffmanAdd vertical breathing room around character toolbar buttons
(18cf670) ~John KauffmanMatch manage characters title bar to triggers height
(549a05e) ~John KauffmanSize manage characters header to its buttons
(73f9efa) ~John KauffmanApply character panel width on theme change
(62878f6) ~John KauffmanWiden character panel a bit more at large fonts
(a238de1) ~John KauffmanUnify toolbar button heights and zero new button padding
(0d395f4) ~John KauffmanWiden character panel at large font sizes
(5fa204f) ~John KauffmanHide new button icon and tighten button row spacing
(5d49c53) ~John KauffmanMake toolbar new dropdown always create at top level
(bb8b2d8) ~John KauffmanReplace character add button with new dropdown
(ab80d31) ~John KauffmanWrite character status onto live tree instances
(c235ee7) ~John KauffmanUse warning icon and unquoted name in delete confirmations
(6d68d7f) ~John KauffmanSync character folder checkboxes with child states
(490e806) ~John KauffmanRevert "shrink message window for short text"
This reverts commit commit # [099ec8b](https://github.com/kauffman12/EQLogParser/commit/099ec8b0d5e2c6fdb2e938a3b5f93982dd174925).
(06bee1e) ~John KauffmanFolder delete back to one line with warning icon
(7dc9853) ~John KauffmanPut folder delete note on its own line
(2c0c28f) ~John KauffmanFolder delete message says contents move to parent
(58d5e44) ~John KauffmanTighten folder delete contents wording
(72dd6d9) ~John KauffmanDrop folder word from delete confirmation
(099ec8b) ~John KauffmanShrink message window for short text
(1fb0f29) ~John KauffmanMatch delete confirmations to app wording and question icon
(50dbd8b) ~John KauffmanReplace character toolbar with compact regular buttons
(33ce076) ~John KauffmanFrame manage characters panel like triggers view header
(9b896eb) ~John KauffmanRevert "give character tree context menus an elevated surface"
This reverts commit commit # [4ba5a82](https://github.com/kauffman12/EQLogParser/commit/4ba5a820333b82e00860ff3df6b8d8f43aa01fa3).
(4ba5a82) ~John KauffmanGive character tree context menus an elevated surface
(c481535) ~John KauffmanAdd new character option to character tree context menus
(db15e27) ~John KauffmanRemoved null annotation
(22a3962) ~John KauffmanStop importing nag text duration as countdown
(61a93fb) ~John KauffmanNag import fixes for operators, case sensitivity and drop notes
(a6b3ab3) ~John KauffmanAdd character folder system and f2 root-rename guard
(eaeb128) ~John KauffmanLatest
(2e29457) ~John KauffmanNag fixes
(920c261) ~John KauffmanNag improvements
(ad31f3a) ~John KauffmanUpdated migrate nag database menu
(4c164e6) ~John KauffmanMore updates to triggers with multiple capture phrases
(ea3463a) ~John KauffmanCode cleanup
(5a23a37) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(339a461) ~John KauffmanMore test updates
(4ed885d) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(b72fb75) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(1a60c1a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(677e40a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(3e93e2d) ~John KauffmanMoved import NAG DB feature
(a82845a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(d0f20c2) ~John KauffmanAdded fallback for phrase actions
(ac072aa) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(5c6158c) ~John KauffmanCleanup
(38f08ae) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(5d08038) ~John KauffmanImplent nag conunters
(3f31cfd) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(7b211f3) ~John KauffmanAdded unit tests for import from nag
(0bb0d16) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(a7014ba) ~John KauffmanAdd user-friendly descriptions for dropped features in HTML report
Replace cryptic feature names like 'set variable (BrdEpic1.5Caster)'
with plain-language explanations:
- set variable: explains that EQLP requires regex named groups
instead, and the trigger still works but stored values may be empty
- class level filtering: explains EQLP doesn't support this
- Other features fall back to their original name
This makes the Partial status reason column much more useful for
users who don't know NAG internals.
(3c25f95) ~John KauffmanInclude variable name in dropped feature reason for unsupported actions
When an action type like 'set variable' (type 5) is dropped, include
the variable name in the reason string so users can identify which
specific variable was involved. E.g. 'set variable (BrdEpic1.5Caster)'
instead of just 'set variable'.
(d0c5da4) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(c098160) ~John KauffmanMap NAG clear variable actions to EndTimerClearVariables
NAG actionType 7 ('clear variable') was being dropped as an unsupported
feature, marking triggers as Partial. EQLP already supports clearing
variables when a timer ends via the EndTimerClearVariables field.
Now maps actionType 7's variableName directly to EndTimerClearVariables,
so triggers like 'Vainglorious Shout VIII' that clear SpellBeingCast
on timer end will work correctly instead of being marked Partial.
Added test: ConvertTriggers_ActionType7_ClearVariable_MappedToEndTimerClearVariables
(952ca5b) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(9d8e1fa) ~John KauffmanMark triggers with missing audio files as Partial instead of Imported
Triggers that import successfully but reference sound files not found
on disk should be 'Partial' (imported but incomplete), not 'Imported'.
This surfaces them in the HTML report's status sorting (Skipped →
Partial → Success) so users notice they need to locate the missing
files. Also adds a reason string listing the count of missing files.
(f827ee2) ~John KauffmanSimplify NAG import report filename and dialog label
- Rename HTML report from 'eqlp-import-report-yyyy-MM-dd_HH-mm-ss.html'
to just 'nag-import.html' in the log directory. The timestamped name
was unnecessarily long; a simple fixed name is cleaner.
- Change import dialog heading from 'Detailed HTML Report:' to 'Report:'
(9c47a5f) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(b070ce6) ~John KauffmanCleanup NAG import dialog and highlight missing audio files
- Remove the list of missing audio files from the import dialog.
People can check the HTML report for that info. This keeps the
dialog concise instead of wasting space with potentially dozens
of file paths.
- Change missing audio file styling in HTML report from grey
(#999) to bold red (#b71c1c) so they stand out as issues.
(05ada98) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(de1ef31) ~John KauffmanCleanup MatchVariableCondition description in triggers view
The old description was 556 chars with excessive syntax documentation,
operator lists, and literal \n sequences that showed as text in the UI.
Replaced with a brief description plus concise examples using == and >,
and a pointer to the documentation.
(69587e1) ~John KauffmanMap NAG timerBackgroundColor to EQLP IdleColor
NAG timer overlays have separate colors for the active portion
(timerColor) and the background/track (timerBackgroundColor), but
only timerColor was being mapped. The timer bar track defaulted to
red (#FF8f1515) instead of the NAG-specified color.
Now maps timerBackgroundColor → IdleColor, preserving the original
dark brown (rgba(67,62,16,0.75)) for overlays like 'Quickies'.
(c1b24b5) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(eff63fa) ~John KauffmanShorten NAG folder dialog description to prevent text wrapping
The FolderBrowserDialog wraps long descriptions awkwardly (every few
words). Shortened from 'Select the directory containing the NAG database
files (overlays-database.json, etc.)' to 'Select the directory containing
your NAG database files.'
(f2e04c6) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(d5ec8cf) ~John KauffmanSimplify NAG import progress dialog text
(ff1d88c) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(9fb914a) ~John KauffmanDark theme + sort HTML report by status, rename Imported to Success
- Apply dark theme CSS (VS-style) to HTML import report:
dark backgrounds (#1e1e1e, #2d2d2d), cyan headers (#4fc3f7),
adjusted badge colors for dark mode readability
- Sort report rows by status: Skipped first, then Partial, then Success
- Rename 'Imported' to 'Success' in report display text (badge labels and
summary stats); internal Status values remain unchanged
- Add WriteImportReportHtml_ResultsSortedByStatus_SkippedFirst test verifying
sort order
- Update existing HTML tests: check for 'Success' instead of 'Imported',
verify dark theme CSS is present
(04428be) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(829476a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(694cfad) ~John KauffmanStore HTML import report in log directory with timestamp + add Open Report button
- Save HTML report only in the EQLP log directory (same dir as error log),
not in the NAG database directory, to avoid polluting user data
- Timestamped filename: eqlp-import-report-yyyy-MM-dd_HH-mm-ss.html
- Added GetLogDirectory() helper that reads the log4net FileAppender path
- Added 'Open Report' button to the NAG Import Complete dialog that opens
the HTML report in the default web browser
(75d8857) ~John KauffmanRemove CSV import report, keep HTML only
The CSV report (WriteImportReport + EscapeCsv) had no external consumers
and the HTML report is strictly more capable. Removed from NagUtil.cs
and TriggerUtil.cs; updated tests to use WriteImportReportHtml instead.
(3f0bc19) ~John KauffmanUpdate NagUtil tests for comment format + add HTML report tests
- Update ConvertTriggers_Comments_PreservedInNagComment to assert that
'Original:' prefix is NOT present (removed in commit # [3b09528](https://github.com/kauffman12/EQLogParser/commit/3b09528a))
- Update ConvertTriggers_DroppedFeatures_ListedInComment to check for
'EQLP Import Notes:' instead of 'Dropped:' (renamed in commit # [3b09528](https://github.com/kauffman12/EQLogParser/commit/3b09528a))
- Add WriteImportReportHtml_ValidResults_CreatesHtml — verifies HTML
structure, summary stats, trigger names, folder paths, missing audio
files, and badge CSS classes
- Add WriteImportReportHtml_EmptyResults_CreatesHtml — verifies graceful
handling of empty results list
- Add WriteImportReportHtml_SpecialCharacters_AreHtmlEncoded — verifies
HTML encoding of < > & characters in trigger names
- Add WriteImportReportHtml_RootFolder_ShowsEmRoot — verifies root folder
path displays as <em>(root)</em>
(860c6ba) ~John KauffmanAdd HTML import report alongside CSV
Adds WriteImportReportHtml() which generates a styled HTML report with
summary stats (imported/partial/skipped counts), color-coded status badges,
folder path display, and expandable missing audio file listings. The
report is generated as eqlp-import-report.html in the NAG database
directory, and both paths are shown in the import summary dialog.
(08d0832) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(e212238) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(0d106b9) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(846b6a1) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(3b09528) ~John KauffmanChanged import item
(d2410c2) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(610503a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(53f85ab) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(636aa1a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(398d946) ~John KauffmanMerge branch 'master' into develop
(4cc3784) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(7d2acc6) ~John KauffmanUpdated custom audio selection
(162697d) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(cabf1c1) ~John KauffmanCode cleanup
(65206d3) ~John KauffmanHandle custom audio files
(4487022) ~John KauffmanImport nag v1
(c53623e) ~John Kauffman2.3.58
(a37882a) ~John KauffmanUpdate timer variable performance
(9b5c077) ~John KauffmanResolve _variables last and make timer updates for them dynamic
(25e66c5) ~John Kauffman2.3.57
(2f282ac) ~John KauffmanAdded trigger variables
(cf53fde) ~John KauffmanReview fixes
(9df3f06) ~John KauffmanUpdated dialog and docs
(fc5032d) ~John KauffmanCleanup
(2957fd5) ~John KauffmanBug fixes
(c756dac) ~John KauffmanAdded progress dialog for import
(d588a5d) ~John KauffmanCleanup
(974ad5d) ~John KauffmanAdded variable clear when timer ends
(c2ad0a1) ~John KauffmanAdded command to clear variables
(07af1fc) ~John KauffmanChanged to Fixed
(21bb950) ~John KauffmanRenamed Value option
(dbbaf7b) ~John KauffmanChanged internal types to number
(808f8b3) ~John KauffmanRenamed Text to Value
(4836f14) ~John KauffmanUpdated docs
(f050ff3) ~John KauffmanMade variable condition validation smarter
(792a793) ~John KauffmanAdd validation for match variables field
(5dcfb57) ~John KauffmanCleanup
(e4e6dec) ~John KauffmanAdded trigger variables
(3deff69) ~John KauffmanUpdated tab names and fixes
(5925a72) ~John KauffmanAdded TTL to variables and updated style
(41e3a04) ~John KauffmanUI cleanup and model updates
(562f50d) ~John KauffmanUI update for variables tab on trigger properties
(0ceb2c0) ~John KauffmanV2.3.56
(d2ff09a) ~John KauffmanV2.3.55
(be43d92) ~John KauffmanExpand all levels
(9600886) ~John KauffmanHandle days when displaying timer
(f6b5ff2) ~John KauffmanMerge branch 'master' into picode
(8e929e8) ~kauffman12PR # [392](https://github.com/kauffman12/EQLogParser/pull/392): text/timer overlay backgrounds rendering black on Wayland/Wine
(ef09d57) ~John KauffmanExtend {ts} labeled formats, add tree grid expand/collapse, and broaden trigger search
- Support labeled time formats in {ts} trigger tag (e.g. 4h:20m:53s, 1d:10h:20m:50s)
with optional components and flexible ordering. Update UpdateTimePattern regex
and refactor SimpleTimeToSeconds to detect and parse d/h/m/s suffixes.
- Add "Expand All" and "Collapse All" context menu items to all SfTreeGrid views
(Damage/Healing/Tanking Breakdown, Damage Summary, Taunt Stats, Random Viewer).
Commands are enabled only on SfTreeGrid targets with nodes.
- Extend trigger search to match against Comments, PreviousPattern,
EndEarlyPattern (1-3), and AltTimerName in addition to Name and Pattern.
(ee7cdf8) ~John KauffmanMerge branch 'master' into picode
(16d351a) ~stvsuFix text/timer overlay backgrounds rendering black on Wayland/Wine
The text and timer overlays are AllowsTransparency windows that fill their
background and border with a fully-transparent brush (#00000000, alpha 0).
On wlroots-based Wayland compositors (e.g. Hyprland) running under Wine/Proton,
fully-transparent regions are not alpha-blended and render as opaque black,
while areas covered by drawn content (timer bars, text) composite correctly.
Windows and KDE/KWin are not affected.
Give the background and border a minimal non-zero alpha (#01000000, 1/255) so
the whole surface goes through the normal blend path. The change is visually
imperceptible and produces identical output on Windows and KDE.
(8a78009) ~kauffman12PR # [389](https://github.com/kauffman12/EQLogParser/pull/389): Add support for 'cleave' 'reave' and 'smite' for DPS parser
Bug Fixes
(223c1ba) ~John KauffmanFix stale action type 6 label (dottimer) in nag docs and comment
(62210d8) ~John KauffmanFix negated equality double parens and stale nag test expectations
Commits
(ea9b623) ~John KauffmanV2.3.60
(9e2ebf3) ~John KauffmanHide tree expander gutter when there are no folders
(3eee461) ~John KauffmanAdd vertical breathing room around character toolbar buttons
(996724a) ~John KauffmanMatch manage characters title bar to triggers height
(6d3e9e5) ~John KauffmanSize manage characters header to its buttons
(b58dba9) ~John KauffmanApply character panel width on theme change
(cc4f8ff) ~John KauffmanWiden character panel a bit more at large fonts
(0a2623e) ~John KauffmanUnify toolbar button heights and zero new button padding
(3b73362) ~John KauffmanWiden character panel at large font sizes
(6df6070) ~John KauffmanHide new button icon and tighten button row spacing
(69ff2a4) ~John KauffmanMake toolbar new dropdown always create at top level
(ea5ff6f) ~John KauffmanReplace character add button with new dropdown
(c41fa25) ~John KauffmanWrite character status onto live tree instances
(c501275) ~John KauffmanUse warning icon and unquoted name in delete confirmations
(0ec1788) ~John KauffmanSync character folder checkboxes with child states
(57014de) ~John KauffmanRevert "shrink message window for short text"
This reverts commit commit # [6eddaf7](https://github.com/kauffman12/EQLogParser/commit/6eddaf77d513e98490241635fdd4462cc8115a42).
(762b2eb) ~John KauffmanFolder delete back to one line with warning icon
(79c817b) ~John KauffmanPut folder delete note on its own line
(08f8e55) ~John KauffmanFolder delete message says contents move to parent
(9aa9b0d) ~John KauffmanTighten folder delete contents wording
(bc142c8) ~John KauffmanDrop folder word from delete confirmation
(6eddaf7) ~John KauffmanShrink message window for short text
(9f6fdc9) ~John KauffmanMatch delete confirmations to app wording and question icon
(4671b4f) ~John KauffmanReplace character toolbar with compact regular buttons
(c8ce6c0) ~John KauffmanFrame manage characters panel like triggers view header
(4e56a7c) ~John KauffmanRevert "give character tree context menus an elevated surface"
This reverts commit commit # [7009a04](https://github.com/kauffman12/EQLogParser/commit/7009a0444d05e043dc87777f87d83b4b9d23bdb4).
(7009a04) ~John KauffmanGive character tree context menus an elevated surface
(d2dd30f) ~John KauffmanAdd new character option to character tree context menus
(a1b92a9) ~John KauffmanRemoved null annotation
(cbf11f2) ~John KauffmanStop importing nag text duration as countdown
(5372ef7) ~John KauffmanNag import fixes for operators, case sensitivity and drop notes
(7afeb84) ~John KauffmanAdd character folder system and f2 root-rename guard
Bug Fixes
(88f9ca1) ~John KauffmanFix tests
(cbd56ed) ~John KauffmanFix multiple phrase trigger
(a64b5e7) ~John KauffmanFix import multiple phrases
- Phrase-specific clear-variable (actionType 7) creates VariableAction
(735842c) ~John KauffmanNAG actionType 7 with a phraseId means 'when this specific phrase matches,
clear the variable'. Previously, all clear-variable actions were mapped to
EndTimerClearVariables, which only fires when a timer ends. For triggers
like 'Capture spell casting' where the clear action has no co-occurring
timer, EndTimerClearVariables would never fire — leaving SpellBeingCast
uncleared when a spell is interrupted.
- Skip blank template actions with missing actionType
(80670fd) ~John KauffmanNAG data contains empty template action objects with no actionType field
and all null/default values. These were falling through to the default
switch case and being logged as 'action type -1' dropped features,
causing valid triggers to be marked as Partial. Now skipped silently.
(305f0ab) ~John KauffmanFix variable format tests
(ad914e5) ~John KauffmanFix MatchVariableCondition description to plain sentence form
Remove \n escape sequences that display literally in the UI. Keep
description as a single flowing sentence consistent with other
property grid descriptions.
(4c16c94) ~John KauffmanFix NAG pipe-separated contains conditions not matching
NAG uses pipe-separated values in contains conditions (e.g.
{SpellBeingCast} contains "Fireball|Flame Strike") to mean 'contains
any of'. But EQLP's contains operator does a literal substring check,
so the entire string 'Fireball|Flame Strike' was being searched for as
a single value — which never matches.
Fix: split on | and create separate contains clauses joined by ||,
e.g. {SpellBeingCast} contains "Fireball" || {SpellBeingCast} contains
"Flame Strike". Single values (no pipe) remain unchanged.
Updated existing test to use single value; added new test for
pipe-separated multi-value case.
(c35d4ff) ~John KauffmanFix NAG trigger overlay assignments lost during import
Root cause: triggers were imported BEFORE overlays, so
ValidateOverlays() in TriggerStateDB.Import() found no matching
overlay nodes and stripped all SelectedOverlays references to [].
Fix: swap import order — call ImportNagOverlays() before
ImportTriggers() so that overlay nodes exist in the tree when
triggers are validated.
(456f9cb) ~John KauffmanFix TextOverlayWrap not updating live when changed in property grid
The ValueChanged handler updates Application.Current.Resources for each
overlay property as the user edits it, but was missing a case for
TextOverlayWrap. This meant changing 'Text Wrap' in the property grid
updated the data model but didn't update the resource dictionary that
the TextBlocks are bound to via SetResourceReference.
Added noTextWrapItem.PropertyName case that updates
TextOverlayTextWrapping-{node.Id} resource and enables save button,
following the same pattern as fontFamilyItem, fontWeightItem, etc.
(5fd7e9b) ~John KauffmanFix TextOverlayWrap not updating when changed via property grid
Root cause: CreateBlock() set TextWrapping as a local value from
NoTextWrap, so changing it in the property grid didn't propagate to
existing TextBlocks. Other overlay properties (font family, size, etc.)
work because they use SetResourceReference with named resources that
get updated in Application.Current.Resources.
Fix:
- Rename NoTextWrap → TextOverlayWrap (default true = wrap enabled)
across data model, NagUtil parsing, TriggerUtil sync, property grid,
and tests
- Add TextOverlayTextWrapping-{node.Id} resource reference pattern
following the same approach as TextOverlayFontFamily etc.
- Set the resource in TriggerUtil.Copy() when loading/syncing overlays
- Use SetResourceReference(TextBlock.TextWrappingProperty, ...) in
CreateBlock() instead of direct local value assignment
- Rename property grid display from 'No Text Wrap' to 'Text Wrap'
(default on)
- Update NagUtil tests: NoTextWrap → TextOverlayWrap, assertions
inverted (nowrap → false, default → true)
(74495bb) ~John KauffmanFix backup filename showing 1.0.0 instead of real version
typeof(FileUtil).Assembly returns EQLogParser.Utils.dll (always 1.0.0)
instead of the main EQLP executable. Use Assembly.GetEntryAssembly() to
get the actual application assembly, falling back to typeof(FileUtil).Assembly
when null (e.g., in test contexts).
(4778814) ~John KauffmanFix NAG trigger folder hierarchy lost during import
ConvertTriggers returned a flat list of folder-wrapped nodes, but the
first Import() overload strips the top-level wrapper (designed for GINA's
single root node). This caused single-level folders like 'Orphaned Triggers'
to lose their folder entirely, and multi-level folders like 'Raids/...' to
lose their top-level 'Raids' parent.
Fix: wrap all NAG trigger nodes in a root ExportTriggerNode, consistent with
GINA's export format, so the first Import() correctly skips the root and
processes each folder/trigger node through the second Import() overload.
(9c8668c) ~John KauffmanFix NAG overlay imports being silently skipped
ConvertOverlays returns flat leaf nodes (OverlayData, no child Nodes),
but the first Import() overload only recursed into nodes with child Nodes.
Added else-if branch to process overlay leaf nodes directly via the second
Import() overload which handles OverlayData.
(5bbcb01) ~John KauffmanFix import boolean NAG
(1a766f2) ~John KauffmanFix for correcting missing path
(d06c203) ~John KauffmanFix to avoid opening file chooser when selecting file programatically
Documentation
(0b47b5d) ~John KauffmanDoc updates
(32976fc) ~John KauffmanDoc updates
(02e9027) ~John KauffmanDoc updates
Testing
(c440e78) ~John KauffmanTest updates
(f8924a4) ~John KauffmanTest fixes
(c12d4d8) ~John KauffmanTest updates
Commits
(8188587) ~John KauffmanLatest
(28c9550) ~John KauffmanNag fixes
(44b1b45) ~John KauffmanNag improvements
(5ad4a8f) ~John KauffmanUpdated migrate nag database menu
(c2e39dc) ~John KauffmanMore updates to triggers with multiple capture phrases
(66af5be) ~John KauffmanCode cleanup
(bbdaf7f) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(a31d7e7) ~John KauffmanMore test updates
(e02ee6c) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(2e37f87) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(d3061b3) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(9beb805) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(0ebd0e3) ~John KauffmanMoved import NAG DB feature
(2a4eaf4) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(4a3b4e3) ~John KauffmanAdded fallback for phrase actions
(685f960) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(6594de1) ~John KauffmanCleanup
(e7de56c) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(ec41d64) ~John KauffmanImplent nag conunters
(47ff80a) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(952d75e) ~John KauffmanAdded unit tests for import from nag
(1e6e7d3) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(b433d95) ~John KauffmanAdd user-friendly descriptions for dropped features in HTML report
Replace cryptic feature names like 'set variable (BrdEpic1.5Caster)'
with plain-language explanations:
- set variable: explains that EQLP requires regex named groups
instead, and the trigger still works but stored values may be empty
- class level filtering: explains EQLP doesn't support this
- Other features fall back to their original name
This makes the Partial status reason column much more useful for
users who don't know NAG internals.
(55be2bf) ~John KauffmanInclude variable name in dropped feature reason for unsupported actions
When an action type like 'set variable' (type 5) is dropped, include
the variable name in the reason string so users can identify which
specific variable was involved. E.g. 'set variable (BrdEpic1.5Caster)'
instead of just 'set variable'.
(ddbf4e7) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(4074ce3) ~John KauffmanMap NAG clear variable actions to EndTimerClearVariables
NAG actionType 7 ('clear variable') was being dropped as an unsupported
feature, marking triggers as Partial. EQLP already supports clearing
variables when a timer ends via the EndTimerClearVariables field.
Now maps actionType 7's variableName directly to EndTimerClearVariables,
so triggers like 'Vainglorious Shout VIII' that clear SpellBeingCast
on timer end will work correctly instead of being marked Partial.
Added test: ConvertTriggers_ActionType7_ClearVariable_MappedToEndTimerClearVariables
(9114585) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(712682f) ~John KauffmanMark triggers with missing audio files as Partial instead of Imported
Triggers that import successfully but reference sound files not found
on disk should be 'Partial' (imported but incomplete), not 'Imported'.
This surfaces them in the HTML report's status sorting (Skipped →
Partial → Success) so users notice they need to locate the missing
files. Also adds a reason string listing the count of missing files.
(514ffe7) ~John KauffmanSimplify NAG import report filename and dialog label
- Rename HTML report from 'eqlp-import-report-yyyy-MM-dd_HH-mm-ss.html'
to just 'nag-import.html' in the log directory. The timestamped name
was unnecessarily long; a simple fixed name is cleaner.
- Change import dialog heading from 'Detailed HTML Report:' to 'Report:'
(264ffaa) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(0b14879) ~John KauffmanCleanup NAG import dialog and highlight missing audio files
- Remove the list of missing audio files from the import dialog.
People can check the HTML report for that info. This keeps the
dialog concise instead of wasting space with potentially dozens
of file paths.
- Change missing audio file styling in HTML report from grey
(#999) to bold red (#b71c1c) so they stand out as issues.
(2b23de7) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(dc6807a) ~John KauffmanCleanup MatchVariableCondition description in triggers view
The old description was 556 chars with excessive syntax documentation,
operator lists, and literal \n sequences that showed as text in the UI.
Replaced with a brief description plus concise examples using == and >,
and a pointer to the documentation.
(04e70d7) ~John KauffmanMap NAG timerBackgroundColor to EQLP IdleColor
NAG timer overlays have separate colors for the active portion
(timerColor) and the background/track (timerBackgroundColor), but
only timerColor was being mapped. The timer bar track defaulted to
red (#FF8f1515) instead of the NAG-specified color.
Now maps timerBackgroundColor → IdleColor, preserving the original
dark brown (rgba(67,62,16,0.75)) for overlays like 'Quickies'.
(5b4d39e) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(ed2e479) ~John KauffmanShorten NAG folder dialog description to prevent text wrapping
The FolderBrowserDialog wraps long descriptions awkwardly (every few
words). Shortened from 'Select the directory containing the NAG database
files (overlays-database.json, etc.)' to 'Select the directory containing
your NAG database files.'
(df75bd9) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(56f6b39) ~John KauffmanSimplify NAG import progress dialog text
(f682441) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(b93a52d) ~John KauffmanDark theme + sort HTML report by status, rename Imported to Success
- Apply dark theme CSS (VS-style) to HTML import report:
dark backgrounds (#1e1e1e, #2d2d2d), cyan headers (#4fc3f7),
adjusted badge colors for dark mode readability
- Sort report rows by status: Skipped first, then Partial, then Success
- Rename 'Imported' to 'Success' in report display text (badge labels and
summary stats); internal Status values remain unchanged
- Add WriteImportReportHtml_ResultsSortedByStatus_SkippedFirst test verifying
sort order
- Update existing HTML tests: check for 'Success' instead of 'Imported',
verify dark theme CSS is present
(56c18cd) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(14d96e5) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(cda38fd) ~John KauffmanStore HTML import report in log directory with timestamp + add Open Report button
- Save HTML report only in the EQLP log directory (same dir as error log),
not in the NAG database directory, to avoid polluting user data
- Timestamped filename: eqlp-import-report-yyyy-MM-dd_HH-mm-ss.html
- Added GetLogDirectory() helper that reads the log4net FileAppender path
- Added 'Open Report' button to the NAG Import Complete dialog that opens
the HTML report in the default web browser
(3af0dc3) ~John KauffmanRemove CSV import report, keep HTML only
The CSV report (WriteImportReport + EscapeCsv) had no external consumers
and the HTML report is strictly more capable. Removed from NagUtil.cs
and TriggerUtil.cs; updated tests to use WriteImportReportHtml instead.
(8eaa9b6) ~John KauffmanUpdate NagUtil tests for comment format + add HTML report tests
- Update ConvertTriggers_Comments_PreservedInNagComment to assert that
'Original:' prefix is NOT present (removed in commit # [a63cce8](https://github.com/kauffman12/EQLogParser/commit/a63cce81))
- Update ConvertTriggers_DroppedFeatures_ListedInComment to check for
'EQLP Import Notes:' instead of 'Dropped:' (renamed in commit # [a63cce8](https://github.com/kauffman12/EQLogParser/commit/a63cce81))
- Add WriteImportReportHtml_ValidResults_CreatesHtml — verifies HTML
structure, summary stats, trigger names, folder paths, missing audio
files, and badge CSS classes
- Add WriteImportReportHtml_EmptyResults_CreatesHtml — verifies graceful
handling of empty results list
- Add WriteImportReportHtml_SpecialCharacters_AreHtmlEncoded — verifies
HTML encoding of < > & characters in trigger names
- Add WriteImportReportHtml_RootFolder_ShowsEmRoot — verifies root folder
path displays as <em>(root)</em>
(a39e8a5) ~John KauffmanAdd HTML import report alongside CSV
Adds WriteImportReportHtml() which generates a styled HTML report with
summary stats (imported/partial/skipped counts), color-coded status badges,
folder path display, and expandable missing audio file listings. The
report is generated as eqlp-import-report.html in the NAG database
directory, and both paths are shown in the import summary dialog.
(823d38c) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(85be2a4) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(d2c76fe) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(e885ed8) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(a63cce8) ~John KauffmanChanged import item
(72f9940) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(5f9f08f) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(f6f3678) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(868cff0) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(409f91b) ~John KauffmanMerge branch 'master' into develop
(46b8f52) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(3e7798f) ~John KauffmanUpdated custom audio selection
(b5e47f0) ~John KauffmanMerge branch 'develop' of https://github.com/kauffman12/EQLogParser into develop
(9b91446) ~John KauffmanCode cleanup
(eaf3e65) ~John KauffmanHandle custom audio files
(87ccb1d) ~John KauffmanImport nag v1
Bug Fixes
(8d56774) ~John KauffmanFix style issues and improved locking
(1ae4d79) ~John KauffmanFix trigger tester
(1cc590a) ~John KauffmanFix tests
(c3497dd) ~John KauffmanFix typo
(3da4357) ~John KauffmanFix resource leak and added tests
(d221dc0) ~John KauffmanFix for end clear variable not saving
(09c7846) ~John KauffmanFix description for end clear variables
(4e013d4) ~John KauffmanFix formatting
(7f01478) ~John KauffmanFix variable TTS related to timeout
(8f0cf23) ~John KauffmanFix variable expiration
(1ad5552) ~John KauffmanFix loading variable settings
(a59c0a0) ~John KauffmanFixed matches variable validator
(256bc20) ~John KauffmanFix for text value being cut short
(dc200b3) ~John KauffmanFix event handling and more UI updates
Performance
(1bc54e2) ~John KauffmanPerformance cleanup
(4f94b98) ~John KauffmanPerformance updates for variables
Styling
(8c04b58) ~John KauffmanStyle cleanup
Commits
(d2ecd7a) ~John Kauffman2.3.57
(f04f901) ~John KauffmanAdded trigger variables
(4560fe1) ~John KauffmanReview fixes
(feee4b3) ~John KauffmanUpdated dialog and docs
(a53d887) ~John KauffmanCleanup
(552de1f) ~John KauffmanBug fixes
(7785320) ~John KauffmanAdded progress dialog for import
(427692f) ~John KauffmanCleanup
(4a1a023) ~John KauffmanAdded variable clear when timer ends
(d191895) ~John KauffmanAdded command to clear variables
(b803939) ~John KauffmanChanged to Fixed
(82e7080) ~John KauffmanRenamed Value option
(3e24ce3) ~John KauffmanChanged internal types to number
(91190be) ~John KauffmanRenamed Text to Value
(47c0aa9) ~John KauffmanUpdated docs
(5cd4213) ~John KauffmanMade variable condition validation smarter
(22798ba) ~John KauffmanAdd validation for match variables field
(154d3d4) ~John KauffmanCleanup
(3503187) ~John KauffmanAdded trigger variables
(42c4cf8) ~John KauffmanUpdated tab names and fixes
(5954d52) ~John KauffmanAdded TTL to variables and updated style
(da52c33) ~John KauffmanUI cleanup and model updates
(65ca6c4) ~John KauffmanUI update for variables tab on trigger properties
Bug Fixes
(c219c16) ~John KauffmanFix tests
Commits
(0227f3c) ~John KauffmanV2.3.55
(fda2354) ~John KauffmanExpand all levels
(16e0d8c) ~John KauffmanHandle days when displaying timer
(ed30a2d) ~John KauffmanMerge branch 'master' into picode
(2f4391e) ~kauffman12PR # [392](https://github.com/kauffman12/EQLogParser/pull/392): text/timer overlay backgrounds rendering black on Wayland/Wine
(6936d5b) ~John KauffmanExtend {ts} labeled formats, add tree grid expand/collapse, and broaden trigger search
- Support labeled time formats in {ts} trigger tag (e.g. 4h:20m:53s, 1d:10h:20m:50s)
with optional components and flexible ordering. Update UpdateTimePattern regex
and refactor SimpleTimeToSeconds to detect and parse d/h/m/s suffixes.
- Add "Expand All" and "Collapse All" context menu items to all SfTreeGrid views
(Damage/Healing/Tanking Breakdown, Damage Summary, Taunt Stats, Random Viewer).
Commands are enabled only on SfTreeGrid targets with nodes.
- Extend trigger search to match against Comments, PreviousPattern,
EndEarlyPattern (1-3), and AltTimerName in addition to Name and Pattern.
(9051155) ~John KauffmanMerge branch 'master' into picode
(c4fa0b1) ~John KauffmanConsolidated safe file write
(8fec127) ~stvsuFix text/timer overlay backgrounds rendering black on Wayland/Wine
The text and timer overlays are AllowsTransparency windows that fill their
background and border with a fully-transparent brush (#00000000, alpha 0).
On wlroots-based Wayland compositors (e.g. Hyprland) running under Wine/Proton,
fully-transparent regions are not alpha-blended and render as opaque black,
while areas covered by drawn content (timer bars, text) composite correctly.
Windows and KDE/KWin are not affected.
Give the background and border a minimal non-zero alpha (#01000000, 1/255) so
the whole surface goes through the normal blend path. The change is visually
imperceptible and produces identical output on Windows and KDE.
(035bfa1) ~kauffman12PR # [389](https://github.com/kauffman12/EQLogParser/pull/389): Add support for 'cleave' 'reave' and 'smite' for DPS parser
- Add support for 'cleave' 'reave' and 'smite' for DPS parser
(bbcf45f) ~Cord B
(f9f6c51) ~John KauffmanRemoved unused interface
(a7122a4) ~John KauffmanUpdated install files list
(fc1751b) ~John KauffmanUpdate tests
(08dbdd8) ~John KauffmanPut iaction back
(1e0390f) ~John KauffmanUpdated tests
(4554849) ~John KauffmanLoad real spell data for tests
(5a2dca7) ~John KauffmanDamage and healing validator tests
(d108ea6) ~John KauffmanAdded tests and moved util classes to their own project
(1909420) ~John KauffmanChanged order or shutdown APIs
(08774fd) ~John KauffmanUpdated to use pattern matching
Bug Fixes
(cb31b97) ~John KauffmanFix deadlock
(535a007) ~John KauffmanFix priority for theme updates
(1d0f89a) ~John KauffmanFix default log list
(1dc161b) ~John KauffmanFix event cleanup
(b5c8b43) ~John KauffmanFix bugs
(1883dc4) ~John KauffmanFixes
(50c4738) ~John KauffmanFixes
(93bb67d) ~John KauffmanFix timer lock
(53ef049) ~John KauffmanFix bottles index
Commits
(6733be3) ~John KauffmanUpdate 2.3.54
(1dcee80) ~John KauffmanUpdated libraries
(cd78607) ~John KauffmanImprove handling of trigger log lists
(747c459) ~John KauffmanCleanup
(29a0ab6) ~John KauffmanClear logs from one spot
(0d23d52) ~John KauffmanUpdate timer usage
(e0bf067) ~John KauffmanChanged timer back to throttle/one shot
(32fb07d) ~John KauffmanRestrict possibly player name to not be unknown
(ba5aa23) ~John KauffmanCleanup timer lock
(e9bfee0) ~John KauffmanAdd verified player option
(f0e8e30) ~John KauffmanRenamed theme manager
(279a700) ~John KauffmanBreakup main actions
(9e158e5) ~John KauffmanBreakup main actions
(e549636) ~John KauffmanRemove cleanup of quickshares
(c53ac20) ~John KauffmanAdd trigger log manager to reduce ui dependence
(0a16ae2) ~John KauffmanUpdate for config util status
(184a9a3) ~John KauffmanRemove UI dependence
(de376b8) ~John KauffmanAdded a quick search manager
(9ee5af7) ~John Kauffman2.3.53 update
(30ac2e2) ~John KauffmanUpdate bottles info again
(b26e591) ~John KauffmanMerged v2.3.53
Bug Fixes
(18e247c) ~John KauffmanFix possibly cut/paste error and fixed player names from healing spells. added paddingleft, right, center to format options in triggers
(f71bc4b) ~John KauffmanFix bug
(d71f4d7) ~John KauffmanFixes
(4423448) ~John KauffmanFixes
(d6305d5) ~John KauffmanFix app cs
(353b3e3) ~John KauffmanFix formatting
(bace40c) ~John KauffmanFix formatting
(033d2fd) ~John KauffmanFix tests
(4006744) ~John KauffmanFix compiler warnings
(50e5b79) ~John KauffmanFix tests
(c8d8d92) ~John KauffmanFix events not being cleaned up
(fbaf1af) ~John KauffmanFix clipboard calls
(fc15365) ~John KauffmanFixes
(8e6dc1d) ~John KauffmanFixes for spell counts hopefully
(95e6bd0) ~John KauffmanFixes
(af91378) ~John KauffmanFixes
(17337d9) ~John KauffmanFix context menu
(f738a04) ~John KauffmanFix raid total percent for groups
(235f2ca) ~John KauffmanFix expanding
(7b08e5d) ~John KauffmanFixes
(f5ba754) ~John KauffmanFixes
(323b1ae) ~John KauffmanFixes
Performance
(dfa3194) ~John KauffmanPerf updates
Refactor
(bb76181) ~John KauffmanRefactor managers
Testing
(145e8a2) ~John KauffmanTest groupid sort
Commits
(c6408ae) ~John KauffmanUpdate docs for padleft/padright
(24f65b2) ~John KauffmanMerge branch 'develop'
(c574a9d) ~John KauffmanRemove generated files
(d5911f3) ~John KauffmanV2.3.52
(7691cf3) ~John KauffmanAdded chat db cleanup
(c1e2d39) ~John KauffmanRemove Linq from hotpaths
(44ea04e) ~John KauffmanUpdate to 2.3.51
(fb469ab) ~John KauffmanAdded group view, best sec for tanking, and lots of re-org
(2c84081) ~John KauffmanSquashed commit of the following:
commit commit # [09cbb47](https://github.com/kauffman12/EQLogParser/commit/09cbb47e77745efc6ca8ca36e64cd94c1c7210cb)
Author: John Kauffman <[email protected]>
Date: Thu Apr 23 16:03:22 2026 -0400
remove id
commit commit # [5474050](https://github.com/kauffman12/EQLogParser/commit/5474050ca7b32310a26424bbce3a1d0e0a37cd29)
Merge: commit # [8f44970](https://github.com/kauffman12/EQLogParser/commit/8f449707) commit # [eb824dd](https://github.com/kauffman12/EQLogParser/commit/eb824dd7)
Author: John Kauffman <[email protected]>
Date: Thu Apr 23 15:56:18 2026 -0400
Merge branch 'master' into opencode2
commit commit # [8f44970](https://github.com/kauffman12/EQLogParser/commit/8f449707f85e959c6c630db422e70036ae20d000)
Author: John Kauffman <[email protected]>
Date: Thu Apr 23 15:52:48 2026 -0400
fix warnings
commit commit # [df8bc21](https://github.com/kauffman12/EQLogParser/commit/df8bc2184573a8b0d3e7c9de2ca4968b751c70b2)
Merge: commit # [45fe494](https://github.com/kauffman12/EQLogParser/commit/45fe4940) commit # [3d3a09a](https://github.com/kauffman12/EQLogParser/commit/3d3a09ad)
Author: John Kauffman <[email protected]>
Date: Thu Apr 23 15:24:43 2026 -0400
Merge branch 'develop' into opencode2
commit commit # [45fe494](https://github.com/kauffman12/EQLogParser/commit/45fe4940e5dd19e720b33bf1902f6e04a447a723)
Author: John Kauffman <[email protected]>
Date: Thu Apr 23 15:11:29 2026 -0400
big reorg
(ec71d06) ~John KauffmanMerge branch 'master' into develop
(3d3a09a) ~John KauffmanMerge branch 'opencode' into develop
(29c7057) ~John KauffmanUtil cleanup
(66c193c) ~John KauffmanUpdated standards
(e79e6e5) ~John KauffmanCleanup
(4743204) ~John KauffmanReorg
(c4ab881) ~John KauffmanMore cleanup
(e90bfcb) ~John KauffmanUpdate ignore file
(a3428f4) ~John KauffmanRemoved invalid file
(86300a9) ~John KauffmanCleanup
(d54f0a9) ~John KauffmanRenaming some classes
(6b5f609) ~John KauffmanFormat fixes
(2bb372e) ~John KauffmanCreated adps tracker
(6cbb5ce) ~John KauffmanSquashed commit of the following:
commit commit # [96b3d4f](https://github.com/kauffman12/EQLogParser/commit/96b3d4fb1f0de6ea4157b120335e5666f0a23905)
Author: John Kauffman <[email protected]>
Date: Mon Apr 20 09:44:46 2026 -0400
handle group id in who
commit commit # [bace40c](https://github.com/kauffman12/EQLogParser/commit/bace40c4c80f307d8244bcf6d64622e0d75d820e)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 23:24:20 2026 -0400
fix formatting
commit commit # [83e5ae0](https://github.com/kauffman12/EQLogParser/commit/83e5ae0dde41e5688c5ff1593debc3568ebe4395)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 23:21:19 2026 -0400
better interface use
commit commit # [033d2fd](https://github.com/kauffman12/EQLogParser/commit/033d2fd86a05f4ea81c0265493d5609d6d8e2a83)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 23:08:06 2026 -0400
fix tests
commit commit # [22162de](https://github.com/kauffman12/EQLogParser/commit/22162de776e035196655cf6d8b8e5ef72cb2117d)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 14:09:24 2026 -0400
update testers
commit commit # [c6a141f](https://github.com/kauffman12/EQLogParser/commit/c6a141f866c36b8f6a558477cdd294f4d30b854a)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 12:22:31 2026 -0400
new tests
commit commit # [c914c48](https://github.com/kauffman12/EQLogParser/commit/c914c4875069441e56eeff82230d9383c46f32ad)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 11:38:02 2026 -0400
more performance updates
commit commit # [0499dff](https://github.com/kauffman12/EQLogParser/commit/0499dff928ddad82921fae56986b07f52903b39c)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 11:36:07 2026 -0400
minor updates
commit commit # [4006744](https://github.com/kauffman12/EQLogParser/commit/40067447415a4d783786ec967f234f8300ef669a)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 11:29:00 2026 -0400
fix compiler warnings
commit commit # [7eb4e96](https://github.com/kauffman12/EQLogParser/commit/7eb4e96b4a4af45d37d9711fcb0583dce7f48e09)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 11:10:57 2026 -0400
removed extra ToArray()
commit commit # [50e5b79](https://github.com/kauffman12/EQLogParser/commit/50e5b79b3ee479c1b4082be51bf2b2c0e68c4ded)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 10:51:38 2026 -0400
fix tests
commit commit # [77c3554](https://github.com/kauffman12/EQLogParser/commit/77c35544eeef341689928e92117e5080dab00449)
Merge: commit # [dfa3194](https://github.com/kauffman12/EQLogParser/commit/dfa3194e) commit # [c8d8d92](https://github.com/kauffman12/EQLogParser/commit/c8d8d921)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 10:10:43 2026 -0400
Merge remote-tracking branch 'refs/remotes/origin/opencode' into opencode
commit commit # [dfa3194](https://github.com/kauffman12/EQLogParser/commit/dfa3194e7d1629fdc4e374e0ae8779ca913b8a2c)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 10:09:27 2026 -0400
perf updates
commit commit # [c8d8d92](https://github.com/kauffman12/EQLogParser/commit/c8d8d921f84b73f097396cd8dffba824fc21778c)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 03:22:47 2026 -0400
fix events not being cleaned up
commit commit # [4a00575](https://github.com/kauffman12/EQLogParser/commit/4a00575c84cec7be32339bd3b1807820976f1f02)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 02:08:35 2026 -0400
cleanup
commit commit # [32784fe](https://github.com/kauffman12/EQLogParser/commit/32784fe81b1a886b4da65e6ac3eb67ee76466440)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 01:46:26 2026 -0400
updated standards
commit commit # [d0c68e7](https://github.com/kauffman12/EQLogParser/commit/d0c68e7e6ea827c33017631bfa9861cec168e648)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 01:21:04 2026 -0400
latest
commit commit # [075b180](https://github.com/kauffman12/EQLogParser/commit/075b180ff03d19f5b4a7fd06e064d63bec5dce8d)
Author: John Kauffman <[email protected]>
Date: Sun Apr 19 00:18:08 2026 -0400
updated damage summary combo
commit commit # [f4d39e5](https://github.com/kauffman12/EQLogParser/commit/f4d39e5e2f0ce9c1b3c80ec485fe6edd0fb9ccb1)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 23:45:30 2026 -0400
more fixes
commit commit # [023fb9e](https://github.com/kauffman12/EQLogParser/commit/023fb9e8699370b38aee2d48d3bc1f01d13e6109)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 22:40:42 2026 -0400
Revert "Revert "group cleanup""
This reverts commit commit # [72ce4f1](https://github.com/kauffman12/EQLogParser/commit/72ce4f12911abd5c10b1fc862789123816e0ccf1).
commit commit # [b2babad](https://github.com/kauffman12/EQLogParser/commit/b2babadb947279ddd9cd00aee9bde9e6d79ee587)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 22:40:14 2026 -0400
Revert "test groupid sort"
This reverts commit commit # [145e8a2](https://github.com/kauffman12/EQLogParser/commit/145e8a21d2a539a80a39d1374d8cfd76c6c6ccd7).
commit commit # [72ce4f1](https://github.com/kauffman12/EQLogParser/commit/72ce4f12911abd5c10b1fc862789123816e0ccf1)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 22:25:06 2026 -0400
Revert "group cleanup"
This reverts commit commit # [599f20f](https://github.com/kauffman12/EQLogParser/commit/599f20f066f559d41e53b8f7278ad0d243c13c7b).
commit commit # [145e8a2](https://github.com/kauffman12/EQLogParser/commit/145e8a21d2a539a80a39d1374d8cfd76c6c6ccd7)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 22:20:18 2026 -0400
test groupid sort
commit commit # [599f20f](https://github.com/kauffman12/EQLogParser/commit/599f20f066f559d41e53b8f7278ad0d243c13c7b)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 22:03:07 2026 -0400
group cleanup
commit commit # [91fcc36](https://github.com/kauffman12/EQLogParser/commit/91fcc3693566104a67b5293c1801a43424f8941d)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 21:47:49 2026 -0400
cleanup
commit commit # [fbaf1af](https://github.com/kauffman12/EQLogParser/commit/fbaf1af1d76c24bf17d64f98fb042859dd462dc3)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 21:14:10 2026 -0400
fix clipboard calls
commit commit # [2e78a78](https://github.com/kauffman12/EQLogParser/commit/2e78a780e1ffd9184381d5caf2af1245aac011f3)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 21:03:16 2026 -0400
cleanup
commit commit # [fc15365](https://github.com/kauffman12/EQLogParser/commit/fc15365f2d2e125de241454be7d89a122b00d230)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 16:38:38 2026 -0400
fixes
commit commit # [8e6dc1d](https://github.com/kauffman12/EQLogParser/commit/8e6dc1d0a85545c83497b8f48a2377ddafdf95e6)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 16:18:53 2026 -0400
fixes for spell counts hopefully
commit commit # [5cb4155](https://github.com/kauffman12/EQLogParser/commit/5cb41554be363a7780ae3eddc4f1704d2bdd6866)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 15:25:55 2026 -0400
minor updates
commit commit # [52065e7](https://github.com/kauffman12/EQLogParser/commit/52065e705abdcf8c95fa85f1cf99e3009f7d72f3)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 15:19:24 2026 -0400
updated delete in pet table
commit commit # [e2c1734](https://github.com/kauffman12/EQLogParser/commit/e2c173433f989c89cd2230da10ab96ab3f52acc1)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 14:52:30 2026 -0400
format updates
commit commit # [a90c13d](https://github.com/kauffman12/EQLogParser/commit/a90c13dafdc171b63b7d44f527bbfb73322a1909)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 14:44:28 2026 -0400
latest
commit commit # [95e6bd0](https://github.com/kauffman12/EQLogParser/commit/95e6bd027fc24eb952c9a2d66d6ec6ae606d2f24)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 14:20:44 2026 -0400
fixes
commit commit # [1b21fc4](https://github.com/kauffman12/EQLogParser/commit/1b21fc4967c3886bde99b5a37e968717257d2c7e)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 13:55:07 2026 -0400
update for class picker
commit commit # [6e83187](https://github.com/kauffman12/EQLogParser/commit/6e83187ad15773b2c78f6015bb6ec37ff3e748ac)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 13:21:18 2026 -0400
updates for pet player dropdown
commit commit # [a09067a](https://github.com/kauffman12/EQLogParser/commit/a09067a1b8113d5d29c01ce2eb8966055f6133ef)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 11:53:50 2026 -0400
single combobox idea
commit commit # [8d186f7](https://github.com/kauffman12/EQLogParser/commit/8d186f7d8a81e6c8e648e832b0096db71a2e2f7f)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 00:34:01 2026 -0400
updated player column
commit commit # [aa8c737](https://github.com/kauffman12/EQLogParser/commit/aa8c737f326678a9890a22c8b6d301c68103f406)
Author: John Kauffman <[email protected]>
Date: Sat Apr 18 00:06:40 2026 -0400
latest
commit commit # [a565fe7](https://github.com/kauffman12/EQLogParser/commit/a565fe78c06256c4ec9b13933ccaad8d873daf23)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 20:57:14 2026 -0400
more changes
commit commit # [ff97383](https://github.com/kauffman12/EQLogParser/commit/ff97383a9127e32f306d786728a09c83e812b4df)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 20:26:18 2026 -0400
more
commit commit # [ca0e078](https://github.com/kauffman12/EQLogParser/commit/ca0e0780b016b87e6838a14bab61237b64ea022d)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 19:33:48 2026 -0400
another mouse update
commit commit # [d26e2b9](https://github.com/kauffman12/EQLogParser/commit/d26e2b96218bf459b88e03526abeb19638b76d2a)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 18:03:03 2026 -0400
mouse click test
commit commit # [af91378](https://github.com/kauffman12/EQLogParser/commit/af913786d64a09f38d18aca6edcaf321b3c4c061)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 17:39:16 2026 -0400
fixes
commit commit # [c60bc04](https://github.com/kauffman12/EQLogParser/commit/c60bc045cc43067c4be261ccf5f2670d814fdb0d)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 16:41:31 2026 -0400
updated pet mapping table
commit commit # [fcf9d40](https://github.com/kauffman12/EQLogParser/commit/fcf9d404da2f53d06542bca884c1f01f70520047)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 15:38:45 2026 -0400
added modified get selected stats
commit commit # [17337d9](https://github.com/kauffman12/EQLogParser/commit/17337d926ae67ac88785fb369697a081c2d29e65)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 15:13:03 2026 -0400
fix context menu
commit commit # [0657e3e](https://github.com/kauffman12/EQLogParser/commit/0657e3e8ceee95390999af436d3bc3cb8a29e918)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 14:53:51 2026 -0400
cleanup
commit commit # [f738a04](https://github.com/kauffman12/EQLogParser/commit/f738a0402e358507705f6f28b8885ea7e85f689a)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 14:39:21 2026 -0400
fix raid total percent for groups
commit commit # [0d5fe2f](https://github.com/kauffman12/EQLogParser/commit/0d5fe2f2d39843eea7a6685ecd1aaa14a1a9405c)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 14:25:41 2026 -0400
changed to IList
commit commit # [ce0022a](https://github.com/kauffman12/EQLogParser/commit/ce0022a65df58236dc151cf95384633a98560fe9)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 14:02:14 2026 -0400
cleanup
commit commit # [cc6be5e](https://github.com/kauffman12/EQLogParser/commit/cc6be5e9100511f54e92bfadde896c5f3cad4ea5)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 12:56:52 2026 -0400
cleanup
commit commit # [209632e](https://github.com/kauffman12/EQLogParser/commit/209632e3c8f9bd2202d81fe0d42b6bfc1a1fd184)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 12:53:09 2026 -0400
added icons and updated combobox UI
commit commit # [31097d1](https://github.com/kauffman12/EQLogParser/commit/31097d19314336ddbce7a2097dcc0cbd6e5ef788)
Author: John Kauffman <[email protected]>
Date: Fri Apr 17 00:05:50 2026 -0400
Revert "use syncfusion dropdown"
This reverts commit commit # [4a5a2cc](https://github.com/kauffman12/EQLogParser/commit/4a5a2cc536382e9ac9e967507d85178f70db28b9).
commit commit # [4a5a2cc](https://github.com/kauffman12/EQLogParser/commit/4a5a2cc536382e9ac9e967507d85178f70db28b9)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 21:17:10 2026 -0400
use syncfusion dropdown
commit commit # [c8ed458](https://github.com/kauffman12/EQLogParser/commit/c8ed458e57cd7b95ac9271babaee46227ae3f02b)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 18:26:17 2026 -0400
more updates
commit commit # [235f2ca](https://github.com/kauffman12/EQLogParser/commit/235f2ca8890f9435626b0355e31249243083b2f0)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 16:22:53 2026 -0400
fix expanding
commit commit # [9c1cf2e](https://github.com/kauffman12/EQLogParser/commit/9c1cf2ede6560210ec665c734205b80d66847db5)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 14:07:21 2026 -0400
new idea
commit commit # [ee2c27d](https://github.com/kauffman12/EQLogParser/commit/ee2c27d24db42ebd621325dd231507f914d60537)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 11:44:33 2026 -0400
more changes
commit commit # [7b08e5d](https://github.com/kauffman12/EQLogParser/commit/7b08e5d64c5a91ac10f56d8411fcc2df6df593a0)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 10:33:10 2026 -0400
fixes
commit commit # [31c695e](https://github.com/kauffman12/EQLogParser/commit/31c695e96b966bb97472917b534cc40df7754f8e)
Author: John Kauffman <[email protected]>
Date: Thu Apr 16 00:43:43 2026 -0400
more updates
commit commit # [f5ba754](https://github.com/kauffman12/EQLogParser/commit/f5ba754eaa49f11adbf7ed2509bc2928f2696a84)
Author: John Kauffman <[email protected]>
Date: Wed Apr 15 23:53:06 2026 -0400
fixes
commit commit # [96c2d05](https://github.com/kauffman12/EQLogParser/commit/96c2d05d34ed0ae723f6ca710d196c06fc327054)
Author: John Kauffman <[email protected]>
Date: Wed Apr 15 23:16:59 2026 -0400
added dynamic group change
commit commit # [0c94b1a](https://github.com/kauffman12/EQLogParser/commit/0c94b1af3112a460446db8fad5fd8c5f623a8ef9)
Author: John Kauffman <[email protected]>
Date: Wed Apr 15 21:22:35 2026 -0400
update group column width
commit commit # [323b1ae](https://github.com/kauffman12/EQLogParser/commit/323b1ae3ca2673872f11ca73600b892550bfcd21)
Author: John Kauffman <[email protected]>
Date: Wed Apr 15 21:09:03 2026 -0400
fixes
commit commit # [1d3bde1](https://github.com/kauffman12/EQLogParser/commit/1d3bde1a6c9d7971176fcb75afe77f8e70b688cb)
Author: John Kauffman <[email protected]>
Date: Wed Apr 15 01:40:23 2026 -0400
opencode added group breakdown
commit commit # [f86551a](https://github.com/kauffman12/EQLogParser/commit/f86551a1c3a704e78bcd0047e063c3e9e9613c68)
Author: John Kauffman <[email protected]>
Date: Tue Apr 14 18:55:04 2026 -0400
overlay fixes
(96b3d4f) ~John KauffmanHandle group id in who
(83e5ae0) ~John KauffmanBetter interface use
(22162de) ~John KauffmanUpdate testers
(c6a141f) ~John KauffmanNew tests
(c914c48) ~John KauffmanMore performance updates
(0499dff) ~John KauffmanMinor updates
(7eb4e96) ~John KauffmanRemoved extra ToArray()
(77c3554) ~John KauffmanMerge remote-tracking branch 'refs/remotes/origin/opencode' into opencode
(4a00575) ~John KauffmanCleanup
(32784fe) ~John KauffmanUpdated standards
(d0c68e7) ~John KauffmanLatest
(075b180) ~John KauffmanUpdated damage summary combo
(f4d39e5) ~John KauffmanMore fixes
(023fb9e) ~John KauffmanRevert "Revert "group cleanup""
This reverts commit commit # [72ce4f1](https://github.com/kauffman12/EQLogParser/commit/72ce4f12911abd5c10b1fc862789123816e0ccf1).
(b2babad) ~John KauffmanRevert "test groupid sort"
This reverts commit commit # [145e8a2](https://github.com/kauffman12/EQLogParser/commit/145e8a21d2a539a80a39d1374d8cfd76c6c6ccd7).
(72ce4f1) ~John KauffmanRevert "group cleanup"
This reverts commit commit # [599f20f](https://github.com/kauffman12/EQLogParser/commit/599f20f066f559d41e53b8f7278ad0d243c13c7b).
(599f20f) ~John KauffmanGroup cleanup
(91fcc36) ~John KauffmanCleanup
(2e78a78) ~John KauffmanCleanup
(5cb4155) ~John KauffmanMinor updates
(52065e7) ~John KauffmanUpdated delete in pet table
(e2c1734) ~John KauffmanFormat updates
(a90c13d) ~John KauffmanLatest
(1b21fc4) ~John KauffmanUpdate for class picker
(6e83187) ~John KauffmanUpdates for pet player dropdown
(a09067a) ~John KauffmanSingle combobox idea
(8d186f7) ~John KauffmanUpdated player column
(aa8c737) ~John KauffmanLatest
(a565fe7) ~John KauffmanMore changes
(ff97383) ~John KauffmanMore
(ca0e078) ~John KauffmanAnother mouse update
(d26e2b9) ~John KauffmanMouse click test
(c60bc04) ~John KauffmanUpdated pet mapping table
(fcf9d40) ~John KauffmanAdded modified get selected stats
(0657e3e) ~John KauffmanCleanup
(0d5fe2f) ~John KauffmanChanged to IList
(ce0022a) ~John KauffmanCleanup
(cc6be5e) ~John KauffmanCleanup
(209632e) ~John KauffmanAdded icons and updated combobox UI
(31097d1) ~John KauffmanRevert "use syncfusion dropdown"
This reverts commit commit # [4a5a2cc](https://github.com/kauffman12/EQLogParser/commit/4a5a2cc536382e9ac9e967507d85178f70db28b9).
(4a5a2cc) ~John KauffmanUse syncfusion dropdown
(c8ed458) ~John KauffmanMore updates
(9c1cf2e) ~John KauffmanNew idea
(ee2c27d) ~John KauffmanMore changes
(31c695e) ~John KauffmanMore updates
(96c2d05) ~John KauffmanAdded dynamic group change
(0c94b1a) ~John KauffmanUpdate group column width
(1d3bde1) ~John KauffmanOpencode added group breakdown
(f86551a) ~John KauffmanOverlay fixes