LCOV - code coverage report
Current view: top level - simulation/helpers - Requirements.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 54 54 100.0 %
Date: 2023-04-02 12:52:40 Functions: 7 7 100.0 %

          Line data    Source code
       1             : function RequirementsHelper() {}
       2             : 
       3           3 : RequirementsHelper.prototype.DEFAULT_RECURSION_DEPTH = 1;
       4             : 
       5           3 : RequirementsHelper.prototype.EntityRequirementsSchema =
       6             :         "<element name='Entities' a:help='Entities that need to be controlled.'>" +
       7             :                 "<oneOrMore>" +
       8             :                         "<element a:help='Class of entity that needs to be controlled.'>" +
       9             :                                 "<anyName/>" +
      10             :                                 "<oneOrMore>" +
      11             :                                         "<choice>" +
      12             :                                                 "<element name='Count' a:help='Number of entities required.'>" +
      13             :                                                         "<data type='nonNegativeInteger'/>" +
      14             :                                                 "</element>" +
      15             :                                                 "<element name='Variants' a:help='Number of different entities of this class required.'>" +
      16             :                                                         "<data type='nonNegativeInteger'/>" +
      17             :                                                 "</element>" +
      18             :                                         "</choice>" +
      19             :                                 "</oneOrMore>" +
      20             :                         "</element>" +
      21             :                 "</oneOrMore>" +
      22             :         "</element>";
      23             : 
      24           3 : RequirementsHelper.prototype.TechnologyRequirementsSchema =
      25             :         "<element name='Techs' a:help='White-space separated list of technologies that need to be researched. ! negates a tech.'>" +
      26             :                 "<attribute name='datatype'>" +
      27             :                         "<value>tokens</value>" +
      28             :                 "</attribute>" +
      29             :                 "<text/>" +
      30             :         "</element>";
      31             : 
      32             : /**
      33             :  * @param {number} recursionDepth - How deep we recurse.
      34             :  * @return {string} - A RelaxRNG schema for requirements.
      35             :  */
      36           3 : RequirementsHelper.prototype.RequirementsSchema = function(recursionDepth)
      37             : {
      38           4 :         return "" +
      39             :                 "<oneOrMore>" +
      40             :                         this.ChoicesSchema(--recursionDepth) +
      41             :                 "</oneOrMore>";
      42             : };
      43             : 
      44             : /**
      45             :  * @param {number} recursionDepth - How deep we recurse.
      46             :  * @return {string} - A RelaxRNG schema for chosing requirements.
      47             :  */
      48           3 : RequirementsHelper.prototype.ChoicesSchema = function(recursionDepth)
      49             : {
      50           6 :         const allAnySchema = recursionDepth > 0 ? "" +
      51             :                 "<element name='All' a:help='Requires all of the conditions to be met.'>" +
      52             :                         this.RequirementsSchema(recursionDepth) +
      53             :                 "</element>" +
      54             :                 "<element name='Any' a:help='Requires at least one of the following conditions met.'>" +
      55             :                         this.RequirementsSchema(recursionDepth) +
      56             :                 "</element>" : "";
      57             : 
      58           6 :         return "" +
      59             :                 "<choice>" +
      60             :                         allAnySchema +
      61             :                         this.EntityRequirementsSchema +
      62             :                         this.TechnologyRequirementsSchema +
      63             :                 "</choice>";
      64             : };
      65             : 
      66             : /**
      67             :  * @param {number} recursionDepth - How deeply recursive we build the schema.
      68             :  * @return {string} - A RelaxRNG schema for requirements.
      69             :  */
      70           3 : RequirementsHelper.prototype.BuildSchema = function(recursionDepth = this.DEFAULT_RECURSION_DEPTH)
      71             : {
      72           2 :         return "" +
      73             :                 "<element name='Requirements' a:help='The requirements that ought to be met before this entity can be produced.'>" +
      74             :                         "<optional>" +
      75             :                                 this.ChoicesSchema(recursionDepth) +
      76             :                         "</optional>" +
      77             :                         "<optional>" +
      78             :                                 "<element name='Tooltip' a:help='A tooltip explaining the requirements.'>" +
      79             :                                         "<text/>" +
      80             :                                 "</element>" +
      81             :                         "</optional>" +
      82             :                 "</element>";
      83             : };
      84             : 
      85             : /**
      86             :  * @param {Object} template - The requirements template as defined above.
      87             :  * @param {number} playerID -
      88             :  * @return {boolean} -
      89             :  */
      90           3 : RequirementsHelper.prototype.AreRequirementsMet = function(template, playerID)
      91             : {
      92          55 :         if (!template || !Object.keys(template).length)
      93           1 :                 return true;
      94             : 
      95          54 :         const cmpTechManager = QueryPlayerIDInterface(playerID, IID_TechnologyManager);
      96          54 :         return cmpTechManager && this.AllRequirementsMet(template, cmpTechManager);
      97             : };
      98             : 
      99             : /**
     100             :  * @param {Object} template - The requirements template for "all".
     101             :  * @param {component} cmpTechManager -
     102             :  * @return {boolean} -
     103             :  */
     104           3 : RequirementsHelper.prototype.AllRequirementsMet = function(template, cmpTechManager)
     105             : {
     106          97 :         for (const requirementType in template)
     107             :         {
     108         104 :                 const requirement = template[requirementType];
     109         104 :                 if (requirementType === "All" && !this.AllRequirementsMet(requirement, cmpTechManager))
     110          20 :                         return false;
     111          84 :                 if (requirementType === "Any" && !this.AnyRequirementsMet(requirement, cmpTechManager))
     112           7 :                         return false;
     113          77 :                 if (requirementType === "Entities")
     114             :                 {
     115          15 :                         for (const className in requirement)
     116             :                         {
     117          15 :                                 const entReq = requirement[className];
     118          15 :                                 if ("Count" in entReq && (!(className in cmpTechManager.classCounts) || cmpTechManager.classCounts[className] < entReq.Count))
     119           4 :                                         return false;
     120          11 :                                 if ("Variants" in entReq && (!(className in cmpTechManager.typeCountsByClass) || Object.keys(cmpTechManager.typeCountsByClass[className]).length < entReq.Variants))
     121           3 :                                         return false;
     122             :                         }
     123             :                 }
     124          70 :                 if (requirementType === "Techs" && requirement._string)
     125          33 :                         for (const tech of requirement._string.split(" "))
     126          39 :                                 if (tech[0] === "!" ? cmpTechManager.IsTechnologyResearched(tech.substring(1)) :
     127             :                                         !cmpTechManager.IsTechnologyResearched(tech))
     128          20 :                                         return false;
     129             :         }
     130          43 :         return true;
     131             : };
     132             : 
     133             : /**
     134             :  * @param {Object} template - The requirements template for "any".
     135             :  * @param {component} cmpTechManager -
     136             :  * @return {boolean} -
     137             :  */
     138           3 : RequirementsHelper.prototype.AnyRequirementsMet = function(template, cmpTechManager)
     139             : {
     140          23 :         for (const requirementType in template)
     141             :         {
     142          33 :                 const requirement = template[requirementType];
     143          33 :                 if (requirementType === "All" && this.AllRequirementsMet(requirement, cmpTechManager))
     144           3 :                         return true;
     145          30 :                 if (requirementType === "Any" && this.AnyRequirementsMet(requirement, cmpTechManager))
     146           1 :                         return true;
     147          29 :                 if (requirementType === "Entities")
     148             :                 {
     149          12 :                         for (const className in requirement)
     150             :                         {
     151          12 :                                 const entReq = requirement[className];
     152          12 :                                 if ("Count" in entReq && className in cmpTechManager.classCounts && cmpTechManager.classCounts[className] >= entReq.Count)
     153           3 :                                         return true;
     154           9 :                                 if ("Variants" in entReq && className in cmpTechManager.typeCountsByClass && Object.keys(cmpTechManager.typeCountsByClass[className]).length >= entReq.Variants)
     155           2 :                                         return true;
     156             :                         }
     157             :                 }
     158          24 :                 if (requirementType === "Techs" && requirement._string)
     159          11 :                         for (const tech of requirement._string.split(" "))
     160          13 :                                 if (tech[0] === "!" ? !cmpTechManager.IsTechnologyResearched(tech.substring(1)) :
     161             :                                         cmpTechManager.IsTechnologyResearched(tech))
     162           6 :                                         return true;
     163             :         }
     164           8 :         return false;
     165             : };
     166             : 
     167           3 : Engine.RegisterGlobal("RequirementsHelper", new RequirementsHelper());

Generated by: LCOV version 1.14