diff options
Diffstat (limited to 'manager.cpp')
-rw-r--r-- | manager.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/manager.cpp b/manager.cpp new file mode 100644 index 0000000..1d9bf96 --- /dev/null +++ b/manager.cpp @@ -0,0 +1,199 @@ +#include <iostream> +#include <iomanip> +#include <sstream> +#include <vector> +#include <string> +#include <numeric> +#include <exception> +#include <cstring> +#include <dirent.h> +#include <sys/stat.h> +#include "common.h" //for NPLAYERS + +using namespace std; + +const int NMATCHES=10,TIMEOUT=30000; + +const char *ignoredfiles[]={"caiaio","caiaio.exe","manager","manager.exe","referee","referee.exe","competition.sh","playerlogs","refereelogs","javascript"}; +const int nignoredfiles=sizeof(ignoredfiles)/sizeof(ignoredfiles[0]); + + +vector<string> findplayers(void){ + vector<string> fnames; + DIR *dir; + struct dirent *ent; + int i; + if((dir=opendir("."))==NULL){ + perror("opendir"); + exit(1); + } + while((ent=readdir(dir))!=NULL){ + for(i=0;i<nignoredfiles;i++){ + if(strcmp(ignoredfiles[i],ent->d_name)==0)break; + } + if(i<nignoredfiles)continue; + fnames.push_back(ent->d_name); + } + closedir(dir); + return fnames; +} + +vector<string> parseplayers(const char *arg){ + vector<string> fnames; + const char *found; + int idx,cursor=0; + while(true){ + found=strchr(arg+cursor,','); + if(found==NULL){ + if(arg[cursor]!='\0')fnames.push_back(arg+cursor); + break; + } + idx=found-arg; + fnames.push_back(string(arg+cursor,idx-cursor)); + cursor=idx+1; + } + return fnames; +} + +template <typename T> +class Combinations{ + vector<T> v; + int N; +public: + template <typename U> + class Combination_it{ + const vector<U> v; + const unsigned int vsz; + int N; //-1 means end iterator + vector<unsigned int> indices; + public: + Combination_it(void):vsz(0),N(-1){} + Combination_it(vector<U> &_v,int _N):v(_v),vsz(v.size()),N(_N){ + indices.resize(N); + for(int i=0;i<N;i++)indices[i]=i; + } + + /*bool operator==(const Combination_it &other){ + return other.N==N&&other.indices==indices; + }*/ + bool operator!=(const Combination_it &other){ + return N==other.N?false:indices!=other.indices; + } + + Combination_it& operator++(void){ //prefix increment + int i; + bool foundequal; + bool seen[vsz]; + do { + for(i=N-1;i>=0;i--){ + if(++indices[i]<vsz)break; + indices[i]=0; + } + if(i==-1){ + N=-1; //end + break; + } + memset(seen,0,vsz*sizeof(bool)); + foundequal=false; + for(i=0;i<N;i++){ + if(seen[indices[i]]){ + foundequal=true; + break; + } + seen[indices[i]]=true; + } + } while(foundequal); + return *this; + } + + vector<U> operator*(void){ //dereference, get value of iterator + vector<U> res; + if(N<0)throw invalid_argument("Combinations::end iterator dereference"); + res.reserve(N); + for(int idx : indices)res.push_back(v[idx]); + return res; + } + }; + + Combinations(vector<T> &_v,int _N):v(_v),N(_N){} + + Combination_it<T> begin(void){return Combination_it<T>(v,N);} + + Combination_it<T> end(void){return Combination_it<T>();} +}; + +//returns {scores,statuses} +pair<vector<int>,vector<string>> playmatch(const vector<string> &fnames,int matchidx){ + const int np=fnames.size(); + int i,j; + cout<<"I number_players "<<np<<endl; + for(i=0;i<np;i++){ + cout<<"I player "<<i+1<<' '<<fnames[i]<<' '<<TIMEOUT<<" playerlogs/" + <<fnames[i]<<'.'<<i+1; + for(j=0;j<np;j++)if(j!=i)cout<<'.'<<fnames[j]; + cout<<'.'<<matchidx<<".log"<<endl; + } + for(i=0;i<np;i++)cout<<"I start "<<i+1<<endl; + cout<<"I referee referee refereelogs/"<<fnames[0]; + for(i=1;i<np;i++)cout<<'-'<<fnames[i]; + cout<<'.'<<matchidx<<".log"<<endl; + string report; + getline(cin,report); + if(!cin)exit(1); + for(i=0;i<np;i++)cout<<"I kill "<<i+1<<endl; + cout<<"I kill_referee"<<endl; + //cerr<<"M:: report="<<report<<endl; + stringstream ss(report); + vector<int> res; + res.resize(np); + for(i=0;i<np;i++)ss>>res[i]; + vector<string> statuses; + statuses.resize(np); + for(i=0;i<np;i++)ss>>statuses[i]; + return make_pair(res,statuses); +} + +int main(int argc,char **argv){ + vector<string> fnames; + if(argc==1)fnames=findplayers(); + else fnames=parseplayers(argv[1]); + struct stat statbuf; + for(unsigned int i=0;i<fnames.size();i++){ + if(stat(fnames[i].c_str(),&statbuf)==-1||!(statbuf.st_mode&S_IXUSR)){ + cerr<<"Not using '"<<fnames[i]<<"' because non-existent or non-executable"<<endl; + fnames.erase(fnames.begin()+i); + i--; + continue; + } + } + const int nfn=fnames.size(); + if(nfn<NPLAYERS){ + cerr<<"Not enough players for a "<<NPLAYERS<<"-player competition!"<<endl; + return 1; + } + int scoretbl[nfn]; + memset(scoretbl,0,nfn*sizeof(int)); + vector<int> playeridcs; + playeridcs.resize(nfn); + iota(playeridcs.begin(),playeridcs.end(),0); + int i,j; + for(const vector<int> indices : Combinations<int>(playeridcs,NPLAYERS)){ + vector<string> players; + players.reserve(NPLAYERS); + for(i=0;i<NPLAYERS;i++)players.push_back(fnames[indices[i]]); + cerr<<"M: Starting "<<players<<endl; + for(i=0;i<NMATCHES;i++){ + const pair<vector<int>,vector<string>> res=playmatch(players,i+1); + for(j=0;j<NPLAYERS;j++)scoretbl[indices[j]]+=res.first[j]; + cerr<<"M: Score "<<res.first<<", "<<res.second<<endl; + } + } + vector<pair<string,int>> ranking; + ranking.reserve(nfn); + for(i=0;i<nfn;i++)ranking.push_back(make_pair(fnames[i],scoretbl[i])); + sort(ranking.begin(),ranking.end(),[](const pair<string,int> &a,const pair<string,int> &b) ->bool{return a.second>b.second;}); + for(i=0;i<nfn;i++){ + cerr<<setw(8)<<right<<ranking[i].second<<' '<<ranking[i].first<<endl; + } + cout<<"I stop_caiaio"<<endl; +} |