1 /* bzflag
2  * Copyright (c) 1993-2021 Tim Riker
3  *
4  * This package is free software;  you can redistribute it and/or
5  * modify it under the terms of the license found in the file
6  * named COPYING that should have accompanied this file.
7  *
8  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  */
12 
13 /* interface headers */
14 #include "ShotStats.h"
15 
16 /* common implementation headers */
17 #include "FontManager.h"
18 #include "TextUtils.h"
19 
20 /* local implementation headers */
21 #include "ShotStatsDefaultKey.h"
22 #include "HUDDialogStack.h"
23 #include "HUDuiLabel.h"
24 #include "LocalPlayer.h"
25 #include "Roster.h"
26 
ShotStats()27 ShotStats::ShotStats() : HUDDialog()
28 {
29     std::vector<HUDuiControl*>& listHUD = getControls();
30 
31     // add title
32     createLabel("Shot Statistics", listHUD);
33 
34     // key
35     createLabel("Shots Hit/Fired", listHUD);
36 
37     columns = 11;
38     rows = 0;
39 
40     visible = false;
41 
42     // section headings (upper)
43     createLabel("", listHUD);
44     createLabel("", listHUD);
45     createLabel("", listHUD);
46     createLabel("", listHUD);
47     createLabel("", listHUD);
48     createLabel("", listHUD);
49     createLabel("Super", listHUD);
50     createLabel("Shock", listHUD);
51     createLabel("", listHUD);
52     createLabel("Fave.", listHUD);
53     createLabel("Best", listHUD);
54     ++rows;
55 
56     // section headings (lower)
57     createLabel("Player", listHUD);
58     createLabel("Hit%", listHUD);
59     createLabel("Total", listHUD);
60     createLabel("Norm", listHUD);
61     createLabel("GM", listHUD);
62     createLabel("Laser", listHUD);
63     createLabel("Bullet", listHUD);
64     createLabel("Wave", listHUD);
65     createLabel("Thief", listHUD);
66     createLabel("Flag", listHUD);
67     createLabel("Flag", listHUD);
68     ++rows;
69 
70     staticLabelCount = listHUD.size();
71 
72     initNavigation(listHUD, 1, 1);
73 }
74 
~ShotStats()75 ShotStats::~ShotStats()
76 {
77 }
78 
refresh()79 void ShotStats::refresh()
80 {
81     if (!visible)
82         return;
83 
84     std::vector<HUDuiControl*>& listHUD = getControls();
85 
86     // Delete all the controls apart from the headings
87     const int count = listHUD.size();
88     for (int i = staticLabelCount; i < count; i++)
89         delete listHUD[i];
90     listHUD.erase(listHUD.begin() + staticLabelCount, listHUD.end());
91 
92     // my statistics first
93     LocalPlayer* myTank = LocalPlayer::getMyTank();
94     if (myTank->getTeam() != ObserverTeam)
95         addStats((Player*)myTank, listHUD);
96 
97     // add statistics for each player
98     for (int i = 0; i < curMaxPlayers; ++i)
99     {
100         if (remotePlayers[i] && (remotePlayers[i]->getTeam() != ObserverTeam))
101             addStats((Player*)remotePlayers[i], listHUD);
102     }
103 
104     resize(HUDDialog::getWidth(), HUDDialog::getHeight());
105 }
106 
createLabel(const std::string & str,std::vector<HUDuiControl * > & _list)107 void ShotStats::createLabel(const std::string &str,
108                             std::vector<HUDuiControl*> &_list)
109 {
110     HUDuiLabel* control = new HUDuiLabel;
111     control->setFontFace(getFontFace());
112     control->setString(str);
113     _list.push_back(control);
114 }
115 
addStats(Player * _player,std::vector<HUDuiControl * > & _list)116 void ShotStats::addStats(Player *_player, std::vector<HUDuiControl*> &_list)
117 {
118     const ShotStatistics* stats = _player->getShotStatistics();
119     createLabel(_player->getCallSign(), _list);
120 
121     createLabel(TextUtils::format("%2d%%", stats->getTotalPerc()), _list);
122     createLabel(TextUtils::format("%d/%d", stats->getTotalHit(),
123                                   stats->getTotalFired()),  _list);
124     createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::Null),
125                                   stats->getFired(Flags::Null)), _list);
126     createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::GuidedMissile),
127                                   stats->getFired(Flags::GuidedMissile)), _list);
128     createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::Laser),
129                                   stats->getFired(Flags::Laser)), _list);
130     createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::SuperBullet),
131                                   stats->getFired(Flags::SuperBullet)), _list);
132     createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::ShockWave),
133                                   stats->getFired(Flags::ShockWave)), _list);
134     createLabel(TextUtils::format("%d/%d", stats->getHit(Flags::Thief),
135                                   stats->getFired(Flags::Thief)), _list);
136 
137     std::string flagName = stats->getFavoriteFlag()->flagAbbv;
138     if (flagName.empty())
139         flagName = "None";
140     createLabel(flagName, _list);
141 
142     flagName = stats->getBestFlag()->flagAbbv;
143     if (flagName.empty())
144         flagName = "None";
145     createLabel(flagName, _list);
146 
147     ++rows;
148 }
149 
getFontFace()150 int         ShotStats::getFontFace()
151 {
152     // create font
153     return FontManager::instance().getFaceID(BZDB.get("sansSerifFont"));
154 }
155 
getDefaultKey()156 HUDuiDefaultKey*    ShotStats::getDefaultKey()
157 {
158     return ShotStatsDefaultKey::getInstance();
159 }
160 
execute()161 void            ShotStats::execute()
162 {
163     HUDDialogStack::get()->pop();
164 }
165 
dismiss()166 void            ShotStats::dismiss()
167 {
168     visible = false;
169 }
170 
show()171 void            ShotStats::show()
172 {
173     visible = true;
174 
175     refresh();
176 }
177 
resize(int _width,int _height)178 void            ShotStats::resize(int _width, int _height)
179 {
180     HUDDialog::resize(_width, _height);
181 
182     // Reposition everything -- that's gonna be a challenge!
183 
184     FontManager &fm = FontManager::instance();
185 
186     // set up table
187     // total width / (number of columns + 3 columns extra for player name + 2 columns margin)
188     const float columnWidth = _width / (columns + 5.0f);
189     const float fontSize = (float) columnWidth / 6;
190     const float rowHeight = fm.getStrHeight(getFontFace(), fontSize, " ") * 1.2f;
191 
192     // center title
193     const float titleFontSize = (float)_height / 15.0f;
194     std::vector<HUDuiControl*>& listHUD = getControls();
195     HUDuiLabel* title = (HUDuiLabel*)listHUD[0];
196     title->setFontSize(titleFontSize);
197     const float titleWidth = fm.getStrLength(getFontFace(), titleFontSize, title->getString());
198     const float titleHeight = fm.getStrHeight(getFontFace(), titleFontSize, " ");
199     const float titleY = (float)_height - titleHeight;
200     float x = 0.5f * ((float)_width - titleWidth);
201     float y = titleY;
202     title->setPosition(x, y);
203 
204     // center key
205     HUDuiLabel* key = (HUDuiLabel*)listHUD[1];
206     key->setFontSize(fontSize);
207     const float keyCenter = ((columns / 2) + 4) * columnWidth;
208     const float keyWidth = fm.getStrLength(getFontFace(), fontSize, key->getString());
209     const float keyY = titleY - 2 * fm.getStrHeight(getFontFace(), fontSize, " ");
210     y = keyY;
211     x = keyCenter - 0.5f * keyWidth;
212     key->setPosition(x, y);
213 
214     for (int i = 2; i < (int)listHUD.size(); ++i)
215     {
216         // determine row & column (i - 2 to account for title & key)
217         int row = (i - 2) / columns;
218         int column = (i - 2) - (columns * row) + 1;
219         // account for 3 extra columns in player name
220         if (column > 1)
221             column = column + 3;
222 
223         // find coordinates corresponding to this row & column
224         x = column * columnWidth;
225         y = keyY - (row + 1) * rowHeight;
226 
227         // move label to the specified coordinates
228         listHUD[i]->setFontSize(fontSize);
229         listHUD[i]->setPosition(x, y);
230     }
231 
232 }
233 
234 // Local Variables: ***
235 // mode: C++ ***
236 // tab-width: 4 ***
237 // c-basic-offset: 4 ***
238 // indent-tabs-mode: nil ***
239 // End: ***
240 // ex: shiftwidth=4 tabstop=4
241