OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      6cd96f086dce
DATE      2025-07-20
SUBJECT   nix: refactor lib
FILES     12 CHANGED
HASH      6cd96f086dce
DATE      2025-07-20
SUBJECT   nix: refactor lib
FILES     12 CHANGED
 

diff --git a/nix/lib/classConfigs.nix b/nix/lib/classConfigs.nix
deleted file mode 100644
index 1793685..0000000
--- a/nix/lib/classConfigs.nix
+++ /dev/null
@@ -1,181 +0,0 @@
-{
-  lib,
-  self,
-  ...
-}: let
-  raidBuffsLib = import ./raidBuffs.nix {inherit lib;};
-  raidDebuffsLib = import ./raidDebuffs.nix {inherit lib;};
-  encountersLib = import ./encounters.nix {inherit lib;};
-
-  # Base configuration that most specs will use
-  baseConfig = {
-    iterations = 12500;
-    randomSeed = "4260890857";
-    debugFirstIteration = true;
-    distanceFromTarget = 5;
-    reactionTimeMs = 100;
-    raidBuffs = raidBuffsLib.fullBuffs;
-    raidDebuffs = raidDebuffsLib.fullDebuffs;
-  };
-
-  # Melee base config
-  meleeConfig = baseConfig;
-
-  # Ranged base config
-  rangedConfig =
-    baseConfig
-    // {
-      distanceFromTarget = 25;
-    };
-
-  # Caster base config
-  casterConfig =
-    baseConfig
-    // {
-      distanceFromTarget = 25;
-    };
-
-  # Class-specific configurations
-  monk = {
-    windwalker = {
-      singleTarget =
-        meleeConfig
-        // {
-          class = "monk";
-          spec = "windwalker";
-          race = "orc";
-          gearset = "p1_bis_dw";
-          apl = "default";
-          consumables = {
-            prepotId = 76089;
-            potId = 76089;
-            flaskId = 76084;
-            foodId = 74648;
-          };
-          profession1 = "Engineering";
-          profession2 = "Tailoring";
-          talents = "213322";
-          glyphs = {
-            major1 = 85697;
-            major2 = 87900;
-            minor1 = 90715;
-          };
-          buffs = {};
-          debuffs = {};
-          targetDummies = 1;
-          options = {};
-        };
-
-      multiTarget =
-        monk.windwalker.singleTarget
-        // {
-          targetDummies = 9;
-        };
-
-      # Challenge Mode variants
-      challengeMode =
-        monk.windwalker.singleTarget
-        // {
-          challengeMode = true;
-        };
-
-      challengeModeMultiTarget =
-        monk.windwalker.singleTarget
-        // {
-          challengeMode = true;
-          targetDummies = 9;
-        };
-    };
-
-    brewmaster = {
-      singleTarget =
-        meleeConfig
-        // {
-          class = "monk";
-          spec = "brewmaster";
-          race = "Pandaren";
-          gearset = "p1_bis";
-          apl = "default";
-          consumables = {
-            prepotId = 76089;
-            potId = 76089;
-            flaskId = 76084;
-            foodId = 74648;
-          };
-          profession1 = "Engineering";
-          profession2 = "Tailoring";
-          talents = "213322";
-          glyphs = {
-            major1 = 85697;
-            major2 = 87900;
-            minor1 = 90715;
-          };
-          buffs = {};
-          debuffs = {};
-          targetDummies = 1;
-          options = {};
-        };
-
-      # Challenge Mode variant
-      challengeMode =
-        monk.brewmaster.singleTarget
-        // {
-          challengeMode = true;
-        };
-    };
-
-    mistweaver = {
-      singleTarget =
-        casterConfig
-        // {
-          class = "monk";
-          spec = "mistweaver";
-          race = "Pandaren";
-          gearset = "p1_bis";
-          apl = "default";
-          consumables = {
-            prepotId = 76089;
-            potId = 76089;
-            flaskId = 76084;
-            foodId = 74648;
-          };
-          profession1 = "Engineering";
-          profession2 = "Tailoring";
-          talents = "213322";
-          glyphs = {
-            major1 = 85697;
-            major2 = 87900;
-            minor1 = 90715;
-          };
-          buffs = {};
-          debuffs = {};
-          targetDummies = 1;
-          options = {};
-        };
-
-      # Challenge Mode variant
-      challengeMode =
-        monk.mistweaver.singleTarget
-        // {
-          challengeMode = true;
-        };
-    };
-  };
-
-  # Generate simulation function
-  generateSimulation = classConfig: encounterType: let
-    generateInfile = import ./generateInfile.nix {inherit lib self;};
-    encounter = encounterType;
-  in
-    generateInfile (classConfig // {inherit encounter;});
-in {
-  inherit baseConfig meleeConfig rangedConfig casterConfig monk generateSimulatio
n;
-
-  # Export encounters for easy access
-  encounters = encountersLib;
-
-  # Export buff/debuff libs for customization
-  raidBuffs = raidBuffsLib;
-  raidDebuffs = raidDebuffsLib;
-}
-

diff --git a/nix/lib/classConfigs.nix b/nix/
lib/classConfigs.nix
deleted file mode 100644
index 1793685..0000000
--- a/nix/lib/classConfigs.nix
+++ /dev/null
@@ -1,181 +0,0 @@
-{
-  lib,
-  self,
-  ...
-}: let
-  raidBuffsLib = import ./raidBuffs.nix {in
herit lib;};
-  raidDebuffsLib = import ./raidDebuffs.nix
 {inherit lib;};
-  encountersLib = import ./encounters.nix {
inherit lib;};
-
-  # Base configuration that most specs will
 use
-  baseConfig = {
-    iterations = 12500;
-    randomSeed = "4260890857";
-    debugFirstIteration = true;
-    distanceFromTarget = 5;
-    reactionTimeMs = 100;
-    raidBuffs = raidBuffsLib.fullBuffs;
-    raidDebuffs = raidDebuffsLib.fullDebuff
s;
-  };
-
-  # Melee base config
-  meleeConfig = baseConfig;
-
-  # Ranged base config
-  rangedConfig =
-    baseConfig
-    // {
-      distanceFromTarget = 25;
-    };
-
-  # Caster base config
-  casterConfig =
-    baseConfig
-    // {
-      distanceFromTarget = 25;
-    };
-
-  # Class-specific configurations
-  monk = {
-    windwalker = {
-      singleTarget =
-        meleeConfig
-        // {
-          class = "monk";
-          spec = "windwalker";
-          race = "orc";
-          gearset = "p1_bis_dw";
-          apl = "default";
-          consumables = {
-            prepotId = 76089;
-            potId = 76089;
-            flaskId = 76084;
-            foodId = 74648;
-          };
-          profession1 = "Engineering";
-          profession2 = "Tailoring";
-          talents = "213322";
-          glyphs = {
-            major1 = 85697;
-            major2 = 87900;
-            minor1 = 90715;
-          };
-          buffs = {};
-          debuffs = {};
-          targetDummies = 1;
-          options = {};
-        };
-
-      multiTarget =
-        monk.windwalker.singleTarget
-        // {
-          targetDummies = 9;
-        };
-
-      # Challenge Mode variants
-      challengeMode =
-        monk.windwalker.singleTarget
-        // {
-          challengeMode = true;
-        };
-
-      challengeModeMultiTarget =
-        monk.windwalker.singleTarget
-        // {
-          challengeMode = true;
-          targetDummies = 9;
-        };
-    };
-
-    brewmaster = {
-      singleTarget =
-        meleeConfig
-        // {
-          class = "monk";
-          spec = "brewmaster";
-          race = "Pandaren";
-          gearset = "p1_bis";
-          apl = "default";
-          consumables = {
-            prepotId = 76089;
-            potId = 76089;
-            flaskId = 76084;
-            foodId = 74648;
-          };
-          profession1 = "Engineering";
-          profession2 = "Tailoring";
-          talents = "213322";
-          glyphs = {
-            major1 = 85697;
-            major2 = 87900;
-            minor1 = 90715;
-          };
-          buffs = {};
-          debuffs = {};
-          targetDummies = 1;
-          options = {};
-        };
-
-      # Challenge Mode variant
-      challengeMode =
-        monk.brewmaster.singleTarget
-        // {
-          challengeMode = true;
-        };
-    };
-
-    mistweaver = {
-      singleTarget =
-        casterConfig
-        // {
-          class = "monk";
-          spec = "mistweaver";
-          race = "Pandaren";
-          gearset = "p1_bis";
-          apl = "default";
-          consumables = {
-            prepotId = 76089;
-            potId = 76089;
-            flaskId = 76084;
-            foodId = 74648;
-          };
-          profession1 = "Engineering";
-          profession2 = "Tailoring";
-          talents = "213322";
-          glyphs = {
-            major1 = 85697;
-            major2 = 87900;
-            minor1 = 90715;
-          };
-          buffs = {};
-          debuffs = {};
-          targetDummies = 1;
-          options = {};
-        };
-
-      # Challenge Mode variant
-      challengeMode =
-        monk.mistweaver.singleTarget
-        // {
-          challengeMode = true;
-        };
-    };
-  };
-
-  # Generate simulation function
-  generateSimulation = classConfig: encount
erType: let
-    generateInfile = import ./generateInfil
e.nix {inherit lib self;};
-    encounter = encounterType;
-  in
-    generateInfile (classConfig // {inherit
 encounter;});
-in {
-  inherit baseConfig meleeConfig rangedConf
ig casterConfig monk generateSimulation;
-
-  # Export encounters for easy access
-  encounters = encountersLib;
-
-  # Export buff/debuff libs for customizati
on
-  raidBuffs = raidBuffsLib;
-  raidDebuffs = raidDebuffsLib;
-}
-
 

diff --git a/nix/lib/default.nix b/nix/lib/default.nix
index 9074507..74fe999 100644
--- a/nix/lib/default.nix
+++ b/nix/lib/default.nix
@@ -5,7 +5,9 @@
 }: {
   # class = import ./class.nix;
   target = import ./target.nix {inherit lib;};
-  encounter = import ./encounter.nix {inherit lib;};
+  encounter = import ./encounter.nix;
   player = import ./player.nix {inherit lib inputs;};
-  raid = import ./raid.nix {};
+  raid = import ./raid.nix {inherit lib;};
+  simulation = import ./simulation.nix {inherit lib;};
+  party = import ./party.nix {inherit lib;};
 }

diff --git a/nix/lib/default.nix b/nix/lib/d
efault.nix
index 9074507..74fe999 100644
--- a/nix/lib/default.nix
+++ b/nix/lib/default.nix
@@ -5,7 +5,9 @@
 }: {
   # class = import ./class.nix;
   target = import ./target.nix {inherit lib
;};
-  encounter = import ./encounter.nix {inher
it lib;};
+  encounter = import ./encounter.nix;
   player = import ./player.nix {inherit lib
 inputs;};
-  raid = import ./raid.nix {};
+  raid = import ./raid.nix {inherit lib;};
+  simulation = import ./simulation.nix {inh
erit lib;};
+  party = import ./party.nix {inherit lib;}
;
 }
 

diff --git a/nix/lib/encounter.nix b/nix/lib/encounter.nix
new file mode 100644
index 0000000..f1aba53
--- /dev/null
+++ b/nix/lib/encounter.nix
@@ -0,0 +1,19 @@
+let
+  # Base encounter template
+  mkEncounter = {
+    duration ? 300,
+    durationVariation ? 60,
+    targets ? [],
+  }: {
+    apiVersion = 1;
+    inherit duration durationVariation targets;
+
+    # default execute config
+    executeProportion20 = 0.2;
+    executeProportion25 = 0.25;
+    executeProportion35 = 0.35;
+    executeProportion45 = 0.45;
+    executeProportion90 = 0.9;
+  };
+  # Duration-based encounter templates
+in {inherit mkEncounter;}

diff --git a/nix/lib/encounter.nix b/nix/lib
/encounter.nix
new file mode 100644
index 0000000..f1aba53
--- /dev/null
+++ b/nix/lib/encounter.nix
@@ -0,0 +1,19 @@
+let
+  # Base encounter template
+  mkEncounter = {
+    duration ? 300,
+    durationVariation ? 60,
+    targets ? [],
+  }: {
+    apiVersion = 1;
+    inherit duration durationVariation targ
ets;
+
+    # default execute config
+    executeProportion20 = 0.2;
+    executeProportion25 = 0.25;
+    executeProportion35 = 0.35;
+    executeProportion45 = 0.45;
+    executeProportion90 = 0.9;
+  };
+  # Duration-based encounter templates
+in {inherit mkEncounter;}
 

diff --git a/nix/lib/encounters.nix b/nix/lib/encounters.nix
deleted file mode 100644
index 6250dd2..0000000
--- a/nix/lib/encounters.nix
+++ /dev/null
@@ -1,52 +0,0 @@
-{lib, ...}: let
-  # Base encounter template
-  inherit (lib) genList;
-  mobs = import ./targets.nix;
-  mkEncounter = {
-    duration ? 300,
-    durationVariation ? 60,
-    targets ? [],
-  }: {
-    apiVersion = 1;
-    inherit duration durationVariation targets;
-
-    # default execute config
-    executeProportion20 = 0.2;
-    executeProportion25 = 0.25;
-    executeProportion35 = 0.35;
-    executeProportion45 = 0.45;
-    executeProportion90 = 0.9;
-  };
-
-  # Duration-based encounter templates
-  raid = {
-    long = {
-      singleTarget = mkEncounter {
-        targets = [
-          mobs.defaultRaidBoss
-        ];
-      };
-
-      twoTarget = mkEncounter {
-        targets = genList (_: mobs.defaultRaidBoss) 3;
-      };
-
-      threeTarget = mkEncounter {
-        targets = genList (_: mobs.defaultRaidBoss) 3;
-      };
-
-      fiveTarget = mkEncounter {
-        targets = genList (_: mobs.defaultRaidBoss) 10;
-      };
-
-      tenTarget = mkEncounter {
-        targets = genList (_: mobs.defaultRaidBoss) 10;
-      };
-
-      twentyTarget = mkEncounter {
-        targets = genList (_: mobs.defaultRaidBoss) 20;
-      };
-    };
-  };
-in
-  raid

diff --git a/nix/lib/encounters.nix b/nix/li
b/encounters.nix
deleted file mode 100644
index 6250dd2..0000000
--- a/nix/lib/encounters.nix
+++ /dev/null
@@ -1,52 +0,0 @@
-{lib, ...}: let
-  # Base encounter template
-  inherit (lib) genList;
-  mobs = import ./targets.nix;
-  mkEncounter = {
-    duration ? 300,
-    durationVariation ? 60,
-    targets ? [],
-  }: {
-    apiVersion = 1;
-    inherit duration durationVariation targ
ets;
-
-    # default execute config
-    executeProportion20 = 0.2;
-    executeProportion25 = 0.25;
-    executeProportion35 = 0.35;
-    executeProportion45 = 0.45;
-    executeProportion90 = 0.9;
-  };
-
-  # Duration-based encounter templates
-  raid = {
-    long = {
-      singleTarget = mkEncounter {
-        targets = [
-          mobs.defaultRaidBoss
-        ];
-      };
-
-      twoTarget = mkEncounter {
-        targets = genList (_: mobs.defaultR
aidBoss) 3;
-      };
-
-      threeTarget = mkEncounter {
-        targets = genList (_: mobs.defaultR
aidBoss) 3;
-      };
-
-      fiveTarget = mkEncounter {
-        targets = genList (_: mobs.defaultR
aidBoss) 10;
-      };
-
-      tenTarget = mkEncounter {
-        targets = genList (_: mobs.defaultR
aidBoss) 10;
-      };
-
-      twentyTarget = mkEncounter {
-        targets = genList (_: mobs.defaultR
aidBoss) 20;
-      };
-    };
-  };
-in
-  raid
 

diff --git a/nix/lib/generateInfile.nix b/nix/lib/generateInfile.nix
deleted file mode 100644
index fb0b1a9..0000000
--- a/nix/lib/generateInfile.nix
+++ /dev/null
@@ -1,104 +0,0 @@
-{
-  lib,
-  self,
-  ...
-}: let
-  inherit (lib.strings) toSentenceCase;
-  
-  # Import utility modules
-  raidBuffsLib = import ./raidBuffs.nix {inherit lib;};
-  raidDebuffsLib = import ./raidDebuffs.nix {inherit lib;};
-  encountersLib = import ./encounters.nix {inherit lib;};
-  generateInfile = {
-    class,
-    spec,
-    race,
-    gearset,
-    consumables,
-    profession1,
-    profession2,
-    talents,
-    buffs ? {},
-    debuffs,
-    apl,
-    targetDummies ? 1,
-    distanceFromTarget ? 5,
-    numberOfTargets ? 1,
-    iterations ? 12500,
-    options ? {},
-    glyphs,
-    raidBuffs ? raidBuffsLib.fullBuffs,
-    raidDebuffs ? raidDebuffsLib.fullDebuffs,
-    reactionTimeMs ? 100,
-    encounter ? encountersLib.long.singleTarget,
-    randomSeed ? "4260890857",
-    debugFirstIteration ? true,
-    challengeMode ? false,
-  }: let
-    baseEquipment = builtins.fromJSON (builtins.readFile "${self}/ui/${class}/${s
pec}/gear_sets/${gearset}.gear.json");
-    rotation = builtins.fromJSON (builtins.readFile "${self}/ui/${class}/${spec}/
apls/${apl}.apl.json");
-    
-    # Add challengeMode flag to all equipment items if enabled
-    equipment = if challengeMode then
-      baseEquipment // {
-        items = map (item: item // {challengeMode = true;}) baseEquipment.items;
-      }
-    else
-      baseEquipment;
-  in
-    builtins.toJSON {
-      requestId = "raidSimAsync-62a8c84a7df3627";
-      raid = {
-        parties = [
-          {
-            players = [
-              {
-                name = "Player";
-                race = "Race${toSentenceCase race}";
-                class = "Class${toSentenceCase class}";
-                inherit equipment consumables buffs glyphs profession1 profession
2 rotation reactionTimeMs distanceFromTarget;
-                talentsString = talents;
-                cooldowns = {};
-                healingModel = {};
-                # Add spec-specific options
-                "${spec}${toSentenceCase class}" = {
-                  inherit options;
-                };
-              }
-              {}
-              {}
-              {}
-              {}
-            ];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-        ];
-        numActiveParties = 5;
-        buffs = raidBuffs;
-        debuffs = raidDebuffs;
-        inherit targetDummies;
-      };
-      inherit encounter;
-      simOptions = {
-        inherit iterations randomSeed debugFirstIteration;
-      };
-      type = "SimTypeIndividual";
-    };
-in
-  generateInfile

diff --git a/nix/lib/generateInfile.nix b/ni
x/lib/generateInfile.nix
deleted file mode 100644
index fb0b1a9..0000000
--- a/nix/lib/generateInfile.nix
+++ /dev/null
@@ -1,104 +0,0 @@
-{
-  lib,
-  self,
-  ...
-}: let
-  inherit (lib.strings) toSentenceCase;
-  
-  # Import utility modules
-  raidBuffsLib = import ./raidBuffs.nix {in
herit lib;};
-  raidDebuffsLib = import ./raidDebuffs.nix
 {inherit lib;};
-  encountersLib = import ./encounters.nix {
inherit lib;};
-  generateInfile = {
-    class,
-    spec,
-    race,
-    gearset,
-    consumables,
-    profession1,
-    profession2,
-    talents,
-    buffs ? {},
-    debuffs,
-    apl,
-    targetDummies ? 1,
-    distanceFromTarget ? 5,
-    numberOfTargets ? 1,
-    iterations ? 12500,
-    options ? {},
-    glyphs,
-    raidBuffs ? raidBuffsLib.fullBuffs,
-    raidDebuffs ? raidDebuffsLib.fullDebuff
s,
-    reactionTimeMs ? 100,
-    encounter ? encountersLib.long.singleTa
rget,
-    randomSeed ? "4260890857",
-    debugFirstIteration ? true,
-    challengeMode ? false,
-  }: let
-    baseEquipment = builtins.fromJSON (buil
tins.readFile "${self}/ui/${class}/${spec}/g
ear_sets/${gearset}.gear.json");
-    rotation = builtins.fromJSON (builtins.
readFile "${self}/ui/${class}/${spec}/apls/$
{apl}.apl.json");
-    
-    # Add challengeMode flag to all equipme
nt items if enabled
-    equipment = if challengeMode then
-      baseEquipment // {
-        items = map (item: item // {challen
geMode = true;}) baseEquipment.items;
-      }
-    else
-      baseEquipment;
-  in
-    builtins.toJSON {
-      requestId = "raidSimAsync-62a8c84a7df
3627";
-      raid = {
-        parties = [
-          {
-            players = [
-              {
-                name = "Player";
-                race = "Race${toSentenceCas
e race}";
-                class = "Class${toSentenceC
ase class}";
-                inherit equipment consumabl
es buffs glyphs profession1 profession2 rota
tion reactionTimeMs distanceFromTarget;
-                talentsString = talents;
-                cooldowns = {};
-                healingModel = {};
-                # Add spec-specific options
-                "${spec}${toSentenceCase cl
ass}" = {
-                  inherit options;
-                };
-              }
-              {}
-              {}
-              {}
-              {}
-            ];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-          {
-            players = [{} {} {} {} {}];
-            buffs = {};
-          }
-        ];
-        numActiveParties = 5;
-        buffs = raidBuffs;
-        debuffs = raidDebuffs;
-        inherit targetDummies;
-      };
-      inherit encounter;
-      simOptions = {
-        inherit iterations randomSeed debug
FirstIteration;
-      };
-      type = "SimTypeIndividual";
-    };
-in
-  generateInfile
 

diff --git a/nix/lib/party.nix b/nix/lib/party.nix
index f7d5498..b4cc7fa 100644
--- a/nix/lib/party.nix
+++ b/nix/lib/party.nix
@@ -1,12 +1,6 @@
-let
-  # TODO, dynamically set buffs/debuffs based on specs present
-  mkRaid = {
-    parties,
-    buffs,
-    debuffs,
-    targetDummies,
-  }: {
-    inherit parties buffs debuffs targetDummies;
+{lib, ...}: let
+  mkParty = players: {
+    players = players ++ (lib.genList (_: {}) (5 - (lib.length players)));
+    buffs = {};
   };
-in
-  mkRaid
+in {inherit mkParty;}

diff --git a/nix/lib/party.nix b/nix/lib/par
ty.nix
index f7d5498..b4cc7fa 100644
--- a/nix/lib/party.nix
+++ b/nix/lib/party.nix
@@ -1,12 +1,6 @@
-let
-  # TODO, dynamically set buffs/debuffs bas
ed on specs present
-  mkRaid = {
-    parties,
-    buffs,
-    debuffs,
-    targetDummies,
-  }: {
-    inherit parties buffs debuffs targetDum
mies;
+{lib, ...}: let
+  mkParty = players: {
+    players = players ++ (lib.genList (_: {
}) (5 - (lib.length players)));
+    buffs = {};
   };
-in
-  mkRaid
+in {inherit mkParty;}
 

diff --git a/nix/lib/player.nix b/nix/lib/player.nix
index 62f94f4..218e9cd 100644
--- a/nix/lib/player.nix
+++ b/nix/lib/player.nix
@@ -3,9 +3,25 @@
   inputs,
   ...
 }: let
-  inherit (lib.string) toSentenceCase;
+  inherit (lib.strings) toSentenceCase concatMapStrings toUpper substring;
+  inherit (builtins) filter isString split readFile fromJSON;
   inherit (inputs) wowsims;
-  inherit (builtins) readFile fromJSON;
+
+  # convert string to pascal case
+  # credit to: https://github.com/LeoLuxo/dots/blob/main/lib/strings.nix
+  toUpperCaseFirstLetter = string: let
+    head = toUpper (substring 0 1 string);
+    tail = substring 1 (-1) string;
+  in
+    head + tail;
+
+  splitWords = string:
+    filter isString (
+      split "[ _-]" string
+    );
+
+  toPascalCase = string: concatMapStrings toUpperCaseFirstLetter (splitWords stri
ng);
+
   mkPlayer = {
     name ? "Player",
     race,
@@ -13,7 +29,7 @@
     spec,
     gearset,
     consumables,
-    options,
+    options ? {},
     talents,
     glyphs,
     profession1,
@@ -35,12 +51,14 @@
 
     rotation = fromJSON (readFile "${wowsims}/ui/${class}/${spec}/apls/${apl}.apl
.json");
   in {
-    inherit equipment name consumables glyphs profession1 profession2 rotation re
actionTimeMs distanceFromTarget;
-    race = "Race${toSentenceCase race}";
-    class = "Class${toSentenceCase class}";
-    talentString = talents;
+    inherit equipment name consumables glyphs rotation reactionTimeMs distanceFro
mTarget;
+    race = toPascalCase "Race_${race}";
+    class = toPascalCase "Class_${class}";
+    profession1 = toSentenceCase profession1;
+    profession2 = toSentenceCase profession2;
+    talentsString = talents;
 
-    "${spec}${toSentenceCase class}" = {
+    "${lib.toCamelCase "${spec}-${class}"}" = {
       inherit options;
     };
 
@@ -48,5 +66,4 @@
     cooldowns = {};
     healingModel = {};
   };
-in
-  mkPlayer
+in {inherit mkPlayer;}

diff --git a/nix/lib/player.nix b/nix/lib/pl
ayer.nix
index 62f94f4..218e9cd 100644
--- a/nix/lib/player.nix
+++ b/nix/lib/player.nix
@@ -3,9 +3,25 @@
   inputs,
   ...
 }: let
-  inherit (lib.string) toSentenceCase;
+  inherit (lib.strings) toSentenceCase conc
atMapStrings toUpper substring;
+  inherit (builtins) filter isString split 
readFile fromJSON;
   inherit (inputs) wowsims;
-  inherit (builtins) readFile fromJSON;
+
+  # convert string to pascal case
+  # credit to: https://github.com/LeoLuxo/d
ots/blob/main/lib/strings.nix
+  toUpperCaseFirstLetter = string: let
+    head = toUpper (substring 0 1 string);
+    tail = substring 1 (-1) string;
+  in
+    head + tail;
+
+  splitWords = string:
+    filter isString (
+      split "[ _-]" string
+    );
+
+  toPascalCase = string: concatMapStrings t
oUpperCaseFirstLetter (splitWords string);
+
   mkPlayer = {
     name ? "Player",
     race,
@@ -13,7 +29,7 @@
     spec,
     gearset,
     consumables,
-    options,
+    options ? {},
     talents,
     glyphs,
     profession1,
@@ -35,12 +51,14 @@
 
     rotation = fromJSON (readFile "${wowsim
s}/ui/${class}/${spec}/apls/${apl}.apl.json"
);
   in {
-    inherit equipment name consumables glyp
hs profession1 profession2 rotation reaction
TimeMs distanceFromTarget;
-    race = "Race${toSentenceCase race}";
-    class = "Class${toSentenceCase class}";
-    talentString = talents;
+    inherit equipment name consumables glyp
hs rotation reactionTimeMs distanceFromTarge
t;
+    race = toPascalCase "Race_${race}";
+    class = toPascalCase "Class_${class}";
+    profession1 = toSentenceCase profession
1;
+    profession2 = toSentenceCase profession
2;
+    talentsString = talents;
 
-    "${spec}${toSentenceCase class}" = {
+    "${lib.toCamelCase "${spec}-${class}"}"
 = {
       inherit options;
     };
 
@@ -48,5 +66,4 @@
     cooldowns = {};
     healingModel = {};
   };
-in
-  mkPlayer
+in {inherit mkPlayer;}
 

diff --git a/nix/lib/raid.nix b/nix/lib/raid.nix
new file mode 100644
index 0000000..90e4c20
--- /dev/null
+++ b/nix/lib/raid.nix
@@ -0,0 +1,28 @@
+{lib, ...}: let
+  inherit (lib.sim.party) mkParty;
+  # TODO, dynamically set buffs/debuffs based on specs present
+  mkRaid = {
+    party1 ? [],
+    party2 ? [],
+    party3 ? [],
+    party4 ? [],
+    party5 ? [],
+    buffs,
+    debuffs,
+    targetDummies ? 1,
+  }: let
+    allParties = [party1 party2 party3 party4 party5];
+    # Count non-empty parties
+    # numActiveParties = builtins.length (builtins.filter (party: party != []) al
lParties);
+    numActiveParties = 5;
+  in {
+    inherit buffs debuffs targetDummies numActiveParties;
+    parties = [
+      (mkParty party1)
+      (mkParty party2)
+      (mkParty party3)
+      (mkParty party4)
+      (mkParty party5)
+    ];
+  };
+in {inherit mkRaid;}

diff --git a/nix/lib/raid.nix b/nix/lib/raid
.nix
new file mode 100644
index 0000000..90e4c20
--- /dev/null
+++ b/nix/lib/raid.nix
@@ -0,0 +1,28 @@
+{lib, ...}: let
+  inherit (lib.sim.party) mkParty;
+  # TODO, dynamically set buffs/debuffs bas
ed on specs present
+  mkRaid = {
+    party1 ? [],
+    party2 ? [],
+    party3 ? [],
+    party4 ? [],
+    party5 ? [],
+    buffs,
+    debuffs,
+    targetDummies ? 1,
+  }: let
+    allParties = [party1 party2 party3 part
y4 party5];
+    # Count non-empty parties
+    # numActiveParties = builtins.length (b
uiltins.filter (party: party != []) allParti
es);
+    numActiveParties = 5;
+  in {
+    inherit buffs debuffs targetDummies num
ActiveParties;
+    parties = [
+      (mkParty party1)
+      (mkParty party2)
+      (mkParty party3)
+      (mkParty party4)
+      (mkParty party5)
+    ];
+  };
+in {inherit mkRaid;}
 

diff --git a/nix/lib/raidBuffs.nix b/nix/lib/raidBuffs.nix
deleted file mode 100644
index cf9b940..0000000
--- a/nix/lib/raidBuffs.nix
+++ /dev/null
@@ -1,40 +0,0 @@
-{lib, ...}: let
-  # Full raid buff configuration - all buffs enabled
-  fullBuffs = {
-    trueshotAura = true;
-    unholyAura = true;
-    darkIntent = true;
-    moonkinAura = true;
-    leaderOfThePack = true;
-    blessingOfMight = true;
-    legacyOfTheEmperor = true;
-    bloodlust = true;
-    stormlashTotemCount = 5;
-    skullBannerCount = 3;
-  };
-
-  # Full buffs without bloodlust/heroism
-  fullBuffsNoLust = fullBuffs // {
-    bloodlust = false;
-  };
-
-  # No raid buffs
-  noBuffs = {
-    trueshotAura = false;
-    unholyAura = false;
-    darkIntent = false;
-    moonkinAura = false;
-    leaderOfThePack = false;
-    blessingOfMight = false;
-    legacyOfTheEmperor = false;
-    bloodlust = false;
-    stormlashTotemCount = 0;
-    skullBannerCount = 0;
-  };
-
-  # Function to merge custom buffs with defaults
-  mergeRaidBuffs = customBuffs: fullBuffs // customBuffs;
-
-in {
-  inherit fullBuffs fullBuffsNoLust noBuffs mergeRaidBuffs;
-}
\ No newline at end of file

diff --git a/nix/lib/raidBuffs.nix b/nix/lib
/raidBuffs.nix
deleted file mode 100644
index cf9b940..0000000
--- a/nix/lib/raidBuffs.nix
+++ /dev/null
@@ -1,40 +0,0 @@
-{lib, ...}: let
-  # Full raid buff configuration - all buff
s enabled
-  fullBuffs = {
-    trueshotAura = true;
-    unholyAura = true;
-    darkIntent = true;
-    moonkinAura = true;
-    leaderOfThePack = true;
-    blessingOfMight = true;
-    legacyOfTheEmperor = true;
-    bloodlust = true;
-    stormlashTotemCount = 5;
-    skullBannerCount = 3;
-  };
-
-  # Full buffs without bloodlust/heroism
-  fullBuffsNoLust = fullBuffs // {
-    bloodlust = false;
-  };
-
-  # No raid buffs
-  noBuffs = {
-    trueshotAura = false;
-    unholyAura = false;
-    darkIntent = false;
-    moonkinAura = false;
-    leaderOfThePack = false;
-    blessingOfMight = false;
-    legacyOfTheEmperor = false;
-    bloodlust = false;
-    stormlashTotemCount = 0;
-    skullBannerCount = 0;
-  };
-
-  # Function to merge custom buffs with def
aults
-  mergeRaidBuffs = customBuffs: fullBuffs /
/ customBuffs;
-
-in {
-  inherit fullBuffs fullBuffsNoLust noBuffs
 mergeRaidBuffs;
-}
\ No newline at end of file
 

diff --git a/nix/lib/raidDebuffs.nix b/nix/lib/raidDebuffs.nix
deleted file mode 100644
index cbb74a8..0000000
--- a/nix/lib/raidDebuffs.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{lib, ...}: let
-  # Full raid debuff configuration - all debuffs enabled
-  fullDebuffs = {
-    physicalVulnerability = true;
-    weakenedArmor = true;
-  };
-
-  # No raid debuffs
-  noDebuffs = {
-    physicalVulnerability = false;
-    weakenedArmor = false;
-  };
-
-  # Function to merge custom debuffs with defaults
-  mergeRaidDebuffs = customDebuffs: fullDebuffs // customDebuffs;
-
-in {
-  inherit fullDebuffs noDebuffs mergeRaidDebuffs;
-}
\ No newline at end of file

diff --git a/nix/lib/raidDebuffs.nix b/nix/l
ib/raidDebuffs.nix
deleted file mode 100644
index cbb74a8..0000000
--- a/nix/lib/raidDebuffs.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{lib, ...}: let
-  # Full raid debuff configuration - all de
buffs enabled
-  fullDebuffs = {
-    physicalVulnerability = true;
-    weakenedArmor = true;
-  };
-
-  # No raid debuffs
-  noDebuffs = {
-    physicalVulnerability = false;
-    weakenedArmor = false;
-  };
-
-  # Function to merge custom debuffs with d
efaults
-  mergeRaidDebuffs = customDebuffs: fullDeb
uffs // customDebuffs;
-
-in {
-  inherit fullDebuffs noDebuffs mergeRaidDe
buffs;
-}
\ No newline at end of file
 

diff --git a/nix/lib/simulation.nix b/nix/lib/simulation.nix
index 3722c21..66c3d86 100644
--- a/nix/lib/simulation.nix
+++ b/nix/lib/simulation.nix
@@ -1,16 +1,41 @@
-let
+{lib, ...}: let
+  inherit (lib.sim.raid) mkRaid;
   mkSim = {
     requestId ? "raidSimAsync-b01aabae125f334e",
     type ? "SimTypeIndividual",
     iterations,
-    randomSeed ? 937883464,
-    raid,
-  }: {
-    inherit type raid requestId;
-    simOptions = {
-      inherit iterations randomSeed;
-      debugFirstIteration = true;
-    };
-  };
-in
-  mkSim
+    encounter,
+    randomSeed ? "1113857305",
+    raid ? null,
+    player ? null,
+    buffs ? null,
+    debuffs ? null,
+  }:
+  # Validation assertions
+    assert (player != null)
+    != (raid != null)
+    || throw "Must provide exactly one of 'player' or 'raid', not both";
+    assert (player != null)
+    -> (buffs != null && debuffs != null)
+    || throw "When using 'player', must also provide 'buffs' and 'debuffs'";
+    assert (raid != null)
+    -> (buffs == null && debuffs == null)
+    || throw "When using 'raid', do not provide 'buffs' or 'debuffs' (they should
 be in the raid)"; let
+      actualRaid =
+        if player != null
+        then
+          mkRaid {
+            party1 = [player];
+            inherit buffs debuffs;
+          }
+        else raid;
+    in
+      builtins.toJSON {
+        inherit type requestId encounter;
+        raid = actualRaid;
+        simOptions = {
+          inherit iterations randomSeed;
+          debugFirstIteration = true;
+        };
+      };
+in {inherit mkSim;}

diff --git a/nix/lib/simulation.nix b/nix/li
b/simulation.nix
index 3722c21..66c3d86 100644
--- a/nix/lib/simulation.nix
+++ b/nix/lib/simulation.nix
@@ -1,16 +1,41 @@
-let
+{lib, ...}: let
+  inherit (lib.sim.raid) mkRaid;
   mkSim = {
     requestId ? "raidSimAsync-b01aabae125f3
34e",
     type ? "SimTypeIndividual",
     iterations,
-    randomSeed ? 937883464,
-    raid,
-  }: {
-    inherit type raid requestId;
-    simOptions = {
-      inherit iterations randomSeed;
-      debugFirstIteration = true;
-    };
-  };
-in
-  mkSim
+    encounter,
+    randomSeed ? "1113857305",
+    raid ? null,
+    player ? null,
+    buffs ? null,
+    debuffs ? null,
+  }:
+  # Validation assertions
+    assert (player != null)
+    != (raid != null)
+    || throw "Must provide exactly one of '
player' or 'raid', not both";
+    assert (player != null)
+    -> (buffs != null && debuffs != null)
+    || throw "When using 'player', must als
o provide 'buffs' and 'debuffs'";
+    assert (raid != null)
+    -> (buffs == null && debuffs == null)
+    || throw "When using 'raid', do not pro
vide 'buffs' or 'debuffs' (they should be in
 the raid)"; let
+      actualRaid =
+        if player != null
+        then
+          mkRaid {
+            party1 = [player];
+            inherit buffs debuffs;
+          }
+        else raid;
+    in
+      builtins.toJSON {
+        inherit type requestId encounter;
+        raid = actualRaid;
+        simOptions = {
+          inherit iterations randomSeed;
+          debugFirstIteration = true;
+        };
+      };
+in {inherit mkSim;}
 

diff --git a/nix/lib/target.nix b/nix/lib/target.nix
index 0eba712..7343e63 100644
--- a/nix/lib/target.nix
+++ b/nix/lib/target.nix
@@ -9,19 +9,31 @@
     swingSpeed ? 2,
   }: {
     inherit id name level damageSpread swingSpeed minBaseDamage;
-    mobType = "MobType${lib.string.toSentenceCase type}";
+    mobType = "MobType${lib.strings.toSentenceCase type}";
+    # default stats
+    stats = [
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      650
+      0
+      0
+      0
+      0
+      24835
+      0
+      120016403
+      0
+      0
+    ];
   };
-  target = {
-    defaultRaidBoss = mkTarget {};
-    smallTrash = mkTarget {
-      level = 90;
-      minBaseDamage = 15000;
-    };
-    largeTrash = mkTarget {
-      level = 90;
-      minBaseDamage = 40000;
-    };
-    # todo add raid bosses
-  };
-in
-  target
+in {inherit mkTarget;}

diff --git a/nix/lib/target.nix b/nix/lib/ta
rget.nix
index 0eba712..7343e63 100644
--- a/nix/lib/target.nix
+++ b/nix/lib/target.nix
@@ -9,19 +9,31 @@
     swingSpeed ? 2,
   }: {
     inherit id name level damageSpread swin
gSpeed minBaseDamage;
-    mobType = "MobType${lib.string.toSenten
ceCase type}";
+    mobType = "MobType${lib.strings.toSente
nceCase type}";
+    # default stats
+    stats = [
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      0
+      650
+      0
+      0
+      0
+      0
+      24835
+      0
+      120016403
+      0
+      0
+    ];
   };
-  target = {
-    defaultRaidBoss = mkTarget {};
-    smallTrash = mkTarget {
-      level = 90;
-      minBaseDamage = 15000;
-    };
-    largeTrash = mkTarget {
-      level = 90;
-      minBaseDamage = 40000;
-    };
-    # todo add raid bosses
-  };
-in
-  target
+in {inherit mkTarget;}
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET