msl2008.cpp

00001 
00002 /***************************************************************************
00003  *  msl2008.cpp - Fawkes mid-size refbox 2008 protocol repeater
00004  *
00005  *  Created: Wed Apr 09 10:38:16 2008
00006  *  Copyright  2008  Stefan Schiffer [stefanschiffer.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include <tools/refboxrep/msl2008.h>
00024 #include <netcomm/socket/datagram_multicast.h>
00025 
00026 #include <cstring>
00027 #include <cstdio>
00028 #include <unistd.h>
00029 #include <iostream>
00030 #include <sstream>
00031 #include <string>
00032 
00033 #include <libxml++/libxml++.h>
00034 
00035 using namespace fawkes;
00036 using namespace xmlpp;
00037 
00038 
00039 // REFBOX_CODES //////////////////////////
00040 
00041 static const std::string REFBOX_EVENT               = "RefboxEvent";
00042 static const std::string REFBOX_GAMEINFO            = "GameInfo";
00043 static const std::string REFBOX_EVENT_REFEREE       = "Referee";
00044 static const std::string REFBOX_EVENT_TEAMSETUP     = "TeamSetup";
00045 
00046 static const std::string REFBOX_CANCEL              = "Cancel";
00047 
00048 static const std::string REFBOX_GAMESTART           = "GameStart";
00049 static const std::string REFBOX_GAMESTOP            = "GameStop";
00050 
00051 static const std::string REFBOX_STAGE_CHANGED       = "StageChanged";
00052 static const std::string REFBOX_STAGETYPE_PREGAME    = "preGame";
00053 static const std::string REFBOX_STAGETYPE_FIRSTHALF  = "firstHalf";
00054 static const std::string REFBOX_STAGETYPE_HALFTIME   = "halfTime";
00055 static const std::string REFBOX_STAGETYPE_SECONDHALF = "secondHalf";
00056 static const std::string REFBOX_STAGETYPE_SHOOTOUT   = "shootOut";
00057 static const std::string REFBOX_STAGETYPE_ENDGAME    = "endGame";
00058 
00059 static const std::string REFBOX_GOAL_AWARDED        = "GoalAwarded";
00060 static const std::string REFBOX_GOAL_REMOVED        = "GoalRemoved";
00061 
00062 static const std::string REFBOX_CARD_AWARDED        = "CardAwarded";
00063 static const std::string REFBOX_CARD_REMOVED        = "CardRemoved";
00064 
00065 static const std::string REFBOX_SUBSTITUTION        = "Substitution";
00066 static const std::string REFBOX_PLAYER_OUT          = "PlayerOut";
00067 static const std::string REFBOX_PLAYER_IN           = "PlayerIn";
00068 
00069 static const std::string REFBOX_DROPPEDBALL         = "DroppedBall";
00070 static const std::string REFBOX_KICKOFF             = "KickOff";
00071 static const std::string REFBOX_FREEKICK            = "FreeKick";
00072 static const std::string REFBOX_GOALKICK            = "GoalKick";
00073 static const std::string REFBOX_THROWIN             = "ThrowIn";
00074 static const std::string REFBOX_CORNER              = "Corner";
00075 static const std::string REFBOX_PENALTY             = "Penalty";
00076 
00077 static const std::string REFBOX_TEAMCOLOR_CYAN       = "Cyan";
00078 static const std::string REFBOX_TEAMCOLOR_MAGENTA    = "Magenta";
00079 
00080 static const std::string REFBOX_GOALCOLOR_YELLOW     = "yellow";
00081 static const std::string REFBOX_GOALCOLOR_BLUE       = "blue";
00082 
00083 static const std::string REFBOX_CARDCOLOR_YELLOW     = "yellow";
00084 static const std::string REFBOX_CARDCOLOR_RED        = "red";
00085 
00086 
00087 /** @class Msl2008RefBoxRepeater <tools/refboxrep/msl2008.h>
00088  * Mid-size league refbox repeater.
00089  * This class will communicate with the mid-size league refbox and derive matching
00090  * game states from the communiation stream and send this via the world info.
00091  * @author Stefan Schiffer
00092  */
00093 
00094 /** Constructor.
00095  * @param rss refbox state sender
00096  * @param refbox_host refbox host
00097  * @param refbox_port refbox port
00098  */
00099 Msl2008RefBoxRepeater::Msl2008RefBoxRepeater(RefBoxStateSender &rss,
00100                                              const char *refbox_host,
00101                                              unsigned short int refbox_port)
00102   : __rss(rss)
00103 {
00104   __quit = false;
00105   __s = NULL;
00106   __score_cyan = __score_magenta = 0;
00107 
00108   __refbox_host = strdup(refbox_host);
00109   __refbox_port = refbox_port;
00110 
00111   reconnect();
00112 }
00113 
00114 
00115 /** Destructor. */
00116 Msl2008RefBoxRepeater::~Msl2008RefBoxRepeater()
00117 {
00118   free(__refbox_host);
00119   __s->close();
00120   delete __s;
00121 }
00122 
00123 
00124 /** Reconnect to refbox. */
00125 void
00126 Msl2008RefBoxRepeater::reconnect()
00127 {
00128   if ( __s ) {
00129     __s->close();
00130     delete __s;
00131   }
00132   printf("Trying to connect to refbox at %s:%u\n", __refbox_host, __refbox_port);
00133   do {
00134     try {
00135       printf("Creating MulticastDatagramSocket\n");
00136       __s = new MulticastDatagramSocket(__refbox_host, __refbox_port, 2.3);
00137       //printf("set loop\n");
00138       __s->set_loop(true); // (re)receive locally sent stuff
00139       //printf("bind\n");
00140       __s->bind();
00141       //printf("bind done\n");
00142 
00143       // printf("check for data availability ...\n");
00144       // if ( !__s->available() ) {
00145       //   printf("... nothing to receive\n");
00146       // } else {
00147       //   printf("... data is available!\n");
00148       // }
00149 
00150     } catch (Exception &e) {
00151       delete __s;
00152       __s = NULL;
00153       printf(".");
00154       fflush(stdout);
00155       usleep(500000);
00156     }
00157   } while ( ! __s );
00158 }
00159 
00160 
00161 /** Process received string. */
00162 void
00163 Msl2008RefBoxRepeater::process_string(char *buf, size_t len)
00164 {
00165   printf("Received\n *****\n %s \n *****\n", buf);
00166 
00167   std::istringstream iss( std::string(buf), std::istringstream::in);
00168 
00169   dom = new DomParser();
00170   //dom->set_validate();
00171   dom->set_substitute_entities();
00172   dom->parse_stream(iss);
00173   root = dom->get_document()->get_root_node();
00174 
00175   //printf( " root node:\n%s\n", root->get_name().data() );
00176 
00177   const Element * el = dynamic_cast<const Element *>(root);
00178 
00179   if ( el ) {
00180     /// valid element
00181     //printf("Is valid Element\n");
00182     printf("root-element name is '%s'\n", el->get_name().data() );
00183 
00184     const Node::NodeList nl = el->get_children();
00185 
00186     if( nl.size() == 0 ) {
00187       printf("root has NO children!\n");
00188     }
00189     else {
00190       //printf("root has %u children!\n", nl.size());
00191 
00192       for (Node::NodeList::const_iterator it = nl.begin(); it != nl.end(); ++it) {
00193         const Node* node = *it;
00194         printf("1st level child name is '%s'\n", node->get_name().data() );
00195 
00196         //if( node->get_name().data() == REFBOX_GAMEINFO ) {
00197         //
00198         //}
00199         //else if( node->get_name().data() == REFBOX_EVENT ) {
00200         //
00201         //}
00202         //else {
00203         //  printf(" unhandled RefboxMessage-type '%s'!\n", node->get_name().data() );
00204         //}
00205         
00206         const Node::NodeList cnl = node->get_children();
00207 
00208         if( cnl.size() == 0 ) {
00209           printf("child has NO children!\n");
00210         }
00211         else {
00212           //printf("child has %u children!\n", nl.size());
00213           
00214           for (Node::NodeList::const_iterator cit = cnl.begin(); cit != cnl.end(); ++cit) {
00215             const Node*  cnode = *cit;
00216             const Element* cel = dynamic_cast<const Element *>(cnode);
00217             std::string cnodename(cnode->get_name().data());
00218 
00219             printf("2nd level child name is '%s'\n", cnode->get_name().data() );
00220 
00221             const Attribute* cattr;
00222             std::string cteamcolor;
00223             //std::string cgoalcolor;
00224             //std::string ccardcolor;
00225             std::string cstagetype;
00226 
00227             if( cnodename == REFBOX_KICKOFF      || cnodename == REFBOX_FREEKICK     ||
00228                 cnodename == REFBOX_GOALKICK     || cnodename == REFBOX_THROWIN      ||
00229                 cnodename == REFBOX_CORNER       || cnodename == REFBOX_PENALTY      ||
00230                 cnodename == REFBOX_GOAL_AWARDED || cnodename == REFBOX_GOAL_REMOVED ||
00231                 cnodename == REFBOX_CARD_AWARDED || cnodename == REFBOX_CARD_REMOVED ||         
00232                 cnodename == REFBOX_PLAYER_OUT   || cnodename == REFBOX_PLAYER_IN    ||
00233                 cnodename == REFBOX_SUBSTITUTION ) 
00234               {
00235                 cattr = cel->get_attribute("team");
00236                 cteamcolor = std::string( cattr->get_value().data() );
00237               }
00238 
00239             if( cnodename == REFBOX_CANCEL ) {
00240               // refbox canceled last command
00241               printf("RefBox cancelled last command\n");
00242             }
00243             else if( cnodename == REFBOX_GAMESTOP ) {
00244               __rss.set_gamestate(GS_FROZEN, TEAM_BOTH);
00245             }
00246             else if( cnodename == REFBOX_GAMESTART ) {
00247               __rss.set_gamestate(GS_PLAY, TEAM_BOTH);
00248             }
00249             else if( cnodename == REFBOX_DROPPEDBALL ) {
00250               __rss.set_gamestate(GS_DROP_BALL, TEAM_BOTH);
00251             }
00252             else if( cnodename == REFBOX_GOAL_AWARDED ) {
00253               // increment according to color
00254               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00255                 __rss.set_score(++__score_cyan, __score_magenta);
00256               } 
00257               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00258                 __rss.set_score(__score_cyan, ++__score_magenta);
00259               }
00260               __rss.set_gamestate(GS_FROZEN, TEAM_BOTH);
00261             }
00262             else if( cnodename == REFBOX_KICKOFF ) {
00263               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00264                 __rss.set_gamestate(GS_KICK_OFF, TEAM_CYAN);
00265               } 
00266               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00267                 __rss.set_gamestate(GS_KICK_OFF, TEAM_MAGENTA);
00268               }
00269             }
00270             else if( cnodename == REFBOX_PENALTY ) {
00271               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00272                 __rss.set_gamestate(GS_PENALTY, TEAM_CYAN);
00273               } 
00274               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00275                 __rss.set_gamestate(GS_PENALTY, TEAM_MAGENTA);
00276               }
00277             }
00278             else if( cnodename == REFBOX_CORNER ) {
00279               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00280                 __rss.set_gamestate(GS_CORNER_KICK, TEAM_CYAN);
00281               } 
00282               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00283                 __rss.set_gamestate(GS_CORNER_KICK, TEAM_MAGENTA);
00284               }
00285             }
00286             else if( cnodename == REFBOX_THROWIN ) {
00287               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00288                 __rss.set_gamestate(GS_THROW_IN, TEAM_CYAN);
00289               } 
00290               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00291                 __rss.set_gamestate(GS_THROW_IN, TEAM_MAGENTA);
00292               }
00293             }
00294             else if( cnodename == REFBOX_FREEKICK ) {
00295               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00296                 __rss.set_gamestate(GS_FREE_KICK, TEAM_CYAN);
00297               } 
00298               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00299                 __rss.set_gamestate(GS_FREE_KICK, TEAM_MAGENTA);
00300               }
00301             }
00302             else if( cnodename == REFBOX_GOALKICK ) {
00303               if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
00304                 __rss.set_gamestate(GS_GOAL_KICK, TEAM_CYAN);
00305               } 
00306               else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
00307                 __rss.set_gamestate(GS_GOAL_KICK, TEAM_MAGENTA);
00308               }
00309             }
00310             else if( cnodename == REFBOX_STAGE_CHANGED ) {
00311               cattr = cel->get_attribute("newStage");
00312               cstagetype = std::string( cattr->get_value().data() );
00313               if( cstagetype == REFBOX_STAGETYPE_PREGAME ) {
00314                 //
00315               } else if( cstagetype == REFBOX_STAGETYPE_FIRSTHALF ) {
00316                 __rss.set_half(HALF_FIRST);
00317               } else if( cstagetype == REFBOX_STAGETYPE_HALFTIME ) {
00318                 __rss.set_gamestate(GS_HALF_TIME, TEAM_BOTH);
00319               } else if( cstagetype == REFBOX_STAGETYPE_SECONDHALF ) {
00320                 __rss.set_half(HALF_SECOND);
00321               } else if( cstagetype == REFBOX_STAGETYPE_SHOOTOUT ) {
00322                 //
00323               } else if( cstagetype == REFBOX_STAGETYPE_ENDGAME ) {
00324                 //
00325               }
00326 
00327             }
00328 
00329           } // end-for "child-node children list iteration"
00330         } // end-if "child-node has children"
00331       } // end-for "root children list iteration"
00332     } // end-if "root has children"
00333   }
00334   else {
00335     // throw RefBoxParserException("root is not an element");
00336     printf("root is NOT a valid element\n");
00337   }
00338 
00339   __rss.send();
00340 }
00341 
00342 
00343 /** Run.
00344  * Reads messages from the network, processes them and calls the refbox state sender.
00345  */
00346 void
00347 Msl2008RefBoxRepeater::run()
00348 {
00349   char tmpbuf[1024];
00350   while ( ! __quit ) {
00351     size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ false);
00352     if ( bytes_read == 0 ) {
00353       // seems that the remote has died, reconnect
00354       printf("Connection died, reconnecting\n");
00355       reconnect();
00356     } else {
00357       tmpbuf[bytes_read] = '\0';
00358       process_string(tmpbuf, bytes_read);
00359     }
00360   }
00361 }

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1