# Rewards code review
1. MainMenuBase
- возможно стоит добавить метод и для коллекций PrepareCollectionsRewards() и вынести туда нужный кусочек кода из PrepareCollections чтобы по интерфейсу сразу было понять что именно имеет свойства ревардсов и легче читалось.
- PrepareLootBoxes**Rewards**() ?
2. Common.cpp
- gui::AttachToButtons(...) выглядит немного костыльно, по-сути мы же не должны подписываться на кнопки повторно, хотя у себя в коде тоже что-то такое писала :)
```
if (button)
{
**button->RemoveActionListener(listener);**
button->AddActionListener(listener);
}
```
3. VCORE_AccountImpl::OnRewardsDataReceived
- стоит добавить проверку размера массива loot_box_skins, что прислал сервер, на всякий случай чтобы избежать падение клиента в месте loot_box_skins[i]. Если нет скина использовать дефолтный.
4. RewardLootBox::GetLootBoxLevelSkinnedName
- запись типа
`const bool key_is_present = data.find(KEY) != data.end();`
можно заменить на более короткую
`const bool key_is_present = data.count(KEY);`
5. VCORE_LootBoxes::GetConvertedLootBoxes возможно также стоит подобавлять проверки на наличие ключей (?), это касается и других похожих кусков кода - основная идея избежать падение клиента
```
j_data["id"] = raw_loot_box.loot_box_id;
j_data["level"] = raw_loot_box.loot_box_level;
j_data["skin"] = raw_loot_box.loot_box_skin;
```
Похоже, я бы добавила проверку
```
void VCORE_LootBoxes::SetLootboxOpened(const LootBoxId_t loot_box_id, const std::vector<Reward_t>& rewards_data)
{
m_loot_boxes_rewards[loot_box_id] = rewards_data;
}
```
6. std::vector<Reward_t> подобные записи можно заменять алиасами, так более короткие записи (особенно, если используется как параметр метода) и проще модифицировать в одно метсте если что
7. std::find_if(...) != data.end() --> std::none_of
8. Reward.hpp
- #include <gui/include/event/ActionListener.hpp> - лишний
- возмона инвалидация итератора
```
void Reward::NotifyListeners(const std::string& command)
{
const std::list<RewardListener*> listeners = m_listeners;
for (const auto& listener : listeners)
{
cpp::count_ptr<Reward> keep(this);
if (listener)
listener->OnRewardNotification(this, command);
}
}
```
9. Стоит добавить дефолтные параметры для всех полей, там же флоаты и инты
typedef int64_t Time;
typedef float Coord;
```
struct RewardLootBoxPopupData_t
{
bool is_set{ false };
gwc::Time wait_before_processing;
gwc::Time wait_between_processings;
gwc::Time move_duration;
gwc::Time fade_duration;
gwc::Time scale_duration;
gwc::Time shift_duration;
gwc::Time loot_box_scale_up_duration;
gwc::Time loot_box_scale_down_duration;
gwc::Coord default_shift_x_offset;
gwc::Coord default_destination_x;
gwc::Coord default_destination_y;
gwc::Coord loot_box_scale_up_value;
gwc::Coord loot_box_scale_down_value;
gwc::Coord spine_view_scale_value;
};
```
10. RewardMoney и др.
Если есть билдеры, то конструктор можно сделать protected (?)
11. RewardsManager
- void ActionPerformed(gui::ActionEvent* event) **override**;
- cpp::count_ptr<Reward> GetRewardById(vcore::RewardId_t reward_id, const RewardsContainer_t& all_rewards) - не используется
- #include <vgui/include/components/VGUI_Panel.hpp> - лишний
12. RewardCollection.cpp
#include <vsdk/Rewards/include/RewardsCmd.hpp> - лишний
13. RewardLootBox.cpp
const std::string LOOTBOX_SPINE_ANIMATION_CLOSED_IDLE = "lootbox_closed_idle"; - не используется
14. RewardMoney.cpp
#include <vsdk/Rewards/include/RewardsCmd.hpp> - лишний