/*
* Copyright 2015 Daniel Dittmar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dan.dit.whatsthat.preferences;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.util.Locale;
import java.util.Random;
import dan.dit.whatsthat.R;
/**
* A tongue is something a language uses to express words. A tongue consists
* of an alphabet which is a set of characters. Each character has a given probabilty
* to appear in a random text of that language.
* Created by daniel on 24.03.15.
*/
public enum Tongue {
// source https://de.wikipedia.org/wiki/Buchstabenh%C3%A4ufigkeit#Buchstabenh.C3.A4ufigkeiten_in_deutschsprachigen_Texten
// de (sums up to 99.668%; some modifications for Umlaute)
// en (without ï; sums up to 99.999%):
GERMAN("Deutsch","de", R.drawable.flag_de, "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ", new double[] {5.58,1.96,3.16,4.98,17.29,1.49,3.02,4.98,8.02,0.24,1.32,3.6,2.55,10.53,2.24,0.67,0.02,7.99,7.19,5.99,3.83,0.84,0.178,0.05,0.05,1.21,0.24,0.20,0.35}),
ENGLISH("English","en", R.drawable.flag_en, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", new double[] {8.167,1.492,2.782,4.253,12.702,2.228,2.015,6.094,6.966,0.153,0.772,4.025,2.406,6.749,7.507,1.929,0.095,5.987,6.327,9.056,2.758,0.978,2.360,0.150,1.974,0.074}),
ENGLISH_US("English", "en-us", R.drawable.flag_en_us, ENGLISH);
private String mLocalizedName;
private String mShortName; // "languagecode-countrycode" or "languagecode". The language codes: http://www.loc.gov/standards/iso639-2/php/English_list.php
private String mAlphabet;
private final double[] mLetterDistribution; // frequency distribution of letters of the alphabet
private Random mRandom;
private int mIconResId;
private Tongue mParentTongue;
Tongue(String localizedName, String shortName, int iconResId, Tongue parent) {
mLocalizedName = localizedName;
mShortName = shortName;
mIconResId = iconResId;
if (parent == null) {
throw new IllegalArgumentException("Null parent given.");
}
mParentTongue = parent;
mAlphabet = parent.mAlphabet;
mRandom = new Random();
mLetterDistribution = parent.mLetterDistribution;
}
Tongue(String localizedName, String shortName, int iconResId, String alphabet, double[] frequencies) {
mLocalizedName = localizedName;
mShortName = shortName;
mIconResId = iconResId;
mAlphabet = alphabet;
mRandom = new Random();
mLetterDistribution = new double[frequencies.length];
for (int i = 0; i < alphabet.length(); i++) {
mLetterDistribution[i] = frequencies[i] / 100.;
if (i > 0) {
mLetterDistribution[i] += mLetterDistribution[i - 1];
}
}
}
@Override
public String toString() {
return mLocalizedName + " (" + mShortName + ")";
}
/**
* Returns a random letter of this tongue distributed by the average character
* distribution of this tongue.
* @return A random letter of this tongue's alphabet.
*/
public char getRandomLetter() {
// inversion method to map uniform distribution to alphabet distribution
double rolledValue = mRandom.nextDouble();
for (int index = mLetterDistribution.length - 2; index >= 0; index--) {
// start at -2 since the last one is (>=) 1.0
if (mLetterDistribution[index] < rolledValue) {
return mAlphabet.charAt(index + 1);
}
}
return mAlphabet.charAt(0);
}
/**
* Returns the shortcut of this tongue.
* @return The tongue's shortcut.
*/
public String getShortcut() {
return mShortName;
}
/**
* Returns the localized name describing the tongue in its own tongue.
* @return The localized name.
*/
public String getLocalizedName() {
return mLocalizedName;
}
/**
* Returns the parent tongue of this tongue if any.
* @return The parent tongue.
*/
@Nullable
public Tongue getParentTongue() {
return mParentTongue;
}
/**
* Searches a tongue with the given shortcut. Not case sensitive.
* @param shortcut The tongue shortcut.
* @return The tongue whose shortcut equals the given shortcut
* or ENGLISH if the given shortcut was empty or not found.
*/
public static Tongue getByShortcut(String shortcut) {
if (TextUtils.isEmpty(shortcut)) {
return ENGLISH; // default
}
for (Tongue t : Tongue.values()) {
if (t.mShortName.equalsIgnoreCase(shortcut)) {
return t;
}
}
return ENGLISH;
}
/**
* Returns the icon resource id that describes this tongue, usually
* a flag of the country that this language origins from.
* @return An icon resource id or 0.
*/
int getIconResId() {
return mIconResId;
}
/**
* Returns the next tongue, starting from the given tongue. Cycles through all tongues.
* @param tongue The tongue to start at or null.
* @return The next tongue or ENGLISH if no tongue given.
*/
public static Tongue nextTongue(Tongue tongue) {
if (tongue == null) {
return ENGLISH;
}
int tonguesCount = Tongue.values().length;
return Tongue.values()[(tongue.ordinal() + 1) % tonguesCount];
}
/**
* Returns the tongue for the given locale if available and supported.
* @param locale The locale to search.
* @return The best matching tongue matching the locale's language (and country)
* or ENGLISH if locale not supported, not valid or no language specified.
*/
@NonNull
public static Tongue getTongueOfLocale(Locale locale) {
if (locale == null) {
return ENGLISH;
}
String language = locale.getLanguage();
if (TextUtils.isEmpty(language)) {
return ENGLISH;
}
String country = locale.getCountry();
if (!TextUtils.isEmpty(country)) {
String shortcut = language + "-" + country;
for (Tongue t : Tongue.values()) {
if (t.mShortName.equalsIgnoreCase(shortcut)) {
return t;
}
}
}
return getByShortcut(language);
}
}