Skip to content

Commit b102105

Browse files
committed
fix
1 parent 5e6cb2c commit b102105

File tree

5 files changed

+156
-23
lines changed

5 files changed

+156
-23
lines changed

sprint4/problems/leave_game/solution/src/application.cpp

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <boost/json/object.hpp>
1515
#include <iomanip>
1616
#include <exception>
17+
#include <stdexcept>
1718
#include <unordered_set>
1819

1920
namespace app {
@@ -283,13 +284,105 @@ Application::Application(model::Game& game, db::ConnectionPool& pool)
283284
game_.SetDefaultTickTime(game.GetDefaultTickTime());
284285
}
285286

287+
std::vector<Application::PlayerMovementInfo> Application::PlayersInfoSnapstot() const {
288+
std::vector<PlayerMovementInfo> result;
289+
result.reserve(players_.GetPlayers().size());
290+
291+
for (const auto& player : players_.GetPlayers()) {
292+
result.push_back({
293+
player.second->GetDogName(),
294+
player.second->GetDogPos(),
295+
player.second->GetDogSpeed(),
296+
});
297+
}
298+
299+
return result;
300+
}
301+
286302
void Application::LoadGameFromFilie() {
287303
listener_->LoadStateFromFile();
288304
}
289305

290-
void Application::Tick(milliseconds delta_time) const {
291-
std::unordered_set<std::shared_ptr<model::Dog>>
292-
afk_players = game_.GetEngine().Tick(delta_time);
306+
bool Application::IsMoving(Application::PlayerMovementInfo& old,
307+
Application::PlayerMovementInfo& current) const {
308+
// bool is_moving = current.speed.x != 0 || current.speed.y != 0;
309+
// return is_moving || old.pos != current.pos;
310+
return 0;
311+
}
312+
313+
void Application::RemoveAFKPlayer(std::shared_ptr<player::Player> player) {
314+
auto dog_id = player->GetDogId();
315+
auto map_id = player->GetGameSession()->GetMapId();
316+
players_.Remove(dog_id, map_id);
317+
}
318+
319+
bool Application::IsAFK(Application::PlayerMovementInfo& old,
320+
Application::PlayerMovementInfo& current) const {
321+
bool is_not_moving = current.speed.x == 0 && current.speed.y == 0;
322+
return is_not_moving || old.pos == current.pos;
323+
}
324+
325+
void Application::SavePlayerStatsToDB(std::shared_ptr<model::Dog> dog) {
326+
try {
327+
auto connection = connection_pool_.GetConnection();
328+
329+
pqxx::work work{*connection};
330+
331+
work.exec_prepared("insert_retire",
332+
dog->GetName(),
333+
dog->GetState().score,
334+
dog->CalcPlayTime()
335+
);
336+
337+
work.commit();
338+
} catch (const std::exception& e) {
339+
throw std::runtime_error(e.what());
340+
}
341+
}
342+
343+
void Application::RemoveAFKPlayers(double delta_time,
344+
std::vector<PlayerMovementInfo>& old,
345+
std::vector<PlayerMovementInfo>& current) {
346+
if (old.size() != current.size()) {
347+
throw std::logic_error("different size of players info (application layer)");
348+
}
349+
350+
std::vector<std::shared_ptr<player::Player>> afk_players;
351+
352+
for (auto old_it = old.begin(), current_it = current.begin();
353+
old_it != old.end() && current_it != current.end();
354+
++old_it, ++current_it) {
355+
356+
auto player_token =
357+
players_.FindPlayerByName(old_it->dog_name.data());
358+
auto player = players_.GetPlayerByToken(player_token.value());
359+
360+
if (IsAFK(*old_it, *current_it)) {
361+
auto play_time = player->GetLastMoveTime();
362+
play_time += delta_time;
363+
player->SetLastMoveTime(play_time);
364+
365+
if (play_time > dog_retirement_time_) {
366+
SavePlayerStatsToDB(player->GetDog());
367+
368+
RemoveAFKPlayer(player);
369+
}
370+
} else {
371+
player->SetLastMoveTime(0);
372+
}
373+
}
374+
375+
for (auto& player : afk_players) {
376+
RemoveAFKPlayer(player);
377+
}
378+
}
379+
380+
void Application::Tick(milliseconds delta_time) {
381+
auto old = PlayersInfoSnapstot();
382+
game_.GetEngine().Tick(delta_time);
383+
auto current = PlayersInfoSnapstot();
384+
385+
RemoveAFKPlayers(delta_time.count(), old, current);
293386

294387
if (listener_) {
295388
listener_->OnTick(delta_time);

sprint4/problems/leave_game/solution/src/application.h

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,22 @@ namespace app {
130130
}
131131

132132
private:
133+
using IdToName = std::pair<uint64_t, std::string>;
133134
PlayerTokens player_tokens_;
134-
std::unordered_map<std::pair<uint64_t, std::string>,
135-
std::shared_ptr<player::Player>, boost::hash<std::pair<uint64_t, std::string>>> players_;
135+
std::unordered_map<IdToName,
136+
std::shared_ptr<player::Player>,
137+
boost::hash<std::pair<uint64_t, std::string>>> players_;
136138

137139
};
138140

139141
class Application {
140142
public:
143+
struct PlayerMovementInfo {
144+
std::string_view dog_name;
145+
model::Pos pos;
146+
model::Speed speed;
147+
};
148+
141149
struct PlayerInfo {
142150
Token token;
143151
model::Dog::Id id;
@@ -182,7 +190,7 @@ namespace app {
182190
PlayerInfo AddPlayer(const std::string& player_name,
183191
std::shared_ptr<model::GameSession> session);
184192

185-
void Tick(milliseconds delta_time) const;
193+
void Tick(milliseconds delta_time);
186194

187195
serialization::GameSer SerializeGame() const {
188196
return serialization::GameSer(game_);
@@ -195,7 +203,24 @@ namespace app {
195203

196204
void LoadGameFromFilie();
197205

206+
198207
private:
208+
bool IsMoving(Application::PlayerMovementInfo& old,
209+
Application::PlayerMovementInfo& current) const;
210+
211+
bool IsAFK(Application::PlayerMovementInfo& old,
212+
Application::PlayerMovementInfo& current) const;
213+
214+
void RemoveAFKPlayer(std::shared_ptr<player::Player> player);
215+
216+
void RemoveAFKPlayers(double delta_time,
217+
std::vector<PlayerMovementInfo>& old,
218+
std::vector<PlayerMovementInfo>& current);
219+
220+
void SavePlayerStatsToDB(std::shared_ptr<model::Dog> dog);
221+
222+
std::vector<PlayerMovementInfo> PlayersInfoSnapstot() const;
223+
199224
PlayerInfo GetPlayerInfo(const std::string& name);
200225

201226
bool HasPlayerByName(const std::string& name) const;
@@ -214,6 +239,8 @@ namespace app {
214239

215240
db::ConnectionPool& connection_pool_;
216241

242+
double dog_retirement_time_ = 15;
243+
217244
model::Game& game_;
218245
Players players_;
219246
ApplicationListener* listener_ = nullptr;

sprint4/problems/leave_game/solution/src/model.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,9 @@ using namespace std::literals;
506506
}
507507

508508
bool Dog::IsMoving(model::Pos new_pos) const {
509-
bool is_moving = this->state_.speed.x != 0 || this->state_.speed.y != 0;
509+
bool is_moving = this->state_.speed.x != 0 ||
510+
this->state_.speed.y != 0;
511+
510512
return is_moving || new_pos != this->state_.position;
511513
}
512514

@@ -562,20 +564,20 @@ using namespace std::literals;
562564
// BOOST_LOG_TRIVIAL(info) << "SavePlayerStatsToDB completed successfully.";
563565
}
564566

565-
void GameSession::RemoveAFKPlayers(std::unordered_map<Dog::Id, Pos> new_positions,
566-
double delta_time) {
567-
std::vector<Dog::Id> afk_players;
567+
// void GameSession::RemoveAFKPlayers(std::unordered_map<Dog::Id, Pos> new_positions,
568+
// double delta_time) {
569+
// std::vector<Dog::Id> afk_players;
568570

569-
for (auto& [dog_id, dog] : dogs_) {
570-
if (dog->IsAfk(delta_time, dog_retirement_time_, new_positions[dog_id])) {
571-
afk_players.push_back(dog_id);
572-
}
573-
}
571+
// for (auto& [dog_id, dog] : dogs_) {
572+
// if (dog->IsAfk(delta_time, dog_retirement_time_, new_positions[dog_id])) {
573+
// afk_players.push_back(dog_id);
574+
// }
575+
// }
574576

575-
for (const auto& dog_id : afk_players) {
576-
RetirePlayer(dog_id);
577-
}
578-
}
577+
// for (const auto& dog_id : afk_players) {
578+
// RetirePlayer(dog_id);
579+
// }
580+
// }
579581

580582
void GameSession::Tick(double delta_time) {
581583
using namespace collision_detector;
@@ -585,7 +587,7 @@ using namespace std::literals;
585587
ComputeNewPositions(delta_time);
586588

587589
// 2. Удаляем афк игроков
588-
RemoveAFKPlayers(new_positions, delta_time);
590+
// RemoveAFKPlayers(new_positions, delta_time);
589591

590592
// 3. Определяем события сбора предметов
591593
std::vector<GatheringEvent> events =

sprint4/problems/leave_game/solution/src/model.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ namespace model {
366366

367367
private:
368368

369-
void RemoveAFKPlayers(std::unordered_map<Dog::Id, Pos> new_positions,
369+
void RemoveAFKPlayer(std::unordered_map<Dog::Id, Pos> new_positions,
370370
double delta_time);
371371

372372
Pos CalculateNewPosition(const Pos& position, const Speed& speed, double delta_time);
@@ -548,8 +548,7 @@ namespace model {
548548
}
549549

550550
void Tick(std::chrono::milliseconds delta_time) {
551-
std::unordered_set<std::shared_ptr<model::Dog>> afk_players =
552-
session_service_->Tick(delta_time);
551+
session_service_->Tick(delta_time);
553552
loot_service_->GenerateLoot(delta_time.count());
554553
}
555554

sprint4/problems/leave_game/solution/src/player.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,24 @@ namespace player {
2727
return dog_->GetName();
2828
}
2929

30+
double GetLastMoveTime() const { return last_move_time_; }
31+
32+
void SetLastMoveTime(double value) { last_move_time_ = value; }
33+
34+
model::Speed GetDogSpeed() const { return dog_->GetSpeed(); }
35+
model::Pos GetDogPos() const { return dog_->GetPosition(); }
36+
3037
void MovePlayer(std::string direction = "");
3138

3239
const std::shared_ptr<model::GameSession> GetGameSession() const;
3340
const std::shared_ptr<model::Dog> GetDog() const { return dog_; }
3441

3542
private:
43+
double last_move_time_ = 0;
44+
45+
std::chrono::steady_clock::time_point play_time_ =
46+
std::chrono::steady_clock::now();
47+
3648
std::shared_ptr<model::Dog> dog_;
3749
std::shared_ptr<model::GameSession> game_session_;
3850

0 commit comments

Comments
 (0)