diff --git a/CMakeLists.txt b/CMakeLists.txt index 476ed6bad..04750b088 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,8 @@ set(FAKER_SOURCES src/modules/database/Database.cpp src/modules/music/Music.cpp src/modules/movie/Movie.cpp - ) + src/modules/hacker/Hacker.cpp +) set(FAKER_UT_SOURCES src/modules/animal/AnimalTest.cpp @@ -68,7 +69,8 @@ set(FAKER_UT_SOURCES src/modules/database/DatabaseTest.cpp src/modules/music/MusicTest.cpp src/modules/movie/MovieTest.cpp - ) + src/modules/hacker/HackerTest.cpp +) add_library(${LIBRARY_NAME} ${FAKER_SOURCES}) diff --git a/include/faker-cxx/Hacker.h b/include/faker-cxx/Hacker.h new file mode 100644 index 000000000..adc5292fa --- /dev/null +++ b/include/faker-cxx/Hacker.h @@ -0,0 +1,74 @@ +#pragma once + +#include + +namespace faker { + class Hacker { +public: + /** + * @brief Returns a hacker abbreviation. + * + * @returns abbreviation. + * + * @code + * Hacker::abbreviation() // "TCP" + * @endcode + */ + static std::string abbreviation(); + + /** + * @brief Returns a random adjective. + * + * @returns adjective. + * + * @code + * Hacker::adjective() // "open-source" + * @endcode + */ + static std::string adjective(); + + /** + * @brief Returns a random noun. + * + * @returns noun. + * + * @code + * Hacker::noun() // "coder" + * @endcode + */ + static std::string noun(); + + /** + * @brief Returns a random verb. + * + * @returns verb. + * + * @code + * Hacker::verb() // "run" + * @endcode + */ + static std::string verb(); + + /** + * @brief Returns a random ingverb. + * + * @returns ingverb. + * + * @code + * Hacker::ingverb() // "backing up" + * @endcode + */ + static std::string ingverb(); + + /** + * @brief Returns a random phrase. + * + * @return phrase. + * + * @code + * Hacker::phrase() // "If we bypass the monitor, we can get to the TCP monitor through the neural EXE monitor!" + * @endcode + */ + static std::string phrase(); + }; +} \ No newline at end of file diff --git a/include/faker-cxx/Helper.h b/include/faker-cxx/Helper.h index d517453cb..794069347 100644 --- a/include/faker-cxx/Helper.h +++ b/include/faker-cxx/Helper.h @@ -2,6 +2,8 @@ #include #include +#include +#include #include "Datatype.h" #include "Number.h" @@ -177,6 +179,46 @@ class Helper return TResult(); } + /* + * @brief Returns a split string into words. + * + * @param input The string to split. + * + * @return A vector of words. + * + * @code + * Helper::splitIntoWords("Hello World!") // {"Hello", "World!"} + * @endcode + */ + static std::vector splitIntoWords(const std::string& input); + + /* + * @brief Returns true if the given character is punctuation. + * + * @param c The character to check. + * + * @return True if the given character is punctuation. + * + * @code + * Helper::isPunctuation('!') // true + * Helper::isPunctuation('a') // false + * @endcode + */ + static bool isPunctuation(char c); + + /* + * @brief Returns the given word without punctuation. + * + * @param word The word to remove punctuation. + * + * @return The given word without punctuation. + * + * @code + * Helper::removePunctuation("Hello!") // "Hello" + * @endcode + */ + static std::string removePunctuation(const std::string& word); + private: static std::random_device randomDevice; static std::mt19937 pseudoRandomGenerator; diff --git a/src/modules/hacker/Hacker.cpp b/src/modules/hacker/Hacker.cpp new file mode 100644 index 000000000..5dfdfe0a8 --- /dev/null +++ b/src/modules/hacker/Hacker.cpp @@ -0,0 +1,74 @@ +#include "faker-cxx/Hacker.h" + +#include +#include + +#include "data/Abbreviations.h" +#include "data/Adjectives.h" +#include "data/Ingverbs.h" +#include "data/Nouns.h" +#include "data/Phrases.h" +#include "data/Verbs.h" + +namespace faker +{ +std::string Hacker::abbreviation() +{ + return faker::Helper::arrayElement(faker::abbreviations); +} + +std::string Hacker::adjective() +{ + return faker::Helper::arrayElement(faker::adjectives); +} + +std::string Hacker::noun() +{ + return faker::Helper::arrayElement(faker::nouns); +} + +std::string Hacker::verb() +{ + return faker::Helper::arrayElement(faker::verbs); +} + +std::string Hacker::ingverb() +{ + return faker::Helper::arrayElement(faker::ingverbs); +} + +std::string Hacker::phrase() +{ + auto splitRandomPhrase = Helper::splitIntoWords(faker::Helper::arrayElement(faker::phrases)); + std::string ret; + + for (auto& word : splitRandomPhrase) + { + word = Helper::removePunctuation(word); + if (word == "{abbreviation}") + { + word = abbreviation(); + } + else if (word == "{adjective}") + { + word = adjective(); + } + else if (word == "{noun}") + { + word = noun(); + } + else if (word == "{verb}") + { + word = verb(); + } + else if (word == "{ingverb}") + { + word = ingverb(); + } + + ret += word + " "; + } + + return ret; +} +} diff --git a/src/modules/hacker/HackerTest.cpp b/src/modules/hacker/HackerTest.cpp new file mode 100644 index 000000000..f6f4aac53 --- /dev/null +++ b/src/modules/hacker/HackerTest.cpp @@ -0,0 +1,109 @@ +#include "faker-cxx/Hacker.h" + +#include +#include + +#include "gtest/gtest.h" + +#include "data/Abbreviations.h" +#include "data/Adjectives.h" +#include "data/Ingverbs.h" +#include "data/Nouns.h" +#include "data/Phrases.h" +#include "data/Verbs.h" +#include "faker-cxx/Helper.h" + +using namespace ::testing; +using namespace faker; + +class HackerTest : public Test +{ +public: +}; + +TEST_F(HackerTest, shouldGenerateAbbreviation) +{ + std::string generatedAbbreviation = Hacker::abbreviation(); + + ASSERT_TRUE(std::ranges::any_of(abbreviations, [generatedAbbreviation](const std::string& abbreviation) + { return abbreviation == generatedAbbreviation; })); +} + +TEST_F(HackerTest, shouldGenerateAdjective) +{ + std::string generatedAdjective = Hacker::adjective(); + + ASSERT_TRUE(std::ranges::any_of(adjectives, [generatedAdjective](const std::string& adjective) + { return adjective == generatedAdjective; })); +} + +TEST_F(HackerTest, shouldGenerateNoun) +{ + std::string generatedNoun = Hacker::noun(); + + ASSERT_TRUE(std::ranges::any_of(nouns, [generatedNoun](const std::string& noun) { return noun == generatedNoun; })); +} + +TEST_F(HackerTest, shouldGenerateVerb) +{ + std::string generatedVerb = Hacker::verb(); + + ASSERT_TRUE(std::ranges::any_of(verbs, [generatedVerb](const std::string& verb) { return verb == generatedVerb; })); +} + +TEST_F(HackerTest, shouldGenerateIngverb) +{ + std::string generatedIngverb = Hacker::ingverb(); + + ASSERT_TRUE(std::ranges::any_of(ingverbs, [generatedIngverb](const std::string& ingverb) + { return ingverb == generatedIngverb; })); +} + +TEST_F(HackerTest, shouldGeneratePhrase) +{ + std::string generatedPhrase = Hacker::phrase(); + bool hasAdjective, hasNoun, hasVerb, hasAbbreviation; + hasAdjective = hasNoun = hasVerb = hasAbbreviation = false; + + // Check for adjectives + for (const std::string& adj : adjectives) + { + if (generatedPhrase.find(adj) != std::string::npos) + { + hasAdjective = true; + break; + } + } + + // Check for nouns + for (const std::string& noun : nouns) + { + if (generatedPhrase.find(noun) != std::string::npos) + { + hasNoun = true; + break; + } + } + + // Check for verbs + for (const std::string& verb : verbs) + { + if (generatedPhrase.find(verb) != std::string::npos) + { + hasVerb = true; + break; + } + } + + // Check for abbreviations + for (const std::string& abbreviation : abbreviations) + { + if (generatedPhrase.find(abbreviation) != std::string::npos) + { + hasAbbreviation = true; + break; + } + } + + ASSERT_TRUE((hasAdjective && hasNoun && hasVerb && hasAbbreviation)); +} diff --git a/src/modules/hacker/data/Abbreviations.h b/src/modules/hacker/data/Abbreviations.h new file mode 100644 index 000000000..a048b9278 --- /dev/null +++ b/src/modules/hacker/data/Abbreviations.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace faker +{ +const std::vector abbreviations = { + "e.g.", "i.e.", "etc.", "Mr.", "Mrs.", "Ms.", "Dr.", "Prof.", + "Ave.", "St.", "A.M.", "P.M.", "USA", "UK", "CEO", "CFO", +}; +} diff --git a/src/modules/hacker/data/Adjectives.h b/src/modules/hacker/data/Adjectives.h new file mode 100644 index 000000000..6cacc6a6c --- /dev/null +++ b/src/modules/hacker/data/Adjectives.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace faker +{ +const std::vector adjectives = { + "auxiliary", "primary", "back-end", "digital", "open-source", "virtual", "cross-platform", "redundant", + "online", "haptic", "multi-byte", "bluetooth", "wireless", "1080p", "neural", "optical", +}; +} diff --git a/src/modules/hacker/data/Ingverbs.h b/src/modules/hacker/data/Ingverbs.h new file mode 100644 index 000000000..8afe2c55b --- /dev/null +++ b/src/modules/hacker/data/Ingverbs.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace faker +{ +const std::vector ingverbs = { + "backing up", "bypassing", "hacking", "overriding", "compressing", "copying", "navigating", "indexing", + "connecting", "generating", "quantifying", "calculating", "synthesizing", "transmitting", "programming", "parsing", +}; +} diff --git a/src/modules/hacker/data/Nouns.h b/src/modules/hacker/data/Nouns.h new file mode 100644 index 000000000..e446dc9b2 --- /dev/null +++ b/src/modules/hacker/data/Nouns.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace faker +{ +const std::vector nouns = { + "driver", "protocol", "bandwidth", "panel", "microchip", "program", "port", "card", + "array", "interface", "system", "sensor", "firewall", "hard drive", "pixel", "alarm", +}; +} diff --git a/src/modules/hacker/data/Phrases.h b/src/modules/hacker/data/Phrases.h new file mode 100644 index 000000000..36c86d639 --- /dev/null +++ b/src/modules/hacker/data/Phrases.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "Abbreviations.h" +#include "Adjectives.h" +#include "faker-cxx/Helper.h" +#include "fmt/format.h" +#include "Ingverbs.h" +#include "Nouns.h" +#include "Verbs.h" + +namespace faker +{ +// use fmt::format() to format each phrase w/ random word + +const std::vector phrases = { + "If we {verb} the {noun}, we can get to the {abbreviation} {noun} through the {adjective} {abbreviation} {noun}!", + "We need to {verb} the {adjective} {abbreviation} {noun}!", + "Try to {verb} the {abbreviation} {noun}, maybe it will {verb} the {adjective} {noun}!", + "You can't {verb} the {noun} without {ingverb} the {adjective} {abbreviation} {noun}!", + "Use the {adjective} {abbreviation} {noun}, then you can {verb} the {adjective} {noun}!", + "The {abbreviation} {noun} is down, {verb} the {adjective} {noun} so we can {verb} the {abbreviation} {noun}!", + "{ingverb} the {noun} won't do anything, we need to {verb} the {adjective} {abbreviation} {noun}!", + "I'll {verb} the {adjective} {abbreviation} {noun}, that should {noun} the {abbreviation} {noun}!", +}; +} diff --git a/src/modules/hacker/data/Verbs.h b/src/modules/hacker/data/Verbs.h new file mode 100644 index 000000000..f62bde23f --- /dev/null +++ b/src/modules/hacker/data/Verbs.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace faker +{ +const std::vector verbs = { + "back up", "bypass", "hack", "override", "compress", "copy", "navigate", "index", + "connect", "generate", "quantify", "calculate", "synthesize", "transmit", "program", "parse", +}; +} diff --git a/src/modules/helper/Helper.cpp b/src/modules/helper/Helper.cpp index 463f4fa51..a76864768 100644 --- a/src/modules/helper/Helper.cpp +++ b/src/modules/helper/Helper.cpp @@ -1,9 +1,12 @@ #include "faker-cxx/Helper.h" #include +#include #include #include +#include #include +#include #include "../src/common/LuhnCheck.h" #include "../src/common/StringHelper.h" @@ -104,4 +107,26 @@ std::string Helper::regexpStyleStringParse(const std::string& input) return string; } + +// helper functions for phrases +std::vector Helper::splitIntoWords(const std::string& input) +{ + std::istringstream iss(input); + std::vector words(std::istream_iterator{iss}, std::istream_iterator()); + return words; +} + +// Function to check if a character is punctuation +bool Helper::isPunctuation(char c) +{ + return (c == '.' || c == ',' || c == '!' || c == '?' || c == ';' || c == ':'); +} + +// Function to remove punctuation from a word +std::string Helper::removePunctuation(const std::string& word) +{ + std::string result = word; + result.erase(std::remove_if(result.begin(), result.end(), isPunctuation), result.end()); + return result; +} } diff --git a/src/modules/helper/HelperTest.cpp b/src/modules/helper/HelperTest.cpp index b58053a1c..e851719e9 100644 --- a/src/modules/helper/HelperTest.cpp +++ b/src/modules/helper/HelperTest.cpp @@ -107,4 +107,35 @@ TEST_F(HelperTest, MaybeDouble) result = Helper::maybe([]() { return 3.14; }, lowProbability); EXPECT_EQ(result, 0.0); } + +TEST_F(HelperTest, IsPunctuation) +{ + std::string punctuation = ".,;:!?"; + for (char c : punctuation) + { + EXPECT_TRUE(Helper::isPunctuation(c)); + } + + std::string notPunctuation = "abc123"; + for (char c : notPunctuation) + { + EXPECT_FALSE(Helper::isPunctuation(c)); + } +} + +TEST_F(HelperTest, RemovePunctuation) +{ + std::string input = "Hello, World!"; + std::string result = Helper::removePunctuation(input); + EXPECT_EQ(result, "Hello World"); +} + +TEST_F(HelperTest, SplitIntoWords) +{ + std::string input = "Hello World!"; + std::vector result = Helper::splitIntoWords(input); + EXPECT_EQ(result.size(), 2); + EXPECT_EQ(result[0], "Hello"); + EXPECT_EQ(result[1], "World!"); +} }