LCOV - code coverage report
Current view: top level - simulation/components - Market.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 113 0.0 %
Date: 2023-04-02 12:52:40 Functions: 0 20 0.0 %

          Line data    Source code
       1             : function Market() {}
       2             : 
       3           0 : Market.prototype.Schema =
       4             :         "<element name='TradeType' a:help='Specifies the type of possible trade route (land or naval).'>" +
       5             :                 "<list>" +
       6             :                         "<oneOrMore>" +
       7             :                                 "<choice>" +
       8             :                                         "<value>land</value>" +
       9             :                                         "<value>naval</value>" +
      10             :                                 "</choice>" +
      11             :                         "</oneOrMore>" +
      12             :                 "</list>" +
      13             :         "</element>" +
      14             :         "<element name='InternationalBonus' a:help='Additional part of the gain donated when two different players trade'>" +
      15             :                 "<ref name='nonNegativeDecimal'/>" +
      16             :         "</element>";
      17             : 
      18           0 : Market.prototype.Init = function()
      19             : {
      20           0 :         this.traders = new Set();       // list of traders with a route on this market
      21           0 :         this.tradeType = new Set(this.template.TradeType.split(/\s+/));
      22             : };
      23             : 
      24           0 : Market.prototype.AddTrader = function(ent)
      25             : {
      26           0 :         this.traders.add(ent);
      27             : };
      28             : 
      29           0 : Market.prototype.RemoveTrader = function(ent)
      30             : {
      31           0 :         this.traders.delete(ent);
      32             : };
      33             : 
      34           0 : Market.prototype.GetInternationalBonus = function()
      35             : {
      36           0 :         return ApplyValueModificationsToEntity("Market/InternationalBonus", +this.template.InternationalBonus, this.entity);
      37             : };
      38             : 
      39           0 : Market.prototype.HasType = function(type)
      40             : {
      41           0 :         return this.tradeType.has(type);
      42             : };
      43             : 
      44           0 : Market.prototype.GetType = function()
      45             : {
      46           0 :         return this.tradeType;
      47             : };
      48             : 
      49           0 : Market.prototype.GetTraders = function()
      50             : {
      51           0 :         return this.traders;
      52             : };
      53             : 
      54             : /**
      55             :  * Check if the traders attached to this market can still trade with it
      56             :  * Warning: traders currently trading with a mirage of this market are dealt with in Mirage.js
      57             :  */
      58             : 
      59           0 : Market.prototype.UpdateTraders = function(onDestruction)
      60             : {
      61           0 :         for (let trader of this.traders)
      62             :         {
      63           0 :                 let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
      64           0 :                 if (!cmpTrader)
      65             :                 {
      66           0 :                         this.RemoveTrader(trader);
      67           0 :                         continue;
      68             :                 }
      69           0 :                 if (!cmpTrader.HasMarket(this.entity) || !onDestruction && cmpTrader.CanTrade(this.entity))
      70           0 :                         continue;
      71             :                 // this trader can no more trade
      72           0 :                 this.RemoveTrader(trader);
      73           0 :                 cmpTrader.RemoveMarket(this.entity);
      74             :         }
      75             : };
      76             : 
      77           0 : Market.prototype.CalculateTraderGain = function(secondMarket, traderTemplate, trader)
      78             : {
      79           0 :         let cmpMarket2 = QueryMiragedInterface(secondMarket, IID_Market);
      80           0 :         if (!cmpMarket2)
      81           0 :                 return null;
      82             : 
      83           0 :         let cmpMarket1Player = QueryOwnerInterface(this.entity);
      84           0 :         let cmpMarket2Player = QueryOwnerInterface(secondMarket);
      85           0 :         if (!cmpMarket1Player || !cmpMarket2Player)
      86           0 :                 return null;
      87             : 
      88           0 :         let cmpFirstMarketPosition = Engine.QueryInterface(this.entity, IID_Position);
      89           0 :         let cmpSecondMarketPosition = Engine.QueryInterface(secondMarket, IID_Position);
      90           0 :         if (!cmpFirstMarketPosition || !cmpFirstMarketPosition.IsInWorld() ||
      91             :            !cmpSecondMarketPosition || !cmpSecondMarketPosition.IsInWorld())
      92           0 :                 return null;
      93           0 :         let firstMarketPosition = cmpFirstMarketPosition.GetPosition2D();
      94           0 :         let secondMarketPosition = cmpSecondMarketPosition.GetPosition2D();
      95             : 
      96           0 :         let mapSize = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain).GetMapSize();
      97           0 :         let gainMultiplier = TradeGainNormalization(mapSize);
      98           0 :         if (trader)
      99             :         {
     100           0 :                 let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
     101           0 :                 if (!cmpTrader)
     102           0 :                         return null;
     103           0 :                 gainMultiplier *= cmpTrader.GetTraderGainMultiplier();
     104             :         }
     105             :         // Called from the gui, modifications already applied.
     106             :         else
     107             :         {
     108           0 :                 if (!traderTemplate || !traderTemplate.GainMultiplier)
     109           0 :                         return null;
     110           0 :                 gainMultiplier *= traderTemplate.GainMultiplier;
     111             :         }
     112             : 
     113           0 :         let gain = {};
     114             : 
     115             :         // Calculate ordinary Euclidean distance between markets.
     116             :         // We don't use pathfinder, because ordinary distance looks more fair.
     117           0 :         let distanceSq = firstMarketPosition.distanceToSquared(secondMarketPosition);
     118             :         // We calculate gain as square of distance to encourage trading between remote markets
     119             :         // and gainMultiplier corresponds to the gain for a 100m distance
     120           0 :         gain.traderGain = Math.round(gainMultiplier * TradeGain(distanceSq, mapSize));
     121             : 
     122           0 :         gain.market1Owner = cmpMarket1Player.GetPlayerID();
     123           0 :         gain.market2Owner = cmpMarket2Player.GetPlayerID();
     124             :         // If trader undefined, the trader owner is supposed to be the same as the first market.
     125           0 :         let cmpPlayer = trader ? QueryOwnerInterface(trader) : cmpMarket1Player;
     126           0 :         if (!cmpPlayer)
     127           0 :                 return null;
     128           0 :         gain.traderOwner = cmpPlayer.GetPlayerID();
     129             : 
     130           0 :         if (gain.market1Owner != gain.market2Owner)
     131             :         {
     132           0 :                 let internationalBonus1 = this.GetInternationalBonus();
     133           0 :                 let internationalBonus2 = cmpMarket2.GetInternationalBonus();
     134           0 :                 gain.market1Gain = Math.round(gain.traderGain * internationalBonus1);
     135           0 :                 gain.market2Gain = Math.round(gain.traderGain * internationalBonus2);
     136             :         }
     137             : 
     138           0 :         return gain;
     139             : };
     140             : 
     141           0 : Market.prototype.OnDiplomacyChanged = function(msg)
     142             : {
     143           0 :         this.UpdateTraders(false);
     144             : };
     145             : 
     146           0 : Market.prototype.OnOwnershipChanged = function(msg)
     147             : {
     148           0 :         this.UpdateTraders(msg.to == INVALID_PLAYER);
     149             : };
     150             : 
     151             : function MarketMirage() {}
     152           0 : MarketMirage.prototype.Init = function(cmpMarket, entity, parent, player)
     153             : {
     154           0 :         this.entity = entity;
     155           0 :         this.parent = parent;
     156           0 :         this.player = player;
     157             : 
     158           0 :         this.traders = new Set();
     159           0 :         for (let trader of cmpMarket.GetTraders())
     160             :         {
     161           0 :                 let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
     162           0 :                 let cmpOwnership = Engine.QueryInterface(trader, IID_Ownership);
     163           0 :                 if (!cmpTrader || !cmpOwnership)
     164             :                 {
     165           0 :                         cmpMarket.RemoveTrader(trader);
     166           0 :                         continue;
     167             :                 }
     168           0 :                 if (this.player != cmpOwnership.GetOwner())
     169           0 :                         continue;
     170           0 :                 cmpTrader.SwitchMarket(cmpMarket.entity, this.entity);
     171           0 :                 cmpMarket.RemoveTrader(trader);
     172           0 :                 this.AddTrader(trader);
     173             :         }
     174           0 :         this.marketType = cmpMarket.GetType();
     175           0 :         this.internationalBonus = cmpMarket.GetInternationalBonus();
     176             : };
     177             : 
     178           0 : MarketMirage.prototype.HasType = function(type) { return this.marketType.has(type); };
     179           0 : MarketMirage.prototype.GetInternationalBonus = function() { return this.internationalBonus; };
     180           0 : MarketMirage.prototype.AddTrader = function(trader) { this.traders.add(trader); };
     181           0 : MarketMirage.prototype.RemoveTrader = function(trader) { this.traders.delete(trader); };
     182             : 
     183           0 : MarketMirage.prototype.UpdateTraders = function(msg)
     184             : {
     185           0 :         let cmpMarket = Engine.QueryInterface(this.parent, IID_Market);
     186           0 :         if (!cmpMarket) // The parent market does not exist anymore
     187             :         {
     188           0 :                 for (let trader of this.traders)
     189             :                 {
     190           0 :                         let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
     191           0 :                         if (cmpTrader)
     192           0 :                                 cmpTrader.RemoveMarket(this.entity);
     193             :                 }
     194           0 :                 return;
     195             :         }
     196             : 
     197             :         // The market becomes visible, switch all traders from the mirage to the market
     198           0 :         for (let trader of this.traders)
     199             :         {
     200           0 :                 let cmpTrader = Engine.QueryInterface(trader, IID_Trader);
     201           0 :                 if (!cmpTrader)
     202           0 :                         continue;
     203           0 :                 cmpTrader.SwitchMarket(this.entity, cmpMarket.entity);
     204           0 :                 this.RemoveTrader(trader);
     205           0 :                 cmpMarket.AddTrader(trader);
     206             :         }
     207             : };
     208             : 
     209           0 : MarketMirage.prototype.CalculateTraderGain = Market.prototype.CalculateTraderGain;
     210             : 
     211           0 : Engine.RegisterGlobal("MarketMirage", MarketMirage);
     212             : 
     213           0 : Market.prototype.Mirage = function(mirageID, miragePlayer)
     214             : {
     215           0 :         let mirage = new MarketMirage();
     216           0 :         mirage.Init(this, mirageID, this.entity, miragePlayer);
     217           0 :         return mirage;
     218             : };
     219             : 
     220           0 : Engine.RegisterComponentType(IID_Market, "Market", Market);

Generated by: LCOV version 1.14