Skip to content

Commit

Permalink
add name internalized formats (#244)
Browse files Browse the repository at this point in the history
* add english prefixes

* add person names struct

* add name internalized formats

* fix typos in tests

* add missing header
  • Loading branch information
cieslarmichal authored Nov 12, 2023
1 parent 74c4398 commit 9e7c16f
Show file tree
Hide file tree
Showing 69 changed files with 2,238 additions and 1,720 deletions.
53 changes: 53 additions & 0 deletions include/faker-cxx/Helper.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <functional>
#include <numeric>
#include <span>
#include <string>

Expand All @@ -9,6 +10,7 @@

namespace faker
{
// TODO: Add error handling if data empty
class Helper
{
public:
Expand All @@ -29,6 +31,11 @@ class Helper
template <class T>
static T arrayElement(std::span<const T> data)
{
if (data.empty())
{
throw std::invalid_argument{"Data is empty."};
}

const auto index = Number::integer<size_t>(data.size() - 1);

return data[index];
Expand All @@ -37,11 +44,57 @@ class Helper
template <class T>
static T arrayElement(const std::vector<T>& data)
{
if (data.empty())
{
throw std::invalid_argument{"Data is empty."};
}

const auto index = Number::integer<size_t>(data.size() - 1);

return data[index];
}

template <class T>
struct WeightedElement
{
unsigned weight;
T value;
};

template <class T>
static T weightedArrayElement(const std::vector<WeightedElement<T>>& data)
{
if (data.empty())
{
throw std::invalid_argument{"Data is empty."};
}

const auto sumOfWeights =
std::accumulate(data.begin(), data.end(), 0u,
[](size_t sum, const WeightedElement<T>& element) { return sum + element.weight; });

if (sumOfWeights == 0)
{
throw std::invalid_argument{"Sum of weights is zero."};
}

const std::integral auto targetWeightValue = Number::integer<unsigned>(sumOfWeights);

unsigned currentSum = 0;

for (const auto& element : data)
{
currentSum += element.weight;

if (targetWeightValue <= currentSum)
{
return element.value;
}
}

return data.at(data.size() - 1).value;
}

/**
* @brief Returns shuffled STL container.
*
Expand Down
26 changes: 26 additions & 0 deletions include/faker-cxx/Person.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Person
* @brief Returns a random last name.
*
* @param language The local name language. Defaults to `Language::English`.
* @param sex The optional sex to use.
*
* @returns Last name starting with a capital letter.
*
Expand All @@ -40,10 +41,24 @@ class Person
*/
static std::string lastName(Language language = Language::English, std::optional<Sex> = std::nullopt);

/**
* @brief Returns a random middle name.
*
* @param sex The optional sex to use.
*
* @returns Middle name starting with a capital letter.
*
* @code
* Person::middleName() // "Васильевич"
* @endcode
*/
static std::string middleName(std::optional<Sex> = std::nullopt);

/**
* @brief Returns a random full name.
*
* @param language The local name language. Defaults to `Language::English`.
* @param sex The optional sex to use.
*
* @returns Full name starting with first name.
*
Expand All @@ -70,6 +85,17 @@ class Person
*/
static std::string prefix(std::optional<Sex> = std::nullopt);

/**
* @brief Returns a random name suffix.
*
* @returns Name suffix.
*
* @code
* Person::suffix() // "Jr."
* @endcode
*/
static std::string suffix();

/**
* @brief Returns a sex.
*
Expand Down
12 changes: 12 additions & 0 deletions include/faker-cxx/types/Sex.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,16 @@ enum class Sex
Male,
Female,
};

inline std::string toString(Sex sex)
{
std::map<Sex, std::string> sexToStringMapping{{Sex::Male, "Male"}, {Sex::Female, "Female"}};

return sexToStringMapping.at(sex);
}

inline std::ostream& operator<<(std::ostream& os, Sex sex)
{
return os << toString(sex);
}
}
2 changes: 2 additions & 0 deletions src/modules/company/Company.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

namespace faker
{
// TODO: add internalization

std::string Company::name()
{
std::string companyName;
Expand Down
9 changes: 4 additions & 5 deletions src/modules/company/CompanyTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
#include "gtest/gtest.h"

#include "../../common/StringHelper.h"
#include "../person/data/english/EnglishFirstNamesFemales.h"
#include "../person/data/english/EnglishFirstNamesMales.h"
#include "../person/data/english/EnglishFirstNames.h"
#include "../person/data/english/EnglishLastNames.h"
#include "../person/data/JobTitles.h"
#include "data/BuzzAdjectives.h"
Expand All @@ -33,10 +32,10 @@ TEST_F(CompanyTest, shouldGenerateCompanyName)

const auto companyNameElements = StringHelper::split(companyName, " ");

std::vector<std::string> expectedFirstNames{englishFirstNamesMales};
std::vector<std::string> expectedFirstNames{englishMalesFirstNames};

expectedFirstNames.insert(expectedFirstNames.end(), englishFirstNamesFemales.begin(),
englishFirstNamesFemales.end());
expectedFirstNames.insert(expectedFirstNames.end(), englishFemalesFirstNames.begin(),
englishFemalesFirstNames.end());

if (companyNameElements.size() == 2)
{
Expand Down
1 change: 1 addition & 0 deletions src/modules/internet/Internet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const std::map<EmojiType, std::vector<std::string>> emojiTypeToEmojisMapping{
};
}

// TODO: add internalization
std::string Internet::username(std::optional<std::string> firstNameInit, std::optional<std::string> lastNameInit)
{
const auto firstName = firstNameInit ? *firstNameInit : Person::firstName();
Expand Down
39 changes: 19 additions & 20 deletions src/modules/internet/InternetTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
#include "gtest/gtest.h"

#include "../../common/StringHelper.h"
#include "../person/data/english/EnglishFirstNamesFemales.h"
#include "../person/data/english/EnglishFirstNamesMales.h"
#include "../person/data/english/EnglishFirstNames.h"
#include "../person/data/english/EnglishLastNames.h"
#include "../string/data/Characters.h"
#include "../word/data/Adjectives.h"
Expand Down Expand Up @@ -102,9 +101,9 @@ class InternetTest : public Test

TEST_F(InternetTest, shouldGenerateUsername)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto username = Internet::username();

Expand All @@ -127,9 +126,9 @@ TEST_F(InternetTest, shouldGenerateUsernameWithFirstNameProvided)

TEST_F(InternetTest, shouldGenerateUsernameWithLastNameProvided)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto lastName = "Cieslar";

Expand All @@ -154,9 +153,9 @@ TEST_F(InternetTest, shouldGenerateUsernameWithFullNameProvided)

TEST_F(InternetTest, shouldGenerateEmail)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto email = Internet::email();

Expand Down Expand Up @@ -197,9 +196,9 @@ TEST_F(InternetTest, shouldGenerateEmailWithFirstName)

TEST_F(InternetTest, shouldGenerateEmailWithLastName)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto lastName = "Howard";

Expand All @@ -221,9 +220,9 @@ TEST_F(InternetTest, shouldGenerateEmailWithLastName)

TEST_F(InternetTest, shouldGenerateEmailWithFullName)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto firstName = "Cindy";

Expand All @@ -246,9 +245,9 @@ TEST_F(InternetTest, shouldGenerateEmailWithFullName)

TEST_F(InternetTest, shouldGenerateEmailWithSpecifiedEmailHost)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto emailHost = "example.com";

Expand All @@ -270,9 +269,9 @@ TEST_F(InternetTest, shouldGenerateEmailWithSpecifiedEmailHost)

TEST_F(InternetTest, shouldGenerateExampleEmail)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto email = Internet::exampleEmail();

Expand Down Expand Up @@ -313,9 +312,9 @@ TEST_F(InternetTest, shouldGenerateExampleEmailWithFirstName)

TEST_F(InternetTest, shouldGenerateExampleEmailWithLastName)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto lastName = "Wilkinson";

Expand All @@ -337,9 +336,9 @@ TEST_F(InternetTest, shouldGenerateExampleEmailWithLastName)

TEST_F(InternetTest, shouldGenerateExampleEmailWithFullName)
{
std::vector<std::string> firstNames{englishFirstNamesMales};
std::vector<std::string> firstNames{englishMalesFirstNames};

firstNames.insert(firstNames.end(), englishFirstNamesFemales.begin(), englishFirstNamesFemales.end());
firstNames.insert(firstNames.end(), englishFemalesFirstNames.begin(), englishFemalesFirstNames.end());

const auto firstName = "Walter";

Expand Down
3 changes: 3 additions & 0 deletions src/modules/location/Location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace faker
{
namespace
{
// TODO: Refactor
const std::map<Country, std::vector<std::string>> countryToCitiesMapping{{Country::Usa, usaCities},
{Country::Russia, russiaCities},
{Country::Poland, polandCities},
Expand Down Expand Up @@ -124,6 +125,8 @@ std::string Location::streetAddress(Country country)

std::string Location::street(Country country)
{
// TODO: add internalization

const auto& streetFormats = countryToStreetFormatsMapping.at(country);

const auto streetFormat = Helper::arrayElement<std::string>(streetFormats);
Expand Down
Loading

0 comments on commit 9e7c16f

Please sign in to comment.