From 4f9688c42a94243377f061f136871ec83d5b1aea Mon Sep 17 00:00:00 2001 From: iht Date: Tue, 29 Oct 2024 19:24:02 +0100 Subject: [PATCH] Some WIP C# classes --- CK3ToEU4/Source/CK3/Characters/Character.cpp | 140 ------- CK3ToEU4/Source/CK3/Characters/Character.cs | 230 ++++++++++++ CK3ToEU4/Source/CK3/Characters/Character.h | 109 ------ .../Source/CK3/Characters/CharacterDomain.cpp | 36 -- .../Source/CK3/Characters/CharacterDomain.cs | 58 +++ .../Source/CK3/Characters/CharacterDomain.h | 38 -- CK3ToEU4/Source/CK3/Characters/Characters.cpp | 241 ------------ CK3ToEU4/Source/CK3/Characters/Characters.cs | 239 ++++++++++++ CK3ToEU4/Source/CK3/Characters/Characters.h | 39 -- CK3ToEU4/Source/CK3/Dynasties/House.cs | 71 ++-- CK3ToEU4/Source/CK3/Flags/Flags.cs | 77 ++-- .../Source/CK3/Geography/CountyDetails.cs | 1 + CK3ToEU4/Source/CK3/Religions/Faith.cs | 43 ++- CK3ToEU4/Source/CK3/Religions/Faiths.cs | 68 ++-- CK3ToEU4/Source/CK3/Religions/Religions.cs | 59 ++- CK3ToEU4/Source/CK3/World.cs | 8 +- CK3ToEU4/Source/CK3World/World.h | 8 +- CK3ToEU4/Source/EU4World/Country/Country.cpp | 2 +- CK3ToEU4/Source/EU4World/Country/Country.h | 2 +- CK3ToEU4/Source/EU4World/EU4World.h | 4 +- .../Source/EU4World/Province/EU4Province.cpp | 2 +- .../CultureDefinitionsMapper.cpp | 2 +- .../Mappers/CultureMapper/CultureMapper.cpp | 163 -------- .../Mappers/CultureMapper/CultureMapper.cs | 173 +++++++++ .../Mappers/CultureMapper/CultureMapper.h | 63 ---- .../CultureMapper/CultureMappingRule.cpp | 157 -------- .../CultureMapper/CultureMappingRule.cs | 177 +++++++++ .../CultureMapper/CultureMappingRule.h | 61 --- .../Mappers/IAmHreMapper/IAmHreMapper.cpp | 26 -- .../Mappers/IAmHreMapper/IAmHreMapper.h | 31 +- .../LocalizationMapper/LocalizationMapper.cpp | 324 ---------------- .../LocalizationMapper/LocalizationMapper.cs | 349 ++++++++++++++++++ .../LocalizationMapper/LocalizationMapper.h | 52 --- .../Mappers/NamedColors/NamedColors.cpp | 29 -- .../Source/Mappers/NamedColors/NamedColors.cs | 33 ++ .../Source/Mappers/NamedColors/NamedColors.h | 21 -- .../Mappers/ReligionMapper/ReligionMapper.h | 2 +- .../Mappers/TraitScraper/TraitScraper.cpp | 58 --- .../Mappers/TraitScraper/TraitScraper.cs | 63 ++++ .../Mappers/TraitScraper/TraitScraper.h | 26 -- .../Mappers/TraitScraper/TraitScraping.cpp | 18 - .../Mappers/TraitScraper/TraitScraping.cs | 26 ++ .../Mappers/TraitScraper/TraitScraping.h | 22 -- 43 files changed, 1546 insertions(+), 1805 deletions(-) delete mode 100644 CK3ToEU4/Source/CK3/Characters/Character.cpp create mode 100644 CK3ToEU4/Source/CK3/Characters/Character.cs delete mode 100644 CK3ToEU4/Source/CK3/Characters/Character.h delete mode 100644 CK3ToEU4/Source/CK3/Characters/CharacterDomain.cpp create mode 100644 CK3ToEU4/Source/CK3/Characters/CharacterDomain.cs delete mode 100644 CK3ToEU4/Source/CK3/Characters/CharacterDomain.h delete mode 100644 CK3ToEU4/Source/CK3/Characters/Characters.cpp create mode 100644 CK3ToEU4/Source/CK3/Characters/Characters.cs delete mode 100644 CK3ToEU4/Source/CK3/Characters/Characters.h delete mode 100644 CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cpp create mode 100644 CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cs delete mode 100644 CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.h delete mode 100644 CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cpp create mode 100644 CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cs delete mode 100644 CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.h delete mode 100644 CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.cpp delete mode 100644 CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cpp create mode 100644 CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cs delete mode 100644 CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.h delete mode 100644 CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cpp create mode 100644 CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cs delete mode 100644 CK3ToEU4/Source/Mappers/NamedColors/NamedColors.h delete mode 100644 CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cpp create mode 100644 CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cs delete mode 100644 CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.h delete mode 100644 CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cpp create mode 100644 CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cs delete mode 100644 CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.h diff --git a/CK3ToEU4/Source/CK3/Characters/Character.cpp b/CK3ToEU4/Source/CK3/Characters/Character.cpp deleted file mode 100644 index c0024a06..00000000 --- a/CK3ToEU4/Source/CK3/Characters/Character.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "Character.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::Character::Character(std::istream& theStream, long long characterID): charID(characterID) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Character::registerKeys() -{ - registerKeyword("first_name", [this](const std::string& unused, std::istream& theStream) { - name = commonItems::singleString(theStream).getString(); - }); - registerKeyword("birth", [this](const std::string& unused, std::istream& theStream) { - birthDate = date(commonItems::singleString(theStream).getString()); - }); - registerKeyword("dead_data", [this](const std::string& unused, std::istream& theStream) { - commonItems::ignoreItem(unused, theStream); - dead = true; - }); - registerKeyword("culture", [this](const std::string& unused, std::istream& theStream) { - culture = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - if (culture->first == 4294967295) - culture.reset(); - }); - registerKeyword("faith", [this](const std::string& unused, std::istream& theStream) { - faith = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - if (faith->first == 4294967295) - faith.reset(); - }); - registerKeyword("dynasty_house", [this](const std::string& unused, std::istream& theStream) { - house = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("skill", [this](const std::string& unused, std::istream& theStream) { - const auto& skillList = commonItems::intList(theStream).getInts(); - if (skillList.size() > 5) - { - skills.diplomacy = skillList[0]; - skills.martial = skillList[1]; - skills.stewardship = skillList[2]; - skills.intrigue = skillList[3]; - skills.learning = skillList[4]; - } - else - Log(LogLevel::Error) << "Character " << charID << " has a malformed skills block! Size: " << skillList.size(); - }); - registerKeyword("traits", [this](const std::string& unused, std::istream& theStream) { - for (const auto traitID: commonItems::intList(theStream).getInts()) - traits.insert(std::pair(traitID, std::string())); - }); - registerKeyword("alive_data", [this](const std::string& unused, std::istream& theStream) { - const auto tempBlock = Character(theStream, charID); - piety = tempBlock.getPiety(); - prestige = tempBlock.getPrestige(); - gold = tempBlock.getGold(); - claims = tempBlock.getClaims(); - }); - registerKeyword("piety", [this](const std::string& unused, std::istream& theStream) { - const auto tempBlock = Character(theStream, charID); - piety = tempBlock.getAccumulated(); - }); - registerKeyword("prestige", [this](const std::string& unused, std::istream& theStream) { - const auto tempBlock = Character(theStream, charID); - prestige = tempBlock.getAccumulated(); - }); - registerKeyword("accumulated", [this](const std::string& unused, std::istream& theStream) { - accumulated = commonItems::singleDouble(theStream).getDouble(); - }); - registerKeyword("gold", [this](const std::string& unused, std::istream& theStream) { - gold = commonItems::singleDouble(theStream).getDouble(); - }); - registerKeyword("court_data", [this](const std::string& unused, std::istream& theStream) { - const auto tempBlock = Character(theStream, charID); - employer = tempBlock.getEmployer(); - knight = tempBlock.isKnight(); - councilor = tempBlock.isCouncilor(); - }); - registerKeyword("employer", [this](const std::string& unused, std::istream& theStream) { - employer = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("knight", [this](const std::string& unused, std::istream& theStream) { - knight = commonItems::singleString(theStream).getString() == "yes"; - }); - registerRegex("council_task|special_council_tasks", [this](const std::string& unused, std::istream& theStream) { - councilor = true; - commonItems::ignoreItem(unused, theStream); - }); - registerKeyword("female", [this](const std::string& unused, std::istream& theStream) { - female = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("landed_data", [this](const std::string& unused, std::istream& theStream) { - characterDomain = CharacterDomain(theStream); - }); - registerKeyword("family_data", [this](const std::string& unused, std::istream& theStream) { - const auto tempBlock = Character(theStream, charID); - spouse = tempBlock.getSpouse(); - }); - registerKeyword("primary_spouse", [this](const std::string& unused, std::istream& theStream) { - spouse = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("claim", [this](const std::string& unused, std::istream& theStream) { - const auto blobList = commonItems::blobList(theStream).getBlobs(); - for (const auto& blob: blobList) - { - auto blobStream = std::stringstream(blob); - const auto titleID = Character(blobStream, charID).getTempTitle(); - if (titleID) - claims.insert(std::pair(titleID, nullptr)); - } - }); - registerKeyword("title", [this](const std::string& unused, std::istream& theStream) { - tempTitle = commonItems::singleLlong(theStream).getLlong(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Character::dropTitleFromDomain(long long titleID) -{ - if (characterDomain) - { - std::vector>> replacementDomain; - for (const auto& title: characterDomain->getDomain()) - { - if (title.first != titleID) - replacementDomain.emplace_back(title); - } - characterDomain->loadDomain(replacementDomain); - } -} - -bool CK3::Character::hasTrait(const std::string& wantedTrait) const -{ - return std::any_of(traits.begin(), traits.end(), [wantedTrait](const std::pair& trait) { - return trait.second == wantedTrait; - }); -} diff --git a/CK3ToEU4/Source/CK3/Characters/Character.cs b/CK3ToEU4/Source/CK3/Characters/Character.cs new file mode 100644 index 00000000..0f727c8a --- /dev/null +++ b/CK3ToEU4/Source/CK3/Characters/Character.cs @@ -0,0 +1,230 @@ + +using CK3ToEU4.CK3.Characters; + +namespace CK3 +{ + +struct Skills +{ + int diplomacy = 0; + int martial = 0; + int stewardship = 0; + int intrigue = 0; + int learning = 0; +} + +class Character +{ + public: + Character(std::istream& theStream, long long characterID) + { + charID = characterID; + + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + [[nodiscard]] auto isDead() const { return dead; } + [[nodiscard]] auto isKnight() const { return knight; } + [[nodiscard]] auto isFemale() const { return female; } + [[nodiscard]] auto isCouncilor() const { return councilor; } + [[nodiscard]] auto getID() const { return charID; } + [[nodiscard]] auto getPiety() const { return piety; } + [[nodiscard]] auto getPrestige() const { return prestige; } + [[nodiscard]] auto getGold() const { return gold; } + [[nodiscard]] auto isSpent() const { return spent; } // Used to mark characters (advisors) so they cannot be reused in different tag. + [[nodiscard]] const auto& getName() const { return name; } + [[nodiscard]] const auto& getBirthDate() const { return birthDate; } + + [[nodiscard]] const auto& getCulture() const { return culture; } + [[nodiscard]] const auto& getFaith() const { return faith; } + [[nodiscard]] const auto& getEmployer() const { return employer; } + [[nodiscard]] const auto& getSpouse() const { return spouse; } + [[nodiscard]] const auto& getHouse() const { return house; } + [[nodiscard]] const auto& getTraits() const { return traits; } + [[nodiscard]] const auto& getClaims() const { return claims; } + + [[nodiscard]] const auto& getSkills() const { return skills; } + [[nodiscard]] const auto& getCharacterDomain() const { return characterDomain; } + [[nodiscard]] const auto& getCourtierNames() const { return courtierNames; } + [[nodiscard]] const auto& getCouncilors() const { return councilors; } + + [[nodiscard]] auto getTempTitle() const { return tempTitle; } + [[nodiscard]] auto getAccumulated() const { return accumulated; } + + void loadCulture(const std::pair>& theCulture) { culture = theCulture; } + void loadFaith(const std::pair>& theFaith) { faith = theFaith; } + void loadHouse(const std::pair>& theHouse) { house = theHouse; } + void loadRealmCapital(const std::pair>& theRealmCapital) { characterDomain->loadRealmCapital(theRealmCapital); } + void loadDomain(const std::vector>>& theDomain) { characterDomain->loadDomain(theDomain); } + void loadClaims(const std::map>& theClaims) { claims = theClaims; } + void loadEmployer(const std::pair>& theEmployer) { employer = theEmployer; } + void loadSpouse(const std::pair>& theSpouse) { spouse = theSpouse; } + void resetSpouse() { spouse.reset(); } + void resetEmployer() { employer.reset(); } + void loadTraits(const std::map& theTraits) { traits = theTraits; } + + // processing + void dropTitleFromDomain(long long titleID) + { + if (characterDomain) + { + std::vector>> replacementDomain; + for (const auto& title: characterDomain->getDomain()) + { + if (title.first != titleID) + replacementDomain.emplace_back(title); + } + characterDomain->loadDomain(replacementDomain); + } + } + void loadCourtierNames(const std::map& theNames) { courtierNames = theNames; } + void loadCouncilors(const std::map>& newCouncilors) { councilors = newCouncilors; } + + // poking + [[nodiscard]] bool hasTrait(const std::string& wantedTrait) + { + return std::any_of(traits.begin(), traits.end(), [wantedTrait](const std::pair& trait) { + return trait.second == wantedTrait; + }); + } + void setSpent() { spent = true; } + + private: + void registerKeys() + { + registerKeyword("first_name", [this](const std::string& unused, std::istream& theStream) { + name = commonItems::singleString(theStream).getString(); + }); + registerKeyword("birth", [this](const std::string& unused, std::istream& theStream) { + birthDate = date(commonItems::singleString(theStream).getString()); + }); + registerKeyword("dead_data", [this](const std::string& unused, std::istream& theStream) { + commonItems::ignoreItem(unused, theStream); + dead = true; + }); + registerKeyword("culture", [this](const std::string& unused, std::istream& theStream) { + culture = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + if (culture->first == 4294967295) + culture.reset(); + }); + registerKeyword("faith", [this](const std::string& unused, std::istream& theStream) { + faith = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + if (faith->first == 4294967295) + faith.reset(); + }); + registerKeyword("dynasty_house", [this](const std::string& unused, std::istream& theStream) { + house = std::pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + }); + registerKeyword("skill", [this](const std::string& unused, std::istream& theStream) { + const auto& skillList = commonItems::intList(theStream).getInts(); + if (skillList.size() > 5) + { + skills.diplomacy = skillList[0]; + skills.martial = skillList[1]; + skills.stewardship = skillList[2]; + skills.intrigue = skillList[3]; + skills.learning = skillList[4]; + } + else + Log(LogLevel::Error) << "Character " << charID << " has a malformed skills block! Size: " << skillList.size(); + }); + registerKeyword("traits", [this](const std::string& unused, std::istream& theStream) { + for (const auto traitID: commonItems::intList(theStream).getInts()) + traits.insert(std::pair(traitID, std::string())); + }); + registerKeyword("alive_data", [this](const std::string& unused, std::istream& theStream) { + const auto tempBlock = Character(theStream, charID); + piety = tempBlock.getPiety(); + prestige = tempBlock.getPrestige(); + gold = tempBlock.getGold(); + claims = tempBlock.getClaims(); + }); + registerKeyword("piety", [this](const std::string& unused, std::istream& theStream) { + const auto tempBlock = Character(theStream, charID); + piety = tempBlock.getAccumulated(); + }); + registerKeyword("prestige", [this](const std::string& unused, std::istream& theStream) { + const auto tempBlock = Character(theStream, charID); + prestige = tempBlock.getAccumulated(); + }); + registerKeyword("accumulated", [this](const std::string& unused, std::istream& theStream) { + accumulated = commonItems::singleDouble(theStream).getDouble(); + }); + registerKeyword("gold", [this](const std::string& unused, std::istream& theStream) { + gold = commonItems::singleDouble(theStream).getDouble(); + }); + registerKeyword("court_data", [this](const std::string& unused, std::istream& theStream) { + const auto tempBlock = Character(theStream, charID); + employer = tempBlock.getEmployer(); + knight = tempBlock.isKnight(); + councilor = tempBlock.isCouncilor(); + }); + registerKeyword("employer", [this](const std::string& unused, std::istream& theStream) { + employer = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + }); + registerKeyword("knight", [this](const std::string& unused, std::istream& theStream) { + knight = commonItems::singleString(theStream).getString() == "yes"; + }); + registerRegex("council_task|special_council_tasks", [this](const std::string& unused, std::istream& theStream) { + councilor = true; + commonItems::ignoreItem(unused, theStream); + }); + registerKeyword("female", [this](const std::string& unused, std::istream& theStream) { + female = commonItems::singleString(theStream).getString() == "yes"; + }); + registerKeyword("landed_data", [this](const std::string& unused, std::istream& theStream) { + characterDomain = CharacterDomain(theStream); + }); + registerKeyword("family_data", [this](const std::string& unused, std::istream& theStream) { + const auto tempBlock = Character(theStream, charID); + spouse = tempBlock.getSpouse(); + }); + registerKeyword("primary_spouse", [this](const std::string& unused, std::istream& theStream) { + spouse = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + }); + registerKeyword("claim", [this](const std::string& unused, std::istream& theStream) { + const auto blobList = commonItems::blobList(theStream).getBlobs(); + for (const auto& blob: blobList) + { + auto blobStream = std::stringstream(blob); + const auto titleID = Character(blobStream, charID).getTempTitle(); + if (titleID) + claims.insert(std::pair(titleID, nullptr)); + } + }); + registerKeyword("title", [this](const std::string& unused, std::istream& theStream) { + tempTitle = commonItems::singleLlong(theStream).getLlong(); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); +} + + bool knight = false; + bool female = false; + bool councilor = false; + long long charID = 0; + double piety = 0; + double prestige = 0; + double gold = 0; + std::string name; + date birthDate = date("1.1.1"); + bool dead = false; + bool spent = false; + + std::optional>> culture; + std::optional>> faith; + std::optional>> employer; + std::optional>> spouse; + std::pair> house; + std::map traits; + std::map> claims; + + Skills skills; + std::optional characterDomain; + std::map courtierNames; // A simple list of people's names and genders. True=male. + std::map> councilors; + + long long tempTitle = 0; // temporary variable for recursive scrapes. + double accumulated = 0; // temporary variable for recursive scrapes. +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Characters/Character.h b/CK3ToEU4/Source/CK3/Characters/Character.h deleted file mode 100644 index cebd8e8d..00000000 --- a/CK3ToEU4/Source/CK3/Characters/Character.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef CK3_CHARACTER_H -#define CK3_CHARACTER_H -#include "CharacterDomain.h" -#include "Date.h" -#include "Parser.h" - -namespace CK3 -{ -class Title; -class House; -class Faith; -class Culture; -typedef struct Skills -{ - int diplomacy = 0; - int martial = 0; - int stewardship = 0; - int intrigue = 0; - int learning = 0; -} Skills; - -class Character: commonItems::parser -{ - public: - Character(std::istream& theStream, long long characterID); - - [[nodiscard]] auto isDead() const { return dead; } - [[nodiscard]] auto isKnight() const { return knight; } - [[nodiscard]] auto isFemale() const { return female; } - [[nodiscard]] auto isCouncilor() const { return councilor; } - [[nodiscard]] auto getID() const { return charID; } - [[nodiscard]] auto getPiety() const { return piety; } - [[nodiscard]] auto getPrestige() const { return prestige; } - [[nodiscard]] auto getGold() const { return gold; } - [[nodiscard]] auto isSpent() const { return spent; } // Used to mark characters (advisors) so they cannot be reused in different tag. - [[nodiscard]] const auto& getName() const { return name; } - [[nodiscard]] const auto& getBirthDate() const { return birthDate; } - - [[nodiscard]] const auto& getCulture() const { return culture; } - [[nodiscard]] const auto& getFaith() const { return faith; } - [[nodiscard]] const auto& getEmployer() const { return employer; } - [[nodiscard]] const auto& getSpouse() const { return spouse; } - [[nodiscard]] const auto& getHouse() const { return house; } - [[nodiscard]] const auto& getTraits() const { return traits; } - [[nodiscard]] const auto& getClaims() const { return claims; } - - [[nodiscard]] const auto& getSkills() const { return skills; } - [[nodiscard]] const auto& getCharacterDomain() const { return characterDomain; } - [[nodiscard]] const auto& getCourtierNames() const { return courtierNames; } - [[nodiscard]] const auto& getCouncilors() const { return councilors; } - - [[nodiscard]] auto getTempTitle() const { return tempTitle; } - [[nodiscard]] auto getAccumulated() const { return accumulated; } - - void loadCulture(const std::pair>& theCulture) { culture = theCulture; } - void loadFaith(const std::pair>& theFaith) { faith = theFaith; } - void loadHouse(const std::pair>& theHouse) { house = theHouse; } - void loadRealmCapital(const std::pair>& theRealmCapital) { characterDomain->loadRealmCapital(theRealmCapital); } - void loadDomain(const std::vector>>& theDomain) { characterDomain->loadDomain(theDomain); } - void loadClaims(const std::map>& theClaims) { claims = theClaims; } - void loadEmployer(const std::pair>& theEmployer) { employer = theEmployer; } - void loadSpouse(const std::pair>& theSpouse) { spouse = theSpouse; } - void resetSpouse() { spouse.reset(); } - void resetEmployer() { employer.reset(); } - void loadTraits(const std::map& theTraits) { traits = theTraits; } - - // processing - void dropTitleFromDomain(long long titleID); - void loadCourtierNames(const std::map& theNames) { courtierNames = theNames; } - void loadCouncilors(const std::map>& newCouncilors) { councilors = newCouncilors; } - - // poking - [[nodiscard]] bool hasTrait(const std::string& wantedTrait) const; - void setSpent() { spent = true; } - - private: - void registerKeys(); - - bool knight = false; - bool female = false; - bool councilor = false; - long long charID = 0; - double piety = 0; - double prestige = 0; - double gold = 0; - std::string name; - date birthDate = date("1.1.1"); - bool dead = false; - bool spent = false; - - std::optional>> culture; - std::optional>> faith; - std::optional>> employer; - std::optional>> spouse; - std::pair> house; - std::map traits; - std::map> claims; - - Skills skills; - std::optional characterDomain; - std::map courtierNames; // A simple list of people's names and genders. True=male. - std::map> councilors; - - long long tempTitle = 0; // temporary variable for recursive scrapes. - double accumulated = 0; // temporary variable for recursive scrapes. -}; -} // namespace CK3 - -#endif // CK3_CHARACTER_H diff --git a/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cpp b/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cpp deleted file mode 100644 index fad9dfa4..00000000 --- a/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "CharacterDomain.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -CK3::CharacterDomain::CharacterDomain(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::CharacterDomain::registerKeys() -{ - registerKeyword("is_powerful_vassal", [this](const std::string& unused, std::istream& theStream) { - powerfulVassal = commonItems::singleString(theStream).getString() == "yes"; - }); - registerKeyword("vassal_power_value", [this](const std::string& unused, std::istream& theStream) { - vassalStrength = commonItems::singleDouble(theStream).getDouble(); - }); - registerKeyword("government", [this](const std::string& unused, std::istream& theStream) { - government = commonItems::singleString(theStream).getString(); - }); - registerKeyword("laws", [this](const std::string& unused, std::istream& theStream) { - const auto& lawsList = commonItems::stringList(theStream).getStrings(); - laws = std::set(lawsList.begin(), lawsList.end()); - }); - registerKeyword("realm_capital", [this](const std::string& unused, std::istream& theStream) { - realmCapital = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); - }); - registerKeyword("domain", [this](const std::string& unused, std::istream& theStream) { - for (auto titleID: commonItems::llongList(theStream).getLlongs()) - domain.emplace_back(std::pair(titleID, nullptr)); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cs b/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cs new file mode 100644 index 00000000..4c612d54 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Characters/CharacterDomain.cs @@ -0,0 +1,58 @@ + +using commonItems; + +namespace CK3ToEU4.CK3.Characters; + +class CharacterDomain +{ + public CharacterDomain() {} + public CharacterDomain(BufferedReader reader) + { + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); + } + + public auto isPowerfulVassal() const { return powerfulVassal; } + public auto getVassalStrength() const { return vassalStrength; } + public const auto& getGovernment() const { return government; } + public const auto& getLaws() const { return laws; } + public const auto& getRealmCapital() const { return realmCapital; } + public const auto& getDomain() const { return domain; } + + public void loadRealmCapital(const std::pair>& theRealmCapital) { realmCapital = theRealmCapital; } + public void loadDomain(const std::vector>>& theDomain) { domain = theDomain; } + + private void registerKeys() + { + registerKeyword("is_powerful_vassal", [this](const std::string& unused, std::istream& theStream) { + powerfulVassal = commonItems::singleString(theStream).getString() == "yes"; + }); + registerKeyword("vassal_power_value", [this](const std::string& unused, std::istream& theStream) { + vassalStrength = commonItems::singleDouble(theStream).getDouble(); + }); + registerKeyword("government", [this](const std::string& unused, std::istream& theStream) { + government = commonItems::singleString(theStream).getString(); + }); + registerKeyword("laws", [this](const std::string& unused, std::istream& theStream) { + const auto& lawsList = commonItems::stringList(theStream).getStrings(); + laws = std::set(lawsList.begin(), lawsList.end()); + }); + registerKeyword("realm_capital", [this](const std::string& unused, std::istream& theStream) { + realmCapital = std::make_pair(commonItems::singleLlong(theStream).getLlong(), nullptr); + }); + registerKeyword("domain", [this](const std::string& unused, std::istream& theStream) { + for (auto titleID: commonItems::llongList(theStream).getLlongs()) + domain.emplace_back(std::pair(titleID, nullptr)); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + + private bool powerfulVassal = false; + private double vassalStrength = 0; + private std::string government; + private std::set laws; + private std::pair> realmCapital; // A barony! + private std::vector>> domain; // These are all titles owned (b-c-d-k-e), landless included. First one is PRIMARY. +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Characters/CharacterDomain.h b/CK3ToEU4/Source/CK3/Characters/CharacterDomain.h deleted file mode 100644 index 63237bb8..00000000 --- a/CK3ToEU4/Source/CK3/Characters/CharacterDomain.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef CK3_CHARACTERDOMAIN_H -#define CK3_CHARACTERDOMAIN_H -#include "Date.h" -#include "Parser.h" -#include - -namespace CK3 -{ -class Title; -class CharacterDomain: commonItems::parser -{ - public: - CharacterDomain() = default; - CharacterDomain(std::istream& theStream); - - [[nodiscard]] auto isPowerfulVassal() const { return powerfulVassal; } - [[nodiscard]] auto getVassalStrength() const { return vassalStrength; } - [[nodiscard]] const auto& getGovernment() const { return government; } - [[nodiscard]] const auto& getLaws() const { return laws; } - [[nodiscard]] const auto& getRealmCapital() const { return realmCapital; } - [[nodiscard]] const auto& getDomain() const { return domain; } - - void loadRealmCapital(const std::pair>& theRealmCapital) { realmCapital = theRealmCapital; } - void loadDomain(const std::vector>>& theDomain) { domain = theDomain; } - - private: - void registerKeys(); - - bool powerfulVassal = false; - double vassalStrength = 0; - std::string government; - std::set laws; - std::pair> realmCapital; // A barony! - std::vector>> domain; // These are all titles owned (b-c-d-k-e), landless included. First one is PRIMARY. -}; -} // namespace CK3 - -#endif // CK3_CHARACTERDOMAIN_H diff --git a/CK3ToEU4/Source/CK3/Characters/Characters.cpp b/CK3ToEU4/Source/CK3/Characters/Characters.cpp deleted file mode 100644 index 923ec7fc..00000000 --- a/CK3ToEU4/Source/CK3/Characters/Characters.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "Characters.h" -#include "../../Mappers/TraitScraper/TraitScraper.h" -#include "../Cultures/Cultures.cs" -#include "../Dynasties/House.cs" -#include "../Dynasties/Houses.cs" -#include "../Religions/Faiths.cs" -#include "../Titles/Title.h" -#include "../Titles/Titles.cs" -#include "Character.h" -#include "CharacterDomain.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -void CK3::Characters::loadCharacters(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void CK3::Characters::registerKeys() -{ - registerRegex(R"(\d+)", [this](const std::string& charID, std::istream& theStream) { - auto newCharacter = std::make_shared(theStream, std::stoll(charID)); - characters.insert(std::pair(newCharacter->getID(), newCharacter)); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -void CK3::Characters::linkCultures(const Cultures& cultures) -{ - auto counter = 0; - const auto& cultureData = cultures.getCultures(); - for (const auto& character: characters) - { - if (!character.second->getCulture()) - { - // We'll sideload this later. - continue; - } - const auto& cultureDataItr = cultureData.find(character.second->getCulture()->first); - if (cultureDataItr != cultureData.end()) - { - character.second->loadCulture(*cultureDataItr); - ++counter; - } - else - { - throw std::runtime_error("Character " + std::to_string(character.first) + " has culture " + std::to_string(character.second->getCulture()->first) + - " which has no definition!"); - } - } - Log(LogLevel::Info) << "<> " << counter << " characters updated."; -} - -void CK3::Characters::linkFaiths(const Faiths& faiths) -{ - auto counter = 0; - const auto& faithData = faiths.getFaiths(); - for (const auto& character: characters) - { - if (!character.second->getFaith()) - { - // We'll sideload this later. - continue; - } - const auto& faithDataItr = faithData.find(character.second->getFaith()->first); - if (faithDataItr != faithData.end()) - { - character.second->loadFaith(*faithDataItr); - ++counter; - } - else - { - throw std::runtime_error("Character " + std::to_string(character.first) + " has faith " + std::to_string(character.second->getFaith()->first) + - " which has no definition!"); - } - } - Log(LogLevel::Info) << "<> " << counter << " characters updated."; -} - -void CK3::Characters::linkHouses(const Houses& houses) -{ - auto counter = 0; - auto missingFaith = 0; - auto missingCulture = 0; - const auto& houseData = houses.getHouses(); - for (const auto& character: characters) - { - const auto& houseDataItr = houseData.find(character.second->getHouse().first); - if (houseDataItr != houseData.end()) - { - character.second->loadHouse(*houseDataItr); - ++counter; - if (!character.second->getCulture()) - { - if (character.second->getHouse().second->getHouseHead() && character.second->getHouse().second->getHouseHead()->second->getCulture()) - character.second->loadCulture(*character.second->getHouse().second->getHouseHead()->second->getCulture()); - else - missingCulture++; - } - if (!character.second->getFaith()) - { - if (character.second->getHouse().second->getHouseHead() && character.second->getHouse().second->getHouseHead()->second->getFaith()) - character.second->loadFaith(*character.second->getHouse().second->getHouseHead()->second->getFaith()); - else - missingFaith++; - } - } - else - { - throw std::runtime_error( - "Character " + std::to_string(character.first) + " has house " + std::to_string(character.second->getHouse().first) + " which has no definition!"); - } - } - Log(LogLevel::Info) << "<> " << counter << " characters updated, " << missingCulture << " are missing culture, " << missingFaith << " are missing faith."; -} - -void CK3::Characters::linkTitles(const Titles& titles) -{ - auto capitalCounter = 0; - auto titleCounter = 0; - auto claimCounter = 0; - const auto& titleData = titles.getTitles(); - // Since titles are locked behind name keys and we'll needs IDs, make a cache. - std::map> IDCache; - for (const auto& title: titleData) - IDCache.insert(std::pair(title.second->getID(), title.second)); - - for (const auto& character: characters) - { - const auto& domain = character.second->getCharacterDomain(); - if (domain && domain->getRealmCapital().first) - { - // load realm capital - auto titleDataItr = IDCache.find(domain->getRealmCapital().first); - if (titleDataItr != IDCache.end()) - { - character.second->loadRealmCapital(*titleDataItr); - ++capitalCounter; - } - else - { - Log(LogLevel::Warning) << "Character " << character.first << " has capital " << domain->getRealmCapital().first << " which has no definition!"; - } - // load owned including landless titles ("the domain"). - std::vector>> replacementDomain; - for (const auto& title: domain->getDomain()) - { - titleDataItr = IDCache.find(title.first); - if (titleDataItr != IDCache.end()) - { - replacementDomain.emplace_back(*titleDataItr); - ++titleCounter; - } - else - { - throw std::runtime_error( - "Character " + std::to_string(character.first) + " owns title " + std::to_string(title.first) + " which has no definition!"); - } - } - character.second->loadDomain(replacementDomain); - } - // Now claims. - std::map> replacementClaims; - for (const auto& claim: character.second->getClaims()) - { - auto titleDataItr = IDCache.find(claim.first); - if (titleDataItr != IDCache.end()) - { - replacementClaims.insert(*titleDataItr); - ++claimCounter; - } - else - { - Log(LogLevel::Error) << "Character " << std::to_string(character.first) << " claims title " << std::to_string(claim.first) - << " which has no definition!"; - } - } - character.second->loadClaims(replacementClaims); - } - Log(LogLevel::Info) << "<> " << capitalCounter << " capitals, " << titleCounter << " titles and " << claimCounter << " claims updated."; -} - -void CK3::Characters::linkCharacters() -{ - auto employerCounter = 0; - auto spouseCounter = 0; - - for (const auto& character: characters) - { - if (character.second->getSpouse()) - { - const auto& charItr = characters.find(character.second->getSpouse()->first); - if (charItr != characters.end()) - { - character.second->loadSpouse(*charItr); - ++spouseCounter; - } - else - { - // dead spouse. - character.second->resetSpouse(); - } - } - if (character.second->getEmployer()) - { - const auto& charItr = characters.find(character.second->getEmployer()->first); - if (charItr != characters.end()) - { - character.second->loadEmployer(*charItr); - ++employerCounter; - } - else - { - // sigh. - character.second->resetEmployer(); - } - } - } - Log(LogLevel::Info) << "<> " << spouseCounter << " spouses, " << employerCounter << " employers updated."; -} - -void CK3::Characters::linkTraits(const mappers::TraitScraper& traitScraper) -{ - auto counter = 0; - for (const auto& character: characters) - { - std::map translatedTraits; - for (const auto& trait: character.second->getTraits()) - { - const auto& traitMatch = traitScraper.getTraitForID(trait.first); - if (traitMatch) - translatedTraits.insert(std::pair(trait.first, *traitMatch)); - } - counter += static_cast(translatedTraits.size()); - character.second->loadTraits(translatedTraits); - } - Log(LogLevel::Info) << "<> " << counter << " traits observed."; -} diff --git a/CK3ToEU4/Source/CK3/Characters/Characters.cs b/CK3ToEU4/Source/CK3/Characters/Characters.cs new file mode 100644 index 00000000..9dbd0a70 --- /dev/null +++ b/CK3ToEU4/Source/CK3/Characters/Characters.cs @@ -0,0 +1,239 @@ + +using commonItems; + +namespace CK3ToEU4.CK3.Characters; + +class Characters +{ + public Characters() {} + public void loadCharacters(BufferedReader reader) + { + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); + } + + public const auto& getCharacters() const { return characters; } + + public void linkCultures(const Cultures& cultures) + { + auto counter = 0; + const auto& cultureData = cultures.getCultures(); + for (const auto& character: characters) + { + if (!character.second->getCulture()) + { + // We'll sideload this later. + continue; + } + const auto& cultureDataItr = cultureData.find(character.second->getCulture()->first); + if (cultureDataItr != cultureData.end()) + { + character.second->loadCulture(*cultureDataItr); + ++counter; + } + else + { + throw std::runtime_error("Character " + std::to_string(character.first) + " has culture " + std::to_string(character.second->getCulture()->first) + + " which has no definition!"); + } + } + Log(LogLevel::Info) << "<> " + counter + " characters updated."; + } + public void linkFaiths(const Faiths& faiths) + { + auto counter = 0; + const auto& faithData = faiths.getFaiths(); + for (const auto& character: characters) + { + if (!character.second->getFaith()) + { + // We'll sideload this later. + continue; + } + const auto& faithDataItr = faithData.find(character.second->getFaith()->first); + if (faithDataItr != faithData.end()) + { + character.second->loadFaith(*faithDataItr); + ++counter; + } + else + { + throw std::runtime_error("Character " + std::to_string(character.first) + " has faith " + std::to_string(character.second->getFaith()->first) + + " which has no definition!"); + } + } + Log(LogLevel::Info) << "<> " << counter << " characters updated."; + } + public void linkHouses(const Houses& houses) + + { + auto counter = 0; + auto missingFaith = 0; + auto missingCulture = 0; + const auto& houseData = houses.getHouses(); + for (const auto& character: characters) + { + const auto& houseDataItr = houseData.find(character.second->getHouse().first); + if (houseDataItr != houseData.end()) + { + character.second->loadHouse(*houseDataItr); + ++counter; + if (!character.second->getCulture()) + { + if (character.second->getHouse().second->getHouseHead() && character.second->getHouse().second->getHouseHead()->second->getCulture()) + character.second->loadCulture(*character.second->getHouse().second->getHouseHead()->second->getCulture()); + else + missingCulture++; + } + if (!character.second->getFaith()) + { + if (character.second->getHouse().second->getHouseHead() && character.second->getHouse().second->getHouseHead()->second->getFaith()) + character.second->loadFaith(*character.second->getHouse().second->getHouseHead()->second->getFaith()); + else + missingFaith++; + } + } + else + { + throw std::runtime_error( + "Character " + std::to_string(character.first) + " has house " + std::to_string(character.second->getHouse().first) + " which has no definition!"); + } + } + Log(LogLevel::Info) << "<> " << counter << " characters updated, " << missingCulture << " are missing culture, " << missingFaith << " are missing faith."; + } + public void linkTitles(const Titles& titles) + + { + auto capitalCounter = 0; + auto titleCounter = 0; + auto claimCounter = 0; + const auto& titleData = titles.getTitles(); + // Since titles are locked behind name keys and we'll needs IDs, make a cache. + std::map> IDCache; + for (const auto& title: titleData) + IDCache.insert(std::pair(title.second->getID(), title.second)); + + for (const auto& character: characters) + { + const auto& domain = character.second->getCharacterDomain(); + if (domain && domain->getRealmCapital().first) + { + // load realm capital + auto titleDataItr = IDCache.find(domain->getRealmCapital().first); + if (titleDataItr != IDCache.end()) + { + character.second->loadRealmCapital(*titleDataItr); + ++capitalCounter; + } + else + { + Log(LogLevel::Warning) << "Character " << character.first << " has capital " << domain->getRealmCapital().first << " which has no definition!"; + } + // load owned including landless titles ("the domain"). + std::vector>> replacementDomain; + for (const auto& title: domain->getDomain()) + { + titleDataItr = IDCache.find(title.first); + if (titleDataItr != IDCache.end()) + { + replacementDomain.emplace_back(*titleDataItr); + ++titleCounter; + } + else + { + throw std::runtime_error( + "Character " + std::to_string(character.first) + " owns title " + std::to_string(title.first) + " which has no definition!"); + } + } + character.second->loadDomain(replacementDomain); + } + // Now claims. + std::map> replacementClaims; + for (const auto& claim: character.second->getClaims()) + { + auto titleDataItr = IDCache.find(claim.first); + if (titleDataItr != IDCache.end()) + { + replacementClaims.insert(*titleDataItr); + ++claimCounter; + } + else + { + Log(LogLevel::Error) << "Character " << std::to_string(character.first) << " claims title " << std::to_string(claim.first) + << " which has no definition!"; + } + } + character.second->loadClaims(replacementClaims); + } + Log(LogLevel::Info) << "<> " << capitalCounter << " capitals, " << titleCounter << " titles and " << claimCounter << " claims updated."; + } + public void linkCharacters() + + { + auto employerCounter = 0; + auto spouseCounter = 0; + + for (const auto& character: characters) + { + if (character.second->getSpouse()) + { + const auto& charItr = characters.find(character.second->getSpouse()->first); + if (charItr != characters.end()) + { + character.second->loadSpouse(*charItr); + ++spouseCounter; + } + else + { + // dead spouse. + character.second->resetSpouse(); + } + } + if (character.second->getEmployer()) + { + const auto& charItr = characters.find(character.second->getEmployer()->first); + if (charItr != characters.end()) + { + character.second->loadEmployer(*charItr); + ++employerCounter; + } + else + { + // sigh. + character.second->resetEmployer(); + } + } + } + Log(LogLevel::Info) << "<> " << spouseCounter << " spouses, " << employerCounter << " employers updated."; + } + public void linkTraits(TraitScraper traitScraper) + { + auto counter = 0; + for (const auto& character: characters) + { + std::map translatedTraits; + for (const auto& trait: character.second->getTraits()) + { + const auto& traitMatch = traitScraper.getTraitForID(trait.first); + if (traitMatch) + translatedTraits.insert(std::pair(trait.first, *traitMatch)); + } + counter += static_cast(translatedTraits.size()); + character.second->loadTraits(translatedTraits); + } + Log(LogLevel::Info) << "<> " << counter << " traits observed."; + } + + + private void registerKeys() + { + registerRegex(R"(\d+)", [this](const std::string& charID, std::istream& theStream) { + auto newCharacter = std::make_shared(theStream, std::stoll(charID)); + characters.insert(std::pair(newCharacter->getID(), newCharacter)); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + private std::map> characters; +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Characters/Characters.h b/CK3ToEU4/Source/CK3/Characters/Characters.h deleted file mode 100644 index 2f8e3f03..00000000 --- a/CK3ToEU4/Source/CK3/Characters/Characters.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef CK3_CHARACTERS_H -#define CK3_CHARACTERS_H -#include "Parser.h" - -namespace mappers -{ -class TraitScraper; -} - -namespace CK3 -{ -class Cultures; -class Faiths; -class Character; -class Houses; -class Titles; -class Characters: commonItems::parser -{ - public: - Characters() = default; - void loadCharacters(std::istream& theStream); - - [[nodiscard]] const auto& getCharacters() const { return characters; } - - void linkCultures(const Cultures& cultures); - void linkFaiths(const Faiths& faiths); - void linkHouses(const Houses& houses); - void linkTitles(const Titles& titles); - void linkCharacters(); - void linkTraits(const mappers::TraitScraper& traitScraper); - - private: - void registerKeys(); - - std::map> characters; -}; -} // namespace CK3 - -#endif // CK3_CHARACTERS_H diff --git a/CK3ToEU4/Source/CK3/Dynasties/House.cs b/CK3ToEU4/Source/CK3/Dynasties/House.cs index b36ed97a..32257427 100644 --- a/CK3ToEU4/Source/CK3/Dynasties/House.cs +++ b/CK3ToEU4/Source/CK3/Dynasties/House.cs @@ -1,4 +1,8 @@ +using System.Collections.Generic; +using CK3; +using commonItems; + namespace CK3ToEU4.CK3.Dynasties; class House @@ -8,58 +12,61 @@ public House() { } - public House(std::istream& theStream, long housID) + public House(BufferedReader reader, long houseID) { - houseID = housID; - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); + ID = houseID; + + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); } - public const auto& getKey() const { return key; } - public const auto& getName() const { return name; } - public const auto& getLocalizedName() const { return localizedName; } - public const auto& getPrefix() const { return prefix; } - public const auto& getDynasty() const { return dynasty; } - public const auto& getID() const { return houseID; } - public const auto& getHouseHead() const { return houseHead; } + public string getKey() { return key; } + public string getName() { return name; } + public string getLocalizedName() { return localizedName; } + public string getPrefix() { return prefix; } + public KeyValuePair getDynasty() { return dynasty; } + public long ID { get; private set; } = 0; + public KeyValuePair? getHouseHead() { return houseHead; } + + public void loadDynasty(KeyValuePair theDynasty) { dynasty = theDynasty; } + public void loadHouseHead(KeyValuePair theHead) { houseHead = theHead; } - public void loadDynasty(const KeyValuePair>& theDynasty) { dynasty = theDynasty; } - public void loadHouseHead(const KeyValuePair>& theHead) { houseHead = theHead; } - public void resetHouseHead() { houseHead.reset(); } + public void resetHouseHead() + { + houseHead = null; + } - public void setName(const string& theName) { name = theName; } - public void setPrefix(const string& thePrefix) { prefix = thePrefix; } + public void setName(string theName) { name = theName; } + public void setPrefix(string thePrefix) { prefix = thePrefix; } - private void registerKeys() + private void registerKeys(Parser parser) { - registerKeyword("key", [this](BufferedReader reader) { + parser.RegisterKeyword("key", reader => { key = reader.GetString(); }); - registerKeyword("name", reader => { + parser.RegisterKeyword("name", reader => { name = reader.GetString(); }); - registerKeyword("localized_name", reader => { + parser.RegisterKeyword("localized_name", reader => { localizedName = reader.GetString(); }); - registerKeyword("prefix", reader => { + parser.RegisterKeyword("prefix", reader => { prefix = reader.GetString(); }); - registerKeyword("dynasty", reader => { - dynasty = std::make_pair(reader.GetLong(), nullptr); + parser.RegisterKeyword("dynasty", reader => { + dynasty = new(reader.GetLong(), null); }); - registerKeyword("head_of_house", reader => { - houseHead = std::make_pair(reader.GetLong(), nullptr); + parser.RegisterKeyword("head_of_house", reader => { + houseHead = new(reader.GetLong(), null); }); - registerRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); } - - - private long houseID = 0; + private string key; private string name; private string localizedName; - private KeyValuePair> dynasty; + private KeyValuePair dynasty; private string prefix; - private std::optional>> houseHead; // houses can have missing heads or dead people... + private KeyValuePair? houseHead; // houses can have missing heads or dead people... }; \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Flags/Flags.cs b/CK3ToEU4/Source/CK3/Flags/Flags.cs index 813f1191..120d9251 100644 --- a/CK3ToEU4/Source/CK3/Flags/Flags.cs +++ b/CK3ToEU4/Source/CK3/Flags/Flags.cs @@ -1,58 +1,55 @@ -#ifndef CK3_FLAGS_H -#define CK3_FLAGS_H -#include +using System.Collections.Generic; +using commonItems; +using Open.Collections; -#include "Parser.h" +namespace CK3ToEU4.CK3.Flags; -namespace CK3 +class Flags { -class Flags: commonItems::parser -{ - public: - Flags() = default; - explicit Flags(BufferedReader reader) + public Flags() { - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); + } - if (itemType == "flag" && !incomingFlag.empty()) - flags.insert(incomingFlag); + public Flags(BufferedReader reader) + { + var parser = new Parser(); + RegisterKeys(parser); + parser.ParseStream(reader); + + if (itemType == "flag" && incomingFlag.Length > 0) + { + flags.Add(incomingFlag); + } } - [[nodiscard]] const auto& getFlags() const { return flags; } + public IReadOnlySet getFlags() { return flags; } - private: - void registerKeys() + private void RegisterKeys(Parser parser) { - registerKeyword("list", reader => { - for (const auto& blob: commonItems::blobList(theStream).getBlobs()) + parser.RegisterKeyword("list", reader => { + foreach (var blob in new BlobList(reader).Blobs) { - auto blobStream = stringstream(blob); - const auto scraper = Flags(blobStream); - const auto& foundFlags = scraper.getFlags(); - flags.insert(foundFlags.begin(), foundFlags.end()); + var blobReader = new BufferedReader(blob); + var scraper = new Flags(blobReader); + var foundFlags = scraper.getFlags(); + flags.AddRange(foundFlags); } }); - registerKeyword("item", reader => { - const auto scraper = Flags(theStream); - const auto& foundFlags = scraper.getFlags(); - flags.insert(foundFlags.begin(), foundFlags.end()); + parser.RegisterKeyword("item", reader => { + var scraper = new Flags(reader); + var foundFlags = scraper.getFlags(); + flags.AddRange(foundFlags); }); - registerKeyword("flag", reader => { + parser.RegisterKeyword("flag", reader => { incomingFlag = reader.GetString(); }); - registerKeyword("type", reader => { + parser.RegisterKeyword("type", reader => { itemType = reader.GetString(); }); - registerRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); } - - - string itemType; - string incomingFlag; - HashSet flags; -}; -} // namespace CK3 - -#endif // CK3_FLAGS_H + + private string itemType = string.Empty; + private string incomingFlag = string.Empty; + private readonly HashSet flags = []; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Geography/CountyDetails.cs b/CK3ToEU4/Source/CK3/Geography/CountyDetails.cs index ff2cd336..5db02077 100644 --- a/CK3ToEU4/Source/CK3/Geography/CountyDetails.cs +++ b/CK3ToEU4/Source/CK3/Geography/CountyDetails.cs @@ -1,5 +1,6 @@ using CK3; +using CK3ToEU4.CK3.Religions; namespace CK3ToEU4.CK3.Geography; diff --git a/CK3ToEU4/Source/CK3/Religions/Faith.cs b/CK3ToEU4/Source/CK3/Religions/Faith.cs index bdbabf90..d0edbe9d 100644 --- a/CK3ToEU4/Source/CK3/Religions/Faith.cs +++ b/CK3ToEU4/Source/CK3/Religions/Faith.cs @@ -1,5 +1,3 @@ - - using System.Collections.Generic; using commonItems; using commonItems.Colors; @@ -17,28 +15,28 @@ public Faith(BufferedReader reader, long theID, ColorFactory colorFactory) ID = theID; var parser = new Parser(); - registerKeys(parser, colorFactory); + RegisterKeys(parser, colorFactory); parser.ParseStream(reader); } - public const auto& getName() { return tag; } - public const auto& getColor() { return color; } - public const auto& getDoctrines() { return doctrines; } - public const auto& getReligion() { return religion; } - public const auto& getReligiousHead() { return religiousHead; } - public auto getID() { return ID; } - public const auto& getCustomName() { return customName; } - public const auto& getCustomAdj() { return customAdjective; } - public const auto& getDescription() { return description; } - public const auto& getTemplate() { return religionTemplate; } - public const auto& getIconPath() { return iconPath; } - public const auto& getReformedFlag() { return reformedFlag; } + public long ID { get; private set; } = 0; + public string getName() { return tag; } + public Color? Color { return color; } + public IReadOnlyList getDoctrines() { return doctrines; } + public KeyValuePair getReligion() { return religion; } + public string getReligiousHead() { return religiousHead; } + public string getCustomName() { return customName; } + public string getCustomAdj() { return customAdjective; } + public string getDescription() { return description; } + public string getTemplate() { return religionTemplate; } + public string getIconPath() { return iconPath; } + public bool getReformedFlag() { return reformedFlag; } - public void setReligiousHead(const auto& newHead) { religiousHead = newHead; } - public void loadReligion(const KeyValuePair>& theReligion) { religion = theReligion; } + public void setReligiousHead(string newHead) { religiousHead = newHead; } + public void loadReligion(KeyValuePair theReligion) { religion = theReligion; } - private void registerKeys(Parser parser, ColorFactory colorFactory) + private void RegisterKeys(Parser parser, ColorFactory colorFactory) { parser.RegisterKeyword("tag", reader => { tag = reader.GetString(); @@ -71,15 +69,16 @@ private void registerKeys(Parser parser, ColorFactory colorFactory) iconPath = reader.GetString(); }); parser.RegisterKeyword("variables", reader => { - if (commonItems::stringOfItem(theStream).getString().find("has_been_reformed") != string::npos) + if (reader.GetStringOfItem().ToString().Contains("has_been_reformed")) + { reformedFlag = true; + } }); parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); } private bool reformedFlag = false; - private long ID = 0; private string tag; private string religionTemplate; private string iconPath; @@ -88,6 +87,6 @@ private void registerKeys(Parser parser, ColorFactory colorFactory) private string description; private string religiousHead; private Color? color; - private List doctrines; // This is a vector in order to keep order consistent. We want the first things read (tenets) to be the first things output, ALWAYS + private readonly List doctrines = []; // This is a vector in order to keep order consistent. We want the first things read (tenets) to be the first things output, ALWAYS private KeyValuePair religion; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/Religions/Faiths.cs b/CK3ToEU4/Source/CK3/Religions/Faiths.cs index e2ceb4b1..725ceb3a 100644 --- a/CK3ToEU4/Source/CK3/Religions/Faiths.cs +++ b/CK3ToEU4/Source/CK3/Religions/Faiths.cs @@ -1,36 +1,36 @@ -#ifndef CK3_FAITHS_H -#define CK3_FAITHS_H -#include "../Titles/LandedTitles.cs" -#include "../Titles/Title.h" -#include "../Titles/Titles.cs" -#include "Parser.h" +using System; +using System.Collections.Generic; +using commonItems; +using commonItems.Colors; -namespace CK3 -{ -class Faith; -class Religions; -class Faiths: commonItems::parser +namespace CK3ToEU4.CK3.Religions; + +class Faiths { - public: - Faiths() = default; - public Faiths(BufferedReader reader) + public Faiths() {} + public Faiths(BufferedReader reader, ColorFactory colorFactory) { - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); + var parser = new Parser(); + registerKeys(parser, colorFactory); + parser.ParseStream(reader); } - [[nodiscard]] const auto& getFaiths() const { return faiths; } + public IReadOnlyDictionary getFaiths() { return faiths; } - void linkReligions(const Religions& religions, const Titles& titles) + public void linkReligions(Religions religions, Titles.Titles titles) { - auto counter = 0; - const auto& religionData = religions.getReligions(); + int counter = 0; + var religionData = religions.getReligions(); Dictionary religiousHeadList; // ID, Title - for (const auto& title: titles.getTitles()) + foreach (var title in titles.getTitles()) + { if (title.second) + { religiousHeadList.emplace(std::to_string(title.second->getID()), title.first); - for (const auto& faith: faiths) + } + } + + foreach (var faith in faiths) { const auto& religionDataItr = religionData.find(faith.second->getReligion().first); if (religionDataItr != religionData.end()) @@ -43,24 +43,20 @@ void linkReligions(const Religions& religions, const Titles& titles) else { throw new Exception( - "Faith " + faith.second->getName() + " has religion " + std::to_string(faith.second->getReligion().first) + " which has no definition!"); + "Faith " + faith.Value.getName() + " has religion " + faith.Value.getReligion().Key + " which has no definition!"); } } - Log(LogLevel::Info) << "<> " << counter << " faiths updated."; + Logger.Info("<> " + counter + " faiths updated."); } - private: - void registerKeys() + private void registerKeys(Parser parser, ColorFactory colorFactory) { - registerRegex(R"(\d+)", [this](const string& faithID, std::istream& theStream) { - auto newFaith = std::make_shared(theStream, std::stoll(faithID)); - faiths.insert(std::pair(newFaith->getID(), newFaith)); + parser.RegisterRegex(CommonRegexes.Integer, (reader, faithId) => { + var newFaith = new Faith(reader, long.Parse(faithId), colorFactory); + faiths.Add(newFaith.ID, newFaith); }); - registerRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); } - Dictionary> faiths; -}; -} // namespace CK3 - -#endif // CK3_FAITHS_H + private Dictionary faiths; +} diff --git a/CK3ToEU4/Source/CK3/Religions/Religions.cs b/CK3ToEU4/Source/CK3/Religions/Religions.cs index 2a7bd8ea..2ee31fef 100644 --- a/CK3ToEU4/Source/CK3/Religions/Religions.cs +++ b/CK3ToEU4/Source/CK3/Religions/Religions.cs @@ -1,31 +1,31 @@ - -using CK3; +using System; +using System.Collections.Generic; +using commonItems; namespace CK3ToEU4.CK3.Religions; class Religions { - public: - explicit Religions(BufferedReader reader) + public Religions(BufferedReader reader) { - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); } - [[nodiscard]] const auto& getReligions() const { return religions; } - [[nodiscard]] auto getFaiths() { return std::move(faiths); } // Use this only once in World.cpp + public IReadOnlyDictionary getReligions() { return religions; } + public Faith getFaiths() { return faiths; } // Use this only once in World.cpp - void linkFaiths(const Faiths& theFaiths) + void linkFaiths(Faiths theFaiths) { - auto counter = 0; - const auto& faithData = theFaiths.getFaiths(); - for (const auto& religion: religions) + int counter = 0; + var faithData = theFaiths.getFaiths(); + foreach (var religion in religions) { - const auto& religionFaiths = religion.second->getFaiths(); - Dictionary> replacementMap; + var religionFaiths = religion.Value.getFaiths(); + Dictionary replacementMap; - for (const auto& faith: religionFaiths) + foreach (var faith in religionFaiths) { const auto& faithDataItr = faithData.find(faith.first); if (faithDataItr != faithData.end()) @@ -34,31 +34,30 @@ void linkFaiths(const Faiths& theFaiths) } else { - throw new Exception("Religion " + religion.second->getName() + " has faith " + std::to_string(faith.first) + " which has no definition!"); + throw new Exception($"Religion {religion.Value.getName()} has faith {faith.Key} which has no definition!"); } } - religion.second->loadFaiths(replacementMap); + religion.Value.loadFaiths(replacementMap); ++counter; } - Log(LogLevel::Info) << "<> " << counter << " religions updated."; + Logger.Info("<> " + counter + " religions updated."); } - private: - void registerKeys() + private void registerKeys(Parser parser) { - registerRegex(R"(\d+)", [this](const string& faithID, std::istream& theStream) { - auto newReligion = std::make_shared(theStream, std::stoll(faithID)); - religions.insert(std::pair(newReligion->getID(), newReligion)); + parser.RegisterRegex(CommonRegexes.Integer, (reader, faithID) => { + var newReligion = new Religion(reader, long.Parse(faithID)); + religions.Add(newReligion.ID, newReligion); }); - registerKeyword("religions", reader => { - religions = Religions(theStream).getReligions(); + parser.RegisterKeyword("religions", reader => { + religions = new(new Religions(reader).getReligions()); }); - registerKeyword("faiths", reader => { - faiths = Faiths(theStream); + parser.RegisterKeyword("faiths", reader => { + faiths = new Faiths(reader); }); - registerRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); + parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreItem); } - Dictionary> religions; + Dictionary religions; Faiths faiths; }; \ No newline at end of file diff --git a/CK3ToEU4/Source/CK3/World.cs b/CK3ToEU4/Source/CK3/World.cs index e022a8bf..eb60a5f8 100644 --- a/CK3ToEU4/Source/CK3/World.cs +++ b/CK3ToEU4/Source/CK3/World.cs @@ -1,8 +1,14 @@ using System; using System.Collections.Generic; using System.IO; +using CK3; +using CK3ToEU4.CK3.Dynasties; +using CK3ToEU4.CK3.Geography; +using CK3ToEU4.CK3.Religions; using CK3ToEU4.CK3.Titles; using CK3ToEU4.Configuration; +using CK3ToEU4.Mappers.NamedColors; +using CK3ToEU4.Mappers.TraitScraper; using commonItems; using commonItems.Mods; using SystemUtils = commonItems.SystemUtils; @@ -1138,7 +1144,7 @@ private void setElectors() } } - Logger.Info("<> " << counter << " electorates linked."); + Logger.Info("<> " + counter + " electorates linked."); } diff --git a/CK3ToEU4/Source/CK3World/World.h b/CK3ToEU4/Source/CK3World/World.h index d160d3a0..b5d82f52 100644 --- a/CK3ToEU4/Source/CK3World/World.h +++ b/CK3ToEU4/Source/CK3World/World.h @@ -1,11 +1,11 @@ #ifndef CK3_WORLD_H #define CK3_WORLD_H -#include "../Mappers/CultureMapper/CultureMapper.h" +#include "../Mappers/CultureMapper/CultureMapper.cs" #include "../Mappers/IAmHreMapper/IAmHreMapper.h" -#include "../Mappers/LocalizationMapper/LocalizationMapper.h" -#include "../Mappers/NamedColors/NamedColors.h" +#include "../Mappers/LocalizationMapper/LocalizationMapper.cs" +#include "../Mappers/NamedColors/NamedColors.cs" #include "../Mappers/ShatterEmpiresMapper/ShatterEmpiresMapper.h" -#include "../Mappers/TraitScraper/TraitScraper.h" +#include "../Mappers/TraitScraper/TraitScraper.cs" #include "../Mappers/VassalSplitoffMapper/VassalSplitoffMapper.h" #include "Characters/Characters.h" #include "CoatsOfArms/CoatsOfArms.h" diff --git a/CK3ToEU4/Source/EU4World/Country/Country.cpp b/CK3ToEU4/Source/EU4World/Country/Country.cpp index 885c6f8d..ca007870 100644 --- a/CK3ToEU4/Source/EU4World/Country/Country.cpp +++ b/CK3ToEU4/Source/EU4World/Country/Country.cpp @@ -10,7 +10,7 @@ #include "../../CK3World/Titles/Title.h" #include "../../Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.h" #include "../../Mappers/CultureDefinitionsMapper/CultureGroupDefinition.h" -#include "../../Mappers/CultureMapper/CultureMapper.h" +#include "../../Mappers/CultureMapper/CultureMapper.cs" #include "../../Mappers/GovernmentsMapper/GovernmentsMapper.h" #include "../../Mappers/ProvinceMapper/ProvinceMapper.h" #include "../../Mappers/ReligionMapper/ReligionMapper.h" diff --git a/CK3ToEU4/Source/EU4World/Country/Country.h b/CK3ToEU4/Source/EU4World/Country/Country.h index cbec5e47..b10fceef 100644 --- a/CK3ToEU4/Source/EU4World/Country/Country.h +++ b/CK3ToEU4/Source/EU4World/Country/Country.h @@ -3,7 +3,7 @@ #include "../../Configuration/Configuration.h" #include "../../Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.h" -#include "../../Mappers/LocalizationMapper/LocalizationMapper.h" +#include "../../Mappers/LocalizationMapper/LocalizationMapper.cs" #include "CountryDetails.h" #include #include diff --git a/CK3ToEU4/Source/EU4World/EU4World.h b/CK3ToEU4/Source/EU4World/EU4World.h index b30b0c1f..215ac6ad 100644 --- a/CK3ToEU4/Source/EU4World/EU4World.h +++ b/CK3ToEU4/Source/EU4World/EU4World.h @@ -4,13 +4,13 @@ #include "../CK3World/World.h" #include "../Mappers/AfricanPassesMapper/AfricanPassesMapper.h" #include "../Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.h" -#include "../Mappers/CultureMapper/CultureMapper.h" +#include "../Mappers/CultureMapper/CultureMapper.cs" #include "../Mappers/DevWeightsMapper/DevWeightsMapper.h" #include "../Mappers/DynamicIdeasMapper/DynamicIdeasMapper.h" #include "../Mappers/GovernmentsMapper/GovernmentsMapper.h" #include "../Mappers/IslamOverrideMapper/IslamOverrideMapper.h" #include "../Mappers/LocDegraderMapper/LocDegraderMapper.h" -#include "../Mappers/LocalizationMapper/LocalizationMapper.h" +#include "../Mappers/LocalizationMapper/LocalizationMapper.cs" #include "../Mappers/PrimaryTagMapper/PrimaryTagMapper.h" #include "../Mappers/ProvinceMapper/ProvinceMapper.h" #include "../Mappers/RegionMapper/RegionMapper.h" diff --git a/CK3ToEU4/Source/EU4World/Province/EU4Province.cpp b/CK3ToEU4/Source/EU4World/Province/EU4Province.cpp index 0cd24984..994ffa59 100644 --- a/CK3ToEU4/Source/EU4World/Province/EU4Province.cpp +++ b/CK3ToEU4/Source/EU4World/Province/EU4Province.cpp @@ -5,7 +5,7 @@ #include "../../CK3World/Religions/Faith.h" #include "../../CK3World/Titles/LandedTitles.h" #include "../../CK3World/Titles/Title.h" -#include "../../Mappers/CultureMapper/CultureMapper.h" +#include "../../Mappers/CultureMapper/CultureMapper.cs" #include "../../Mappers/ReligionMapper/ReligionMapper.h" #include "../Country/Country.h" #include "Log.h" diff --git a/CK3ToEU4/Source/Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.cpp b/CK3ToEU4/Source/Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.cpp index 76f9a46c..fd473804 100644 --- a/CK3ToEU4/Source/Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.cpp +++ b/CK3ToEU4/Source/Mappers/CultureDefinitionsMapper/CultureDefinitionsMapper.cpp @@ -2,7 +2,7 @@ #include "../../CK3World/Cultures/Culture.h" #include "../../Configuration/Configuration.h" #include "../CultureDefinitionsMapper/CultureDefiniton.h" -#include "../CultureMapper/CultureMapper.h" +#include "../CultureMapper/CultureMapper.cs" #include "CommonRegexes.h" #include "CultureGroupDefinition.h" #include "Log.h" diff --git a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cpp b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cpp deleted file mode 100644 index b2e05ae3..00000000 --- a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "CultureMapper.h" -#include "../../CK3World/Cultures/Culture.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" -#include - -mappers::CultureMapper::CultureMapper(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); - buildCultureCaches(); -} - -void mappers::CultureMapper::loadCulturesFromDisk() -{ - Log(LogLevel::Info) << "-> Parsing culture mappings."; - registerKeys(); - parseFile("configurables/culture_map.txt"); - clearRegisteredKeywords(); - buildCultureCaches(); - Log(LogLevel::Info) << "<> Loaded " << cultureMapRules.size() << " cultural links."; -} - -void mappers::CultureMapper::storeCultures(const std::set>& incCultures) -{ - for (const auto culture: incCultures) - { - if (culture->isEU4Ready()) - eu4Overrides.insert(culture->getName()); - else if (culture->isDynamic()) - eu4Overrides.insert(culture->getName()); - } - cultures = incCultures; -} - - -void mappers::CultureMapper::loadRegionMapper(const std::shared_ptr& theRegionMapper) -{ - for (auto& rule: cultureMapRules) - rule.insertRegionMapper(theRegionMapper); -} - -void mappers::CultureMapper::registerKeys() -{ - registerKeyword("link", [this](std::istream& theStream) { - const CultureMappingRule rule(theStream); - cultureMapRules.push_back(rule); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - -std::optional mappers::CultureMapper::cultureMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const -{ - if (eu4Overrides.contains(ck3culture)) - return ck3culture; - - for (const auto& cultureMappingRule: cultureMapRules) - { - const auto& possibleMatch = cultureMappingRule.cultureMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); - if (possibleMatch) - return *possibleMatch; - } - return std::nullopt; -} - -std::optional mappers::CultureMapper::cultureRegionalMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const -{ - if (eu4Overrides.contains(ck3culture)) - return ck3culture; - - for (const auto& cultureMappingRule: cultureMapRules) - { - const auto& possibleMatch = cultureMappingRule.cultureRegionalMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); - if (possibleMatch) - return *possibleMatch; - } - return std::nullopt; -} - -std::optional mappers::CultureMapper::cultureNonRegionalNonReligiousMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const -{ - if (eu4Overrides.contains(ck3culture)) - return ck3culture; - - for (const auto& cultureMappingRule: cultureMapRules) - { - const auto& possibleMatch = cultureMappingRule.cultureNonRegionalNonReligiousMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); - if (possibleMatch) - return *possibleMatch; - } - return std::nullopt; -} - -std::optional mappers::CultureMapper::getTechGroup(const std::string& incEU4Culture) const -{ - auto checkCulture = incEU4Culture; - if (eu4Overrides.contains(incEU4Culture)) - { - // if this is dynamic (not eu4ready) then see if we can grab a nonregional nonreligious mapping and ping the results of that. - for (const auto& culture: cultures) - { - // Log(LogLevel::Debug) << "> vs: " << culture->getName() << " | " << culture->isDynamic() << " | " << culture->getNameList().empty(); - - if (culture->getName() == incEU4Culture && culture->isDynamic() && !culture->getNameLists().empty()) - { - const auto& origCulture = *culture->getNameLists().begin(); - const auto& match = cultureNonRegionalNonReligiousMatch(origCulture, "", 0, ""); - if (match) - checkCulture = *match; - } - } - } - - for (const auto& mapping: cultureMapRules) - if (mapping.getTechGroup(checkCulture)) - return mapping.getTechGroup(checkCulture); - return std::nullopt; -} - -std::optional mappers::CultureMapper::getGFX(const std::string& incEU4Culture) const -{ - auto checkCulture = incEU4Culture; - if (eu4Overrides.contains(incEU4Culture)) - { - // if this is dynamic (not eu4ready) then see if we can grab a nonregional nonreligious mapping and ping the results of that. - for (const auto& culture: cultures) - { - if (culture->getName() == incEU4Culture && culture->isDynamic() && !culture->getNameLists().empty()) - { - const auto& origCulture = *culture->getNameLists().begin(); - const auto& match = cultureNonRegionalNonReligiousMatch(origCulture, "", 0, ""); - if (match) - checkCulture = *match; - } - } - } - - for (const auto& mapping: cultureMapRules) - if (mapping.getGFX(checkCulture)) - return mapping.getGFX(checkCulture); - return std::nullopt; -} - -void mappers::CultureMapper::buildCultureCaches() -{ - for (const auto& mappingRule: cultureMapRules) - { - targetCultures.insert(mappingRule.getEU4Culture()); - for (const auto& culture: mappingRule.getCK3Cultures()) - sourceCultures.insert(culture); - } -} diff --git a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cs b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cs new file mode 100644 index 00000000..7081fce8 --- /dev/null +++ b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.cs @@ -0,0 +1,173 @@ + +using CK3ToEU4.Mappers.CultureMapper; + +namespace mappers; + +class CultureMapper +{ + public CultureMapper() = default; + public CultureMapper(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + buildCultureCaches(); + } + public void loadCulturesFromDisk() + { + Log(LogLevel::Info) << "-> Parsing culture mappings."; + registerKeys(); + parseFile("configurables/culture_map.txt"); + clearRegisteredKeywords(); + buildCultureCaches(); + Log(LogLevel::Info) << "<> Loaded " << cultureMapRules.size() << " cultural links."; + } + + public void loadRegionMapper(const std::shared_ptr& theRegionMapper) + { + for (auto& rule: cultureMapRules) + rule.insertRegionMapper(theRegionMapper); + } + public void storeCultures(const std::set>& incCultures) + { + for (const auto culture: incCultures) + { + if (culture->isEU4Ready()) + eu4Overrides.insert(culture->getName()); + else if (culture->isDynamic()) + eu4Overrides.insert(culture->getName()); + } + cultures = incCultures; + } + + public std::optional cultureMatch(const std::string& ck3culture, + const std::string& eu4religion, + int eu4Province, + const std::string& eu4ownerTag) + { + if (eu4Overrides.contains(ck3culture)) + return ck3culture; + + for (const auto& cultureMappingRule: cultureMapRules) + { + const auto& possibleMatch = cultureMappingRule.cultureMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); + if (possibleMatch) + return *possibleMatch; + } + return std::nullopt; + } + + public std::optional cultureRegionalMatch(const std::string& ck3culture, + const std::string& eu4religion, + int eu4Province, + const std::string& eu4ownerTag) + { + if (eu4Overrides.contains(ck3culture)) + return ck3culture; + + for (const auto& cultureMappingRule: cultureMapRules) + { + const auto& possibleMatch = cultureMappingRule.cultureRegionalMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); + if (possibleMatch) + return *possibleMatch; + } + return std::nullopt; + } + + public std::optional cultureNonRegionalNonReligiousMatch(const std::string& ck3culture, + const std::string& eu4religion, + int eu4Province, + const std::string& eu4ownerTag) + { + if (eu4Overrides.contains(ck3culture)) + return ck3culture; + + for (const auto& cultureMappingRule: cultureMapRules) + { + const auto& possibleMatch = cultureMappingRule.cultureNonRegionalNonReligiousMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); + if (possibleMatch) + return *possibleMatch; + } + return std::nullopt; + } + + public std::optional getTechGroup(const std::string& incEU4Culture) + { + auto checkCulture = incEU4Culture; + if (eu4Overrides.contains(incEU4Culture)) + { + // if this is dynamic (not eu4ready) then see if we can grab a nonregional nonreligious mapping and ping the results of that. + for (const auto& culture: cultures) + { + // Log(LogLevel::Debug) << "> vs: " << culture->getName() << " | " << culture->isDynamic() << " | " << culture->getNameList().empty(); + + if (culture->getName() == incEU4Culture && culture->isDynamic() && !culture->getNameLists().empty()) + { + const auto& origCulture = *culture->getNameLists().begin(); + const auto& match = cultureNonRegionalNonReligiousMatch(origCulture, "", 0, ""); + if (match) + checkCulture = *match; + } + } + } + + for (const auto& mapping: cultureMapRules) + if (mapping.getTechGroup(checkCulture)) + return mapping.getTechGroup(checkCulture); + return std::nullopt; + } + public std::optional getGFX(const std::string& incEU4Culture) + { + auto checkCulture = incEU4Culture; + if (eu4Overrides.contains(incEU4Culture)) + { + // if this is dynamic (not eu4ready) then see if we can grab a nonregional nonreligious mapping and ping the results of that. + for (const auto& culture: cultures) + { + if (culture->getName() == incEU4Culture && culture->isDynamic() && !culture->getNameLists().empty()) + { + const auto& origCulture = *culture->getNameLists().begin(); + const auto& match = cultureNonRegionalNonReligiousMatch(origCulture, "", 0, ""); + if (match) + checkCulture = *match; + } + } + } + + for (const auto& mapping: cultureMapRules) + if (mapping.getGFX(checkCulture)) + return mapping.getGFX(checkCulture); + return std::nullopt; + } + + public const auto& getTargetCultures() const { return targetCultures; } + public const auto& getSourceCultures() const { return sourceCultures; } + public const auto& getCK3Cultures() const { return cultures; } + + private void registerKeys() + { + registerKeyword("link", [this](std::istream& theStream) { + const CultureMappingRule rule(theStream); + cultureMapRules.push_back(rule); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + private void buildCultureCaches() + { + for (const auto& mappingRule: cultureMapRules) + { + targetCultures.insert(mappingRule.getEU4Culture()); + for (const auto& culture: mappingRule.getCK3Cultures()) + sourceCultures.insert(culture); + } + } + + + private std::vector cultureMapRules; + + private std::set targetCultures; + private std::set sourceCultures; + private std::set> cultures; + + private std::set eu4Overrides; // cultures from ck3 we don't map but return as is - either eu4 ready cultures or dynamic ones. +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.h b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.h deleted file mode 100644 index b5afc726..00000000 --- a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMapper.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CULTURE_MAPPER_H -#define CULTURE_MAPPER_H - -#include "../RegionMapper/RegionMapper.h" -#include "CultureMappingRule.h" -#include "Parser.h" -#include -#include - -namespace CK3 -{ -class Culture; -} - -namespace mappers -{ -class CultureMapper: commonItems::parser -{ - public: - CultureMapper() = default; - explicit CultureMapper(std::istream& theStream); - void loadCulturesFromDisk(); - - void loadRegionMapper(const std::shared_ptr& theRegionMapper); - void storeCultures(const std::set>& incCultures); - - [[nodiscard]] std::optional cultureMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const; - - [[nodiscard]] std::optional cultureRegionalMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const; - - [[nodiscard]] std::optional cultureNonRegionalNonReligiousMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const; - - [[nodiscard]] std::optional getTechGroup(const std::string& incEU4Culture) const; - [[nodiscard]] std::optional getGFX(const std::string& incEU4Culture) const; - - [[nodiscard]] const auto& getTargetCultures() const { return targetCultures; } - [[nodiscard]] const auto& getSourceCultures() const { return sourceCultures; } - [[nodiscard]] const auto& getCK3Cultures() const { return cultures; } - - private: - void registerKeys(); - void buildCultureCaches(); - - std::vector cultureMapRules; - - std::set targetCultures; - std::set sourceCultures; - std::set> cultures; - - std::set eu4Overrides; // cultures from ck3 we don't map but return as is - either eu4 ready cultures or dynamic ones. -}; -} // namespace mappers - -#endif // CULTURE_MAPPER_H \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cpp b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cpp deleted file mode 100644 index dc3af87f..00000000 --- a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "CultureMappingRule.h" -#include "../RegionMapper/RegionMapper.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" - -mappers::CultureMappingRule::CultureMappingRule(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void mappers::CultureMappingRule::registerKeys() -{ - registerKeyword("eu4", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString eu4Str(theStream); - destinationCulture = eu4Str.getString(); - }); - registerKeyword("region", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString regionStr(theStream); - regions.insert(regionStr.getString()); - }); - registerKeyword("religion", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString religionStr(theStream); - religions.insert(religionStr.getString()); - }); - registerKeyword("owner", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString ownerStr(theStream); - owners.insert(ownerStr.getString()); - }); - registerKeyword("tech", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString techStr(theStream); - techGroup = techStr.getString(); - }); - registerKeyword("gfx", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString gfxStr(theStream); - gfx = gfxStr.getString(); - }); - registerKeyword("province", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString provinceStr(theStream); - try - { - provinces.insert(stoi(provinceStr.getString())); - } - catch (std::exception&) - { - Log(LogLevel::Warning) << "Invalid province ID in culture mapper: " << provinceStr.getString(); - } - }); - registerKeyword("ck3", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString ck3Str(theStream); - cultures.insert(ck3Str.getString()); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} - - -std::optional mappers::CultureMappingRule::cultureMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const -{ - // We need at least a viable EU4culture. - if (ck3culture.empty()) - return std::nullopt; - - if (!cultures.contains(ck3culture)) - return std::nullopt; - - if (!owners.empty()) - if (eu4ownerTag.empty() || !owners.contains(eu4ownerTag)) - return std::nullopt; - - if (!religions.empty()) - if (eu4religion.empty() || !religions.contains(eu4religion)) - return std::nullopt; - - // This is a straight province check, not regions. - if (!provinces.empty() && regions.empty()) - if (!eu4Province || !provinces.contains(eu4Province)) - return std::nullopt; - - // Asking for a regions check without an incoming province is pointless. - if (!regions.empty() && !eu4Province) - return std::nullopt; - - // This is a regions check, that checks if a provided province is within that region. - if (eu4Province && !regions.empty()) - { - if (!regionMapper) - throw std::runtime_error("Culture Mapper: Region Mapper is unloaded!"); - auto regionMatch = false; - for (const auto& region: regions) - { - if (!regionMapper->regionNameIsValid(region)) - { - Log(LogLevel::Warning) << "Checking for culture " << ck3culture << " inside invalid region: " << region << "! Fix the mapping rules!"; - // We could say this was a match, and thus pretend this region entry doesn't exist, but it's better - // for the converter to explode across the logs with invalid names. So, continue. - continue; - } - if (regionMapper->provinceIsInRegion(eu4Province, region)) - regionMatch = true; - } - // This is an override if we have a province outside the regions specified. - if (!provinces.empty() && provinces.count(eu4Province)) - regionMatch = true; - if (!regionMatch) - return std::nullopt; - } - return destinationCulture; -} - -std::optional mappers::CultureMappingRule::cultureRegionalMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const -{ - // This is a regional match. We need a mapping within the given region, so if the - // mapping rule has no regional qualifiers it needs to fail. - if (regions.empty()) - return std::nullopt; - - // Otherwise, as usual. - return cultureMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); -} - -std::optional mappers::CultureMappingRule::cultureNonRegionalNonReligiousMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const -{ - // This is a non regional non religious match. We need a mapping without any region/religion, so if the - // mapping rule has any regional/religious qualifiers it needs to fail. - if (!regions.empty()) - return std::nullopt; - if (!religions.empty()) - return std::nullopt; - - // Otherwise, as usual. - return cultureMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); -} - -std::optional mappers::CultureMappingRule::getTechGroup(const std::string& incEU4Culture) const -{ - if (incEU4Culture == destinationCulture && !techGroup.empty()) - return techGroup; - return std::nullopt; -} - -std::optional mappers::CultureMappingRule::getGFX(const std::string& incEU4Culture) const -{ - if (incEU4Culture == destinationCulture && !gfx.empty()) - return gfx; - return std::nullopt; -} diff --git a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cs b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cs new file mode 100644 index 00000000..c26bca0a --- /dev/null +++ b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.cs @@ -0,0 +1,177 @@ +namespace CK3ToEU4.Mappers.CultureMapper; + +class CultureMappingRule +{ + public CultureMappingRule() = default; + public CultureMappingRule(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + + public std::optional cultureMatch(const std::string& ck3culture, + const std::string& eu4religion, + int eu4Province, + const std::string& eu4ownerTag) + { + // We need at least a viable EU4culture. + if (ck3culture.empty()) + return std::nullopt; + + if (!cultures.contains(ck3culture)) + return std::nullopt; + + if (!owners.empty()) + if (eu4ownerTag.empty() || !owners.contains(eu4ownerTag)) + return std::nullopt; + + if (!religions.empty()) + if (eu4religion.empty() || !religions.contains(eu4religion)) + return std::nullopt; + + // This is a straight province check, not regions. + if (!provinces.empty() && regions.empty()) + if (!eu4Province || !provinces.contains(eu4Province)) + return std::nullopt; + + // Asking for a regions check without an incoming province is pointless. + if (!regions.empty() && !eu4Province) + return std::nullopt; + + // This is a regions check, that checks if a provided province is within that region. + if (eu4Province && !regions.empty()) + { + if (!regionMapper) + throw std::runtime_error("Culture Mapper: Region Mapper is unloaded!"); + auto regionMatch = false; + for (const auto& region: regions) + { + if (!regionMapper->regionNameIsValid(region)) + { + Log(LogLevel::Warning) << "Checking for culture " << ck3culture << " inside invalid region: " << region << "! Fix the mapping rules!"; + // We could say this was a match, and thus pretend this region entry doesn't exist, but it's better + // for the converter to explode across the logs with invalid names. So, continue. + continue; + } + if (regionMapper->provinceIsInRegion(eu4Province, region)) + regionMatch = true; + } + // This is an override if we have a province outside the regions specified. + if (!provinces.empty() && provinces.count(eu4Province)) + regionMatch = true; + if (!regionMatch) + return std::nullopt; + } + return destinationCulture; + } + + public std::optional cultureRegionalMatch(const std::string& ck3culture, + const std::string& eu4religion, + int eu4Province, + const std::string& eu4ownerTag) + { + // This is a regional match. We need a mapping within the given region, so if the + // mapping rule has no regional qualifiers it needs to fail. + if (regions.empty()) + return std::nullopt; + + // Otherwise, as usual. + return cultureMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); + } + + public std::optional cultureNonRegionalNonReligiousMatch(const std::string& ck3culture, + const std::string& eu4religion, + int eu4Province, + const std::string& eu4ownerTag) + { + // This is a non regional non religious match. We need a mapping without any region/religion, so if the + // mapping rule has any regional/religious qualifiers it needs to fail. + if (!regions.empty()) + return std::nullopt; + if (!religions.empty()) + return std::nullopt; + + // Otherwise, as usual. + return cultureMatch(ck3culture, eu4religion, eu4Province, eu4ownerTag); + } + + public std::optional getTechGroup(const std::string& incEU4Culture) + { + if (incEU4Culture == destinationCulture && !techGroup.empty()) + return techGroup; + return std::nullopt; + } + public std::optional getGFX(const std::string& incEU4Culture) + { + if (incEU4Culture == destinationCulture && !gfx.empty()) + return gfx; + return std::nullopt; + } + + public void insertRegionMapper(const std::shared_ptr& theRegionMapper) { regionMapper = theRegionMapper; } + + public const auto& getEU4Culture() const { return destinationCulture; } // for testing + public const auto& getCK3Cultures() const { return cultures; } // for testing + public const auto& getReligions() const { return religions; } // for testing + public const auto& getRegions() const { return regions; } // for testing + public const auto& getOwners() const { return owners; } // for testing + public const auto& getProvinces() const { return provinces; } // for testing + public const auto& getTechGroupField() const { return techGroup; } // for testing + public const auto& getGFXField() const { return gfx; } // for testing + + private void registerKeys() + { + registerKeyword("eu4", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString eu4Str(theStream); + destinationCulture = eu4Str.getString(); + }); + registerKeyword("region", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString regionStr(theStream); + regions.insert(regionStr.getString()); + }); + registerKeyword("religion", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString religionStr(theStream); + religions.insert(religionStr.getString()); + }); + registerKeyword("owner", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString ownerStr(theStream); + owners.insert(ownerStr.getString()); + }); + registerKeyword("tech", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString techStr(theStream); + techGroup = techStr.getString(); + }); + registerKeyword("gfx", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString gfxStr(theStream); + gfx = gfxStr.getString(); + }); + registerKeyword("province", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString provinceStr(theStream); + try + { + provinces.insert(stoi(provinceStr.getString())); + } + catch (std::exception&) + { + Log(LogLevel::Warning) << "Invalid province ID in culture mapper: " << provinceStr.getString(); + } + }); + registerKeyword("ck3", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString ck3Str(theStream); + cultures.insert(ck3Str.getString()); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + private std::string destinationCulture; + private std::string techGroup; + private std::string gfx; + private std::set cultures; + private std::set religions; + private std::set regions; + private std::set owners; + private std::set provinces; + + private std::shared_ptr regionMapper; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.h b/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.h deleted file mode 100644 index ec5d00cc..00000000 --- a/CK3ToEU4/Source/Mappers/CultureMapper/CultureMappingRule.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef CULTURE_MAPPING_RULE_H -#define CULTURE_MAPPING_RULE_H - -#include "Parser.h" -#include - -namespace mappers -{ -class RegionMapper; -class CultureMappingRule: commonItems::parser -{ - public: - CultureMappingRule() = default; - explicit CultureMappingRule(std::istream& theStream); - - [[nodiscard]] std::optional cultureMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const; - - [[nodiscard]] std::optional cultureRegionalMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const; - - [[nodiscard]] std::optional cultureNonRegionalNonReligiousMatch(const std::string& ck3culture, - const std::string& eu4religion, - int eu4Province, - const std::string& eu4ownerTag) const; - - [[nodiscard]] std::optional getTechGroup(const std::string& incEU4Culture) const; - [[nodiscard]] std::optional getGFX(const std::string& incEU4Culture) const; - - void insertRegionMapper(const std::shared_ptr& theRegionMapper) { regionMapper = theRegionMapper; } - - [[nodiscard]] const auto& getEU4Culture() const { return destinationCulture; } // for testing - [[nodiscard]] const auto& getCK3Cultures() const { return cultures; } // for testing - [[nodiscard]] const auto& getReligions() const { return religions; } // for testing - [[nodiscard]] const auto& getRegions() const { return regions; } // for testing - [[nodiscard]] const auto& getOwners() const { return owners; } // for testing - [[nodiscard]] const auto& getProvinces() const { return provinces; } // for testing - [[nodiscard]] const auto& getTechGroupField() const { return techGroup; } // for testing - [[nodiscard]] const auto& getGFXField() const { return gfx; } // for testing - - private: - void registerKeys(); - - std::string destinationCulture; - std::string techGroup; - std::string gfx; - std::set cultures; - std::set religions; - std::set regions; - std::set owners; - std::set provinces; - - std::shared_ptr regionMapper; -}; -} // namespace mappers - -#endif // CULTURE_MAPPING_RULE_H diff --git a/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.cpp b/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.cpp deleted file mode 100644 index 11c0521d..00000000 --- a/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "IAmHreMapper.h" -#include "CommonRegexes.h" -#include "ParserHelpers.h" - -mappers::IAmHreMapper::IAmHreMapper() -{ - registerKeys(); - parseFile("configurables/i_am_hre.txt"); - clearRegisteredKeywords(); -} - -mappers::IAmHreMapper::IAmHreMapper(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void mappers::IAmHreMapper::registerKeys() -{ - registerKeyword("hre_mechanics", [this](const std::string& unused, std::istream& theStream) { - const commonItems::singleString hreStr(theStream); - hre = hreStr.getString(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.h b/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.h index 2ef82af2..6a52771e 100644 --- a/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.h +++ b/CK3ToEU4/Source/Mappers/IAmHreMapper/IAmHreMapper.h @@ -1,23 +1,34 @@ -#ifndef I_AM_HRE_MAPPER -#define I_AM_HRE_MAPPER - -#include "Parser.h" namespace mappers { class IAmHreMapper: commonItems::parser { public: - IAmHreMapper(); - explicit IAmHreMapper(std::istream& theStream); + IAmHreMapper() + { + registerKeys(); + parseFile("configurables/i_am_hre.txt"); + clearRegisteredKeywords(); + } + explicit IAmHreMapper(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } [[nodiscard]] const auto& getHRE() const { return hre; } private: - void registerKeys(); + void registerKeys() + { + registerKeyword("hre_mechanics", [this](const std::string& unused, std::istream& theStream) { + const commonItems::singleString hreStr(theStream); + hre = hreStr.getString(); + }); + registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } std::string hre; }; -} // namespace mappers - -#endif // I_AM_HRE_MAPPER \ No newline at end of file +} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cpp b/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cpp deleted file mode 100644 index 3903dc93..00000000 --- a/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cpp +++ /dev/null @@ -1,324 +0,0 @@ -#include "LocalizationMapper.h" -#include "../../Configuration/Configuration.h" -#include "Log.h" -#include "OSCompatibilityLayer.h" -#include -#include - -void mappers::LocalizationMapper::scrapeLocalizations(const Configuration& theConfiguration, const Mods& mods) -{ - scrapeLanguage("english", theConfiguration.getCK3Path() + "localization"); - scrapeLanguage("french", theConfiguration.getCK3Path() + "localization"); - scrapeLanguage("german", theConfiguration.getCK3Path() + "localization"); - scrapeLanguage("korean", theConfiguration.getCK3Path() + "/localization"); - scrapeLanguage("russian", theConfiguration.getCK3Path() + "/localization"); - scrapeLanguage("simp_chinese", theConfiguration.getCK3Path() + "/localization"); - scrapeLanguage("spanish", theConfiguration.getCK3Path() + "localization"); - - for (const auto& mod: mods) - { - if (commonItems::DoesFolderExist(mod.path + "localization")) - { - Log(LogLevel::Info) << "\t>> Found some words in: [" << mod.name + "]"; - scrapeLanguage("english", mod.path + "/localization"); - scrapeLanguage("french", mod.path + "/localization"); - scrapeLanguage("german", mod.path + "/localization"); - scrapeLanguage("korean", mod.path + "/localization"); - scrapeLanguage("russian", mod.path + "/localization"); - scrapeLanguage("simp_chinese", mod.path + "/localization"); - scrapeLanguage("spanish", mod.path + "/localization"); - scrapeLanguage("english", mod.path + "/localization/replace"); - scrapeLanguage("french", mod.path + "/localization/replace"); - scrapeLanguage("german", mod.path + "/localization/replace"); - scrapeLanguage("korean", mod.path + "/localization/replace"); - scrapeLanguage("russian", mod.path + "/localization/replace"); - scrapeLanguage("simp_chinese", mod.path + "/localization/replace"); - scrapeLanguage("spanish", mod.path + "/localization/replace"); - } - } - - Log(LogLevel::Info) << ">> " << localizations.size() << " words read."; -} - -void mappers::LocalizationMapper::scrapeLanguage(const std::string& language, const std::string& path) -{ - if (!commonItems::DoesFolderExist(path + "/" + language)) - return; - const auto fileNames = commonItems::GetAllFilesInFolderRecursive(path + "/" + language); - for (const auto& file: fileNames) - { - std::ifstream fileStream(path + "/" + language + "/" + file); - if (fileStream.is_open()) - scrapeStream(fileStream, language); - fileStream.close(); - } -} - -void mappers::LocalizationMapper::unravelNestedLocs(LocBlock& block) const -{ - // Support Korean/Chinese/Russian? - for (const auto& lang: std::vector{"english", "french", "spanish", "german"}) - { - const auto& loc = selectLanguage(lang, block); - if (loc.find('$') != std::string::npos) // TODO: handle escaped \$ - { - const auto& keyStr = getLeadStr(loc, 2, "$"); // Chop off tail after nested key - const auto& nestedKey = getTailStr(keyStr, 1, "$"); // Chop off head before nested key - if (const auto& newblock = getLocBlockForKey(nestedKey); newblock) - { - const auto& fstr = getLeadStr(loc, 1, "$"); - const auto& bstr = getTailStr(loc, 2, "$"); - assignSelectLanguage(fstr + selectLanguage(lang, newblock.value()) + bstr, lang, block); - } - else - { - Log(LogLevel::Warning) << "Could not find locblock for nested loc: " + nestedKey; - return; - } - unravelNestedLocs(block); - } - } - return; -} - -void mappers::LocalizationMapper::removeEmphasis(LocBlock& block) const -{ - for (const auto& lang: std::vector{"english", "french", "spanish", "german"}) - { - const auto& loc = selectLanguage(lang, block); - assignSelectLanguage(cleanLocMarkups(loc), lang, block); - } -} - -const std::string mappers::LocalizationMapper::selectLanguage(const std::string& language, const LocBlock& block) const -{ - if (language == "english") - return block.english; - else if (language == "french") - return block.french; - else if (language == "spanish") - return block.spanish; - else if (language == "german") - return block.german; - else if (language == "korean") - return block.korean; - else if (language == "russian") - return block.russian; - else if (language == "simp_chinese") - return block.simp_chinese; - else - return block.english; -} - -void mappers::LocalizationMapper::assignSelectLanguage(const std::string& str, const std::string& language, LocBlock& block) const -{ - if (language == "english") - block.english = commonItems::remQuotes(str); - else if (language == "french") - block.french = commonItems::remQuotes(str); - else if (language == "spanish") - block.spanish = commonItems::remQuotes(str); - else if (language == "german") - block.german = commonItems::remQuotes(str); - else if (language == "korean") - block.korean = commonItems::remQuotes(str); - else if (language == "russian") - block.russian = commonItems::remQuotes(str); - else if (language == "simp_chinese") - block.simp_chinese = commonItems::remQuotes(str); - else - throw std::invalid_argument(language + " is not currently supported or has a typo."); - return; -} - -void mappers::LocalizationMapper::scrapeStream(std::istream& theStream, const std::string& language) -{ - std::string line; - std::getline(theStream, line); // Dropping first line and BOM with it. - - while (!theStream.eof()) - { - std::getline(theStream, line); - const auto [key, value] = determineKeyLocalizationPair(line); - if (!key.empty() && !value.empty()) - { - if (localizations.contains(key)) - { - if (language == "english") - localizations[key].english = value; - if (language == "french") - localizations[key].french = value; - if (language == "german") - localizations[key].german = value; - if (language == "korean") - localizations[key].korean = value; - if (language == "russian") - localizations[key].russian = value; - if (language == "simp_chinese") - localizations[key].simp_chinese = value; - if (language == "spanish") - localizations[key].spanish = value; - } - else - { - LocBlock newBlock; - if (language == "english") - newBlock.english = value; - if (language == "french") - newBlock.french = value; - if (language == "german") - newBlock.german = value; - if (language == "korean") - newBlock.korean = value; - if (language == "russian") - newBlock.russian = value; - if (language == "simp_chinese") - newBlock.simp_chinese = value; - if (language == "spanish") - newBlock.spanish = value; - localizations.insert(std::pair(key, newBlock)); - } - } - } -} - -std::pair mappers::LocalizationMapper::determineKeyLocalizationPair(const std::string& text) -{ - std::pair blankReturn; - - if (text.size() > 2 && (text[0] == '#' || text[1] == '#')) - return blankReturn; - - const auto keyBeginPos = text.find_first_not_of(' '); - if (keyBeginPos == std::string::npos) - return blankReturn; - - const auto keyEndPos = text.find_first_of(':', keyBeginPos + 1); - const auto quotePos = text.find_first_of('"', keyEndPos); - if (quotePos == std::string::npos) - return blankReturn; - - const auto localizationBeginPos = quotePos + 1; - const auto localizationEndPos = text.find_last_of('"', text.size()); - return std::make_pair(text.substr(keyBeginPos, keyEndPos - keyBeginPos), text.substr(localizationBeginPos, localizationEndPos - localizationBeginPos)); -} - -std::optional mappers::LocalizationMapper::getLocBlockForKey(const std::string& key) const -{ - if (key.empty()) - return std::nullopt; - const auto& keyItr = localizations.find(key); - if (keyItr == localizations.end()) - return std::nullopt; - - if (!keyItr->second.english.empty() && (keyItr->second.spanish.empty() || keyItr->second.german.empty() || keyItr->second.french.empty() || - keyItr->second.korean.empty() || keyItr->second.russian.empty() || keyItr->second.simp_chinese.empty())) - { - auto newBlock = keyItr->second; - if (newBlock.spanish.empty()) - newBlock.spanish = newBlock.english; - if (newBlock.german.empty()) - newBlock.german = newBlock.english; - if (newBlock.french.empty()) - newBlock.french = newBlock.english; - if (newBlock.korean.empty()) - newBlock.korean = newBlock.english; - if (newBlock.russian.empty()) - newBlock.russian = newBlock.english; - if (newBlock.simp_chinese.empty()) - newBlock.simp_chinese = newBlock.english; - return newBlock; - } - - // either all is well, or we're missing english. Can't do anything about the latter. Since English is absolute base, we bail if it's missing. - // (Quite a few locs have only russian entries and no other languages.) - if (keyItr->second.english.empty()) - return std::nullopt; - - return keyItr->second; -} - -std::optional mappers::LocalizationMapper::reverseLookupCultureName(const std::string& localization) const -{ - // This looks for specifically *_name keys cultures use. - - for (const auto& [locName, locBlock]: localizations) - { - if (locBlock.english == localization || locBlock.french == localization || locBlock.german == localization || locBlock.korean == localization || - locBlock.russian == localization || locBlock.simp_chinese == localization || locBlock.spanish == localization) - if (locName.find("_name") != std::string::npos) - return locName; - } - return std::nullopt; -} - -std::string mappers::getLeadStr(const std::string& str, const int occurrence, const std::string& match) -{ - if (const auto& i = str.find(match); i != std::string::npos) - if (occurrence == 1) - return str.substr(0, i); - else - return str.substr(0, i) + match + getLeadStr(str.substr(i + match.length()), occurrence - 1, match); - else - return str; -} -std::string mappers::getTailStr(const std::string& str, const int occurrence, const std::string& match) -{ - if (const auto& i = str.find(match); i != std::string::npos) - if (occurrence == 1) - { - auto tail = str.substr(i + match.length()); - if (tail.starts_with("!")) - tail = tail.substr(1, tail.length()); - return tail; - } - else - return getTailStr(str.substr(i + match.length()), occurrence - 1, match); - else - return str; -} -std::string mappers::cleanLocMarkups(const std::string& loc) -{ - if (loc.find('#') == std::string::npos) - return loc; - - // Locmarks come in two styles: #SOMETHING with a whitespace behind it, and a #! witho no whitespace trailing it. - // We iterate over the entire string and just rip these out. - - auto workingLoc = loc; - auto pos = workingLoc.find('#'); - - while (pos != std::string::npos) - { - // find first # - const auto& head = getLeadStr(workingLoc, 1, "#"); - - // find how long it is. - if (pos <= workingLoc.size() - 2 && workingLoc.at(pos + 1) == '!') - { - // Delete #! - workingLoc = head + workingLoc.substr(pos + 2, workingLoc.size()); - } - else if (pos <= workingLoc.size() - 2 && workingLoc.at(pos + 1) == ' ') - { - // Delete freeform # - workingLoc = head + workingLoc.substr(pos + 1, workingLoc.size()); - } - else if (pos == workingLoc.size() - 1) - { - // Delete # at endline - workingLoc = head; - } - else - { - // find the whitespace ending the mark. - auto endpos = workingLoc.find(' ', pos + 1); - if (endpos == std::string::npos) - return loc; // bail - workingLoc = head + workingLoc.substr(endpos + 1, workingLoc.size()); - } - pos = workingLoc.find('#'); - } - - return workingLoc; -} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cs b/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cs new file mode 100644 index 00000000..98d3c59b --- /dev/null +++ b/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.cs @@ -0,0 +1,349 @@ +#ifndef LOCALIZATION_MAPPER +#define LOCALIZATION_MAPPER +#include "ModLoader/ModLoader.h" +#include +#include +#include + + + +namespace mappers +{ + +struct LocBlock +{ + std::string english; + std::string french; + std::string german; + std::string korean; + std::string russian; + std::string simp_chinese; + std::string spanish; +} ; + +// Returns substring of str before nth occurrence of match string. +std::string getLeadStr(const std::string& str, const int occurrence = 1, const std::string& match = "_") +{ + if (const auto& i = str.find(match); i != std::string::npos) + if (occurrence == 1) + return str.substr(0, i); + else + return str.substr(0, i) + match + getLeadStr(str.substr(i + match.length()), occurrence - 1, match); + else + return str; +} +// Returns substring of string after nth occurrence of match string. +std::string getTailStr(const std::string& str, const int occurrence = 1, const std::string& match = "_") +{ + if (const auto& i = str.find(match); i != std::string::npos) + if (occurrence == 1) + { + auto tail = str.substr(i + match.length()); + if (tail.starts_with("!")) + tail = tail.substr(1, tail.length()); + return tail; + } + else + return getTailStr(str.substr(i + match.length()), occurrence - 1, match); + else + return str; +} +// Returns loc without pesky CK3 #EMP STRING# +std::string cleanLocMarkups(const std::string& loc) +{ + if (loc.find('#') == std::string::npos) + return loc; + + // Locmarks come in two styles: #SOMETHING with a whitespace behind it, and a #! witho no whitespace trailing it. + // We iterate over the entire string and just rip these out. + + auto workingLoc = loc; + auto pos = workingLoc.find('#'); + + while (pos != std::string::npos) + { + // find first # + const auto& head = getLeadStr(workingLoc, 1, "#"); + + // find how long it is. + if (pos <= workingLoc.size() - 2 && workingLoc.at(pos + 1) == '!') + { + // Delete #! + workingLoc = head + workingLoc.substr(pos + 2, workingLoc.size()); + } + else if (pos <= workingLoc.size() - 2 && workingLoc.at(pos + 1) == ' ') + { + // Delete freeform # + workingLoc = head + workingLoc.substr(pos + 1, workingLoc.size()); + } + else if (pos == workingLoc.size() - 1) + { + // Delete # at endline + workingLoc = head; + } + else + { + // find the whitespace ending the mark. + auto endpos = workingLoc.find(' ', pos + 1); + if (endpos == std::string::npos) + return loc; // bail + workingLoc = head + workingLoc.substr(endpos + 1, workingLoc.size()); + } + pos = workingLoc.find('#'); + } + + return workingLoc; +} + +class LocalizationMapper +{ + public: + LocalizationMapper() = default; + void scrapeLocalizations(const Configuration& theConfiguration, const Mods& mods) + + { + scrapeLanguage("english", theConfiguration.getCK3Path() + "localization"); + scrapeLanguage("french", theConfiguration.getCK3Path() + "localization"); + scrapeLanguage("german", theConfiguration.getCK3Path() + "localization"); + scrapeLanguage("korean", theConfiguration.getCK3Path() + "/localization"); + scrapeLanguage("russian", theConfiguration.getCK3Path() + "/localization"); + scrapeLanguage("simp_chinese", theConfiguration.getCK3Path() + "/localization"); + scrapeLanguage("spanish", theConfiguration.getCK3Path() + "localization"); + + for (const auto& mod: mods) + { + if (commonItems::DoesFolderExist(mod.path + "localization")) + { + Log(LogLevel::Info) << "\t>> Found some words in: [" << mod.name + "]"; + scrapeLanguage("english", mod.path + "/localization"); + scrapeLanguage("french", mod.path + "/localization"); + scrapeLanguage("german", mod.path + "/localization"); + scrapeLanguage("korean", mod.path + "/localization"); + scrapeLanguage("russian", mod.path + "/localization"); + scrapeLanguage("simp_chinese", mod.path + "/localization"); + scrapeLanguage("spanish", mod.path + "/localization"); + scrapeLanguage("english", mod.path + "/localization/replace"); + scrapeLanguage("french", mod.path + "/localization/replace"); + scrapeLanguage("german", mod.path + "/localization/replace"); + scrapeLanguage("korean", mod.path + "/localization/replace"); + scrapeLanguage("russian", mod.path + "/localization/replace"); + scrapeLanguage("simp_chinese", mod.path + "/localization/replace"); + scrapeLanguage("spanish", mod.path + "/localization/replace"); + } + } + + Log(LogLevel::Info) << ">> " << localizations.size() << " words read."; + } + void scrapeStream(std::istream& theStream, const std::string& language) + + { + std::string line; + std::getline(theStream, line); // Dropping first line and BOM with it. + + while (!theStream.eof()) + { + std::getline(theStream, line); + const auto [key, value] = determineKeyLocalizationPair(line); + if (!key.empty() && !value.empty()) + { + if (localizations.contains(key)) + { + if (language == "english") + localizations[key].english = value; + if (language == "french") + localizations[key].french = value; + if (language == "german") + localizations[key].german = value; + if (language == "korean") + localizations[key].korean = value; + if (language == "russian") + localizations[key].russian = value; + if (language == "simp_chinese") + localizations[key].simp_chinese = value; + if (language == "spanish") + localizations[key].spanish = value; + } + else + { + LocBlock newBlock; + if (language == "english") + newBlock.english = value; + if (language == "french") + newBlock.french = value; + if (language == "german") + newBlock.german = value; + if (language == "korean") + newBlock.korean = value; + if (language == "russian") + newBlock.russian = value; + if (language == "simp_chinese") + newBlock.simp_chinese = value; + if (language == "spanish") + newBlock.spanish = value; + localizations.insert(std::pair(key, newBlock)); + } + } + } + } + void unravelNestedLocs(LocBlock& block) + + { + // Support Korean/Chinese/Russian? + for (const auto& lang: std::vector{"english", "french", "spanish", "german"}) + { + const auto& loc = selectLanguage(lang, block); + if (loc.find('$') != std::string::npos) // TODO: handle escaped \$ + { + const auto& keyStr = getLeadStr(loc, 2, "$"); // Chop off tail after nested key + const auto& nestedKey = getTailStr(keyStr, 1, "$"); // Chop off head before nested key + if (const auto& newblock = getLocBlockForKey(nestedKey); newblock) + { + const auto& fstr = getLeadStr(loc, 1, "$"); + const auto& bstr = getTailStr(loc, 2, "$"); + assignSelectLanguage(fstr + selectLanguage(lang, newblock.value()) + bstr, lang, block); + } + else + { + Log(LogLevel::Warning) << "Could not find locblock for nested loc: " + nestedKey; + return; + } + unravelNestedLocs(block); + } + } + return; + } + void removeEmphasis(LocBlock& block) + { + for (const auto& lang: std::vector{"english", "french", "spanish", "german"}) + { + const auto& loc = selectLanguage(lang, block); + assignSelectLanguage(cleanLocMarkups(loc), lang, block); + } + } + + [[nodiscard]] std::optional getLocBlockForKey(const std::string& key) + { + if (key.empty()) + return std::nullopt; + const auto& keyItr = localizations.find(key); + if (keyItr == localizations.end()) + return std::nullopt; + + if (!keyItr->second.english.empty() && (keyItr->second.spanish.empty() || keyItr->second.german.empty() || keyItr->second.french.empty() || + keyItr->second.korean.empty() || keyItr->second.russian.empty() || keyItr->second.simp_chinese.empty())) + { + auto newBlock = keyItr->second; + if (newBlock.spanish.empty()) + newBlock.spanish = newBlock.english; + if (newBlock.german.empty()) + newBlock.german = newBlock.english; + if (newBlock.french.empty()) + newBlock.french = newBlock.english; + if (newBlock.korean.empty()) + newBlock.korean = newBlock.english; + if (newBlock.russian.empty()) + newBlock.russian = newBlock.english; + if (newBlock.simp_chinese.empty()) + newBlock.simp_chinese = newBlock.english; + return newBlock; + } + + // either all is well, or we're missing english. Can't do anything about the latter. Since English is absolute base, we bail if it's missing. + // (Quite a few locs have only russian entries and no other languages.) + if (keyItr->second.english.empty()) + return std::nullopt; + + return keyItr->second; + } + [[nodiscard]] std::optional reverseLookupCultureName(const std::string& localization) + { + // This looks for specifically *_name keys cultures use. + + for (const auto& [locName, locBlock]: localizations) + { + if (locBlock.english == localization || locBlock.french == localization || locBlock.german == localization || locBlock.korean == localization || + locBlock.russian == localization || locBlock.simp_chinese == localization || locBlock.spanish == localization) + if (locName.find("_name") != std::string::npos) + return locName; + } + return std::nullopt; + } + + private: + void scrapeLanguage(const std::string& language, const std::string& path) + { + if (!commonItems::DoesFolderExist(path + "/" + language)) + return; + const auto fileNames = commonItems::GetAllFilesInFolderRecursive(path + "/" + language); + for (const auto& file: fileNames) + { + std::ifstream fileStream(path + "/" + language + "/" + file); + if (fileStream.is_open()) + scrapeStream(fileStream, language); + fileStream.close(); + } + } + const std::string selectLanguage(const std::string& language, const LocBlock& block) + { + if (language == "english") + return block.english; + else if (language == "french") + return block.french; + else if (language == "spanish") + return block.spanish; + else if (language == "german") + return block.german; + else if (language == "korean") + return block.korean; + else if (language == "russian") + return block.russian; + else if (language == "simp_chinese") + return block.simp_chinese; + else + return block.english; + } + void assignSelectLanguage(const std::string& str, const std::string& language, LocBlock& block) + { + if (language == "english") + block.english = commonItems::remQuotes(str); + else if (language == "french") + block.french = commonItems::remQuotes(str); + else if (language == "spanish") + block.spanish = commonItems::remQuotes(str); + else if (language == "german") + block.german = commonItems::remQuotes(str); + else if (language == "korean") + block.korean = commonItems::remQuotes(str); + else if (language == "russian") + block.russian = commonItems::remQuotes(str); + else if (language == "simp_chinese") + block.simp_chinese = commonItems::remQuotes(str); + else + throw std::invalid_argument(language + " is not currently supported or has a typo."); + return; + } + + private static std::pair determineKeyLocalizationPair(const std::string& text) + { + std::pair blankReturn; + + if (text.size() > 2 && (text[0] == '#' || text[1] == '#')) + return blankReturn; + + const auto keyBeginPos = text.find_first_not_of(' '); + if (keyBeginPos == std::string::npos) + return blankReturn; + + const auto keyEndPos = text.find_first_of(':', keyBeginPos + 1); + const auto quotePos = text.find_first_of('"', keyEndPos); + if (quotePos == std::string::npos) + return blankReturn; + + const auto localizationBeginPos = quotePos + 1; + const auto localizationEndPos = text.find_last_of('"', text.size()); + return std::make_pair(text.substr(keyBeginPos, keyEndPos - keyBeginPos), text.substr(localizationBeginPos, localizationEndPos - localizationBeginPos)); + } + + std::map localizations; +}; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.h b/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.h deleted file mode 100644 index bff29573..00000000 --- a/CK3ToEU4/Source/Mappers/LocalizationMapper/LocalizationMapper.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef LOCALIZATION_MAPPER -#define LOCALIZATION_MAPPER -#include "ModLoader/ModLoader.h" -#include -#include -#include - -class Configuration; -namespace mappers -{ -typedef struct -{ - std::string english; - std::string french; - std::string german; - std::string korean; - std::string russian; - std::string simp_chinese; - std::string spanish; -} LocBlock; - -// Returns substring of str before nth occurrence of match string. -std::string getLeadStr(const std::string& str, const int occurrence = 1, const std::string& match = "_"); -// Returns substring of string after nth occurrence of match string. -std::string getTailStr(const std::string& str, const int occurrence = 1, const std::string& match = "_"); -// Returns loc without pesky CK3 #EMP STRING# -std::string cleanLocMarkups(const std::string& loc); - -class LocalizationMapper -{ - public: - LocalizationMapper() = default; - void scrapeLocalizations(const Configuration& theConfiguration, const Mods& mods); - void scrapeStream(std::istream& theStream, const std::string& language); - void unravelNestedLocs(LocBlock& block) const; - void removeEmphasis(LocBlock& block) const; - - [[nodiscard]] std::optional getLocBlockForKey(const std::string& key) const; - [[nodiscard]] std::optional reverseLookupCultureName(const std::string& localization) const; - - private: - void scrapeLanguage(const std::string& language, const std::string& path); - const std::string selectLanguage(const std::string& language, const LocBlock& block) const; - void assignSelectLanguage(const std::string& str, const std::string& language, LocBlock& block) const; - - [[nodiscard]] static std::pair determineKeyLocalizationPair(const std::string& text); - - std::map localizations; -}; -} // namespace mappers - -#endif // LOCALIZATION_MAPPER \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cpp b/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cpp deleted file mode 100644 index bc88cecd..00000000 --- a/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "NamedColors.h" -#include "CommonRegexes.h" -#include "ParserHelpers.h" - -void mappers::NamedColors::loadColors(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void mappers::NamedColors::loadColors(const std::string& filepath) -{ - registerKeys(); - parseFile(filepath); - clearRegisteredKeywords(); -} - -void mappers::NamedColors::registerKeys() -{ - // If we get a color named "colors", we're f--d. - registerKeyword("colors", [](const std::string& unused, std::istream& theStream) { - auto loadedColors = NamedColors(); - loadedColors.loadColors(theStream); - }); - registerRegex(commonItems::catchallRegex, [](const std::string& colorName, std::istream& theStream) { - laFabricaDeColor.addNamedColor(colorName, theStream); - }); -} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cs b/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cs new file mode 100644 index 00000000..9850b4ce --- /dev/null +++ b/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.cs @@ -0,0 +1,33 @@ +using commonItems; +using commonItems.Colors; + +namespace CK3ToEU4.Mappers.NamedColors; + +class NamedColors +{ + public NamedColors() {} + public void loadColors(BufferedReader reader, ColorFactory colorFactory) + { + var parser = new Parser(); + RegisterKeys(parser, colorFactory); + parser.ParseStream(reader); + } + public void loadColors(string filepath, ColorFactory colorFactory) + { + var parser = new Parser(); + RegisterKeys(parser, colorFactory); + parser.ParseFile(filepath); + } + + private static void RegisterKeys(Parser parser, ColorFactory colorFactory) + { + // If we get a color named "colors", we're f--d. + parser.RegisterKeyword("colors", reader => { + var loadedColors = new NamedColors(); + loadedColors.loadColors(reader, colorFactory); + }); + parser.RegisterRegex(CommonRegexes.Catchall, (reader, colorName) => { + colorFactory.AddNamedColor(colorName, reader); + }); + } +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.h b/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.h deleted file mode 100644 index a23d8eb3..00000000 --- a/CK3ToEU4/Source/Mappers/NamedColors/NamedColors.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef NAMED_COLORS_H -#define NAMED_COLORS_H -#include "Color.h" -#include "Parser.h" -extern commonItems::Color::Factory laFabricaDeColor; - -namespace mappers -{ -class NamedColors: commonItems::parser -{ - public: - NamedColors() = default; - void loadColors(std::istream& theStream); - void loadColors(const std::string& filepath); - - private: - void registerKeys(); -}; -} // namespace mappers - -#endif // NAMED_COLORS_H \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/ReligionMapper/ReligionMapper.h b/CK3ToEU4/Source/Mappers/ReligionMapper/ReligionMapper.h index d643696b..f1599962 100644 --- a/CK3ToEU4/Source/Mappers/ReligionMapper/ReligionMapper.h +++ b/CK3ToEU4/Source/Mappers/ReligionMapper/ReligionMapper.h @@ -2,7 +2,7 @@ #define RELIGION_MAPPER_H #include "../../EU4World/Religion/GeneratedReligion.h" #include "../CK3ReligionScraper/CK3ReligionScraper.h" -#include "../LocalizationMapper/LocalizationMapper.h" +#include "../LocalizationMapper/LocalizationMapper.cs" #include "Parser.h" #include #include diff --git a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cpp b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cpp deleted file mode 100644 index 27601e0c..00000000 --- a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "TraitScraper.h" -#include "CommonRegexes.h" -#include "Log.h" -#include "ParserHelpers.h" -#include "TraitScraping.h" - -void mappers::TraitScraper::loadTraits(const std::string& fileName) -{ - registerKeys(); - parseFile(fileName); - clearRegisteredKeywords(); -} - -void mappers::TraitScraper::loadTraits(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void mappers::TraitScraper::registerKeys() -{ - registerRegex("@.*", commonItems::ignoreItem); - registerRegex(commonItems::catchallRegex, [this](const std::string& traitName, std::istream& theStream) { - const auto newScraping = TraitScraping(theStream); - if (newScraping.getIndex() > 0) // indexes start at 1! - { - if (traits.contains(newScraping.getIndex())) - { - traits.at(newScraping.getIndex()) = traitName; // override existing one - } - else - { - traits.emplace(newScraping.getIndex(), traitName); - } - } - else // otherwise index them ourselves. - { - if (!traits.contains(index)) - { - traits.emplace(index, traitName); - } - else - { - traits.at(index) = traitName; // override existing one - } - ++index; - } - }); -} - -std::optional mappers::TraitScraper::getTraitForID(int ID) const -{ - const auto& traitsItr = traits.find(ID); - if (traitsItr != traits.end()) - return traitsItr->second; - return std::nullopt; -} diff --git a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cs b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cs new file mode 100644 index 00000000..be56bc1d --- /dev/null +++ b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.cs @@ -0,0 +1,63 @@ +namespace CK3ToEU4.Mappers.TraitScraper; + +class TraitScraper +{ + public TraitScraper() {} + public void loadTraits(std::istream& theStream) + { + registerKeys(); + parseStream(theStream); + clearRegisteredKeywords(); + } + public void loadTraits(const std::string& fileName) + { + registerKeys(); + parseFile(fileName); + clearRegisteredKeywords(); + } + + public const auto& getTraits() const { return traits; } + + public std::optional getTraitForID(int ID) const + { + const auto& traitsItr = traits.find(ID); + if (traitsItr != traits.end()) + return traitsItr->second; + return std::nullopt; + } + + + private void registerKeys() + { + registerRegex("@.*", commonItems::ignoreItem); + registerRegex(commonItems::catchallRegex, [this](const std::string& traitName, std::istream& theStream) { + const auto newScraping = TraitScraping(theStream); + if (newScraping.getIndex() > 0) // indexes start at 1! + { + if (traits.contains(newScraping.getIndex())) + { + traits.at(newScraping.getIndex()) = traitName; // override existing one + } + else + { + traits.emplace(newScraping.getIndex(), traitName); + } + } + else // otherwise index them ourselves. + { + if (!traits.contains(index)) + { + traits.emplace(index, traitName); + } + else + { + traits.at(index) = traitName; // override existing one + } + ++index; + } + }); + } + + private int index = 1; + private std::map traits; +} \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.h b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.h deleted file mode 100644 index 0dbd1851..00000000 --- a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraper.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TRAIT_SCRAPER -#define TRAIT_SCRAPER -#include "Parser.h" - -namespace mappers -{ -class TraitScraper: commonItems::parser -{ - public: - TraitScraper() = default; - void loadTraits(std::istream& theStream); - void loadTraits(const std::string& fileName); - - [[nodiscard]] const auto& getTraits() const { return traits; } - - [[nodiscard]] std::optional getTraitForID(int ID) const; - - private: - void registerKeys(); - - int index = 1; - std::map traits; -}; -} // namespace mappers - -#endif // TRAIT_SCRAPER \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cpp b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cpp deleted file mode 100644 index f95cc536..00000000 --- a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "TraitScraping.h" -#include "CommonRegexes.h" -#include "ParserHelpers.h" - -mappers::TraitScraping::TraitScraping(std::istream& theStream) -{ - registerKeys(); - parseStream(theStream); - clearRegisteredKeywords(); -} - -void mappers::TraitScraping::registerKeys() -{ - registerKeyword("index", [this](const std::string& personalityName, std::istream& theStream) { - index = commonItems::singleInt(theStream).getInt(); - }); - registerRegex(commonItems::catchallRegex, commonItems::ignoreItem); -} diff --git a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cs b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cs new file mode 100644 index 00000000..af74456f --- /dev/null +++ b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.cs @@ -0,0 +1,26 @@ +using commonItems; + +namespace CK3ToEU4.Mappers.TraitScraper; + +class TraitScraping +{ + public TraitScraping() {} + public TraitScraping(std::istream& theStream) + { + var parser = new Parser(); + registerKeys(parser); + parser.ParseStream(reader); + } + + public int getIndex() { return index; } + + private void registerKeys(Parser parser) + { + parser.RegisterKeyword("index", [this](const std::string& personalityName, std::istream& theStream) { + index = commonItems::singleInt(theStream).getInt(); + }); + parser.RegisterRegex(commonItems::catchallRegex, commonItems::ignoreItem); + } + + private int index = 0; +}; \ No newline at end of file diff --git a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.h b/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.h deleted file mode 100644 index 17c7e59c..00000000 --- a/CK3ToEU4/Source/Mappers/TraitScraper/TraitScraping.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TRAIT_SCRAPING -#define TRAIT_SCRAPING -#include "Parser.h" - -namespace mappers -{ -class TraitScraping: commonItems::parser -{ - public: - TraitScraping() = default; - explicit TraitScraping(std::istream& theStream); - - [[nodiscard]] auto getIndex() const { return index; } - - private: - void registerKeys(); - - int index = 0; -}; -} // namespace mappers - -#endif // TRAIT_SCRAPING \ No newline at end of file