summaryrefslogtreecommitdiff
path: root/manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'manager.cpp')
-rw-r--r--manager.cpp199
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;
+}