Ticket #3234: wonderOptions_v2.patch

File wonderOptions_v2.patch, 22.0 KB (added by elexis, 8 years ago)

Fixed most things noted above besides resizeMoreOptionsWindow. Didn't test.

  • binaries/data/mods/public/gui/common/settings.js

    function loadSettingsValues()  
    3030{
    3131    var settings = {
    3232        "AIDescriptions": loadAIDescriptions(),
    3333        "AIDifficulties": loadAIDifficulties(),
    3434        "Ceasefire": loadCeasefire(),
     35        "WonderDurations": loadWonderDuration(),
    3536        "GameSpeeds": loadSettingValuesFile("game_speeds.json"),
    3637        "MapTypes": loadMapTypes(),
    3738        "MapSizes": loadSettingValuesFile("map_sizes.json"),
    3839        "PlayerDefaults": loadPlayerDefaults(),
    3940        "PopulationCapacities": loadPopulationCapacities(),
    function loadAIDifficulties()  
    129130        }
    130131    ];
    131132}
    132133
    133134/**
     135 * Loads available wonder-victory times
     136 */
     137function loadWonderDuration()
     138{
     139    var jsonFile = "wonder_times.json";
     140    var json = Engine.ReadJSONFile(g_SettingsDirectory + jsonFile);
     141
     142    if (!json || json.Default === undefined || !json.Times || !Array.isArray(json.Times))
     143    {
     144        error("Could not load " + jsonFile);
     145        return undefined;
     146    }
     147
     148    return json.Times.map(duration => ({
     149        "Duration": duration,
     150        "Default": duration == json.Default,
     151        "Title": sprintf(translatePluralWithContext("wonder victory", "%(min)s minute", "%(min)s minutes", duration), { "min": duration })
     152    }));
     153}
     154
     155/**
    134156 * Loads available ceasefire settings.
    135157 *
    136158 * @returns {Array|undefined}
    137159 */
    138160function loadCeasefire()
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

    const g_GameSpeeds = prepareForDropdown(  
    66const g_MapSizes = prepareForDropdown(g_Settings ? g_Settings.MapSizes : undefined);
    77const g_MapTypes = prepareForDropdown(g_Settings ? g_Settings.MapTypes : undefined);
    88const g_PopulationCapacities = prepareForDropdown(g_Settings ? g_Settings.PopulationCapacities : undefined);
    99const g_StartingResources = prepareForDropdown(g_Settings ? g_Settings.StartingResources : undefined);
    1010const g_VictoryConditions = prepareForDropdown(g_Settings ? g_Settings.VictoryConditions : undefined);
     11const g_WonderDurations = prepareForDropdown(g_Settings ? g_Settings.WonderDurations : undefined);
    1112
    1213/**
    1314 * All selectable playercolors except gaia.
    1415 */
    1516const g_PlayerColors = g_Settings ? g_Settings.PlayerDefaults.slice(1).map(pData => pData.Color) : undefined;
    function initGUIObjects()  
    235236        initNumberOfPlayers();
    236237        initGameSpeed();
    237238        initPopulationCaps();
    238239        initStartingResources();
    239240        initCeasefire();
     241        initWonderDurations();
    240242        initVictoryConditions();
    241243        initMapSizes();
    242244        initRadioButtons();
    243245    }
    244246    else
    function initMapFilters()  
    294296function resizeMoreOptionsWindow()
    295297{
    296298    // For singleplayer reduce the size of more options dialog by three options (cheats, rated game, observer late join = 90px)
    297299    if (!g_IsNetworked)
    298300    {
    299         Engine.GetGUIObjectByName("moreOptions").size = "50%-200 50%-195 50%+200 50%+160";
    300         Engine.GetGUIObjectByName("hideMoreOptions").size = "50%-70 310 50%+70 336";
     301        Engine.GetGUIObjectByName("moreOptions").size = "50%-200 50%-195 50%+200 50%+190";
     302        Engine.GetGUIObjectByName("hideMoreOptions").size = "50%-70 340 50%+70 366";
    301303    }
    302304    // For non-lobby multiplayergames reduce the size of the dialog by one option (rated game, 30px)
    303305    else if (!Engine.HasXmppClient())
    304306    {
    305307        Engine.GetGUIObjectByName("moreOptions").size = "50%-200 50%-195 50%+200 50%+220";
    function initVictoryConditions()  
    394396        updateGameAttributes();
    395397    };
    396398    victoryConditions.selected = g_VictoryConditions.Default;
    397399}
    398400
     401function initWonderDurations()
     402{
     403    let wonderConditions = Engine.GetGUIObjectByName("wonderDuration");
     404    wonderConditions.list = g_WonderDurations.Title;
     405    wonderConditions.list_data = g_WonderDurations.Duration;
     406    wonderConditions.selected = g_WonderDurations.Default;
     407    wonderConditions.onSelectionChange = function()
     408    {
     409        if (this.selected != -1)
     410            g_GameAttributes.settings.WonderDuration = g_WonderDurations.Duration[this.selected];
     411
     412        updateGameAttributes();
     413    };
     414}
     415
    399416function initMapSizes()
    400417{
    401418    let mapSize = Engine.GetGUIObjectByName("mapSize");
    402419    mapSize.list = g_MapSizes.LongName;
    403420    mapSize.list_data = g_MapSizes.Tiles;
    function updateGUIObjects()  
    12321249    let gameSpeedIdx = g_GameAttributes.gameSpeed !== undefined ? g_GameSpeeds.Speed.indexOf(g_GameAttributes.gameSpeed) : g_GameSpeeds.Default;
    12331250
    12341251    // These dropdowns might set the default (as they ignore g_IsInGuiUpdate)
    12351252    let mapSizeIdx = mapSettings.Size !== undefined ? g_MapSizes.Tiles.indexOf(mapSettings.Size) : g_MapSizes.Default;
    12361253    let victoryIdx = mapSettings.GameType !== undefined ? g_VictoryConditions.Name.indexOf(mapSettings.GameType) : g_VictoryConditions.Default;
     1254    let wonderDurationIdx = mapSettings.WonderDuration !== undefined ? g_WonderDurations.Duration.indexOf(mapSettings.WonderDuration) : g_WonderDurations.Default;
    12371255    let popIdx = mapSettings.PopulationCap !== undefined ? g_PopulationCapacities.Population.indexOf(mapSettings.PopulationCap) : g_PopulationCapacities.Default;
    12381256    let startingResIdx = mapSettings.StartingResources !== undefined ? g_StartingResources.Resources.indexOf(mapSettings.StartingResources) : g_StartingResources.Default;
    12391257    let ceasefireIdx = mapSettings.Ceasefire !== undefined ? g_Ceasefire.Duration.indexOf(mapSettings.Ceasefire) : g_Ceasefire.Default;
    12401258    let numPlayers = mapSettings.PlayerData ? mapSettings.PlayerData.length : g_MaxPlayers;
    12411259
    function updateGUIObjects()  
    12481266        Engine.GetGUIObjectByName("numPlayersSelection").selected = numPlayers - 1;
    12491267        Engine.GetGUIObjectByName("victoryCondition").selected = victoryIdx;
    12501268        Engine.GetGUIObjectByName("populationCap").selected = popIdx;
    12511269        Engine.GetGUIObjectByName("gameSpeed").selected = gameSpeedIdx;
    12521270        Engine.GetGUIObjectByName("ceasefire").selected = ceasefireIdx;
     1271        Engine.GetGUIObjectByName("wonderDuration").selected = wonderDurationIdx;
    12531272        Engine.GetGUIObjectByName("startingResources").selected = startingResIdx;
    12541273    }
    12551274    else
    12561275    {
    12571276        Engine.GetGUIObjectByName("mapTypeText").caption = g_MapTypes.Title[mapTypeIdx];
    function updateGUIObjects()  
    12621281
    12631282    // Can be visible to both host and clients
    12641283    Engine.GetGUIObjectByName("mapSizeText").caption = g_GameAttributes.mapType == "random" ? g_MapSizes.LongName[mapSizeIdx] : translate("Default");
    12651284    Engine.GetGUIObjectByName("numPlayersText").caption = numPlayers;
    12661285    Engine.GetGUIObjectByName("victoryConditionText").caption = g_VictoryConditions.Title[victoryIdx];
     1286    Engine.GetGUIObjectByName("wonderDurationText").caption = g_WonderDurations.Title[wonderDurationIdx];
    12671287    Engine.GetGUIObjectByName("populationCapText").caption = g_PopulationCapacities.Title[popIdx];
    12681288    Engine.GetGUIObjectByName("startingResourcesText").caption = g_StartingResources.Title[startingResIdx];
    12691289    Engine.GetGUIObjectByName("ceasefireText").caption = g_Ceasefire.Title[ceasefireIdx];
    12701290    Engine.GetGUIObjectByName("gameSpeedText").caption = g_GameSpeeds.Title[gameSpeedIdx];
    12711291
    function updateGUIObjects()  
    12751295    setGUIBoolean("revealMap", "revealMapText", !!mapSettings.RevealMap);
    12761296    setGUIBoolean("lockTeams", "lockTeamsText", !!mapSettings.LockTeams);
    12771297    setGUIBoolean("observerLateJoin", "observerLateJoinText", !!mapSettings.ObserverLateJoin);
    12781298    setGUIBoolean("enableRating", "enableRatingText", !!mapSettings.RatingEnabled);
    12791299
     1300    Engine.GetGUIObjectByName("optionWonderDuration").hidden =
     1301        g_GameAttributes.settings.GameType &&
     1302        g_GameAttributes.settings.GameType == "wonder";
     1303
    12801304    Engine.GetGUIObjectByName("cheatWarningText").hidden = !g_IsNetworked || !mapSettings.CheatsEnabled;
    12811305
    12821306    Engine.GetGUIObjectByName("enableCheats").enabled = !mapSettings.RatingEnabled;
    12831307    Engine.GetGUIObjectByName("lockTeams").enabled = !mapSettings.RatingEnabled;
    12841308
    function updateGUIObjects()  
    12891313    Engine.GetGUIObjectByName("mapSizeText").hidden = !isRandom || g_IsController;
    12901314    hideControl("numPlayersSelection", "numPlayersText", isRandom && g_IsController);
    12911315
    12921316    let notScenario = g_GameAttributes.mapType != "scenario" && g_IsController ;
    12931317    hideControl("victoryCondition", "victoryConditionText", notScenario);
     1318    hideControl("wonderDuration", "wonderDurationText", notScenario);
    12941319    hideControl("populationCap", "populationCapText", notScenario);
    12951320    hideControl("startingResources", "startingResourcesText", notScenario);
    12961321    hideControl("ceasefire", "ceasefireText", notScenario);
    12971322    hideControl("revealMap", "revealMapText", notScenario);
    12981323    hideControl("exploreMap", "exploreMapText", notScenario);
    function updateGUIObjects()  
    13461371        pColorPickerHeading.hidden = !canChangeColors;
    13471372        if (canChangeColors)
    13481373            pColorPicker.selected = g_PlayerColors.findIndex(col => sameColor(col, color));
    13491374    }
    13501375
     1376    resizeMoreOptionsWindow();
     1377
    13511378    g_IsInGuiUpdate = false;
    13521379
    13531380    // Game attributes include AI settings, so update the player list
    13541381    updatePlayerList();
    13551382
    function setMapDescription()  
    13641391{
    13651392    let numPlayers = g_GameAttributes.settings.PlayerData ? g_GameAttributes.settings.PlayerData.length : 0;
    13661393    let mapName = g_GameAttributes.map || "";
    13671394
    13681395    let victoryIdx = Math.max(0, g_VictoryConditions.Name.indexOf(g_GameAttributes.settings.GameType || ""));
    1369     let victoryTitle = g_VictoryConditions.Title[victoryIdx];
     1396    let victoryTitle;
     1397
     1398    if (g_VictoryConditions.Name[victoryIdx] == "wonder")
     1399        victoryTitle = sprintf(
     1400                translatePluralWithContext(
     1401                    "victory condition",
     1402                    "Wonder (%(min)s minute)",
     1403                    "Wonder (%(min)s minutes)",
     1404                    g_GameAttributes.settings.WonderDuration
     1405                ),
     1406                { "min": g_GameAttributes.settings.WonderDuration }
     1407        );
     1408    else
     1409        victoryTitle = g_VictoryConditions.Title[victoryIdx];
     1410
    13701411    if (victoryIdx != g_VictoryConditions.Default)
    13711412        victoryTitle = "[color=\"" + g_VictoryColor + "\"]" + victoryTitle + "[/color]";
    13721413
    13731414    let mapDescription = g_GameAttributes.settings.Description ? translate(g_GameAttributes.settings.Description) : translate("Sorry, no description available.");
    13741415    if (mapName == "random")
  • binaries/data/mods/public/gui/gamesetup/gamesetup.xml

     
    268268            <!-- End Options -->
    269269            </object>
    270270
    271271            <!-- More Options -->
    272272            <object hidden="true" name="moreOptionsFade" type="image" z="60" sprite="ModernFade"/>
    273             <object name="moreOptions" type="image" sprite="ModernDialog" size="50%-200 50%-195 50%+200 50%+250" z="70" hidden="true">
     273            <object name="moreOptions" type="image" sprite="ModernDialog" size="50%-200 50%-120 50%+200 50%+250" z="70" hidden="true">
    274274                <object style="ModernLabelText" type="text" size="50%-128 -18 50%+128 14">
    275275                    <translatableAttribute id="caption">More Options</translatableAttribute>
    276276                </object>
    277277
    278278                <object size="14 38 94% 66">
     
    323323                    <object name="ceasefire" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
    324324                        <translatableAttribute id="tooltip">Set time where no attacks are possible.</translatableAttribute>
    325325                    </object>
    326326                </object>
    327327
    328                 <object size="14 188 94% 216">
     328                <object name="optionWonderDuration" size="14 188 94% 216">
     329                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
     330                        <translatableAttribute id="caption">Wonder:</translatableAttribute>
     331                    </object>
     332                    <object name="wonderDurationText" size="40% 0 100% 100%" type="text" style="ModernLeftLabelText"/>
     333                    <object name="wonderDuration" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
     334                        <translatableAttribute id="tooltip">Number of minuts that the player has to keep the wonder in order to win.</translatableAttribute>
     335                    </object>
     336                </object>
     337
     338                <object size="14 218 94% 246">
    329339                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    330340                        <translatableAttribute id="caption" comment="Make sure to differentiate between the revealed map and explored map options!">Revealed Map:</translatableAttribute>
    331341                    </object>
    332342                    <object name="revealMapText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    333343                    <object name="revealMap" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
    334344                        <translatableAttribute id="tooltip" comment="Make sure to differentiate between the revealed map and explored map options!">Toggle revealed map (see everything).</translatableAttribute>
    335345                    </object>
    336346                </object>
    337347
    338                 <object size="14 218 94% 246">
     348                <object size="14 248 94% 276">
    339349                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    340350                        <translatableAttribute id="caption" comment="Make sure to differentiate between the revealed map and explored map options!">Explored Map:</translatableAttribute>
    341351                    </object>
    342352                    <object name="exploreMapText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    343353                    <object name="exploreMap" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
    344354                        <translatableAttribute id="tooltip" comment="Make sure to differentiate between the revealed map and explored map options!">Toggle explored map (see initial map).</translatableAttribute>
    345355                    </object>
    346356                </object>
    347357
    348                 <object size="14 248 94% 276">
     358                <object size="14 278 94% 306">
    349359                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    350360                        <translatableAttribute id="caption">Disable Treasures:</translatableAttribute>
    351361                    </object>
    352362                    <object name="disableTreasuresText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    353363                    <object name="disableTreasures" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
    354364                        <translatableAttribute id="tooltip">Disable all treasures on the map.</translatableAttribute>
    355365                    </object>
    356366                </object>
    357367
    358                 <object size="14 278 94% 306">
     368                <object size="14 308 94% 336">
    359369                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    360370                        <translatableAttribute id="caption">Teams Locked:</translatableAttribute>
    361371                    </object>
    362372                    <object name="lockTeamsText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    363373                    <object name="lockTeams" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
    364374                        <translatableAttribute id="tooltip">Toggle locked teams.</translatableAttribute>
    365375                    </object>
    366376                </object>
    367377
    368                 <object name="optionCheats" size="14 308 94% 336" hidden="true">
     378                <object name="optionCheats" size="14 338 94% 366" hidden="true">
    369379                    <object size="0 0 40% 28" type="text" style="ModernRightLabelText">
    370380                        <translatableAttribute id="caption">Cheats:</translatableAttribute>
    371381                    </object>
    372382                    <object name="enableCheatsText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    373383                    <object name="enableCheats" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
    374384                        <translatableAttribute id="tooltip">Toggle the usability of cheats.</translatableAttribute>
    375385                    </object>
    376386                </object>
    377387
    378                 <object name="optionRating" size="14 338 94% 366" hidden="true">
     388                <object name="optionRating" size="14 368 94% 396" hidden="true">
    379389                    <object size="0 0 40% 28" hidden="false" type="text" style="ModernRightLabelText">
    380390                        <translatableAttribute id="caption">Rated Game:</translatableAttribute>
    381391                    </object>
    382392                    <object name="enableRatingText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    383393                    <object name="enableRating" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
    384394                        <translatableAttribute id="tooltip">Toggle if this game will be rated for the leaderboard.</translatableAttribute>
    385395                    </object>
    386396                </object>
    387397
    388                 <object name="optionObserverLateJoin" size="14 368 94% 396" hidden="true">
     398                <object name="optionObserverLateJoin" size="14 398 94% 426" hidden="true">
    389399                    <object size="0 0 40% 28" type="text" hidden="false" style="ModernRightLabelText">
    390400                        <translatableAttribute id="caption">Late Observer Joins:</translatableAttribute>
    391401                    </object>
    392402                    <object name="observerLateJoinText" size="40% 0 100% 28" type="text" style="ModernLeftLabelText"/>
    393403                    <object name="observerLateJoin" size="40%+10 5 40%+30 100%-5" type="checkbox" style="ModernTickBox" hidden="true" tooltip_style="onscreenToolTip">
     
    398408                <!-- Hide More Options Button -->
    399409                <object
    400410                    name="hideMoreOptions"
    401411                    type="button"
    402412                    style="StoneButton"
    403                     size="50%-70 400 50%+70 426"
     413                    size="50%-70 430 50%+70 456"
    404414                    tooltip_style="onscreenToolTip"
    405415                    hotkey="cancel"
    406416                >
    407417                    <translatableAttribute id="caption">OK</translatableAttribute>
    408418                    <translatableAttribute id="tooltip">Close more game options window</translatableAttribute>
  • binaries/data/mods/public/maps/scripts/WonderVictory.js

    Trigger.prototype.CheckWonderVictory = f  
    2929    var players = [-1];
    3030    for (var i = 1; i < numPlayers; i++)
    3131        if (i != data.to)
    3232            players.push(i);
    3333
    34     var time = cmpWonder.GetTimeTillVictory()*1000;
     34    var time = cmpWonder.GetVictoryDuration() * 1000 * 60; // minutes to millisecounds
    3535    messages.otherMessage = cmpGuiInterface.AddTimeNotification({
    3636        "message": markForTranslation("%(player)s will have won in %(time)s"),
    3737        "players": players,
    3838        "parameters": {"player": cmpPlayer.GetName()},
    3939        "translateMessage": true,
  • binaries/data/mods/public/simulation/components/EndGameManager.js

    EndGameManager.prototype.Init = function  
    1717    this.gameType = "conquest";
    1818   
    1919    // Allied victory means allied players can win if victory conditions are met for each of them
    2020    // Would be false for a "last man standing" game (when diplomacy is fully implemented)
    2121    this.alliedVictory = true;
     22
     23    this.wonderDuration = 0;
    2224};
    2325
    2426EndGameManager.prototype.GetGameType = function()
    2527{
    2628    return this.gameType;
    EndGameManager.prototype.SetGameType = f  
    3537EndGameManager.prototype.CheckGameType = function(type)
    3638{
    3739    return this.gameType == type;
    3840};
    3941
     42EndGameManager.prototype.SetWonderDuration = function(wonderDuration)
     43{
     44    this.wonderDuration = wonderDuration;
     45};
     46
     47EndGameManager.prototype.GetWonderDuration = function()
     48{
     49    return this.wonderDuration;
     50};
     51
    4052EndGameManager.prototype.MarkPlayerAsWon = function(playerID)
    4153{
    4254    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
    4355    var numPlayers = cmpPlayerManager.GetNumPlayers();
    4456    for (var i = 1; i < numPlayers; i++)
  • binaries/data/mods/public/simulation/components/Wonder.js

     
    11function Wonder() {}
    22
    33Wonder.prototype.Schema =
    4     "<element name='TimeTillVictory'>" +
    5         "<data type='nonNegativeInteger'/>" +
     4    "<element name='DurationMultiplier'>" +
     5        "<data type='nonNegativeDecimal'/>" +
    66    "</element>";
    77
    88Wonder.prototype.Init = function()
    99{
    1010};
    1111
    1212Wonder.prototype.Serialize = null;
    1313
    14 Wonder.prototype.GetTimeTillVictory = function()
     14/**
     15 * Returns the number of minutes that a player has to keep the wonder in order to win.
     16 */
     17Wonder.prototype.GetVictoryDuration = function()
    1518{
    16     return +this.template.TimeTillVictory;
     19    var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
     20    return cmpEndGameManager.GetWonderDuration() * this.template.DurationMultiplier;
    1721};
    1822
    1923Engine.RegisterComponentType(IID_Wonder, "Wonder", Wonder);
  • binaries/data/mods/public/simulation/data/settings/wonder_times.json

     
     1{
     2    "Times": [1, 5, 10, 15, 20, 25, 30],
     3    "Default": 15
     4}
  • binaries/data/mods/public/simulation/helpers/Setup.js

    function LoadMapSettings(settings)  
    4747    }
    4848
    4949    var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
    5050    if (settings.GameType)
    5151        cmpEndGameManager.SetGameType(settings.GameType);
     52    if (settings.WonderDurations)
     53        cmpEndGameManager.SetWonderDuration(settings.WonderDuration);
    5254
    5355    if (settings.Garrison)
    5456    {
    5557        for (let holder in settings.Garrison)
    5658        {
  • binaries/data/mods/public/simulation/templates/template_structure_wonder.xml

     
    8484  </Vision>
    8585  <VisualActor>
    8686    <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
    8787  </VisualActor>
    8888  <Wonder>
    89     <TimeTillVictory>300</TimeTillVictory>
     89    <DurationMultiplier>1</DurationMultiplier>
    9090  </Wonder>
    9191</Entity>