2016-07-09 22:30:12 +00:00
using System ;
using System.Collections.Generic ;
2017-07-02 02:43:51 +00:00
using System.Diagnostics ;
2017-10-23 18:18:44 +00:00
using System.IO ;
2016-07-09 22:30:12 +00:00
using System.Linq ;
2017-05-12 04:34:18 +00:00
using System.Reflection ;
2016-07-09 22:30:12 +00:00
2017-01-08 07:54:09 +00:00
namespace PKHeX.Core
2016-07-09 22:30:12 +00:00
{
2018-05-12 19:28:48 +00:00
public static partial class Util
2016-07-09 22:30:12 +00:00
{
2017-03-24 17:59:45 +00:00
private const string TranslationSplitter = " = " ;
2017-11-03 03:39:38 +00:00
private static readonly Assembly thisAssembly = typeof ( Util ) . GetTypeInfo ( ) . Assembly ;
private static readonly string [ ] manifestResourceNames = thisAssembly . GetManifestResourceNames ( ) ;
private static readonly Dictionary < string , string > resourceNameMap = new Dictionary < string , string > ( ) ;
private static readonly Dictionary < string , string [ ] > stringListCache = new Dictionary < string , string [ ] > ( ) ;
2017-03-24 17:59:45 +00:00
2018-05-12 19:28:48 +00:00
#region String Lists
2016-10-06 04:06:24 +00:00
2016-08-08 20:11:02 +00:00
/// <summary>
/// Gets a list of all Pokémon species names.
/// </summary>
/// <param name="language">Language of the Pokémon species names to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each Pokémon species name.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetSpeciesList ( string language ) = > GetStringList ( "species" , language ) ;
2016-08-08 20:11:02 +00:00
/// <summary>
/// Gets a list of all move names.
/// </summary>
/// <param name="language">Language of the move names to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each move name.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetMovesList ( string language ) = > GetStringList ( "moves" , language ) ;
2016-08-08 20:11:02 +00:00
/// <summary>
/// Gets a list of all Pokémon ability names.
/// </summary>
/// <param name="language">Language of the Pokémon ability names to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each Pokémon ability name.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetAbilitiesList ( string language ) = > GetStringList ( "abilities" , language ) ;
2016-08-08 20:11:02 +00:00
2016-10-06 04:06:24 +00:00
/// <summary>
/// Gets a list of all Pokémon nature names.
/// </summary>
/// <param name="language">Language of the Pokémon nature names to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each Pokémon nature name.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetNaturesList ( string language ) = > GetStringList ( "natures" , language ) ;
2016-10-06 04:06:24 +00:00
/// <summary>
/// Gets a list of all Pokémon form names.
/// </summary>
/// <param name="language">Language of the Pokémon form names to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each Pokémon form name.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetFormsList ( string language ) = > GetStringList ( "forms" , language ) ;
2016-10-06 04:06:24 +00:00
/// <summary>
/// Gets a list of all Pokémon type names.
/// </summary>
/// <param name="language">Language of the Pokémon type names to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each Pokémon type name.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetTypesList ( string language ) = > GetStringList ( "types" , language ) ;
2016-10-06 04:06:24 +00:00
/// <summary>
/// Gets a list of all Pokémon characteristic.
/// </summary>
/// <param name="language">Language of the Pokémon characteristic to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each Pokémon characteristic.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetCharacteristicsList ( string language ) = > GetStringList ( "character" , language ) ;
2016-10-06 04:06:24 +00:00
/// <summary>
/// Gets a list of all items.
/// </summary>
/// <param name="language">Language of the items to select (e.g. "en", "fr", "jp", etc.)</param>
/// <returns>An array of strings whose indexes correspond to the IDs of each item.</returns>
2017-10-12 03:00:18 +00:00
public static string [ ] GetItemsList ( string language ) = > GetStringList ( "items" , language ) ;
2016-10-06 04:06:24 +00:00
#endregion
2017-06-18 01:37:19 +00:00
public static string [ ] GetStringList ( string f )
2016-07-09 22:30:12 +00:00
{
2017-11-02 02:34:01 +00:00
if ( stringListCache . ContainsKey ( f ) )
2017-11-08 01:12:04 +00:00
return ( string [ ] ) stringListCache [ f ] . Clone ( ) ;
2017-11-02 02:34:01 +00:00
2017-10-23 18:18:44 +00:00
var txt = GetStringResource ( f ) ; // Fetch File, \n to list.
2018-08-02 01:30:51 +00:00
if ( txt = = null ) return Array . Empty < string > ( ) ;
2017-09-30 05:58:25 +00:00
string [ ] rawlist = txt . Split ( '\n' ) ;
2016-07-09 22:30:12 +00:00
for ( int i = 0 ; i < rawlist . Length ; i + + )
2018-05-25 04:16:55 +00:00
rawlist [ i ] = rawlist [ i ] . TrimEnd ( '\r' ) ;
2017-11-02 02:42:12 +00:00
stringListCache . Add ( f , rawlist ) ;
2017-11-08 01:12:04 +00:00
return ( string [ ] ) rawlist . Clone ( ) ;
2016-07-09 22:30:12 +00:00
}
2018-07-29 20:27:48 +00:00
2017-10-12 03:00:18 +00:00
public static string [ ] GetStringList ( string f , string l , string type = "text" ) = > GetStringList ( $"{type}_{f}_{l}" ) ;
2018-07-29 20:27:48 +00:00
2017-06-18 01:37:19 +00:00
public static string [ ] GetNulledStringArray ( string [ ] SimpleStringList )
2016-07-09 22:30:12 +00:00
{
try
{
2017-09-30 08:07:30 +00:00
int len = ToInt32 ( SimpleStringList . Last ( ) . Split ( ',' ) [ 0 ] ) + 1 ;
string [ ] newlist = new string [ len ] ;
2016-07-09 22:30:12 +00:00
for ( int i = 1 ; i < SimpleStringList . Length ; i + + )
2017-09-30 08:07:30 +00:00
{
var split = SimpleStringList [ i ] . Split ( ',' ) ;
newlist [ ToInt32 ( split [ 0 ] ) ] = split [ 1 ] ;
}
2016-07-09 22:30:12 +00:00
return newlist ;
}
catch { return null ; }
}
2017-03-24 17:59:45 +00:00
2017-06-18 01:37:19 +00:00
public static byte [ ] GetBinaryResource ( string name )
2017-05-12 04:34:18 +00:00
{
2017-11-02 02:34:01 +00:00
using ( var resource = thisAssembly . GetManifestResourceStream (
2017-09-30 05:58:25 +00:00
$"PKHeX.Core.Resources.byte.{name}" ) )
2017-05-12 04:34:18 +00:00
{
var buffer = new byte [ resource . Length ] ;
resource . Read ( buffer , 0 , ( int ) resource . Length ) ;
return buffer ;
2017-10-23 18:18:44 +00:00
}
}
public static string GetStringResource ( string name )
{
2017-11-02 02:47:55 +00:00
if ( ! resourceNameMap . ContainsKey ( name ) )
2018-05-12 19:28:48 +00:00
{
bool Match ( string x ) = > x . StartsWith ( "PKHeX.Core.Resources.text." ) & & x . EndsWith ( $"{name}.txt" , StringComparison . OrdinalIgnoreCase ) ;
var resname = Array . Find ( manifestResourceNames , Match ) ;
resourceNameMap . Add ( name , resname ) ;
}
2017-11-02 02:44:35 +00:00
2017-11-03 03:39:38 +00:00
if ( resourceNameMap [ name ] = = null )
2017-11-02 02:44:35 +00:00
return null ;
2017-11-02 02:47:55 +00:00
using ( var resource = thisAssembly . GetManifestResourceStream ( resourceNameMap [ name ] ) )
2017-10-23 18:18:44 +00:00
using ( var reader = new StreamReader ( resource ) )
return reader . ReadToEnd ( ) ;
2017-05-12 04:34:18 +00:00
}
2017-03-25 01:23:39 +00:00
#region Non - Form Translation
2017-03-24 17:59:45 +00:00
/// <summary>
/// Gets the names of the properties defined in the given input
/// </summary>
/// <param name="input">Enumerable of translation definitions in the form "Property = Value".</param>
/// <returns></returns>
2017-06-18 01:37:19 +00:00
private static string [ ] GetProperties ( IEnumerable < string > input )
2017-03-24 17:59:45 +00:00
{
return input . Select ( l = > l . Substring ( 0 , l . IndexOf ( TranslationSplitter , StringComparison . Ordinal ) ) ) . ToArray ( ) ;
}
private static IEnumerable < string > DumpStrings ( Type t )
{
2018-04-08 16:19:19 +00:00
var props = ReflectUtil . GetPropertiesStartWithPrefix ( t , "" ) ;
2018-05-12 19:28:48 +00:00
return props . Select ( p = > $"{p}{TranslationSplitter}{ReflectUtil.GetValue(t, p)}" ) ;
2017-03-24 17:59:45 +00:00
}
/// <summary>
/// Gets the current localization in a static class containing language-specific strings
/// </summary>
2018-05-12 19:28:48 +00:00
/// <param name="t"></param>
/// <param name="existingLines">Existing localization lines (if provided)</param>
2017-06-18 01:37:19 +00:00
public static string [ ] GetLocalization ( Type t , string [ ] existingLines = null )
2017-03-24 17:59:45 +00:00
{
var currentLines = DumpStrings ( t ) . ToArray ( ) ;
2018-06-01 05:40:55 +00:00
if ( existingLines = = null )
return currentLines ;
2017-06-18 01:37:19 +00:00
var existing = GetProperties ( existingLines ) ;
var current = GetProperties ( currentLines ) ;
2017-03-24 17:59:45 +00:00
var result = new string [ currentLines . Length ] ;
for ( int i = 0 ; i < current . Length ; i + + )
{
int index = Array . IndexOf ( existing , current [ i ] ) ;
result [ i ] = index < 0 ? currentLines [ i ] : existingLines [ index ] ;
}
return result ;
}
/// <summary>
/// Applies localization to a static class containing language-specific strings.
/// </summary>
2017-03-25 01:23:39 +00:00
/// <param name="t">Type of the static class containing the desired strings.</param>
2017-03-24 17:59:45 +00:00
/// <param name="lines">Lines containing the localized strings</param>
2017-06-18 01:37:19 +00:00
private static void SetLocalization ( Type t , IEnumerable < string > lines )
2018-05-12 15:13:39 +00:00
{
2017-03-24 17:59:45 +00:00
if ( lines = = null )
return ;
foreach ( var line in lines . Where ( l = > l ! = null ) )
{
var index = line . IndexOf ( TranslationSplitter , StringComparison . Ordinal ) ;
if ( index < 0 )
continue ;
var prop = line . Substring ( 0 , index ) ;
var value = line . Substring ( index + TranslationSplitter . Length ) ;
try
{
2018-04-08 16:19:19 +00:00
ReflectUtil . SetValue ( t , prop , value ) ;
2017-03-24 17:59:45 +00:00
}
catch
{
2017-07-02 02:43:51 +00:00
Debug . WriteLine ( $"Property not present: {prop} || Value written: {value}" ) ;
2017-03-24 17:59:45 +00:00
}
}
}
/// <summary>
/// Applies localization to a static class containing language-specific strings.
/// </summary>
2017-03-25 01:23:39 +00:00
/// <param name="t">Type of the static class containing the desired strings.</param>
2017-03-24 17:59:45 +00:00
/// <param name="languageFilePrefix">Prefix of the language file to use. Example: if the target is legality_en.txt, <paramref name="languageFilePrefix"/> should be "legality".</param>
2017-05-12 16:33:12 +00:00
/// <param name="currentCultureCode">Culture information</param>
2017-06-18 01:37:19 +00:00
private static void SetLocalization ( Type t , string languageFilePrefix , string currentCultureCode )
2017-03-24 17:59:45 +00:00
{
2017-06-18 01:37:19 +00:00
SetLocalization ( t , GetStringList ( $"{languageFilePrefix}_{currentCultureCode}" ) ) ;
2017-03-24 17:59:45 +00:00
}
/// <summary>
/// Applies localization to a static class containing language-specific strings.
/// </summary>
2017-03-25 01:23:39 +00:00
/// <param name="t">Type of the static class containing the desired strings.</param>
2017-03-24 17:59:45 +00:00
/// <remarks>The values used to translate the given static class are retrieved from [TypeName]_[CurrentLangCode2].txt in the resource manager of PKHeX.Core.</remarks>
2017-05-12 16:33:12 +00:00
/// <param name="currentCultureCode">Culture information</param>
2017-06-18 01:37:19 +00:00
public static void SetLocalization ( Type t , string currentCultureCode )
2017-03-24 17:59:45 +00:00
{
2017-06-18 01:37:19 +00:00
SetLocalization ( t , t . Name , currentCultureCode ) ;
2017-03-24 17:59:45 +00:00
}
2017-03-25 01:23:39 +00:00
#endregion
2017-03-24 17:59:45 +00:00
2016-10-06 04:06:24 +00:00
#region DataSource Providing
2017-06-18 01:37:19 +00:00
public static List < ComboItem > GetCBList ( string textfile , string lang )
2016-07-09 22:30:12 +00:00
{
// Set up
2017-06-18 01:37:19 +00:00
string [ ] inputCSV = GetStringList ( textfile ) ;
2016-07-09 22:30:12 +00:00
// Get Language we're fetching for
int index = Array . IndexOf ( new [ ] { "ja" , "en" , "fr" , "de" , "it" , "es" , "ko" , "zh" , } , lang ) ;
// Gather our data from the input file
2017-09-30 08:07:30 +00:00
return inputCSV . Skip ( 1 )
. Select ( entry = > entry . Split ( ',' ) )
. Select ( data = > new ComboItem { Text = data [ 1 + index ] , Value = Convert . ToInt32 ( data [ 0 ] ) } )
. OrderBy ( z = > z . Text )
. ToList ( ) ;
}
2018-07-29 20:27:48 +00:00
2017-09-30 08:07:30 +00:00
public static List < ComboItem > GetUnsortedCBList ( string textfile )
{
string [ ] inputCSV = GetStringList ( textfile ) ;
return inputCSV . Skip ( 1 )
. Select ( entry = > entry . Split ( ',' ) )
. Select ( data = > new ComboItem { Text = data [ 1 ] , Value = Convert . ToInt32 ( data [ 0 ] ) } )
. ToList ( ) ;
2016-07-09 22:30:12 +00:00
}
2018-07-29 20:27:48 +00:00
2018-06-30 16:59:48 +00:00
public static List < ComboItem > GetCBList ( IReadOnlyList < string > inStrings , params int [ ] [ ] allowed )
2016-07-09 22:30:12 +00:00
{
2017-12-05 04:16:54 +00:00
if ( allowed ? [ 0 ] = = null )
2018-06-30 16:59:48 +00:00
allowed = new [ ] { Enumerable . Range ( 0 , inStrings . Count ) . ToArray ( ) } ;
2016-07-09 22:30:12 +00:00
2017-09-30 08:07:30 +00:00
return allowed . SelectMany ( list = > list
. Select ( z = > new ComboItem { Text = inStrings [ z ] , Value = z } )
. OrderBy ( z = > z . Text ) )
. ToList ( ) ;
2016-07-09 22:30:12 +00:00
}
2018-07-29 20:27:48 +00:00
2018-06-30 16:59:48 +00:00
public static List < ComboItem > GetOffsetCBList ( List < ComboItem > cbList , IReadOnlyList < string > inStrings , int offset , IEnumerable < int > allowed )
2016-07-09 22:30:12 +00:00
{
2017-09-30 08:07:30 +00:00
var list = allowed
2018-05-12 19:28:48 +00:00
. Select ( z = > new ComboItem { Text = inStrings [ z - offset ] , Value = z } )
2017-09-30 08:07:30 +00:00
. OrderBy ( z = > z . Text ) ;
2016-07-09 22:30:12 +00:00
2017-09-30 08:07:30 +00:00
cbList . AddRange ( list ) ;
2016-07-09 22:30:12 +00:00
return cbList ;
}
2018-07-29 20:27:48 +00:00
2017-09-30 08:07:30 +00:00
public static List < ComboItem > GetVariedCBListBall ( string [ ] inStrings , int [ ] stringNum , int [ ] stringVal )
2016-07-09 22:30:12 +00:00
{
2017-09-30 08:07:30 +00:00
// First 3 Balls are always first
2018-09-02 02:55:08 +00:00
var newlist = new List < ComboItem > ( 3 + stringNum . Length )
{
new ComboItem { Text = inStrings [ 4 ] , Value = ( int ) Ball . Poke } ,
new ComboItem { Text = inStrings [ 3 ] , Value = ( int ) Ball . Great } ,
new ComboItem { Text = inStrings [ 2 ] , Value = ( int ) Ball . Ultra } ,
} ;
2016-07-09 22:30:12 +00:00
2018-09-02 02:55:08 +00:00
var ordered = stringNum
. Select ( ( z , i ) = > new ComboItem { Text = inStrings [ z ] , Value = stringVal [ i ] } )
. OrderBy ( z = > z . Text ) ;
newlist . AddRange ( ordered ) ;
2016-07-09 22:30:12 +00:00
return newlist ;
}
2016-10-06 04:06:24 +00:00
#endregion
2016-07-09 22:30:12 +00:00
}
}