...
This commit is contained in:
@@ -18,7 +18,7 @@ for i, country in all_countries {
|
||||
|
||||
// --- Example: Find a specific country (e.g., Belgium) ---
|
||||
println('\n--- Searching for Belgium ---')
|
||||
found := false
|
||||
mut found := false
|
||||
for country in all_countries {
|
||||
if country.iso == 'BE' {
|
||||
println('Found Belgium: ${country.str()}')
|
||||
@@ -41,4 +41,10 @@ for country in all_countries {
|
||||
println('Found ${eu_countries.len} European countries.')
|
||||
// Optionally print them or process further
|
||||
|
||||
|
||||
// --- Example: Using the helper function ---
|
||||
println('\n--- Using helper function to find Japan ---')
|
||||
japan := countries.find_country_by_iso('JP') or {
|
||||
println('Error finding Japan: ${err}')
|
||||
return
|
||||
}
|
||||
println('Found Japan: ${japan.str()}')
|
||||
|
||||
77
lib/data/countries/README.md
Normal file
77
lib/data/countries/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Countries Data Module
|
||||
|
||||
This module provides access to country information data, including ISO codes, country names, continents, currencies, and more. It parses country data from a built-in dataset and makes it available through a simple API.
|
||||
|
||||
## Purpose
|
||||
|
||||
The countries module allows you to:
|
||||
- Load all country data from an embedded dataset
|
||||
- Search for specific countries by ISO code
|
||||
- Filter countries by continent or other attributes
|
||||
- Access detailed information about countries including names, codes, currencies, and more
|
||||
|
||||
## Data Source
|
||||
|
||||
The country data is sourced from GeoNames (http://www.geonames.org), containing information about countries including:
|
||||
- ISO country codes (2-letter, 3-letter, and numeric)
|
||||
- Country names and capitals
|
||||
- Continent information
|
||||
- Currency codes and names
|
||||
- Phone country codes
|
||||
- Postal code formats and regex patterns
|
||||
- Languages spoken
|
||||
- Neighboring countries
|
||||
- FIPS codes and equivalent FIPS codes
|
||||
|
||||
## Example Usage
|
||||
|
||||
```v
|
||||
import freeflowuniverse.herolib.data.countries
|
||||
|
||||
// Get all countries
|
||||
mut all_countries := countries.get_all_countries()!
|
||||
|
||||
println('Total countries loaded: ${all_countries.len}')
|
||||
|
||||
// Find a specific country by ISO code
|
||||
japan := countries.find_country_by_iso('JP')!
|
||||
println('Found Japan: ${japan.str()}')
|
||||
|
||||
// Filter countries by continent
|
||||
mut eu_countries := []countries.Country{}
|
||||
for country in all_countries {
|
||||
if country.continent == 'EU' {
|
||||
eu_countries << country
|
||||
}
|
||||
}
|
||||
println('Found ${eu_countries.len} European countries.')
|
||||
```
|
||||
|
||||
## Country Structure
|
||||
|
||||
Each country entry contains the following fields:
|
||||
|
||||
- `iso`: ISO 2-letter country code (e.g., "BE" for Belgium)
|
||||
- `iso3`: ISO 3-letter country code (e.g., "BEL" for Belgium)
|
||||
- `iso_numeric`: ISO numeric country code (e.g., "056" for Belgium)
|
||||
- `fips`: FIPS country code
|
||||
- `country_name`: Full country name
|
||||
- `capital`: Country capital city
|
||||
- `area_sqkm`: Area in square kilometers
|
||||
- `population`: Population count
|
||||
- `continent`: Continent code (e.g., "EU" for Europe, "NA" for North America)
|
||||
- `tld`: Top-level domain (e.g., ".be" for Belgium)
|
||||
- `currency_code`: Currency code (e.g., "EUR" for Euro)
|
||||
- `currency_name`: Full currency name
|
||||
- `phone`: Phone country code
|
||||
- `postal_format`: Postal code format
|
||||
- `postal_regex`: Postal code validation regex
|
||||
- `languages`: Languages spoken in the country
|
||||
- `geonameid`: GeoNames ID
|
||||
- `neighbours`: Neighboring countries (ISO codes separated by commas)
|
||||
- `equiv_fips_code`: Equivalent FIPS code
|
||||
|
||||
## Available Functions
|
||||
|
||||
- `get_all_countries()`: Returns a list of all countries in the dataset
|
||||
- `find_country_by_iso(iso_code string)`: Finds and returns a country by its 2-letter ISO code
|
||||
@@ -1,67 +1,87 @@
|
||||
module countries
|
||||
|
||||
import os
|
||||
import strings
|
||||
|
||||
// --- Embed the data file content at compile time ---
|
||||
// The path is relative to the location of this `module.v` file.
|
||||
const embedded_country_data = $embed_file('data/countryInfo.txt')
|
||||
// The path is relative to the location of this `factory.v` file.
|
||||
|
||||
|
||||
// get_all_countries parses the country data embedded in the executable.
|
||||
// It returns a list of Country structs.
|
||||
pub fn get_all_countries() ![]Country {
|
||||
mut countries_list := []Country{}
|
||||
|
||||
embedded_country_data := $embed_file('data/countryInfo.txt', .zlib).to_string()
|
||||
|
||||
// --- Parse the embedded string ---
|
||||
// Use strings.split to split the text into lines
|
||||
lines := embedded_country_data.split_into_lines()
|
||||
mut found_header := false
|
||||
|
||||
for line in lines {
|
||||
// --- Skip empty lines and comments ---
|
||||
if line == '' || line.trim_space().starts_with('#') {
|
||||
trimmed_line := line.trim_space()
|
||||
if trimmed_line == '' || trimmed_line.starts_with('#') {
|
||||
continue
|
||||
}
|
||||
|
||||
// --- Identify and skip the header ---
|
||||
// Check if this line looks like the header (contains key identifiers)
|
||||
if !found_header && line.contains('ISO') && line.contains('Country') && line.contains('CurrencyCode') {
|
||||
if !found_header && trimmed_line.contains('ISO') && trimmed_line.contains('Country') && trimmed_line.contains('CurrencyCode') {
|
||||
found_header = true
|
||||
continue // Skip the header line itself
|
||||
}
|
||||
|
||||
// --- Process data lines ---
|
||||
// Split the line by tab character
|
||||
fields := line.split('\t')
|
||||
// println("Processing line:${countries_list.len} ${line} ")
|
||||
|
||||
// --- Process data lines ---
|
||||
// Use strings.split to split the line by tab character
|
||||
fields := line.split_by_space()
|
||||
|
||||
// Ensure we have the expected number of fields (header indicates 19)
|
||||
if fields.len < 19 {
|
||||
// Handle potential parsing errors or incomplete lines
|
||||
// println('Warning: Skipping line with insufficient fields (found ${fields.len}): "${line}"')
|
||||
continue
|
||||
}
|
||||
|
||||
// --- Create Country struct instance ---
|
||||
// Map fields by index based on the header structure
|
||||
// Map fields by index based on the header structure.
|
||||
// Handle potential out-of-bounds or missing data gracefully using `or {}`.
|
||||
// The last field might sometimes be empty or missing in the data, handle it
|
||||
iso_field := fields[0] or { '' }
|
||||
iso3_field := fields[1] or { '' }
|
||||
iso_numeric_field := fields[2] or { '' }
|
||||
fips_field := fields[3] or { '' }
|
||||
country_name_field := fields[4] or { '' }
|
||||
capital_field := fields[5] or { '' }
|
||||
area_sqkm_field := fields[6] or { '' }
|
||||
population_field := fields[7] or { '' }
|
||||
continent_field := fields[8] or { '' }
|
||||
tld_field := fields[9] or { '' }
|
||||
currency_code_field := fields[10] or { '' }
|
||||
currency_name_field := fields[11] or { '' }
|
||||
phone_field := fields[12] or { '' }
|
||||
postal_format_field := fields[13] or { '' }
|
||||
postal_regex_field := fields[14] or { '' }
|
||||
languages_field := fields[15] or { '' }
|
||||
geonameid_field := fields[16] or { '' }
|
||||
neighbours_field := fields[17] or { '' }
|
||||
equiv_fips_code_field := fields[18] or { '' }
|
||||
|
||||
country := Country{
|
||||
iso: fields[0].trim_space()
|
||||
iso3: fields[1].trim_space()
|
||||
iso_numeric: fields[2].trim_space()
|
||||
fips: fields[3].trim_space()
|
||||
country_name: fields[4].trim_space()
|
||||
capital: fields[5].trim_space()
|
||||
area_sqkm: fields[6].trim_space()
|
||||
population: fields[7].trim_space()
|
||||
continent: fields[8].trim_space()
|
||||
tld: fields[9].trim_space()
|
||||
currency_code: fields[10].trim_space()
|
||||
currency_name: fields[11].trim_space()
|
||||
phone: fields[12].trim_space()
|
||||
postal_format: fields[13].trim_space()
|
||||
postal_regex: fields[14].trim_space()
|
||||
languages: fields[15].trim_space()
|
||||
geonameid: fields[16].trim_space()
|
||||
neighbours: fields[17].trim_space()
|
||||
equiv_fips_code: fields[18].trim_space() // Handle potential trailing empty fields or newlines
|
||||
iso: iso_field.trim_space()
|
||||
iso3: iso3_field.trim_space()
|
||||
iso_numeric: iso_numeric_field.trim_space()
|
||||
fips: fips_field.trim_space()
|
||||
country_name: country_name_field.trim_space()
|
||||
capital: capital_field.trim_space()
|
||||
area_sqkm: area_sqkm_field.trim_space()
|
||||
population: population_field.trim_space()
|
||||
continent: continent_field.trim_space()
|
||||
tld: tld_field.trim_space()
|
||||
currency_code: currency_code_field.trim_space()
|
||||
currency_name: currency_name_field.trim_space()
|
||||
phone: phone_field.trim_space()
|
||||
postal_format: postal_format_field.trim_space()
|
||||
postal_regex: postal_regex_field.trim_space()
|
||||
languages: languages_field.trim_space()
|
||||
geonameid: geonameid_field.trim_space()
|
||||
neighbours: neighbours_field.trim_space()
|
||||
equiv_fips_code: equiv_fips_code_field.trim_space()
|
||||
}
|
||||
|
||||
// --- Append to list ---
|
||||
@@ -70,3 +90,14 @@ pub fn get_all_countries() ![]Country {
|
||||
|
||||
return countries_list
|
||||
}
|
||||
|
||||
// Optional: Helper function to find a country by ISO code
|
||||
pub fn find_country_by_iso(iso_code string) !Country {
|
||||
countries := get_all_countries()!
|
||||
for country in countries {
|
||||
if country.iso == iso_code {
|
||||
return country
|
||||
}
|
||||
}
|
||||
return error('Country with ISO code "${iso_code}" not found')
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ module countries
|
||||
|
||||
// Country represents a country entry from countryInfo.txt
|
||||
pub struct Country {
|
||||
pub:
|
||||
iso string // ISO
|
||||
iso3 string // ISO3
|
||||
iso_numeric string // ISO-Numeric
|
||||
|
||||
Reference in New Issue
Block a user