diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..d7727c8c99e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing to Canary + +Thank you for your interest in contributing to Canary! This document provides guidelines for contributing to the project to ensure a smooth and effective collaboration. + +## Code of Conduct + +This project adheres to the [Contributor Covenant Code of Conduct](https://github.com/opentibiabr/canary/blob/main/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at email: opentibiabr@outlook.com or discord: https://discord.com/invite/gvTj5sh9Mp + +## Project Roadmap + +- The Canary project is part of a larger ecosystem within the Open Tibia BR organization, which includes various projects focused on enhancing and innovating within OT server development. You can follow our shared roadmap, encompassing projects like Canary, OTServBR, and OTServBR-Global, among others, in the projects section on GitHub: [Open Tibia BR - Project Roadmap](https://github.com/orgs/opentibiabr/projects). + +- This roadmap aims to ensure alignment of initiatives and prioritize the development of improvements and new features that benefit the community. Community participation is crucial, and we encourage contributors to review the roadmap before proposing major changes, to ensure these align with the strategic direction of our projects. + + +## Getting Started + +### Issues + +- **Bug Reports**: If you encounter any bugs or issues while using Canary, please submit them via our [bug report template](https://github.com/opentibiabr/canary/blob/main/.github/ISSUE_TEMPLATE/bug.yaml). +- **Feature Requests**: If you have any ideas for features or enhancements, you can submit them through our [feature request template](https://github.com/opentibiabr/canary/blob/main/.github/ISSUE_TEMPLATE/request.yaml). + +Please provide as much relevant information as possible, including logs, screenshots, or other details to help the team understand the problem or your request. + +### Pull Requests + +To contribute code to the project, please follow these guidelines: + +1. **Fork the Repository**: Fork the Canary repository and create your own branch to make changes. +2. **Follow the Style Guides**: The project uses **Clang Format** for C++ and **Lua Format** for Lua scripts. It is important that your code follows these styles. We use GitHub Actions (GHA) for formatting checks, so make sure to format your code properly before submitting. +3. **No Complex Lua Scripts**: Contributions involving Lua scripts should focus on simple and efficient implementations. Performance-heavy features should be implemented in C++, and contributions that introduce overly complex Lua scripts may be rejected in favor of a C++ implementation. +4. **Database Standards**: We use an advanced key/value system for data storage called "KV System." We do not accept new tables in the MySQL database. All persistent data must be integrated using the KV system, which includes a protobuf-based abstraction for performance and integration. Please refer to the [KV System README](https://github.com/opentibiabr/canary/blob/main/src/kv/README.md) for more information. +5. **PR Guidelines**: Use our [Pull Request Template](https://github.com/opentibiabr/canary/blob/main/.github/PULL_REQUEST_TEMPLATE.md) when submitting a pull request. Ensure your PR: + - Follows the project coding standards. + - Contains relevant descriptions and details about the changes. + - Respects project maintainers' decisions. Some contributions may not be merged immediately or might be rejected due to internal project priorities. +6. **Do Not Use Legacy Storage System**: Pull requests that introduce new features using the legacy storage system will not be accepted. Contributors must adopt the "KV System" to ensure compatibility with our modern approach. + +## Development Standards + +### Code Quality +- Follow modern C++20+ standards when contributing to the codebase. +- Ensure that your code is well-documented. Comments should be in English, and special attention should be given to areas that are hard to understand. + +### Formatting and Style +- **C++**: Code must be formatted with **Clang Format** according to the project's style configuration. +- **Lua**: Scripts must follow the formatting provided by **Lua Format**. + +We recommend using the provided GitHub Actions to validate the formatting before submitting any pull requests. + +## Communication + +Please use a respectful and welcoming tone when communicating with others. We aim to foster a positive and friendly community, so be mindful of others' perspectives and experiences. + +If you need to reach out to project maintainers for any assistance or inquiries, feel free to contact us at opentibiabr@outlook.com. + +## Review Process + +- Pull requests will be reviewed by the project maintainers. Please be patient, as it may take some time to get feedback. +- Contributors must be prepared for their PRs to be modified or even rejected. Reasons for this include internal priorities, a need for better performance, or violations of contribution guidelines. + +## Best Practices +- Respect the project standards and guidelines. +- Make small, focused pull requests, as it makes the review process easier. +- Write tests where possible to ensure that your changes do not introduce new issues. +- Provide clear descriptions in your commits and pull requests. +- Ensure that new features are properly integrated with existing systems. + +## Advanced Contribution +- **Complex Systems**: For features that impact performance or require deeper integrations, discuss them with the maintainers before implementation. +- **KV System Usage**: All persistent data should leverage the KV system. It allows for efficient data mapping, storing complex structures seamlessly. Learn more about the KV system [here](https://github.com/opentibiabr/canary/blob/main/src/kv/README.md). + +Thank you for your contributions and for helping make Canary better! + diff --git a/data/scripts/actions/items/mystery_box.lua b/data/scripts/actions/items/mystery_box.lua new file mode 100644 index 00000000000..6afdf3ca464 --- /dev/null +++ b/data/scripts/actions/items/mystery_box.lua @@ -0,0 +1,13 @@ +local mysteryBox = Action() + +function mysteryBox.onUse(player, item, fromPosition, target, toPosition, isHotkey) + local items = { 25361, 25360 } + local randomItem = items[math.random(#items)] + player:addItem(randomItem, 1) + player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) + item:remove(1) + return true +end + +mysteryBox:id(26186) +mysteryBox:register() diff --git a/src/account/account.cpp b/src/account/account.cpp index 22d69d8833a..93596f77b15 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -10,6 +10,7 @@ #include "account/account.hpp" #include "account/account_repository_db.hpp" +#include "account/account_info.hpp" #include "security/argon.hpp" #include "utils/tools.hpp" #include "enums/account_coins.hpp" @@ -34,113 +35,116 @@ Account::Account(std::string descriptor) : m_account->accountType = ACCOUNT_TYPE_NORMAL; } -uint8_t Account::load() { +AccountErrors_t Account::load() { + using enum AccountErrors_t; if (m_account->id != 0 && g_accountRepository().loadByID(m_account->id, m_account)) { m_accLoaded = true; - return enumToValue(AccountErrors_t::Ok); + return Ok; } if (!m_descriptor.empty() && g_accountRepository().loadByEmailOrName(getProtocolCompat(), m_descriptor, m_account)) { m_accLoaded = true; - return enumToValue(AccountErrors_t::Ok); + return Ok; } if (!m_descriptor.empty() && g_accountRepository().loadBySession(m_descriptor, m_account)) { m_accLoaded = true; - return enumToValue(AccountErrors_t::Ok); + return Ok; } updatePremiumTime(); - return enumToValue(AccountErrors_t::LoadingAccount); + return LoadingAccount; } -uint8_t Account::reload() { +AccountErrors_t Account::reload() { if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return AccountErrors_t::NotInitialized; } return load(); } -uint8_t Account::save() { +AccountErrors_t Account::save() const { + using enum AccountErrors_t; if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return NotInitialized; } - if (!g_accountRepository().save(m_account)) { - return enumToValue(AccountErrors_t::Storage); + return Storage; } - - return enumToValue(AccountErrors_t::Ok); + return Ok; } -std::tuple Account::getCoins(const uint8_t &type) const { +std::tuple Account::getCoins(CoinType type) const { + using enum AccountErrors_t; if (!m_accLoaded) { - return { 0, enumToValue(AccountErrors_t::NotInitialized) }; + return { 0, NotInitialized }; } uint32_t coins = 0; if (!g_accountRepository().getCoins(m_account->id, type, coins)) { - return { 0, enumToValue(AccountErrors_t::Storage) }; + return { 0, Storage }; } - return { coins, enumToValue(AccountErrors_t::Ok) }; + return { coins, Ok }; } -uint8_t Account::addCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail) { +AccountErrors_t Account::addCoins(CoinType type, const uint32_t &amount, const std::string &detail) { + using enum AccountErrors_t; if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return NotInitialized; } if (amount == 0) { - return enumToValue(AccountErrors_t::Ok); + return Ok; } auto [coins, result] = getCoins(type); - if (AccountErrors_t::Ok != enumFromValue(result)) { + if (Ok != result) { return result; } if (!g_accountRepository().setCoins(m_account->id, type, coins + amount)) { - return enumToValue(AccountErrors_t::Storage); + return Storage; } - registerCoinTransaction(enumToValue(CoinTransactionType::Add), type, amount, detail); + registerCoinTransaction(CoinTransactionType::Add, type, amount, detail); - return enumToValue(AccountErrors_t::Ok); + return Ok; } -uint8_t Account::removeCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail) { +AccountErrors_t Account::removeCoins(CoinType type, const uint32_t &amount, const std::string &detail) { + using enum AccountErrors_t; if (!m_accLoaded) { - return enumToValue(AccountErrors_t::NotInitialized); + return NotInitialized; } if (amount == 0) { - return enumToValue(AccountErrors_t::Ok); + return Ok; } auto [coins, result] = getCoins(type); - if (AccountErrors_t::Ok != enumFromValue(result)) { + if (Ok != result) { return result; } if (coins < amount) { g_logger().info("Account doesn't have enough coins! current[{}], remove:[{}]", coins, amount); - return enumToValue(AccountErrors_t::RemoveCoins); + return RemoveCoins; } if (!g_accountRepository().setCoins(m_account->id, type, coins - amount)) { - return enumToValue(AccountErrors_t::Storage); + return Storage; } - registerCoinTransaction(enumToValue(CoinTransactionType::Remove), type, amount, detail); + registerCoinTransaction(CoinTransactionType::Remove, type, amount, detail); - return enumToValue(AccountErrors_t::Ok); + return Ok; } -void Account::registerCoinTransaction(const uint8_t &transactionType, const uint8_t &type, const uint32_t &amount, const std::string &detail) { +void Account::registerCoinTransaction(CoinTransactionType transactionType, CoinType type, const uint32_t &amount, const std::string &detail) { if (!m_accLoaded) { return; } @@ -208,12 +212,12 @@ void Account::setPremiumDays(const int32_t &days) { return m_account->premiumDaysPurchased; } -uint8_t Account::setAccountType(const uint8_t &accountType) { +AccountErrors_t Account::setAccountType(AccountType accountType) { m_account->accountType = accountType; - return enumToValue(AccountErrors_t::Ok); + return AccountErrors_t::Ok; } -[[nodiscard]] uint8_t Account::getAccountType() const { +[[nodiscard]] AccountType Account::getAccountType() const { return m_account->accountType; } @@ -240,14 +244,15 @@ void Account::updatePremiumTime() { return; } - if (AccountErrors_t::Ok != enumFromValue(save())) { + if (AccountErrors_t::Ok != save()) { g_logger().error("Failed to update account premium time: [{}]", getDescriptor()); } } -std::tuple, uint8_t> +std::tuple, AccountErrors_t> Account::getAccountPlayers() const { - auto valueToReturn = enumToValue(m_accLoaded ? AccountErrors_t::Ok : AccountErrors_t::NotInitialized); + using enum AccountErrors_t; + auto valueToReturn = m_accLoaded ? Ok : NotInitialized; return { m_account->players, valueToReturn }; } diff --git a/src/account/account.hpp b/src/account/account.hpp index 16bc72b2de6..2c6098a8dbd 100644 --- a/src/account/account.hpp +++ b/src/account/account.hpp @@ -11,6 +11,11 @@ struct AccountInfo; +enum class CoinType : uint8_t; +enum class CoinTransactionType : uint8_t; +enum class AccountErrors_t : uint8_t; +enum AccountType : uint8_t; + class Account { public: explicit Account(const uint32_t &id); @@ -26,7 +31,7 @@ class Account { * @return uint32_t Number of coins * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - [[nodiscard]] std::tuple getCoins(const uint8_t &type) const; + [[nodiscard]] std::tuple getCoins(CoinType type) const; /** * @brief Add coins to the account. @@ -35,7 +40,7 @@ class Account { * @param amount Amount of coins to be added * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t addCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail = "ADD Coins"); + AccountErrors_t addCoins(CoinType type, const uint32_t &amount, const std::string &detail = "ADD Coins"); /** * @brief Removes coins from the account. @@ -44,7 +49,7 @@ class Account { * @param amount Amount of coins to be removed * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t removeCoins(const uint8_t &type, const uint32_t &amount, const std::string &detail = "REMOVE Coins"); + AccountErrors_t removeCoins(CoinType type, const uint32_t &amount, const std::string &detail = "REMOVE Coins"); /** * @brief Registers a coin transaction. @@ -53,7 +58,7 @@ class Account { * @param amount Amount of coins to be added * @param detail Detail of the transaction */ - void registerCoinTransaction(const uint8_t &transactionType, const uint8_t &type, const uint32_t &amount, const std::string &detail); + void registerCoinTransaction(CoinTransactionType transactionType, CoinType type, const uint32_t &amount, const std::string &detail); /*************************************************************************** * Account Load/Save @@ -64,14 +69,14 @@ class Account { * * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t save(); + AccountErrors_t save() const; /** * @brief Load Account Information. * * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t load(); + AccountErrors_t load(); /** * @brief Re-Load Account Information to get update information(mainly the @@ -79,7 +84,7 @@ class Account { * * @return AccountErrors_t AccountErrors_t::Ok(0) Success, otherwise Fail. */ - uint8_t reload(); + AccountErrors_t reload(); /*************************************************************************** * Setters and Getters @@ -107,12 +112,12 @@ class Account { [[nodiscard]] time_t getPremiumLastDay() const; - uint8_t setAccountType(const uint8_t &accountType); - [[nodiscard]] uint8_t getAccountType() const; + AccountErrors_t setAccountType(AccountType accountType); + [[nodiscard]] AccountType getAccountType() const; void updatePremiumTime(); - std::tuple, uint8_t> getAccountPlayers() const; + std::tuple, AccountErrors_t> getAccountPlayers() const; // Old protocol compat void setProtocolCompat(bool toggle); diff --git a/src/account/account_info.hpp b/src/account/account_info.hpp index 8723bcd8b71..b9dad60dbbc 100644 --- a/src/account/account_info.hpp +++ b/src/account/account_info.hpp @@ -14,13 +14,15 @@ #include #endif +#include "enums/account_type.hpp" + struct AccountInfo { ~AccountInfo() = default; uint32_t id = 0; uint32_t premiumRemainingDays = 0; time_t premiumLastDay = 0; - uint8_t accountType = 0; + AccountType accountType = ACCOUNT_TYPE_NONE; phmap::flat_hash_map players; bool oldProtocol = false; time_t sessionExpires = 0; diff --git a/src/account/account_repository.hpp b/src/account/account_repository.hpp index e6817151382..5a9cd5292c3 100644 --- a/src/account/account_repository.hpp +++ b/src/account/account_repository.hpp @@ -11,6 +11,9 @@ struct AccountInfo; +enum class CoinType : uint8_t; +enum class CoinTransactionType : uint8_t; + class AccountRepository { public: AccountRepository() = default; @@ -31,13 +34,13 @@ class AccountRepository { virtual bool getPassword(const uint32_t &id, std::string &password) = 0; - virtual bool getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) = 0; - virtual bool setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) = 0; + virtual bool getCoins(const uint32_t &id, CoinType coinType, uint32_t &coins) = 0; + virtual bool setCoins(const uint32_t &id, CoinType coinType, const uint32_t &amount) = 0; virtual bool registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) = 0; }; diff --git a/src/account/account_repository_db.cpp b/src/account/account_repository_db.cpp index 81d44e270b0..c3f02bfe972 100644 --- a/src/account/account_repository_db.cpp +++ b/src/account/account_repository_db.cpp @@ -14,8 +14,13 @@ #include "utils/definitions.hpp" #include "utils/tools.hpp" -AccountRepositoryDB::AccountRepositoryDB() : - coinTypeToColumn({ { enumToValue(CoinType::Normal), "coins" }, { enumToValue(CoinType::Tournament), "tournament_coins" }, { enumToValue(CoinType::Transferable), "coins_transferable" } }) { } +AccountRepositoryDB::AccountRepositoryDB() { + coinTypeToColumn = { + { CoinType::Normal, "coins" }, + { CoinType::Tournament, "coins_tournament" }, + { CoinType::Transferable, "coins_transferable" } + }; +} bool AccountRepositoryDB::loadByID(const uint32_t &id, std::unique_ptr &acc) { auto query = fmt::format("SELECT `id`, `type`, `premdays`, `lastday`, `creation`, `premdays_purchased`, 0 AS `expires` FROM `accounts` WHERE `id` = {}", id); @@ -80,15 +85,18 @@ bool AccountRepositoryDB::getPassword(const uint32_t &id, std::string &password) return true; }; -bool AccountRepositoryDB::getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) { - if (coinTypeToColumn.find(type) == coinTypeToColumn.end()) { - g_logger().error("[{}]: invalid coin type:[{}]", __FUNCTION__, type); +bool AccountRepositoryDB::getCoins(const uint32_t &id, CoinType coinType, uint32_t &coins) { + auto it = coinTypeToColumn.find(coinType); + if (it == coinTypeToColumn.end()) { + g_logger().error("[{}] invalid coin type:[{}]", __FUNCTION__, coinType); return false; } - auto result = g_database().storeQuery(fmt::format( + auto column = it->second; + + const auto result = g_database().storeQuery(fmt::format( "SELECT `{}` FROM `accounts` WHERE `id` = {}", - coinTypeToColumn.at(type), + column, id )); @@ -96,20 +104,23 @@ bool AccountRepositoryDB::getCoins(const uint32_t &id, const uint8_t &type, uint return false; } - coins = result->getNumber(coinTypeToColumn.at(type)); + coins = result->getNumber(column); return true; }; -bool AccountRepositoryDB::setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) { - if (coinTypeToColumn.find(type) == coinTypeToColumn.end()) { - g_logger().error("[{}]: invalid coin type:[{}]", __FUNCTION__, type); +bool AccountRepositoryDB::setCoins(const uint32_t &id, CoinType coinType, const uint32_t &amount) { + auto it = coinTypeToColumn.find(coinType); + if (it == coinTypeToColumn.end()) { + g_logger().error("[{}]: invalid coin type:[{}]", __FUNCTION__, coinType); return false; } - bool successful = g_database().executeQuery(fmt::format( + auto column = it->second; + + const bool successful = g_database().executeQuery(fmt::format( "UPDATE `accounts` SET `{}` = {} WHERE `id` = {}", - coinTypeToColumn.at(type), + column, amount, id )); @@ -123,9 +134,9 @@ bool AccountRepositoryDB::setCoins(const uint32_t &id, const uint8_t &type, cons bool AccountRepositoryDB::registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) { bool successful = g_database().executeQuery( @@ -153,7 +164,7 @@ bool AccountRepositoryDB::registerCoinsTransaction( return successful; }; -bool AccountRepositoryDB::loadAccountPlayers(std::unique_ptr &acc) { +bool AccountRepositoryDB::loadAccountPlayers(std::unique_ptr &acc) const { auto result = g_database().storeQuery( fmt::format("SELECT `name`, `deletion` FROM `players` WHERE `account_id` = {} ORDER BY `name` ASC", acc->id) ); @@ -182,7 +193,7 @@ bool AccountRepositoryDB::load(const std::string &query, std::unique_ptrid = result->getNumber("id"); - acc->accountType = result->getNumber("type"); + acc->accountType = result->getNumber("type"); acc->premiumLastDay = result->getNumber("lastday"); acc->sessionExpires = result->getNumber("expires"); acc->premiumDaysPurchased = result->getNumber("premdays_purchased"); diff --git a/src/account/account_repository_db.hpp b/src/account/account_repository_db.hpp index 014d5af1c68..e7a11c15e51 100644 --- a/src/account/account_repository_db.hpp +++ b/src/account/account_repository_db.hpp @@ -11,6 +11,9 @@ #include "account/account_repository.hpp" +enum class CoinType : uint8_t; +enum class CoinTransactionType : uint8_t; + class AccountRepositoryDB final : public AccountRepository { public: AccountRepositoryDB(); @@ -24,19 +27,20 @@ class AccountRepositoryDB final : public AccountRepository { bool getPassword(const uint32_t &id, std::string &password) override; - bool getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) override; - bool setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) override; + bool getCoins(const uint32_t &id, CoinType coinType, uint32_t &coins) override; + bool setCoins(const uint32_t &id, CoinType coinType, const uint32_t &amount) override; bool registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) override; private: - const std::map coinTypeToColumn; + std::unordered_map coinTypeToColumn {}; + bool load(const std::string &query, std::unique_ptr &acc); - bool loadAccountPlayers(std::unique_ptr &acc); + bool loadAccountPlayers(std::unique_ptr &acc) const; void setupLoyaltyInfo(std::unique_ptr &acc); }; diff --git a/src/creatures/players/cyclopedia/player_badge.cpp b/src/creatures/players/cyclopedia/player_badge.cpp index 6ed7451b1c3..0d97747a248 100644 --- a/src/creatures/players/cyclopedia/player_badge.cpp +++ b/src/creatures/players/cyclopedia/player_badge.cpp @@ -118,7 +118,7 @@ bool PlayerBadge::loyalty(uint8_t amount) const { std::vector> PlayerBadge::getPlayersInfoByAccount(const std::shared_ptr &acc) const { const auto [accountPlayers, error] = acc->getAccountPlayers(); - if (error != enumToValue(AccountErrors_t::Ok) || accountPlayers.empty()) { + if (error != AccountErrors_t::Ok || accountPlayers.empty()) { return {}; } diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index aaf0954a7ba..5b9b597e5de 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -10070,7 +10070,7 @@ bool Player::setAccount(uint32_t accountId) { } account = std::make_shared(accountId); - return AccountErrors_t::Ok == enumFromValue(account->load()); + return AccountErrors_t::Ok == account->load(); } uint8_t Player::getAccountType() const { diff --git a/src/database/database.hpp b/src/database/database.hpp index 97c12f3de47..69c47d324ad 100644 --- a/src/database/database.hpp +++ b/src/database/database.hpp @@ -95,8 +95,19 @@ class DBResult { return T(); } - T data = 0; + T data {}; try { + // Check if the type T is a enum + if constexpr (std::is_enum_v) { + using underlying_type = std::underlying_type_t; + underlying_type value = 0; + if constexpr (std::is_signed_v) { + value = static_cast(std::stoll(row[it->second])); + } else { + value = static_cast(std::stoull(row[it->second])); + } + return static_cast(value); + } // Check if the type T is signed or unsigned if constexpr (std::is_signed_v) { // Check if the type T is int8_t or int16_t diff --git a/src/enums/account_type.hpp b/src/enums/account_type.hpp index df76c4a289f..4929a32cfbf 100644 --- a/src/enums/account_type.hpp +++ b/src/enums/account_type.hpp @@ -14,6 +14,7 @@ #endif enum AccountType : uint8_t { + ACCOUNT_TYPE_NONE = 0, ACCOUNT_TYPE_NORMAL = 1, ACCOUNT_TYPE_TUTOR = 2, ACCOUNT_TYPE_SENIORTUTOR = 3, diff --git a/src/game/game.cpp b/src/game/game.cpp index bb68947214b..6c67ca3ef28 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1118,7 +1118,7 @@ ReturnValue Game::getPlayerByNameWildcard(const std::string &s, std::shared_ptr< std::vector> Game::getPlayersByAccount(const std::shared_ptr &acc, bool allowOffline /* = false */) { auto [accountPlayers, error] = acc->getAccountPlayers(); - if (error != enumToValue(AccountErrors_t::Ok)) { + if (error != AccountErrors_t::Ok) { return {}; } std::vector> ret; @@ -4124,7 +4124,7 @@ void Game::playerMoveUpContainer(uint32_t playerId, uint8_t cid) { auto it = browseFields.find(tile); if (it == browseFields.end() || it->second.expired()) { - parentContainer = Container::create(tile); + parentContainer = Container::createBrowseField(tile); browseFields[tile] = parentContainer; } else { parentContainer = it->second.lock(); @@ -4689,7 +4689,7 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) { auto it = browseFields.find(tile); if (it == browseFields.end() || it->second.expired()) { - container = Container::create(tile); + container = Container::createBrowseField(tile); browseFields[tile] = container; } else { container = it->second.lock(); @@ -9011,7 +9011,7 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t ite } if (it.id == ITEM_STORE_COIN) { - auto [transferableCoins, result] = player->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + auto [transferableCoins, result] = player->getAccount()->getCoins(CoinType::Transferable); if (amount > transferableCoins) { offerStatus << "Amount is greater than coins for player " << player->getName(); @@ -9019,7 +9019,7 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t ite } // Do not register a transaction for coins creating an offer - player->getAccount()->removeCoins(enumToValue(CoinType::Transferable), static_cast(amount), ""); + player->getAccount()->removeCoins(CoinType::Transferable, static_cast(amount), ""); } else { if (!removeOfferItems(player, depotLocker, it, amount, tier, offerStatus)) { g_logger().error("[{}] failed to remove item with id {}, from player {}, errorcode: {}", __FUNCTION__, it.id, player->getName(), offerStatus.str()); @@ -9100,7 +9100,7 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 if (it.id == ITEM_STORE_COIN) { // Do not register a transaction for coins upon cancellation - player->getAccount()->addCoins(enumToValue(CoinType::Transferable), offer.amount, ""); + player->getAccount()->addCoins(CoinType::Transferable, offer.amount, ""); } else if (it.stackable) { uint16_t tmpAmount = offer.amount; while (tmpAmount > 0) { @@ -9212,9 +9212,9 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 } if (it.id == ITEM_STORE_COIN) { - auto [transferableCoins, error] = player->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + auto [transferableCoins, error] = player->getAccount()->getCoins(CoinType::Transferable); - if (error != enumToValue(AccountErrors_t::Ok)) { + if (error != AccountErrors_t::Ok) { offerStatus << "Failed to load transferable coins for player " << player->getName(); return; } @@ -9225,7 +9225,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 } player->getAccount()->removeCoins( - enumToValue(CoinType::Transferable), + CoinType::Transferable, amount, "Sold on Market" ); @@ -9253,7 +9253,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 g_metrics().addCounter("balance_increase", totalPrice, { { "player", player->getName() }, { "context", "market_sale" } }); if (it.id == ITEM_STORE_COIN) { - buyerPlayer->getAccount()->addCoins(enumToValue(CoinType::Transferable), amount, "Purchased on Market"); + buyerPlayer->getAccount()->addCoins(CoinType::Transferable, amount, "Purchased on Market"); } else if (it.stackable) { uint16_t tmpAmount = amount; while (tmpAmount > 0) { @@ -9324,7 +9324,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 g_metrics().addCounter("balance_decrease", totalPrice, { { "player", player->getName() }, { "context", "market_purchase" } }); if (it.id == ITEM_STORE_COIN) { - player->getAccount()->addCoins(enumToValue(CoinType::Transferable), amount, "Purchased on Market"); + player->getAccount()->addCoins(CoinType::Transferable, amount, "Purchased on Market"); } else if (it.stackable) { uint16_t tmpAmount = amount; while (tmpAmount > 0) { @@ -9378,7 +9378,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16 sellerPlayer->setBankBalance(sellerPlayer->getBankBalance() + totalPrice); g_metrics().addCounter("balance_increase", totalPrice, { { "player", sellerPlayer->getName() }, { "context", "market_sale" } }); if (it.id == ITEM_STORE_COIN) { - sellerPlayer->getAccount()->registerCoinTransaction(enumToValue(CoinTransactionType::Remove), enumToValue(CoinType::Transferable), amount, "Sold on Market"); + sellerPlayer->getAccount()->registerCoinTransaction(CoinTransactionType::Remove, CoinType::Transferable, amount, "Sold on Market"); } if (it.id != ITEM_STORE_COIN) { diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index f7efef90de4..02f58bec04b 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -92,16 +92,16 @@ bool IOLoginDataLoad::preLoadPlayer(const std::shared_ptr &player, const return false; } - auto [coins, error] = player->account->getCoins(enumToValue(CoinType::Normal)); - if (error != enumToValue(AccountErrors_t::Ok)) { + auto [coins, error] = player->account->getCoins(CoinType::Normal); + if (error != AccountErrors_t::Ok) { g_logger().error("Failed to get coins for player {}, error {}", player->name, static_cast(error)); return false; } player->coinBalance = coins; - auto [transferableCoins, errorT] = player->account->getCoins(enumToValue(CoinType::Transferable)); - if (errorT != enumToValue(AccountErrors_t::Ok)) { + auto [transferableCoins, errorT] = player->account->getCoins(CoinType::Transferable); + if (errorT != AccountErrors_t::Ok) { g_logger().error("Failed to get transferable coins for player {}, error {}", player->name, static_cast(errorT)); return false; } diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index 83116537b34..0249d70a517 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -23,7 +23,7 @@ bool IOLoginData::gameWorldAuthentication(const std::string &accountDescriptor, Account account(accountDescriptor); account.setProtocolCompat(oldProtocol); - if (AccountErrors_t::Ok != enumFromValue(account.load())) { + if (AccountErrors_t::Ok != account.load()) { g_logger().error("Couldn't load account [{}].", account.getDescriptor()); return false; } @@ -43,13 +43,13 @@ bool IOLoginData::gameWorldAuthentication(const std::string &accountDescriptor, return false; } - if (AccountErrors_t::Ok != enumFromValue(account.load())) { + if (AccountErrors_t::Ok != account.load()) { g_logger().error("Failed to load account [{}]", accountDescriptor); return false; } auto [players, result] = account.getAccountPlayers(); - if (AccountErrors_t::Ok != enumFromValue(result)) { + if (AccountErrors_t::Ok != result) { g_logger().error("Failed to load account [{}] players", accountDescriptor); return false; } diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index e19de0da183..70ad1cbabbf 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -44,20 +44,36 @@ std::shared_ptr Container::create(uint16_t type, uint16_t size, bool return std::make_shared(type, size, unlocked, pagination); } -std::shared_ptr Container::create(const std::shared_ptr &tile) { - auto container = std::make_shared(ITEM_BROWSEFIELD, 30, false, true); +std::shared_ptr Container::createBrowseField(const std::shared_ptr &tile) { + const auto &newContainer = create(ITEM_BROWSEFIELD, 30, false, true); + if (!newContainer || !tile) { + return nullptr; + } + const TileItemVector* itemVector = tile->getItemList(); if (itemVector) { for (const auto &item : *itemVector) { - if (((item->getContainer() || item->hasProperty(CONST_PROP_MOVABLE)) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH))) && !item->hasAttribute(ItemAttribute_t::UNIQUEID)) { - container->itemlist.push_front(item); - item->setParent(container); + if (!item) { + continue; } + + // Checks if the item has an internal container, is movable, or is packable without blocking the path. + bool isItemValid = item->getContainer() || item->hasProperty(CONST_PROP_MOVABLE) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH)); + + // If the item has a unique ID or is not valid, skip to the next item. + if (item->hasAttribute(ItemAttribute_t::UNIQUEID) || !isItemValid) { + continue; + } + + // Add the item to the new container and set its parent. + newContainer->itemlist.push_front(item); + item->setParent(newContainer); } } - container->setParent(tile); - return container; + // Set the parent of the new container to be the tile. + newContainer->setParent(tile); + return newContainer; } Container::~Container() { diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index b9840a0b0b5..f7e1b5c42a3 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -138,7 +138,21 @@ class Container : public Item, public Cylinder { static std::shared_ptr create(uint16_t type); static std::shared_ptr create(uint16_t type, uint16_t size, bool unlocked = true, bool pagination = false); - static std::shared_ptr create(const std::shared_ptr &type); + + /** + * @brief Creates a container for browse field functionality with items from a specified tile. + * + * This function generates a new container specifically for browse field use, + * populating it with items that meet certain criteria from the provided tile. Items + * that can be included must either have an internal container, be movable, or be + * wrapable without blocking path and without a unique ID. + * + * @param tile A shared pointer to the Tile from which items will be sourced. + * @return std::shared_ptr Returns a shared pointer to the newly created Container if successful; otherwise, returns nullptr. + * + * @note This function will return nullptr if the newContainer could not be created or if the tile pointer is null. + */ + static std::shared_ptr createBrowseField(const std::shared_ptr &type); // non-copyable Container(const Container &) = delete; diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index 6468ec431e2..89a3093106a 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -667,12 +667,12 @@ int PlayerFunctions::luaPlayerSetAccountType(lua_State* L) { return 1; } - if (player->getAccount()->setAccountType(Lua::getNumber(L, 2)) != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->setAccountType(Lua::getNumber(L, 2)) != AccountErrors_t::Ok) { lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { lua_pushnil(L); return 1; } @@ -2898,7 +2898,7 @@ int PlayerFunctions::luaPlayerAddPremiumDays(lua_State* L) { player->getAccount()->addPremiumDays(addDays); - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { return 1; } @@ -2927,7 +2927,7 @@ int PlayerFunctions::luaPlayerRemovePremiumDays(lua_State* L) { player->getAccount()->addPremiumDays(-removeDays); - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { return 1; } @@ -2944,9 +2944,9 @@ int PlayerFunctions::luaPlayerGetTibiaCoins(lua_State* L) { return 1; } - auto [coins, result] = player->getAccount()->getCoins(enumToValue(CoinType::Normal)); + auto [coins, result] = player->getAccount()->getCoins(CoinType::Normal); - if (result == enumToValue(AccountErrors_t::Ok)) { + if (result == AccountErrors_t::Ok) { lua_pushnumber(L, coins); } @@ -2962,13 +2962,13 @@ int PlayerFunctions::luaPlayerAddTibiaCoins(lua_State* L) { return 1; } - if (player->account->addCoins(enumToValue(CoinType::Normal), Lua::getNumber(L, 2)) != enumToValue(AccountErrors_t::Ok)) { + if (player->account->addCoins(CoinType::Normal, Lua::getNumber(L, 2)) != AccountErrors_t::Ok) { Lua::reportErrorFunc("Failed to add coins"); lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { Lua::reportErrorFunc("Failed to save account"); lua_pushnil(L); return 1; @@ -2988,12 +2988,12 @@ int PlayerFunctions::luaPlayerRemoveTibiaCoins(lua_State* L) { return 1; } - if (player->account->removeCoins(enumToValue(CoinType::Normal), Lua::getNumber(L, 2)) != enumToValue(AccountErrors_t::Ok)) { + if (player->account->removeCoins(CoinType::Normal, Lua::getNumber(L, 2)) != AccountErrors_t::Ok) { Lua::reportErrorFunc("Failed to remove coins"); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { Lua::reportErrorFunc("Failed to save account"); lua_pushnil(L); return 1; @@ -3013,9 +3013,9 @@ int PlayerFunctions::luaPlayerGetTransferableCoins(lua_State* L) { return 1; } - auto [coins, result] = player->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + auto [coins, result] = player->getAccount()->getCoins(CoinType::Transferable); - if (result == enumToValue(AccountErrors_t::Ok)) { + if (result == AccountErrors_t::Ok) { lua_pushnumber(L, coins); } @@ -3031,13 +3031,13 @@ int PlayerFunctions::luaPlayerAddTransferableCoins(lua_State* L) { return 1; } - if (player->account->addCoins(enumToValue(CoinType::Transferable), Lua::getNumber(L, 2)) != enumToValue(AccountErrors_t::Ok)) { + if (player->account->addCoins(CoinType::Transferable, Lua::getNumber(L, 2)) != AccountErrors_t::Ok) { Lua::reportErrorFunc("failed to add transferable coins"); lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { Lua::reportErrorFunc("failed to save account"); lua_pushnil(L); return 1; @@ -3057,13 +3057,13 @@ int PlayerFunctions::luaPlayerRemoveTransferableCoins(lua_State* L) { return 1; } - if (player->account->removeCoins(enumToValue(CoinType::Transferable), Lua::getNumber(L, 2)) != enumToValue(AccountErrors_t::Ok)) { + if (player->account->removeCoins(CoinType::Transferable, Lua::getNumber(L, 2)) != AccountErrors_t::Ok) { Lua::reportErrorFunc("failed to remove transferable coins"); lua_pushnil(L); return 1; } - if (player->getAccount()->save() != enumToValue(AccountErrors_t::Ok)) { + if (player->getAccount()->save() != AccountErrors_t::Ok) { Lua::reportErrorFunc("failed to save account"); lua_pushnil(L); return 1; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 5f6bea22164..196e10c3497 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -4616,7 +4616,7 @@ void ProtocolGame::sendUnjustifiedPoints(const uint8_t &dayProgress, const uint8 } void ProtocolGame::sendContainer(uint8_t cid, const std::shared_ptr &container, bool hasParent, uint16_t firstIndex) { - if (!player) { + if (!player || !container) { return; } @@ -5037,8 +5037,8 @@ void ProtocolGame::updateCoinBalance() { [playerId = player->getID()] { const auto &threadPlayer = g_game().getPlayerByID(playerId); if (threadPlayer && threadPlayer->getAccount()) { - const auto [coins, errCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Normal)); - const auto [transferCoins, errTCoin] = threadPlayer->getAccount()->getCoins(enumToValue(CoinType::Transferable)); + const auto [coins, errCoin] = threadPlayer->getAccount()->getCoins(CoinType::Normal); + const auto [transferCoins, errTCoin] = threadPlayer->getAccount()->getCoins(CoinType::Transferable); threadPlayer->coinBalance = coins; threadPlayer->coinTransferableBalance = transferCoins; diff --git a/src/server/network/protocol/protocollogin.cpp b/src/server/network/protocol/protocollogin.cpp index d1768e68e58..9e28982e91f 100644 --- a/src/server/network/protocol/protocollogin.cpp +++ b/src/server/network/protocol/protocollogin.cpp @@ -41,7 +41,7 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const return; } - if (account.load() != enumToValue(AccountErrors_t::Ok) || !account.authenticate(password)) { + if (account.load() != AccountErrors_t::Ok || !account.authenticate(password)) { std::ostringstream ss; ss << (oldProtocol ? "Username" : "Email") << " or password is not correct."; disconnectClient(ss.str()); @@ -66,7 +66,7 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const // Add char list auto [players, result] = account.getAccountPlayers(); - if (enumToValue(AccountErrors_t::Ok) != result) { + if (AccountErrors_t::Ok != result) { g_logger().warn("Account[{}] failed to load players!", account.getID()); } diff --git a/tests/fixture/account/in_memory_account_repository.hpp b/tests/fixture/account/in_memory_account_repository.hpp index 3c4f5e3f061..d86d6a483be 100644 --- a/tests/fixture/account/in_memory_account_repository.hpp +++ b/tests/fixture/account/in_memory_account_repository.hpp @@ -75,7 +75,7 @@ namespace tests { return !failGetPassword; } - bool getCoins(const uint32_t &id, const uint8_t &type, uint32_t &coins) final { + bool getCoins(const uint32_t &id, CoinType type, uint32_t &coins) final { auto accountCoins = coins_.find(id); if (accountCoins == coins_.end()) { @@ -92,11 +92,11 @@ namespace tests { return true; } - bool setCoins(const uint32_t &id, const uint8_t &type, const uint32_t &amount) final { + bool setCoins(const uint32_t &id, CoinType type, const uint32_t &amount) final { auto accountCoins = coins_.find(id); if (accountCoins == coins_.end()) { - coins_[id] = phmap::flat_hash_map(); + coins_[id] = phmap::flat_hash_map(); } coins_[id][type] = amount; @@ -105,15 +105,15 @@ namespace tests { bool registerCoinsTransaction( const uint32_t &id, - uint8_t type, + CoinTransactionType type, uint32_t coins, - const uint8_t &coinType, + CoinType coinType, const std::string &description ) final { auto accountCoins = coinsTransactions_.find(id); if (accountCoins == coinsTransactions_.end()) { - coinsTransactions_[id] = std::vector>(); + coinsTransactions_[id] = std::vector>(); } coinsTransactions_[id].emplace_back(type, coins, coinType, description); @@ -150,8 +150,8 @@ namespace tests { bool failAuthenticateFromSession = false; std::string password_ = "123456"; phmap::flat_hash_map accounts; - phmap::flat_hash_map> coins_; - phmap::flat_hash_map>> coinsTransactions_; + phmap::flat_hash_map> coins_; + phmap::flat_hash_map>> coinsTransactions_; }; } diff --git a/tests/unit/account/account_test.cpp b/tests/unit/account/account_test.cpp index db3b84a3674..5ff6322769d 100644 --- a/tests/unit/account/account_test.cpp +++ b/tests/unit/account/account_test.cpp @@ -22,6 +22,19 @@ using namespace boost::ut; using namespace std; +template +bool eqEnum(const T& lhs, const U& rhs) { + if constexpr (std::is_enum_v && std::is_enum_v) { + return enumToValue(lhs) == enumToValue(rhs); + } else if constexpr (std::is_enum_v) { + return enumToValue(lhs) == rhs; + } else if constexpr (std::is_enum_v) { + return lhs == enumToValue(rhs); + } else { + return lhs == rhs; + } +} + suite<"account"> accountTest = [] { InjectionFixture injectionFixture{}; @@ -36,11 +49,9 @@ suite<"account"> accountTest = [] { expect(eq(byDescriptor->getDescriptor(), string{"canary@test.com"})); for (auto& account : { byId, byDescriptor }) { - expect( - eq(account->getPremiumRemainingDays(), 0) and - eq(account->getPremiumLastDay(), 0) and - eq(account->getAccountType(), AccountType::ACCOUNT_TYPE_NORMAL) - ); + expect(eq(account->getPremiumRemainingDays(), 0)); + expect(eq(account->getPremiumLastDay(), 0)); + expect(eqEnum(account->getAccountType(), AccountType::ACCOUNT_TYPE_NORMAL)); } }; @@ -61,12 +72,12 @@ suite<"account"> accountTest = [] { test(testCase.description) = [&injectionFixture, &testCase] { auto [accountRepository] = injectionFixture.get(); accountRepository.addAccount("canary@test.com", AccountInfo{1, 1, 1, AccountType::ACCOUNT_TYPE_GOD}); - expect(eq(testCase.account->load(), enumToValue(testCase.expectedError))) << testCase.description; + expect(eqEnum(testCase.account->load(), testCase.expectedError)) << testCase.description; }; } test("Account::reload returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.reload(), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.reload(), AccountErrors_t::NotInitialized)); }; test("Account::reload reloads account info") = [&injectionFixture] { @@ -75,21 +86,17 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GOD) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GOD)); accountRepository.addAccount("canary2@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GAMEMASTER }); - expect( - eq(acc.reload(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER) - ); + expect(eqEnum(acc.reload(), AccountErrors_t::Ok)); + expect(eqEnum(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER)); }; test("Account::save returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.save(), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.save(), AccountErrors_t::NotInitialized)); }; test("Account::save returns error if it fails") = [&injectionFixture] { @@ -99,7 +106,8 @@ suite<"account"> accountTest = [] { accountRepository.failSave = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(acc.load(), enumToValue(AccountErrors_t::Ok) and eq(acc.save(), enumToValue(AccountErrors_t::Storage)))); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.save(), AccountErrors_t::Storage)); }; test("Account::save saves account info") = [&injectionFixture] { @@ -109,11 +117,12 @@ suite<"account"> accountTest = [] { accountRepository.failSave = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(acc.load(), enumToValue(AccountErrors_t::Ok) and eq(acc.save(), enumToValue(AccountErrors_t::Ok)))); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.save(), AccountErrors_t::Ok)); }; test("Account::getCoins returns error if not yet loaded") = [&injectionFixture] { - expect(eq(std::get<1>(Account { 1 }.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(std::get<1>(Account { 1 }.getCoins(CoinType::Normal)), AccountErrors_t::NotInitialized)); }; test("Account::getCoins returns error if it fails") = [&injectionFixture] { @@ -122,10 +131,8 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Storage)); }; test("Account::getCoins returns coins") = [&injectionFixture] { @@ -133,13 +140,11 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 100) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 100)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::getCoins returns coins for specified account only") = [&injectionFixture] { @@ -147,16 +152,14 @@ suite<"account"> accountTest = [] { Account acc { 2 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); accountRepository.addAccount("canary2@test.com", AccountInfo { 2, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(2, enumToValue(CoinType::Normal), 33); + accountRepository.setCoins(2, CoinType::Normal, 33); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 33) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 33)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::getCoins returns coins for specified coin type only") = [&injectionFixture] { @@ -164,20 +167,18 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - accountRepository.setCoins(1, enumToValue(CoinType::Tournament), 100); - - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 100) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Tournament))), 100) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Tournament))), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + accountRepository.setCoins(1, CoinType::Tournament, 100); + + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 100)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Tournament)), 100)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Tournament)), AccountErrors_t::Ok)); }; test("Account::addCoins returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.addCoins(CoinType::Normal, 100), AccountErrors_t::NotInitialized)); }; test("Account::addCoins returns error if it fails") = [&injectionFixture] { @@ -186,12 +187,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Storage)); }; test("Account::addCoins returns error if get coins fail") = [&injectionFixture] { @@ -199,12 +198,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Tournament), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Tournament, 100), AccountErrors_t::Storage)); }; test("Account::addCoins adds coins") = [&injectionFixture] { @@ -213,14 +210,12 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) - and eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 200) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 200)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::addCoins adds coins for specified account only") = [&injectionFixture] { @@ -229,17 +224,15 @@ suite<"account"> accountTest = [] { Account acc { 2 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); accountRepository.addAccount("canary2@test.com", AccountInfo { 2, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(2, enumToValue(CoinType::Normal), 33); + accountRepository.setCoins(2, CoinType::Normal, 33); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 133) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 133)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::addCoins adds coins for specified coin type only") = [&injectionFixture] { @@ -247,33 +240,29 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - accountRepository.setCoins(1, enumToValue(CoinType::Tournament), 57); + accountRepository.setCoins(1, CoinType::Normal, 100); + accountRepository.setCoins(1, CoinType::Tournament, 57); accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.addCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 200) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Tournament))), 57) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Tournament))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 200)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Tournament)), 57)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Tournament)), AccountErrors_t::Ok)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); auto [type, coins, coinType, description] = accountRepository.coinsTransactions_[1][0]; - expect( - eq(coins, 100) and - eq(coinType, enumToValue(CoinType::Normal)) and - eq(type, enumToValue(CoinTransactionType::Add)) and - eq(description, std::string { "ADD Coins" }) - ); + expect(eq(coins, 100)); + expect(eqEnum(coinType, CoinType::Normal)); + expect(eqEnum(type, CoinTransactionType::Add)); + expect(eq(description, std::string { "ADD Coins" })); }; test("Account::removeCoins returns error if not yet loaded") = [] { - expect(eq(Account { 1 }.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(Account { 1 }.removeCoins(CoinType::Normal, 100), AccountErrors_t::NotInitialized)); }; test("Account::removeCoins returns error if it fails") = [&injectionFixture] { @@ -282,12 +271,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Storage)); }; test("Account::removeCoins returns error if get coins fail") = [&injectionFixture] { @@ -295,12 +282,10 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Tournament), 100), enumToValue(AccountErrors_t::Storage)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Tournament, 100), AccountErrors_t::Storage)); }; test("Account::removeCoins removes coins") = [&injectionFixture] { @@ -309,14 +294,12 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 0) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 0)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::removeCoins removes coins for specified account only") = [&injectionFixture] { @@ -325,17 +308,15 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); + accountRepository.setCoins(1, CoinType::Normal, 100); accountRepository.addAccount("canary2@test.com", AccountInfo { 2, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(2, enumToValue(CoinType::Normal), 33); + accountRepository.setCoins(2, CoinType::Normal, 33); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 0) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 0)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); }; test("Account::removeCoins removes coins for specified coin type only") = [&injectionFixture] { @@ -344,28 +325,24 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - accountRepository.setCoins(1, enumToValue(CoinType::Tournament), 57); - - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 0) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok)) and - eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Tournament))), 57) and - eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Tournament))), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + accountRepository.setCoins(1, CoinType::Tournament, 57); + + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 0)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Tournament)), 57)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Tournament)), AccountErrors_t::Ok)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); auto [type, coins, coinType, description] = accountRepository.coinsTransactions_[1][0]; - expect( - eq(coins, 100) and - eq(coinType, enumToValue(CoinType::Normal)) and - eq(type, enumToValue(CoinTransactionType::Remove)) and - eq(description, std::string { "REMOVE Coins" }) - ); + expect(eq(coins, 100)); + expect(eqEnum(coinType, CoinType::Normal)); + expect(eqEnum(type, CoinTransactionType::Remove)); + expect(eq(description, std::string { "REMOVE Coins" })); }; test("Account::removeCoins returns error if account doesn't have enough coins") = [&injectionFixture] { @@ -373,38 +350,30 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.failAddCoins = false; - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 1); + accountRepository.setCoins(1, CoinType::Normal, 1); accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::RemoveCoins)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::RemoveCoins)); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 50); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::RemoveCoins)) - ); + accountRepository.setCoins(1, CoinType::Normal, 50); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::RemoveCoins)); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 100); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::Ok)) - ); + accountRepository.setCoins(1, CoinType::Normal, 100); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::Ok)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); auto [type, coins, coinType, description] = accountRepository.coinsTransactions_[1][0]; - expect( - eq(coins, 100) and - eq(coinType,enumToValue(CoinType::Normal)) and - eq(type, enumToValue(CoinTransactionType::Remove)) and - eq(description, std::string { "REMOVE Coins" }) - ); + expect(eq(coins, 100)); + expect(eqEnum(coinType,CoinType::Normal)); + expect(eqEnum(type, CoinTransactionType::Remove)); + expect(eq(description, std::string { "REMOVE Coins" })); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and eq(acc.removeCoins(enumToValue(CoinType::Normal), 100), enumToValue(AccountErrors_t::RemoveCoins)) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 100), AccountErrors_t::RemoveCoins)); expect(eq(accountRepository.coinsTransactions_.size(), 1) >> fatal); expect(eq(accountRepository.coinsTransactions_[1].size(), 1) >> fatal); @@ -415,23 +384,23 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect(eq(acc.load(), enumToValue(AccountErrors_t::Ok))); - accountRepository.setCoins(1, enumToValue(CoinType::Normal), 1); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + accountRepository.setCoins(1, CoinType::Normal, 1); - expect(eq(acc.addCoins(enumToValue(CoinType::Normal), 100, ""), enumToValue(AccountErrors_t::Ok))); - expect(eq(acc.removeCoins(enumToValue(CoinType::Normal), 80, ""), enumToValue(AccountErrors_t::Ok))); + expect(eqEnum(acc.addCoins(CoinType::Normal, 100, ""), AccountErrors_t::Ok)); + expect(eqEnum(acc.removeCoins(CoinType::Normal, 80, ""), AccountErrors_t::Ok)); - expect(eq(std::get<0>(acc.getCoins(enumToValue(CoinType::Normal))), 21)); - expect(eq(std::get<1>(acc.getCoins(enumToValue(CoinType::Normal))), enumToValue(AccountErrors_t::Ok))); + expect(eqEnum(std::get<0>(acc.getCoins(CoinType::Normal)), 21)); + expect(eqEnum(std::get<1>(acc.getCoins(CoinType::Normal)), AccountErrors_t::Ok)); - acc.registerCoinTransaction(enumToValue(CoinTransactionType::Add), enumToValue(CoinType::Normal), 100, ""); - acc.registerCoinTransaction(enumToValue(CoinTransactionType::Remove), enumToValue(CoinType::Normal), 100, ""); + acc.registerCoinTransaction(CoinTransactionType::Add, CoinType::Normal, 100, ""); + acc.registerCoinTransaction(CoinTransactionType::Remove, CoinType::Normal, 100, ""); expect(eq(accountRepository.coinsTransactions_.size(), 0)); }; test("Account::getPassword returns empty string if not yet loaded") = [] { - expect(eq(Account { 1 }.getPassword(), std::string { "" })); + expect(eqEnum(Account { 1 }.getPassword(), std::string { "" })); }; test("Account::getPassword returns password") = [&injectionFixture] { @@ -440,10 +409,8 @@ suite<"account"> accountTest = [] { Account acc { 1 }; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getPassword(), std::string { "123456" }) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eq(acc.getPassword(), std::string { "123456" })); }; test("Account::getPassword returns logs error if it fails") = [&injectionFixture] { @@ -453,12 +420,10 @@ suite<"account"> accountTest = [] { accountRepository.failGetPassword = true; accountRepository.addAccount("canary@test.com", AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD }); - expect( - eq(acc.load(), enumToValue(AccountErrors_t::Ok)) and - eq(std::string{}, acc.getPassword()) and - eq(std::string{"error"}, logger.logs[0].level) and - eq(std::string{"Failed to get password for account[1]!"}, logger.logs[0].message) - ); + expect(eqEnum(acc.load(), AccountErrors_t::Ok)); + expect(eq(std::string{}, acc.getPassword())); + expect(eq(std::string{"error"}, logger.logs[0].level)); + expect(eq(std::string{"Failed to get password for account[1]!"}, logger.logs[0].message)); }; test("Account::addPremiumDays sets premium remaining days") = [] { @@ -474,10 +439,8 @@ suite<"account"> accountTest = [] { acc.setPremiumDays(50); acc.addPremiumDays(50); - expect( - approx(acc.getPremiumLastDay(), getTimeNow() + (100 * 86400), 60 * 60 * 1000) and - eq(acc.getPremiumRemainingDays(), 100) - ); + expect(approx(acc.getPremiumLastDay(), getTimeNow() + (100 * 86400), 60 * 60 * 1000)); + expect(eq(acc.getPremiumRemainingDays(), 100)); }; test("Account::addPremiumDays can reduce premium") = [] { @@ -486,10 +449,8 @@ suite<"account"> accountTest = [] { acc.setPremiumDays(50); acc.addPremiumDays(-30); - expect( - approx(acc.getPremiumLastDay(), getTimeNow() - (20 * 86400), 60 * 60 * 1000) and - eq(acc.getPremiumRemainingDays(), 20) - ); + expect(approx(acc.getPremiumLastDay(), getTimeNow() - (20 * 86400), 60 * 60 * 1000)); + expect(eq(acc.getPremiumRemainingDays(), 20)); }; test("Account::setPremiumDays sets to 0 if day is negative") = [] { @@ -497,18 +458,14 @@ suite<"account"> accountTest = [] { acc.setPremiumDays(10); acc.setPremiumDays(-20); - expect( - eq(acc.getPremiumLastDay(), 0) and - eq(acc.getPremiumLastDay(), 0) - ); + expect(eq(acc.getPremiumLastDay(), 0)); + expect(eq(acc.getPremiumLastDay(), 0)); }; test("Account::setAccountType sets account type") = [] { Account acc { 1 }; - expect( - eq(acc.setAccountType(AccountType::ACCOUNT_TYPE_GAMEMASTER), enumToValue(AccountErrors_t::Ok)) and - eq(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER) - ); + expect(eqEnum(acc.setAccountType(AccountType::ACCOUNT_TYPE_GAMEMASTER), AccountErrors_t::Ok)); + expect(eqEnum(acc.getAccountType(), AccountType::ACCOUNT_TYPE_GAMEMASTER)); }; test("Account::updatePremiumTime sets premium remaining days to 0 if last day is in the past") = [] { @@ -548,7 +505,7 @@ suite<"account"> accountTest = [] { }; test("Account::getAccountPlayer returns error if not yet loaded") = [] { - expect(eq(std::get<1>(Account { 1 }.getAccountPlayers()), enumToValue(AccountErrors_t::NotInitialized))); + expect(eqEnum(std::get<1>(Account { 1 }.getAccountPlayers()), AccountErrors_t::NotInitialized)); }; test("Account::getAccountPlayer returns players") = [&injectionFixture] { @@ -560,15 +517,13 @@ suite<"account"> accountTest = [] { AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD, {{ "Canary", 1 }, { "Canary2", 2 }} } ); - expect(acc.load() == enumToValue(AccountErrors_t::Ok)); + expect(acc.load() == AccountErrors_t::Ok); auto [players, error] = acc.getAccountPlayers(); - expect( - eq(error, enumToValue(AccountErrors_t::Ok)) and - eq(players.size(), 2) and - eq(players["Canary"], 1) and - eq(players["Canary2"], 2) - ); + expect(eqEnum(error, AccountErrors_t::Ok)); + expect(eq(players.size(), 2)); + expect(eq(players["Canary"], 1)); + expect(eq(players["Canary2"], 2)); }; test("Account::authenticate password using sha1") = [&injectionFixture] { @@ -580,7 +535,7 @@ suite<"account"> accountTest = [] { AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD, { { "Canary", 1 }, { "Canary2", 2 } } } ); - expect(acc.load() == enumToValue(AccountErrors_t::Ok)); + expect(acc.load() == AccountErrors_t::Ok); accountRepository.password_ = "7c4a8d09ca3762af61e59520943dc26494f8941b"; expect(acc.authenticate("123456")); }; @@ -594,7 +549,7 @@ suite<"account"> accountTest = [] { AccountInfo { 1, 1, 1, AccountType::ACCOUNT_TYPE_GOD, { { "Canary", 1 }, { "Canary2", 2 } }, false, getTimeNow() + 24 * 60 * 60 * 1000 } ); - expect(acc.load() == enumToValue(AccountErrors_t::Ok)); + expect(acc.load() == AccountErrors_t::Ok); expect(acc.authenticate()); };