diff --git a/src/pages/game.cpp b/src/pages/game.cpp index 69bc622..acb5955 100644 --- a/src/pages/game.cpp +++ b/src/pages/game.cpp @@ -76,6 +76,39 @@ void write_html_game(cppdb::session& database, const OastatGame& game, const std json_file << json_data.str(); json_file.close(); + // Get kill matrix + std::map, int> kill_matrix; + std::vector matrix_players; + getGameKillMatrix(database, game.gamenumber, kill_matrix, matrix_players); + + // Add kill matrix to template + if (!matrix_players.empty()) { + game_tpl.ShowSection("HAS_KILL_MATRIX"); + + // Add header row with player names + for (int playerid : matrix_players) { + ctemplate::TemplateDictionary* header_dict = game_tpl.AddSectionDictionary("MATRIX_HEADER"); + const OastatPlayer& p = getPlayer(database, playerid); + header_dict->SetValue("PLAYER_NICKNAME", p.nickname); + } + + // Add data rows + for (int killer : matrix_players) { + ctemplate::TemplateDictionary* row_dict = game_tpl.AddSectionDictionary("MATRIX_ROWS"); + const OastatPlayer& killer_player = getPlayer(database, killer); + row_dict->SetValue("KILLER_NICKNAME", killer_player.nickname); + for (int victim : matrix_players) { + ctemplate::TemplateDictionary* cell_dict = row_dict->AddSectionDictionary("MATRIX_CELLS"); + auto key = std::make_pair(killer, victim); + int kills = kill_matrix.count(key) ? kill_matrix[key] : 0; + cell_dict->SetValue("KILL_COUNT", std::to_string(kills)); + if (kills > 0) { + cell_dict->ShowSection("HAS_KILLS"); + } + } + } + } + std::string output; ctemplate::ExpandTemplate("templates/game.tpl", ctemplate::DO_NOT_STRIP, &game_tpl, &output); std::ofstream myfile; @@ -121,3 +154,31 @@ void getGameScoreProgression(cppdb::session& database, int gamenumber, std::vect } } +void getGameKillMatrix(cppdb::session& database, int gamenumber, std::map, int>& matrix, std::vector& players) { + // Get all players in the game + std::set player_set; + std::string sql_players = "SELECT DISTINCT player FROM oastat.oastat_points WHERE gamenumber = ?"; + cppdb::statement st_players = database.prepare(sql_players); + st_players.bind(1, gamenumber); + cppdb::result res_players = st_players.query(); + while(res_players.next()) { + int playerid; + res_players >> playerid; + player_set.insert(playerid); + } + + // Convert to vector for ordered iteration + players.assign(player_set.begin(), player_set.end()); + + // Get kill data + std::string sql = "SELECT attacker, target, COUNT(0) as kills FROM oastat.oastat_kills WHERE gamenumber = ? AND attacker <> target GROUP BY attacker, target"; + cppdb::statement st = database.prepare(sql); + st.bind(1, gamenumber); + cppdb::result res = st.query(); + while(res.next()) { + int attacker, target, kills; + res >> attacker >> target >> kills; + matrix[std::make_pair(attacker, target)] = kills; + } +} + diff --git a/src/pages/pages.hpp b/src/pages/pages.hpp index 9c73a1e..6cd9733 100644 --- a/src/pages/pages.hpp +++ b/src/pages/pages.hpp @@ -42,6 +42,7 @@ void getMapRecentGames(cppdb::session& database, const std::string& mapname, std void getRecentGames(cppdb::session& database, std::vector& games); void getGameScoreTotal(cppdb::session& database, int gamenumber, std::vector>& scores); void getGameScoreProgression(cppdb::session& database, int gamenumber, std::vector& progression); +void getGameKillMatrix(cppdb::session& database, int gamenumber, std::map, int>& matrix, std::vector& players); // Page generation functions void write_html_index(cppdb::session& database, const std::string& output_dir); diff --git a/static_content/css/oastat.css b/static_content/css/oastat.css index 9669e37..0cc09df 100644 --- a/static_content/css/oastat.css +++ b/static_content/css/oastat.css @@ -107,3 +107,20 @@ td { border-radius: 4px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } + +/* Kill matrix styling */ +.kill-matrix { + font-size: 0.9em; +} + +.kill-matrix th:first-child, +.kill-matrix td:first-child { + text-align: left; + font-weight: 600; +} + +.kill-matrix td.has-kills { + background: #e8f5e9; + font-weight: 600; + color: #2e7d32; +} diff --git a/templates/game.tpl b/templates/game.tpl index 5f024c4..263684a 100644 --- a/templates/game.tpl +++ b/templates/game.tpl @@ -44,11 +44,11 @@
{{GAME_MAP}}
- +

Score Progression Over Time

- +

Final Scores

@@ -62,7 +62,27 @@ {{/SCORES_LIST}}
- + + {{#HAS_KILL_MATRIX}} +

Kill Matrix

+ + + + {{#MATRIX_HEADER}} + + {{/MATRIX_HEADER}} + + {{#MATRIX_ROWS}} + + + {{#MATRIX_CELLS}} + {{KILL_COUNT}} + {{/MATRIX_CELLS}} + + {{/MATRIX_ROWS}} +
Killer \ Victim{{PLAYER_NICKNAME}}
{{KILLER_NICKNAME}}
+ {{/HAS_KILL_MATRIX}} +