2023-01-22 04:02:33 +00:00
|
|
|
using System;
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
namespace PKHeX.Core;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Geolocation Utility for Generation 6/7 (3DS) Earth location values.
|
|
|
|
/// </summary>
|
|
|
|
public static class GeoLocation
|
2018-08-26 00:04:01 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
private static readonly string[]?[] CountryList = GetCountryList();
|
2023-12-04 04:13:20 +00:00
|
|
|
private static readonly string[] lang_geo = ["ja", "en", "fr", "de", "it", "es", "zh", "ko", "zh2"];
|
2022-06-18 18:04:24 +00:00
|
|
|
private static readonly string[]?[]?[] RegionList = new string[CountryList.Length][][];
|
|
|
|
|
2022-03-06 02:13:31 +00:00
|
|
|
/// <summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
/// Returns the index of which the <see cref="language"/> is in the country/region list.
|
2022-03-06 02:13:31 +00:00
|
|
|
/// </summary>
|
2022-06-18 18:04:24 +00:00
|
|
|
public static int GetLanguageIndex(string language) => Array.IndexOf(lang_geo, language);
|
|
|
|
private static int GetLanguageIndex(LanguageID language) => GetLanguageIndex(language.GetLanguage2CharName());
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private const string INVALID = nameof(INVALID);
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private static string[]?[] GetCountryList()
|
|
|
|
{
|
|
|
|
var input = Util.GetStringList("countries");
|
|
|
|
return UnpackList(input);
|
|
|
|
}
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2023-01-22 04:02:33 +00:00
|
|
|
private static string[]?[] GetRegionList(byte country)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
var input = Util.GetStringList($"sr_{country:000}");
|
|
|
|
return UnpackList(input);
|
|
|
|
}
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2023-02-27 01:41:22 +00:00
|
|
|
private static string[]?[] UnpackList(ReadOnlySpan<string> input)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
var last = GetEntry(input[^1], out var lastIndex);
|
|
|
|
string[]?[] list = new string[lastIndex+1][];
|
|
|
|
list[lastIndex] = last;
|
2023-02-27 01:41:22 +00:00
|
|
|
foreach (var line in input[..^1])
|
2018-08-26 00:04:01 +00:00
|
|
|
{
|
2022-06-18 18:04:24 +00:00
|
|
|
var entry = GetEntry(line, out var index);
|
|
|
|
list[index] = entry;
|
2018-08-26 00:04:01 +00:00
|
|
|
}
|
2022-06-18 18:04:24 +00:00
|
|
|
return list;
|
|
|
|
}
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
private static string[] GetEntry(string line, out int index)
|
|
|
|
{
|
2023-02-27 01:41:22 +00:00
|
|
|
var entries = line.Split('\t');
|
2022-06-18 18:04:24 +00:00
|
|
|
index = int.Parse(entries[0]);
|
|
|
|
return entries;
|
|
|
|
}
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2023-01-22 04:02:33 +00:00
|
|
|
private static string GetCountryName(byte country, int l)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
if (l < 0)
|
2018-08-26 00:04:01 +00:00
|
|
|
return INVALID;
|
2022-06-18 18:04:24 +00:00
|
|
|
if ((uint)country >= CountryList.Length)
|
|
|
|
return INVALID;
|
|
|
|
var countryNames = CountryList[country];
|
2023-02-28 03:12:27 +00:00
|
|
|
if (countryNames is not null && (uint)l < countryNames.Length)
|
2022-06-18 18:04:24 +00:00
|
|
|
return countryNames[l + 1];
|
|
|
|
return INVALID;
|
|
|
|
}
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2023-01-22 04:02:33 +00:00
|
|
|
private static string GetRegionName(byte country, byte region, int l)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
if (l < 0)
|
2018-08-26 00:04:01 +00:00
|
|
|
return INVALID;
|
2022-06-18 18:04:24 +00:00
|
|
|
if ((uint)country >= RegionList.Length)
|
|
|
|
return INVALID;
|
|
|
|
var regionNames = RegionList[country] ??= GetRegionList(country);
|
|
|
|
if ((uint)region >= regionNames.Length)
|
|
|
|
return INVALID;
|
|
|
|
var localized = regionNames[region];
|
2023-02-28 03:12:27 +00:00
|
|
|
if (localized is not null && (uint)l < localized.Length)
|
2022-06-18 18:04:24 +00:00
|
|
|
return localized[l + 1];
|
|
|
|
return INVALID;
|
|
|
|
}
|
2018-08-26 00:04:01 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Gets an array of all country names for the requested <see cref="language"/>.
|
|
|
|
/// </summary>
|
|
|
|
public static string[]? GetCountryList(string language)
|
|
|
|
{
|
|
|
|
int index = GetLanguageIndex(language);
|
|
|
|
return CountryList[index];
|
|
|
|
}
|
2022-03-06 02:13:31 +00:00
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Gets the Country string for a given Country ID
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="language">Language ID</param>
|
|
|
|
/// <param name="country">Country ID</param>
|
|
|
|
/// <returns>Country ID string</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
public static string GetCountryName(string language, byte country) => GetCountryName(country, GetLanguageIndex(language));
|
2022-06-18 18:04:24 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the Region string for a specified country ID.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="language">Language ID</param>
|
|
|
|
/// <param name="country">Country ID</param>
|
|
|
|
/// <param name="region">Region ID</param>
|
|
|
|
/// <returns>Region ID string</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
public static string GetRegionName(string language, byte country, byte region) => GetRegionName(country, region, GetLanguageIndex(language));
|
2022-06-18 18:04:24 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the Country string for a given Country ID
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="language">Language ID</param>
|
|
|
|
/// <param name="country">Country ID</param>
|
|
|
|
/// <returns>Country ID string</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
public static string GetCountryName(LanguageID language, byte country) => GetCountryName(country, GetLanguageIndex(language));
|
2022-06-18 18:04:24 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the Region string for a specified country ID.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="language">Language ID</param>
|
|
|
|
/// <param name="country">Country ID</param>
|
|
|
|
/// <param name="region">Region ID</param>
|
|
|
|
/// <returns>Region ID string</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
public static string GetRegionName(LanguageID language, byte country, byte region) => GetRegionName(country, region, GetLanguageIndex(language));
|
2022-06-18 18:04:24 +00:00
|
|
|
|
2023-03-05 09:39:13 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Checks if the Country and Region exist for selection.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="country">Country ID</param>
|
|
|
|
/// <param name="region">Region ID</param>
|
|
|
|
/// <returns>True if exists</returns>
|
|
|
|
public static bool GetIsCountryRegionExist(byte country, byte region)
|
|
|
|
{
|
|
|
|
if ((uint)country >= RegionList.Length)
|
|
|
|
return false;
|
|
|
|
var regionNames = RegionList[country] ??= GetRegionList(country);
|
|
|
|
return (uint)region < regionNames.Length && regionNames[region] is not null;
|
|
|
|
}
|
|
|
|
|
2022-06-18 18:04:24 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Gets Country and Region strings for corresponding IDs and language.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="country">Country ID</param>
|
|
|
|
/// <param name="region">Region ID</param>
|
|
|
|
/// <param name="language">Language ID</param>
|
|
|
|
/// <returns>Tuple containing country and region</returns>
|
2023-01-22 04:02:33 +00:00
|
|
|
public static (string Country, string Region) GetCountryRegionText(byte country, byte region, string language)
|
2022-06-18 18:04:24 +00:00
|
|
|
{
|
|
|
|
// Get Language we're fetching for
|
|
|
|
int lang = Array.IndexOf(lang_geo, language);
|
|
|
|
var countryName = GetCountryName(country, lang);
|
|
|
|
var regionName = GetRegionName(country, region, lang);
|
|
|
|
return (countryName, regionName);
|
2018-08-26 00:04:01 +00:00
|
|
|
}
|
|
|
|
}
|