<commit_before>﻿unit KM_GUIGameResultsMP;
{$I KaM_Remake.inc}
interface
uses
  Classes, Controls, Math, StrUtils, SysUtils,
  KM_CommonTypes, KM_Controls, KM_Defaults, KM_Pics,
  KM_InterfaceDefaults, KM_ResWares, KM_HandStats;


type
  TKMStatType = (st_ByPlayers, st_ByTeams);

  TKMEconomyStatKind = (est_Citizens, est_Houses);

  // Army chart types (enum)
  TKMChartWarriorType = (cwt_ArmyPower, cwt_All,
    cwt_Militia,      cwt_AxeFighter,   cwt_Swordsman,     cwt_Bowman,
    cwt_Arbaletman,   cwt_Pikeman,      cwt_Hallebardman,  cwt_HorseScout,
    cwt_Cavalry,      cwt_Barbarian,
    cwt_Peasant,      cwt_Slingshot,    cwt_MetalBarbarian, cwt_Horseman);

  // Chart army type class
  TKMChartWarrior = class
  private
    fType: TKMChartWarriorType;
    fUnitType: TKMUnitType;
    function GetUnitType: TKMUnitType;
    function GetGUIName: UnicodeString;
    function GetGUIIcon: Word;
  public
    constructor Create(aType: TKMChartWarriorType);
    property UnitType: TKMUnitType read GetUnitType;
    property GUIName: UnicodeString read GetGUIName;
    property GUIIcon: Word read GetGUIIcon;
    function HasUnitType: Boolean;
  end;

  TKMChartArmyMP = class
  private
    fType: TKMChartWarrior;
    fKind: TKMChartArmyKind;
    fChart: TKMChart;
    function GetArmyPowerChartData(aPlayer: TKMHandIndex): TKMCardinalArray;
  public
    constructor Create(aType: TKMChartWarriorType; aKind: TKMChartArmyKind; aParent: TKMPanel; aLeft, aTop, aWidth, aHeight: Integer);
    destructor Destroy; override;
    function IsEmpty(aPlayer: TKMHandIndex): Boolean;
    function GetChartData(aPlayer: TKMHandIndex): TKMCardinalArray;
    property Chart: TKMChart read fChart;
    property ChartType: TKMChartWarrior read fType;
  end;

  PKMChartArmyMP = ^TKMChartArmyMP;

  TKMStatsValues = array[0..MAX_HANDS-1] of array [0..9] of Cardinal;

  TKMGameResultsMP = class
  private
    fOnStopGame: TUnicodeStringWDefEvent;
    fOnShowSPStats: TEvent;

    fReinitedLastTime: Boolean;

    fGameResultMsg: TKMGameResultMsg; //So we know where to go after results screen
    fLegendLinesVisible: array [TKMStatType] of array [0 .. MAX_HANDS - 1] of Boolean;  //Remember visible players when toggling wares

    fStatType: TKMStatType;

    fNoEconomyChartData: Boolean;
    fNoArmyChartData: Boolean;
    fColumnBoxArmy_Rows: array[TKMChartArmyKind] of array of TKMChartWarriorType;

    fChartSeparatorsPos: array[TKMStatType] of TStringList;
    fNamesToShow: array[TKMStatType] of array[0 .. MAX_HANDS - 1] of String;
    fTeamMembersNames: array[0 .. MAX_HANDS - 1] of array[0 .. MAX_HANDS - 1] of String;
    fTeamMembersColors: array[0 .. MAX_HANDS - 1] of array[0 .. MAX_HANDS - 1] of Cardinal;
    fTeamMembersCounts: array[0 .. MAX_HANDS - 1] of Byte;
    fColorsToShow: array[TKMStatType] of array[0 .. MAX_HANDS - 1] of Cardinal;
    fListToShow: array[TKMStatType] of TStringList;
    fStatsValues: array[TKMStatType] of TKMStatsValues;

    fShowAIResults: Boolean;
    procedure RecreateListToShow(aStatType: TKMStatType);
    procedure BackClick(Sender: TObject);
    function DoAdjoinSameColorHand(aHandId: Integer): Boolean;
    function GetSelectedChartArmyKind: TKMChartArmyKind;
    function GetChartWares(aPlayer: TKMHandIndex; aWare: TKMWareType; aUseGDP: Boolean): TKMCardinalArray;
    function DoShowHandStats(aHandId: Integer): Boolean;

    procedure Create_ResultsMP(aParent: TKMPanel);
    procedure CreateBars(aParent: TKMPanel);
    procedure CreateChartEconomy;
    procedure CreateChartWares(aParent: TKMPanel);
    procedure CreateChartArmy(aParent: TKMPanel);

    procedure UpdateVisibleTab;
    procedure TabChange(Sender: TObject);
    procedure StatTypeChange(Sender: TObject);
    procedure BarsUpdate(aStatType: TKMStatType);
    procedure EconomyUpdate(Sender: TObject);
    procedure WareUpdate(Sender: TObject);
    procedure ArmyUpdate(Sender: TObject);

    procedure Chart_LegendClick(Sender: TObject; aLegendLineId: Integer; aLineVisible: Boolean);

    procedure RadioEconomyTypeChange(Sender: TObject);
    procedure RadioWareTypeChange(Sender: TObject);
    procedure RadioArmyTypeChange(Sender: TObject);

    function GetChartLegendDetailedTitles(aStatType: TKMStatType; aLineI: Integer): TStringArray;
    function GetChartLegendDetailedColors(aStatType: TKMStatType; aLineI: Integer): TKMCardinalArray;

    procedure Reinit;
    procedure ReinitPlayersToShow;
    procedure ReinitTeamsToShow;
    procedure ReinitBars;
    procedure ReinitChartEconomy;
    procedure ReinitChartWares;
    procedure ReinitChartArmy;
  protected
    Panel_ResultsMP: TKMPanel;
      Button_Bars,
      Button_Army,
      Button_Economy,
      Button_Wares,
      Button_Players,Button_Teams: TKMButtonFlat;
      Label_ResultsMP: TKMLabel;
      Panel_Bars: TKMPanel;
        Panel_BarsUpper, Panel_BarsLower: TKMPanel;
          Label_ResultsPlayerName1, Label_ResultsPlayerName2: array [0 .. MAX_LOBBY_PLAYERS - 1] of TKMLabel;
          Bar_Results: array [0 .. MAX_LOBBY_PLAYERS - 1, 0 .. 9] of TKMPercentBar;
          Image_ResultsRosette: array [0 .. MAX_LOBBY_PLAYERS - 1, 0 .. 9] of TKMImage;
      Panel_ChartsEconomy: TKMPanel;
        Chart_Players_Citizens: TKMChart;
        Chart_Players_Houses: TKMChart;
        Chart_Teams_Citizens: TKMChart;
        Chart_Teams_Houses: TKMChart;
        Label_NoEconomyData: TKMLabel;
        Panel_ChartEconomy_Type: TKMPanel;
          Radio_ChartEconomyType: TKMRadioGroup;
      Panel_ChartsWares: TKMPanel;
        Columnbox_Wares: TKMColumnBox;    //columnBox for Quantities charts
        Columnbox_WaresGDP: TKMColumnBox; //columnBox for GDP charts
        Charts_Wares: array[TKMStatType] of array[TKMWareType] of TKMChart; //One for each kind
        Charts_WaresGDP: array[TKMStatType] of array [0..2] of TKMChart;
        Label_NoWareData: TKMLabel;
        Panel_ChartWare_Type: TKMPanel;
          Radio_ChartWareType: TKMRadioGroup;
      Panel_ChartsArmy: TKMPanel;
        Columnbox_Army: TKMColumnBox;
        Charts_Army: array[TKMStatType] of array[TKMChartArmyKind] of array[TKMChartWarriorType] of TKMChartArmyMP;
        Label_NoArmyData: TKMLabel;
        Panel_ChartArmy_Type: TKMPanel;
          Radio_ChartArmyType: TKMRadioGroup;
      Button_Back: TKMButton;
      Button_BackToGame: TKMButton;
  public
    constructor Create(aParent: TKMPanel; aOnStopGame: TUnicodeStringWDefEvent; aOnShowSPStats: TEvent);
    destructor Destroy; override;

    property GameResultMsg: TKMGameResultMsg read fGameResultMsg;

    procedure ResetControls;
    procedure Show(aMsg: TKMGameResultMsg; aReinitLastTime: Boolean = False);
    function Visible: Boolean;
    procedure Hide;
    procedure UpdateState(aTick: Cardinal);
  end;


implementation
uses
  KM_ResTexts, KM_Game, KM_HandsCollection, KM_CommonUtils, KM_Resource, KM_ResFonts,
  KM_RenderUI, KM_Hand, KM_ResUnits,
  KM_GameTypes;


const
  PANES_TOP = 185-80;
  BAR_ROW_HEIGHT = 21;
  CHART_HEIGHT = 595;
  CHART_ECO_HEIGHT = 285;
  BACK_BTN_Y_TO_BOTTOM = 60;
  SUBMENU_RIGHT_WIDTH = 160;
  BTN_BACK_TO_GAME_LEFT = RESULTS_X_PADDING + 330;

  WARRIORS_POWER_RATES: array [WARRIOR_MIN..WARRIOR_MAX] of Single = (
    1, 2.4, 5.2,    // ut_Militia, ut_AxeFighter, ut_Swordsman
    2.2, 4,         // ut_Bowman, ut_Arbaletman
    2, 4,           // ut_Pikeman, ut_Hallebardman
    3.3, 6,         // ut_HorseScout, ut_Cavalry
    5.3, 1.5, 1.5,  // ut_Barbarian, ut_Peasant, ut_Slingshot
    5.3, 2.1        // ut_MetalBarbarian, ut_Horseman
  );

  GDPWares: array [0..2] of TKMWareType = (wt_All, wt_Warfare, wt_Food);


function GetWareIdInGDPArr(aWare: TKMWareType): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := 0 to 2 do
    if aWare = GDPWares[I] then
    begin<commit_msg>SubMenu chart width 160 -> 170<commit_after>﻿unit KM_GUIGameResultsMP;
{$I KaM_Remake.inc}
interface
uses
  Classes, Controls, Math, StrUtils, SysUtils,
  KM_CommonTypes, KM_Controls, KM_Defaults, KM_Pics,
  KM_InterfaceDefaults, KM_ResWares, KM_HandStats;


type
  TKMStatType = (st_ByPlayers, st_ByTeams);

  TKMEconomyStatKind = (est_Citizens, est_Houses);

  // Army chart types (enum)
  TKMChartWarriorType = (cwt_ArmyPower, cwt_All,
    cwt_Militia,      cwt_AxeFighter,   cwt_Swordsman,     cwt_Bowman,
    cwt_Arbaletman,   cwt_Pikeman,      cwt_Hallebardman,  cwt_HorseScout,
    cwt_Cavalry,      cwt_Barbarian,
    cwt_Peasant,      cwt_Slingshot,    cwt_MetalBarbarian, cwt_Horseman);

  // Chart army type class
  TKMChartWarrior = class
  private
    fType: TKMChartWarriorType;
    fUnitType: TKMUnitType;
    function GetUnitType: TKMUnitType;
    function GetGUIName: UnicodeString;
    function GetGUIIcon: Word;
  public
    constructor Create(aType: TKMChartWarriorType);
    property UnitType: TKMUnitType read GetUnitType;
    property GUIName: UnicodeString read GetGUIName;
    property GUIIcon: Word read GetGUIIcon;
    function HasUnitType: Boolean;
  end;

  TKMChartArmyMP = class
  private
    fType: TKMChartWarrior;
    fKind: TKMChartArmyKind;
    fChart: TKMChart;
    function GetArmyPowerChartData(aPlayer: TKMHandIndex): TKMCardinalArray;
  public
    constructor Create(aType: TKMChartWarriorType; aKind: TKMChartArmyKind; aParent: TKMPanel; aLeft, aTop, aWidth, aHeight: Integer);
    destructor Destroy; override;
    function IsEmpty(aPlayer: TKMHandIndex): Boolean;
    function GetChartData(aPlayer: TKMHandIndex): TKMCardinalArray;
    property Chart: TKMChart read fChart;
    property ChartType: TKMChartWarrior read fType;
  end;

  PKMChartArmyMP = ^TKMChartArmyMP;

  TKMStatsValues = array[0..MAX_HANDS-1] of array [0..9] of Cardinal;

  TKMGameResultsMP = class
  private
    fOnStopGame: TUnicodeStringWDefEvent;
    fOnShowSPStats: TEvent;

    fReinitedLastTime: Boolean;

    fGameResultMsg: TKMGameResultMsg; //So we know where to go after results screen
    fLegendLinesVisible: array [TKMStatType] of array [0 .. MAX_HANDS - 1] of Boolean;  //Remember visible players when toggling wares

    fStatType: TKMStatType;

    fNoEconomyChartData: Boolean;
    fNoArmyChartData: Boolean;
    fColumnBoxArmy_Rows: array[TKMChartArmyKind] of array of TKMChartWarriorType;

    fChartSeparatorsPos: array[TKMStatType] of TStringList;
    fNamesToShow: array[TKMStatType] of array[0 .. MAX_HANDS - 1] of String;
    fTeamMembersNames: array[0 .. MAX_HANDS - 1] of array[0 .. MAX_HANDS - 1] of String;
    fTeamMembersColors: array[0 .. MAX_HANDS - 1] of array[0 .. MAX_HANDS - 1] of Cardinal;
    fTeamMembersCounts: array[0 .. MAX_HANDS - 1] of Byte;
    fColorsToShow: array[TKMStatType] of array[0 .. MAX_HANDS - 1] of Cardinal;
    fListToShow: array[TKMStatType] of TStringList;
    fStatsValues: array[TKMStatType] of TKMStatsValues;

    fShowAIResults: Boolean;
    procedure RecreateListToShow(aStatType: TKMStatType);
    procedure BackClick(Sender: TObject);
    function DoAdjoinSameColorHand(aHandId: Integer): Boolean;
    function GetSelectedChartArmyKind: TKMChartArmyKind;
    function GetChartWares(aPlayer: TKMHandIndex; aWare: TKMWareType; aUseGDP: Boolean): TKMCardinalArray;
    function DoShowHandStats(aHandId: Integer): Boolean;

    procedure Create_ResultsMP(aParent: TKMPanel);
    procedure CreateBars(aParent: TKMPanel);
    procedure CreateChartEconomy;
    procedure CreateChartWares(aParent: TKMPanel);
    procedure CreateChartArmy(aParent: TKMPanel);

    procedure UpdateVisibleTab;
    procedure TabChange(Sender: TObject);
    procedure StatTypeChange(Sender: TObject);
    procedure BarsUpdate(aStatType: TKMStatType);
    procedure EconomyUpdate(Sender: TObject);
    procedure WareUpdate(Sender: TObject);
    procedure ArmyUpdate(Sender: TObject);

    procedure Chart_LegendClick(Sender: TObject; aLegendLineId: Integer; aLineVisible: Boolean);

    procedure RadioEconomyTypeChange(Sender: TObject);
    procedure RadioWareTypeChange(Sender: TObject);
    procedure RadioArmyTypeChange(Sender: TObject);

    function GetChartLegendDetailedTitles(aStatType: TKMStatType; aLineI: Integer): TStringArray;
    function GetChartLegendDetailedColors(aStatType: TKMStatType; aLineI: Integer): TKMCardinalArray;

    procedure Reinit;
    procedure ReinitPlayersToShow;
    procedure ReinitTeamsToShow;
    procedure ReinitBars;
    procedure ReinitChartEconomy;
    procedure ReinitChartWares;
    procedure ReinitChartArmy;
  protected
    Panel_ResultsMP: TKMPanel;
      Button_Bars,
      Button_Army,
      Button_Economy,
      Button_Wares,
      Button_Players,Button_Teams: TKMButtonFlat;
      Label_ResultsMP: TKMLabel;
      Panel_Bars: TKMPanel;
        Panel_BarsUpper, Panel_BarsLower: TKMPanel;
          Label_ResultsPlayerName1, Label_ResultsPlayerName2: array [0 .. MAX_LOBBY_PLAYERS - 1] of TKMLabel;
          Bar_Results: array [0 .. MAX_LOBBY_PLAYERS - 1, 0 .. 9] of TKMPercentBar;
          Image_ResultsRosette: array [0 .. MAX_LOBBY_PLAYERS - 1, 0 .. 9] of TKMImage;
      Panel_ChartsEconomy: TKMPanel;
        Chart_Players_Citizens: TKMChart;
        Chart_Players_Houses: TKMChart;
        Chart_Teams_Citizens: TKMChart;
        Chart_Teams_Houses: TKMChart;
        Label_NoEconomyData: TKMLabel;
        Panel_ChartEconomy_Type: TKMPanel;
          Radio_ChartEconomyType: TKMRadioGroup;
      Panel_ChartsWares: TKMPanel;
        Columnbox_Wares: TKMColumnBox;    //columnBox for Quantities charts
        Columnbox_WaresGDP: TKMColumnBox; //columnBox for GDP charts
        Charts_Wares: array[TKMStatType] of array[TKMWareType] of TKMChart; //One for each kind
        Charts_WaresGDP: array[TKMStatType] of array [0..2] of TKMChart;
        Label_NoWareData: TKMLabel;
        Panel_ChartWare_Type: TKMPanel;
          Radio_ChartWareType: TKMRadioGroup;
      Panel_ChartsArmy: TKMPanel;
        Columnbox_Army: TKMColumnBox;
        Charts_Army: array[TKMStatType] of array[TKMChartArmyKind] of array[TKMChartWarriorType] of TKMChartArmyMP;
        Label_NoArmyData: TKMLabel;
        Panel_ChartArmy_Type: TKMPanel;
          Radio_ChartArmyType: TKMRadioGroup;
      Button_Back: TKMButton;
      Button_BackToGame: TKMButton;
  public
    constructor Create(aParent: TKMPanel; aOnStopGame: TUnicodeStringWDefEvent; aOnShowSPStats: TEvent);
    destructor Destroy; override;

    property GameResultMsg: TKMGameResultMsg read fGameResultMsg;

    procedure ResetControls;
    procedure Show(aMsg: TKMGameResultMsg; aReinitLastTime: Boolean = False);
    function Visible: Boolean;
    procedure Hide;
    procedure UpdateState(aTick: Cardinal);
  end;


implementation
uses
  KM_ResTexts, KM_Game, KM_HandsCollection, KM_CommonUtils, KM_Resource, KM_ResFonts,
  KM_RenderUI, KM_Hand, KM_ResUnits,
  KM_GameTypes;


const
  PANES_TOP = 185-80;
  BAR_ROW_HEIGHT = 21;
  CHART_HEIGHT = 595;
  CHART_ECO_HEIGHT = 285;
  BACK_BTN_Y_TO_BOTTOM = 60;
  SUBMENU_RIGHT_WIDTH = 170;
  BTN_BACK_TO_GAME_LEFT = RESULTS_X_PADDING + 330;

  WARRIORS_POWER_RATES: array [WARRIOR_MIN..WARRIOR_MAX] of Single = (
    1, 2.4, 5.2,    // ut_Militia, ut_AxeFighter, ut_Swordsman
    2.2, 4,         // ut_Bowman, ut_Arbaletman
    2, 4,           // ut_Pikeman, ut_Hallebardman
    3.3, 6,         // ut_HorseScout, ut_Cavalry
    5.3, 1.5, 1.5,  // ut_Barbarian, ut_Peasant, ut_Slingshot
    5.3, 2.1        // ut_MetalBarbarian, ut_Horseman
  );

  GDPWares: array [0..2] of TKMWareType = (wt_All, wt_Warfare, wt_Food);


function GetWareIdInGDPArr(aWare: TKMWareType): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := 0 to 2 do
    if aWare = GDPWares[I] then
    begin
{'fraction_non_alphanumeric': 0.0758208571612157, 'fraction_numerical': 0.011051853755702628, 'mean_word_length': 4.035263668715626, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2390300', 'n_tokens_mistral': 5845, 'n_tokens_neox': 5466, 'n_words': 1185}