diff --git a/package.json b/package.json index 9bd14f5..a547d85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aurora-electrons", - "version": "0.8.6", + "version": "0.8.8", "description": "Aurora Electrons", "repository": "https://github.com/rubybrowncoat/Aurora-Electrons", "main": "./dist/main/index.js", diff --git a/src/renderer/pages/warnings.vue b/src/renderer/pages/warnings.vue index def596b..f1fbbf9 100644 --- a/src/renderer/pages/warnings.vue +++ b/src/renderer/pages/warnings.vue @@ -4,7 +4,43 @@
- + + + Contacts + + + + + + Intruders detected in {{ intruders.length }} systems + + + + + + + {{ intruder.System.RaceSystemSurveys[0].Name }} —  + + + + + + + + {{ group.Race.AlienRaces[0].AlienRaceName }} — {{ Object.entries(group.Types).filter(([, contacts]) => contacts.length).map(([type, contacts]) => `${contacts.length} ${type}s`).join(', ') }} Hostile + + + + + + + + + + + + + Economy @@ -468,7 +504,8 @@ {{ construct.SystemBody.System.RaceSystemSurveys[0].Name }} — {{ modelSystemBodyName(construct.SystemBody) }} - {{ roundToDecimal((construct.ResearchBonus - 1) * 100) }}% {{ construct.ResearchField.FieldName }} + {{ roundToDecimal((construct.ResearchBonus - 1) * 100) }}% {{ construct.ResearchField.FieldName }} + Dormant Lacking 10 million population on the body No population on the body @@ -524,6 +561,8 @@ import _partition from 'lodash/partition' import { separatedNumber, roundToDecimal } from '../../utilities/math' import { systemBodyName, modelSystemBodyName, populationName } from '../../utilities/aurora' +import { Op } from 'sequelize' + const secondsPerTwoWeeks = 1209600 const secondsPerYear = 31536000 @@ -552,6 +591,8 @@ export default { modelSystemBodyName, populationName, + _partition, + levelColor(morale) { if (morale > 0.85) { return 'green' @@ -578,6 +619,24 @@ export default { return `${days > 0 && `${days}d `}${hours && `${hours}m `}${minutes && `${minutes}m `}${remainingSeconds && `${remainingSeconds}s`}` || 'Expired' }, + + intruderTotals(intruder) { + return Object.entries(intruder.Totals).filter(([, contacts]) => contacts.length).map(([type, contacts]) => { + const [hostiles, neutrals] = _partition(contacts, contact => contact.ContactRace.AlienRaces[0].ContactStatus === 0) + + const out = [] + + if (hostiles.length) { + out.push(`${hostiles.length} Hostile ${type}s`) + } + + if (neutrals.length) { + out.push(`${neutrals.length} ${type}s`) + } + + return out.join(', ') + }).join(', ') + }, }, computed: { ...mapGetters([ @@ -822,7 +881,7 @@ export default { return [] } - const populations = await this.database.query(`select VIR_ConstructionPopulation.*, 100 - SUM(FCT_IndustrialProjects.Percentage) as FreePercentage from (select FCT_Population.PopulationID, FCT_Population.PopName, SUM(FCT_PopulationInstallations.Amount) as ConstructionAmount, FCT_RaceSysSurvey.Name as SystemName, FCT_SystemBody.SystemBodyID, FCT_SystemBody.PlanetNumber, FCT_SystemBody.OrbitNumber, FCT_SystemBody.BodyClass, FCT_SystemBodyName.Name as SystemBodyName, FCT_Star.Component from FCT_Population inner join FCT_PopulationInstallations on FCT_Population.PopulationID = FCT_PopulationInstallations.PopID left join DIM_PlanetaryInstallation ON FCT_PopulationInstallations.PlanetaryInstallationID = DIM_PlanetaryInstallation.PlanetaryInstallationID left join FCT_SystemBody on FCT_Population.SystemBodyID = FCT_SystemBody.SystemBodyID left join FCT_SystemBodyName on FCT_SystemBody.SystemBodyID = FCT_SystemBodyName.SystemBodyID and FCT_Population.RaceID = FCT_SystemBodyName.RaceID left join FCT_RaceSysSurvey on FCT_Population.SystemID = FCT_RaceSysSurvey.SystemID and FCT_Population.RaceID = FCT_RaceSysSurvey.RaceID left join FCT_Star on FCT_SystemBody.StarID = FCT_Star.StarID where FCT_Population.GameID = ${this.GameID} and FCT_Population.RaceID = ${this.RaceID} and DIM_PlanetaryInstallation.ConstructionValue > 0 GROUP BY FCT_Population.PopulationID) as VIR_ConstructionPopulation left join FCT_IndustrialProjects on VIR_ConstructionPopulation.PopulationID = FCT_IndustrialProjects.PopulationID and FCT_IndustrialProjects.Queue = 0 and FCT_IndustrialProjects.ProductionType IN (0,3,4) group by FCT_IndustrialProjects.PopulationID having SUM(FCT_IndustrialProjects.Percentage) < 100`).then(([ items ]) => { + const populations = await this.database.query(`select VIR_ConstructionPopulation.*, 100 - COALESCE(SUM(FCT_IndustrialProjects.Percentage), 0) as FreePercentage from (select FCT_Population.PopulationID, FCT_Population.PopName, SUM(FCT_PopulationInstallations.Amount) as ConstructionAmount, FCT_RaceSysSurvey.Name as SystemName, FCT_SystemBody.SystemBodyID, FCT_SystemBody.PlanetNumber, FCT_SystemBody.OrbitNumber, FCT_SystemBody.BodyClass, FCT_SystemBodyName.Name as SystemBodyName, FCT_Star.Component from FCT_Population inner join FCT_PopulationInstallations on FCT_Population.PopulationID = FCT_PopulationInstallations.PopID left join DIM_PlanetaryInstallation ON FCT_PopulationInstallations.PlanetaryInstallationID = DIM_PlanetaryInstallation.PlanetaryInstallationID left join FCT_SystemBody on FCT_Population.SystemBodyID = FCT_SystemBody.SystemBodyID left join FCT_SystemBodyName on FCT_SystemBody.SystemBodyID = FCT_SystemBodyName.SystemBodyID and FCT_Population.RaceID = FCT_SystemBodyName.RaceID left join FCT_RaceSysSurvey on FCT_Population.SystemID = FCT_RaceSysSurvey.SystemID and FCT_Population.RaceID = FCT_RaceSysSurvey.RaceID left join FCT_Star on FCT_SystemBody.StarID = FCT_Star.StarID where FCT_Population.GameID = ${this.GameID} and FCT_Population.RaceID = ${this.RaceID} and DIM_PlanetaryInstallation.ConstructionValue > 0 GROUP BY FCT_Population.PopulationID) as VIR_ConstructionPopulation left join FCT_IndustrialProjects on VIR_ConstructionPopulation.PopulationID = FCT_IndustrialProjects.PopulationID and FCT_IndustrialProjects.Queue = 0 and FCT_IndustrialProjects.ProductionType IN (0,3,4) group by FCT_IndustrialProjects.PopulationID having FreePercentage > 0`).then(([ items ]) => { console.log('Free Construction Capacity', items) return items.filter(item => item.FreePercentage > 0.00006) @@ -838,7 +897,7 @@ export default { return [] } - const populations = await this.database.query(`select VIR_OrdnanceProductionPopulation.*, 100 - SUM(FCT_IndustrialProjects.Percentage) as FreePercentage from (select FCT_Population.PopulationID, FCT_Population.PopName, SUM(FCT_PopulationInstallations.Amount) as OrdnanceProductionAmount, FCT_RaceSysSurvey.Name as SystemName, FCT_SystemBody.SystemBodyID, FCT_SystemBody.PlanetNumber, FCT_SystemBody.OrbitNumber, FCT_SystemBody.BodyClass, FCT_SystemBodyName.Name as SystemBodyName, FCT_Star.Component from FCT_Population join FCT_PopulationInstallations on FCT_Population.PopulationID = FCT_PopulationInstallations.PopID left join DIM_PlanetaryInstallation ON FCT_PopulationInstallations.PlanetaryInstallationID = DIM_PlanetaryInstallation.PlanetaryInstallationID left join FCT_SystemBody on FCT_Population.SystemBodyID = FCT_SystemBody.SystemBodyID left join FCT_SystemBodyName on FCT_SystemBody.SystemBodyID = FCT_SystemBodyName.SystemBodyID and FCT_Population.RaceID = FCT_SystemBodyName.RaceID left join FCT_RaceSysSurvey on FCT_Population.SystemID = FCT_RaceSysSurvey.SystemID and FCT_Population.RaceID = FCT_RaceSysSurvey.RaceID left join FCT_Star on FCT_SystemBody.StarID = FCT_Star.StarID where FCT_Population.GameID = ${this.GameID} and FCT_Population.RaceID = ${this.RaceID} and DIM_PlanetaryInstallation.OrdnanceProductionValue > 0 GROUP BY FCT_Population.PopulationID) as VIR_OrdnanceProductionPopulation left join FCT_IndustrialProjects on VIR_OrdnanceProductionPopulation.PopulationID = FCT_IndustrialProjects.PopulationID and FCT_IndustrialProjects.Queue = 0 and FCT_IndustrialProjects.ProductionType = 1 group by VIR_OrdnanceProductionPopulation.PopulationID having SUM(FCT_IndustrialProjects.Percentage) < 100`).then(([ items ]) => { + const populations = await this.database.query(`select VIR_OrdnanceProductionPopulation.*, 100 - COALESCE(SUM(FCT_IndustrialProjects.Percentage), 0) as FreePercentage from (select FCT_Population.PopulationID, FCT_Population.PopName, SUM(FCT_PopulationInstallations.Amount) as OrdnanceProductionAmount, FCT_RaceSysSurvey.Name as SystemName, FCT_SystemBody.SystemBodyID, FCT_SystemBody.PlanetNumber, FCT_SystemBody.OrbitNumber, FCT_SystemBody.BodyClass, FCT_SystemBodyName.Name as SystemBodyName, FCT_Star.Component from FCT_Population join FCT_PopulationInstallations on FCT_Population.PopulationID = FCT_PopulationInstallations.PopID left join DIM_PlanetaryInstallation ON FCT_PopulationInstallations.PlanetaryInstallationID = DIM_PlanetaryInstallation.PlanetaryInstallationID left join FCT_SystemBody on FCT_Population.SystemBodyID = FCT_SystemBody.SystemBodyID left join FCT_SystemBodyName on FCT_SystemBody.SystemBodyID = FCT_SystemBodyName.SystemBodyID and FCT_Population.RaceID = FCT_SystemBodyName.RaceID left join FCT_RaceSysSurvey on FCT_Population.SystemID = FCT_RaceSysSurvey.SystemID and FCT_Population.RaceID = FCT_RaceSysSurvey.RaceID left join FCT_Star on FCT_SystemBody.StarID = FCT_Star.StarID where FCT_Population.GameID = ${this.GameID} and FCT_Population.RaceID = ${this.RaceID} and DIM_PlanetaryInstallation.OrdnanceProductionValue > 0 GROUP BY FCT_Population.PopulationID) as VIR_OrdnanceProductionPopulation left join FCT_IndustrialProjects on VIR_OrdnanceProductionPopulation.PopulationID = FCT_IndustrialProjects.PopulationID and FCT_IndustrialProjects.Queue = 0 and FCT_IndustrialProjects.ProductionType = 1 group by VIR_OrdnanceProductionPopulation.PopulationID having FreePercentage > 0`).then(([ items ]) => { console.log('Free Ordnance Production Capacity', items) return items @@ -854,7 +913,7 @@ export default { return [] } - const populations = await this.database.query(`select VIR_OrdnanceProductionPopulation.*, 100 - SUM(FCT_IndustrialProjects.Percentage) as FreePercentage from (select FCT_Population.PopulationID, FCT_Population.PopName, SUM(FCT_PopulationInstallations.Amount) as FighterProductionAmount, FCT_RaceSysSurvey.Name as SystemName, FCT_SystemBody.SystemBodyID, FCT_SystemBody.PlanetNumber, FCT_SystemBody.OrbitNumber, FCT_SystemBody.BodyClass, FCT_SystemBodyName.Name as SystemBodyName, FCT_Star.Component from FCT_Population join FCT_PopulationInstallations on FCT_Population.PopulationID = FCT_PopulationInstallations.PopID left join DIM_PlanetaryInstallation ON FCT_PopulationInstallations.PlanetaryInstallationID = DIM_PlanetaryInstallation.PlanetaryInstallationID left join FCT_SystemBody on FCT_Population.SystemBodyID = FCT_SystemBody.SystemBodyID left join FCT_SystemBodyName on FCT_SystemBody.SystemBodyID = FCT_SystemBodyName.SystemBodyID and FCT_Population.RaceID = FCT_SystemBodyName.RaceID left join FCT_RaceSysSurvey on FCT_Population.SystemID = FCT_RaceSysSurvey.SystemID and FCT_Population.RaceID = FCT_RaceSysSurvey.RaceID left join FCT_Star on FCT_SystemBody.StarID = FCT_Star.StarID where FCT_Population.GameID = ${this.GameID} and FCT_Population.RaceID = ${this.RaceID} and DIM_PlanetaryInstallation.FighterProductionValue > 0 GROUP BY FCT_Population.PopulationID) as VIR_OrdnanceProductionPopulation left join FCT_IndustrialProjects on VIR_OrdnanceProductionPopulation.PopulationID = FCT_IndustrialProjects.PopulationID and FCT_IndustrialProjects.Queue = 0 and FCT_IndustrialProjects.ProductionType = 2 group by VIR_OrdnanceProductionPopulation.PopulationID having SUM(FCT_IndustrialProjects.Percentage) < 100`).then(([ items ]) => { + const populations = await this.database.query(`select VIR_OrdnanceProductionPopulation.*, 100 - COALESCE(SUM(FCT_IndustrialProjects.Percentage), 0) as FreePercentage from (select FCT_Population.PopulationID, FCT_Population.PopName, SUM(FCT_PopulationInstallations.Amount) as FighterProductionAmount, FCT_RaceSysSurvey.Name as SystemName, FCT_SystemBody.SystemBodyID, FCT_SystemBody.PlanetNumber, FCT_SystemBody.OrbitNumber, FCT_SystemBody.BodyClass, FCT_SystemBodyName.Name as SystemBodyName, FCT_Star.Component from FCT_Population join FCT_PopulationInstallations on FCT_Population.PopulationID = FCT_PopulationInstallations.PopID left join DIM_PlanetaryInstallation ON FCT_PopulationInstallations.PlanetaryInstallationID = DIM_PlanetaryInstallation.PlanetaryInstallationID left join FCT_SystemBody on FCT_Population.SystemBodyID = FCT_SystemBody.SystemBodyID left join FCT_SystemBodyName on FCT_SystemBody.SystemBodyID = FCT_SystemBodyName.SystemBodyID and FCT_Population.RaceID = FCT_SystemBodyName.RaceID left join FCT_RaceSysSurvey on FCT_Population.SystemID = FCT_RaceSysSurvey.SystemID and FCT_Population.RaceID = FCT_RaceSysSurvey.RaceID left join FCT_Star on FCT_SystemBody.StarID = FCT_Star.StarID where FCT_Population.GameID = ${this.GameID} and FCT_Population.RaceID = ${this.RaceID} and DIM_PlanetaryInstallation.FighterProductionValue > 0 GROUP BY FCT_Population.PopulationID) as VIR_OrdnanceProductionPopulation left join FCT_IndustrialProjects on VIR_OrdnanceProductionPopulation.PopulationID = FCT_IndustrialProjects.PopulationID and FCT_IndustrialProjects.Queue = 0 and FCT_IndustrialProjects.ProductionType = 2 group by VIR_OrdnanceProductionPopulation.PopulationID having FreePercentage > 0`).then(([ items ]) => { console.log('Free Fighter Production Capacity', items) return items @@ -1077,7 +1136,7 @@ export default { construct.AlienPopulations = construct.SystemBody.Populations.filter(population => population.RaceID !== this.RaceID) return construct - }).filter(construct => !construct.OwnPopulations.length || !construct.OwnPopulations.filter(population => population.Population > 10).length) + }).filter(construct => !construct.Active || !construct.OwnPopulations.length || !construct.OwnPopulations.filter(population => population.Population > 10).length) }) return constructs @@ -1161,6 +1220,110 @@ export default { }, default: [], }, + intruders: { + async get() { + if (!this.database || !this.GameID) { + return [] + } + + const contacts = await this.database.models.Contact.findAll({ + where: { + GameID: this.GameID, + DetectRaceID: this.RaceID, + + ContactType: { + [Op.in]: [1, 3, 4, 12, 14, 16] + } + }, + + group: 'ContactID', + order: [['LastUpdate', 'DESC']], + + include: [{ + required: true, + model: this.database.models.System, + include: [{ + required: true, + model: this.database.models.RaceSystemSurvey, + where: { + RaceID: this.RaceID, + }, + }], + }, { + required: true, + model: this.database.models.Race, + as: 'ContactRace', + + where: { + RaceID: { + [Op.ne]: this.RaceID + }, + }, + + include: [{ + model: this.database.models.AlienRace, + + where: { + ViewRaceID: this.RaceID, + }, + }], + }, { + required: false, + model: this.database.models.Population, + }] + }).then((items) => { + console.log('Intruder Contacts', items) + + const typeMap = { + 0: 'Other', + 1: 'Ship', + 3: 'Salvo', + 4: 'Population', + 12: 'GroundUnit', + 14: 'GroundUnit', + 16: 'Shipyard', + } + + return Object.values(items.reduce((aggregate, contact) => { + if (!contact.ContactRace.AlienRaces.length) { + console.log('!!! NO ALIEN RACE', contact) + + return aggregate + } + + if ([2, 3].includes(contact.ContactRace.AlienRaces[0].ContactStatus)) { + return aggregate + } + + + if (!aggregate[contact.SystemID]) { + aggregate[contact.SystemID] = { + System: contact.System, + + Contacts: {}, + Totals: Object.fromEntries(Object.values(typeMap).map(type => [type, []])), + } + } + + if (!aggregate[contact.SystemID].Contacts[contact.ContactRaceID]) { + aggregate[contact.SystemID].Contacts[contact.ContactRaceID] = { + Race: contact.ContactRace, + + Types: Object.fromEntries(Object.values(typeMap).map(type => [type, []])), + } + } + + aggregate[contact.SystemID].Contacts[contact.ContactRaceID].Types[typeMap[contact.ContactType] || 'Other'].push(contact) + aggregate[contact.SystemID].Totals[typeMap[contact.ContactType] || 'Other'].push(contact) + + return aggregate + }, {})) + }) + + return contacts + }, + default: [], + }, }, } diff --git a/src/utilities/database.js b/src/utilities/database.js index c189e94..0959e11 100644 --- a/src/utilities/database.js +++ b/src/utilities/database.js @@ -58,6 +58,46 @@ export const resetDatabase = (storagePath) => { timestamps: false, }) + class AlienRace extends Model {} + AlienRace.init({ + AlienRaceID: { + type: Sequelize.INTEGER, + primaryKey: true, + }, + ViewRaceID: { + type: Sequelize.INTEGER, + primaryKey: true, + }, + + GameID: Sequelize.INTEGER, + + AlienRaceName: Sequelize.TEXT, + Abbrev: Sequelize.TEXT, + + FixedRelationship: Sequelize.INTEGER, + ContactStatus: Sequelize.INTEGER, + CommStatus: Sequelize.INTEGER, + CommModifier: Sequelize.DOUBLE, + TradeTreaty: Sequelize.BOOLEAN, + TechTreaty: Sequelize.BOOLEAN, + GeoTreaty: Sequelize.BOOLEAN, + GravTreaty: Sequelize.BOOLEAN, + + ClassThemeID: Sequelize.INTEGER, + RealClassNames: Sequelize.INTEGER, + + DiplomaticPoints: Sequelize.DOUBLE, + AlienRaceIntelligencePoints: Sequelize.DOUBLE, + + FirstDetected: Sequelize.DOUBLE, + CommEstablished: Sequelize.DOUBLE, + }, { + sequelize, + modelName: 'AlienRace', + tableName: 'FCT_AlienRace', + timestamps: false, + }) + class TechSystem extends Model {} TechSystem.init({ // INCOMPLETE TechSystemID: { @@ -546,6 +586,49 @@ export const resetDatabase = (storagePath) => { }) AetherRift.removeAttribute('id') + class Contact extends Model {} + Contact.init({ + UniqueID: { + type: Sequelize.INTEGER, + primaryKey: true, + }, + + ContactID: Sequelize.INTEGER, + + GameID: Sequelize.INTEGER, + SystemID: Sequelize.INTEGER, + + DetectRaceID: Sequelize.INTEGER, + ContactRaceID: Sequelize.INTEGER, + + ContactName: Sequelize.TEXT, + ContactMethod: Sequelize.INTEGER, + ContactType: Sequelize.INTEGER, + ContactStrength: Sequelize.DOUBLE, + ContactNumber: Sequelize.INTEGER, + Resolution: Sequelize.INTEGER, + Speed: Sequelize.INTEGER, + + CreationTime: Sequelize.DOUBLE, + Reestablished: Sequelize.DOUBLE, + LastUpdate: Sequelize.DOUBLE, + ContinualContactTime: Sequelize.INTEGER, + + Xcor: Sequelize.DOUBLE, + Ycor: Sequelize.DOUBLE, + LastXcor: Sequelize.DOUBLE, + LastYcor: Sequelize.DOUBLE, + IncrementStartX: Sequelize.DOUBLE, + IncrementStartY: Sequelize.DOUBLE, + + Msg: Sequelize.BOOLEAN, + }, { + sequelize, + modelName: 'Contact', + tableName: 'FCT_Contacts', + timestamps: false, + }) + // Relations Game.hasMany(Race, { foreignKey: 'GameID', sourceKey: 'GameID' }) @@ -559,12 +642,20 @@ export const resetDatabase = (storagePath) => { Race.hasMany(SystemBodySurvey, { foreignKey: 'RaceID', sourceKey: 'RaceID' }) Race.hasMany(Fleet, { foreignKey: 'RaceID' }) Race.hasMany(GroundUnitFormation, { foreignKey: 'RaceID' }) + Race.hasMany(AlienRace, { foreignKey: 'AlienRaceID' }) + + AlienRace.belongsTo(Game, { foreignKey: 'GameID' }) + AlienRace.belongsTo(Race, { foreignKey: 'AlienRaceID' }) + AlienRace.belongsTo(Race, { foreignKey: 'ViewRaceID', as: 'ViewRace' }) Population.belongsTo(Race, { foreignKey: 'RaceID', sourceKey: 'RaceID' }) Population.belongsTo(System, { foreignKey: 'SystemID', sourceKey: 'SystemID' }) Population.belongsTo(SystemBody, { foreignKey: 'SystemBodyID', sourceKey: 'SystemBodyID' }) Population.hasMany(PopulationInstallation, { foreignKey: 'PopID' }) Population.hasMany(GroundUnitFormation, { foreignKey: 'PopulationID' }) + Population.hasMany(Contact, { foreignKey: 'ContactID', scope: { + ContactType: 4, + }}) PopulationInstallation.belongsTo(Population, { foreignKey: 'PopID' }) PopulationInstallation.belongsTo(PlanetaryInstallation, { foreignKey: 'PlanetaryInstallationID', sourceKey: 'PlanetaryInstallationID' }) @@ -605,6 +696,8 @@ export const resetDatabase = (storagePath) => { GroundUnitFormation.belongsTo(Population, { foreignKey: 'PopulationID' }) GroundUnitFormation.belongsTo(Race, { foreignKey: 'RaceID' }) + ResearchField.hasMany(AncientConstruct, { foreignKey: 'ResearchFieldID', sourceKey: 'ResearchFieldID' }) + AncientConstruct.belongsTo(Game, { foreignKey: 'GameID', sourceKey: 'GameID' }) AncientConstruct.belongsTo(SystemBody, { foreignKey: 'SystemBodyID', sourceKey: 'SystemBodyID' }) AncientConstruct.belongsTo(ResearchField, { foreignKey: 'ResearchFieldID', sourceKey: 'ResearchFieldID' }) @@ -612,7 +705,28 @@ export const resetDatabase = (storagePath) => { AetherRift.belongsTo(Game, { foreignKey: 'GameID', sourceKey: 'GameID' }) AetherRift.belongsTo(System, { foreignKey: 'SystemID', sourceKey: 'SystemID' }) - ResearchField.hasMany(AncientConstruct, { foreignKey: 'ResearchFieldID', sourceKey: 'ResearchFieldID' }) + Contact.belongsTo(Game, { foreignKey: 'GameID' }) + Contact.belongsTo(System, { foreignKey: 'SystemID' }) + Contact.belongsTo(Race, { foreignKey: 'DetectRaceID', as: 'DetectRace' }) + Contact.belongsTo(Race, { foreignKey: 'ContactRaceID', as: 'ContactRace' }) + + Contact.belongsTo(Population, { foreignKey: 'ContactID' }) + Contact.addHook('afterFind', results => { + console.log('makeContactVirtualProperty', results.length) + + if (!Array.isArray(results)) { + results = [results] + } + + for (const instance of results) { + if (instance.ContactType === 4 && instance.Population !== undefined) { + instance.Contact = instance.Population + } + + delete instance.Population + delete instance.dataValues.Population + } + }, 'makeContactVirtualProperty') return sequelize }