1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2012-2015 Joerg Henrichs
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #ifndef HEADER_REPLAY__PLAY_HPP
20 #define HEADER_REPLAY__PLAY_HPP
21 
22 #include "replay/replay_base.hpp"
23 #include "tracks/track.hpp"
24 
25 #include "irrString.h"
26 #include <algorithm>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 using namespace irr;
32 
33 class GhostKart;
34 
35 /**
36   * \ingroup replay
37   */
38 class ReplayPlay : public ReplayBase
39 {
40 
41 public:
42     /** Order of sort for ReplayData */
43     enum SortOrder
44     {
45         SO_DEFAULT,
46         SO_TRACK = SO_DEFAULT,
47         SO_REV,
48         SO_KART_NUM,
49         SO_DIFF,
50         SO_LAPS,
51         SO_TIME,
52         SO_USER,
53         SO_VERSION
54     };
55 
56     class ReplayData
57     {
58     public:
59         std::string                m_filename;
60         std::string                m_track_name;
61         Track*                     m_track;
62         std::string                m_minor_mode;
63         core::stringw              m_stk_version;
64         core::stringw              m_user_name;
65         std::vector<std::string>   m_kart_list;
66         std::vector<core::stringw> m_name_list;
67         std::vector<float>         m_kart_color; //no sorting for this
68         bool                       m_reverse;
69         bool                       m_custom_replay_file;
70         unsigned int               m_difficulty;
71         unsigned int               m_laps;
72         unsigned int               m_replay_version; //no sorting for this
73         uint64_t                   m_replay_uid; //no sorting for this
74         float                      m_min_time;
75 
operator <(const ReplayData & r) const76         bool operator < (const ReplayData& r) const
77         {
78             switch (m_sort_order)
79             {
80                 case SO_TRACK:
81                     return m_track->getSortName() < r.m_track->getSortName();
82                     break;
83                 case SO_KART_NUM:
84                     return m_kart_list.size() < r.m_kart_list.size();
85                     break;
86                 case SO_REV:
87                     return m_reverse < r.m_reverse;
88                     break;
89                 case SO_DIFF:
90                     return m_difficulty < r.m_difficulty;
91                     break;
92                 case SO_LAPS:
93                     return m_laps < r.m_laps;
94                     break;
95                 case SO_TIME:
96                     return m_min_time < r.m_min_time;
97                     break;
98                 case SO_USER:
99                     return m_user_name < r.m_user_name;
100                     break;
101                 case SO_VERSION:
102                     return m_stk_version < r.m_stk_version;
103                     break;
104             }   // switch
105             return true;
106         }   // operator <
107     };   // ReplayData
108 
109 private:
110     static ReplayPlay       *m_replay_play;
111 
112     static SortOrder         m_sort_order;
113 
114     unsigned int             m_current_replay_file;
115 
116     unsigned int             m_second_replay_file;
117 
118     bool                     m_second_replay_enabled;
119 
120     std::vector<ReplayData>  m_replay_file_list;
121 
122     /** All ghost karts. */
123     std::vector<std::shared_ptr<GhostKart> > m_ghost_karts;
124 
125           ReplayPlay();
126          ~ReplayPlay();
127     void  readKartData(FILE *fd, char *next_line, bool second_replay);
128 public:
129     void  reset();
130     void  load();
131     void  loadFile(bool second_replay);
132     void  loadAllReplayFile();
133     // ------------------------------------------------------------------------
setSortOrder(SortOrder so)134     static void        setSortOrder(SortOrder so)       { m_sort_order = so; }
135     // ------------------------------------------------------------------------
sortReplay(bool reverse)136     void               sortReplay(bool reverse)
137     {
138         (reverse ? std::stable_sort(m_replay_file_list.rbegin(),
139             m_replay_file_list.rend()) : std::stable_sort(m_replay_file_list.begin(),
140             m_replay_file_list.end()));
141     }
142     // ------------------------------------------------------------------------
setReplayFile(unsigned int n)143     void               setReplayFile(unsigned int n)
144                                                 { m_current_replay_file = n; }
145 
146     // ------------------------------------------------------------------------
setSecondReplayFile(unsigned int n,bool second_replay_enabled)147     void               setSecondReplayFile(unsigned int n, bool second_replay_enabled)
148                            { m_second_replay_file = n;
149                              m_second_replay_enabled = second_replay_enabled;}
150 
151     // ------------------------------------------------------------------------
152     void               setReplayFileByUID(uint64_t uid);
153     // ------------------------------------------------------------------------
154     unsigned int       getReplayIdByUID(uint64_t uid);
155 
156     // ------------------------------------------------------------------------
157     bool               addReplayFile(const std::string& fn,
158                                      bool custom_replay = false,
159                                      int call_index = 0);
160     // ------------------------------------------------------------------------
getReplayData(unsigned int n) const161     const ReplayData&  getReplayData(unsigned int n) const
162                                           { return m_replay_file_list.at(n); }
163     // ------------------------------------------------------------------------
getCurrentReplayData() const164     const ReplayData&  getCurrentReplayData() const
165                            { return m_replay_file_list.at(m_current_replay_file); }
166     // ------------------------------------------------------------------------
getNumReplayFile() const167     const unsigned int getNumReplayFile() const
168                            { return (unsigned int)m_replay_file_list.size(); }
169     // ------------------------------------------------------------------------
getGhostKart(int n)170     std::shared_ptr<GhostKart> getGhostKart(int n) { return m_ghost_karts[n]; }
171     // ------------------------------------------------------------------------
getNumGhostKart() const172     const unsigned int getNumGhostKart() const
173     {
174         assert(m_replay_file_list.size() > 0);
175         unsigned int num =
176             (unsigned int)m_replay_file_list.at(m_current_replay_file)
177                                             .m_kart_list.size();
178         unsigned int second_file_num =
179             (unsigned int)m_replay_file_list.at(m_second_replay_file)
180                                             .m_kart_list.size();
181 
182         num = (m_second_replay_enabled) ? num + second_file_num : num;
183 
184         return num;
185     }   // getNumGhostKart
186     // ------------------------------------------------------------------------
getGhostKartName(unsigned int n) const187     const std::string& getGhostKartName(unsigned int n) const
188     {
189         assert(m_replay_file_list.size() > 0);
190 
191         unsigned int fkn =
192             (unsigned int)m_replay_file_list.at(m_current_replay_file)
193                                             .m_kart_list.size();
194         if (n < fkn)
195             return m_replay_file_list.at(m_current_replay_file).m_kart_list.at(n);
196         else
197             return m_replay_file_list.at(m_second_replay_file).m_kart_list.at(n-fkn);
198     }
199     // ------------------------------------------------------------------------
200     /** Creates a new instance of the replay object. */
create()201     static void        create()          { m_replay_play = new ReplayPlay(); }
202     // ------------------------------------------------------------------------
203     /** Returns the instance of the replay object. */
get()204     static ReplayPlay  *get()                        { return m_replay_play; }
205     // ------------------------------------------------------------------------
206     /** Delete the instance of the replay object. */
destroy()207     static void        destroy()
208                                { delete m_replay_play; m_replay_play = NULL; }
209     // ------------------------------------------------------------------------
210     /** Returns the filename that was opened. */
getReplayFilename(int replay_file_number=1) const211     virtual const std::string& getReplayFilename(int replay_file_number = 1) const
212     {
213         assert(m_replay_file_list.size() > 0);
214         if (replay_file_number == 2)
215             return m_replay_file_list.at(m_second_replay_file).m_filename;
216         else
217             return m_replay_file_list.at(m_current_replay_file).m_filename;
218     }
219     // ------------------------------------------------------------------------
220 };   // Replay
221 
222 #endif
223