All checks were successful
Deploy to production / deploy (push) Successful in 3m3s
- Added new political powers and benefits functionalities, including reputation ticks, tax jurisdiction management, and appointment capabilities. - Introduced a new job for periodic reputation updates and created necessary database tables for tracking political benefits. - Enhanced the FalukantController and services to support new endpoints for managing political powers and appointments. - Updated localization files to reflect new features and improve user experience across multiple languages. - Modified the UI to display new political powers and benefits, ensuring accurate representation in the PoliticsView.
95 lines
3.9 KiB
JavaScript
95 lines
3.9 KiB
JavaScript
/**
|
|
* Periodischer Job: reputation_periodic für politische Amtsinhaber.
|
|
* Aufruf: systemd-Timer oder FALUKANT_POLITICAL_REPUTATION_JOB=1 (siehe server.js).
|
|
*/
|
|
import PoliticalOffice from '../models/falukant/data/political_office.js';
|
|
import PoliticalOfficeType from '../models/falukant/type/political_office_type.js';
|
|
import PoliticalOfficeBenefit from '../models/falukant/predefine/political_office_benefit.js';
|
|
import PoliticalOfficeBenefitType from '../models/falukant/type/political_office_benefit_type.js';
|
|
import PoliticalBenefitLastTick from '../models/falukant/data/political_benefit_last_tick.js';
|
|
import FalukantCharacter from '../models/falukant/data/character.js';
|
|
import FalukantUser from '../models/falukant/data/user.js';
|
|
import User from '../models/community/user.js';
|
|
import { sequelize } from '../utils/sequelize.js';
|
|
import { notifyUser } from '../utils/socket.js';
|
|
|
|
export async function runPoliticalReputationTicks() {
|
|
const offices = await PoliticalOffice.findAll({
|
|
include: [{ model: PoliticalOfficeType, as: 'type', attributes: ['id', 'name'] }]
|
|
});
|
|
const toNotify = new Set();
|
|
let ticks = 0;
|
|
|
|
for (const po of offices) {
|
|
const characterId = po.characterId;
|
|
const benefitRows = await PoliticalOfficeBenefit.findAll({
|
|
where: { officeTypeId: po.officeTypeId },
|
|
include: [
|
|
{
|
|
model: PoliticalOfficeBenefitType,
|
|
as: 'benefitDefinition',
|
|
attributes: ['tr'],
|
|
required: true,
|
|
where: { tr: 'reputation_periodic' }
|
|
}
|
|
]
|
|
});
|
|
|
|
for (const br of benefitRows) {
|
|
const v = br.value && typeof br.value === 'object' ? br.value : {};
|
|
const intervalDays = Math.max(1, Number(v.intervalDays ?? v.everyDays ?? 7));
|
|
const gain = Math.max(1, Number(v.gain ?? 1));
|
|
|
|
const [tickRow, created] = await PoliticalBenefitLastTick.findOrCreate({
|
|
where: {
|
|
characterId,
|
|
politicalOfficeBenefitId: br.id
|
|
},
|
|
defaults: {
|
|
characterId,
|
|
politicalOfficeBenefitId: br.id,
|
|
lastTickAt: new Date(po.createdAt),
|
|
ticksCount: 0
|
|
}
|
|
});
|
|
|
|
const baseMs = new Date(tickRow.lastTickAt).getTime();
|
|
const daysSince = Math.floor((Date.now() - baseMs) / 86400000);
|
|
if (daysSince < intervalDays) continue;
|
|
|
|
await sequelize.transaction(async (t) => {
|
|
const ch = await FalukantCharacter.findByPk(characterId, { transaction: t });
|
|
if (!ch) return;
|
|
const nextRep = Math.min(100, (ch.reputation ?? 0) + gain);
|
|
await ch.update({ reputation: nextRep }, { transaction: t });
|
|
await PoliticalBenefitLastTick.update(
|
|
{
|
|
lastTickAt: new Date(),
|
|
ticksCount: (tickRow.ticksCount || 0) + 1
|
|
},
|
|
{ where: { id: tickRow.id }, transaction: t }
|
|
);
|
|
});
|
|
|
|
ticks += 1;
|
|
toNotify.add(characterId);
|
|
console.info(
|
|
`[PoliticalBenefits] reputation_tick characterId=${characterId} benefitId=${br.id} gain=${gain}`
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const characterId of toNotify) {
|
|
const ch = await FalukantCharacter.findByPk(characterId, { attributes: ['userId'] });
|
|
if (!ch?.userId) continue;
|
|
const fu = await FalukantUser.findOne({
|
|
where: { id: ch.userId },
|
|
include: [{ model: User, as: 'user', attributes: ['hashedId'] }]
|
|
});
|
|
const hid = fu?.user?.hashedId;
|
|
if (hid) notifyUser(hid, 'falukantUpdateStatus', {});
|
|
}
|
|
|
|
return { processedOffices: offices.length, ticksApplied: ticks };
|
|
}
|