Add adult verification and erotic moderation features: Implement new routes and controller methods for managing adult verification requests, status updates, and document retrieval. Introduce erotic moderation actions and reports, enhancing administrative capabilities. Update chat and navigation controllers to support adult content filtering and access control. Enhance user parameter handling for adult verification status and requests, improving overall user experience and compliance.
This commit is contained in:
96
backend/utils/falukant/falukantProductEconomy.js
Normal file
96
backend/utils/falukant/falukantProductEconomy.js
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Zentrale Produktions- und Preisformeln (muss mit der Spielwirtschaft konsistent bleiben).
|
||||
* Wird von falukantService und der Produkt-Initialisierung genutzt.
|
||||
*
|
||||
* Mindest-Erlös (Ertrags-Tabelle, Branch): bei 100 % Produktwissen ist der Verkaufspreis
|
||||
* das obere Ende der Spanne = basePrice = sellCost * (effectiveWorth/100), mit
|
||||
* effectiveWorth >= 75 (siehe effectiveWorthPercent in falukantService).
|
||||
* Engster Fall für Gewinn/Stück: Zertifikat = Produktkategorie (kein Headroom-Rabatt auf
|
||||
* Stückkosten) und regionale Nachfrage am Boden (75 %).
|
||||
*/
|
||||
|
||||
export const PRODUCTION_COST_BASE = 6.0;
|
||||
export const PRODUCTION_COST_PER_PRODUCT_CATEGORY = 1.0;
|
||||
export const PRODUCTION_HEADROOM_DISCOUNT_PER_STEP = 0.035;
|
||||
export const PRODUCTION_HEADROOM_DISCOUNT_CAP = 0.14;
|
||||
|
||||
export function productionPieceCost(certificate, category) {
|
||||
const c = Math.max(1, Number(category) || 1);
|
||||
const cert = Math.max(1, Number(certificate) || 1);
|
||||
const raw = PRODUCTION_COST_BASE + (c * PRODUCTION_COST_PER_PRODUCT_CATEGORY);
|
||||
const headroom = Math.max(0, cert - c);
|
||||
const discount = Math.min(
|
||||
headroom * PRODUCTION_HEADROOM_DISCOUNT_PER_STEP,
|
||||
PRODUCTION_HEADROOM_DISCOUNT_CAP
|
||||
);
|
||||
return raw * (1 - discount);
|
||||
}
|
||||
|
||||
export function productionCostTotal(quantity, category, certificate) {
|
||||
const q = Math.min(100, Math.max(1, Number(quantity) || 1));
|
||||
return q * productionPieceCost(certificate, category);
|
||||
}
|
||||
|
||||
export 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 regionalen Basispreis. */
|
||||
export const KNOWLEDGE_PRICE_FLOOR = 0.7;
|
||||
|
||||
export function calcSellPrice(product, knowledgeFactor = 0) {
|
||||
const max = product.sellCost;
|
||||
const min = max * KNOWLEDGE_PRICE_FLOOR;
|
||||
return min + (max - min) * (knowledgeFactor / 100);
|
||||
}
|
||||
|
||||
export function calcRegionalSellPriceSync(product, knowledgeFactor, worthPercent) {
|
||||
if (product.sellCost === null || product.sellCost === undefined) return null;
|
||||
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);
|
||||
}
|
||||
|
||||
/** Untergrenze für worthPercent nach effectiveWorthPercent (75–100). */
|
||||
export const EFFECTIVE_WORTH_PERCENT_MIN = 75;
|
||||
|
||||
/**
|
||||
* Minimaler ganzzahliger Basis-sell_cost (vor Steuer-/Regions-Faktoren in der DB),
|
||||
* sodass bei Zertifikat = Produktkategorie, 100 % Wissen und 75 % Nachfrage
|
||||
* der Erlös pro Stück >= Stückkosten (kein struktureller Verlust in der Ertrags-Tabelle).
|
||||
*/
|
||||
export function minBaseSellCostForTightProduction(category) {
|
||||
const c = Math.max(1, Number(category) || 1);
|
||||
const cost = productionPieceCost(c, c);
|
||||
return Math.ceil((cost * 100) / EFFECTIVE_WORTH_PERCENT_MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft Vordefinierungen; meldet Abweichungen nur per warn (kein Throw), damit Deployments
|
||||
* mit alter DB nicht brechen — Balance-Anpassung erfolgt bewusst im Code/SQL.
|
||||
*/
|
||||
export function validateProductBaseSellCosts(products, { warn = console.warn } = {}) {
|
||||
const issues = [];
|
||||
for (const p of products) {
|
||||
const min = minBaseSellCostForTightProduction(p.category);
|
||||
if (Number(p.sellCost) < min) {
|
||||
issues.push({
|
||||
labelTr: p.labelTr,
|
||||
category: p.category,
|
||||
sellCost: p.sellCost,
|
||||
minRequired: min,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (issues.length && typeof warn === 'function') {
|
||||
warn(
|
||||
'[falukantProductEconomy] sell_cost unter Mindestbedarf (Zertifikat=Kategorie, 100% Wissen, 75% Nachfrage):',
|
||||
issues
|
||||
);
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
Reference in New Issue
Block a user