Some fixes and additions

This commit is contained in:
Torsten Schulz
2025-07-09 14:28:35 +02:00
parent 5029be81e9
commit fceea5b7fb
32 changed files with 4373 additions and 1294 deletions

View File

@@ -48,6 +48,16 @@ class FalukantController {
this.advanceNobility = this.advanceNobility.bind(this);
this.getHealth = this.getHealth.bind(this);
this.healthActivity = this.healthActivity.bind(this);
this.getPoliticsOverview = this.getPoliticsOverview.bind(this);
this.getOpenPolitics = this.getOpenPolitics.bind(this);
this.getElections = this.getElections.bind(this);
this.vote = this.vote.bind(this);
this.getOpenPolitics = this.getOpenPolitics.bind(this);
this.applyForElections = this.applyForElections.bind(this);
this.getRegions = this.getRegions.bind(this);
this.renovate = this.renovate.bind(this);
this.renovateAll = this.renovateAll.bind(this);
this.createBranch = this.createBranch.bind(this);
}
async getUser(req, res) {
@@ -117,6 +127,29 @@ class FalukantController {
}
}
async createBranch(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const { cityId, branchTypeId } = req.body;
const result = await FalukantService.createBranch(hashedUserId, cityId, branchTypeId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async getBranchTypes(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getBranchTypes(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async getBranch(req, res) {
try {
const { userid: hashedUserId } = req.headers;
@@ -325,6 +358,7 @@ class FalukantController {
const result = await FalukantService.convertProposalToDirector(hashedUserId, proposalId);
res.status(200).json(result);
} catch (error) {
console.log(error.message, error.stack);
res.status(500).json({ error: error.message });
}
}
@@ -482,7 +516,6 @@ class FalukantController {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getUserHouse(hashedUserId);
console.log(result);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -671,6 +704,108 @@ class FalukantController {
console.log(error);
}
}
async getPoliticsOverview(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getPoliticsOverview(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async getOpenPolitics(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getOpenPolitics(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async getElections(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getElections(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async vote(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const { votes } = req.body;
const result = await FalukantService.vote(hashedUserId, votes);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async getOpenPolitics(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getOpenPolitics(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async applyForElections(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const { electionIds } = req.body;
const result = await FalukantService.applyForElections(hashedUserId, electionIds);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async getRegions(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.getRegions(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async renovate(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const { element } = req.body;
const result = await FalukantService.renovate(hashedUserId, element);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
async renovateAll(req, res) {
try {
const { userid: hashedUserId } = req.headers;
const result = await FalukantService.renovateAll(hashedUserId);
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
console.log(error);
}
}
}
export default FalukantController;

View File

@@ -85,434 +85,437 @@ import PoliticalOffice from './falukant/data/political_office.js';
import PoliticalOfficeBenefit from './falukant/predefine/political_office_benefit.js';
import PoliticalOfficeBenefitType from './falukant/type/political_office_benefit_type.js';
import PoliticalOfficeRequirement from './falukant/predefine/political_office_prerequisite.js';
import PoliticalOfficePrerequisite from './falukant/predefine/political_office_prerequisite.js';
import PoliticalOfficeHistory from './falukant/log/political_office_history.js';
import ElectionHistory from './falukant/log/election_history.js';
export default function setupAssociations() {
// UserParam related associations
SettingsType.hasMany(UserParamType, { foreignKey: 'settingsId', as: 'user_param_types' });
UserParamType.belongsTo(SettingsType, { foreignKey: 'settingsId', as: 'settings_type' });
UserParamType.hasMany(UserParam, { foreignKey: 'paramTypeId', as: 'user_params' });
UserParam.belongsTo(UserParamType, { foreignKey: 'paramTypeId', as: 'paramType' });
User.hasMany(UserParam, { foreignKey: 'userId', as: 'user_params' });
UserParam.belongsTo(User, { foreignKey: 'userId', as: 'user' });
UserParamValue.belongsTo(UserParamType, { foreignKey: 'userParamTypeId', as: 'user_param_value_type' });
UserParamType.hasMany(UserParamValue, { foreignKey: 'userParamTypeId', as: 'user_param_type_value' });
UserRight.belongsTo(User, { foreignKey: 'userId', as: 'user_with_rights' });
UserRight.belongsTo(UserRightType, { foreignKey: 'rightTypeId', as: 'rightType' });
UserRightType.hasMany(UserRight, { foreignKey: 'rightTypeId', as: 'user_rights' });
UserParam.hasMany(UserParamVisibility, { foreignKey: 'param_id', as: 'param_visibilities' });
UserParamVisibility.belongsTo(UserParam, { foreignKey: 'param_id', as: 'param' });
UserParamVisibility.belongsTo(UserParamVisibilityType, { foreignKey: 'visibility', as: 'visibility_type' });
UserParamVisibilityType.hasMany(UserParamVisibility, { foreignKey: 'visibility', as: 'user_param_visibilities' });
// Interest related associations
InterestType.hasMany(InterestTranslationType, { foreignKey: 'interestsId', as: 'interest_translations' });
InterestTranslationType.belongsTo(InterestType, { foreignKey: 'interestsId', as: 'interest_translations' });
InterestType.hasMany(Interest, { foreignKey: 'userinterestId', as: 'user_interest_type' });
User.hasMany(Interest, { foreignKey: 'userId', as: 'user_interests' });
Interest.belongsTo(InterestType, { foreignKey: 'userinterestId', as: 'interest_type' });
Interest.belongsTo(User, { foreignKey: 'userId', as: 'interest_owner' });
// Folder and Image related associations
Folder.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(Folder, { foreignKey: 'userId' });
Folder.belongsTo(Folder, { foreignKey: 'parentId', as: 'parent' });
Folder.hasMany(Folder, { foreignKey: 'parentId', as: 'children' });
Image.belongsTo(Folder, { foreignKey: 'folderId' });
Folder.hasMany(Image, { foreignKey: 'folderId' });
Image.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(Image, { foreignKey: 'userId' });
// Image visibility associations
Folder.belongsToMany(ImageVisibilityType, {
through: FolderImageVisibility,
foreignKey: 'folderId',
otherKey: 'visibilityTypeId'
});
ImageVisibilityType.belongsToMany(Folder, {
through: FolderImageVisibility,
foreignKey: 'visibilityTypeId',
otherKey: 'folderId'
});
Image.belongsToMany(ImageVisibilityType, {
through: ImageImageVisibility,
foreignKey: 'imageId',
otherKey: 'visibilityTypeId'
});
ImageVisibilityType.belongsToMany(Image, {
through: ImageImageVisibility,
foreignKey: 'visibilityTypeId',
otherKey: 'imageId'
});
Folder.belongsToMany(ImageVisibilityUser, {
through: FolderVisibilityUser,
foreignKey: 'folderId',
otherKey: 'visibilityUserId'
});
ImageVisibilityUser.belongsToMany(Folder, {
through: FolderVisibilityUser,
foreignKey: 'visibilityUserId',
otherKey: 'folderId'
});
// UserParam related associations
SettingsType.hasMany(UserParamType, { foreignKey: 'settingsId', as: 'user_param_types' });
UserParamType.belongsTo(SettingsType, { foreignKey: 'settingsId', as: 'settings_type' });
UserParamType.hasMany(UserParam, { foreignKey: 'paramTypeId', as: 'user_params' });
UserParam.belongsTo(UserParamType, { foreignKey: 'paramTypeId', as: 'paramType' });
User.hasMany(UserParam, { foreignKey: 'userId', as: 'user_params' });
UserParam.belongsTo(User, { foreignKey: 'userId', as: 'user' });
UserParamValue.belongsTo(UserParamType, { foreignKey: 'userParamTypeId', as: 'user_param_value_type' });
UserParamType.hasMany(UserParamValue, { foreignKey: 'userParamTypeId', as: 'user_param_type_value' });
UserRight.belongsTo(User, { foreignKey: 'userId', as: 'user_with_rights' });
UserRight.belongsTo(UserRightType, { foreignKey: 'rightTypeId', as: 'rightType' });
UserRightType.hasMany(UserRight, { foreignKey: 'rightTypeId', as: 'user_rights' });
UserParam.hasMany(UserParamVisibility, { foreignKey: 'param_id', as: 'param_visibilities' });
UserParamVisibility.belongsTo(UserParam, { foreignKey: 'param_id', as: 'param' });
UserParamVisibility.belongsTo(UserParamVisibilityType, { foreignKey: 'visibility', as: 'visibility_type' });
UserParamVisibilityType.hasMany(UserParamVisibility, { foreignKey: 'visibility', as: 'user_param_visibilities' });
// Interest related associations
InterestType.hasMany(InterestTranslationType, { foreignKey: 'interestsId', as: 'interest_translations' });
InterestTranslationType.belongsTo(InterestType, { foreignKey: 'interestsId', as: 'interest_translations' });
InterestType.hasMany(Interest, { foreignKey: 'userinterestId', as: 'user_interest_type' });
User.hasMany(Interest, { foreignKey: 'userId', as: 'user_interests' });
Interest.belongsTo(InterestType, { foreignKey: 'userinterestId', as: 'interest_type' });
Interest.belongsTo(User, { foreignKey: 'userId', as: 'interest_owner' });
// Folder and Image related associations
Folder.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(Folder, { foreignKey: 'userId' });
Folder.belongsTo(Folder, { foreignKey: 'parentId', as: 'parent' });
Folder.hasMany(Folder, { foreignKey: 'parentId', as: 'children' });
Image.belongsTo(Folder, { foreignKey: 'folderId' });
Folder.hasMany(Image, { foreignKey: 'folderId' });
Image.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(Image, { foreignKey: 'userId' });
// Image visibility associations
Folder.belongsToMany(ImageVisibilityType, {
through: FolderImageVisibility,
foreignKey: 'folderId',
otherKey: 'visibilityTypeId'
});
ImageVisibilityType.belongsToMany(Folder, {
through: FolderImageVisibility,
foreignKey: 'visibilityTypeId',
otherKey: 'folderId'
});
Image.belongsToMany(ImageVisibilityType, {
through: ImageImageVisibility,
foreignKey: 'imageId',
otherKey: 'visibilityTypeId'
});
ImageVisibilityType.belongsToMany(Image, {
through: ImageImageVisibility,
foreignKey: 'visibilityTypeId',
otherKey: 'imageId'
});
Folder.belongsToMany(ImageVisibilityUser, {
through: FolderVisibilityUser,
foreignKey: 'folderId',
otherKey: 'visibilityUserId'
});
ImageVisibilityUser.belongsToMany(Folder, {
through: FolderVisibilityUser,
foreignKey: 'visibilityUserId',
otherKey: 'folderId'
});
// Guestbook related associations
User.hasMany(GuestbookEntry, { foreignKey: 'recipientId', as: 'receivedEntries' });
User.hasMany(GuestbookEntry, { foreignKey: 'senderId', as: 'sentEntries' });
GuestbookEntry.belongsTo(User, { foreignKey: 'recipientId', as: 'recipient' });
GuestbookEntry.belongsTo(User, { foreignKey: 'senderId', as: 'sender' });
// Guestbook related associations
User.hasMany(GuestbookEntry, { foreignKey: 'recipientId', as: 'receivedEntries' });
User.hasMany(GuestbookEntry, { foreignKey: 'senderId', as: 'sentEntries' });
GuestbookEntry.belongsTo(User, { foreignKey: 'recipientId', as: 'recipient' });
GuestbookEntry.belongsTo(User, { foreignKey: 'senderId', as: 'sender' });
// Forum related associations
Forum.hasMany(Title, { foreignKey: 'forumId' });
Title.belongsTo(Forum, { foreignKey: 'forumId' });
// Forum related associations
Forum.hasMany(Title, { foreignKey: 'forumId' });
Title.belongsTo(Forum, { foreignKey: 'forumId' });
Title.belongsTo(User, { foreignKey: 'createdBy', as: 'createdByUser' });
User.hasMany(Title, { foreignKey: 'createdBy', as: 'titles' });
Title.belongsTo(User, { foreignKey: 'createdBy', as: 'createdByUser' });
User.hasMany(Title, { foreignKey: 'createdBy', as: 'titles' });
Title.hasMany(Message, { foreignKey: 'titleId', as: 'messages' });
Message.belongsTo(Title, { foreignKey: 'titleId', as: 'title' });
Title.hasMany(Message, { foreignKey: 'titleId', as: 'messages' });
Message.belongsTo(Title, { foreignKey: 'titleId', as: 'title' });
Message.belongsTo(User, { foreignKey: 'createdBy', as: 'lastMessageUser' });
User.hasMany(Message, { foreignKey: 'createdBy', as: 'userMessages' });
Message.belongsTo(User, { foreignKey: 'createdBy', as: 'lastMessageUser' });
User.hasMany(Message, { foreignKey: 'createdBy', as: 'userMessages' });
Message.hasMany(MessageImage, { foreignKey: 'messageId' });
MessageImage.belongsTo(Message, { foreignKey: 'messageId' });
Message.hasMany(MessageImage, { foreignKey: 'messageId' });
MessageImage.belongsTo(Message, { foreignKey: 'messageId' });
Message.hasMany(MessageHistory, { foreignKey: 'messageId' });
MessageHistory.belongsTo(Message, { foreignKey: 'messageId' });
Message.hasMany(MessageHistory, { foreignKey: 'messageId' });
MessageHistory.belongsTo(Message, { foreignKey: 'messageId' });
Title.hasMany(TitleHistory, { foreignKey: 'titleId' });
TitleHistory.belongsTo(Title, { foreignKey: 'titleId' });
Title.hasMany(TitleHistory, { foreignKey: 'titleId' });
TitleHistory.belongsTo(Title, { foreignKey: 'titleId' });
// Forum permissions associations
Forum.hasMany(ForumUserPermission, { foreignKey: 'forumId', as: 'userPermissions' });
ForumUserPermission.belongsTo(Forum, { foreignKey: 'forumId' });
// Forum permissions associations
Forum.hasMany(ForumUserPermission, { foreignKey: 'forumId', as: 'userPermissions' });
ForumUserPermission.belongsTo(Forum, { foreignKey: 'forumId' });
User.hasMany(ForumUserPermission, { foreignKey: 'userId', as: 'userPermissions' });
ForumUserPermission.belongsTo(User, { foreignKey: 'userId' });
User.hasMany(ForumUserPermission, { foreignKey: 'userId', as: 'userPermissions' });
ForumUserPermission.belongsTo(User, { foreignKey: 'userId' });
Forum.belongsToMany(ForumPermission, {
through: ForumForumPermission,
foreignKey: 'forumId',
as: 'associatedPermissions'
});
Forum.belongsToMany(ForumPermission, {
through: ForumForumPermission,
foreignKey: 'forumId',
as: 'associatedPermissions'
});
ForumPermission.belongsToMany(Forum, {
through: ForumForumPermission,
foreignKey: 'permissionId',
as: 'forums'
});
ForumPermission.belongsToMany(Forum, {
through: ForumForumPermission,
foreignKey: 'permissionId',
as: 'forums'
});
ForumPermission.hasMany(ForumUserPermission, { foreignKey: 'permissionId' });
ForumUserPermission.belongsTo(ForumPermission, { foreignKey: 'permissionId' });
ForumPermission.hasMany(ForumUserPermission, { foreignKey: 'permissionId' });
ForumUserPermission.belongsTo(ForumPermission, { foreignKey: 'permissionId' });
Friendship.belongsTo(User, { foreignKey: 'user1Id', as: 'friendSender' });
Friendship.belongsTo(User, { foreignKey: 'user2Id', as: 'friendReceiver' });
User.hasMany(Friendship, { foreignKey: 'user1Id', as: 'friendSender' });
User.hasMany(Friendship, { foreignKey: 'user2Id', as: 'friendReceiver' });
Friendship.belongsTo(User, { foreignKey: 'user1Id', as: 'friendSender' });
Friendship.belongsTo(User, { foreignKey: 'user2Id', as: 'friendReceiver' });
User.hasMany(Friendship, { foreignKey: 'user1Id', as: 'friendSender' });
User.hasMany(Friendship, { foreignKey: 'user2Id', as: 'friendReceiver' });
User.hasMany(FalukantUser, { foreignKey: 'userId', as: 'falukantData' });
FalukantUser.belongsTo(User, { foreignKey: 'userId', as: 'user' });
User.hasMany(FalukantUser, { foreignKey: 'userId', as: 'falukantData' });
FalukantUser.belongsTo(User, { foreignKey: 'userId', as: 'user' });
RegionType.hasMany(RegionType, { foreignKey: 'parentId', as: 'children' });
RegionType.belongsTo(RegionType, { foreignKey: 'parentId', as: 'parent' });
RegionType.hasMany(RegionType, { foreignKey: 'parentId', as: 'children' });
RegionType.belongsTo(RegionType, { foreignKey: 'parentId', as: 'parent' });
RegionData.hasMany(RegionData, { foreignKey: 'parentId', as: 'children' });
RegionData.belongsTo(RegionData, { foreignKey: 'parentId', as: 'parent' });
RegionData.hasMany(RegionData, { foreignKey: 'parentId', as: 'children' });
RegionData.belongsTo(RegionData, { foreignKey: 'parentId', as: 'parent' });
RegionData.belongsTo(RegionType, { foreignKey: 'regionTypeId', as: 'regionType' });
RegionType.hasMany(RegionData, { foreignKey: 'regionTypeId', as: 'regions' });
RegionData.belongsTo(RegionType, { foreignKey: 'regionTypeId', as: 'regionType' });
RegionType.hasMany(RegionData, { foreignKey: 'regionTypeId', as: 'regions' });
FalukantUser.belongsTo(RegionData, { foreignKey: 'mainBranchRegionId', as: 'mainBranchRegion' });
RegionData.hasMany(FalukantUser, { foreignKey: 'mainBranchRegionId', as: 'users' });
FalukantUser.belongsTo(RegionData, { foreignKey: 'mainBranchRegionId', as: 'mainBranchRegion' });
RegionData.hasMany(FalukantUser, { foreignKey: 'mainBranchRegionId', as: 'users' });
FalukantCharacter.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'user' });
FalukantUser.hasOne(FalukantCharacter, { foreignKey: 'userId', as: 'character' });
FalukantCharacter.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'user' });
FalukantUser.hasOne(FalukantCharacter, { foreignKey: 'userId', as: 'character' });
FalukantCharacter.belongsTo(FalukantPredefineFirstname, { foreignKey: 'firstName', as: 'definedFirstName' });
FalukantPredefineFirstname.hasMany(FalukantCharacter, { foreignKey: 'firstName', as: 'charactersWithFirstName' });
FalukantCharacter.belongsTo(FalukantPredefineFirstname, { foreignKey: 'firstName', as: 'definedFirstName' });
FalukantPredefineFirstname.hasMany(FalukantCharacter, { foreignKey: 'firstName', as: 'charactersWithFirstName' });
FalukantCharacter.belongsTo(FalukantPredefineLastname, { foreignKey: 'lastName', as: 'definedLastName' });
FalukantPredefineLastname.hasMany(FalukantCharacter, { foreignKey: 'lastName', as: 'charactersWithLastName' });
FalukantCharacter.belongsTo(FalukantPredefineLastname, { foreignKey: 'lastName', as: 'definedLastName' });
FalukantPredefineLastname.hasMany(FalukantCharacter, { foreignKey: 'lastName', as: 'charactersWithLastName' });
FalukantCharacter.belongsTo(TitleOfNobility, { foreignKey: 'titleOfNobility', as: 'nobleTitle' });
TitleOfNobility.hasMany(FalukantCharacter, { foreignKey: 'titleOfNobility', as: 'charactersWithNobleTitle' });
FalukantCharacter.belongsTo(TitleOfNobility, { foreignKey: 'titleOfNobility', as: 'nobleTitle' });
TitleOfNobility.hasMany(FalukantCharacter, { foreignKey: 'titleOfNobility', as: 'charactersWithNobleTitle' });
FalukantCharacter.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(FalukantCharacter, { foreignKey: 'regionId', as: 'charactersInRegion' });
FalukantCharacter.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(FalukantCharacter, { foreignKey: 'regionId', as: 'charactersInRegion' });
FalukantStock.belongsTo(FalukantStockType, { foreignKey: 'stockTypeId', as: 'stockType' });
FalukantStockType.hasMany(FalukantStock, { foreignKey: 'stockTypeId', as: 'stocks' });
FalukantStock.belongsTo(FalukantStockType, { foreignKey: 'stockTypeId', as: 'stockType' });
FalukantStockType.hasMany(FalukantStock, { foreignKey: 'stockTypeId', as: 'stocks' });
Knowledge.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(Knowledge, { foreignKey: 'productId', as: 'knowledges' });
Knowledge.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(Knowledge, { foreignKey: 'productId', as: 'knowledges' });
Knowledge.belongsTo(FalukantCharacter, { foreignKey: 'characterId', as: 'character' });
FalukantCharacter.hasMany(Knowledge, { foreignKey: 'characterId', as: 'knowledges' });
Knowledge.belongsTo(FalukantCharacter, { foreignKey: 'characterId', as: 'character' });
FalukantCharacter.hasMany(Knowledge, { foreignKey: 'characterId', as: 'knowledges' });
TitleRequirement.belongsTo(TitleOfNobility, { foreignKey: 'titleId', as: 'title' });
TitleOfNobility.hasMany(TitleRequirement, { foreignKey: 'titleId', as: 'requirements' });
TitleRequirement.belongsTo(TitleOfNobility, { foreignKey: 'titleId', as: 'title' });
TitleOfNobility.hasMany(TitleRequirement, { foreignKey: 'titleId', as: 'requirements' });
Branch.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(Branch, { foreignKey: 'regionId', as: 'branches' });
Branch.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(Branch, { foreignKey: 'regionId', as: 'branches' });
Branch.belongsTo(FalukantUser, { foreignKey: 'falukantUserId', as: 'user' });
FalukantUser.hasMany(Branch, { foreignKey: 'falukantUserId', as: 'branches' });
Branch.belongsTo(FalukantUser, { foreignKey: 'falukantUserId', as: 'user' });
FalukantUser.hasMany(Branch, { foreignKey: 'falukantUserId', as: 'branches' });
Branch.belongsTo(BranchType, { foreignKey: 'branchTypeId', as: 'branchType' });
BranchType.hasMany(Branch, { foreignKey: 'branchTypeId', as: 'branches' });
Branch.belongsTo(BranchType, { foreignKey: 'branchTypeId', as: 'branchType' });
BranchType.hasMany(Branch, { foreignKey: 'branchTypeId', as: 'branches' });
Production.belongsTo(Branch, { foreignKey: 'branchId', as: 'branch' });
Branch.hasMany(Production, { foreignKey: 'branchId', as: 'productions' });
Production.belongsTo(Branch, { foreignKey: 'branchId', as: 'branch' });
Branch.hasMany(Production, { foreignKey: 'branchId', as: 'productions' });
Production.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(Production, { foreignKey: 'productId', as: 'productions' });
Production.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(Production, { foreignKey: 'productId', as: 'productions' });
Inventory.belongsTo(FalukantStock, { foreignKey: 'stockId', as: 'stock' });
FalukantStock.hasMany(Inventory, { foreignKey: 'stockId', as: 'inventories' });
Inventory.belongsTo(FalukantStock, { foreignKey: 'stockId', as: 'stock' });
FalukantStock.hasMany(Inventory, { foreignKey: 'stockId', as: 'inventories' });
Inventory.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(Inventory, { foreignKey: 'productId', as: 'inventories' });
Inventory.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(Inventory, { foreignKey: 'productId', as: 'inventories' });
BuyableStock.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(BuyableStock, { foreignKey: 'regionId', as: 'buyableStocks' });
BuyableStock.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(BuyableStock, { foreignKey: 'regionId', as: 'buyableStocks' });
Branch.hasMany(FalukantStock, { foreignKey: 'branchId', as: 'stocks' });
FalukantStock.belongsTo(Branch, { foreignKey: 'branchId', as: 'branch' });
Branch.hasMany(FalukantStock, { foreignKey: 'branchId', as: 'stocks' });
FalukantStock.belongsTo(Branch, { foreignKey: 'branchId', as: 'branch' });
MoneyFlow.belongsTo(FalukantUser, { foreignKey: 'falukantUserId', as: 'user' });
FalukantUser.hasMany(MoneyFlow, { foreignKey: 'falukantUserId', as: 'flows' });
MoneyFlow.belongsTo(FalukantUser, { foreignKey: 'falukantUserId', as: 'user' });
FalukantUser.hasMany(MoneyFlow, { foreignKey: 'falukantUserId', as: 'flows' });
BuyableStock.belongsTo(FalukantStockType, { foreignKey: 'stockTypeId', as: 'stockType' });
FalukantStockType.hasMany(BuyableStock, { foreignKey: 'stockTypeId', as: 'buyableStocks' });
BuyableStock.belongsTo(FalukantStockType, { foreignKey: 'stockTypeId', as: 'stockType' });
FalukantStockType.hasMany(BuyableStock, { foreignKey: 'stockTypeId', as: 'buyableStocks' });
Director.belongsTo(FalukantUser, { foreignKey: 'employerUserId', as: 'user' });
FalukantUser.hasMany(Director, { foreignKey: 'employerUserId', as: 'directors' });
Director.belongsTo(FalukantUser, { foreignKey: 'employerUserId', as: 'user' });
FalukantUser.hasMany(Director, { foreignKey: 'employerUserId', as: 'directors' });
Director.belongsTo(FalukantCharacter, { foreignKey: 'directorCharacterId', as: 'character' });
FalukantCharacter.hasMany(Director, { foreignKey: 'directorCharacterId', as: 'directors' });
Director.belongsTo(FalukantCharacter, { foreignKey: 'directorCharacterId', as: 'character' });
FalukantCharacter.hasMany(Director, { foreignKey: 'directorCharacterId', as: 'directors' });
DirectorProposal.belongsTo(FalukantUser, { foreignKey: 'employerUserId', as: 'user' });
FalukantUser.hasMany(DirectorProposal, { foreignKey: 'employerUserId', as: 'directorProposals' });
DirectorProposal.belongsTo(FalukantUser, { foreignKey: 'employerUserId', as: 'user' });
FalukantUser.hasMany(DirectorProposal, { foreignKey: 'employerUserId', as: 'directorProposals' });
DirectorProposal.belongsTo(FalukantCharacter, { foreignKey: 'directorCharacterId', as: 'character' });
FalukantCharacter.hasMany(DirectorProposal, { foreignKey: 'directorCharacterId', as: 'directorProposals' });
DirectorProposal.belongsTo(FalukantCharacter, { foreignKey: 'directorCharacterId', as: 'character' });
FalukantCharacter.hasMany(DirectorProposal, { foreignKey: 'directorCharacterId', as: 'directorProposals' });
TownProductWorth.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(TownProductWorth, { foreignKey: 'productId', as: 'townProductWorths' });
TownProductWorth.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(TownProductWorth, { foreignKey: 'productId', as: 'townProductWorths' });
TownProductWorth.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(TownProductWorth, { foreignKey: 'regionId', as: 'townProductWorths' });
TownProductWorth.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(TownProductWorth, { foreignKey: 'regionId', as: 'townProductWorths' });
DayProduction.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(DayProduction, { foreignKey: 'productId', as: 'dayProductions' });
DayProduction.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(DayProduction, { foreignKey: 'productId', as: 'dayProductions' });
DayProduction.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(DayProduction, { foreignKey: 'regionId', as: 'dayProductions' });
DayProduction.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(DayProduction, { foreignKey: 'regionId', as: 'dayProductions' });
DayProduction.belongsTo(FalukantUser, { foreignKey: 'producerId', as: 'user' });
FalukantUser.hasMany(DayProduction, { foreignKey: 'producerId', as: 'dayProductions' });
DayProduction.belongsTo(FalukantUser, { foreignKey: 'producerId', as: 'user' });
FalukantUser.hasMany(DayProduction, { foreignKey: 'producerId', as: 'dayProductions' });
DaySell.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(DaySell, { foreignKey: 'productId', as: 'daySells' });
DaySell.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(DaySell, { foreignKey: 'productId', as: 'daySells' });
DaySell.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(DaySell, { foreignKey: 'regionId', as: 'daySells' });
DaySell.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(DaySell, { foreignKey: 'regionId', as: 'daySells' });
DaySell.belongsTo(FalukantUser, { foreignKey: 'sellerId', as: 'user' });
FalukantUser.hasMany(DaySell, { foreignKey: 'sellerId', as: 'daySells' });
DaySell.belongsTo(FalukantUser, { foreignKey: 'sellerId', as: 'user' });
FalukantUser.hasMany(DaySell, { foreignKey: 'sellerId', as: 'daySells' });
Notification.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'user' });
FalukantUser.hasMany(Notification, { foreignKey: 'userId', as: 'notifications' });
Notification.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'user' });
FalukantUser.hasMany(Notification, { foreignKey: 'userId', as: 'notifications' });
MarriageProposal.belongsTo(FalukantCharacter, { foreignKey: 'requesterCharacterId', as: 'requesterCharacter', });
FalukantCharacter.hasMany(MarriageProposal, { foreignKey: 'requesterCharacterId', as: 'initiatedProposals' });
MarriageProposal.belongsTo(FalukantCharacter, { foreignKey: 'requesterCharacterId', as: 'requesterCharacter', });
FalukantCharacter.hasMany(MarriageProposal, { foreignKey: 'requesterCharacterId', as: 'initiatedProposals' });
MarriageProposal.belongsTo(FalukantCharacter, { foreignKey: 'proposedCharacterId', as: 'proposedCharacter', });
FalukantCharacter.hasMany(MarriageProposal, { foreignKey: 'proposedCharacterId', as: 'receivedProposals' });
MarriageProposal.belongsTo(FalukantCharacter, { foreignKey: 'proposedCharacterId', as: 'proposedCharacter', });
FalukantCharacter.hasMany(MarriageProposal, { foreignKey: 'proposedCharacterId', as: 'receivedProposals' });
FalukantCharacter.belongsToMany(CharacterTrait, { through: FalukantCharacterTrait, foreignKey: 'character_id', as: 'traits', });
CharacterTrait.belongsToMany(FalukantCharacter, { through: FalukantCharacterTrait, foreignKey: 'trait_id', as: 'characters', });
FalukantCharacter.belongsToMany(CharacterTrait, { through: FalukantCharacterTrait, foreignKey: 'character_id', as: 'traits', });
CharacterTrait.belongsToMany(FalukantCharacter, { through: FalukantCharacterTrait, foreignKey: 'trait_id', as: 'characters', });
Mood.hasMany(FalukantCharacter, { foreignKey: 'mood_id', as: 'moods' });
FalukantCharacter.belongsTo(Mood, { foreignKey: 'mood_id', as: 'mood' });
Mood.hasMany(FalukantCharacter, { foreignKey: 'mood_id', as: 'moods' });
FalukantCharacter.belongsTo(Mood, { foreignKey: 'mood_id', as: 'mood' });
PromotionalGift.belongsToMany(CharacterTrait, { through: PromotionalGiftCharacterTrait, foreignKey: 'gift_id', as: 'traits', });
CharacterTrait.belongsToMany(PromotionalGift, { through: PromotionalGiftCharacterTrait, foreignKey: 'trait_id', as: 'gifts', });
PromotionalGift.belongsToMany(CharacterTrait, { through: PromotionalGiftCharacterTrait, foreignKey: 'gift_id', as: 'traits', });
CharacterTrait.belongsToMany(PromotionalGift, { through: PromotionalGiftCharacterTrait, foreignKey: 'trait_id', as: 'gifts', });
PromotionalGift.belongsToMany(Mood, { through: PromotionalGiftMood, foreignKey: 'gift_id', as: 'moods', });
Mood.belongsToMany(PromotionalGift, { through: PromotionalGiftMood, foreignKey: 'mood_id', as: 'gifts', });
PromotionalGift.belongsToMany(Mood, { through: PromotionalGiftMood, foreignKey: 'gift_id', as: 'moods', });
Mood.belongsToMany(PromotionalGift, { through: PromotionalGiftMood, foreignKey: 'mood_id', as: 'gifts', });
Relationship.belongsTo(RelationshipType, { foreignKey: 'relationshipTypeId', as: 'relationshipType' });
RelationshipType.hasMany(Relationship, { foreignKey: 'relationshipTypeId', as: 'relationships' });
Relationship.belongsTo(RelationshipType, { foreignKey: 'relationshipTypeId', as: 'relationshipType' });
RelationshipType.hasMany(Relationship, { foreignKey: 'relationshipTypeId', as: 'relationships' });
Relationship.belongsTo(FalukantCharacter, { foreignKey: 'character1Id', as: 'character1', });
Relationship.belongsTo(FalukantCharacter, { foreignKey: 'character2Id', as: 'character2', });
FalukantCharacter.hasMany(Relationship, { foreignKey: 'character1Id', as: 'relationshipsAsCharacter1', });
FalukantCharacter.hasMany(Relationship, { foreignKey: 'character2Id', as: 'relationshipsAsCharacter2', });
Relationship.belongsTo(FalukantCharacter, { foreignKey: 'character1Id', as: 'character1', });
Relationship.belongsTo(FalukantCharacter, { foreignKey: 'character2Id', as: 'character2', });
FalukantCharacter.hasMany(Relationship, { foreignKey: 'character1Id', as: 'relationshipsAsCharacter1', });
FalukantCharacter.hasMany(Relationship, { foreignKey: 'character2Id', as: 'relationshipsAsCharacter2', });
PromotionalGiftLog.belongsTo(PromotionalGift, { foreignKey: 'giftId', as: 'gift' });
PromotionalGift.hasMany(PromotionalGiftLog, { foreignKey: 'giftId', as: 'logs' });
PromotionalGiftLog.belongsTo(PromotionalGift, { foreignKey: 'giftId', as: 'gift' });
PromotionalGift.hasMany(PromotionalGiftLog, { foreignKey: 'giftId', as: 'logs' });
PromotionalGiftLog.belongsTo(FalukantCharacter, { foreignKey: 'senderCharacterId', as: 'character' });
FalukantCharacter.hasMany(PromotionalGiftLog, { foreignKey: 'senderCharacterId', as: 'logs' });
PromotionalGiftLog.belongsTo(FalukantCharacter, { foreignKey: 'senderCharacterId', as: 'character' });
FalukantCharacter.hasMany(PromotionalGiftLog, { foreignKey: 'senderCharacterId', as: 'logs' });
PromotionalGiftLog.belongsTo(FalukantCharacter, { foreignKey: 'recipientCharacterId', as: 'recipient' });
FalukantCharacter.hasMany(PromotionalGiftLog, { foreignKey: 'recipientCharacterId', as: 'giftlogs' });
PromotionalGiftLog.belongsTo(FalukantCharacter, { foreignKey: 'recipientCharacterId', as: 'recipient' });
FalukantCharacter.hasMany(PromotionalGiftLog, { foreignKey: 'recipientCharacterId', as: 'giftlogs' });
PromotionalGift.hasMany(PromotionalGiftCharacterTrait, { foreignKey: 'gift_id', as: 'characterTraits' });
PromotionalGift.hasMany(PromotionalGiftMood, { foreignKey: 'gift_id', as: 'promotionalgiftmoods' });
PromotionalGift.hasMany(PromotionalGiftCharacterTrait, { foreignKey: 'gift_id', as: 'characterTraits' });
PromotionalGift.hasMany(PromotionalGiftMood, { foreignKey: 'gift_id', as: 'promotionalgiftmoods' });
PromotionalGiftCharacterTrait.belongsTo(PromotionalGift, { foreignKey: 'gift_id', as: 'promotionalgiftcharactertrait' });
PromotionalGiftMood.belongsTo(PromotionalGift, { foreignKey: 'gift_id', as: 'promotionalgiftcharactermood' });
PromotionalGiftCharacterTrait.belongsTo(PromotionalGift, { foreignKey: 'gift_id', as: 'promotionalgiftcharactertrait' });
PromotionalGiftMood.belongsTo(PromotionalGift, { foreignKey: 'gift_id', as: 'promotionalgiftcharactermood' });
HouseType.hasMany(BuyableHouse, { foreignKey: 'houseTypeId', as: 'buyableHouses' });
BuyableHouse.belongsTo(HouseType, { foreignKey: 'houseTypeId', as: 'houseType' });
HouseType.hasMany(BuyableHouse, { foreignKey: 'houseTypeId', as: 'buyableHouses' });
BuyableHouse.belongsTo(HouseType, { foreignKey: 'houseTypeId', as: 'houseType' });
HouseType.hasMany(UserHouse, { foreignKey: 'houseTypeId', as: 'userHouses' });
UserHouse.belongsTo(HouseType, { foreignKey: 'houseTypeId', as: 'houseType' });
HouseType.hasMany(UserHouse, { foreignKey: 'houseTypeId', as: 'userHouses' });
UserHouse.belongsTo(HouseType, { foreignKey: 'houseTypeId', as: 'houseType' });
FalukantUser.hasOne(UserHouse, { foreignKey: 'userId', as: 'userHouse' });
UserHouse.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'houseUser' });
FalukantUser.hasOne(UserHouse, { foreignKey: 'userId', as: 'userHouse' });
UserHouse.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'houseUser' });
TitleOfNobility.hasMany(HouseType, { foreignKey: 'minimumNobleTitle', as: 'houseTypes' });
HouseType.belongsTo(TitleOfNobility, { foreignKey: 'minimumNobleTitle', as: 'titleOfNobility' });
PartyType.hasMany(Party, { foreignKey: 'partyTypeId', as: 'parties' });
Party.belongsTo(PartyType, { foreignKey: 'partyTypeId', as: 'partyType' });
MusicType.hasMany(Party, { foreignKey: 'musicTypeId', as: 'parties' });
Party.belongsTo(MusicType, { foreignKey: 'musicTypeId', as: 'musicType' });
BanquetteType.hasMany(Party, { foreignKey: 'banquetteTypeId', as: 'parties' });
Party.belongsTo(BanquetteType, { foreignKey: 'banquetteTypeId', as: 'banquetteType' });
FalukantUser.hasMany(Party, { foreignKey: 'falukantUserId', as: 'parties' });
Party.belongsTo(FalukantUser, { foreignKey: 'falukantUserId', as: 'partyUser' });
Party.belongsToMany(TitleOfNobility, {
through: PartyInvitedNobility,
foreignKey: 'party_id',
otherKey: 'title_of_nobility_id',
as: 'invitedNobilities',
});
TitleOfNobility.belongsToMany(Party, {
through: PartyInvitedNobility,
foreignKey: 'title_of_nobility_id',
otherKey: 'party_id',
as: 'partiesInvitedTo',
});
ChildRelation.belongsTo(FalukantCharacter, {
foreignKey: 'fatherCharacterId',
as: 'father'
});
FalukantCharacter.hasMany(ChildRelation, {
foreignKey: 'fatherCharacterId',
as: 'childrenFather'
});
ChildRelation.belongsTo(FalukantCharacter, {
foreignKey: 'motherCharacterId',
as: 'mother'
});
FalukantCharacter.hasMany(ChildRelation, {
foreignKey: 'motherCharacterId',
as: 'childrenMother'
});
ChildRelation.belongsTo(FalukantCharacter, {
foreignKey: 'childCharacterId',
as: 'child'
});
FalukantCharacter.hasMany(ChildRelation, {
foreignKey: 'childCharacterId',
as: 'parentRelations'
});
Learning.belongsTo(LearnRecipient, {
foreignKey: 'learningRecipientId',
as: 'recipient'
}
);
LearnRecipient.hasMany(Learning, {
foreignKey: 'learningRecipientId',
as: 'learnings'
});
Learning.belongsTo(FalukantUser, {
foreignKey: 'associatedFalukantUserId',
as: 'learner'
}
);
FalukantUser.hasMany(Learning, {
foreignKey: 'associatedFalukantUserId',
as: 'learnings'
});
Learning.belongsTo(ProductType, {
foreignKey: 'productId',
as: 'productType'
});
ProductType.hasMany(Learning, {
foreignKey: 'productId',
as: 'learnings'
});
Learning.belongsTo(FalukantCharacter, {
foreignKey: 'associatedLearningCharacterId',
as: 'learningCharacter'
});
FalukantCharacter.hasMany(Learning, {
foreignKey: 'associatedLearningCharacterId',
as: 'learningsCharacter'
});
FalukantUser.hasMany(Credit, {
foreignKey: 'falukantUserId',
as: 'credits'
});
Credit.belongsTo(FalukantUser, {
foreignKey: 'falukantUserId',
as: 'user'
});
FalukantCharacter.hasMany(DebtorsPrism, {
foreignKey: 'character_id',
as: 'debtorsPrisms'
});
DebtorsPrism.belongsTo(FalukantCharacter, {
foreignKey: 'character_id',
as: 'character'
});
HealthActivity.belongsTo(FalukantCharacter, {
foreignKey: 'character_id',
as: 'character'
});
FalukantCharacter.hasMany(HealthActivity, {
foreignKey: 'character_id',
as: 'healthActivities'
});
// — Political Offices —
// predefine requirements for office
PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
TitleOfNobility.hasMany(HouseType, { foreignKey: 'minimumNobleTitle', as: 'houseTypes' });
HouseType.belongsTo(TitleOfNobility, { foreignKey: 'minimumNobleTitle', as: 'titleOfNobility' });
PartyType.hasMany(Party, { foreignKey: 'partyTypeId', as: 'parties' });
Party.belongsTo(PartyType, { foreignKey: 'partyTypeId', as: 'partyType' });
MusicType.hasMany(Party, { foreignKey: 'musicTypeId', as: 'parties' });
Party.belongsTo(MusicType, { foreignKey: 'musicTypeId', as: 'musicType' });
BanquetteType.hasMany(Party, { foreignKey: 'banquetteTypeId', as: 'parties' });
Party.belongsTo(BanquetteType, { foreignKey: 'banquetteTypeId', as: 'banquetteType' });
FalukantUser.hasMany(Party, { foreignKey: 'falukantUserId', as: 'parties' });
Party.belongsTo(FalukantUser, { foreignKey: 'falukantUserId', as: 'partyUser' });
Party.belongsToMany(TitleOfNobility, {
through: PartyInvitedNobility,
foreignKey: 'party_id',
otherKey: 'title_of_nobility_id',
as: 'invitedNobilities',
});
TitleOfNobility.belongsToMany(Party, {
through: PartyInvitedNobility,
foreignKey: 'title_of_nobility_id',
otherKey: 'party_id',
as: 'partiesInvitedTo',
});
ChildRelation.belongsTo(FalukantCharacter, {
foreignKey: 'fatherCharacterId',
as: 'father'
});
FalukantCharacter.hasMany(ChildRelation, {
foreignKey: 'fatherCharacterId',
as: 'childrenFather'
});
ChildRelation.belongsTo(FalukantCharacter, {
foreignKey: 'motherCharacterId',
as: 'mother'
});
FalukantCharacter.hasMany(ChildRelation, {
foreignKey: 'motherCharacterId',
as: 'childrenMother'
});
ChildRelation.belongsTo(FalukantCharacter, {
foreignKey: 'childCharacterId',
as: 'child'
});
FalukantCharacter.hasMany(ChildRelation, {
foreignKey: 'childCharacterId',
as: 'parentRelations'
});
Learning.belongsTo(LearnRecipient, {
foreignKey: 'learningRecipientId',
as: 'recipient'
}
);
LearnRecipient.hasMany(Learning, {
foreignKey: 'learningRecipientId',
as: 'learnings'
});
Learning.belongsTo(FalukantUser, {
foreignKey: 'associatedFalukantUserId',
as: 'learner'
}
);
FalukantUser.hasMany(Learning, {
foreignKey: 'associatedFalukantUserId',
as: 'learnings'
});
Learning.belongsTo(ProductType, {
foreignKey: 'productId',
as: 'productType'
});
ProductType.hasMany(Learning, {
foreignKey: 'productId',
as: 'learnings'
});
Learning.belongsTo(FalukantCharacter, {
foreignKey: 'associatedLearningCharacterId',
as: 'learningCharacter'
});
FalukantCharacter.hasMany(Learning, {
foreignKey: 'associatedLearningCharacterId',
as: 'learningsCharacter'
});
FalukantUser.hasMany(Credit, {
foreignKey: 'falukantUserId',
as: 'credits'
});
Credit.belongsTo(FalukantUser, {
foreignKey: 'falukantUserId',
as: 'user'
});
FalukantCharacter.hasMany(DebtorsPrism, {
foreignKey: 'character_id',
as: 'debtorsPrisms'
});
DebtorsPrism.belongsTo(FalukantCharacter, {
foreignKey: 'character_id',
as: 'character'
});
HealthActivity.belongsTo(FalukantCharacter, {
foreignKey: 'character_id',
as: 'character'
});
FalukantCharacter.hasMany(HealthActivity, {
foreignKey: 'character_id',
as: 'healthActivities'
});
// — Political Offices —
// predefine requirements for office
PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'officeType'
});
@@ -520,9 +523,9 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'requirements'
});
// predefine benefits for office
PoliticalOfficeBenefit.belongsTo(
PoliticalOfficeBenefit.belongsTo(
PoliticalOfficeBenefitType,
{ foreignKey: 'benefitTypeId', as: 'benefitDefinition' }
);
@@ -530,7 +533,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
PoliticalOfficeBenefit,
{ foreignKey: 'benefitTypeId', as: 'benefitDefinitions' }
);
// tie benefits back to office type
PoliticalOfficeBenefit.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
@@ -540,7 +543,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'benefits'
});
// actual office holdings
PoliticalOffice.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
@@ -550,16 +553,16 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'offices'
});
PoliticalOffice.belongsTo(FalukantCharacter, {
foreignKey: 'characterId',
as: 'holder'
});
FalukantCharacter.hasMany(PoliticalOffice, {
FalukantCharacter.hasOne(PoliticalOffice, {
foreignKey: 'characterId',
as: 'heldOffices'
as: 'heldOffice'
});
// elections
Election.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
@@ -569,7 +572,17 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'elections'
});
Election.belongsTo(RegionData, {
foreignKey: 'regionId',
as: 'region'
});
RegionData.hasMany(Election, {
foreignKey: 'regionId',
as: 'elections'
});
// candidates in an election
Candidate.belongsTo(Election, {
foreignKey: 'electionId',
@@ -579,7 +592,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'electionId',
as: 'candidates'
});
Candidate.belongsTo(FalukantCharacter, {
foreignKey: 'characterId',
as: 'character'
@@ -588,7 +601,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'characterId',
as: 'candidacies'
});
// votes cast
Vote.belongsTo(Election, {
foreignKey: 'electionId',
@@ -598,7 +611,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'electionId',
as: 'votes'
});
Vote.belongsTo(Candidate, {
foreignKey: 'candidateId',
as: 'candidate'
@@ -607,7 +620,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'candidateId',
as: 'votes'
});
Vote.belongsTo(FalukantCharacter, {
foreignKey: 'voterCharacterId',
as: 'voter'
@@ -616,7 +629,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'voterCharacterId',
as: 'votesCast'
});
// election results
ElectionResult.belongsTo(Election, {
foreignKey: 'electionId',
@@ -626,7 +639,7 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
foreignKey: 'electionId',
as: 'results'
});
ElectionResult.belongsTo(Candidate, {
foreignKey: 'candidateId',
as: 'candidate'
@@ -645,4 +658,43 @@ PoliticalOfficeRequirement.belongsTo(PoliticalOfficeType, {
as: 'offices'
});
PoliticalOfficePrerequisite.belongsTo(PoliticalOfficeType, {
foreignKey: 'office_type_id',
as: 'officeTypePrerequisite',
});
PoliticalOfficeType.hasMany(PoliticalOfficePrerequisite, {
foreignKey: 'office_type_id',
as: 'prerequisites',
});
PoliticalOfficeHistory.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'officeTypeHistory',
});
PoliticalOfficeType.hasMany(PoliticalOfficeHistory, {
foreignKey: 'officeTypeId',
as: 'history',
});
FalukantCharacter.hasMany(PoliticalOfficeHistory, {
foreignKey: 'characterId',
as: 'officeHistories',
});
PoliticalOfficeHistory.belongsTo(FalukantCharacter, {
foreignKey: 'characterId',
as: 'character',
});
ElectionHistory.belongsTo(PoliticalOfficeType, {
foreignKey: 'officeTypeId',
as: 'officeTypeHistory',
});
PoliticalOfficeType.hasMany(ElectionHistory, {
foreignKey: 'officeTypeId',
as: 'electionHistory',
}
)
}

View File

@@ -30,6 +30,11 @@ ChildRelation.init(
allowNull: false,
default: false,
},
isHeir: {
type: DataTypes.BOOLEAN,
allowNull: true,
default: false,
}
},
{
sequelize,

View File

@@ -10,15 +10,19 @@ Election.init({
primaryKey: true,
autoIncrement: true,
},
political_office_id: {
officeTypeId: {
type: DataTypes.INTEGER,
allowNull: false,
allowNull: true,
},
date: {
regionId: {
type: DataTypes.INTEGER,
allowNull: false
},
date: {
type: DataTypes.DATE,
allowNull: false,
},
posts_to_fill: {
postsToFill: {
type: DataTypes.INTEGER,
allowNull: false,
},

View File

@@ -26,6 +26,11 @@ RegionData.init({
key: 'id',
schema: 'falukant_data',
}
},
map: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: {}
}
}, {
sequelize,

View File

@@ -4,36 +4,45 @@ import { sequelize } from '../../../utils/sequelize.js';
class Vote extends Model {}
Vote.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
Vote.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
electionId: {
type: DataTypes.INTEGER,
allowNull: false,
},
candidateId: {
type: DataTypes.INTEGER,
allowNull: false,
},
timestamp: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
},
falukantUserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
election_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
voter_character_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
candidate_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
timestamp: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Vote',
tableName: 'vote',
schema: 'falukant_data',
timestamps: false,
underscored: true,
});
{
sequelize,
modelName: 'Vote',
tableName: 'vote',
schema: 'falukant_data',
timestamps: true,
underscored: true,
indexes: [
{
unique: true,
fields: ['election_id', 'candidate_id'],
},
],
}
);
export default Vote;

View File

@@ -0,0 +1,32 @@
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../../utils/sequelize.js';
class ElectionHistory extends Model { }
ElectionHistory.init({
electionId: {
type: DataTypes.INTEGER,
allowNull: false,
},
politicalOfficeTypeId: {
type: DataTypes.INTEGER,
allowNull: false,
},
electionDate: {
type: DataTypes.DATE,
allowNull: false,
},
electionResult: {
type: DataTypes.JSON,
allowNull: false,
}
}, {
sequelize,
modelName: 'ElectionHistory',
tableName: 'election_history',
schema: 'falukant_log',
timestamps: true,
underscored: true,
});
export default ElectionHistory;

View File

@@ -0,0 +1,35 @@
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../../utils/sequelize.js';
class PoliticalOfficeHistory extends Model { }
PoliticalOfficeHistory.init(
{
characterId: {
type: DataTypes.INTEGER,
allowNull: false,
},
officeTypeId: {
type: DataTypes.INTEGER,
allowNull: false,
},
startDate: {
type: DataTypes.DATE,
allowNull: false,
},
endDate: {
type: DataTypes.DATE,
allowNull: false,
}
},
{
sequelize,
modelName: 'PoliticalOfficeHistory',
tableName: 'political_office_history',
schema: 'falukant_log',
timestamps: true,
underscored: true,
}
);
export default PoliticalOfficeHistory;

View File

@@ -1,4 +1,5 @@
// falukant/predefine/political_office_prerequisite.js
// models/falukant/predefine/political_office_prerequisite.js
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../../utils/sequelize.js';
@@ -10,10 +11,13 @@ PoliticalOfficePrerequisite.init({
primaryKey: true,
autoIncrement: true,
},
political_office_id: {
// Neu: Feld heißt jetzt eindeutig "office_type_id"
office_type_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
prerequisite: {
type: DataTypes.JSONB,
allowNull: false,

View File

@@ -94,6 +94,8 @@ import Election from './falukant/data/election.js';
import Candidate from './falukant/data/candidate.js';
import Vote from './falukant/data/vote.js';
import ElectionResult from './falukant/data/election_result.js';
import PoliticalOfficeHistory from './falukant/log/political_office_history.js';
import ElectionHistory from './falukant/log/election_history.js';
const models = {
SettingsType,
@@ -191,6 +193,8 @@ const models = {
Candidate,
Vote,
ElectionResult,
PoliticalOfficeHistory,
ElectionHistory,
};
export default models;

View File

@@ -241,6 +241,180 @@ export async function createTriggers() {
$$ LANGUAGE plpgsql VOLATILE;
`;
// process_electionsStored-Procedure anlegen
const createProcessElectionsFunction = `
CREATE OR REPLACE FUNCTION falukant_data.process_elections()
RETURNS TABLE (
office_id INTEGER,
office_type_id INTEGER,
character_id INTEGER,
region_id INTEGER
)
AS $$
BEGIN
RETURN QUERY
WITH
-- 1) Alle Wahlen, die vor mindestens 3 Tagen erstellt wurden
to_process AS (
SELECT
e.id AS election_id,
e.office_type_id AS tp_office_type_id,
e.region_id AS tp_region_id,
e.posts_to_fill AS tp_posts_to_fill,
e.date AS tp_election_date
FROM falukant_data.election e
WHERE (e.created_at::date + INTERVAL '3 days') <= NOW()::date
),
-- 2) Stimmen pro Kandidat zählen
votes AS (
SELECT
tp.election_id,
tp.tp_posts_to_fill AS posts_to_fill,
c.character_id,
COUNT(v.*) AS votes_received
FROM to_process tp
JOIN falukant_data.candidate c
ON c.election_id = tp.election_id
LEFT JOIN falukant_data.vote v
ON v.election_id = c.election_id
AND v.candidate_id = c.id
GROUP BY tp.election_id, tp.tp_posts_to_fill, c.character_id
),
-- 3) Ranking nach Stimmen
ranked AS (
SELECT
v.election_id,
v.character_id,
v.votes_received,
ROW_NUMBER() OVER (
PARTITION BY v.election_id
ORDER BY v.votes_received DESC, RANDOM()
) AS rn
FROM votes v
),
-- 4) Top-N (posts_to_fill) sind Gewinner
winners AS (
SELECT
r.election_id,
r.character_id
FROM ranked r
JOIN to_process tp
ON tp.election_id = r.election_id
WHERE r.rn <= tp.tp_posts_to_fill
),
-- 5) Verbleibende Kandidaten ohne Gewinner
remaining AS (
SELECT
tp.election_id,
c.character_id
FROM to_process tp
JOIN falukant_data.candidate c
ON c.election_id = tp.election_id
WHERE c.character_id NOT IN (
SELECT w.character_id
FROM winners w
WHERE w.election_id = tp.election_id
)
),
-- 6) Zufalls-Nachrücker bis alle Plätze gefüllt sind
random_fill AS (
SELECT
rp.election_id,
rp.character_id
FROM remaining rp
JOIN to_process tp
ON tp.election_id = rp.election_id
JOIN LATERAL (
SELECT r2.character_id
FROM remaining r2
WHERE r2.election_id = rp.election_id
ORDER BY RANDOM()
LIMIT GREATEST(
0,
tp.tp_posts_to_fill
- (SELECT COUNT(*) FROM winners w2 WHERE w2.election_id = tp.election_id)
)
) sub
ON sub.character_id = rp.character_id
),
-- 7) Finale Gewinner (Winners random_fill)
final_winners AS (
SELECT * FROM winners
UNION ALL
SELECT * FROM random_fill
),
-- 8) Neue Ämter anlegen und sofort zurückliefern
created_offices AS (
INSERT INTO falukant_data.political_office
(office_type_id, character_id, created_at, updated_at, region_id)
SELECT
tp.tp_office_type_id,
fw.character_id,
NOW() AS created_at,
NOW() AS updated_at,
tp.tp_region_id
FROM final_winners fw
JOIN to_process tp
ON tp.election_id = fw.election_id
RETURNING
id AS co_office_id,
falukant_data.political_office.office_type_id AS co_office_type_id,
falukant_data.political_office.character_id AS co_character_id,
falukant_data.political_office.region_id AS co_region_id
),
-- 9) election_history befüllen
_hist AS (
INSERT INTO falukant_log.election_history
(election_id, political_office_type_id, election_date, election_result, created_at, updated_at)
SELECT
tp.election_id,
tp.tp_office_type_id,
tp.tp_election_date,
(
SELECT json_agg(vr)
FROM votes vr
WHERE vr.election_id = tp.election_id
),
NOW() AS created_at,
NOW() AS updated_at
FROM to_process tp
),
-- 10) Cleanup: Stimmen, Kandidaten und Wahlen löschen
_del_votes AS (
DELETE FROM falukant_data.vote
WHERE election_id IN (SELECT election_id FROM to_process)
),
_del_candidates AS (
DELETE FROM falukant_data.candidate
WHERE election_id IN (SELECT election_id FROM to_process)
),
_del_elections AS (
DELETE FROM falukant_data.election
WHERE id IN (SELECT election_id FROM to_process)
)
-- 11) Ergebnis wirklich zurückliefern
SELECT
co.co_office_id AS office_id,
co.co_office_type_id,
co.co_character_id,
co.co_region_id
FROM created_offices co
ORDER BY co.co_region_id, co.co_office_id;
END;
$$ LANGUAGE plpgsql;
`;
try {
await sequelize.query(createTriggerFunction);
await sequelize.query(createInsertTrigger);
@@ -257,6 +431,7 @@ export async function createTriggers() {
await sequelize.query(createChildRelationNameFunction);
await sequelize.query(createChildRelationNameTrigger);
await sequelize.query(createRandomMoodUpdateMethod);
await sequelize.query(createProcessElectionsFunction);
await initializeCharacterTraitTrigger();
console.log('Triggers created successfully');

View File

@@ -11,8 +11,10 @@ router.get('/character/affect', falukantController.getCharacterAffect);
router.get('/name/randomfirstname/:gender', falukantController.randomFirstName);
router.get('/name/randomlastname', falukantController.randomLastName);
router.get('/info', falukantController.getInfo);
router.get('/branches/types', falukantController.getBranchTypes);
router.get('/branches/:branch', falukantController.getBranch);
router.get('/branches', falukantController.getBranches);
router.post('/branches', falukantController.createBranch);
router.get('/productions', falukantController.getAllProductions);
router.post('/production', falukantController.createProduction);
router.get('/production/:branchId', falukantController.getProduction);
@@ -43,6 +45,8 @@ router.get('/nobility/titels', falukantController.getTitelsOfNobility);
router.get('/houses/types', falukantController.getHouseTypes);
router.get('/houses/buyable', falukantController.getBuyableHouses);
router.get('/houses', falukantController.getUserHouse);
router.post('/houses/renovate-all', falukantController.renovateAll);
router.post('/houses/renovate', falukantController.renovate);
router.post('/houses', falukantController.buyUserHouse);
router.get('/party/types', falukantController.getPartyTypes);
router.post('/party', falukantController.createParty);
@@ -57,5 +61,13 @@ router.post('/bank/credits', falukantController.takeBankCredits);
router.get('/nobility', falukantController.getNobility);
router.post('/nobility', falukantController.advanceNobility);
router.get('/health', falukantController.getHealth);
router.post('/health', falukantController.healthActivity)
router.post('/health', falukantController.healthActivity);
router.get('/politics/overview', falukantController.getPoliticsOverview);
router.get('/politics/open', falukantController.getOpenPolitics);
router.get('/politics/elections', falukantController.getElections);
router.post('/politics/elections', falukantController.vote);
router.get('/politics/open', falukantController.getOpenPolitics);
router.post('/politics/open', falukantController.applyForElections);
router.get('/cities', falukantController.getRegions);
export default router;

View File

@@ -1,6 +1,6 @@
import BaseService from './BaseService.js';
import { Sequelize, Op, where } from 'sequelize';
import { Sequelize, Op } from 'sequelize';
import { sequelize } from '../utils/sequelize.js';
import FalukantPredefineFirstname from '../models/falukant/predefine/firstname.js';
import FalukantPredefineLastname from '../models/falukant/predefine/lastname.js';
import FalukantUser from '../models/falukant/data/user.js';
@@ -47,6 +47,12 @@ import LearnRecipient from '../models/falukant/type/learn_recipient.js';
import Credit from '../models/falukant/data/credit.js';
import TitleRequirement from '../models/falukant/type/title_requirement.js';
import HealthActivity from '../models/falukant/log/health_activity.js';
import Election from '../models/falukant/data/election.js';
import PoliticalOfficeType from '../models/falukant/type/political_office_type.js';
import Candidate from '../models/falukant/data/candidate.js';
import Vote from '../models/falukant/data/vote.js';
import PoliticalOfficePrerequisite from '../models/falukant/predefine/political_office_prerequisite.js';
import PoliticalOfficeHistory from '../models/falukant/log/political_office_history.js';
function calcAge(birthdate) {
const b = new Date(birthdate); b.setHours(0, 0);
@@ -96,13 +102,33 @@ class FalukantService extends BaseService {
all: { min: 400, max: 40000 }
};
static HEALTH_ACTIVITIES = [
{ tr: "barber", method: "healthBarber", cost: 10 },
{ tr: "doctor", method: "healthDoctor", cost: 50 },
{ tr: "witch", method: "healthWitch", cost: 500 },
{ tr: "pill", method: "healthPill", cost: 5000 },
{ tr: "drunkOfLife", method: "healthDruckOfLife", cost:5000000 }
];
{ tr: "barber", method: "healthBarber", cost: 10 },
{ tr: "doctor", method: "healthDoctor", cost: 50 },
{ tr: "witch", method: "healthWitch", cost: 500 },
{ tr: "pill", method: "healthPill", cost: 5000 },
{ tr: "drunkOfLife", method: "healthDruckOfLife", cost: 5000000 }
];
static RECURSIVE_REGION_SEARCH = `
WITH RECURSIVE ancestors AS (
SELECT
r.id,
r.parent_id
FROM falukant_data.region r
join falukant_data."character" c
on c.region_id = r.id
WHERE c.user_id = :user_id
UNION ALL
SELECT
r.id,
r.parent_id
FROM falukant_data.region r
JOIN ancestors a ON r.id = a.parent_id
)
SELECT id
FROM ancestors;
`;
async getFalukantUserByHashedId(hashedId) {
const user = await FalukantUser.findOne({
include: [
@@ -168,9 +194,21 @@ class FalukantService extends BaseService {
attributes: ['name']
}
]
}
},
{
model: UserHouse,
as: 'userHouse',
include: [
{
model: HouseType,
as: 'houseType',
'attributes': ['labelTr', 'position']
},
],
attributes: ['roofCondition'],
},
],
attributes: ['money', 'creditAmount', 'todayCreditTaken']
attributes: ['money', 'creditAmount', 'todayCreditTaken',]
});
if (!u) throw new Error('User not found');
if (u.character?.birthdate) u.character.setDataValue('age', calcAge(u.character.birthdate));
@@ -277,6 +315,38 @@ class FalukantService extends BaseService {
return bs.map(b => ({ ...b.toJSON(), isMainBranch: u.mainBranchRegionId === b.regionId }));
}
async createBranch(hashedUserId, cityId, branchTypeId) {
const user = await getFalukantUserOrFail(hashedUserId);
const branchType = await BranchType.findByPk(branchTypeId);
if (!branchType) {
throw new Error(`Unknown branchTypeId ${branchTypeId}`);
}
const existingCount = await Branch.count({
where: { falukantUserId: user.id }
});
const exponentBase = Math.max(existingCount, 1);
const rawCost = branchType.baseCost * Math.pow(exponentBase, 1.2);
const cost = Math.round(rawCost * 100) / 100;
await updateFalukantUserMoney(
user.id,
-cost,
'create_branch'
);
const branch = await Branch.create({
branchTypeId,
regionId: cityId,
falukantUserId: user.id
});
return branch;
}
async getBranchTypes(hashedUserId) {
const user = await getFalukantUserOrFail(hashedUserId);
const branchTypes = await BranchType.findAll();
return branchTypes;
}
async getBranch(hashedUserId, branchId) {
const u = await getFalukantUserOrFail(hashedUserId);
const br = await Branch.findOne({
@@ -318,6 +388,8 @@ class FalukantService extends BaseService {
const runningProductions = await Production.findAll({ where: { branchId: b.id } });
if (runningProductions.length >= 2) {
throw new Error('Too many productions');
return; // wird später implementiert, wenn familie implementiert ist.
}
if (!p) throw new Error('Product not found');
quantity = Math.min(100, quantity);
@@ -822,9 +894,12 @@ class FalukantService extends BaseService {
await this.deleteExpiredProposals();
const existingProposals = await this.fetchProposals(falukantUserId, regionId);
if (existingProposals.length > 0) {
console.log('Existing proposals:', existingProposals);
return this.formatProposals(existingProposals);
}
console.log('No existing proposals, generating new ones');
await this.generateProposals(falukantUserId, regionId);
console.log('Fetch new proposals');
const newProposals = await this.fetchProposals(falukantUserId, regionId);
return this.formatProposals(newProposals);
}
@@ -867,13 +942,14 @@ class FalukantService extends BaseService {
}
async generateProposals(falukantUserId, regionId) {
const proposalCount = Math.floor(Math.random() * 3) + 3;
for (let i = 0; i < proposalCount; i++) {
const directorCharacter = await FalukantCharacter.findOne({
where: {
regionId,
createdAt: {
[Op.lt]: new Date(Date.now() - 21 * 24 * 60 * 60 * 1000),
try {
const threeWeeksAgo = new Date(Date.now() - 21 * 24 * 60 * 60 * 1000);
const proposalCount = Math.floor(Math.random() * 3) + 3;
for (let i = 0; i < proposalCount; i++) {
const directorCharacter = await FalukantCharacter.findOne({
where: {
regionId,
createdAt: { [Op.lt]: threeWeeksAgo },
},
include: [
{
@@ -881,22 +957,25 @@ class FalukantService extends BaseService {
as: 'nobleTitle',
attributes: ['level'],
},
]
},
order: Sequelize.fn('RANDOM'),
});
if (!directorCharacter) {
throw new Error('No directors available for the region');
],
order: sequelize.literal('RANDOM()'),
});
if (!directorCharacter) {
throw new Error('No directors available for the region');
}
const avgKnowledge = await this.calculateAverageKnowledge(directorCharacter.id);
const proposedIncome = Math.round(
directorCharacter.nobleTitle.level * Math.pow(1.231, avgKnowledge / 1.5)
);
await DirectorProposal.create({
directorCharacterId: directorCharacter.id,
employerUserId: falukantUserId,
proposedIncome,
});
}
const avgKnowledge = await this.calculateAverageKnowledge(directorCharacter.id);
const proposedIncome = Math.round(
directorCharacter.nobleTitle.level * Math.pow(1.231, avgKnowledge / 1.5)
);
await DirectorProposal.create({
directorCharacterId: directorCharacter.id,
employerUserId: falukantUserId,
proposedIncome,
});
} catch (error) {
console.log(error.message, error.stack);
throw new Error(error.message);
}
}
@@ -1394,39 +1473,65 @@ class FalukantService extends BaseService {
}
async getGifts(hashedUserId) {
// 1) Mein User & Character
const user = await this.getFalukantUserByHashedId(hashedUserId);
const character = await FalukantCharacter.findOne({
where: { userId: user.id },
const myChar = await FalukantCharacter.findOne({ where: { userId: user.id } });
if (!myChar) throw new Error('Character not found');
// 2) Beziehung finden und „anderen“ Character bestimmen
const rel = await Relationship.findOne({
where: {
[Op.or]: [
{ character1Id: myChar.id },
{ character2Id: myChar.id }
]
},
include: [
{ model: FalukantCharacter, as: 'character1', include: [{ model: CharacterTrait, as: 'traits' }] },
{ model: FalukantCharacter, as: 'character2', include: [{ model: CharacterTrait, as: 'traits' }] }
]
});
if (!character) {
throw new Error('Character not found');
}
let gifts = await PromotionalGift.findAll({
if (!rel) throw new Error('Beziehung nicht gefunden');
const relatedChar = rel.character1.id === myChar.id ? rel.character2 : rel.character1;
// 3) Trait-IDs und Mood des relatedChar
const relatedTraitIds = relatedChar.traits.map(t => t.id);
const relatedMoodId = relatedChar.moodId;
// 4) Gifts laden aber nur die passenden Moods und Traits als Unter-Arrays
const gifts = await PromotionalGift.findAll({
include: [
{
model: PromotionalGiftMood,
as: 'promotionalgiftmoods',
attributes: ['mood_id', 'suitability']
attributes: ['mood_id', 'suitability'],
where: { mood_id: relatedMoodId },
required: false // Gifts ohne Mood-Match bleiben erhalten, haben dann leeres Array
},
{
model: PromotionalGiftCharacterTrait,
as: 'characterTraits',
attributes: ['trait_id', 'suitability']
attributes: ['trait_id', 'suitability'],
where: { trait_id: relatedTraitIds },
required: false // Gifts ohne Trait-Match bleiben erhalten
}
]
});
const lowestTitleOfNobility = await TitleOfNobility.findOne({
order: [['id', 'ASC']],
});
return await Promise.all(gifts.map(async (gift) => {
return {
id: gift.id,
name: gift.name,
cost: await this.getGiftCost(gift.value, character.titleOfNobility, lowestTitleOfNobility.id),
moodsAffects: gift.promotionalgiftmoods,
charactersAffects: gift.characterTraits,
};
}));
// 5) Rest wie gehabt: Kosten berechnen und zurückgeben
const lowestTitleOfNobility = await TitleOfNobility.findOne({ order: [['id', 'ASC']] });
return Promise.all(gifts.map(async gift => ({
id: gift.id,
name: gift.name,
cost: await this.getGiftCost(
gift.value,
myChar.titleOfNobility,
lowestTitleOfNobility.id
),
moodsAffects: gift.promotionalgiftmoods, // nur Einträge mit relatedMoodId
charactersAffects: gift.characterTraits // nur Einträge mit relatedTraitIds
})));
}
async getChildren(hashedUserId) {
@@ -2199,8 +2304,8 @@ class FalukantService extends BaseService {
async getHealth(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId);
const healthActivities = FalukantService.HEALTH_ACTIVITIES.map((activity) => {return { tr: activity.tr, cost: activity.cost }});
const healthHistory = await HealthActivity.findAll({
const healthActivities = FalukantService.HEALTH_ACTIVITIES.map((activity) => { return { tr: activity.tr, cost: activity.cost } });
const healthHistory = await HealthActivity.findAll({
where: { characterId: user.character.id },
order: [['createdAt', 'DESC']],
});
@@ -2208,7 +2313,7 @@ class FalukantService extends BaseService {
age: calcAge(user.character.birthdate),
health: user.character.health,
healthActivities: healthActivities,
history: healthHistory.map((activity) => {return { tr: activity.activityTr, cost: activity.cost, createdAt: activity.createdAt, success: activity.successPercentage }}),
history: healthHistory.map((activity) => { return { tr: activity.activityTr, cost: activity.cost, createdAt: activity.createdAt, success: activity.successPercentage } }),
};
}
@@ -2232,14 +2337,14 @@ class FalukantService extends BaseService {
if (!activityObject) {
throw new Error('invalid');
}
if (user.money - activityObject.cost < 0) {
if (user.money - activityObject.cost < 0) {
throw new Error('no money');
}
user.character.health -= activityObject.cost;
await HealthActivity.create({
characterId: user.character.id,
activityTr: activity,
successPercentage: await this[activityObject.method](user),
successPercentage: await this[activityObject.method](user),
cost: activityObject.cost
});
updateFalukantUserMoney(user.id, -activityObject.cost, 'health.' + activity);
@@ -2256,32 +2361,424 @@ class FalukantService extends BaseService {
health: Math.min(FalukantService.HEALTH_MAX || 100, Math.max(0, char.health + delta))
});
return delta;
}
async healthBarber(user) {
const raw = Math.floor(Math.random() * 11) - 5;
return this.healthChange(user, raw);
}
async healthDoctor(user) {
const raw = Math.floor(Math.random() * 8) - 2;
return this.healthChange(user, raw);
}
async healthWitch(user) {
const raw = Math.floor(Math.random() * 7) - 1;
return this.healthChange(user, raw);
}
async healthPill(user) {
const raw = Math.floor(Math.random() * 8);
return this.healthChange(user, raw);
}
async healthDrunkOfLife(user) {
const raw = Math.floor(Math.random() * 26);
return this.healthChange(user, raw);
}
}
async healthBarber(user) {
const raw = Math.floor(Math.random() * 11) - 5;
return this.healthChange(user, raw);
}
async healthDoctor(user) {
const raw = Math.floor(Math.random() * 8) - 2;
return this.healthChange(user, raw);
}
async healthWitch(user) {
const raw = Math.floor(Math.random() * 7) - 1;
return this.healthChange(user, raw);
}
async healthPill(user) {
const raw = Math.floor(Math.random() * 8);
return this.healthChange(user, raw);
}
async healthDrunkOfLife(user) {
const raw = Math.floor(Math.random() * 26);
return this.healthChange(user, raw);
}
async getPoliticsOverview(hashedUserId) {
}
async getOpenPolitics(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId);
if (!user || user.character.nobleTitle.labelTr === 'noncivil') {
return [];
}
}
async getElections(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId);
if (!user || user.character.nobleTitle.labelTr === 'noncivil') {
return [];
}
const rows = await sequelize.query(
FalukantService.RECURSIVE_REGION_SEARCH,
{
replacements: { user_id: user.id },
type: sequelize.QueryTypes.SELECT
}
);
const regionIds = rows.map(r => r.id);
// 3) Zeitbereich "heute"
const todayStart = new Date();
todayStart.setHours(0, 0, 0, 0);
const todayEnd = new Date();
todayEnd.setHours(23, 59, 59, 999);
// 4) Wahlen laden (inkl. Kandidaten, Stimmen und Verknüpfungen)
const rawElections = await Election.findAll({
where: {
regionId: { [Op.in]: regionIds },
date: { [Op.between]: [todayStart, todayEnd] }
},
include: [
{
model: RegionData,
as: 'region',
attributes: ['name'],
include: [{
model: RegionType,
as: 'regionType',
attributes: ['labelTr']
}]
},
{
model: PoliticalOfficeType,
as: 'officeType',
attributes: ['name']
},
{
model: Candidate,
as: 'candidates',
attributes: ['id'],
include: [{
model: FalukantCharacter,
as: 'character',
attributes: ['birthdate', 'gender'],
include: [
{ model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'] },
{ model: FalukantPredefineLastname, as: 'definedLastName', attributes: ['name'] },
{ model: TitleOfNobility, as: 'nobleTitle', attributes: ['labelTr'] }
]
}]
},
{
model: Vote,
as: 'votes',
attributes: ['candidateId'],
where: {
falukantUserId: user.id
},
required: false
}
]
});
return rawElections.map(election => {
const e = election.get({ plain: true });
const voted = Array.isArray(e.votes) && e.votes.length > 0;
const reducedCandidates = (e.candidates || []).map(cand => {
const ch = cand.character || {};
const firstname = ch.definedFirstName?.name || '';
const lastname = ch.definedLastName?.name || '';
return {
id: cand.id,
title: ch.nobleTitle?.labelTr || null,
name: `${firstname} ${lastname}`.trim(),
age: calcAge(ch.birthdate),
gender: ch.gender
};
});
return {
id: e.id,
officeType: { name: e.officeType.name },
region: {
name: e.region.name,
regionType: { labelTr: e.region.regionType.labelTr }
},
date: e.date,
postsToFill: e.postsToFill,
candidates: reducedCandidates,
voted: voted,
votedFor: voted ? e.votes.map(vote => { return vote.candidateId }) : null,
};
});
}
async vote(hashedUserId, votes) {
const elections = await this.getElections(hashedUserId);
if (!Array.isArray(elections) || elections.length === 0) {
throw new Error('No elections found');
}
const user = await this.getFalukantUserByHashedId(hashedUserId);
if (!user) {
throw new Error('User not found');
}
const validElections = votes.filter(voteEntry => {
const e = elections.find(el => el.id === voteEntry.electionId);
return e && !e.voted;
});
if (validElections.length === 0) {
throw new Error('No valid elections to vote for (either nonexistent or already voted)');
}
validElections.forEach(voteEntry => {
const e = elections.find(el => el.id === voteEntry.electionId);
const allowedIds = e.candidates.map(c => c.id);
voteEntry.candidateIds.forEach(cid => {
if (!allowedIds.includes(cid)) {
throw new Error(`Candidate ID ${cid} is not valid for election ${e.id}`);
}
});
if (voteEntry.candidateIds.length > e.postsToFill) {
throw new Error(`Too many candidates selected for election ${e.id}. Allowed: ${e.postsToFill}`);
}
});
return await sequelize.transaction(async (tx) => {
const toCreate = [];
validElections.forEach(voteEntry => {
voteEntry.candidateIds.forEach(candidateId => {
toCreate.push({
electionId: voteEntry.electionId,
candidateId,
falukantUserId: user.id
});
});
});
await Vote.bulkCreate(toCreate, {
transaction: tx,
ignoreDuplicates: true,
returning: false
});
return { success: true };
});
}
async getOpenPolitics(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId);
const characterId = user.character.id;
const rows = await sequelize.query(
FalukantService.RECURSIVE_REGION_SEARCH,
{
replacements: { user_id: user.id },
type: sequelize.QueryTypes.SELECT
}
);
const regionIds = rows.map(r => r.id);
const histories = await PoliticalOfficeHistory.findAll({
where: { characterId },
attributes: ['officeTypeId', 'startDate', 'endDate']
});
const heldOfficeTypeIds = histories.map(h => h.officeTypeId);
const allTypes = await PoliticalOfficeType.findAll({ attributes: ['id', 'name'] });
const nameToId = Object.fromEntries(allTypes.map(t => [t.name, t.id]));
const openPositions = await Election.findAll({
where: {
regionId: { [Op.in]: regionIds },
date: { [Op.lt]: new Date() }
},
include: [
{
model: RegionData,
as: 'region',
attributes: ['name'],
include: [
{ model: RegionType, as: 'regionType', attributes: ['labelTr'] }
]
},
{ model: Candidate, as: 'candidates' },
{
model: PoliticalOfficeType, as: 'officeType',
include: [{ model: PoliticalOfficePrerequisite, as: 'prerequisites' }]
}
]
});
const result = openPositions
.filter(election => {
const prereqs = election.officeType.prerequisites || [];
return prereqs.some(pr => {
const jobs = pr.prerequisite.jobs;
if (!Array.isArray(jobs) || jobs.length === 0) return true;
return jobs.some(jobName => {
const reqId = nameToId[jobName];
return heldOfficeTypeIds.includes(reqId);
});
});
})
.map(election => {
const e = election.get({ plain: true });
const jobs = e.officeType.prerequisites[0]?.prerequisite.jobs || [];
const matchingHistory = histories
.filter(h => jobs.includes(allTypes.find(t => t.id === h.officeTypeId)?.name))
.map(h => ({
officeTypeId: h.officeTypeId,
startDate: h.startDate,
endDate: h.endDate
}));
return {
...e,
history: matchingHistory
};
});
return result;
}
async applyForElections(hashedUserId, electionIds) {
// 1) Hole FalukantUser + Character
const user = await this.getFalukantUserByHashedId(hashedUserId);
if (!user) {
throw new Error('User nicht gefunden');
}
const character = user.character;
if (!character) {
throw new Error('Kein Charakter zum User gefunden');
}
// 2) NoncivilTitel aussperren
if (character.nobleTitle.labelTr === 'noncivil') {
return { applied: [], skipped: electionIds };
}
// 3) Ermittle die heute offenen Wahlen, auf die er zugreifen darf
// (getElections liefert id, officeType, region, date, postsToFill, candidates, voted…)
const openElections = await this.getElections(hashedUserId);
const allowedIds = new Set(openElections.map(e => e.id));
// 4) Filter alle electionIds auf gültige/erlaubte
const toTry = electionIds.filter(id => allowedIds.has(id));
if (toTry.length === 0) {
return { applied: [], skipped: electionIds };
}
// 5) Prüfe, auf welche dieser Wahlen der Character bereits als Candidate eingetragen ist
const existing = await Candidate.findAll({
where: {
electionId: { [Op.in]: toTry },
characterId: character.id
},
attributes: ['electionId']
});
const alreadyIds = new Set(existing.map(c => c.electionId));
// 6) Erstelle Liste der Wahlen, für die er sich noch nicht beworben hat
const newApplications = toTry.filter(id => !alreadyIds.has(id));
const skipped = electionIds.filter(id => !newApplications.includes(id));
console.log(newApplications, skipped);
// 7) Bulk-Insert aller neuen Bewerbungen
if (newApplications.length > 0) {
const toInsert = newApplications.map(eid => ({
electionId: eid,
characterId: character.id
}));
await Candidate.bulkCreate(toInsert);
}
return {
applied: newApplications,
skipped: skipped
};
}
async getRegions(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId);
const regions = await RegionData.findAll({
attributes: ['id', 'name', 'map'],
include: [
{
model: RegionType,
as: 'regionType',
where: {
labelTr: 'city'
},
attributes: ['labelTr']
},
{
model: Branch,
as: 'branches',
where: {
falukantUserId: user.id
},
include: [
{
model: BranchType,
as: 'branchType',
attributes: ['labelTr'],
},
],
attributes: ['branchTypeId'],
required: false,
}
]
});
return regions;
}
async renovate(hashedUserId, element) {
const user = await getFalukantUserOrFail(hashedUserId);
const house = await UserHouse.findOne({
where: { userId: user.id },
include: [{ model: HouseType, as: 'houseType' }]
});
if (!house) throw new Error('House not found');
const oldValue = house[element];
if (oldValue >= 100) {
return { cost: 0 };
}
const baseCost = house.houseType?.cost || 0;
const cost = this._calculateRenovationCost(baseCost, element, oldValue);
house[element] = 100;
await house.save();
await updateFalukantUserMoney(
user.id,
-cost,
`renovation_${element}`
);
return { cost };
}
_calculateRenovationCost(baseCost, key, currentVal) {
const weights = {
roofCondition: 0.25,
wallCondition: 0.25,
floorCondition: 0.25,
windowCondition: 0.25
};
const weight = weights[key] || 0;
const missing = 100 - currentVal;
const raw = (missing / 100) * baseCost * weight;
return Math.round(raw * 100) / 100;
}
async renovateAll(hashedUserId) {
const user = await getFalukantUserOrFail(hashedUserId);
const house = await UserHouse.findOne({
where: { userId: user.id },
include: [{ model: HouseType, as: 'houseType' }]
});
if (!house) throw new Error('House not found');
const baseCost = house.houseType?.cost || 0;
const keys = ['roofCondition', 'wallCondition', 'floorCondition', 'windowCondition'];
let rawSum = 0;
for (const key of keys) {
const current = house[key];
if (current < 100) {
rawSum += this._calculateRenovationCost(baseCost, key, current);
}
}
const totalCost = Math.round(rawSum * 0.8 * 100) / 100;
for (const key of keys) {
house[key] = 100;
}
await house.save();
await updateFalukantUserMoney(
user.id,
-totalCost,
'renovation_all'
);
return { cost: totalCost };
}
}
export default new FalukantService();

View File

@@ -12,6 +12,8 @@ import PartyType from "../../models/falukant/type/party.js";
import MusicType from "../../models/falukant/type/music.js";
import BanquetteType from "../../models/falukant/type/banquette.js";
import LearnRecipient from "../../models/falukant/type/learn_recipient.js";
import PoliticalOfficeType from "../../models/falukant/type/political_office_type.js";
import PoliticalOfficePrerequisite from "../../models/falukant/predefine/political_office_prerequisite.js";
export const initializeFalukantTypes = async () => {
await initializeFalukantTypeRegions();
@@ -25,6 +27,8 @@ export const initializeFalukantTypes = async () => {
await initializeFalukantMusicTypes();
await initializeFalukantBanquetteTypes();
await initializeLearnerTypes();
await initializePoliticalOfficeTypes();
await initializePoliticalOfficePrerequisites();
};
const regionTypes = [];
@@ -39,14 +43,15 @@ const regionTypeTrs = [
const regions = [
{ labelTr: "falukant", regionType: "country", parentTr: null },
{ labelTr: "duchy1", regionType: "duchy", parentTr: "falukant" },
{ labelTr: "markgravate", regionType: "markgravate", parentTr: "duchy1" },
{ labelTr: "shire1", regionType: "shire", parentTr: "markgravate" },
{ labelTr: "county1", regionType: "county", parentTr: "shire1" },
{ labelTr: "town1", regionType: "city", parentTr: "county1" },
{ labelTr: "town2", regionType: "city", parentTr: "county1" },
{ labelTr: "town3", regionType: "city", parentTr: "county1" },
{ labelTr: "town4", regionType: "city", parentTr: "county1" },
{ labelTr: "Hessen", regionType: "duchy", parentTr: "falukant" },
{ labelTr: "Groß-Benbach", regionType: "markgravate", parentTr: "Hessen" },
{ labelTr: "Siebenbachen", regionType: "shire", parentTr: "Groß-Benbach" },
{ labelTr: "Bad Homburg", regionType: "county", parentTr: "Siebenbachen" },
{ labelTr: "Maintal", regionType: "county", parentTr: "Siebenbachen" },
{ labelTr: "Frankfurt", regionType: "city", parentTr: "Bad Homburg", map: {x: 187, y: 117, w: 10, h:11} },
{ labelTr: "Oberursel", regionType: "city", parentTr: "Bad Homburg", map: {x: 168, y: 121, w: 10, h:11} },
{ labelTr: "Offenbach", regionType: "city", parentTr: "Bad Homburg", map: {x: 171, y: 142, w: 10, h:11} },
{ labelTr: "Königstein", regionType: "city", parentTr: "Maintal", map: {x: 207, y: 124, w: 24, h:18} },
];
const relationships = [
@@ -244,8 +249,8 @@ const musicTypes = [
];
const banquetteTypes = [
{ type: 'bread', cost: 5, reputationGrowth: 0 },
{ type: 'roastWithBeer', cost: 200, reputationGrowth: 5 },
{ type: 'bread', cost: 5, reputationGrowth: 0 },
{ type: 'roastWithBeer', cost: 200, reputationGrowth: 5 },
{ type: 'poultryWithVegetablesAndWine', cost: 5000, reputationGrowth: 10 },
{ type: 'extensiveBuffet', cost: 100000, reputationGrowth: 20 }
];
@@ -256,6 +261,282 @@ const learnerTypes = [
{ tr: 'director', },
];
const politicalOffices = [
{ tr: "assessor", seatsPerRegion: 10, regionType: "city", termLength: 5 },
{ tr: "councillor", seatsPerRegion: 7, regionType: "city", termLength: 7 },
{ tr: "council", seatsPerRegion: 5, regionType: "city", termLength: 4 },
{ tr: "beadle", seatsPerRegion: 1, regionType: "city", termLength: 6 },
{ tr: "town-clerk", seatsPerRegion: 3, regionType: "city", termLength: 10 },
{ tr: "mayor", seatsPerRegion: 1, regionType: "city", termLength: 3 },
{ tr: "master-builder", seatsPerRegion: 10, regionType: "county", termLength: 10 },
{ tr: "village-major", seatsPerRegion: 6, regionType: "county", termLength: 5 },
{ tr: "judge", seatsPerRegion: 3, regionType: "county", termLength: 8 },
{ tr: "bailif", seatsPerRegion: 1, regionType: "county", termLength: 4 },
{ tr: "taxman", seatsPerRegion: 8, regionType: "shire", termLength: 5 },
{ tr: "sheriff", seatsPerRegion: 5, regionType: "shire", termLength: 8 },
{ tr: "consultant", seatsPerRegion: 3, regionType: "shire", termLength: 9 },
{ tr: "treasurer", seatsPerRegion: 1, regionType: "shire", termLength: 7 },
{ tr: "hangman", seatsPerRegion: 9, regionType: "markgravate", termLength: 5 },
{ tr: "territorial-council", seatsPerRegion: 6, regionType: "markgravate", termLength: 6 },
{ tr: "territorial-council-speaker", seatsPerRegion: 4, regionType: "markgravate", termLength: 8 },
{ tr: "ruler-consultant", seatsPerRegion: 1, regionType: "markgravate", termLength: 3 },
{ tr: "state-administrator", seatsPerRegion: 7, regionType: "duchy", termLength: 3 },
{ tr: "super-state-administrator", seatsPerRegion: 5, regionType: "duchy", termLength: 6 },
{ tr: "governor", seatsPerRegion: 1, regionType: "duchy", termLength: 5 },
{ tr: "ministry-helper", seatsPerRegion: 12, regionType: "country", termLength: 4 },
{ tr: "minister", seatsPerRegion: 3, regionType: "country", termLength: 4 },
{ tr: "chancellor", seatsPerRegion: 1, regionType: "country", termLength: 4 }
];
const politicalOfficePrerequisites = [
{
officeTr: "assessor",
prerequisite: {
titles: [
"civil", "sir", "townlord", "by", "landlord", "knight",
"baron", "count", "palsgrave", "margrave", "landgrave",
"ruler", "elector", "imperial-prince", "duke", "grand-duke",
"prince-regent", "king"
]
}
},
{
officeTr: "councillor",
prerequisite: {
titles: [
"civil", "sir", "townlord", "by", "landlord", "knight",
"baron", "count", "palsgrave", "margrave", "landgrave",
"ruler", "elector", "imperial-prince", "duke", "grand-duke",
"prince-regent", "king"
],
jobs: ["assessor"]
}
},
{
officeTr: "council",
prerequisite: {
titles: [
"civil", "sir", "townlord", "by", "landlord", "knight",
"baron", "count", "palsgrave", "margrave", "landgrave",
"ruler", "elector", "imperial-prince", "duke", "grand-duke",
"prince-regent", "king"
],
jobs: ["councillor"]
}
},
{
officeTr: "beadle",
prerequisite: {
titles: [
"sir", "townlord", "by", "landlord", "knight", "baron",
"count", "palsgrave", "margrave", "landgrave", "ruler",
"elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["council"]
}
},
{
officeTr: "town-clerk",
prerequisite: {
titles: [
"sir", "townlord", "by", "landlord", "knight", "baron",
"count", "palsgrave", "margrave", "landgrave", "ruler",
"elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["council"]
}
},
{
officeTr: "mayor",
prerequisite: {
titles: [
"townlord", "by", "landlord", "knight", "baron", "count",
"palsgrave", "margrave", "landgrave", "ruler", "elector",
"imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["beadle", "town-clerk"]
}
},
{
officeTr: "master-builder",
prerequisite: {
titles: [
"by", "landlord", "knight", "baron", "count", "palsgrave",
"margrave", "landgrave", "ruler", "elector", "imperial-prince",
"duke", "grand-duke", "prince-regent", "king"
],
jobs: ["mayor"]
}
},
{
officeTr: "village-major",
prerequisite: {
titles: [
"by", "landlord", "knight", "baron", "count", "palsgrave",
"margrave", "landgrave", "ruler", "elector", "imperial-prince",
"duke", "grand-duke", "prince-regent", "king"
],
jobs: ["master-builder"]
}
},
{
officeTr: "judge",
prerequisite: {
titles: [
"landlord", "knight", "baron", "count", "palsgrave", "margrave",
"landgrave", "ruler", "elector", "imperial-prince", "duke",
"grand-duke", "prince-regent", "king"
],
jobs: ["village-major"]
}
},
{
officeTr: "bailif",
prerequisite: {
titles: [
"landlord", "knight", "baron", "count", "palsgrave", "margrave",
"landgrave", "ruler", "elector", "imperial-prince", "duke",
"grand-duke", "prince-regent", "king"
],
jobs: ["judge"]
}
},
{
officeTr: "taxman",
prerequisite: {
titles: [
"knight", "baron", "count", "palsgrave", "margrave", "landgrave",
"ruler", "elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["bailif"]
}
},
{
officeTr: "sheriff",
prerequisite: {
titles: [
"baron", "count", "palsgrave", "margrave", "landgrave", "ruler",
"elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["taxman"]
}
},
{
officeTr: "consultant",
prerequisite: {
titles: [
"baron", "count", "palsgrave", "margrave", "landgrave", "ruler",
"elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["sheriff"]
}
},
{
officeTr: "treasurer",
prerequisite: {
titles: [
"count", "palsgrave", "margrave", "landgrave", "ruler", "elector",
"imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["consultant"]
}
},
{
officeTr: "hangman",
prerequisite: {
titles: [
"count", "palsgrave", "margrave", "landgrave", "ruler", "elector",
"imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["consultant"]
}
},
{
officeTr: "territorial-council",
prerequisite: {
titles: [
"palsgrave", "margrave", "landgrave", "ruler", "elector", "imperial-prince",
"duke", "grand-duke", "prince-regent", "king"
],
jobs: ["treasurer", "hangman"]
}
},
{
officeTr: "territorial-council-speaker",
prerequisite: {
titles: [
"margrave", "landgrave", "ruler", "elector", "imperial-prince", "duke",
"grand-duke", "prince-regent", "king"
],
jobs: ["territorial-council"]
}
},
{
officeTr: "ruler-consultant",
prerequisite: {
titles: [
"landgrave", "ruler", "elector", "imperial-prince", "duke", "grand-duke",
"prince-regent", "king"
],
jobs: ["territorial-council-speaker"]
}
},
{
officeTr: "state-administrator",
prerequisite: {
titles: [
"ruler", "elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["ruler-consultant"]
}
},
{
officeTr: "super-state-administrator",
prerequisite: {
titles: [
"elector", "imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["state-administrator"]
}
},
{
officeTr: "governor",
prerequisite: {
titles: [
"imperial-prince", "duke", "grand-duke", "prince-regent", "king"
],
jobs: ["super-state-administrator"]
}
},
{
officeTr: "ministry-helper",
prerequisite: {
titles: [
"grand-duke", "prince-regent", "king"
],
jobs: ["governor"]
}
},
{
officeTr: "minister",
prerequisite: {
titles: [
"prince-regent", "king"
],
jobs: ["ministry-helper"]
}
},
{
officeTr: "chancellor",
prerequisite: {
titles: [
"prince-regent", "king"
],
jobs: ["minister"]
}
}
];
{
const giftNames = promotionalGifts.map(g => g.name);
const traitNames = characterTraits.map(t => t.name);
@@ -330,7 +611,8 @@ export const initializeFalukantRegions = async () => {
where: { name: region.labelTr },
defaults: {
regionTypeId: regionType.id,
parentId: parentRegion?.id || null
parentId: parentRegion?.id || null,
map: parentRegion?.map || {},
}
});
}
@@ -478,4 +760,37 @@ export const initializeLearnerTypes = async () => {
}
});
}
}
}
export const initializePoliticalOfficeTypes = async () => {
for (const po of politicalOffices) {
await PoliticalOfficeType.findOrCreate({
where: { name: po.tr },
defaults: {
seatsPerRegion: po.seatsPerRegion,
regionType: po.regionType,
termLength: po.termLength
}
});
}
};
export const initializePoliticalOfficePrerequisites = async () => {
for (const prereq of politicalOfficePrerequisites) {
// zunächst den OfficeType anhand seines Namens (tr) ermitteln
const office = await PoliticalOfficeType.findOne({
where: { name: prereq.officeTr }
});
if (!office) continue;
// Nun findOrCreate mit dem neuen Spaltennamen:
await PoliticalOfficePrerequisite.findOrCreate({
where: { office_type_id: office.id },
defaults: {
office_type_id: office.id,
prerequisite: prereq.prerequisite
}
});
}
};