lamoule.cpp

Go to the documentation of this file.
00001 /*
00002 #########################################################################
00003 #
00004 #  This file is part of trustyRC.
00005 #
00006 #  trustyRC, fully modular IRC robot 
00007 #  Copyright (C) 2006-2008 Nicoleau Fabien 
00008 #
00009 #  trustyRC is free software: you can redistribute it and/or modify
00010 #  it under the terms of the GNU General Public License as published by
00011 #  the Free Software Foundation, either version 3 of the License, or
00012 #  (at your option) any later version.
00013 #
00014 #  trustyRC is distributed in the hope that it will be useful,
00015 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 #  GNU General Public License for more details.
00018 #
00019 #  You should have received a copy of the GNU General Public License
00020 #  along with trustyRC.  If not, see <http://www.gnu.org/licenses/>.
00021 #
00022 #########################################################################
00023 */
00024 
00029 #include "lamoule.h"
00030 
00034 Lamoule::Lamoule(BotKernel*b)
00035 {
00036         this->author = "eponyme";
00037         this->description = "ladder lamoule";
00038         this->version = VERSION;
00039         this->name = "lamoule";
00040         this->bindFunction("lamoule",IN_COMMAND_HANDLER,"lamoule",0,10);
00041         this->bindFunction("topshot",IN_COMMAND_HANDLER,"topshot",0,10);
00042         this->bindFunction("top5",IN_COMMAND_HANDLER,"top5",0,10);
00043         this->bindFunction("player",IN_COMMAND_HANDLER,"player",0,10);
00044         this->bindFunction("deleteplayer",IN_COMMAND_HANDLER,"deleteplayer",0,10);
00045         this->bindFunction("toptotal",IN_COMMAND_HANDLER,"toptotal",0,10);
00046         this->bindFunction("nextscore",IN_COMMAND_HANDLER,"nextscore",0,10);
00047         this->bindFunction("increase",IN_COMMAND_HANDLER,"increase",0,10);
00048         this->bindFunction("3600",IN_LOOP,"purifyFile",0,10);
00049    this->addRequirement("admin");
00050    this->addRequirement("usersinfos");
00051 
00052    this->nextScore = 0 ;
00053    this->MAX_SCORE=1000;
00054    this->FIRST_FLOOR = 250 ;
00055    this->SECOND_FLOOR  = 800 ;
00056    this->doc = new TiXmlDocument(b->getDatasDir()+"lamoule.xml");
00057    if ( this->doc->LoadFile() ) {
00058       this->root = this->doc->FirstChild();
00059    }
00060    else {
00061       this->initFile();
00062    }
00063 }
00064 
00068 void Lamoule::initFile()
00069 {
00070    TiXmlElement born("trustyrc_lamoule_ladder");
00071    this->doc->InsertEndChild(born);
00072    this->root = this->doc->FirstChild();
00073    TiXmlElement ladderNode( "ladder" );
00074    this->root->InsertEndChild(ladderNode);
00075 
00076    TiXmlElement topNode("topshot" );
00077         topNode.SetAttribute( "nick","" );
00078         topNode.SetAttribute( "score", "0" );
00079    topNode.SetAttribute( "date", "" );
00080    this->root->InsertEndChild(topNode);
00081    
00082    this->doc->SaveFile();
00083 }
00084 
00089 vector<string> Lamoule::getTopShot()
00090 {
00091    vector<string> back;
00092    TiXmlHandle docHandle (this->doc);
00093    TiXmlElement*elem = docHandle.FirstChild("trustyrc_lamoule_ladder").FirstChild("topshot").Element();
00094    if ( elem ) {
00095       back.push_back(elem->Attribute("nick"));
00096       back.push_back(elem->Attribute("score"));
00097       back.push_back(elem->Attribute("date"));
00098    }
00099    return back;
00100 }
00101 
00108 void Lamoule::setTopShot(string nick,string score,string date)
00109 {
00110    TiXmlHandle docHandle (this->doc);
00111    TiXmlElement*elem = docHandle.FirstChild("trustyrc_lamoule_ladder").FirstChild("topshot").Element();
00112    if ( elem ) {
00113       elem->SetAttribute("nick",nick);
00114       elem->SetAttribute("score",score);
00115       elem->SetAttribute("date",date);
00116       this->doc->SaveFile();
00117    }
00118 }
00119 
00125 void Lamoule::addPlayer(string nick,unsigned int initialScore)
00126 {
00127    time_t now;
00128    time(&now);
00129    TiXmlElement newNode("player");
00130    newNode.SetAttribute("nick",nick);
00131    newNode.SetAttribute("total",Tools::intToStr(initialScore));
00132    newNode.SetAttribute("nbLamoule","1");
00133    newNode.SetAttribute("lastLamoule",Tools::intToStr(int(now)));
00134    this->root->FirstChild("ladder")->InsertEndChild(newNode);
00135    this->doc->SaveFile();
00136 }
00137 
00143 int Lamoule::generateScore() {
00144    int score;
00145    if ( this->nextScore != 0 ) {
00146       score = this->nextScore;
00147       this->nextScore = 0 ;
00148    }
00149    else {
00150       score = Tools::random(0,this->MAX_SCORE);
00151       if ( score >= this->SECOND_FLOOR ) {
00152          score = Tools::random(0,score) ;
00153          if ( score >= this->SECOND_FLOOR ) {
00154             score = Tools::random(0,score) ;
00155          }
00156       }
00157       else if ((score >= this->FIRST_FLOOR) && (score < this->SECOND_FLOOR)) {
00158          score = Tools::random(0,score) ;
00159       }
00160    }
00161    return score;
00162 }
00163 
00172 char Lamoule::increaseScore(string nick,int score,unsigned int diffAttempts,bool checkTop)
00173 {
00174    time_t now;
00175    time(&now);
00176         char timeFormat[17];
00177    bool found = false;
00178    for(TiXmlElement*child = this->root->FirstChild("ladder")->FirstChildElement(); child!=0; child=child->NextSiblingElement()) {
00179       if ( Tools::to_lower(child->Attribute("nick")) == Tools::to_lower(nick) ) {
00180          found = true ;
00181          if (difftime(now,Tools::strToInt(child->Attribute("lastLamoule"))) > diffAttempts) {
00182             child->SetAttribute("total",(int)(Tools::strToDouble(child->Attribute("total"))+score));
00183             child->SetAttribute("nbLamoule",Tools::strToInt(child->Attribute("nbLamoule"))+1);
00184             child->SetAttribute("lastLamoule",now);
00185             this->doc->SaveFile();         
00186          } 
00187          else {
00188             return '\0';
00189          }
00190          break;
00191       }
00192    }
00193    if (!found) {
00194       this->addPlayer(nick,score);
00195    }
00196    if ( checkTop ) {
00197       if ( score > Tools::strToInt(this->getTopShot()[1]) ) {
00198          strftime(timeFormat,18,"%y-%m-%d %X",localtime(&now));
00199          this->setTopShot(nick,Tools::intToStr(score),timeFormat);
00200          return 't';
00201       }
00202    }
00203    return 'o';
00204 }
00205 
00213 vector<TiXmlElement *> Lamoule::sort(sort_criterion criterion,int min_attempts)
00214 {
00215    vector<TiXmlElement *> vecBack;
00216    vector<TiXmlElement*>::iterator it;
00217    vecBack.clear();
00218    bool inserted;
00219    double tempXML,tempVEC;
00220    for(TiXmlElement*child = this->root->FirstChild("ladder")->FirstChildElement(); child!=0; child=child->NextSiblingElement()) {
00221       inserted = false;
00222       if ( Tools::strToInt(child->Attribute("nbLamoule")) >= min_attempts ) {
00223          if ( vecBack.empty() ) {
00224             vecBack.push_back(child);   
00225          }
00226          else {
00227             for (it = vecBack.begin();it != vecBack.end();it++) {
00228                if (criterion == AVERAGE) {
00229                   tempXML = Tools::strToDouble(child->Attribute("total")) / Tools::strToDouble(child->Attribute("nbLamoule")) ;
00230                   tempVEC = Tools::strToDouble((*it)->Attribute("total")) / Tools::strToDouble((*it)->Attribute("nbLamoule")) ;
00231                   if ( (tempXML >= tempVEC)  ) {
00232                      vecBack.insert(it,child);
00233                      inserted = true;
00234                      break;
00235                   }
00236                }
00237                else if ( criterion == TOTAL ) {
00238                   tempXML = Tools::strToDouble(child->Attribute("total")) ;
00239                   tempVEC = Tools::strToDouble((*it)->Attribute("total")) ;
00240                   if ( (tempXML >= tempVEC) ) {
00241                      vecBack.insert(it,child);
00242                      inserted = true;
00243                      break;
00244                   }
00245                }
00246             }
00247             if ( ! inserted ) {
00248                vecBack.push_back(child);                  
00249             }         
00250          }
00251       }
00252    }
00253    return vecBack;
00254 }
00255 
00262 vector<string> Lamoule::get5first(sort_criterion criterion,int min_attempts)
00263 {
00264    vector<string> back;
00265    vector<TiXmlElement *> vecElems ;
00266    unsigned int i;
00267    vecElems.clear();
00268    back.clear();
00269    string nbPlayers;
00270    vecElems = this->sort(criterion,min_attempts);
00271         nbPlayers = Tools::intToStr(vecElems.size());
00272    i = 0 ;
00273    while ((i < 5) && (i < vecElems.size()))
00274    {  
00275       back.push_back("("+Tools::intToStr(i+1)+"/"+nbPlayers+") " + ""+string(vecElems[i]->Attribute("nick")) + " => average:" + Tools::doubleToStr(Tools::strToDouble(string(vecElems[i]->Attribute("total")))/Tools::strToDouble(string(vecElems[i]->Attribute("nbLamoule")))) + " total:" + string(vecElems[i]->Attribute("total"))+"" );
00276       i++;
00277    }
00278    return back ;
00279 }
00280 
00292 vector<string> Lamoule::getInfosPlayer(string nick,int min_attempts)
00293 {
00294    vector<TiXmlElement *> vecElems ;
00295    vector<string> back;
00296    vecElems.clear();
00297         bool found = false;
00298    vecElems = this->sort(AVERAGE,min_attempts);
00299    unsigned int i ;
00300    for (i=0  ; i < vecElems.size() ; i ++ ) {
00301                 if ( Tools::to_lower(vecElems[i]->Attribute("nick")) == Tools::to_lower(nick) )
00302                 {
00303                         found = true;
00304                         break;
00305                 }
00306    }
00307    for(TiXmlElement*child = this->root->FirstChild("ladder")->FirstChildElement(); child!=0; child=child->NextSiblingElement()) {
00308       if ( Tools::to_lower(child->Attribute("nick")) == Tools::to_lower(nick) ) {
00309          back.push_back(child->Attribute("total"));
00310          back.push_back(child->Attribute("nbLamoule")) ;
00311          back.push_back(Tools::doubleToStr(double(Tools::strToDouble(child->Attribute("total")) / Tools::strToDouble(child->Attribute("nbLamoule")))));
00312          back.push_back(child->Attribute("lastLamoule")) ;
00313          if (found) {
00314             back.push_back(Tools::intToStr(i+1));
00315          }
00316          else {
00317             back.push_back("-");
00318          }
00319          break;
00320       }
00321    }
00322    return back ;
00323 }
00324 
00330 bool Lamoule::deletePlayer(string nick)
00331 {
00332    for(TiXmlElement*child = this->root->FirstChild("ladder")->FirstChildElement(); child!=0; child=child->NextSiblingElement()) {
00333       if ( Tools::to_lower(child->Attribute("nick")) == Tools::to_lower(nick) ) {
00334          child->Parent()->RemoveChild(child) ;
00335          this->doc->SaveFile();
00336          return true;
00337       }
00338    }
00339    return false;
00340 }
00341 
00346 void Lamoule::purifyFile(int reset_time) 
00347 {
00348    time_t now;
00349    time(&now);
00350    for(TiXmlElement*child = this->root->FirstChild("ladder")->FirstChildElement(); child!=0; child=child->NextSiblingElement()) {
00351       if ( difftime(now,Tools::strToInt(child->Attribute("lastLamoule"))) >= reset_time ) {
00352          child->Parent()->RemoveChild(child) ;
00353       }
00354    }
00355    this->doc->SaveFile();
00356 }
00357 
00362 bool Lamoule::setNextScore(int score) 
00363 {
00364    if ( score < this->MAX_SCORE ) {
00365       this->nextScore = score;
00366       return true;
00367    }
00368    else {
00369       return false;
00370    }
00371 }
00372 
00373 extern "C"
00374 {
00375         Plugin *contruct_lamoule(BotKernel*b)
00376         {
00377                 return new Lamoule(b);
00378         }
00379         void destroy_lamoule(Plugin*p)
00380         {
00381                 delete p;
00382         }
00383         bool lamoule (Message*m,Plugin*p,BotKernel*b)
00384         {
00385       vector<string*> list,chanUsers;
00386       map<string,Channel*>::iterator fter ;
00387       map<string,Channel*>* users;
00388       string nick="";
00389       pPlugin * ppUI = b->getPlugin("usersinfos");
00390       Lamoule*lm=  (Lamoule*)p;
00391       UsersInfos*ui = NULL;
00392       int rdm,rdm2 ;
00393       string message,bonus;
00394       char back;
00395       if (m->isPublic()) {
00396          rdm = lm->generateScore() ;
00397          string lamoule = "la mou" ;
00398          for (int i = 0; i < (rdm/10) ; i ++)  {
00399             lamoule += "u" ;
00400          }
00401          lamoule += "le !!!" ;
00402          rdm2 = Tools::random(0,50) ;
00403          switch (rdm2 ) {
00404             case 1 : if ( ppUI != NULL ) {
00405                         ui=(UsersInfos*)ppUI->object;
00406                         users = ui->getUsers();
00407                         fter = users->find(m->getSource());
00408                         if ( fter != users->end() ) {
00409                            chanUsers = ((Channel*)fter->second)->getUsers();
00410                            if ( chanUsers.size() > 0 )  {
00411                               nick = chanUsers[Tools::random(0,chanUsers.size()-1)][0];
00412                            }
00413                            else {
00414                               nick = m->getNickSender();
00415                            }
00416                         }
00417                      }
00418                      if ( nick == m->getNickSender() )  {
00419                         bonus = " ("+nick+" cratered. : 0)";
00420                         rdm = 0;
00421                      }
00422                      else {
00423                         bonus = " (railed by "+nick+" : -100)" ;
00424                         rdm -= 100 ;
00425                         if ( rdm < 0 ) {
00426                            rdm = 0 ;
00427                         }
00428                      }
00429             break;
00430             case 2 : if ( ppUI != NULL ) {
00431                         ui=(UsersInfos*)ppUI->object;
00432                         users = ui->getUsers();
00433                         fter = users->find(m->getSource());
00434                         if ( fter != users->end() ) {
00435                            chanUsers = ((Channel*)fter->second)->getUsers();
00436                            if ( chanUsers.size() > 0 )  {
00437                               nick = chanUsers[Tools::random(0,chanUsers.size()-1)][0];
00438                            }
00439                            else {
00440                               nick = m->getNickSender();
00441                            }
00442                         }
00443                      }
00444                      if ( nick == m->getNickSender() )  {
00445                         bonus = " ("+nick+" killed himself. : 0)";
00446                      }
00447                      else {
00448                         bonus = " (pummeled by "+nick+" : 0)";
00449                      }   
00450                      rdm = 0 ;
00451             break ;
00452             case 3 : bonus = " (MH taken !!! : +100)" ;
00453                      rdm += 100 ;
00454                      if ( rdm >= 1000 ) {
00455                         rdm = 950 ;
00456                      }
00457             break;
00458             case 4 : bonus = " (YA taken !!! : +50)" ;
00459                      rdm += 50 ;
00460                      if ( rdm >= 1000 ) {
00461                         rdm = 950 ;
00462                      }
00463             break;
00464             case 5 : bonus = " (RA taken !!! : +100)" ;
00465                      rdm += 100 ;
00466                      if ( rdm >= 1000 ) {
00467                         rdm = 950 ;
00468                      }
00469             break;
00470             default : bonus = "";
00471          }  
00472          back = lm->increaseScore(m->getNickSender(),rdm,Tools::strToInt(b->getCONFF()->getValue(p->getName()+".diff_attempts")),true);
00473          if (back!='\0') {
00474             message = lamoule+", "+ Tools::intToStr(rdm) + " pour " +m->getNickSender()+""+bonus;
00475             if ( back == 't' ) {
00476                message += " (TOPSHOT !!!)";
00477             }
00478             b->send(IRCProtocol::sendMsg(m->getSource(),message));
00479          }    
00480          else  {  
00481              b->send(IRCProtocol::sendNotice(m->getNickSender(),"A lamoule every "+b->getCONFF()->getValue(p->getName()+".diff_attempts")+" seconds " + m->getNickSender() +""));
00482          }
00483       }
00484                 return true;
00485         }
00486         bool topshot (Message*m,Plugin*p,BotKernel*b) {
00487       Lamoule*lm=  (Lamoule*)p;
00488       vector<string> back;
00489       if (m->isPublic()) {
00490          back = lm->getTopShot();
00491          b->send(IRCProtocol::sendMsg(m->getSource(),"* Topshot by " + back[0] + " : " + back[1] + " on " +back[2] +" *"));
00492       }
00493       return true;
00494    }
00495         bool nextscore (Message*m,Plugin*p,BotKernel*b) {
00496       pPlugin * ppAdm = b->getPlugin("admin");
00497       Lamoule*lm=  (Lamoule*)p;
00498       Admin*adm = NULL;
00499       if (ppAdm!=NULL) {
00500          adm = (Admin*)ppAdm->object ;
00501          if (m->isPublic() && adm->isSuperAdmin(m->getSender()) && (m->nbParts()==5)) {
00502             if (lm->setNextScore(Tools::strToInt(m->getPart(4))) ) {
00503                b->send(IRCProtocol::sendNotice(m->getNickSender(),"Done." ));
00504             }
00505             else {
00506                b->send(IRCProtocol::sendNotice(m->getNickSender(),"Not done." ));
00507             }
00508          }
00509       }
00510       return true;
00511    }
00512         bool increase (Message*m,Plugin*p,BotKernel*b) {
00513       pPlugin * ppAdm = b->getPlugin("admin");
00514       Lamoule*lm=  (Lamoule*)p;
00515       Admin*adm = NULL;
00516       if (ppAdm!=NULL) {
00517          adm = (Admin*)ppAdm->object ;
00518          if (m->isPublic() && adm->isSuperAdmin(m->getSender()) && (m->nbParts()==6)) {
00519             if (lm->increaseScore(m->getPart(4),Tools::strToInt(m->getPart(5)),0,false) == 'o' ) {
00520                b->send(IRCProtocol::sendNotice(m->getNickSender(),"done." ));
00521             }
00522             else {
00523                b->send(IRCProtocol::sendNotice(m->getNickSender(),"not done." ));
00524             }
00525          }
00526       }
00527       return true;
00528    }
00529         bool player (Message*m,Plugin*p,BotKernel*b) {
00530       time_t now;
00531       time(&now);
00532       vector<string> infos;
00533       Lamoule*lm=  (Lamoule*)p;
00534       if ( m->isPublic() && (m->nbParts()==5) ) {
00535          infos = lm->getInfosPlayer(m->getPart(4),Tools::strToInt(b->getCONFF()->getValue(p->getName()+".min_attempts"))) ;
00536          if ( infos.size() > 0 ) {
00537             b->send(IRCProtocol::sendMsg(m->getSource(),"* "+m->getPart(4)+" => total:" + infos[0]+ " shots:" + infos[1]+ " average:"+infos[2]+ " rank:"+infos[4]+ " reset:"+ Tools::doubleToStr((Tools::strToDouble(b->getCONFF()->getValue(p->getName()+".reset_time")) - difftime(now,Tools::strToInt(infos[3])))/3600) + "H *") ) ;
00538          }
00539          else {
00540             b->send(IRCProtocol::sendMsg(m->getSource(),"* Non existent nick *") ) ;
00541          }
00542       }
00543       return true;
00544    }
00545         bool deleteplayer (Message*m,Plugin*p,BotKernel*b) {
00546       pPlugin * ppAdm = b->getPlugin("admin");
00547       Lamoule*lm=  (Lamoule*)p;
00548       Admin*adm = NULL;
00549       if (ppAdm!=NULL) {
00550          adm = (Admin*)ppAdm->object ;
00551          if ( m->isPublic() && (m->nbParts()==5) && adm->isSuperAdmin(m->getSender()) ) {
00552             if (lm->deletePlayer(m->getPart(4)) ) {
00553                b->send(IRCProtocol::sendNotice(m->getNickSender(),"Done." ));
00554             }
00555             else {
00556                b->send(IRCProtocol::sendNotice(m->getNickSender(),"Not done." ));
00557             }
00558          }
00559       }
00560       return true;
00561    }
00562         bool top5 (Message*m,Plugin*p,BotKernel*b) {
00563       vector<string> back;
00564       Lamoule*lm=  (Lamoule*)p;
00565       if (m->isPublic())
00566       {
00567          back =lm->get5first(AVERAGE,Tools::strToInt(b->getCONFF()->getValue(p->getName()+".min_attempts")));
00568          for (unsigned int i = 0 ; i < back.size() ; i ++ ) {
00569             b->send(IRCProtocol::sendMsg(m->getSource(),back[i] ));
00570          }
00571       }
00572       return true;
00573    }
00574         bool toptotal (Message*m,Plugin*p,BotKernel*b) {
00575       vector<string> back;
00576       Lamoule*lm=  (Lamoule*)p;
00577       if (m->isPublic())
00578       {
00579          back =lm->get5first(TOTAL,Tools::strToInt(b->getCONFF()->getValue(p->getName()+".min_attempts")));
00580          for (unsigned int i = 0 ; i < back.size() ; i ++ ) {
00581             b->send(IRCProtocol::sendMsg(m->getSource(),back[i] ));
00582          }
00583       }
00584       return true;
00585    }
00586    bool purifyFile (Message*m,Plugin*p,BotKernel*b) {
00587       Lamoule*lm=  (Lamoule*)p;
00588       lm->purifyFile(Tools::strToInt(b->getCONFF()->getValue(p->getName()+".reset_time")));
00589       return true;
00590    }
00591 }

Generated on Sun Aug 16 15:28:28 2009 for trustyRC by  doxygen 1.5.8