00001 #ifndef Impala_Application_Videolympics_ServerConnector_h
00002 #define Impala_Application_Videolympics_ServerConnector_h
00003
00004 #include <iostream>
00005 #include <queue>
00006 #include "Link/PracticalSocket.h"
00007 #include "Link/PracticalSocket.cpp"
00008
00009 #include "Util/StringParser.h"
00010
00011 namespace Impala {
00012 namespace Application {
00013 namespace Videolympics {
00014
00015 class ShotPacket
00016 {
00017 public:
00018 ShotPacket()
00019 {
00020 }
00021
00022 int teamID;
00023 std::string shotName;
00024 double timestamp;
00025 int sequenceNo;
00026 int shotNo;
00027 int relevance;
00028 int selectedByOthers;
00029 };
00030
00031 class GlobalStats
00032 {
00033 public:
00034 GlobalStats()
00035 {
00036 unjudged = positive = negative = 0;
00037 timeSinceStart = 0.0;
00038 contestActive = 0;
00039 totalRelevantShots = 0;
00040 connected = false;
00041 }
00042
00043 int unjudged;
00044 int positive;
00045 int negative;
00046 double timeSinceStart;
00047 int contestActive;
00048 int totalRelevantShots;
00049 bool connected;
00050 };
00051
00052 class StatsPacket
00053 {
00054 public:
00055 StatsPacket()
00056 {
00057 }
00058
00059 int teamID;
00060 int unjudged;
00061 int positive;
00062 int negative;
00063 };
00064
00065
00066 class ServerConnector
00067 {
00068 public:
00069 ServerConnector(std::string server, int port, std::string password)
00070 {
00071 mVidolServer = server;
00072 mVidolPort = port;
00073 mSecretPassword = password + "\n";
00074 mConnected = false;
00075
00076 mGlobalStats = new GlobalStats();
00077 }
00078
00079 void Connect()
00080 {
00081 if (mConnected)
00082 return;
00083 ILOG_DEBUG("establishing connection... ");
00084 try {
00085 mSocket = new TCPSocket(mVidolServer, mVidolPort);
00086 } catch (SocketException e) {
00087 ILOG_DEBUG("Could not connect to server.");
00088 mConnected = false;
00089 mStats.clear();
00090
00091 mGlobalStats->connected = mConnected;
00092 return;
00093 }
00094 ILOG_DEBUG("connection established. Sending password...");
00095 mSocket->send(mSecretPassword.c_str(), strlen(mSecretPassword.c_str()));
00096 mConnected = true;
00097 mGlobalStats->connected = mConnected;
00098 }
00099
00100 ShotPacket *GetPacket()
00101 {
00102 if (mShotQueue.empty())
00103 return 0;
00104 ShotPacket *p = (ShotPacket*)mShotQueue.front();
00105 mShotQueue.pop();
00106 return p;
00107 }
00108
00109 StatsPacket *GetStats(int team)
00110 {
00111 if(mStats.find(team) == mStats.end())
00112 {
00113 return 0;
00114 }
00115 return mStats[team];
00116 }
00117
00118 GlobalStats *GetGlobalStats()
00119 {
00120 return mGlobalStats;
00121 }
00122
00123 bool Update()
00124 {
00125 Connect();
00126 if (!mConnected)
00127 return false;
00128
00129 ILOG_DEBUG("Requesting POLL update...");
00130 try {
00131 mSocket->send("POLL", 4);
00132 } catch (SocketException e) {
00133 ILOG_ERROR("Server connection failed during SEND.");
00134 mConnected = false;
00135 mGlobalStats->connected = false;
00136 mStats.clear();
00137 return false;
00138 }
00139
00140 int aantal;
00141 try {
00142 mSocket->recv(&aantal, 4);
00143 } catch (SocketException e) {
00144 ILOG_ERROR("Server connection failed during RECV.");
00145 mConnected = false;
00146 mGlobalStats->connected = false;
00147 mStats.clear();
00148 return false;
00149 }
00150 ILOG_DEBUG(aantal << " shots in queue");
00151 char buffer[20000];
00152 if (aantal > 0)
00153 {
00154 int recv = 0;
00155 try {
00156 recv = mSocket->recv(buffer, 20000);
00157 } catch (SocketException e) {
00158 ILOG_ERROR("Server connection failed during RECV.");
00159 mConnected = false;
00160 mGlobalStats->connected = false;
00161 mStats.clear();
00162 return false;
00163 }
00164 if (recv <= 0)
00165 {
00166 ILOG_ERROR("There should be a queue, however nothing was read.");
00167 return false;
00168 }
00169 buffer[recv] = 0;
00170 ParsePoll(buffer);
00171 }
00172
00173 ILOG_DEBUG("Requesting POLL update...");
00174 try {
00175 mSocket->send("STAT", 4);
00176 } catch (SocketException e) {
00177 ILOG_ERROR("Server connection failed.");
00178 mConnected = false;
00179 mGlobalStats->connected = false;
00180 mStats.clear();
00181 return false;
00182 }
00183 try {
00184 mSocket->recv(&aantal, 4);
00185 } catch (SocketException e) {
00186 ILOG_ERROR("Server connection failed during RECV.");
00187 mConnected = false;
00188 mGlobalStats->connected = false;
00189 mStats.clear();
00190 return false;
00191 }
00192 ILOG_DEBUG(aantal << " statistics received.");
00193 if (aantal > 0)
00194 {
00195 int recv;
00196 try {
00197 recv = mSocket->recv(buffer, 20000);
00198 } catch (SocketException e) {
00199 ILOG_ERROR("Server connection failed during RECV.");
00200 mConnected = false;
00201 mGlobalStats->connected = false;
00202 mStats.clear();
00203 return false;
00204 }
00205 if (recv <= 0)
00206 {
00207 ILOG_ERROR("There should be statistics, however nothing was read.");
00208 return false;
00209 }
00210 buffer[recv] = 0;
00211 ParseStat(buffer, aantal);
00212 }
00213
00214 return true;
00215 }
00216
00217 void
00218 ParsePoll(std::string input)
00219 {
00220 Util::StringParser p = Util::StringParser(input);
00221 while (1)
00222 {
00223 std::string oneline = p.GetString('\n', false);
00224 if (oneline.size() == 0)
00225 break;
00226 Util::StringParser line = Util::StringParser(oneline);
00227 ShotPacket *entry = new ShotPacket();
00228 entry->timestamp = line.GetDouble(',');
00229 entry->sequenceNo = line.GetInt(',');
00230 entry->teamID = line.GetInt(',');
00231 entry->shotName = line.GetString(',', false);
00232 entry->shotNo = line.GetInt(',');
00233 entry->relevance = line.GetInt(',');
00234 entry->selectedByOthers = line.GetInt(',');
00235 mShotQueue.push(entry);
00236
00237 if (mShotQueue.size() > 100)
00238 mShotQueue.pop();
00239 }
00240 }
00241
00242
00243 void
00244 ParseStat(std::string input, int aantal)
00245 {
00246 Util::StringParser p = Util::StringParser(input);
00247 while (aantal--)
00248 {
00249 std::string oneline = p.GetString('\n', false);
00250 if (oneline.size() == 0)
00251 break;
00252 Util::StringParser line = Util::StringParser(oneline);
00253 int teamnr = line.GetInt(',');
00254 if (teamnr == -1)
00255 {
00256 mGlobalStats->unjudged = line.GetInt(',');
00257 mGlobalStats->positive = line.GetInt(',');
00258 mGlobalStats->negative = line.GetInt(',');
00259 mGlobalStats->timeSinceStart = line.GetDouble(',');
00260 mGlobalStats->contestActive = line.GetInt(',');
00261 mGlobalStats->totalRelevantShots = line.GetInt(',');
00262
00263 ILOG_DEBUG("Global: " << mGlobalStats->unjudged << " unjudged, " << mGlobalStats->positive << " positive, " << mGlobalStats->negative << ". contest runs for " << mGlobalStats->timeSinceStart);
00264
00265 if (!mGlobalStats->contestActive) {
00266 mStats.clear();
00267 }
00268 }
00269 else
00270 {
00271 StatsPacket *t = GetStats(teamnr);
00272 if (!t)
00273 {
00274 t = new StatsPacket();
00275 mStats[teamnr] = t;
00276 }
00277 t->unjudged = line.GetInt(',');
00278 t->positive = line.GetInt(',');
00279 t->negative = line.GetInt(',');
00280 ILOG_DEBUG(" TEAM: " << teamnr << " - pos=" << t->positive << " - neg=" << t->negative);
00281 }
00282 }
00283 }
00284
00285 private:
00286 std::string mVidolServer;
00287 std::string mSecretPassword;
00288 int mVidolPort;
00289 TCPSocket *mSocket;
00290 bool mConnected;
00291 queue <ShotPacket*> mShotQueue;
00292
00293 GlobalStats *mGlobalStats;
00294 map <int, StatsPacket*> mStats;
00295
00296 ILOG_VAR_DEC;
00297 };
00298
00299 ILOG_VAR_INIT(ServerConnector, Application.Videolympics);
00300
00301
00302 }
00303 }
00304 }
00305
00306 #endif