Refactors Abilities to Ability Groups.

This commit is contained in:
2023-05-03 15:04:46 -07:00
parent 182f76cb87
commit cf383f27c7
8 changed files with 1496 additions and 733 deletions

View File

@@ -4,41 +4,34 @@
#include <string> #include <string>
namespace SBF { namespace SBF {
namespace {
using std::ostream; using std::ostream;
using std::string; using std::string;
using std::vector; using std::vector;
} // End namespace
const int kAbilitiesCount = 3; const int kAbilityGroupUnknownId = 0;
const std::string kAbilityGroupUnknownLabel = "";
const std::string kAbilityGroupTalentsSingular = "Talent";
const std::string kAbilityGroupTalentsPlural = "Talents";
const std::string kAbilityGroupSkillsSingular = "Skill";
const std::string kAbilityGroupSkillsPlural = "Skills";
const std::string kAbilityGroupKnowledgesSingular = "Knowledge";
const std::string kAbilityGroupKnowledgesPlural = "Knowledges";
const AbilityGroup kAbilityGroupUnknown =
AbilityGroup(kAbilityGroupUnknownId, kAbilityGroupUnknownLabel, kAbilityGroupUnknownLabel);
const AbilityGroup kAbilityGroupTalents =
AbilityGroup(kAbilityGroupTalentsId, kAbilityGroupTalentsSingular, kAbilityGroupTalentsPlural);
const AbilityGroup kAbilityGroupSkills =
AbilityGroup(kAbilityGroupSkillsId, kAbilityGroupSkillsSingular, kAbilityGroupSkillsPlural);
const AbilityGroup kAbilityGroupKnowledges =
AbilityGroup(kAbilityGroupKnowledgesId, kAbilityGroupKnowledgesSingular, kAbilityGroupKnowledgesPlural);
const vector<AbilityGroup> kAbilityGroups = {kAbilityGroupTalents, kAbilityGroupSkills, kAbilityGroupKnowledges};
const int kAbilityUnknownId = 0;
const std::string kAbilityUnknownLabel = ""; const std::string kAbilityUnknownLabel = "";
const std::string kAbilityTalentsSingular = "Talent"; const Ability kAbilityUnknown = Ability(kAbilityUnknownId, kAbilityGroupUnknownId, kAbilityUnknownLabel);
const std::string kAbilityTalentsPlural = "Talents";
const std::string kAbilitySkillsSingular = "Skill";
const std::string kAbilitySkillsPlural = "Skills";
const std::string kAbilityKnowledgesSingular = "Knowledge";
const std::string kAbilityKnowledgesPlural = "Knowledges";
const AbilityType kAbilityGroupUnknown = {0, "", ""};
const AbilityType kAbilityGroupTalents = {
kAbilityTalentsId,
kAbilityTalentsSingular,
kAbilityTalentsPlural,
};
const AbilityType kAbilityGroupSkills = {
kAbilitySkillsId,
kAbilitySkillsSingular,
kAbilitySkillsPlural,
};
const AbilityType kAbilityGroupKnowledges = {
kAbilityKnowledgesId,
kAbilityKnowledgesSingular,
kAbilityKnowledgesPlural,
};
const AbilityType kAbilities[]{
kAbilityGroupUnknown,
kAbilityGroupTalents,
kAbilityGroupSkills,
kAbilityGroupKnowledges,
};
const std::string kTalentActingLabel = "Acting"; const std::string kTalentActingLabel = "Acting";
const std::string kTalentAlertnessLabel = "Alertness"; const std::string kTalentAlertnessLabel = "Alertness";
@@ -50,6 +43,29 @@ const std::string kTalentIntimidationLabel = "Intimidation";
const std::string kTalentLeadershipLabel = "Leadership"; const std::string kTalentLeadershipLabel = "Leadership";
const std::string kTalentStreetwiseLabel = "Streetwise"; const std::string kTalentStreetwiseLabel = "Streetwise";
const std::string kTalentSubterfugeLabel = "Subterfuge"; const std::string kTalentSubterfugeLabel = "Subterfuge";
const Ability kTalentActing = Ability(kTalentActingId, kAbilityGroupTalentsId, kTalentActingLabel);
const Ability kTalentAlertness = Ability(kTalentAlertnessId, kAbilityGroupTalentsId, kTalentAlertnessLabel);
const Ability kTalentAthletics = Ability(kTalentAthleticsId, kAbilityGroupTalentsId, kTalentAthleticsLabel);
const Ability kTalentBrawl = Ability(kTalentBrawlId, kAbilityGroupTalentsId, kTalentBrawlLabel);
const Ability kTalentDodge = Ability(kTalentDodgeId, kAbilityGroupTalentsId, kTalentDodgeLabel);
const Ability kTalentEmpathy = Ability(kTalentEmpathyId, kAbilityGroupTalentsId, kTalentEmpathyLabel);
const Ability kTalentIntimidation = Ability(kTalentIntimidationId, kAbilityGroupTalentsId, kTalentIntimidationLabel);
const Ability kTalentLeadership = Ability(kTalentLeadershipId, kAbilityGroupTalentsId, kTalentLeadershipLabel);
const Ability kTalentStreetwise = Ability(kTalentStreetwiseId, kAbilityGroupTalentsId, kTalentStreetwiseLabel);
const Ability kTalentSubterfuge = Ability(kTalentSubterfugeId, kAbilityGroupTalentsId, kTalentSubterfugeLabel);
const vector<Ability> kTalents = {
kTalentActing,
kTalentAlertness,
kTalentAthletics,
kTalentBrawl,
kTalentDodge,
kTalentEmpathy,
kTalentIntimidation,
kTalentLeadership,
kTalentStreetwise,
kTalentSubterfuge,
};
const std::string kSkillAnimalKenLabel = "Animal Ken"; const std::string kSkillAnimalKenLabel = "Animal Ken";
const std::string kSkillDriveLabel = "Drive"; const std::string kSkillDriveLabel = "Drive";
const std::string kSkillEtiquetteLabel = "Etiquette"; const std::string kSkillEtiquetteLabel = "Etiquette";
@@ -60,6 +76,29 @@ const std::string kSkillRepairLabel = "Repair";
const std::string kSkillSecurityLabel = "Security"; const std::string kSkillSecurityLabel = "Security";
const std::string kSkillStealthLabel = "Stealth"; const std::string kSkillStealthLabel = "Stealth";
const std::string kSkillSurvivalLabel = "Survival"; const std::string kSkillSurvivalLabel = "Survival";
const Ability kSkillAnimalKen = Ability(kSkillAnimalKenId, kAbilityGroupSkillsId, kSkillAnimalKenLabel);
const Ability kSkillDrive = Ability(kSkillDriveId, kAbilityGroupSkillsId, kSkillDriveLabel);
const Ability kSkillEtiquette = Ability(kSkillEtiquetteId, kAbilityGroupSkillsId, kSkillEtiquetteLabel);
const Ability kSkillFirearms = Ability(kSkillFirearmsId, kAbilityGroupSkillsId, kSkillFirearmsLabel);
const Ability kSkillMelee = Ability(kSkillMeleeId, kAbilityGroupSkillsId, kSkillMeleeLabel);
const Ability kSkillMusic = Ability(kSkillMusicId, kAbilityGroupSkillsId, kSkillMusicLabel);
const Ability kSkillRepair = Ability(kSkillRepairId, kAbilityGroupSkillsId, kSkillRepairLabel);
const Ability kSkillSecurity = Ability(kSkillSecurityId, kAbilityGroupSkillsId, kSkillSecurityLabel);
const Ability kSkillStealth = Ability(kSkillStealthId, kAbilityGroupSkillsId, kSkillStealthLabel);
const Ability kSkillSurvival = Ability(kSkillSurvivalId, kAbilityGroupSkillsId, kSkillSurvivalLabel);
const vector<Ability> kSkills = {
kSkillAnimalKen,
kSkillDrive,
kSkillEtiquette,
kSkillFirearms,
kSkillMelee,
kSkillMusic,
kSkillRepair,
kSkillSecurity,
kSkillStealth,
kSkillSurvival,
};
const std::string kKnowledgeBureaucracyLabel = "Bureaucracy"; const std::string kKnowledgeBureaucracyLabel = "Bureaucracy";
const std::string kKnowledgeComputerLabel = "Computer"; const std::string kKnowledgeComputerLabel = "Computer";
const std::string kKnowledgeFinanceLabel = "Finance"; const std::string kKnowledgeFinanceLabel = "Finance";
@@ -70,210 +109,269 @@ const std::string kKnowledgeMedicineLabel = "Medicine";
const std::string kKnowledgeOccultLabel = "Occult"; const std::string kKnowledgeOccultLabel = "Occult";
const std::string kKnowledgePoliticsLabel = "Politics"; const std::string kKnowledgePoliticsLabel = "Politics";
const std::string kKnowledgeScienceLabel = "Science"; const std::string kKnowledgeScienceLabel = "Science";
const int kTalentsCount = 10; const Ability kKnowledgeBureaucracy =
const int kSkillsCount = 10; Ability(kKnowledgeBureaucracyId, kAbilityGroupKnowledgesId, kKnowledgeBureaucracyLabel);
const int kKnowledgesCount = 10; const Ability kKnowledgeComputer = Ability(kKnowledgeComputerId, kAbilityGroupKnowledgesId, kKnowledgeComputerLabel);
const std::string kSkills[] = { const Ability kKnowledgeFinance = Ability(kKnowledgeFinanceId, kAbilityGroupKnowledgesId, kKnowledgeFinanceLabel);
kAbilityUnknownLabel, const Ability kKnowledgeInvestigation =
kSkillAnimalKenLabel, Ability(kKnowledgeInvestigationId, kAbilityGroupKnowledgesId, kKnowledgeInvestigationLabel);
kSkillDriveLabel, const Ability kKnowledgeLaw = Ability(kKnowledgeLawId, kAbilityGroupKnowledgesId, kKnowledgeLawLabel);
kSkillEtiquetteLabel, const Ability kKnowledgeLinguistics =
kSkillFirearmsLabel, Ability(kKnowledgeLinguisticsId, kAbilityGroupKnowledgesId, kKnowledgeLinguisticsLabel);
kSkillMeleeLabel, const Ability kKnowledgeMedicine = Ability(kKnowledgeMedicineId, kAbilityGroupKnowledgesId, kKnowledgeMedicineLabel);
kSkillMusicLabel, const Ability kKnowledgeOccult = Ability(kKnowledgeOccultId, kAbilityGroupKnowledgesId, kKnowledgeOccultLabel);
kSkillRepairLabel, const Ability kKnowledgePolitics = Ability(kKnowledgePoliticsId, kAbilityGroupKnowledgesId, kKnowledgePoliticsLabel);
kSkillSecurityLabel, const Ability kKnowledgeScience = Ability(kKnowledgeScienceId, kAbilityGroupKnowledgesId, kKnowledgeScienceLabel);
kSkillStealthLabel, const vector<Ability> kKnowledges = {
kSkillSurvivalLabel, kKnowledgeBureaucracy,
}; kKnowledgeComputer,
const std::string kTalents[] = { kKnowledgeFinance,
kAbilityUnknownLabel, kKnowledgeInvestigation,
kTalentActingLabel, kKnowledgeLaw,
kTalentAlertnessLabel, kKnowledgeLinguistics,
kTalentAthleticsLabel, kKnowledgeMedicine,
kTalentBrawlLabel, kKnowledgeOccult,
kTalentDodgeLabel, kKnowledgePolitics,
kTalentEmpathyLabel, kKnowledgeScience,
kTalentIntimidationLabel,
kTalentLeadershipLabel,
kTalentStreetwiseLabel,
kTalentSubterfugeLabel,
};
const std::string kKnowledges[] = {
kAbilityUnknownLabel,
kKnowledgeBureaucracyLabel,
kKnowledgeComputerLabel,
kKnowledgeFinanceLabel,
kKnowledgeInvestigationLabel,
kKnowledgeLawLabel,
kKnowledgeLinguisticsLabel,
kKnowledgeMedicineLabel,
kKnowledgeOccultLabel,
kKnowledgePoliticsLabel,
kKnowledgeScienceLabel,
}; };
ostream& operator<<(ostream& os, const AbilityType& ability) { vector<string> AbilityGroup::GetAbilityLabels() const {
os << "AbilityGroup: {id: " << ability.id << ", singular: \"" << ability.singular << "\", plural: \"" return AbilityGroup::GetAbilityLabels(id_);
<< ability.plural << "\"}";
return os;
} }
bool operator==(const AbilityType& left, const AbilityType& right) { vector<string> AbilityGroup::GetAbilityLabels(int id) {
return left.id == right.id && left.singular == right.singular && left.plural == right.plural;
}
bool operator!=(const AbilityType& left, const AbilityType& right) {
return !(left == right);
}
void FillAbilities(vector<AbilityType>& abilities) {
abilities.clear();
abilities.push_back(kAbilityGroupTalents);
abilities.push_back(kAbilityGroupSkills);
abilities.push_back(kAbilityGroupKnowledges);
}
vector<string> GetAbilityGroupPluralLabels() {
vector<string> labels;
for (int id = 1; id <= kAbilitiesCount; id++) {
labels.push_back(GetAbility(id).plural);
}
return labels;
}
void FillAbilitiesForAbilityGroup(vector<string>& abilities, int id) {
abilities.clear();
int numAbilities = GetNumItemsForAbilityGroup(id);
switch (id) { switch (id) {
case kAbilityTalentsId: case kAbilityGroupKnowledgesId:
for (int talent_id = 1; talent_id <= numAbilities; talent_id++) { return Ability::GetKnowledgeLabels();
abilities.push_back(GetTalentLabel(talent_id)); case kAbilityGroupSkillsId:
} return Ability::GetSkillLabels();
break; case kAbilityGroupTalentsId:
case kAbilitySkillsId: return Ability::GetTalentLabels();
for (int skill_id = 1; skill_id <= numAbilities; skill_id++) {
abilities.push_back(GetSkillLabel(skill_id));
}
break;
case kAbilityKnowledgesId:
for (int knowledge_id = 1; knowledge_id <= numAbilities; knowledge_id++) {
abilities.push_back(GetKnowledgeLabel(knowledge_id));
}
break;
}
}
vector<string> GetAbilityLabelsForAbilityGroup(int group_id) {
vector<string> labels;
int count = GetNumItemsForAbilityGroup(group_id);
for (int id = 1; id <= count; id++) {
labels.push_back(GetAbilityLabel(group_id, id));
} }
return labels; return vector<string>();
}
void FillAbilityLabels(vector<string>& labels, int id) {
labels.clear();
switch (id) {
case kAbilityTalentsId:
FillTalentLabels(labels);
break;
case kAbilitySkillsId:
FillSkillLabels(labels);
break;
case kAbilityKnowledgesId:
FillKnowledgeLabels(labels);
break;
}
}
void FillKnowledgeLabels(vector<string>& labels) {
labels.clear();
int numAbilities = GetNumItemsForAbilityGroup(kAbilityKnowledgesId);
for (int knowledge_id = 1; knowledge_id <= numAbilities; knowledge_id++) {
labels.push_back(GetKnowledgeLabel(knowledge_id));
}
}
void FillSkillLabels(vector<string>& labels) {
labels.clear();
int numAbilities = GetNumItemsForAbilityGroup(kAbilitySkillsId);
for (int skill_id = 1; skill_id <= numAbilities; skill_id++) {
labels.push_back(GetSkillLabel(skill_id));
}
}
void FillTalentLabels(vector<string>& labels) {
labels.clear();
int numAbilities = GetNumItemsForAbilityGroup(kAbilityTalentsId);
for (int talent_id = 1; talent_id <= numAbilities; talent_id++) {
labels.push_back(GetTalentLabel(talent_id));
}
}
const AbilityType& GetAbility(int ability_group_id) {
switch (ability_group_id) {
case kAbilityTalentsId:
return kAbilityGroupTalents;
case kAbilitySkillsId:
return kAbilityGroupSkills;
case kAbilityKnowledgesId:
return kAbilityGroupKnowledges;
};
return kAbilityGroupUnknown;
}
const string GetAbilityLabel(int ability_group_id, int ability_id) {
switch (ability_group_id) {
case kAbilityTalentsId:
return GetTalentLabel(ability_id);
case kAbilitySkillsId:
return GetSkillLabel(ability_id);
case kAbilityKnowledgesId:
return GetKnowledgeLabel(ability_id);
};
return "";
}
const std::string GetKnowledgeLabel(int talent_id) {
if (talent_id > 0 && talent_id <= kKnowledgesCount) {
return kKnowledges[talent_id];
}
return "";
} }
int GetNumItemsForAbilityGroup(int ability_group_id) { int GetNumItemsForAbilityGroup(int ability_group_id) {
switch (ability_group_id) { switch (ability_group_id) {
case kAbilityTalentsId: case kAbilityGroupTalentsId:
return kTalentsCount; return kTalents.size();
case kAbilitySkillsId: case kAbilityGroupSkillsId:
return kSkillsCount; return kSkills.size();
case kAbilityKnowledgesId: case kAbilityGroupKnowledgesId:
return kKnowledgesCount; return kKnowledges.size();
} }
return 0; return 0;
} }
const std::string GetSkillLabel(int skill_id) { int AbilityGroup::GetCount() {
if (skill_id > 0 && skill_id <= kSkillsCount) { return kAbilityGroups.size();
return kSkills[skill_id];
}
return "";
} }
const std::string GetTalentLabel(int talent_id) { int AbilityGroup::GetAbilityCount() const {
if (talent_id > 0 && talent_id <= kTalentsCount) { switch (id_) {
return kTalents[talent_id]; case kAbilityGroupKnowledgesId:
return kTalents.size();
case kAbilityGroupSkillsId:
return kSkills.size();
case kAbilityGroupTalentsId:
return kTalents.size();
} }
return ""; return 0;
} }
int GetNumAbilityGroups() { AbilityGroup::AbilityGroup() : id_(0), singular_(""), plural_("") {}
return kAbilitiesCount;
AbilityGroup::AbilityGroup(int id, const string& singular, const string& plural)
: id_(id), singular_(singular), plural_(plural) {}
int AbilityGroup::id() const {
return id_;
}
void AbilityGroup::id(int id) {
id_ = id;
}
string AbilityGroup::plural() const {
return plural_;
}
void AbilityGroup::plural(const string& plural) {
plural_ = plural;
}
string AbilityGroup::singular() const {
return singular_;
}
void AbilityGroup::singular(const string& singular) {
singular_ = singular;
}
vector<string> AbilityGroup::GetPluralLabels() {
vector<string> labels;
for_each(kAbilityGroups.begin(), kAbilityGroups.end(), [&labels](const auto& ability) {
labels.push_back(ability.plural());
});
return labels;
}
Ability::Ability() : id_(0), group_id_(0), label_("") {}
Ability::Ability(int id, int group_id, const string& label) : id_(id), group_id_(group_id), label_(label) {}
int Ability::id() const {
return id_;
}
void Ability::id(int id) {
id_ = id;
}
int Ability::group_id() const {
return group_id_;
}
void Ability::group_id(int group_id) {
group_id_ = group_id;
}
string Ability::label() const {
return label_;
}
void Ability::label(const string& label) {
label_ = label;
}
AbilityGroup AbilityGroup::FromId(int id) {
switch (id) {
case kAbilityGroupTalentsId:
return kAbilityGroupTalents;
case kAbilityGroupSkillsId:
return kAbilityGroupSkills;
case kAbilityGroupKnowledgesId:
return kAbilityGroupKnowledges;
}
return kAbilityGroupUnknown;
}
ostream& operator<<(ostream& os, const AbilityGroup& ability_group) {
os << "AbilityGroup: {id: " << ability_group.id_ << ", singular: \"" << ability_group.singular_ << "\", plural: \""
<< ability_group.plural_ << "\"}";
return os;
}
bool AbilityGroup::operator==(const AbilityGroup& other) const {
return id_ == other.id_ && singular_ == other.singular_ && plural_ == other.plural_;
}
bool AbilityGroup::operator!=(const AbilityGroup& other) const {
return !(*this == other);
}
ostream& operator<<(ostream& os, const Ability& ability) {
os << "Ability: {id: " << ability.id_ << ", group_id: " << ability.group_id_ << ", label: \"" << ability.label_
<< "\"}";
return os;
}
bool Ability::operator==(const Ability& other) const {
return id_ == other.id_ && group_id_ == other.group_id_ && label_ == other.label_;
}
bool Ability::operator!=(const Ability& other) const {
return !(*this == other);
}
string Ability::GetSkillLabel(int id) {
return Ability::FromSkillId(id).label();
}
vector<string> Ability::GetSkillLabels() {
vector<string> labels;
for_each(kSkills.begin(), kSkills.end(), [&labels](const auto& ability) { labels.push_back(ability.label()); });
return labels;
}
string Ability::GetTalentLabel(int id) {
return Ability::FromTalentId(id).label();
}
vector<string> Ability::GetTalentLabels() {
vector<string> labels;
for_each(kTalents.begin(), kTalents.end(), [&labels](const auto& ability) { labels.push_back(ability.label()); });
return labels;
}
string Ability::GetKnowledgeLabel(int id) {
return Ability::FromKnowledgeId(id).label();
}
vector<string> Ability::GetKnowledgeLabels() {
vector<string> labels;
for_each(
kKnowledges.begin(), kKnowledges.end(), [&labels](const auto& ability) { labels.push_back(ability.label()); });
return labels;
}
Ability Ability::FromKnowledgeId(int id) {
if (id > 0 && id <= kKnowledges.size()) {
return kKnowledges.at(id - 1);
}
return kAbilityUnknown;
}
Ability Ability::FromSkillId(int id) {
if (id > 0 && id <= kSkills.size()) {
return kSkills.at(id - 1);
}
return kAbilityUnknown;
}
Ability Ability::FromTalentId(int id) {
if (id > 0 && id <= kTalents.size()) {
return kTalents.at(id - 1);
}
return kAbilityUnknown;
}
Ability Ability::FromIds(int id, int group_id) {
switch (group_id) {
case kAbilityGroupKnowledgesId:
return Ability::FromKnowledgeId(id);
case kAbilityGroupSkillsId:
return Ability::FromSkillId(id);
case kAbilityGroupTalentsId:
return Ability::FromTalentId(id);
}
return kAbilityUnknown;
}
int Ability::GetCount(int group_id) {
switch (group_id) {
case kAbilityGroupKnowledgesId:
return kKnowledges.size();
case kAbilityGroupSkillsId:
return kSkills.size();
case kAbilityGroupTalentsId:
return kTalents.size();
}
return 0;
}
int Ability::GetKnowledgesCount() {
return kKnowledges.size();
}
int Ability::GetSkillsCount() {
return kSkills.size();
}
int Ability::GetTalentsCount() {
return kTalents.size();
} }
} // End namespace SBF } // End namespace SBF

View File

@@ -16,9 +16,9 @@
* @{ * @{
*/ */
namespace SBF { namespace SBF {
const int kAbilityTalentsId = 1; const int kAbilityGroupTalentsId = 1;
const int kAbilitySkillsId = 2; const int kAbilityGroupSkillsId = 2;
const int kAbilityKnowledgesId = 3; const int kAbilityGroupKnowledgesId = 3;
const int kTalentActingId = 1; const int kTalentActingId = 1;
const int kTalentAlertnessId = 2; const int kTalentAlertnessId = 2;
@@ -53,99 +53,73 @@ const int kKnowledgeOccultId = 8;
const int kKnowledgePoliticsId = 9; const int kKnowledgePoliticsId = 9;
const int kKnowledgeScienceId = 10; const int kKnowledgeScienceId = 10;
/// @brief This type represents an ability group such as Talents, Skills or Knowledges. class AbilityGroup {
struct AbilityType { public:
/// @brief The id of this ability group AbilityGroup();
int id; AbilityGroup(int id, const std::string& singular, const std::string& plural);
/// @brief The singular form of this group i.e. Talent. int GetAbilityCount() const;
std::string singular; std::vector<std::string> GetAbilityLabels() const;
/// @brief The plural form of this group i.e. Talents. int id() const;
std::string plural; void id(int id);
std::string plural() const;
void plural(const std::string& plural);
std::string singular() const;
void singular(const std::string& singular);
bool operator==(const AbilityGroup& other) const;
bool operator!=(const AbilityGroup& other) const;
static AbilityGroup FromId(int id);
static std::vector<std::string> GetPluralLabels();
static std::vector<std::string> GetAbilityLabels(int id);
static int GetCount();
friend std::ostream& operator<<(std::ostream& os, const AbilityGroup& ability_group);
private:
int id_;
std::string singular_;
std::string plural_;
}; };
/// @brief This function writes an AbilityType value to an output stream; std::ostream& operator<<(std::ostream& os, const AbilityGroup& ability_group);
/// @param os The output stream to write to.
/// @param group The AbilityType to write.
/// @return Thw output stream for chaining.
std::ostream& operator<<(std::ostream& os, const AbilityType& group);
/// @brief This function compares two AbilityType values for equality. class Ability {
/// @param left The first AbilityType. public:
/// @param right The second AbilityType. Ability();
/// @return True if left is equal to right and false otherwise. Ability(int id, int group_id, const std::string& label);
bool operator==(const AbilityType& left, const AbilityType& right); int group_id() const;
void group_id(int group_id);
int id() const;
void id(int id);
std::string label() const;
void label(const std::string& label);
bool operator==(const Ability& other) const;
bool operator!=(const Ability& other) const;
/// @brief This function compares two AbilityType values for equality. static Ability FromIds(int id, int group_id);
/// @param left The first AbilityType. static Ability FromKnowledgeId(int id);
/// @param right The second AbilityType. static Ability FromSkillId(int id);
/// @return True if left and right are not equal and false otherwise. static Ability FromTalentId(int id);
bool operator!=(const AbilityType& left, const AbilityType& right); static int GetCount(int group_id);
static std::string GetKnowledgeLabel(int id);
static std::vector<std::string> GetKnowledgeLabels();
static int GetKnowledgesCount();
static std::string GetSkillLabel(int id);
static std::vector<std::string> GetSkillLabels();
static int GetSkillsCount();
static std::string GetTalentLabel(int id);
static std::vector<std::string> GetTalentLabels();
static int GetTalentsCount();
/// @brief Fills the provided vector with all of the available ability groups. It will be cleared before filling. friend std::ostream& operator<<(std::ostream& os, const Ability& ability);
/// @param abilities The vector to fill.
void FillAbilities(std::vector<AbilityType>& abilities);
std::vector<std::string> GetAbilityGroupPluralLabels(); private:
int id_;
int group_id_;
std::string label_;
};
/// @brief Fills the provided vector with all of the ability labels in the specified group. It will be cleared before std::ostream& operator<<(std::ostream& os, const Ability& ability);
/// filling.
/// @param abilities The vector to fill.
/// @param id The id of the ability group to fill for.
void FillAbilitiesForAbilityGroup(std::vector<std::string>& abilities, int id);
std::vector<std::string> GetAbilityLabelsForAbilityGroup(int group_id);
/// @brief Fills the provided vector with all of the ability labels in the specified group. It will be cleared before
/// filling.
/// @param labels The vector to fill.
/// @param id The id of the ability group to fill for.
void FillAbilityLabels(std::vector<std::string>& labels, int id);
/// @brief Fills the provided vector with all of the knowledge labels. It will be cleared before filling.
/// @param labels The vector to fill.
void FillKnowledgeLabels(std::vector<std::string>& labels);
/// @brief Fills the provided vector with all of the skill labels. It will be cleared before filling.
/// @param labels The vector to fill.
void FillSkillLabels(std::vector<std::string>& labels);
/// @brief Fills the provided vector with all of the talent labels. It will be cleared before filling.
/// @param labels The vector to fill.
void FillTalentLabels(std::vector<std::string>& labels);
/// @brief Gets an ability group for a given id.
/// @param id The id of the ability group to return.
/// @return The ability group with an id of id or kAbilityGroupUnknown if id is invalid.
const AbilityType& GetAbility(int id);
/// @brief Gets the label for an ability given its ability group (talents/skills/knowledges) and its id (acting, brawl,
/// dodge, ...).
/// @param group_id The id for the ability group (talents/skills/knowledges).
/// @param id The id for the ability within the ability group (acting, dodge, brawl, ...).
/// @return The label for the specific ability ("Acting").
const std::string GetAbilityLabel(int group_id, int id);
/// @brief Gets the label for a knowledge ability given its id.
/// @param id The id of the ability to return the label for.
/// @return The label for the specific ability.
const std::string GetKnowledgeLabel(int id);
/// @brief Gets the number of abilities in an ability group.
/// @param id The id of the ability group to return the number of abilities for.
/// @return The number of abilities in the specific ability group.
int GetNumItemsForAbilityGroup(int id);
/// @brief Gets the label for a skill ability given its id.
/// @param id The id of the ability to return the label for.
/// @return The label of the specific ability.
const std::string GetSkillLabel(int id);
/// @brief Gets the label for a talent ability given its id.
/// @param id The id of the ability to return.
/// @return The label for the specific ability.
const std::string GetTalentLabel(int id);
int GetNumAbilityGroups();
} // End namespace SBF } // End namespace SBF
/** @}*/ /** @}*/

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@ cc_library(
cc_test( cc_test(
name = "abilities_test", name = "abilities_test",
size = "small",
srcs = ["Abilities_test.cpp"], srcs = ["Abilities_test.cpp"],
deps = [ deps = [
":abilities", ":abilities",
@@ -29,6 +30,7 @@ cc_library(
cc_test( cc_test(
name = "archetypes_test", name = "archetypes_test",
size = "small",
srcs = ["Archetypes_test.cpp"], srcs = ["Archetypes_test.cpp"],
deps = [ deps = [
":archetypes", ":archetypes",
@@ -44,6 +46,7 @@ cc_library(
cc_test( cc_test(
name = "attributes_test", name = "attributes_test",
size = "small",
srcs = ["Attributes_test.cpp"], srcs = ["Attributes_test.cpp"],
deps = [ deps = [
":attributes", ":attributes",
@@ -59,6 +62,7 @@ cc_library(
cc_test( cc_test(
name = "backgrounds_test", name = "backgrounds_test",
size = "small",
srcs = ["Backgrounds_test.cpp"], srcs = ["Backgrounds_test.cpp"],
deps = [ deps = [
":backgrounds", ":backgrounds",
@@ -85,6 +89,7 @@ cc_library(
cc_test( cc_test(
name = "character_test", name = "character_test",
size = "small",
srcs = ["Character_test.cpp"], srcs = ["Character_test.cpp"],
deps = [ deps = [
":character", ":character",
@@ -100,6 +105,7 @@ cc_library(
cc_test( cc_test(
name = "clans_test", name = "clans_test",
size = "small",
srcs = ["Clans_test.cpp"], srcs = ["Clans_test.cpp"],
deps = [ deps = [
":clans", ":clans",
@@ -115,6 +121,7 @@ cc_library(
cc_test( cc_test(
name = "colors_test", name = "colors_test",
size = "small",
srcs = ["Colors_test.cpp"], srcs = ["Colors_test.cpp"],
deps = [ deps = [
":colors", ":colors",
@@ -131,6 +138,7 @@ cc_library(
cc_test( cc_test(
name = "derangements_test", name = "derangements_test",
size = "small",
srcs = ["Derangements_test.cpp"], srcs = ["Derangements_test.cpp"],
deps = [ deps = [
":derangements", ":derangements",
@@ -146,6 +154,7 @@ cc_library(
cc_test( cc_test(
name = "disciplines_test", name = "disciplines_test",
size = "small",
srcs = ["Disciplines_test.cpp"], srcs = ["Disciplines_test.cpp"],
deps = [ deps = [
":disciplines", ":disciplines",
@@ -161,6 +170,7 @@ cc_library(
cc_test( cc_test(
name = "freebies_test", name = "freebies_test",
size = "small",
srcs = ["Freebies_test.cpp"], srcs = ["Freebies_test.cpp"],
deps = [ deps = [
":freebies", ":freebies",
@@ -176,6 +186,7 @@ cc_library(
cc_test( cc_test(
name = "genders_test", name = "genders_test",
size = "small",
srcs = ["Genders_test.cpp"], srcs = ["Genders_test.cpp"],
deps = [ deps = [
":genders", ":genders",
@@ -198,6 +209,7 @@ cc_library(
cc_test( cc_test(
name = "character_generator_test", name = "character_generator_test",
size = "small",
srcs = ["CharacterGenerator_test.cpp"], srcs = ["CharacterGenerator_test.cpp"],
deps = [ deps = [
":character_generator", ":character_generator",
@@ -233,6 +245,7 @@ cc_library(
cc_test( cc_test(
name = "menus_test", name = "menus_test",
size = "small",
srcs = ["Menus_test.cpp"], srcs = ["Menus_test.cpp"],
deps = [ deps = [
":menus", ":menus",
@@ -248,6 +261,7 @@ cc_library(
cc_test( cc_test(
name = "random_test", name = "random_test",
size = "small",
srcs = ["Random_test.cpp"], srcs = ["Random_test.cpp"],
deps = [ deps = [
":random", ":random",
@@ -263,6 +277,7 @@ cc_library(
cc_test( cc_test(
name = "ranks_test", name = "ranks_test",
size = "small",
srcs = ["Ranks_test.cpp"], srcs = ["Ranks_test.cpp"],
deps = [ deps = [
":ranks", ":ranks",
@@ -299,6 +314,7 @@ cc_library(
cc_test( cc_test(
name = "utils_test", name = "utils_test",
size = "small",
srcs = ["Utils_test.cpp"], srcs = ["Utils_test.cpp"],
deps = [ deps = [
":tinytest", ":tinytest",
@@ -314,6 +330,7 @@ cc_library(
cc_test( cc_test(
name = "virtues_test", name = "virtues_test",
size = "small",
srcs = ["Virtues_test.cpp"], srcs = ["Virtues_test.cpp"],
deps = [ deps = [
":tinytest", ":tinytest",

View File

@@ -47,8 +47,9 @@ CharacterType::CharacterType() {
// Arrays/Objects // Arrays/Objects
// Abilities (Talents/Skills/Knowledges) // Abilities (Talents/Skills/Knowledges)
for (int group_id = 1; group_id <= GetNumAbilityGroups(); group_id++) { for (int group_id = 1; group_id <= AbilityGroup::GetCount(); group_id++) {
const int num_abilities = GetNumItemsForAbilityGroup(group_id); const AbilityGroup group = AbilityGroup::FromId(group_id);
const int num_abilities = group.GetAbilityCount();
for (int id = 1; id <= num_abilities; id++) { for (int id = 1; id <= num_abilities; id++) {
SetAbilityValue(group_id, id, 0); SetAbilityValue(group_id, id, 0);
} }
@@ -401,13 +402,13 @@ int GetAttributePointsForRank(int id) {
void CharacterType::SetAbilityValue(int group_id, int id, int value) { void CharacterType::SetAbilityValue(int group_id, int id, int value) {
switch (group_id) { switch (group_id) {
case kAbilityTalentsId: case kAbilityGroupTalentsId:
SetTalentValue(id, value); SetTalentValue(id, value);
break; break;
case kAbilitySkillsId: case kAbilityGroupSkillsId:
SetSkillValue(id, value); SetSkillValue(id, value);
break; break;
case kAbilityKnowledgesId: case kAbilityGroupKnowledgesId:
SetKnowledgeValue(id, value); SetKnowledgeValue(id, value);
break; break;
} }
@@ -415,11 +416,11 @@ void CharacterType::SetAbilityValue(int group_id, int id, int value) {
int CharacterType::GetAbilityValue(int group_id, int id) const { int CharacterType::GetAbilityValue(int group_id, int id) const {
switch (group_id) { switch (group_id) {
case kAbilityTalentsId: case kAbilityGroupTalentsId:
return GetTalentValue(id); return GetTalentValue(id);
case kAbilityKnowledgesId: case kAbilityGroupKnowledgesId:
return GetKnowledgeValue(id); return GetKnowledgeValue(id);
case kAbilitySkillsId: case kAbilityGroupSkillsId:
return GetSkillValue(id); return GetSkillValue(id);
} }
return 0; return 0;
@@ -438,7 +439,8 @@ int GetAbilityPointsForRank(int id) {
} }
void CharacterType::FillAbilityValues(std::vector<int>& values, int group_id) const { void CharacterType::FillAbilityValues(std::vector<int>& values, int group_id) const {
int num_abilities = GetNumItemsForAbilityGroup(group_id); const AbilityGroup group = AbilityGroup::FromId(group_id);
int num_abilities = group.GetAbilityCount();
values.clear(); values.clear();
for (int id = 0; id <= num_abilities; id++) { for (int id = 0; id <= num_abilities; id++) {
values[id] = GetAbilityValue(group_id, id); values[id] = GetAbilityValue(group_id, id);

View File

@@ -273,18 +273,18 @@ void CGSpendAbilityPoint(CharacterType& ch) {
bool done = false; bool done = false;
while (!done) { while (!done) {
MaybeClearScreen(); MaybeClearScreen();
ms.cancel_item_id = GetNumAbilityGroups(); ms.cancel_item_id = AbilityGroup::GetCount();
int ability_group_id = int ability_group_id =
ChooseStringId(GetAbilityGroupPluralLabels(), ms, "What kind of ability would you like to add 1 dot to?"); ChooseStringId(AbilityGroup::GetPluralLabels(), ms, "What kind of ability would you like to add 1 dot to?");
if (ability_group_id == ms.cancel_item_id) { if (ability_group_id == ms.cancel_item_id) {
return; return;
} }
AbilityType ability = GetAbility(ability_group_id); AbilityGroup ability_group = AbilityGroup::FromId(ability_group_id);
vector<string> labels = GetAbilityLabelsForAbilityGroup(ability_group_id); vector<string> labels = ability_group.GetAbilityLabels();
ms.cancel_item_id = labels.size() + 1; ms.cancel_item_id = labels.size() + 1;
int ability_id = int ability_id =
ChooseStringId(labels, ms, "What " + ToLower(ability.singular) + " would you like to add 1 dot to?"); ChooseStringId(labels, ms, "What " + ToLower(ability_group.singular()) + " would you like to add 1 dot to?");
if (ability_id != ms.cancel_item_id) { if (ability_id != ms.cancel_item_id) {
ch.SetAbilityValue(ability_group_id, ability_id, ch.GetAbilityValue(ability_group_id, ability_id) + 1); ch.SetAbilityValue(ability_group_id, ability_id, ch.GetAbilityValue(ability_group_id, ability_id) + 1);
ch.SetFreebiePoints(ch.GetFreebiePoints() - GetFreebieCost(kFreebieAbilityId)); ch.SetFreebiePoints(ch.GetFreebiePoints() - GetFreebieCost(kFreebieAbilityId));
@@ -426,9 +426,9 @@ void ShowCharacterSheet(CharacterType& ch) {
cout << "" << MakeFitC("Abilities", 76) << "" << endl; cout << "" << MakeFitC("Abilities", 76) << "" << endl;
cout << "" << MakeFitC("Talents", 24) << MakeFitC("Skills", 24) << MakeFitC("Knowledges", 24) << "" << endl; cout << "" << MakeFitC("Talents", 24) << MakeFitC("Skills", 24) << MakeFitC("Knowledges", 24) << "" << endl;
for (index = 1; index <= 10; index++) { for (index = 1; index <= 10; index++) {
cout << "" << FormatAbilityWithValue(GetTalentLabel(index), ch.GetTalentValue(index)) cout << "" << FormatAbilityWithValue(Ability::GetTalentLabel(index), ch.GetTalentValue(index))
<< FormatAbilityWithValue(GetSkillLabel(index), ch.GetSkillValue(index)) << FormatAbilityWithValue(Ability::GetSkillLabel(index), ch.GetSkillValue(index))
<< FormatAbilityWithValue(GetKnowledgeLabel(index), ch.GetKnowledgeValue(index)) << "" << endl; << FormatAbilityWithValue(Ability::GetKnowledgeLabel(index), ch.GetKnowledgeValue(index)) << "" << endl;
} }
cout << "╠══════════════════════════════════════╦═══════════════════════════════════════╣" << endl; cout << "╠══════════════════════════════════════╦═══════════════════════════════════════╣" << endl;
cout << "" << MakeFitL("Backgrounds:", kLeftColumnWidth) << "" << MakeFitL("Virtues:", kRightColumnWidth) << "" cout << "" << MakeFitL("Backgrounds:", kLeftColumnWidth) << "" << MakeFitL("Virtues:", kRightColumnWidth) << ""

View File

@@ -276,4 +276,8 @@ void PrintResults(std::ostream& os, TestResults results) {
os << "Skipped: " << results.skipped() << " 🚧" << endl; os << "Skipped: " << results.skipped() << " 🚧" << endl;
os << "Errors: " << results.errors() << " 🔥" << endl; os << "Errors: " << results.errors() << " 🔥" << endl;
} }
MaybeTestConfigureFunction DefaultTestConfigureFunction() {
return std::nullopt;
}
} // End namespace Test } // End namespace Test

View File

@@ -205,8 +205,14 @@ using TestCompareFunction = std::function<bool(const TResult& expected, const TR
template <typename TResult> template <typename TResult>
using MaybeTestCompareFunction = std::optional<TestCompareFunction<TResult>>; using MaybeTestCompareFunction = std::optional<TestCompareFunction<TResult>>;
template <typename TResult>
MaybeTestCompareFunction<TResult> DefaultTestCompareFunction() {
return std::nullopt;
}
using TestConfigureFunction = std::function<void()>; using TestConfigureFunction = std::function<void()>;
using MaybeTestConfigureFunction = std::optional<TestConfigureFunction>; using MaybeTestConfigureFunction = std::optional<TestConfigureFunction>;
MaybeTestConfigureFunction DefaultTestConfigureFunction();
// TODO: For some reason all hell breaks loose if test_name or expected output are const&. Figure out why. // TODO: For some reason all hell breaks loose if test_name or expected output are const&. Figure out why.
/// @brief /// @brief
@@ -410,6 +416,31 @@ TestResults execute_suite(std::string suite_label,
return results; return results;
} }
/// @brief
/// @tparam TResult The result type of the test.
/// @tparam TInputParams... The types of parameters sent to the test function.
/// @param suite_label The label for this test suite. For example a class name such as "MortgageCalculator".
/// @param function_to_test The function to be tested. It will be called with std::apply and a
/// std::tuple<TInputParams...> made from each item in tests.
/// @param tests A std::vector of test runs.
/// @param suite_compare A function used to compare the expected and actual test results. This can be
/// overridden per test by setting test_compare.
/// @param after_all This is called before each suite is started to setup the environment. This is where you should
/// build mocks, setup spies, and test fixtures.
/// @param before_all This is called after each suite has completed to cleanup anything allocated in suite_before_each.
/// @param is_enabled If false the test is reported as skipped. If true the test is run as normal.
template <typename TResult, typename... TInputParams>
TestResults execute_suite(std::string suite_label,
std::function<TResult(TInputParams...)> function_to_test,
std::initializer_list<TestTuple<TResult, TInputParams...>> tests,
MaybeTestCompareFunction<TResult> suite_compare = std::nullopt,
MaybeTestConfigureFunction before_all = std::nullopt,
MaybeTestConfigureFunction after_all = std::nullopt,
bool is_enabled = true) {
std::vector test_data = std::vector(tests);
return execute_suite(suite_label, function_to_test, tests, suite_compare, before_all, after_all, is_enabled);
}
/// @brief /// @brief
/// @tparam TResult The result type of the test. /// @tparam TResult The result type of the test.
/// @tparam ...TInputParams The types of parameters sent to the test function. /// @tparam ...TInputParams The types of parameters sent to the test function.
@@ -457,6 +488,22 @@ TestSuite<TResult, TInputParams...> make_test_suite(const string& suite_name,
return make_tuple(suite_name, function_to_test, test_data, compare, before_each, after_each, is_enabled); return make_tuple(suite_name, function_to_test, test_data, compare, before_each, after_each, is_enabled);
} }
template <typename TResult, typename TFunctionToTest, typename... TInputParams>
TestSuite<TResult, TInputParams...> make_test_suite(
const string& suite_name,
TFunctionToTest function_to_test,
std::initializer_list<TestTuple<TResult, TInputParams...>> test_data,
MaybeTestCompareFunction<TResult> compare = std::nullopt,
MaybeTestConfigureFunction before_each = std::nullopt,
MaybeTestConfigureFunction after_each = std::nullopt,
bool is_enabled = true) {
return make_tuple(suite_name, function_to_test, test_data, compare, before_each, after_each, is_enabled);
}
/// @brief
/// @tparam TResult The result type of the test.
/// @tparam TInputParams... The types of parameters sent to the test function.
/// @param test_suite A tuple representing the test suite configuration.
template <typename TResult, typename... TInputParams> template <typename TResult, typename... TInputParams>
TestResults execute_suite(const TestSuite<TResult, TInputParams...>& test_suite) { TestResults execute_suite(const TestSuite<TResult, TInputParams...>& test_suite) {
return execute_suite<TResult, TInputParams...>( return execute_suite<TResult, TInputParams...>(
@@ -493,7 +540,6 @@ MaybeTestConfigureFunction coalesce(MaybeTestConfigureFunction first, MaybeTestC
void PrintResults(std::ostream& os, TestResults results); void PrintResults(std::ostream& os, TestResults results);
} // End namespace Test } // End namespace Test
// TODO: define operator<< for std::tuple.
// TODO: Add TShared(*)(string /*test_name*/, UUID /*test_run_id*/) allocate_shared_data to the test tuple to make some // TODO: Add TShared(*)(string /*test_name*/, UUID /*test_run_id*/) allocate_shared_data to the test tuple to make some
// shared data that can be used in a thread safe way by setup, teardown, and evaluate steps of the test. // shared data that can be used in a thread safe way by setup, teardown, and evaluate steps of the test.
// TODO: Add TShared to be returned by the setup functions, and consumed by the evaluate and teardown functions. // TODO: Add TShared to be returned by the setup functions, and consumed by the evaluate and teardown functions.