From ca33577bb6fe2d2d3985f24106edaa9f620486e6 Mon Sep 17 00:00:00 2001 From: Matt Cavanagh Date: Fri, 2 Sep 2022 01:59:27 +0100 Subject: [PATCH 1/3] Support team ID in population data --- package.json | 2 +- src/brokers/CharacterBroker.ts | 6 +++++- src/data/Character.ts | 10 +++++++++- src/handlers/CharacterPresenceHandler.ts | 2 +- src/ps2alerts-constants | 2 +- yarn.lock | 8 ++++---- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index ded5e48c..d1af7190 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "logform": "^2.4.2", "moment": "^2.29.4", "moment-timezone": "^0.5.33", - "ps2census": "^4.3.0", + "ps2census": "^4.4.1", "reflect-metadata": "^0.1.13", "utf-8-validate": "^5.0.8", "winston": "^3.8.1", diff --git a/src/brokers/CharacterBroker.ts b/src/brokers/CharacterBroker.ts index d08b46bf..ad928c34 100644 --- a/src/brokers/CharacterBroker.ts +++ b/src/brokers/CharacterBroker.ts @@ -33,12 +33,16 @@ export default class CharacterBroker { throw new Error('AttackerEvent had no actual attacker character ID! ps2census bug'); } + // Re-create character with teamID supplied + character = new Character(await payload.character(), parseInt(payload.team_id, 10)); + const attackerCharacter = await payload.attacker(); if (!attackerCharacter) { CharacterBroker.logger.warn('AttackerEvent returned no attacker!'); } else { - attacker = new Character(attackerCharacter); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + attacker = new Character(attackerCharacter, parseInt(payload.attacker_team_id, 10)); } } diff --git a/src/data/Character.ts b/src/data/Character.ts index 2f44be4a..ff1aca0c 100644 --- a/src/data/Character.ts +++ b/src/data/Character.ts @@ -10,13 +10,14 @@ class Character implements CharacterInterface { public id: string; public name: string; public faction: Faction; + public teamId: Faction; public world: World; public battleRank: number; public asp: number; public adjustedBattleRank: number; public outfit: Outfit | null; - constructor(characterData: CharacterWorldOutfitLeader) { + constructor(characterData: CharacterWorldOutfitLeader, teamId: Faction | null = null) { this.id = characterData.character_id; this.name = characterData.name.first; this.faction = parseInt(characterData.faction_id, 10); @@ -45,6 +46,13 @@ class Character implements CharacterInterface { } else { this.outfit = new FakeOutfitFactory(this.faction).build(); } + + // If we're injecting the teamId from a death / other event, add it now + if (teamId) { + this.teamId = teamId; + } else { + this.teamId = this.faction; + } } } diff --git a/src/handlers/CharacterPresenceHandler.ts b/src/handlers/CharacterPresenceHandler.ts index b6d4496c..7b73434b 100644 --- a/src/handlers/CharacterPresenceHandler.ts +++ b/src/handlers/CharacterPresenceHandler.ts @@ -34,7 +34,7 @@ export default class CharacterPresenceHandler implements CharacterPresenceHandle await this.cacheClient.setex(`CharacterPresence-${character.id}`, 60 * 5, zone); // Add character to overall redis set to be scanned later split by world and faction - const listName = `CharacterPresencePops-${instance.world}-${character.faction}`; + const listName = `CharacterPresencePops-${instance.world}-${character.teamId}`; await this.cacheClient.sadd(listName, character.id); // Add list to global list, so they can all be cleared up upon start of aggregator diff --git a/src/ps2alerts-constants b/src/ps2alerts-constants index 11240092..4d47c98e 160000 --- a/src/ps2alerts-constants +++ b/src/ps2alerts-constants @@ -1 +1 @@ -Subproject commit 112400922a9f5381f900c35c9fb82160eccd1fd2 +Subproject commit 4d47c98e5e47be9bebfa3237e89dbf5fff9624a2 diff --git a/yarn.lock b/yarn.lock index 8fb3da41..5ae5b54b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1888,10 +1888,10 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -ps2census@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ps2census/-/ps2census-4.3.0.tgz#42757e6a639427b3f340d46fe3bef646cfe4b828" - integrity sha512-7HN9YXs5XANsqpZJX4z9tI828x6m+PCA6WXDSncMYQkwqPFMpX3a1ukvdmmTSfoMv753SdJmApLFciaTBXcXpA== +ps2census@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/ps2census/-/ps2census-4.4.1.tgz#54165a901d754b58cfa23925c1bab98feafaa2d7" + integrity sha512-3SPnzZALX+K9VlymMpssyOUmI69X/EOKWTkIJ2CKFcrMz3vhLiB2OW4vN5OFcBVkEe80iksN1buBGq57H6QBcQ== dependencies: axios "0.27.2" eventemitter3 "4.0.7" From a9cc1a5aa84440664b2b45245ea82ba29dbaa6a3 Mon Sep 17 00:00:00 2001 From: Matt Cavanagh Date: Fri, 2 Sep 2022 02:02:13 +0100 Subject: [PATCH 2/3] Removed undetermined kill type --- src/logics/VehicleDestroyLogic.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logics/VehicleDestroyLogic.ts b/src/logics/VehicleDestroyLogic.ts index 105fafa1..01beb0c5 100644 --- a/src/logics/VehicleDestroyLogic.ts +++ b/src/logics/VehicleDestroyLogic.ts @@ -18,7 +18,7 @@ export default class VehicleDestroyLogic implements LogicInterface { // IvV if (!this.event.attackerVehicleId) { - if (this.event.killType === Destroy.Normal || this.event.killType === Destroy.Undetermined) { + if (this.event.killType === Destroy.Normal) { VehicleDestroyLogic.logger.silly(`[${this.mode}] IvV death`); victimDocs.push({$inc: {['infantry.deaths']: 1}}); } else if (this.event.attackerCharacter.faction === this.event.character.faction) { @@ -30,7 +30,7 @@ export default class VehicleDestroyLogic implements LogicInterface { // VvV if (this.event.attackerVehicleId) { // Non TKs - if (this.event.killType === Destroy.Normal || this.event.killType === Destroy.Undetermined) { + if (this.event.killType === Destroy.Normal) { // Kill - VvV VehicleDestroyLogic.logger.silly(`[${this.mode}] VvV`); attackerDocs.push({$inc: {['vehicles.kills']: 1}}); From f5839fa482244b5b74fcb8b13ee3a9b7e501f300 Mon Sep 17 00:00:00 2001 From: Matt Cavanagh Date: Fri, 2 Sep 2022 02:42:45 +0100 Subject: [PATCH 3/3] Migrated all combat logic to use proper kill types using team id. Closes #600. --- .../aggregate/global/GlobalCharacterAggregate.ts | 9 +++------ .../aggregate/global/GlobalFactionCombatAggregate.ts | 9 +++------ src/handlers/aggregate/global/GlobalLoadoutAggregate.ts | 9 +++------ src/handlers/aggregate/global/GlobalOutfitAggregate.ts | 8 ++------ src/handlers/aggregate/global/GlobalWeaponAggregate.ts | 9 +++------ .../aggregate/instance/InstanceCharacterAggregate.ts | 8 ++------ .../aggregate/instance/InstanceFactionCombatAggregate.ts | 9 +++------ .../aggregate/instance/InstanceLoadoutAggregate.ts | 9 +++------ .../aggregate/instance/InstanceOutfitAggregate.ts | 9 +++------ .../aggregate/instance/InstanceWeaponAggregate.ts | 9 +++------ src/logics/VehicleCharacterDeathLogic.ts | 3 ++- src/logics/VehicleDestroyLogic.ts | 2 +- 12 files changed, 31 insertions(+), 62 deletions(-) diff --git a/src/handlers/aggregate/global/GlobalCharacterAggregate.ts b/src/handlers/aggregate/global/GlobalCharacterAggregate.ts index 58c5f6b4..92598f31 100644 --- a/src/handlers/aggregate/global/GlobalCharacterAggregate.ts +++ b/src/handlers/aggregate/global/GlobalCharacterAggregate.ts @@ -67,6 +67,9 @@ export default class GlobalCharacterAggregate implements AggregateHandlerInterfa if (event.killType === Kill.Normal) { attackerDocs.push({$inc: {kills: 1}}); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + attackerDocs.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -83,12 +86,6 @@ export default class GlobalCharacterAggregate implements AggregateHandlerInterfa attackerDocs.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - attackerDocs.push({$inc: {[factionKey]: 1}}); - } - if (event.attackerCharacter && attackerDocs.length > 0) { try { if (event.instance.ps2AlertsEventType === Ps2AlertsEventType.LIVE_METAGAME) { diff --git a/src/handlers/aggregate/global/GlobalFactionCombatAggregate.ts b/src/handlers/aggregate/global/GlobalFactionCombatAggregate.ts index 0dcc31d2..bd056ce2 100644 --- a/src/handlers/aggregate/global/GlobalFactionCombatAggregate.ts +++ b/src/handlers/aggregate/global/GlobalFactionCombatAggregate.ts @@ -40,6 +40,9 @@ export default class GlobalFactionCombatAggregate implements AggregateHandlerInt {$inc: {[attackerKillKey]: 1}}, {$inc: {['totals.kills']: 1}}, ); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + documents.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -59,12 +62,6 @@ export default class GlobalFactionCombatAggregate implements AggregateHandlerInt {$inc: {['totals.headshots']: 1}}, ); } - - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - documents.push({$inc: {[factionKey]: 1}}); - } } // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/restrict-template-expressions diff --git a/src/handlers/aggregate/global/GlobalLoadoutAggregate.ts b/src/handlers/aggregate/global/GlobalLoadoutAggregate.ts index c1db6027..c928b599 100644 --- a/src/handlers/aggregate/global/GlobalLoadoutAggregate.ts +++ b/src/handlers/aggregate/global/GlobalLoadoutAggregate.ts @@ -35,6 +35,9 @@ export default class GlobalLoadoutAggregate implements AggregateHandlerInterface if (event.killType === Kill.Normal) { attackerDocs.push({$inc: {kills: 1}}); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + attackerDocs.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -51,12 +54,6 @@ export default class GlobalLoadoutAggregate implements AggregateHandlerInterface attackerDocs.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - attackerDocs.push({$inc: {[factionKey]: 1}}); - } - if (attackerDocs.length > 0) { try { await this.apiMQDelayPublisher.send(new ApiMQGlobalAggregateMessage( diff --git a/src/handlers/aggregate/global/GlobalOutfitAggregate.ts b/src/handlers/aggregate/global/GlobalOutfitAggregate.ts index 86e42f30..0dc90805 100644 --- a/src/handlers/aggregate/global/GlobalOutfitAggregate.ts +++ b/src/handlers/aggregate/global/GlobalOutfitAggregate.ts @@ -70,6 +70,8 @@ export default class GlobalOutfitAggregate implements AggregateHandlerInterface< if (event.killType === Kill.Normal) { attackerDocs.push({$inc: {kills: 1}}); + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + attackerDocs.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -86,12 +88,6 @@ export default class GlobalOutfitAggregate implements AggregateHandlerInterface< attackerDocs.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - attackerDocs.push({$inc: {[factionKey]: 1}}); - } - // Purpose for this is we can aggregate stats for "outfitless" characters, e.g. TR (-3) got X kills const attackerOutfitId = event.attackerCharacter.outfit ? event.attackerCharacter.outfit.id : `-${event.attackerCharacter.faction}`; const victimOutfitId = event.character.outfit ? event.character.outfit.id : `-${event.character.faction}`; diff --git a/src/handlers/aggregate/global/GlobalWeaponAggregate.ts b/src/handlers/aggregate/global/GlobalWeaponAggregate.ts index cb774677..e59ba89e 100644 --- a/src/handlers/aggregate/global/GlobalWeaponAggregate.ts +++ b/src/handlers/aggregate/global/GlobalWeaponAggregate.ts @@ -35,6 +35,9 @@ export default class GlobalWeaponAggregate implements AggregateHandlerInterface< if (event.killType === Kill.Normal) { documents.push({$inc: {kills: 1}}); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + documents.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -49,12 +52,6 @@ export default class GlobalWeaponAggregate implements AggregateHandlerInterface< documents.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - documents.push({$inc: {[factionKey]: 1}}); - } - try { await this.apiMQDelayPublisher.send(new ApiMQGlobalAggregateMessage( MqAcceptedPatterns.GLOBAL_WEAPON_AGGREGATE, diff --git a/src/handlers/aggregate/instance/InstanceCharacterAggregate.ts b/src/handlers/aggregate/instance/InstanceCharacterAggregate.ts index 4c39c3df..ac3dc475 100644 --- a/src/handlers/aggregate/instance/InstanceCharacterAggregate.ts +++ b/src/handlers/aggregate/instance/InstanceCharacterAggregate.ts @@ -41,6 +41,8 @@ export default class InstanceCharacterAggregate implements AggregateHandlerInter if (event.killType === Kill.Normal) { attackerDocs.push({$inc: {kills: 1}}); + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + attackerDocs.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -57,12 +59,6 @@ export default class InstanceCharacterAggregate implements AggregateHandlerInter attackerDocs.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - attackerDocs.push({$inc: {[factionKey]: 1}}); - } - if (event.attackerCharacter && attackerDocs.length > 0) { try { await this.apiMQPublisher.send(new ApiMQMessage( diff --git a/src/handlers/aggregate/instance/InstanceFactionCombatAggregate.ts b/src/handlers/aggregate/instance/InstanceFactionCombatAggregate.ts index e5b58427..23edde54 100644 --- a/src/handlers/aggregate/instance/InstanceFactionCombatAggregate.ts +++ b/src/handlers/aggregate/instance/InstanceFactionCombatAggregate.ts @@ -34,6 +34,9 @@ export default class InstanceFactionCombatAggregate implements AggregateHandlerI {$inc: {[attackerKillKey]: 1}}, {$inc: {['totals.kills']: 1}}, ); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + documents.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -53,12 +56,6 @@ export default class InstanceFactionCombatAggregate implements AggregateHandlerI {$inc: {['totals.headshots']: 1}}, ); } - - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - documents.push({$inc: {[factionKey]: 1}}); - } } // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/restrict-template-expressions diff --git a/src/handlers/aggregate/instance/InstanceLoadoutAggregate.ts b/src/handlers/aggregate/instance/InstanceLoadoutAggregate.ts index edc85460..749a11e4 100644 --- a/src/handlers/aggregate/instance/InstanceLoadoutAggregate.ts +++ b/src/handlers/aggregate/instance/InstanceLoadoutAggregate.ts @@ -30,6 +30,9 @@ export default class InstanceLoadoutAggregate implements AggregateHandlerInterfa if (event.killType === Kill.Normal) { attackerDocs.push({$inc: {kills: 1}}); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + attackerDocs.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -46,12 +49,6 @@ export default class InstanceLoadoutAggregate implements AggregateHandlerInterfa attackerDocs.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - attackerDocs.push({$inc: {[factionKey]: 1}}); - } - if (event.attackerCharacter && attackerDocs.length > 0) { try { await this.apiMQPublisher.send(new ApiMQMessage( diff --git a/src/handlers/aggregate/instance/InstanceOutfitAggregate.ts b/src/handlers/aggregate/instance/InstanceOutfitAggregate.ts index bef21126..149d3b69 100644 --- a/src/handlers/aggregate/instance/InstanceOutfitAggregate.ts +++ b/src/handlers/aggregate/instance/InstanceOutfitAggregate.ts @@ -71,6 +71,9 @@ export default class InstanceOutfitAggregate implements AggregateHandlerInterfac if (event.killType === Kill.Normal) { attackerDocs.push({$inc: {kills: 1}}); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + attackerDocs.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -87,12 +90,6 @@ export default class InstanceOutfitAggregate implements AggregateHandlerInterfac attackerDocs.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - attackerDocs.push({$inc: {[factionKey]: 1}}); - } - // Purpose for this is we can aggregate stats for "outfitless" characters, e.g. TR (-3) got X kills const attackerOutfitId = event.attackerCharacter.outfit ? event.attackerCharacter.outfit.id : `-${event.attackerCharacter.faction}`; const victimOutfitId = event.character.outfit ? event.character.outfit.id : `-${event.character.faction}`; diff --git a/src/handlers/aggregate/instance/InstanceWeaponAggregate.ts b/src/handlers/aggregate/instance/InstanceWeaponAggregate.ts index 22be5a8b..e236ae72 100644 --- a/src/handlers/aggregate/instance/InstanceWeaponAggregate.ts +++ b/src/handlers/aggregate/instance/InstanceWeaponAggregate.ts @@ -31,6 +31,9 @@ export default class InstanceWeaponAggregate implements AggregateHandlerInterfac if (event.killType === Kill.Normal) { documents.push({$inc: {kills: 1}}); + + const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; + documents.push({$inc: {[factionKey]: 1}}); } if (event.killType === Kill.TeamKill) { @@ -45,12 +48,6 @@ export default class InstanceWeaponAggregate implements AggregateHandlerInterfac documents.push({$inc: {headshots: 1}}); } - // Faction vs Faction - if (event.attackerCharacter.faction !== event.character.faction) { - const factionKey = `factionKills.${attackerFactionShort}.${victimFactionShort}`; - documents.push({$inc: {[factionKey]: 1}}); - } - try { await this.apiMQPublisher.send(new ApiMQMessage( MqAcceptedPatterns.INSTANCE_WEAPON_AGGREGATE, diff --git a/src/logics/VehicleCharacterDeathLogic.ts b/src/logics/VehicleCharacterDeathLogic.ts index 7b705fba..9afc65c7 100644 --- a/src/logics/VehicleCharacterDeathLogic.ts +++ b/src/logics/VehicleCharacterDeathLogic.ts @@ -1,6 +1,7 @@ import LogicInterface from './LogicInterface'; import {getLogger} from '../logger'; import DeathEvent from '../handlers/ps2census/events/DeathEvent'; +import {Kill} from 'ps2census'; export default class VehicleCharacterDeathLogic implements LogicInterface { private static readonly logger = getLogger('VehicleCharacterDeathLogic'); @@ -25,7 +26,7 @@ export default class VehicleCharacterDeathLogic implements LogicInterface { } // If TK - if (this.event.attackerCharacter.faction === this.event.character.faction) { + if (this.event.killType === Kill.TeamKill) { if (this.event.attackerCharacter.id !== this.event.character.id) { VehicleCharacterDeathLogic.logger.silly(`[${this.mode}] VvI TK`); attackerDocs.push({$inc: {['infantry.teamkills']: 1}}); diff --git a/src/logics/VehicleDestroyLogic.ts b/src/logics/VehicleDestroyLogic.ts index 01beb0c5..ec4fd37e 100644 --- a/src/logics/VehicleDestroyLogic.ts +++ b/src/logics/VehicleDestroyLogic.ts @@ -21,7 +21,7 @@ export default class VehicleDestroyLogic implements LogicInterface { if (this.event.killType === Destroy.Normal) { VehicleDestroyLogic.logger.silly(`[${this.mode}] IvV death`); victimDocs.push({$inc: {['infantry.deaths']: 1}}); - } else if (this.event.attackerCharacter.faction === this.event.character.faction) { + } else if (this.event.killType === Destroy.Friendly) { VehicleDestroyLogic.logger.silly(`[${this.mode}] IvV TK`); victimDocs.push({$inc: {['infantry.teamkilled']: 1}}); }