Function bodies 443 total
updateArchive function · typescript · L424-L437 (14 LOC)src/search/genetic-core.ts
function updateArchive(state: LoopState, maxArchiveSize: number): void {
for (const ind of state.population) {
const key = getPieceKey(ind);
const existing = state.archive.get(key);
if (existing == null || ind.score > existing.score) {
state.archive.set(key, ind);
}
}
// Trim archive to max size (keep highest-scoring entries)
if (state.archive.size > maxArchiveSize) {
const sorted = [...state.archive.entries()].sort((a, b) => b[1].score - a[1].score);
state.archive = new Map(sorted.slice(0, maxArchiveSize));
}
}GeneticSearch.search method · typescript · L486-L548 (63 LOC)src/search/genetic-core.ts
async search(
gearPool: GearPool,
constraints: HardConstraints,
fitness: readonly SoftConstraint[],
options: SearchOptions,
): Promise<readonly SearchResult[]> {
this.token.cancelled = false;
this.migrantQueue = [];
const pool = buildIndexedPool(gearPool);
const populationSize = options.populationSize ?? 200;
const generations = options.generations ?? 500;
const mutationRate = options.mutationRate ?? 0.15;
const crossoverRate = options.crossoverRate ?? 0.8;
this.totalGenerations = generations;
const population = initPopulation(pool, constraints, fitness, populationSize);
this.currentPopulation = population;
const evolveParams: EvolveParams = {
pool, constraints, fitness, populationSize, mutationRate, crossoverRate,
};
const state: LoopState = {
population,
archive: new Map(),
bestScore: population[0]?.score ?? -Infinity,
stagnation: 0,
injections: 0,
finalGeneration: 0,
getPieceForSlot function · typescript · L27-L35 (9 LOC)src/search/genetic-repair.ts
export function getPieceForSlot(
chromo: Chromosome,
slotIdx: number,
pool: IndexedPool,
): EquipmentPiece | undefined {
if (slotIdx === 0) return pool.chestplates[chromo.chestIdx];
if (slotIdx === 1) return pool.leggings[chromo.legsIdx];
return pool.accessories[chromo.accIndices[slotIdx - 2] ?? 0];
}repair function · typescript · L47-L61 (15 LOC)src/search/genetic-repair.ts
export function repair(
chromo: Chromosome,
pool: IndexedPool,
maxUnwardedInsanity?: number,
): void {
chromo.chestIdx = clamp(chromo.chestIdx, 0, pool.chestplates.length - 1);
chromo.legsIdx = clamp(chromo.legsIdx, 0, pool.leggings.length - 1);
repairAccessories(chromo, pool);
for (let i = 0; i < 5; i++) {
repairSlotIndices(chromo, i, pool);
}
if (maxUnwardedInsanity != null) {
repairInsanity(chromo, pool, maxUnwardedInsanity);
}
}repairAccessories function · typescript · L67-L78 (12 LOC)src/search/genetic-repair.ts
function repairAccessories(chromo: Chromosome, pool: IndexedPool): void {
for (let i = 0; i < 3; i++) {
chromo.accIndices[i] = clamp(chromo.accIndices[i] ?? 0, 0, pool.accessories.length - 1);
}
const accSet = new Set<number>();
for (let i = 0; i < 3; i++) {
let idx = chromo.accIndices[i] ?? 0;
while (accSet.has(idx)) { idx = (idx + 1) % pool.accessories.length; }
chromo.accIndices[i] = idx;
accSet.add(idx);
}
}repairSetModifier function · typescript · L84-L93 (10 LOC)src/search/genetic-repair.ts
function repairSetModifier(chromo: Chromosome, i: number, pool: IndexedPool): void {
const piece = getPieceForSlot(chromo, i, pool);
if (piece?.atlanteanOnly === false) return;
const modIdx = chromo.modIndices[i] ?? -1;
if (modIdx < 0) return;
const mod = pool.modifiers[modIdx];
if (mod != null && mod.atlanteanBehavior == null) {
chromo.modIndices[i] = pool.setModifierIndices[0] ?? -1;
}
}repairSlotIndices function · typescript · L103-L114 (12 LOC)src/search/genetic-repair.ts
function repairSlotIndices(chromo: Chromosome, i: number, pool: IndexedPool): void {
const enchPool = getEnchantPool(i, pool);
chromo.enchantIndices[i] = clamp(chromo.enchantIndices[i] ?? -1, -1, enchPool.length - 1);
chromo.modIndices[i] = clamp(chromo.modIndices[i] ?? -1, -1, pool.modifiers.length - 1);
repairSetModifier(chromo, i, pool);
const slotGems = chromo.gemIndices[i];
if (slotGems != null) {
for (let s = 0; s < slotGems.length; s++) {
slotGems[s] = clamp(slotGems[s] ?? -1, -1, pool.gems.length - 1);
}
}
}Repobility (the analyzer behind this table) · https://repobility.com
repairInsanity function · typescript · L129-L148 (20 LOC)src/search/genetic-repair.ts
function repairInsanity(
chromo: Chromosome,
pool: IndexedPool,
maxUnwarded: number,
): void {
const atlanteanSlots = gatherAtlanteanSlots(chromo, pool);
let totalInsanity = atlanteanSlots.reduce(
(sum, s) => sum + s.insanity, 0,
);
if (totalInsanity <= maxUnwarded) return;
shuffleInPlace(atlanteanSlots);
for (const entry of atlanteanSlots) {
if (totalInsanity <= maxUnwarded) break;
chromo.modIndices[entry.slot] = -1;
totalInsanity -= entry.insanity;
}
}gatherAtlanteanSlots function · typescript · L155-L169 (15 LOC)src/search/genetic-repair.ts
function gatherAtlanteanSlots(
chromo: Chromosome,
pool: IndexedPool,
): AtlanteanSlotEntry[] {
const entries: AtlanteanSlotEntry[] = [];
for (let i = 0; i < 5; i++) {
const modIdx = chromo.modIndices[i] ?? -1;
if (modIdx < 0) continue;
const mod = pool.modifiers[modIdx];
if (mod?.atlanteanBehavior != null) {
entries.push({ slot: i, insanity: mod.atlanteanBehavior.insanity });
}
}
return entries;
}shuffleInPlace function · typescript · L171-L181 (11 LOC)src/search/genetic-repair.ts
function shuffleInPlace(arr: unknown[]): void {
for (let i = arr.length - 1; i > 0; i--) {
const j = randInt(i + 1);
const tmp = arr[i];
const swp = arr[j];
if (tmp != null && swp != null) {
arr[i] = swp;
arr[j] = tmp;
}
}
}IslandCore.start method · typescript · L67-L96 (30 LOC)src/search/island-core.ts
start(config: IslandGAConfig): void {
this.search = new GeneticSearch();
// Wire up callbacks
this.search.onProgress = (checked, _total, bestScore, topResults) => {
this.callbacks.onProgress(checked, bestScore, topResults);
};
this.search.onStagnating = () => {
this.callbacks.onStagnating();
};
// Run the search
const { gearPool, constraints, fitness, options } = config;
this.search
.search(gearPool, constraints, fitness, options)
.then((results) => {
this.callbacks.onComplete(
results,
this.search?.exitReason ?? "complete",
this.search?.finalGeneration ?? 0,
);
this.search = null;
})
.catch((err: unknown) => {
const message = err instanceof Error ? err.message : "Unknown island error";
this.callbacks.onError(message);
this.search = null;
});
}IslandCore.stop method · typescript · L99-L104 (6 LOC)src/search/island-core.ts
stop(): void {
if (this.search != null) {
this.search.cancel();
this.search = null;
}
}secondaryStatMultiplier function · typescript · L55-L75 (21 LOC)src/search/multiplier-scoring.ts
export function secondaryStatMultiplier(stat: number, isHaste = false): number {
// Handle edge cases
if (stat <= 0) return 1;
const coef = isHaste ? 0.2 : 0.1;
const linearCoef = isHaste ? 0.3 : 0.15;
const denominator = 0.1 + 0.15 * Math.sqrt(175);
const logArg = coef * stat + 4;
// Guard against log of non-positive (shouldn't happen with stat > 0 and coef > 0)
if (logArg <= 0) return 1;
const logTerm = Math.pow(Math.log(logArg), 3) * 0.09 * 16;
const linearTerm = linearCoef * stat;
const numerator = logTerm + linearTerm;
const result = 1 + (1.35 / 100) * (numerator / denominator - 0.79);
// Ensure we don't return less than 1 due to floating point
return Math.max(1, result);
}computeMultiplierScore function · typescript · L105-L138 (34 LOC)src/search/multiplier-scoring.ts
export function computeMultiplierScore(
stats: Stats,
weights: Readonly<Record<StatName, number>>,
): number {
const defWeight = weights.defense / 100;
const powWeight = weights.power / 100;
// Base multiplier from power/defense
const defenseBonus = (1 + stats.defense / BASE_HEALTH) * defWeight;
const powerBonus = (stats.power / BASE_ATTACK) * powWeight;
const baseMultiplier = (defenseBonus + 1) * (powerBonus + 1);
// Secondary stats with diminishing returns
let secondaryMult = 1;
for (const statName of SECONDARY_STATS_WITH_WEIGHTS) {
const formulaWeight = STAT_FORMULA_WEIGHTS[statName];
if (formulaWeight == null) continue;
const value = stats[statName];
const userWeight = weights[statName] / 100;
// Skip if user weight is 0
if (userWeight === 0) continue;
const isHaste = statName === "haste";
const statMult = secondaryStatMultiplier(value, isHaste);
// Apply formula weight and user weight via exponentiation
secondaryisRelevantItem function · typescript · L55-L66 (12 LOC)src/search/pool-filter.ts
function isRelevantItem(item: EquipmentPiece, targetStats: Set<StatName>): boolean {
// Keep items with sockets (enhancements can contribute goal stats)
if (item.socketCount > 0) return true;
// Keep items that contribute any goal stat (positive or negative)
const stats = getEffectiveStats(item);
for (const stat of targetStats) {
if ((stats[stat] ?? 0) !== 0) return true;
}
return false;
}Repobility · MCP-ready · https://repobility.com
filterEquipment function · typescript · L71-L77 (7 LOC)src/search/pool-filter.ts
function filterEquipment(
items: readonly EquipmentPiece[],
targetStats: Set<StatName>,
): readonly EquipmentPiece[] {
if (targetStats.size === 0) return items; // No goals = keep all
return items.filter((item) => isRelevantItem(item, targetStats));
}formatFilterStats function · typescript · L129-L143 (15 LOC)src/search/pool-filter.ts
export function formatFilterStats(stats: PoolFilterStats): string | null {
const prunedChest = stats.original.chestplates - stats.filtered.chestplates;
const prunedLegs = stats.original.leggings - stats.filtered.leggings;
const prunedAcc = stats.original.accessories - stats.filtered.accessories;
const totalPruned = prunedChest + prunedLegs + prunedAcc;
if (totalPruned === 0) return null;
const parts: string[] = [];
if (prunedChest > 0) parts.push(`${String(prunedChest)} chest`);
if (prunedLegs > 0) parts.push(`${String(prunedLegs)} legs`);
if (prunedAcc > 0) parts.push(`${String(prunedAcc)} acc`);
return `Pruned ${parts.join(", ")} (no goal stats)`;
}checkBetween function · typescript · L38-L46 (9 LOC)src/search/satisfaction.ts
function checkBetween(value: number, min: number, max: number): SatisfactionLevel {
if (value >= min && value <= max) return "positive";
const belowMin = min - value;
const aboveMax = value - max;
const margin = (max - min) * 0.1 || 1;
if (belowMin > 0 && belowMin <= margin) return "warning";
if (aboveMax > 0 && aboveMax <= margin) return "warning";
return "negative";
}getSatisfaction function · typescript · L66-L71 (6 LOC)src/search/satisfaction.ts
export function getSatisfaction(
value: number,
constraint: SoftConstraint,
): SatisfactionLevel {
return CHECKERS[constraint.type](value, constraint.value, constraint.hardCap);
}emptyStats function · typescript · L59-L74 (16 LOC)src/search/stats.ts
export function emptyStats(): Stats {
return {
power: 0,
defense: 0,
size: 0,
dexterity: 0,
range: 0,
haste: 0,
insanity: 0,
warding: 0,
drawback: 0,
regeneration: 0,
pierce: 0,
resistance: 0,
};
}sumStats function · typescript · L77-L85 (9 LOC)src/search/stats.ts
export function sumStats(...blocks: readonly Partial<Stats>[]): Stats {
const result = emptyStats();
for (const block of blocks) {
for (const name of STAT_NAMES) {
result[name] += block[name] ?? 0;
}
}
return result;
}getValidAtlanteanChoices function · typescript · L103-L115 (13 LOC)src/search/stats.ts
export function getValidAtlanteanChoices(
slot: EquippedSlot,
): readonly StatName[] {
const config = slot.modifier?.atlanteanBehavior;
if (config == null) return [];
const pieceStats = getPieceStats(slot.piece);
return config.possibleBonusStats.filter((stat) => {
if (hasNonZeroStat(pieceStats, stat)) return false;
if (slot.enchantment != null && hasNonZeroStat(slot.enchantment.stats, stat)) return false;
return !slot.gems.some((gem) => hasNonZeroStat(gem.stats, stat));
});
}getAtlanteanBonusStat function · typescript · L124-L129 (6 LOC)src/search/stats.ts
export function getAtlanteanBonusStat(
slot: EquippedSlot,
): StatName | null {
const choices = getValidAtlanteanChoices(slot);
return choices[0] ?? null;
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
resolveAtlanteanBonus function · typescript · L137-L148 (12 LOC)src/search/stats.ts
export function resolveAtlanteanBonus(
slot: EquippedSlot,
atlanteanChoice: StatName | null,
): Partial<Stats> {
if (atlanteanChoice == null) return {};
if (slot.modifier?.atlanteanBehavior == null) return {};
const bonusValue = ATLANTEAN_BONUS_VALUES[atlanteanChoice];
if (bonusValue === 0) return {};
return { [atlanteanChoice]: bonusValue };
}computeLoadoutStats function · typescript · L160-L179 (20 LOC)src/search/stats.ts
export function computeLoadoutStats(
loadout: Loadout,
atlanteanChoices?: ReadonlyMap<number, StatName>,
): Stats {
const slotBlocks: Partial<Stats>[] = [];
for (let i = 0; i < loadout.slots.length; i++) {
const slot = loadout.slots[i];
if (slot == null) continue;
slotBlocks.push(computeSlotStats(slot));
if (slot.modifier?.atlanteanBehavior != null) {
const choice = atlanteanChoices?.get(i) ?? null;
slotBlocks.push(resolveAtlanteanBonus(slot, choice));
}
}
return sumStats(...slotBlocks);
}getNumericProperty function · typescript · L71-L77 (7 LOC)src/stores/fitness-store-migrations.ts
function getNumericProperty(obj: object, key: string): number | undefined {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const val = Reflect.get(obj, key) as unknown;
if (typeof val === "number") return val;
}
return undefined;
}parseStatWeights function · typescript · L83-L98 (16 LOC)src/stores/fitness-store-migrations.ts
function parseStatWeights(
value: unknown,
fallback: Readonly<Record<StatName, number>>,
): StatWeights {
if (value == null || typeof value !== "object" || Array.isArray(value)) {
return fallback;
}
const merged = { ...DEFAULT_STAT_WEIGHTS };
for (const statKey of STAT_NAME_LIST) {
const numVal = getNumericProperty(value, statKey);
if (numVal !== undefined) {
merged[statKey] = numVal;
}
}
return merged;
}parseStatLimits function · typescript · L100-L112 (13 LOC)src/stores/fitness-store-migrations.ts
function parseStatLimits(value: unknown): StatLimits {
if (value == null || typeof value !== "object" || Array.isArray(value)) {
return DEFAULT_LIMITS;
}
const insanityVal = getNumericProperty(value, "insanity");
const wardingVal = getNumericProperty(value, "warding");
const drawbackVal = getNumericProperty(value, "drawback");
return {
insanity: insanityVal ?? DEFAULT_LIMITS.insanity,
warding: wardingVal ?? DEFAULT_LIMITS.warding,
drawback: drawbackVal ?? DEFAULT_LIMITS.drawback,
};
}parseStatMinimums function · typescript · L114-L126 (13 LOC)src/stores/fitness-store-migrations.ts
function parseStatMinimums(value: unknown): StatMinimums {
if (value == null || typeof value !== "object" || Array.isArray(value)) {
return DEFAULT_MINIMUMS;
}
const result: Partial<Record<StatName, number>> = {};
for (const statKey of STAT_NAME_LIST) {
const numVal = getNumericProperty(value, statKey);
if (numVal !== undefined) {
result[statKey] = numVal;
}
}
return result;
}parseConstraintsModeConfig function · typescript · L128-L136 (9 LOC)src/stores/fitness-store-migrations.ts
export function parseConstraintsModeConfig(value: unknown): ConstraintsModeConfig {
if (value == null || typeof value !== "object" || Array.isArray(value)) {
return DEFAULT_CONSTRAINTS_CONFIG;
}
const obj = value as { constraints?: unknown };
return {
constraints: Array.isArray(obj.constraints) ? obj.constraints : [],
};
}parseWeightsModeConfig function · typescript · L138-L148 (11 LOC)src/stores/fitness-store-migrations.ts
export function parseWeightsModeConfig(value: unknown): WeightsModeConfig {
if (value == null || typeof value !== "object" || Array.isArray(value)) {
return DEFAULT_WEIGHTS_CONFIG;
}
const obj = value as { limits?: unknown; minimums?: unknown; weights?: unknown };
return {
limits: parseStatLimits(obj.limits),
minimums: parseStatMinimums(obj.minimums),
weights: parseStatWeights(obj.weights, DEFAULT_STAT_WEIGHTS),
};
}Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
migrateConstraints function · typescript · L154-L161 (8 LOC)src/stores/fitness-store-migrations.ts
function migrateConstraints(raw: readonly SoftConstraint[]): readonly SoftConstraint[] {
return raw.map((c) => {
if (c.stat === "insanity" && c.type === "exactly") {
return { ...c, type: "atMost" as const };
}
return c;
});
}migrateFromV4Plus function · typescript · L163-L175 (13 LOC)src/stores/fitness-store-migrations.ts
function migrateFromV4Plus(raw: Partial<FitnessSerialized>): FitnessState {
return {
scoringMode: isValidScoringMode(raw.scoringMode) ? raw.scoringMode : "linear",
enabledVariants: Array.isArray(raw.enabledVariants)
? new Set<string>(raw.enabledVariants)
: new Set<string>(),
constraintsConfig: parseConstraintsModeConfig(raw.constraintsConfig),
efficiencyConfig: parseWeightsModeConfig(raw.efficiencyConfig),
multiplierConfig: parseWeightsModeConfig(raw.multiplierConfig),
activeProfileId: typeof raw.activeProfileId === "string" ? raw.activeProfileId : null,
hasUnsavedChanges: typeof raw.hasUnsavedChanges === "boolean" ? raw.hasUnsavedChanges : false,
};
}migrateFromLegacy function · typescript · L177-L200 (24 LOC)src/stores/fitness-store-migrations.ts
function migrateFromLegacy(legacy: LegacyFitnessSerialized): FitnessState {
const constraints = Array.isArray(legacy.constraints)
? migrateConstraints(legacy.constraints)
: [];
const statWeights = parseStatWeights(legacy.statWeights, DEFAULT_STAT_WEIGHTS);
const constraintsConfig: ConstraintsModeConfig = { constraints };
const weightsConfig: WeightsModeConfig = {
limits: DEFAULT_LIMITS,
minimums: DEFAULT_MINIMUMS,
weights: statWeights,
};
return {
scoringMode: isValidScoringMode(legacy.scoringMode) ? legacy.scoringMode : "linear",
enabledVariants: Array.isArray(legacy.enabledVariants)
? new Set<string>(legacy.enabledVariants)
: new Set<string>(),
constraintsConfig,
efficiencyConfig: weightsConfig,
multiplierConfig: weightsConfig,
activeProfileId: typeof legacy.activeProfileId === "string" ? legacy.activeProfileId : null,
hasUnsavedChanges: typeof legacy.hasUnsavedChanges === "boolean" ? legacy.hasUnsavedChanges : migrateFitnessState function · typescript · L202-L210 (9 LOC)src/stores/fitness-store-migrations.ts
export function migrateFitnessState(
persisted: unknown,
version: number,
initialState: FitnessState,
): FitnessState {
if (persisted == null || typeof persisted !== "object") return initialState;
if (version >= 4) return migrateFromV4Plus(persisted as Partial<FitnessSerialized>);
return migrateFromLegacy(persisted as LegacyFitnessSerialized);
}mergePersistedState function · typescript · L212-L233 (22 LOC)src/stores/fitness-store-migrations.ts
export function mergePersistedState<T extends FitnessState>(
persisted: unknown,
current: T,
): T {
if (persisted == null || typeof persisted !== "object") {
return current;
}
const raw = persisted as Partial<FitnessSerialized>;
return {
...current,
scoringMode: isValidScoringMode(raw.scoringMode) ? raw.scoringMode : current.scoringMode,
enabledVariants: Array.isArray(raw.enabledVariants)
? new Set<string>(raw.enabledVariants)
: current.enabledVariants,
constraintsConfig: raw.constraintsConfig ?? current.constraintsConfig,
efficiencyConfig: raw.efficiencyConfig ?? current.efficiencyConfig,
multiplierConfig: raw.multiplierConfig ?? current.multiplierConfig,
activeProfileId: typeof raw.activeProfileId === "string" ? raw.activeProfileId : current.activeProfileId,
hasUnsavedChanges: typeof raw.hasUnsavedChanges === "boolean" ? raw.hasUnsavedChanges : current.hasUnsavedChanges,
};
}buildInitialStateFromProfile function · typescript · L73-L83 (11 LOC)src/stores/fitness-store.ts
function buildInitialStateFromProfile(profile: ProfileConfig & { id?: string }): FitnessState {
return {
scoringMode: profile.scoringMode,
enabledVariants: new Set<string>(profile.enabledVariants),
constraintsConfig: profile.constraintsConfig,
efficiencyConfig: profile.efficiencyConfig,
multiplierConfig: profile.multiplierConfig,
activeProfileId: profile.id ?? null,
hasUnsavedChanges: false,
};
}getDefaultFitnessState function · typescript · L85-L95 (11 LOC)src/stores/fitness-store.ts
function getDefaultFitnessState(): FitnessState {
return {
scoringMode: "linear",
enabledVariants: new Set<string>(),
constraintsConfig: DEFAULT_CONSTRAINTS_CONFIG,
efficiencyConfig: DEFAULT_WEIGHTS_CONFIG,
multiplierConfig: DEFAULT_WEIGHTS_CONFIG,
activeProfileId: null,
hasUnsavedChanges: false,
};
}getInitialState function · typescript · L97-L102 (6 LOC)src/stores/fitness-store.ts
function getInitialState(): FitnessState {
const defaults = loadDefaultProfiles();
const firstProfile = defaults[0];
if (!firstProfile) return getDefaultFitnessState();
return buildInitialStateFromProfile(firstProfile);
}Repobility (the analyzer behind this table) · https://repobility.com
createSetStorage function · typescript · L110-L118 (9 LOC)src/stores/fitness-store.ts
function createSetStorage(): ReturnType<typeof createJSONStorage<FitnessState>> {
return createJSONStorage<FitnessState>(() => localStorage, {
replacer: (_key: string, value: unknown): unknown => {
if (value instanceof Set) return [...value];
return value;
},
reviver: (_key: string, value: unknown): unknown => value,
});
}toggleSetItem function · typescript · L124-L129 (6 LOC)src/stores/fitness-store.ts
function toggleSetItem(set: ReadonlySet<string>, item: string): ReadonlySet<string> {
const next = new Set(set);
if (next.has(item)) next.delete(item);
else next.add(item);
return next;
}addVariantsOfType function · typescript · L131-L138 (8 LOC)src/stores/fitness-store.ts
function addVariantsOfType(current: ReadonlySet<string>, typeId: string): ReadonlySet<string> {
const variantTypes = loadVariantTypes();
const typeEntry = variantTypes[typeId];
if (!typeEntry) return current;
const next = new Set(current);
for (const v of typeEntry.variants) next.add(v);
return next;
}removeVariantsOfType function · typescript · L140-L147 (8 LOC)src/stores/fitness-store.ts
function removeVariantsOfType(current: ReadonlySet<string>, typeId: string): ReadonlySet<string> {
const variantTypes = loadVariantTypes();
const typeEntry = variantTypes[typeId];
if (!typeEntry) return current;
const next = new Set(current);
for (const v of typeEntry.variants) next.delete(v);
return next;
}createConstraintActions function · typescript · L156-L182 (27 LOC)src/stores/fitness-store.ts
function createConstraintActions(set: SetFn): Pick<FitnessActions,
"setConstraints" | "addConstraint" | "removeConstraint" | "updateConstraint"
> {
return {
setConstraints: (constraints) => {
set({ constraintsConfig: { constraints }, hasUnsavedChanges: true });
},
addConstraint: (constraint) => {
set((s) => ({
constraintsConfig: { constraints: [...s.constraintsConfig.constraints, constraint] },
hasUnsavedChanges: true,
}));
},
removeConstraint: (index) => {
set((s) => ({
constraintsConfig: { constraints: s.constraintsConfig.constraints.filter((_, i) => i !== index) },
hasUnsavedChanges: true,
}));
},
updateConstraint: (index, constraint) => {
set((s) => ({
constraintsConfig: { constraints: s.constraintsConfig.constraints.map((c, i) => (i === index ? constraint : c)) },
hasUnsavedChanges: true,
}));
},
};
}createVariantActions function · typescript · L184-L199 (16 LOC)src/stores/fitness-store.ts
function createVariantActions(set: SetFn): Pick<FitnessActions,
"toggleVariant" | "setEnabledVariants" | "enableAllVariantsOfType" | "disableAllVariantsOfType"
> {
return {
toggleVariant: (variant) => {
set((s) => ({ enabledVariants: toggleSetItem(s.enabledVariants, variant), hasUnsavedChanges: true }));
},
setEnabledVariants: (variants) => { set({ enabledVariants: variants, hasUnsavedChanges: true }); },
enableAllVariantsOfType: (typeId) => {
set((s) => ({ enabledVariants: addVariantsOfType(s.enabledVariants, typeId), hasUnsavedChanges: true }));
},
disableAllVariantsOfType: (typeId) => {
set((s) => ({ enabledVariants: removeVariantsOfType(s.enabledVariants, typeId), hasUnsavedChanges: true }));
},
};
}createScoringActions function · typescript · L204-L244 (41 LOC)src/stores/fitness-store.ts
function createScoringActions(set: SetFn, get: GetFn): Pick<FitnessActions,
"setScoringMode" | "getCurrentModeConfig" | "setLimit" | "setMinimum" | "setWeight" | "resetWeights"
> {
return {
setScoringMode: (mode) => { set({ scoringMode: mode, hasUnsavedChanges: true }); },
getCurrentModeConfig: () => {
const s = get();
return s.scoringMode === "linear" ? s.constraintsConfig : s[getConfigKey(s.scoringMode)];
},
setLimit: (stat, value) => {
set((s) => {
if (s.scoringMode === "linear") return s;
const key = getConfigKey(s.scoringMode);
return { [key]: { ...s[key], limits: { ...s[key].limits, [stat]: value } }, hasUnsavedChanges: true };
});
},
setMinimum: (stat, value) => {
set((s) => {
if (s.scoringMode === "linear") return s;
const key = getConfigKey(s.scoringMode);
const { [stat]: _removed, ...rest } = s[key].minimums;
const minimums = value === null ? rest : { ...s[key].micreateProfileActions function · typescript · L246-L274 (29 LOC)src/stores/fitness-store.ts
function createProfileActions(set: SetFn, get: GetFn): Pick<FitnessActions,
"applyProfile" | "getCurrentConfig" | "markDirty" | "markClean"
> {
return {
applyProfile: (id, config) => {
set({
scoringMode: config.scoringMode,
enabledVariants: new Set(config.enabledVariants),
constraintsConfig: config.constraintsConfig,
efficiencyConfig: config.efficiencyConfig,
multiplierConfig: config.multiplierConfig,
activeProfileId: id,
hasUnsavedChanges: false,
});
},
getCurrentConfig: () => {
const s = get();
return {
scoringMode: s.scoringMode,
enabledVariants: [...s.enabledVariants],
constraintsConfig: s.constraintsConfig,
efficiencyConfig: s.efficiencyConfig,
multiplierConfig: s.multiplierConfig,
};
},
markDirty: () => { set({ hasUnsavedChanges: true }); },
markClean: () => { set({ hasUnsavedChanges: false }); },
};
}Repobility · MCP-ready · https://repobility.com
toggleSetItem function · typescript · L48-L56 (9 LOC)src/stores/gear-pool-store.ts
function toggleSetItem(set: ReadonlySet<string>, id: string): ReadonlySet<string> {
const next = new Set(set);
if (next.has(id)) {
next.delete(id);
} else {
next.add(id);
}
return next;
}createSetStorage function · typescript · L73-L83 (11 LOC)src/stores/gear-pool-store.ts
function createSetStorage(): ReturnType<typeof createJSONStorage<GearPoolState>> {
return createJSONStorage<GearPoolState>(() => localStorage, {
replacer: (_key: string, value: unknown): unknown => {
if (value instanceof Set) {
return [...value];
}
return value;
},
reviver: (_key: string, value: unknown): unknown => value,
});
}mergePersistedState function · typescript · L89-L127 (39 LOC)src/stores/gear-pool-store.ts
function mergePersistedState(
persisted: unknown,
current: GearPoolState & GearPoolActions,
): GearPoolState & GearPoolActions {
if (persisted == null || typeof persisted !== "object") {
return current;
}
const raw = persisted as Partial<GearPoolSerialized>;
const allEquipmentIds = new Set(loadEquipment().map((e) => e.id));
const allEnchantmentIds = new Set(loadEnchantments().map((e) => e.id));
const allModifierIds = new Set(loadModifiers().map((m) => m.id));
const allGemIds = new Set(loadGems().map((g) => g.id));
// Merge persisted IDs, adding any new items not in persisted set
const mergeIds = (
persistedIds: string[] | undefined,
allIds: Set<string>,
): Set<string> => {
if (!Array.isArray(persistedIds)) return allIds;
const persisted = new Set<string>(persistedIds);
// Add any new IDs that weren't in the persisted set
for (const id of allIds) {
if (!persisted.has(id)) persisted.add(id);
}
// Remove IDs that no longer