Recent

Author Topic: [SOLVED]Help: Need Advice & Guidance Please  (Read 547 times)

Aruna

  • Hero Member
  • *****
  • Posts: 658
[SOLVED]Help: Need Advice & Guidance Please
« on: May 21, 2025, 11:11:38 am »
Hi everyone, this is something I have been working on (off and on) and this is my first time using records so be gentle. I suddenly realized if I continue this way I will soon have a unmanageable piece of code that spans thousands of lines. So what I need to know is am I doing this the right way? If not what should I do  to keep things readable and manageable? It can be a useful tool I feel once completed but after adding data for just two countries and taking a second look at my code I think this may not be the best way to go about doing this? I can attach a zip if needed but the full unit is given below. Attached screenshot will give you an idea of what I am trying to accomplish.

EDIT: I just attached a zip contains the source.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Grids, StdCtrls,
  9.   ComCtrls;
  10.  
  11. type
  12.   TDemographics = record
  13.     Population, PopulationDensity, EthnicGroups, Languages, Religions,
  14.     UrbanizationRate, LiteracyRate: string;
  15.   end;
  16.  
  17.   TEconomy = record
  18.     GDP, MajorIndustries, Currency, UnemploymentRate, InflationRate: string;
  19.   end;
  20.  
  21.   TCulture = record
  22.     NationalHolidays, TraditionalFoods, ArtsAndMusic, Sports, Clothing: string;
  23.   end;
  24.  
  25.   TGovernment = record
  26.     GovernmentType, HeadOfState, HeadOfGovernment, AdministrativeDivisions, IndependenceDate: string;
  27.   end;
  28.  
  29.   TGeography = record
  30.     Area, Borders, HighestPoint, MajorRivers, Climate: string;
  31.   end;
  32.  
  33.   TInfrastructure = record
  34.     Transportation, InternetPenetration, ElectricityAccess, WaterAccess, MobileCoverage: string;
  35.   end;
  36.  
  37.   TCountry = record
  38.     Name, OfficialName, CapitalCity, Region, PhoneCode, FlagEmoji: string;
  39.     Demographics: TDemographics;
  40.     Economy: TEconomy;
  41.     Culture: TCulture;
  42.     Government: TGovernment;
  43.     Geography: TGeography;
  44.     Infrastructure: TInfrastructure;
  45.   end;
  46.  
  47.   { TForm1 }
  48.  
  49.   TForm1 = class(TForm)
  50.     memoOverview: TMemo;
  51.     memoInfrastructure: TMemo;
  52.     memoGeography: TMemo;
  53.     memoGovernment: TMemo;
  54.     memoCulture: TMemo;
  55.     memoEconomy: TMemo;
  56.     memoDemographics: TMemo;
  57.     PageControl1: TPageControl;
  58.     sgCountries: TStringGrid;
  59.  
  60.     tabCulture: TTabSheet;
  61.     tabDemographics: TTabSheet;
  62.     tabEconomy: TTabSheet;
  63.     tabGeography: TTabSheet;
  64.     tabGovernment: TTabSheet;
  65.     tabInfrastructure: TTabSheet;
  66.     tabOverview: TTabSheet;
  67.  
  68.     procedure FormCreate(Sender: TObject);
  69.     procedure sgCountriesClick(Sender: TObject);
  70.  
  71.   private
  72.     procedure FillCountryData;
  73.     procedure ShowCountryDetails(const C: TCountry);
  74.   public
  75.   end;
  76.  
  77. var
  78.   Form1: TForm1;
  79.   Countries: array of TCountry;
  80.  
  81. implementation
  82.  
  83. {$R *.lfm}
  84.  
  85. { TForm1 }
  86.  
  87. procedure TForm1.FormCreate(Sender: TObject);
  88. begin
  89.   // Configure StringGrid
  90.   sgCountries.RowCount := 3;
  91.   sgCountries.ColCount := 6;
  92.   sgCountries.FixedRows := 1;
  93.  
  94.   sgCountries.Cells[0, 0] := 'Name';
  95.   sgCountries.Cells[1, 0] := 'Official Name';
  96.   sgCountries.Cells[2, 0] := 'Capital';
  97.   sgCountries.Cells[3, 0] := 'Region';
  98.   sgCountries.Cells[4, 0] := 'Phone Code';
  99.   sgCountries.Cells[5, 0] := 'Flag';
  100.  
  101.   // Add Afghanistan
  102.   sgCountries.Cells[0, 1] := 'Afghanistan';
  103.   sgCountries.Cells[1, 1] := 'Islamic Emirate of Afghanistan';
  104.   sgCountries.Cells[2, 1] := 'Kabul';
  105.   sgCountries.Cells[3, 1] := 'Asia';
  106.   sgCountries.Cells[4, 1] := '+93';
  107.   sgCountries.Cells[5, 1] := '🇦🇫';
  108.  
  109.   // Add Albania
  110.   sgCountries.Cells[0, 2] := 'Albania';
  111.   sgCountries.Cells[1, 2] := 'Republic of Albania';
  112.   sgCountries.Cells[2, 2] := 'Tirana';
  113.   sgCountries.Cells[3, 2] := 'Europe';
  114.   sgCountries.Cells[4, 2] := '+355';
  115.   sgCountries.Cells[5, 2] := '🇦🇱';
  116.  
  117.   sgCountries.AutoSizeColumns;
  118.   FillCountryData;
  119. end;
  120.  
  121. procedure TForm1.sgCountriesClick(Sender: TObject);
  122.  
  123. var
  124.   CountryName: string;
  125.   SelectedRow: Integer;
  126.  
  127. begin
  128.   SelectedRow := sgCountries.Row;
  129.   CountryName := sgCountries.Cells[0, SelectedRow];
  130.  
  131.   writeln(SelectedRow);
  132.   writeln(CountryName);
  133.  
  134.   ShowCountryDetails(Countries[SelectedRow]);
  135.  
  136.  
  137. end;
  138.  
  139. procedure TForm1.FillCountryData;
  140. begin
  141.   SetLength(Countries, 1);
  142.  
  143.   with Countries[0] do
  144.   begin
  145.     Name := 'Afghanistan';
  146.     OfficialName := 'Islamic Emirate of Afghanistan';
  147.     CapitalCity := 'Kabul';
  148.     Region := 'Asia';
  149.     PhoneCode := '+93';
  150.     FlagEmoji := '🇦🇫';
  151.  
  152.     with Demographics do
  153.     begin
  154.       Population := '~41 million';
  155.       PopulationDensity := '~63/km²';
  156.       EthnicGroups := 'Pashtun, Tajik, Hazara, Uzbek, etc.';
  157.       Languages := 'Pashto, Dari';
  158.       Religions := 'Sunni Islam (~85%), Shia Islam (~15%)';
  159.       UrbanizationRate := '~26%';
  160.       LiteracyRate := '~38%';
  161.     end;
  162.  
  163.     with Economy do
  164.     begin
  165.       GDP := '$20 billion';
  166.       MajorIndustries := 'Agriculture, textiles, mining';
  167.       Currency := 'Afghani (AFN)';
  168.       UnemploymentRate := '~11%';
  169.       InflationRate := '~5.6%';
  170.     end;
  171.  
  172.     with Culture do
  173.     begin
  174.       NationalHolidays := 'Nowruz, Independence Day';
  175.       TraditionalFoods := 'Kabuli Pulao, Mantu';
  176.       ArtsAndMusic := 'Poetry, Rubab music';
  177.       Sports := 'Buzkashi, Cricket';
  178.       Clothing := 'Perahan Tunban, Chador';
  179.     end;
  180.  
  181.     with Government do
  182.     begin
  183.       GovernmentType := 'Islamic Emirate';
  184.       HeadOfState := 'Hibatullah Akhundzada';
  185.       HeadOfGovernment := 'Hasan Akhund';
  186.       AdministrativeDivisions := '34 provinces';
  187.       IndependenceDate := 'August 19, 1919';
  188.     end;
  189.  
  190.     with Geography do
  191.     begin
  192.       Area := '652,230 km²';
  193.       Borders := 'Iran, Pakistan, China, etc.';
  194.       HighestPoint := 'Noshaq (7,492 m)';
  195.       MajorRivers := 'Helmand, Kabul';
  196.       Climate := 'Arid, semi-arid';
  197.     end;
  198.  
  199.     with Infrastructure do
  200.     begin
  201.       Transportation := 'Few paved roads, limited rail';
  202.       InternetPenetration := '~18%';
  203.       ElectricityAccess := '~70% (urban)';
  204.       WaterAccess := '~64%';
  205.       MobileCoverage := '~89%';
  206.     end;
  207.   end;
  208. end;
  209.  
  210. procedure TForm1.ShowCountryDetails(const C: TCountry);
  211.  
  212. var
  213.   CountryName: string;
  214.   SelectedRow: Integer;
  215.  
  216. begin
  217.   SelectedRow := sgCountries.Row;
  218.   CountryName := sgCountries.Cells[0, SelectedRow];
  219.  
  220.   writeln(SelectedRow);
  221.   writeln(CountryName);
  222.  
  223.   if CountryName = 'Afghanistan' then
  224.   begin
  225.     MemoOverview.Text :=
  226.   'Country Name        : Afghanistan' + LineEnding +
  227.   'Official Name       : Islamic Republic of Afghanistan' + LineEnding +
  228.   'Flag                : 🇦🇫' + LineEnding +
  229.   'ISO Codes           : ISO 3166-1: AF / AFG' + LineEnding +
  230.   'Capital City        : Kabul' + LineEnding +
  231.   'Continent/Region    : Asia / Southern Asia' + LineEnding +
  232.   'Country Code (Phone): +93' + LineEnding +
  233.   'Currency            : Afghan Afghani (AFN)' + LineEnding +
  234.   'Time Zone(s)        : UTC+4:30' + LineEnding +
  235.   'Driving Side        : Right' + LineEnding +
  236.   'Major Cities        : Kabul, Kandahar, Herat, Mazar-i-Sharif, Jalalabad';
  237.  
  238. memoDemographics.Text :=
  239.   'Population   : ~40 million' + sLineBreak +
  240.   'Density      : ~60 people per km²' + sLineBreak +
  241.   'Ethnic Groups: Pashtun, Tajik, Hazara, Uzbek, others' + sLineBreak +
  242.   'Languages    : Dari (Persian), Pashto (both official)' + sLineBreak +
  243.   'Religions    : Islam (mostly Sunni, some Shia)' + sLineBreak +
  244.   'Urbanization : ~25%' + sLineBreak +
  245.   'Literacy Rate: ~37% (higher among males)';
  246.  
  247. memoEconomy.Text :=
  248.   'GDP: ~$20 billion USD (nominal)' + sLineBreak +
  249.   'Industries: Agriculture, mining, carpets, small-scale manufacturing' + sLineBreak +
  250.   'Currency: Afghan Afghani (AFN)' + sLineBreak +
  251.   'Unemployment: ~30–40%' + sLineBreak +
  252.   'Inflation: Varies, ~5–10%';
  253.  
  254. memoCulture.Text :=
  255.   'Holidays: Independence Day (August 19), Nowruz (Persian New Year)' + sLineBreak +
  256.   'Foods: Kabuli pulao, mantu, bolani, kebabs' + sLineBreak +
  257.   'Arts: Poetry, music, carpet weaving, miniature painting' + sLineBreak +
  258.   'Sports: Cricket, football, buzkashi (traditional horseback sport)' + sLineBreak +
  259.   'Clothing: Traditional attire like perahan tunban, chador';
  260.  
  261. memoGovernment.Text :=
  262.   'Type: De facto Islamic Emirate (Taliban control); formerly republic' + sLineBreak +
  263.   'Head of State: Hibatullah Akhundzada (Taliban leader)' + sLineBreak +
  264.   'Head of Gov: Hasan Akhund (Acting PM, Taliban)' + sLineBreak +
  265.   'Divisions: 34 provinces (wilayat)' + sLineBreak +
  266.   'Independence: August 19, 1919 (from British influence)';
  267.  
  268. memoGeography.Text :=
  269.   'Area: ~652,860 km²' + sLineBreak +
  270.   'Borders: Pakistan, Iran, Turkmenistan, Uzbekistan, Tajikistan, China' + sLineBreak +
  271.   'Highest Point: Noshaq (7,492 m)' + sLineBreak +
  272.   'Rivers: Amu Darya, Kabul River, Helmand River' + sLineBreak +
  273.   'Climate: Arid to semi-arid; hot summers, cold winters';
  274.  
  275. memoInfrastructure.Text :=
  276.   'Transport: Limited road/rail networks, major projects under development' + sLineBreak +
  277.   'Internet: Low (~15–20% penetration)' + sLineBreak +
  278.   'Electricity: ~70% access, with regional variation' + sLineBreak +
  279.   'Water: ~55% access to clean water' + sLineBreak +
  280.   'Mobile: ~90% coverage, depending on region';
  281.  
  282.   end
  283.   else if CountryName = 'Albania' then
  284.   begin
  285.     MemoOverview.Text :=
  286.       'Country Name        : Albania' + LineEnding +
  287.       'Official Name       : Republic of Albania' + LineEnding +
  288.       'Flag                : 🇦🇱' + LineEnding +
  289.       'ISO Codes           : ISO 3166-1: AL / ALB' + LineEnding +
  290.       'Capital City        : Tirana' + LineEnding +
  291.       'Continent/Region    : Europe / Southern Europe' + LineEnding +
  292.       'Country Code (Phone): +355' + LineEnding +
  293.       'Currency            : Albanian Lek (ALL)' + LineEnding +
  294.       'Time Zone(s)        : UTC+1 (Standard), UTC+2 (DST)' + LineEnding +
  295.       'Driving Side        : Right' + LineEnding +
  296.       'Major Cities        : Tirana, Durrës, Vlorë, Shkodër, Elbasan';
  297.  
  298.     memoDemographics.Text :=
  299.       'Population   : ~2.8 million' + sLineBreak +
  300.       'Density      : ~100 people per km²' + sLineBreak +
  301.       'Ethnic Groups: Albanian (~98%), Greek, others' + sLineBreak +
  302.       'Languages    : Albanian (official), Greek, others' + sLineBreak +
  303.       'Religions    : Islam, Christianity (Orthodox & Catholic), others' + sLineBreak +
  304.       'Urbanization : ~60%' + sLineBreak +
  305.       'Literacy Rate: ~98%';
  306.  
  307.     memoEconomy.Text :=
  308.       'GDP: ~$18 billion USD' + sLineBreak +
  309.       'Industries: Agriculture, energy, tourism, textiles, mining' + sLineBreak +
  310.       'Currency: Albanian Lek (ALL)' + sLineBreak +
  311.       'Unemployment: ~11%' + sLineBreak +
  312.       'Inflation: ~3.5%';
  313.  
  314.     memoCulture.Text :=
  315.       'Holidays: Independence Day (Nov 28), Liberation Day (Nov 29)' + sLineBreak +
  316.       'Foods: Tavë kosi, byrek, qofte' + sLineBreak +
  317.       'Arts: Folk music, iso-polyphony, modern art' + sLineBreak +
  318.       'Sports: Football (soccer), basketball, weightlifting' + sLineBreak +
  319.       'Clothing: Traditional dress includes xhubleta, fustanella';
  320.  
  321.     memoGovernment.Text :=
  322.       'Type: Parliamentary republic' + sLineBreak +
  323.       'Head of State: President Bajram Begaj' + sLineBreak +
  324.       'Head of Gov: Prime Minister Edi Rama' + sLineBreak +
  325.       'Divisions: 12 counties (qarqe)' + sLineBreak +
  326.       'Independence: November 28, 1912';
  327.  
  328.     memoGeography.Text :=
  329.       'Area: ~28,748 km²' + sLineBreak +
  330.       'Borders: Montenegro, Kosovo, North Macedonia, Greece' + sLineBreak +
  331.       'Highest Point: Mount Korab (2,764 m)' + sLineBreak +
  332.       'Rivers: Drin, Seman, Vjosa' + sLineBreak +
  333.       'Climate: Mediterranean; mild, wet winters and hot, dry summers';
  334.  
  335.     memoInfrastructure.Text :=
  336.       'Transport: Roads improving, limited rail, major ports in Durrës and Vlorë' + sLineBreak +
  337.       'Internet: ~75% penetration' + sLineBreak +
  338.       'Electricity: ~100% access' + sLineBreak +
  339.       'Water: ~95% access to clean water' + sLineBreak +
  340.       'Mobile: ~95% coverage';
  341.   end;
  342. end;
  343.  
  344. end.
  345.  
  346.  
« Last Edit: May 21, 2025, 05:12:05 pm by Aruna »

Nimbus

  • Jr. Member
  • **
  • Posts: 57
Re: Help: Need Advice & Guidance Please
« Reply #1 on: May 21, 2025, 11:56:48 am »
Hi Aruna,

You should definitely separate your data from the code, rather than inline everything with literals.
Put all the countries info into a separate file (can be a JSON for example), and load from there as necessary. That will keep the code clean, and you can easily add/modify info by editing the data file later.

If you still want the data to be a part of the EXE (so you don't need any extra files), you can include it as a Resource https://wiki.freepascal.org/Lazarus_Resources

Upd - another option would be at least to move the data to a separate unit, and populate right where it's declared

Code: Pascal  [Select][+][-]
  1. var
  2.   Countries: array of TCountry = (
  3.     (
  4.       Name: 'Afghanistan';
  5.       OfficialName: 'Islamic Emirate of Afghanistan';
  6.       CapitalCity: 'Kabul';
  7.       Region: 'Asia';
  8.       PhoneCode: '+93';
  9.       FlagEmoji: '🇦🇫';
  10.       Demographics: (
  11.         Population: '~41 million';
  12.         PopulationDensity: '~63/km²';
  13.         EthnicGroups: 'Pashtun, Tajik, Hazara, Uzbek, etc.';
  14.         Languages: 'Pashto, Dari';
  15.         Religions: 'Sunni Islam (~85%), Shia Islam (~15%)';
  16.         UrbanizationRate: '~26%';
  17.         LiteracyRate: '~38%';
  18.       );
  19.       Economy: (
  20.         GDP: '$20 billion';
  21.         MajorIndustries: 'Agriculture, textiles, mining';
  22.         Currency: 'Afghani (AFN)';
  23.         UnemploymentRate: '~11%';
  24.         InflationRate: '~5.6%';
  25.       );
  26.       Culture: (
  27.         NationalHolidays: 'Nowruz, Independence Day';
  28.         TraditionalFoods: 'Kabuli Pulao, Mantu';
  29.         ArtsAndMusic: 'Poetry, Rubab music';
  30.         Sports: 'Buzkashi, Cricket';
  31.         Clothing: 'Perahan Tunban, Chador';
  32.       );
  33.       Government: (
  34.         GovernmentType: 'Islamic Emirate';
  35.         HeadOfState: 'Hibatullah Akhundzada';
  36.         HeadOfGovernment: 'Hasan Akhund';
  37.         AdministrativeDivisions: '34 provinces';
  38.         IndependenceDate: 'August 19, 1919';
  39.       );
  40.       Geography: (
  41.         Area: '652,230 km²';
  42.         Borders: 'Iran, Pakistan, China, etc.';
  43.         HighestPoint: 'Noshaq (7,492 m)';
  44.         MajorRivers: 'Helmand, Kabul';
  45.         Climate: 'Arid, semi-arid';
  46.       );
  47.       Infrastructure: (
  48.         Transportation: 'Few paved roads, limited rail';
  49.         InternetPenetration: '~18%';
  50.         ElectricityAccess: '~70% (urban)';
  51.         WaterAccess: '~64%';
  52.         MobileCoverage: '~89%';
  53.       );
  54.     ),
  55.     (
  56.        Name: 'Albania';
  57.        ...
  58.     ),
  59.     ...
  60.   );
  61.  
  62.  

Also you may probably want to make the memos text to be part of the records, so you don't need that bunch of if statements in ShowCountryDetails but can simply match by country Name (or better, by selected row index).
« Last Edit: May 21, 2025, 12:22:12 pm by Nimbus »

silvercoder70

  • Full Member
  • ***
  • Posts: 190
    • Tim Coates
Re: Help: Need Advice & Guidance Please
« Reply #2 on: May 21, 2025, 01:54:26 pm »
if you have it working for one record, that is a good start.

however if you consider the number of countries and information you are storing about each country that is a fair amount of data to be setup.

here is where the painful part is going to be... (1) if you need to add a country to the dataset you would have to recompile the program, (2) if some data associated with a country changes then again you would have to recompile the program, and (3) if you wanted to add/remove information you want to display, that has its own impacts.

So...

my suggestion would be to the store the data separate from the program. That way, if you want to add or change any data, the program does not have change.

Whether you store the data in a text file (regardless of the format) or use a database - that is up to you.

Otherwise a good start.
🔥 Pascal Isn’t Dead -> See What It Can Do: @silvercoder70 on YouTube

VisualLab

  • Hero Member
  • *****
  • Posts: 686
Re: Help: Need Advice & Guidance Please
« Reply #3 on: May 21, 2025, 02:06:07 pm »
You should definitely separate your data from the code, rather than inline everything with literals.
Put all the countries info into a separate file (can be a JSON for example), and load from there as necessary. That will keep the code clean, and you can easily add/modify info by editing the data file later.

I confirm. Given the amount of data you want to process (display), this is basically the only reasonable approach. However, I prefer XML (it's easier to manually correct, in particular Lazarus has syntax highlighting, and you can also use NetBeans, which helps you find errors in XML code). And Lazarus supports XML quite well (I use it, I recommend it).

The information about a single country could be stored in an object (e.g. TCountryData), which in turn would have properties that were simple objects (e.g. TEconomyData, TCultureData, TGovernmentData, etc.). All information could be stored in a list of countries (e.g. TCountryList, where the Item property of this list would be of type TCountryData). Each class would be responsible for retrieving its portion of data from the file. The list of countries would be a container from which it would be easy to retrieve data for display. The classes that store the data (e.g. TCountryList, TCountryData, etc.) would be best placed in a separate module. In the next unit, you could place a class (e.g. TCountryPresenter) that would retrieve data from the list of countries and display it in some view, e.g. TListView, TStringGrid, etc. (not necessarily all at once).
« Last Edit: May 21, 2025, 02:08:22 pm by VisualLab »

paweld

  • Hero Member
  • *****
  • Posts: 1423
Re: Help: Need Advice & Guidance Please
« Reply #4 on: May 21, 2025, 02:54:03 pm »
I would separate the management of the list of countries into a separate unit. Personally, I prefer classes and lists to records and arrays so I changed that too.
Best regards / Pozdrawiam
paweld

Nimbus

  • Jr. Member
  • **
  • Posts: 57
Re: Help: Need Advice & Guidance Please
« Reply #5 on: May 21, 2025, 04:09:42 pm »
I guess one more way to tackle this is to go for sqlite (or an in-memory dataset, sort of TMemDataset / TBufDataset, though these are inferior to SQL IMO). This would allow to utilize the DB-aware components, instead of coding all the logic around the string grid and memos.

Aruna

  • Hero Member
  • *****
  • Posts: 658
Re: Help: Need Advice & Guidance Please
« Reply #6 on: May 21, 2025, 05:10:58 pm »
Hi @Nimbus, @silvercoder70, @VisualLab, @paweld thank you all for the helpful insights. I decided to go with what Nimbus suggested with JSON. The attached screenshot speaks for itself :) I am working on a full grid search and sort on column header click. I will release the code once completed.

TBMan

  • Full Member
  • ***
  • Posts: 178
Re: [SOLVED]Help: Need Advice & Guidance Please
« Reply #7 on: May 21, 2025, 07:26:38 pm »
Just as a general suggestion, don't forget about enumerated data types. They allow for easy data expansion.

 

TinyPortal © 2005-2018