feat(political-office): enhance political office benefits and salary computation
All checks were successful
Deploy to production / deploy (push) Successful in 3m6s
All checks were successful
Deploy to production / deploy (push) Successful in 3m6s
- Added a new hierarchyLevel field to PoliticalOfficeType for better categorization of political roles. - Updated computePoliticalDailySalaryPayout function to incorporate hierarchy level in salary calculations, allowing for more dynamic salary adjustments based on office rank. - Modified SQL scripts to reflect changes in political office benefits, ensuring compatibility with the new salary structure. - Enhanced localization files to support updated benefit descriptions and salary formats across multiple languages. - Improved UI components to display the new salary calculations and benefits accurately in the PoliticsView.
This commit is contained in:
@@ -134,15 +134,53 @@ const POLITICAL_OFFICE_RANKS = {
|
||||
chancellor: 6
|
||||
};
|
||||
|
||||
function computePoliticalDailySalaryPayout(value, officeName) {
|
||||
const _envPolSalaryStart = Number(process.env.POLITICAL_DAILY_SALARY_START);
|
||||
const _envPolSalaryGrowth = Number(process.env.POLITICAL_DAILY_SALARY_GROWTH);
|
||||
/** Tageshonorar niedrigste Stufe (Default ~50; per ENV überschreibbar). */
|
||||
const POLITICAL_DAILY_SALARY_START_DEFAULT =
|
||||
Number.isFinite(_envPolSalaryStart) && _envPolSalaryStart > 0 ? _envPolSalaryStart : 50;
|
||||
/** Pro hierarchy_level leicht exponentiell (Default 1,22; per ENV überschreibbar). */
|
||||
const POLITICAL_DAILY_SALARY_GROWTH_DEFAULT =
|
||||
Number.isFinite(_envPolSalaryGrowth) && _envPolSalaryGrowth > 1 ? _envPolSalaryGrowth : 1.22;
|
||||
|
||||
/**
|
||||
* Tageshonorar: value.dailyAmount fest, sonst salaryStart × salaryGrowth^(Stufe−1).
|
||||
* Stufe: value.rank (JSON), sonst hierarchy_level, sonst POLITICAL_OFFICE_RANKS[name].
|
||||
* Optional im JSON: salaryStart, salaryGrowth (pro Amt); ENV POLITICAL_DAILY_SALARY_* (global).
|
||||
* Legacy linear: nur bei salaryFormula === 'linear' mit base und perRank.
|
||||
*/
|
||||
function computePoliticalDailySalaryPayout(value, officeName, hierarchyLevelFromType) {
|
||||
const v = value && typeof value === 'object' ? value : {};
|
||||
if (v.dailyAmount != null && Number.isFinite(Number(v.dailyAmount))) {
|
||||
return Math.round(Number(v.dailyAmount) * 100) / 100;
|
||||
}
|
||||
const rank = POLITICAL_OFFICE_RANKS[officeName] ?? 0;
|
||||
const base = Number(v.base ?? 0);
|
||||
const perRank = Number(v.perRank ?? v.per_rank ?? 0);
|
||||
return Math.round((base + perRank * rank) * 100) / 100;
|
||||
const nameKey = typeof officeName === 'string' ? officeName.trim() : officeName;
|
||||
let rank = 0;
|
||||
if (v.rank != null && Number.isFinite(Number(v.rank))) {
|
||||
rank = Math.max(0, Number(v.rank));
|
||||
} else {
|
||||
const fromDb = Number(hierarchyLevelFromType);
|
||||
if (Number.isFinite(fromDb) && fromDb > 0) {
|
||||
rank = fromDb;
|
||||
} else {
|
||||
rank = POLITICAL_OFFICE_RANKS[nameKey] ?? 0;
|
||||
}
|
||||
}
|
||||
if (rank < 1) {
|
||||
return 0;
|
||||
}
|
||||
if (v.salaryFormula === 'linear') {
|
||||
const base = Number(v.base ?? 0);
|
||||
const perRank = Number(v.perRank ?? v.per_rank ?? 0);
|
||||
return Math.round((base + perRank * rank) * 100) / 100;
|
||||
}
|
||||
const startRaw = Number(v.salaryStart ?? v.salary_start);
|
||||
const growthRaw = Number(v.salaryGrowth ?? v.salary_growth);
|
||||
const start = Number.isFinite(startRaw) && startRaw > 0 ? startRaw : POLITICAL_DAILY_SALARY_START_DEFAULT;
|
||||
const growth =
|
||||
Number.isFinite(growthRaw) && growthRaw > 1 ? growthRaw : POLITICAL_DAILY_SALARY_GROWTH_DEFAULT;
|
||||
const amount = start * growth ** (rank - 1);
|
||||
return Math.round(amount * 100) / 100;
|
||||
}
|
||||
|
||||
const CERTIFICATE_THRESHOLDS = {
|
||||
@@ -6089,7 +6127,7 @@ class FalukantService extends BaseService {
|
||||
return this.healthChange(user, delta);
|
||||
}
|
||||
|
||||
politicsBenefitEntriesFromRows(benefitRows, officeName) {
|
||||
politicsBenefitEntriesFromRows(benefitRows, officeName, hierarchyLevelFromType) {
|
||||
if (!benefitRows?.length) {
|
||||
return [];
|
||||
}
|
||||
@@ -6106,7 +6144,7 @@ class FalukantService extends BaseService {
|
||||
out.push({ tr: 'tax_exemption', params: { regions } });
|
||||
}
|
||||
} else if (tr === 'daily_salary' || tr === 'salary') {
|
||||
const amount = computePoliticalDailySalaryPayout(v, officeName);
|
||||
const amount = computePoliticalDailySalaryPayout(v, officeName, hierarchyLevelFromType);
|
||||
if (amount > 0) {
|
||||
out.push({ tr: 'daily_salary', params: { amount } });
|
||||
}
|
||||
@@ -6150,7 +6188,7 @@ class FalukantService extends BaseService {
|
||||
|
||||
const held = await PoliticalOffice.findAll({
|
||||
where: { characterId },
|
||||
include: [{ model: PoliticalOfficeType, as: 'type', attributes: ['name'] }]
|
||||
include: [{ model: PoliticalOfficeType, as: 'type', attributes: ['name', 'hierarchyLevel'] }]
|
||||
});
|
||||
if (!held.length) {
|
||||
return;
|
||||
@@ -6180,7 +6218,8 @@ class FalukantService extends BaseService {
|
||||
continue;
|
||||
}
|
||||
const v = typeof row.value === 'object' && row.value ? row.value : {};
|
||||
total += computePoliticalDailySalaryPayout(v, name);
|
||||
const level = h.type?.hierarchyLevel;
|
||||
total += computePoliticalDailySalaryPayout(v, name, level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6235,7 +6274,7 @@ class FalukantService extends BaseService {
|
||||
{
|
||||
model: PoliticalOfficeType,
|
||||
as: 'type',
|
||||
attributes: ['name', 'termLength']
|
||||
attributes: ['name', 'termLength', 'hierarchyLevel']
|
||||
},
|
||||
{
|
||||
model: RegionData,
|
||||
@@ -6311,7 +6350,8 @@ class FalukantService extends BaseService {
|
||||
const officeName = o.type?.name;
|
||||
const benefit = this.politicsBenefitEntriesFromRows(
|
||||
benefitByType.get(o.officeTypeId) || [],
|
||||
officeName
|
||||
officeName,
|
||||
o.type?.hierarchyLevel
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user