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:
Torsten Schulz (local)
2026-03-27 09:14:54 +01:00
parent f93687c753
commit 3e6c09ab29
73 changed files with 4459 additions and 197 deletions

View File

@@ -76,6 +76,13 @@ import ProductWeatherEffect from '../models/falukant/type/product_weather_effect
import WeatherType from '../models/falukant/type/weather.js';
import ReputationActionType from '../models/falukant/type/reputation_action.js';
import ReputationActionLog from '../models/falukant/log/reputation_action.js';
import {
productionPieceCost,
productionCostTotal,
effectiveWorthPercent,
KNOWLEDGE_PRICE_FLOOR,
calcRegionalSellPriceSync,
} from '../utils/falukant/falukantProductEconomy.js';
function calcAge(birthdate) {
const b = new Date(birthdate); b.setHours(0, 0);
@@ -97,54 +104,6 @@ async function getBranchOrFail(userId, branchId) {
return branch;
}
const PRODUCTION_COST_BASE = 6.0;
const PRODUCTION_COST_PER_PRODUCT_CATEGORY = 1.0;
const PRODUCTION_HEADROOM_DISCOUNT_PER_STEP = 0.035;
const PRODUCTION_HEADROOM_DISCOUNT_CAP = 0.14;
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);
}
function productionCostTotal(quantity, category, certificate) {
const q = Math.min(100, Math.max(1, Number(quantity) || 1));
return q * productionPieceCost(certificate, category);
}
/** 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 * 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 w = effectiveWorthPercent(worthPercent);
const basePrice = product.sellCost * (w / 100);
const min = basePrice * KNOWLEDGE_PRICE_FLOOR;
const max = basePrice;
return min + (max - min) * (knowledgeFactor / 100);
}
const POLITICAL_OFFICE_RANKS = {
assessor: 1,
councillor: 1,