import { bagSpecParser, parseDelimiters, splitOn, splitOnLast } from "./string_utils.js";
import { createBag } from "./create_bag.js";
import { createItem } from "./create_item.js";
import { logger } from "./utils.js";
import { random, roll, test } from "./random_utils.js";
import { ymlParser } from "./data_loaders.js";
import Bag from "./models/bag.js";
async function parseContainers() {
const config = {};
const parser = ymlParser({
keyProp: "name",
lists: ["desc", "items"],
});
const data = await parser("containers.data");
for (const entry of data) {
if (entry.desc) {
entry.description = entry.desc;
delete entry.desc;
}
if (entry.items) {
entry.items = entry.items.reduce((acc, item) => {
let [itemTag, itemCount] = splitOnLast(item, " ");
acc[itemTag] = parseInt(itemCount);
return acc;
}, {});
}
let [hasDelimiters, nameStr, usedStr] = parseDelimiters(entry.name);
entry.name = nameStr;
if (hasDelimiters) {
let [percent, text] = splitOn(usedStr, " ");
entry.qualPercent = parseInt(percent.replace("%", ""));
entry.qual = text;
}
config[entry.name] = entry;
}
return config;
}
const CONFIG = await parseContainers();
const CONTAINER_TYPES = Object.keys(CONFIG);
export function getContainerTypes() {
return CONTAINER_TYPES;
}
function getCount(isUsed, maxCount) {
if (isUsed && maxCount === 1) {
return test(70) ? 1 : 0;
}
return isUsed ? roll(maxCount) : maxCount;
}
/**
* Creates a container (e.g., a first aid kit, cabinet, or ammunition box) of a given type,
* potentially pre-filled with items. Containers may be empty or show signs of prior use.
*
* @param {Object} [options={}] - Container creation options
* @param {string} [options.type] - Type of container to create, selected from the values returned by
* `getContainerTypes()`. If not provided, a type is randomly selected.
* @returns {Bag} A new Bag instance (extends Bag) with a name, optional description, and items
*/
export function createContainer({ type = random(CONTAINER_TYPES) } = {}) {
logger.start("createContainer", { type });
if (!CONFIG[type]) {
throw new Error('Invalid container type: "' + type + '"');
}
let config = CONFIG[type];
let isUsed = config.qual === "used" && test(config.qualPercent ?? 0);
let isEmpty = config.qual === "empty" && test(config.qualPercent ?? 0);
let descParts = [
config.description ? random(config.description) : undefined,
isUsed ? "used" : undefined,
];
let description = descParts.filter(Boolean).join(" ") || undefined;
let bag = new Bag({ name: config.name, description });
if (!isEmpty) {
if (config.query) {
let bagConfig = bagSpecParser(config.query);
bag = createBag({ ...bagConfig, name: config.name, description });
} else if (config.items) {
bag = new Bag({ name: config.name, description });
for (let tags of Object.keys(config.items)) {
let maxCount = config.items[tags];
let item = createItem({ tags });
let count = getCount(isUsed, maxCount);
bag.add(item, count);
}
}
}
return logger.end(bag);
}