Update environment configuration and enhance logging: Add support for loading a local .env file and improve logging behavior based on QUIET_ENV_LOGS settings. Introduce new diagnostic scripts in package.json for town worth and money flow analysis. Adjust production cost calculations in FalukantService to align with updated pricing logic and enhance product initialization parameters.

This commit is contained in:
Torsten Schulz (local)
2026-03-25 13:23:51 +01:00
parent 44991743d2
commit 8af726c65a
15 changed files with 498 additions and 46 deletions

View File

@@ -97,17 +97,40 @@ async function getBranchOrFail(userId, branchId) {
return branch;
}
/**
* Gesamtkosten für eine Produktionscharge (früher: quantity * category * 6 pro Einheit).
* Pro Einheit jetzt 2 * Kategorie (z.B. Kat.1 = 2, Kat.2 = 4), damit Nettoerlös und
* typischer town_product_worth (oft 4060 %, siehe Model-Hook) zusammenpassen.
*/
function productionCostTotal(quantity, category) {
const c = Math.max(1, Number(category) || 1);
const q = Math.min(100, Math.max(1, Number(quantity) || 1));
const perUnit = 2 * c;
return q * perUnit;
}
/** Regionaler Nachfragewert: sehr niedrige Werte aus der DB sonst unspielbar; Decke nach oben bei 100. */
function effectiveWorthPercent(worthPercent) {
const w = Number(worthPercent);
if (Number.isNaN(w)) return 75;
return Math.min(100, Math.max(75, w));
}
/** Untergrenze für den Wissens-Multiplikator auf den Basispreis (0 = minAnteil, 100 = voller Basispreis). */
const KNOWLEDGE_PRICE_FLOOR = 0.7;
function calcSellPrice(product, knowledgeFactor = 0) {
const max = product.sellCost;
const min = max * 0.6;
const min = max * KNOWLEDGE_PRICE_FLOOR;
return min + (max - min) * (knowledgeFactor / 100);
}
/** Synchrone Preisberechnung, wenn worthPercent bereits bekannt ist (kein DB-Zugriff). */
function calcRegionalSellPriceSync(product, knowledgeFactor, worthPercent) {
if (product.sellCost === null || product.sellCost === undefined) return null;
const basePrice = product.sellCost * (worthPercent / 100);
const min = basePrice * 0.6;
const w = effectiveWorthPercent(worthPercent);
const basePrice = product.sellCost * (w / 100);
const min = basePrice * KNOWLEDGE_PRICE_FLOOR;
const max = basePrice;
return min + (max - min) * (knowledgeFactor / 100);
}
@@ -224,17 +247,16 @@ async function calcRegionalSellPrice(product, knowledgeFactor, regionId, worthPe
});
worthPercent = townWorth?.worthPercent || 50; // Default 50% wenn nicht gefunden
}
// Prüfe ob sellCost vorhanden ist
if (product.sellCost === null || product.sellCost === undefined) {
throw new Error(`Product ${product.id} has no sellCost defined`);
}
// Basispreis basierend auf regionalem worthPercent
const basePrice = product.sellCost * (worthPercent / 100);
// Dann Knowledge-Faktor anwenden
const min = basePrice * 0.6;
const w = effectiveWorthPercent(worthPercent);
const basePrice = product.sellCost * (w / 100);
const min = basePrice * KNOWLEDGE_PRICE_FLOOR;
const max = basePrice;
return min + (max - min) * (knowledgeFactor / 100);
}
@@ -2031,7 +2053,7 @@ class FalukantService extends BaseService {
}
if (!p) throw new Error('Product not found');
quantity = Math.min(100, quantity);
const cost = quantity * p.category * 6;
const cost = productionCostTotal(quantity, p.category);
if (u.money < cost) throw new Error('notenoughmoney');
const r = await updateFalukantUserMoney(u.id, -cost, 'Production cost', u.id);
if (!r.success) throw new Error('Failed to update money');