#include "graph.h"
#include "node.h"


void Booster::print_state(){
  for(auto cen: big_vertices){
    int i = 0;
    for(auto ng: cen->neighbors) if(ng->cooperator) i++;
    char s = 'S';
    if(cen->neighbors.size()>2)  s = 'B';
    cout<<s<<":"<<cen->cooperator<<" ("<<i<<","<<cen->compute_payoff(1.2,10)<<") ";
  }
  cout<<endl;
  //for(auto cen: small_vertices){
 //   cout<<"S:"<<cen->cooperator<<" ("<<cen->compute_payoff(1.0,1.0)<<") ";
  //}
 // cout<<endl;
  cout<<"---------\n";
}

void Booster::create_edges(){
  int deg_of_center = setting.bigger_support;
  int cluster_size = deg_of_center*2 - 1;

  for(int a = 0; a < (int)nodes.size(); a++){
    if(a % cluster_size == 0){
      if(a-cluster_size >=0)
        make_edge(nodes[a], nodes[a-cluster_size+2]);
      big_vertices.push_back(nodes[a]);
    }else if(a % cluster_size == 1){
      big_vertices.push_back(nodes[a]);
      make_edge(nodes[a], nodes[a-1]);
    }else if(a % cluster_size == 2){
      make_edge(nodes[a], nodes[a-1]);
      big_vertices.push_back(nodes[a]);

    }else if((a%cluster_size)<= deg_of_center){
      make_edge(nodes[a], nodes[a-(a%cluster_size)]);
    }else{
      make_edge(nodes[a], nodes[a-(a%cluster_size)+1]);
    }

  }

}

void Booster::run(){
  while(!finished_half()){
    for(int a = 0; a < (int)nodes.size(); a++){
      make_step();
    }
    if(setting.get_s() > 5){
      // Lower Bound on the fixation in the strong selection setting, otherwise it takes too long.
      bool good = false, to_change = false;
      double fr;
      for(auto bb: big_vertices){
        if(!bb->cooperator) continue;
        if(bb->neighbors.size() < 10) continue;
        good = true;
        //Compute the bound for the forward ratio.

        for(auto nn: bb->neighbors){
          if(!nn->cooperator) good = false;
        }
        if(good){
          fr = pow(((double)setting.bigger_support),4)/ (double)bb->compute_payoff(setting.get_b(), setting.get_s());
          float f = (float)rand()/(float)RAND_MAX;
          //cout<<fr<<" "<<f<<endl;
          if(f > fr)to_change = true;
          break;
        }
      }
      if(good) for(auto nn: nodes) nn->change(to_change);
    }
  }
}

/*
bool Booster::contains_invincible(){
  for(auto bb: big_vertices){
    if(!bb->cooperator) continue;
    if(bb->compute_payoff(0.0) > (setting.get_b())*(support_small + 2*bridge_vertices + 1)) return true;
  }
  return false;
}

void Booster::run_invincible(){
  while(!finished()){
    for(int a = 0; a < (int)nodes.size(); a++){
      make_step();
    }
    if(contains_invincible()){
      for(auto nn: nodes) nn->change(true);
    }
  }
}
*/

Booster::Booster(Setting st):Graph(st){
  create_vertices();
  create_edges();
}

/*
void Booster::print_name(){
  cout<<"Booster"<<endl;
}
*/


