Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
refbox_state_writer.cpp
1 
2 /***************************************************************************
3  * refbox_state_writer.cpp - Fawkes RefBox state writer
4  *
5  * Created: Wed Apr 09 10:19:27 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "refbox_state_writer.h"
24 
25 #include <netcomm/worldinfo/transceiver.h>
26 #include <utils/time/time.h>
27 #include <utils/time/clock.h>
28 
29 #include <set>
30 #include <cstdio>
31 
32 #define log(...) if (__debug) {\
33  printf("%3u %s ", __counter, get_time().c_str());\
34  printf(__VA_ARGS__);\
35  fflush(stdout);\
36  }
37 
38 using namespace std;
39 using namespace fawkes;
40 
41 namespace {
42 std::string get_time() throw()
43 {
44  Clock* c = Clock::instance();
45  Time t = c->now();
46  char* buf = new char[Time::TIMESTR_SIZE];
47  t.str_r(buf, true);
48  std::string str = buf;
49  delete buf;
50  std::string::size_type from =
51  1+str.find_first_of(' ',
52  1+str.find_first_of(' ',
53  1+str.find_first_of(' ')));
54  std::string::size_type to = str.find_last_of(' ');
55  return str.substr(from, to - from + 1);
56 }
57 }
58 
59 /** @class RefBoxStateBBWriter "refbox_state_writer.h"
60  * RefBox repeater state writer.
61  * Writes to GameStateInterfaces "WM GameState" of given hosts.
62  * @author Christoph Schwering
63  */
64 
65 /** Constructor.
66  * @param hosts hosts to connect to to send game state info via remote
67  * blackboard
68  * @param debug true to enable debug output
69  */
70 RefBoxStateBBWriter::RefBoxStateBBWriter(vector<string> hosts, bool debug)
71 {
72  __counter = 0;
73  __debug = debug;
74 
75  __game_state = GS_FROZEN;
76  __state_team = TEAM_BOTH;
77  __score_cyan = 0;
78  __score_magenta = 0;
79  __our_team = TEAM_CYAN;
80  __our_goal_color = GOAL_BLUE;
81  __half = HALF_FIRST;
82 
83  for (vector<string>::const_iterator it = hosts.begin(); it != hosts.end();
84  it++) {
85  connect(*it);
86  }
87 }
88 
89 
90 /** Destructor. */
92 {
93  for (map<RemoteBlackBoard*, GameStateInterface*>::iterator it = __giss.begin();
94  it != __giss.end(); it++) {
95  RemoteBlackBoard* rbb = it->first;
96  GameStateInterface* gis = it->second;
97  rbb->close(gis);
98  delete rbb;
99  }
100 }
101 
102 
103 /* Connects to a host and opens and stores the interface at the right place. */
104 void RefBoxStateBBWriter::connect(const string& host)
105 {
106  try {
107  RemoteBlackBoard* rbb = new RemoteBlackBoard(host.c_str(), 1910);
108  __rbbs[rbb] = host;
109  GameStateInterface* gis = static_cast<GameStateInterface*>(rbb->open_for_writing("GameStateInterface", "WM GameState"));
110  __giss[rbb] = gis;
111  log("Successfully connected to %s\n", host.c_str());
112  set_gamestate(__game_state, __state_team);
113  set_score(__score_cyan, __score_magenta);
114  set_team_goal(__our_team, __our_goal_color);
115  set_half(__half);
116  gis->write();
117  } catch (Exception& e) {
118  log("Connecting to %s failed\n", host.c_str());
119  e.print_trace();
120  log("\n");
121  log("\n");
122  }
123 }
124 
125 /** Set current game state.
126  * @param game_state current game state
127  * @param state_team team referenced by the game state
128  */
129 void
131  worldinfo_gamestate_team_t state_team)
132 {
133  log("Setting gamestate to '%d' for team '%s'\n",
134  game_state, worldinfo_gamestate_team_tostring(state_team));
135 
136  __game_state = game_state;
137  __state_team = state_team;
138 
139  for (map<RemoteBlackBoard*,GameStateInterface*>::iterator it = __giss.begin(); it != __giss.end(); it++) {
140  GameStateInterface* gis = it->second;
141  switch (game_state)
142  {
143  case(GS_FROZEN):
144  gis->set_game_state( GameStateInterface::GS_FROZEN );
145  break;
146 
147  case(GS_PLAY):
148  gis->set_game_state( GameStateInterface::GS_PLAY );
149  break;
150 
151  case(GS_KICK_OFF):
152  gis->set_game_state( GameStateInterface::GS_KICK_OFF );
153  break;
154 
155  case(GS_DROP_BALL):
156  gis->set_game_state( GameStateInterface::GS_DROP_BALL );
157  break;
158 
159  case(GS_PENALTY):
160  gis->set_game_state( GameStateInterface::GS_PENALTY );
161  break;
162 
163  case(GS_CORNER_KICK):
164  gis->set_game_state( GameStateInterface::GS_CORNER_KICK );
165  break;
166 
167  case(GS_THROW_IN):
168  gis->set_game_state( GameStateInterface::GS_THROW_IN );
169  break;
170 
171  case(GS_FREE_KICK):
172  gis->set_game_state( GameStateInterface::GS_FREE_KICK );
173  break;
174 
175  case(GS_GOAL_KICK):
176  gis->set_game_state( GameStateInterface::GS_GOAL_KICK );
177  break;
178 
179  case(GS_HALF_TIME):
180  gis->set_game_state( GameStateInterface::GS_HALF_TIME );
181  break;
182  }
183 
184  switch (state_team)
185  {
186  case(TEAM_NONE):
187  gis->set_state_team( GameStateInterface::TEAM_NONE );
188  break;
189 
190  case(TEAM_CYAN):
191  gis->set_state_team( GameStateInterface::TEAM_CYAN );
192  break;
193 
194  case(TEAM_MAGENTA):
195  gis->set_state_team( GameStateInterface::TEAM_MAGENTA );
196  break;
197 
198  case(TEAM_BOTH):
199  gis->set_state_team( GameStateInterface::TEAM_BOTH );
200  break;
201  }
202  }
203 }
204 
205 
206 /** Set score.
207  * @param score_cyan current score of team cyan
208  * @param score_magenta current score of team magenta
209  */
210 void
211 RefBoxStateBBWriter::set_score(unsigned int score_cyan, unsigned int score_magenta)
212 {
213  log("Setting score to %u:%u (cyan:magenta)\n", score_cyan, score_magenta);
214 
215  __score_cyan = score_cyan;
216  __score_magenta = score_magenta;
217 
218  for (map<RemoteBlackBoard*,GameStateInterface*>::iterator it = __giss.begin(); it != __giss.end(); it++) {
219  GameStateInterface* gis = it->second;
220  gis->set_score_cyan( score_cyan );
221  gis->set_score_magenta( score_magenta );
222  }
223 }
224 
225 
226 /** Set team and goal info.
227  * @param our_team our team color
228  * @param goal_color our goal color
229  */
230 void
233 {
234  log("Setting team color to '%s' and goal color to '%s'\n",
237 
238  __our_team = our_team;
239  __our_goal_color = goal_color;
240 
241  for (map<RemoteBlackBoard*,GameStateInterface*>::iterator it = __giss.begin(); it != __giss.end(); it++) {
242  GameStateInterface* gis = it->second;
243  if (our_team == TEAM_CYAN) {
244  gis->set_our_team( GameStateInterface::TEAM_CYAN );
245  } else {
246  gis->set_our_team( GameStateInterface::TEAM_MAGENTA );
247  }
248 
249  if (goal_color == GOAL_BLUE) {
250  gis->set_our_goal_color( GameStateInterface::GOAL_BLUE );
251  } else {
252  gis->set_our_goal_color( GameStateInterface::GOAL_YELLOW );
253  }
254  }
255 }
256 
257 
258 /** Set current half of the game time.
259  * @param half current half
260  */
261 void
263 {
264  log("Setting half to '%s'\n",
266 
267  __half = half;
268 
269  for (map<RemoteBlackBoard*,GameStateInterface*>::iterator it = __giss.begin(); it != __giss.end(); it++) {
270  GameStateInterface* gis = it->second;
271  switch (half) {
272  case HALF_FIRST:
273  gis->set_half(GameStateInterface::HALF_FIRST);
274  break;
275  case HALF_SECOND:
276  gis->set_half(GameStateInterface::HALF_SECOND);
277  break;
278  }
279  }
280 }
281 
282 
283 /** Send worldinfo. */
284 void
286 {
287  ++__counter;
288  log("Sending worldinfo\n");
289 
290  set<RemoteBlackBoard*> erase_rbbs;
291  set<string> reconnect_hosts;
292 
293  unsigned int i = 0;
294  for (map<RemoteBlackBoard*,GameStateInterface*>::iterator it = __giss.begin(); it != __giss.end(); it++) {
295  RemoteBlackBoard* rbb = it->first;
296  GameStateInterface* gis = it->second;
297  const string host = __rbbs[rbb].c_str();
298  try {
299  gis->set_score_cyan(gis->score_cyan() + 1); // just for checking at the recipient's side whether the data ankommt
300  gis->write();
301  log("%u. Successfully wrote game state on %s\n", ++i, __rbbs[rbb].c_str());
302  } catch (Exception& e) {
303  log("%u. Writing game state on %s failed, reason:\n", ++i, __rbbs[rbb].c_str());
304  e.print_trace();
305  log("I will reconnect after this loop\n");
306  erase_rbbs.insert(rbb);
307  reconnect_hosts.insert(host);
308  }
309  }
310  for (set<RemoteBlackBoard*>::iterator it = erase_rbbs.begin(); it != erase_rbbs.end(); it++) {
311  RemoteBlackBoard* rbb = *it;
312  __rbbs.erase(rbb);
313  __giss.erase(rbb);
314  }
315  for (set<std::string>::iterator it = reconnect_hosts.begin(); it != reconnect_hosts.end(); it++) {
316  std::string host = *it;
317  log("Reconnecting to %s\n", host.c_str());
318  connect(host);
319  }
320 
321  log("Sending worldinfo done\n");
322 }