Skip to content

Commit

Permalink
feat: replace ssn country with locale (cieslarmichal#864)
Browse files Browse the repository at this point in the history
  • Loading branch information
cieslarmichal authored Aug 20, 2024
1 parent 4dd9981 commit 6336aca
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 162 deletions.
19 changes: 3 additions & 16 deletions include/faker-cxx/person.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
namespace faker::person
{
enum class Sex;
enum class SsnCountry;
enum class Language;

/**
Expand Down Expand Up @@ -204,16 +203,16 @@ FAKER_CXX_EXPORT std::string_view nationality();
/**
* @brief Returns a random SSN.
*
* @param country The optional country to use.
* @param locale The optional locale to use. Defaults to `Locale::en_US`.
*
* @returns Social Security Number.
*
* @code
* faker::person::ssn() // "437-12-6854"
* faker::person::ssn(SsnCountry::Polish) // "95111901567"
* faker::person::ssn(Locale::pl_PL) // "95111901567"
* @endcode
*/
FAKER_CXX_EXPORT std::string ssn(std::optional<SsnCountry> country = std::nullopt);
FAKER_CXX_EXPORT std::string ssn(Locale locale = Locale::en_US);

/**
* @brief Returns a random Western Zodiac
Expand Down Expand Up @@ -256,18 +255,6 @@ enum class Sex
Male,
};

enum class SsnCountry
{
England,
France,
Germany,
India,
Italy,
Poland,
Spain,
Usa,
};

enum class Language
{
Albanian,
Expand Down
69 changes: 69 additions & 0 deletions include/faker-cxx/types/locale.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#pragma once

#include <string>
#include <unordered_map>
#include <vector>

namespace faker
{
enum class Locale
{
af_ZA, // Afrikaans, South Africa
Expand Down Expand Up @@ -129,3 +135,66 @@ enum class Locale
zh_SG, // Chinese, Singapore
zh_TW // Traditional Chinese, Taiwan
};

const std::vector<Locale> locales{
Locale::af_ZA, Locale::ar_AE, Locale::ar_BH, Locale::ar_DZ, Locale::ar_EG, Locale::ar_IQ, Locale::ar_JO,
Locale::ar_KW, Locale::ar_LY, Locale::ar_MA, Locale::ar_OM, Locale::ar_QA, Locale::ar_SA, Locale::ar_TN,
Locale::ar_YE, Locale::as_IN, Locale::az_AZ, Locale::be_BY, Locale::bg_BG, Locale::bn_IN, Locale::bs_BA,
Locale::ca_ES, Locale::cs_CZ, Locale::da_DK, Locale::de_AT, Locale::de_BE, Locale::de_CH, Locale::de_DE,
Locale::de_LI, Locale::de_LU, Locale::el_CY, Locale::el_GR, Locale::en_AU, Locale::en_BW, Locale::en_CA,
Locale::en_GB, Locale::en_HK, Locale::en_IE, Locale::en_IN, Locale::en_MT, Locale::en_NZ, Locale::en_PH,
Locale::en_SG, Locale::en_US, Locale::en_ZW, Locale::es_AR, Locale::es_BO, Locale::es_CL, Locale::es_CO,
Locale::es_CR, Locale::es_DO, Locale::es_EC, Locale::es_ES, Locale::es_GT, Locale::es_HN, Locale::es_MX,
Locale::es_NI, Locale::es_PA, Locale::es_PE, Locale::es_PR, Locale::es_PY, Locale::es_SV, Locale::es_US,
Locale::es_UY, Locale::es_VE, Locale::et_EE, Locale::fi_FI, Locale::fr_BE, Locale::fr_CA, Locale::fr_CH,
Locale::fr_FR, Locale::fr_LU, Locale::gu_IN, Locale::he_IL, Locale::hi_IN, Locale::hr_HR, Locale::hu_HU,
Locale::hy_AM, Locale::id_ID, Locale::is_IS, Locale::it_CH, Locale::it_IT, Locale::ja_JP, Locale::ka_GE,
Locale::kk_KZ, Locale::kn_IN, Locale::ko_KR, Locale::ks_IN, Locale::ku_TR, Locale::ky_KG, Locale::lt_LT,
Locale::lv_LV, Locale::mk_MK, Locale::ml_IN, Locale::mr_IN, Locale::ms_MY, Locale::mt_MT, Locale::nb_NO,
Locale::nl_BE, Locale::nl_NL, Locale::nn_NO, Locale::or_IN, Locale::pa_IN, Locale::pl_PL, Locale::pt_BR,
Locale::pt_PT, Locale::ro_RO, Locale::ru_RU, Locale::ru_UA, Locale::sa_IN, Locale::sk_SK, Locale::sl_SI,
Locale::sq_AL, Locale::sr_ME, Locale::sr_RS, Locale::sv_SE, Locale::ta_IN, Locale::te_IN, Locale::th_TH,
Locale::tr_TR, Locale::uk_UA, Locale::vi_VN, Locale::zh_CN, Locale::zh_HK, Locale::zh_SG, Locale::zh_TW,
};

inline std::string toString(Locale locale)
{
std::unordered_map<Locale, std::string> localeToStringMapping{
{Locale::af_ZA, "af_ZA"}, {Locale::ar_AE, "ar_AE"}, {Locale::ar_BH, "ar_BH"}, {Locale::ar_DZ, "ar_DZ"},
{Locale::ar_EG, "ar_EG"}, {Locale::ar_IQ, "ar_IQ"}, {Locale::ar_JO, "ar_JO"}, {Locale::ar_KW, "ar_KW"},
{Locale::ar_LY, "ar_LY"}, {Locale::ar_MA, "ar_MA"}, {Locale::ar_OM, "ar_OM"}, {Locale::ar_QA, "ar_QA"},
{Locale::ar_SA, "ar_SA"}, {Locale::ar_TN, "ar_TN"}, {Locale::ar_YE, "ar_YE"}, {Locale::as_IN, "as_IN"},
{Locale::az_AZ, "az_AZ"}, {Locale::be_BY, "be_BY"}, {Locale::bg_BG, "bg_BG"}, {Locale::bn_IN, "bn_IN"},
{Locale::bs_BA, "bs_BA"}, {Locale::ca_ES, "ca_ES"}, {Locale::cs_CZ, "cs_CZ"}, {Locale::da_DK, "da_DK"},
{Locale::de_AT, "de_AT"}, {Locale::de_BE, "de_BE"}, {Locale::de_CH, "de_CH"}, {Locale::de_DE, "de_DE"},
{Locale::de_LI, "de_LI"}, {Locale::de_LU, "de_LU"}, {Locale::el_CY, "el_CY"}, {Locale::el_GR, "el_GR"},
{Locale::en_AU, "en_AU"}, {Locale::en_BW, "en_BW"}, {Locale::en_CA, "en_CA"}, {Locale::en_GB, "en_GB"},
{Locale::en_HK, "en_HK"}, {Locale::en_IE, "en_IE"}, {Locale::en_IN, "en_IN"}, {Locale::en_MT, "en_MT"},
{Locale::en_NZ, "en_NZ"}, {Locale::en_PH, "en_PH"}, {Locale::en_SG, "en_SG"}, {Locale::en_US, "en_US"},
{Locale::en_ZW, "en_ZW"}, {Locale::es_AR, "es_AR"}, {Locale::es_BO, "es_BO"}, {Locale::es_CL, "es_CL"},
{Locale::es_CO, "es_CO"}, {Locale::es_CR, "es_CR"}, {Locale::es_DO, "es_DO"}, {Locale::es_EC, "es_EC"},
{Locale::es_ES, "es_ES"}, {Locale::es_GT, "es_GT"}, {Locale::es_HN, "es_HN"}, {Locale::es_MX, "es_MX"},
{Locale::es_NI, "es_NI"}, {Locale::es_PA, "es_PA"}, {Locale::es_PE, "es_PE"}, {Locale::es_PR, "es_PR"},
{Locale::es_PY, "es_PY"}, {Locale::es_SV, "es_SV"}, {Locale::es_US, "es_US"}, {Locale::es_UY, "es_UY"},
{Locale::es_VE, "es_VE"}, {Locale::et_EE, "et_EE"}, {Locale::fi_FI, "fi_FI"}, {Locale::fr_BE, "fr_BE"},
{Locale::fr_CA, "fr_CA"}, {Locale::fr_CH, "fr_CH"}, {Locale::fr_FR, "fr_FR"}, {Locale::fr_LU, "fr_LU"},
{Locale::gu_IN, "gu_IN"}, {Locale::he_IL, "he_IL"}, {Locale::hi_IN, "hi_IN"}, {Locale::hr_HR, "hr_HR"},
{Locale::hu_HU, "hu_HU"}, {Locale::hy_AM, "hy_AM"}, {Locale::id_ID, "id_ID"}, {Locale::is_IS, "is_IS"},
{Locale::it_CH, "it_CH"}, {Locale::it_IT, "it_IT"}, {Locale::ja_JP, "ja_JP"}, {Locale::ka_GE, "ka_GE"},
{Locale::kk_KZ, "kk_KZ"}, {Locale::kn_IN, "kn_IN"}, {Locale::ko_KR, "ko_KR"}, {Locale::ks_IN, "ks_IN"},
{Locale::ku_TR, "ku_TR"}, {Locale::ky_KG, "ky_KG"}, {Locale::lt_LT, "lt_LT"}, {Locale::lv_LV, "lv_LV"},
{Locale::mk_MK, "mk_MK"}, {Locale::ml_IN, "ml_IN"}, {Locale::mr_IN, "mr_IN"}, {Locale::ms_MY, "ms_MY"},
{Locale::mt_MT, "mt_MT"}, {Locale::nb_NO, "nb_NO"}, {Locale::nl_BE, "nl_BE"}, {Locale::nl_NL, "nl_NL"},
{Locale::nn_NO, "nn_NO"}, {Locale::or_IN, "or_IN"}, {Locale::pa_IN, "pa_IN"}, {Locale::pl_PL, "pl_PL"},
{Locale::pt_BR, "pt_BR"}, {Locale::pt_PT, "pt_PT"}, {Locale::ro_RO, "ro_RO"}, {Locale::ru_RU, "ru_RU"},
{Locale::ru_UA, "ru_UA"}, {Locale::sa_IN, "sa_IN"}, {Locale::sk_SK, "sk_SK"}, {Locale::sl_SI, "sl_SI"},
{Locale::sq_AL, "sq_AL"}, {Locale::sr_ME, "sr_ME"}, {Locale::sr_RS, "sr_RS"}, {Locale::sv_SE, "sv_SE"},
{Locale::ta_IN, "ta_IN"}, {Locale::te_IN, "te_IN"}, {Locale::th_TH, "th_TH"}, {Locale::tr_TR, "tr_TR"},
{Locale::uk_UA, "uk_UA"}, {Locale::vi_VN, "vi_VN"}, {Locale::zh_CN, "zh_CN"}, {Locale::zh_HK, "zh_HK"},
{Locale::zh_SG, "zh_SG"}, {Locale::zh_TW, "zh_TW"},
};

return localeToStringMapping.at(locale);
}

}
15 changes: 5 additions & 10 deletions src/modules/person.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ namespace faker::person
{
namespace
{
const std::unordered_map<Locale, std::string_view> passportFormats{
{Locale::es_US, "AA0000000"}, {Locale::en_US, "AA0000000"}, {Locale::pl_PL, "AA0000000"},
{Locale::fr_FR, "00AA00000"}, {Locale::ro_RO, "00000000"},
};

const struct PeopleNames& getPeopleNamesByCountry(const Country& country)
{
switch (country)
Expand Down Expand Up @@ -394,11 +389,10 @@ std::string_view nationality()
return helper::randomElement(nationalities);
}

std::string ssn(std::optional<SsnCountry> country)
std::string ssn(Locale locale)
{
const auto ssnCountry = country ? *country : helper::randomElement(supportedSsnCountries);

const auto& ssnFormat = std::string{ssnFormats.at(ssnCountry)};
const auto& ssnFormat =
std::string{ssnFormats.contains(locale) ? ssnFormats.at(locale) : ssnFormats.at(Locale::en_US)};

auto ssnWithoutRegexes = helper::regexpStyleStringParse(ssnFormat);

Expand Down Expand Up @@ -439,7 +433,8 @@ std::string_view chineseZodiac()

std::string passport(Locale locale)
{
const auto& passportFormat = passportFormats.at(locale);
const auto& passportFormat =
passportFormats.contains(locale) ? passportFormats.at(locale) : passportFormats.at(Locale::en_US);

std::string passportNumber;

Expand Down
172 changes: 61 additions & 111 deletions src/modules/person_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <vector>

#include "faker-cxx/person.h"
#include "faker-cxx/types/locale.h"

namespace faker::person
{
Expand Down Expand Up @@ -50,85 +51,10 @@ const auto bioFormats = std::to_array<std::string_view>(
"{bio_part}, {bio_part}, {bio_part}, {emoji}", "{noun} {bio_supporter}", "{noun} {bio_supporter} {emoji}",
"{noun} {bio_supporter}, {bio_part}", "{noun} {bio_supporter}, {bio_part} {emoji}"});

// Source: https://en.wikipedia.org/wiki/List_of_gender_identities
const auto genders = std::to_array<std::string_view>({
"Male", "Female", "Transexual",
// "Agender",
// "Androgyne",
// "Androgynous",
// "Bigender",
// "Cis female",
// "Cis male",
// "Cis man",
// "Cis woman",
// "Cis",
// "Cisgender female",
// "Cisgender male",
// "Cisgender man",
// "Cisgender woman",
// "Cisgender",
// "Demi-boy",
// "Demi-girl",
// "Demi-man",
// "Demi-woman",
// "Demiflux",
// "Demigender",
// "F2M",
// "FTM",
// "Female to male trans man",
// "Female to male transgender man",
// "Female to male transsexual man",
// "Female to male",
// "Gender fluid",
// "Gender neutral",
// "Gender nonconforming",
// "Gender questioning",
// "Gender variant",
// "Genderflux",
// "Genderqueer",
// "Hermaphrodite",
// "Intersex man",
// "Intersex person",
// "Intersex woman",
// "Intersex",
// "M2F",
// "MTF",
// "Male to female trans woman",
// "Male to female transgender woman",
// "Male to female transsexual woman",
// "Male to female",
// "Man",
// "Multigender",
// "Neither",
// "Neutrois",
// "Non-binary",
// "Omnigender",
// "Other",
// "Pangender",
// "Polygender",
// "T* man",
// "T* woman",
// "Trans female",
// "Trans male",
// "Trans man",
// "Trans person",
// "Trans woman",
// "Trans",
// "Transexual female",
// "Transexual male",
// "Transexual man",
// "Transexual person",
// "Transexual woman",
// "Transexual",
// "Transgender female",
// "Transgender person",
// "Transmasculine",
// "Trigender",
// "Two* person",
// "Two-spirit person",
// "Two-spirit",
// "Woman",
// "Xenogender",
"Male",
"Female",
"Transexual",
});

const auto hobbies = std::to_array<std::string_view>({
Expand Down Expand Up @@ -216,31 +142,66 @@ const auto nationalities = std::to_array<std::string_view>({
"Ecuadorian", "Bolivian", "Costa Rican", "Panamanian", "Honduran", "Guatemalan",
});

const std::unordered_map<SsnCountry, std::string_view> ssnFormats{
{SsnCountry::Poland, "##[0-1][0-2][0-2]######"},
{SsnCountry::Usa, "###-##-####"},
// TODO: handle letters
{SsnCountry::England, "LL ## ## ## L"},
// TODO: handle conditional values like if year starts with 2 then second number must be 0-3
{SsnCountry::Germany, "####[0-2]#[0-1][0-2][1-2][5-9]##"},
{SsnCountry::France, "## [0-1][0-2] [0-2]# ### ### ##"},
// TODO: add alfa-numeric support
{SsnCountry::Italy, "FFFF FFFF FFFF FFFF"},
{SsnCountry::Spain, "X########L"},
{SsnCountry::India, "LLLLL####L"},
const std::unordered_map<Locale, std::string_view> passportFormats{
{Locale::es_US, "AA0000000"}, {Locale::en_US, "AA0000000"}, {Locale::pl_PL, "AA0000000"},
{Locale::fr_FR, "00AA00000"}, {Locale::ro_RO, "00000000"},
};

const auto westernZodiacs =
std::to_array<std::string_view>({"Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio",
"Sagittarius", "Capricorn", "Aquarius", "Pisces"});
const std::unordered_map<Locale, std::string_view> ssnFormats{
{Locale::pl_PL, "##[0-1][0-2][0-2]######"},
{Locale::es_US, "###-##-####"},
{Locale::en_US, "###-##-####"},
{Locale::en_GB, "LL ## ## ## L"},
{Locale::de_DE, "####[0-2]#[0-1][0-2][1-2][5-9]##"},
{Locale::fr_FR, "## [0-1][0-2] [0-2]# ### ### ##"},
{Locale::it_IT, "FFFF FFFF FFFF FFFF"},
{Locale::es_ES, "X########L"},
{Locale::ca_ES, "X########L"},
{Locale::as_IN, "LLLLL####L"},
{Locale::bn_IN, "LLLLL####L"},
{Locale::en_IN, "LLLLL####L"},
{Locale::gu_IN, "LLLLL####L"},
{Locale::hi_IN, "LLLLL####L"},
{Locale::kn_IN, "LLLLL####L"},
{Locale::ks_IN, "LLLLL####L"},
{Locale::ml_IN, "LLLLL####L"},
{Locale::mr_IN, "LLLLL####L"},
{Locale::or_IN, "LLLLL####L"},
{Locale::pa_IN, "LLLLL####L"},
{Locale::sa_IN, "LLLLL####L"},
{Locale::ta_IN, "LLLLL####L"},
{Locale::te_IN, "LLLLL####L"},
};

const auto chineseZodiacs = std::to_array<std::string_view>({"Rat", "Ox", "Tiger", "Rabbit", "Dragon",
"Snake"
"Horse",
"Sheep",
"Monkey"
"Rooster",
"Dog", "Pig"});
const auto westernZodiacs = std::to_array<std::string_view>({
"Aries",
"Taurus",
"Gemini",
"Cancer",
"Leo",
"Virgo",
"Libra",
"Scorpio",
"Sagittarius",
"Capricorn",
"Aquarius",
"Pisces",
});

const auto chineseZodiacs = std::to_array<std::string_view>({
"Rat",
"Ox",
"Tiger",
"Rabbit",
"Dragon",
"Snake"
"Horse",
"Sheep",
"Monkey"
"Rooster",
"Dog",
"Pig",
});

const std::unordered_map<Language, std::unordered_map<Sex, std::string_view>> sexTranslations = {
{Language::English, {{Sex::Male, "Male"}, {Sex::Female, "Female"}}},
Expand Down Expand Up @@ -278,17 +239,6 @@ const std::unordered_map<Language, std::unordered_map<Sex, std::string_view>> se
{Language::Estonian, {{Sex::Male, "Mees"}, {Sex::Female, "Naine"}}},
{Language::Irish, {{Sex::Male, "fireannach"}, {Sex::Female, "baineann"}}}};

const auto supportedSsnCountries = std::to_array<SsnCountry>({
SsnCountry::Poland,
SsnCountry::Usa,
SsnCountry::England,
SsnCountry::Germany,
SsnCountry::France,
SsnCountry::Italy,
SsnCountry::Spain,
SsnCountry::India,
});

// Albania

const auto albanianMaleFirstNames = std::to_array<std::string_view>(
Expand Down
Loading

0 comments on commit 6336aca

Please sign in to comment.