text:
#include <iostream>
#include <bits/stdc++.h>
#include <vector>
#include <string>
#include <climits>
#include <boost/algorithm/string.hpp>
#include <cmath>

using namespace std;

// valid_move_list(board, vector<pair<int,int>>)
vector<pair<int,int>> dirs = {make_pair(0,-2),make_pair(-1,1),make_pair(-1,-1),make_pair(0,2),make_pair(1,1),make_pair(1,-1)};
pair<int,int> sel_ring = make_pair(-1,-1);
pair<int,int> remove_row_start = make_pair(-1,-1);
pair<int,int> remove_row_end = make_pair(-1,-1);

vector<vector<int>> setMarker(vector<vector<int>> board, int x, int y, int marker){
  board[x][y] = marker;
  return board;
}

bool isValidPoint(vector<vector<int>> board,int col, int row){
  if(row > 19 || row < 0 || col < 0 || col > 10 || board[col][row] == -100)
        return false;
    return true;
}

vector<vector<int>> removeMarker(vector<vector<int>> board, int col, int row){
  board[col][row] = 0;
  return board;
}

vector<vector<int>> flipMarkers(vector<vector<int>> board, int x_init, int y_init, int x_fin, int y_fin){
  int ind = 0;
  for(int i = 0; i < dirs.size(); i++){
    if(dirs[i].first == 0){
      if( x_init == x_fin  && (y_fin - y_init) % dirs[i].second == 0 ){
                ind = i;
                break;
      }
    }
    else if( (x_fin - x_init) / dirs[i].first == (y_fin - y_init) / dirs[i].second){
            ind = i;
            break;
    }
  }
  int temp_x = x_init + dirs[ind].first;
  int temp_y = y_init + dirs[ind].second;
  int k = (y_fin - y_init) / dirs[ind].second;
  for(int l = 1 ; l < k; l++){
    if(board[temp_x][temp_y] == -1)
      board[temp_x][temp_y] = 1;
    else if(board[temp_x][temp_y] == 1)
      board[temp_x][temp_y] = -1;
    temp_x = temp_x + dirs[ind].first;
    temp_y = temp_y + dirs[ind].second;
  }
  return board;
}

vector<vector<int>> moveRing(vector<vector<int>> board,int x_init, int y_init, int x_fin, int y_fin){
  int ring = board[x_init][y_init];
  int marker = (ring == 2) ? 1 : -1;
  board[x_init][y_init] = marker;
  board = flipMarkers(board,x_init,y_init,x_fin,y_fin);
  board[x_fin][y_fin] = ring;
  return board;
}

vector<vector<int>> placeRingAt(vector<vector<int>> board, int x, int y, int id){
  if(id == 0){
    return setMarker(board, x, y, 2);
  }
  else{
    return setMarker(board,x,y,-2);
  }
}

vector<vector<int>> removeRing(vector<vector<int>> board, int x, int y, int id){
  return removeMarker(board,x,y);
}

vector<vector<int>> selectRing(vector<vector<int>> board, int x, int y){
  sel_ring.first = x;
  sel_ring.second = y;
  return board;
}

vector<vector<int>> removeRow(vector<vector<int>> board, int x_init, int y_init, int x_fin, int y_fin){
  int ind = 0;
  for(int i = 0; i < 6; i++){
    if(dirs[i].first == 0){
      if( x_init == x_fin  && (y_fin - y_init) % dirs[i].second == 0 ){
                ind = i;
                break;
      }
    }
    else if((x_fin - x_init) / dirs[i].first == (y_fin - y_init) / dirs[i].second){
    ind = i;
    break;
    }
  }
  int temp_x = x_init;
  int temp_y = y_init;
  int k = (y_fin - y_init) / dirs[ind].second;
  for(int k = 1; k < 4; k++){
    board[temp_x][temp_y] = 0;

    temp_x = temp_x + dirs[ind].first;
    temp_y = temp_y + dirs[ind].second;
  }
  return board;
}

vector<vector<int>> selectRowStart(vector<vector<int>> board, int x, int y){
  remove_row_start.first = x;
  remove_row_start.second = y;
  return board;
}

vector<vector<int>> selectRowEnd(vector<vector<int>> board, int x, int y){
  remove_row_end.first = x;
  remove_row_end.second = y;
  return removeRow(board,remove_row_start.first,remove_row_start.second,remove_row_end.first, remove_row_end.second);
}

vector<vector<int>> execute(vector<vector<int>> board, string cmd,int id);

vector<vector<int>> execute_sequence(vector<vector<int>> board,vector<string> moves,int id){
  vector<string> moves_list = {};
  //cout << "lol" << endl;
  string move;
  for(int i = 0; i < moves.size(); i++){
    move = moves[i];
  //  cout << "move " << move << endl;
    if( i % 3 == 2){
      moves_list.push_back(move);
      string lol;
      for (auto const& s : moves_list) { lol = lol + s + " "; }
    // cout <<"lol :  " << lol << endl;
      board = execute(board,lol.substr(0,lol.length()-1), id);
      moves_list = {};
    }
    else{
      moves_list.push_back(move);
    }
  }
  return board;
}

vector<vector<int>> execute(vector<vector<int>> board, string cmd,int id){
  //vector<vector<int>> temp = board;
  vector<string> moves;
  boost::split(moves, cmd, [](char c){return (c == ' ');});
  if(moves.size() > 3){
    //cout << moves.size() << "moves[0]: " << moves[0] << endl;
    return execute_sequence(board,moves,id);
  }
  string move_type = moves[0];
  int x = stoi(moves[1]);
  int y = stoi(moves[2]);
  //cout << "Error in next funs" << endl;
  if(move_type == "P")
        return placeRingAt(board, x, y, id);
  else if (move_type == "S")
        return selectRing(board, x ,y);
  else if (move_type == "M")
        return moveRing(board,sel_ring.first,sel_ring.second,x,y);
  else if (move_type == "RS")
        return selectRowStart(board, x, y);
  else if (move_type == "RE")
        return selectRowEnd(board, x, y);
  else if (move_type == "X")
        return removeMarker(board, x, y);
  else
    return board;
}

vector<float> CalculateScore(int wRings,int bRings,int wMarkers,int bMarkers, char Error_state){
    vector<int> scores = {0,0};
    vector<float> score = {0.0,0.0};
    if(Error_state == '1'){
      wRings = 0;
      bRings = 3;
    }
    else if(Error_state == '2'){
      bRings = 0;
      wRings = 3;
    }
    if(wRings == 3){
      scores[0] = 10 - bRings;
      scores[1] = bRings;
    }
    else if(bRings == 3){
      scores[0] = wRings;
      scores[1] = 10 - wRings;
    }
    else if(wRings == bRings){
      scores[0] = 5;
      scores[1] = 5;
    }
    else if(wRings - bRings == 2){
      scores[0] = 7;
      scores[1] = 3;
    }
    else if(bRings - wRings == 2){
      scores[0] = 3;
      scores[1] = 7;
    }
    else if(wRings > bRings){
      scores[0] = 6;
      scores[1] = 4;
    }
    else if(bRings > wRings){
      scores[0] = 4;
      scores[1] = 6;
    }
    else{
      scores[0] = -1;
      scores[1] = -1;
    }
    score[0] = scores[0] + ((float) wMarkers)/1000;
    score[1] = scores[1] + ((float) bMarkers)/1000;
    return score;
}

float get_score(vector<vector<int>> board, int p_id, char Error_state = '0'){
  int w_rings = 0;
  int b_rings = 0;
  int w_markers = 0;
  int b_markers = 0;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 19; j++){
      int s = board[i][j];
      if(s == 0 || s == -100){
        continue;
      }
      else if(s == 2){
        w_rings++;
      }
      else if(s == -2){
        b_rings++;
      }
      else if(s == 1){
        w_markers++;
      }
      else if(s == -1){
        b_markers++;
      }
    }
  }
  return CalculateScore(5-w_rings,5-b_rings,w_markers,b_markers,Error_state)[p_id];
}

int lenRowsFormed(vector<vector<int>> board, pair<int,int> dir, int i, int j){
  int row = j + dir.second;
  int col = i + dir.first;
  int marker = 1;
  int len = 1;
  while(row > -1 && row < 19 && col > -1 && col < 19){
    if(board[col][row] == marker){
      len++;
    }
    else{
      break;
    }
  }
  return len;
}

float fun1(vector<vector<int>> board){
  float score = 0.0f;
  int len = 0;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 19; j++){
      if(board[i][j] == 1){
        for(int k = 0 ; k < 6; k++){
          len = lenRowsFormed(board,dirs[k], i, j);
          score += pow(2.0f,len);
        }
      }
    }
  }
  //cout << "Working fine fun1" << endl;
  return score;
}

float fun2(vector<vector<int>> board){
  float score = 0.0f;
  float weight = 0.0f;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 19; j++){
      if(board[i][j] == 2){
        if(i == 5 && j == 9){
          weight = 1000.0f;
        }
        else{
          int l = (i-5 > 0) ? i-5:5-i;
          int m = (j-9 > 0) ? j-9:9-j;
          weight = (100.0f/sqrt(pow((float)l,2) + pow((float)m,2)));
        }
        score += weight;
      }
    }
  }
  return score;
}

int flippedUtil(vector<vector<int>> board, int marker, int ring, pair<int,int> dir, int i, int j){
  int row = i + dir.second;
  int col = j + dir.first;
  int marker_count = 0;
  while (row < 19 && row > -1 && col < 11 && col > -1 && board[col][row] == 0){
        row += dir.second;
        col += dir.first;
      }
  while (row < 19 && row > -1 && col < 11 && col > -1 && board[col][row] != -100){
      if(board[col][row] == marker)
            marker_count += 1;
      else if (board[col][row] == 0)
            return marker_count;
      else if (board[col][row] == -2 || board[col][row] == 2 ){
            return 0;
      }
      row += dir.second;
      col += dir.first;
      }
    return 0;
}

float flippedScore(vector<vector<int>> board, int marker, int ring){
  float flipped_score = 0.0;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 19; j++){
      if(board[i][j] == ring){
        for(int k = 0; j < 6; k++){
          flipped_score += 1.0 * flippedUtil(board, marker, ring, dirs[k], i ,j);
        }
      }
    }
  }
  return flipped_score;
}

int countMarkers(vector<vector<int>> board, int marker){
  int marker_count = 0;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 19; j++){
      if(board[i][j] == marker){
        marker_count++;
      }
    }
  }
  return marker_count;
}

int mobilityUtil(vector<vector<int>> board, int ring, pair<int,int> dir, int i, int j){
  int row = j + dir.second;
  int col = i + dir.first;
  int space_count = 0;
  while (row < 19 && row > -1 && col < 11 && col > -1 && board[col][row] == 0){
        space_count++;
        row += dir.second;
        col += dir.first;
      }
  while (row < 19 && row > -1 && col < 11 && col > -1 && board[col][row] != -100){
      if(board[col][row] == 0)
            return space_count+1;
      else if (board[col][row] == -2 || board[col][row] == 2 )
            return space_count;
        row += dir.second;
        col += dir.first;
      }
  return space_count;
}

float mobilityScore(vector<vector<int>> board, int ring){
  float mobility_score = 0.0;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 19; j++){
      if(board[i][j] == ring){
        for(int k = 0; j < 6; k++){
          mobility_score += 1.0 * mobilityUtil(board,ring, dirs[k], i ,j);
        }
      }
    }
  }
  return mobility_score;
}

float evaluate(vector<vector<int>> board, int current_player){
  //cout << "Before countMarkers white" << endl;
  int num_w_marker = 0;//countMarkers(board,1);
  //cout << "Before countMarkers black" << endl;
  int num_b_marker = 0;//countMarkers(board,-1);

  //  black_row = markerScore(board,-1,-2)
  //  white_row = markerScore(board,1,2)
  //cout << "Before countMarkers " << endl;
  int flip_ring = (current_player == 0) ? 2 : -2;
  //cout << "Before flippedscore white" << endl;
  int flip_white_marker = 0;//flippedScore(board,-1,flip_ring);
  //cout << "Before flippedscore blacks" << endl;
  int flip_black_marker = 0;//flippedScore(board,1,flip_ring);
  //cout << "Before mobilityscore white" << endl;
  int mobility_black_ring = 0;//mobilityScore(board,-2);
  //cout << "Before mobilityscore black" << endl;
  int mobility_white_ring = 0;//mobilityScore(board,2);
  //cout << "Before get_score white" << endl;
  int val1 = fun1(board);
  int val2 = fun2(board);
  int white_score = get_score(board, 0);
  //cout << "Before get_score blacak" << endl;
  int black_score = get_score(board, 1);
  //cout << "after all this time? always" << endl;

  return (num_w_marker +flip_white_marker + mobility_white_ring + white_score) * (0.5 * (1 + white_score)) + (num_b_marker + flip_black_marker + mobility_black_ring + black_score) * (0.5 * (1 + black_score)) + val1 + val2;

}

//valid_moves_list()
// execute()
// rows_formed()
// evaluate()
vector<pair<int,int>> validPointsInARow(vector<vector<int>> board, pair<int,int> point, pair<int,int> dir){
    vector<pair<int,int>> lis;
    int col = point.first + dir.first;
    int row = point.second + dir.second;
    bool no_jump = true;
    bool first_jump = false;
    while(row > -1 && row < 19 && col > -1 && col < 11){
      if(board[col][row] == 2 || board[col][row] == -2){
        return lis;
      }
      else if(board[col][row] == 1 || board[col][row] == -1){
        first_jump = true;
        no_jump = false;
      }
      else if(board[col][row] == 0){
        if(no_jump){
          lis.push_back(make_pair(col,row));
        }
        if(first_jump){
          lis.push_back(make_pair(col,row));
          return lis;
        }
      }
      col += dir.first;
      row += dir.second;
    }
    return lis;
}

vector<pair<int,int>> addList(vector<pair<int,int>> lis1, vector<pair<int,int>> lis2){
  for(auto it = lis2.begin(); it != lis2.end();it++){
    lis1.push_back((*it));
  }
  return lis1;
}

vector<pair<int,int>> valid_moves_list(vector<vector<int>> board, pair<int, int> point){
  vector<pair<int,int>> lis;
  for(int i = 0; i < 6; i++){
    lis = addList(lis,validPointsInARow(board,point,dirs[i]));
  }
  return lis;
}

vector<pair<pair<int,int>,pair<int,int>>> rows_formed(vector<vector<int>> board, int pid){
  vector<vector<int>> temp = board;
  int marker = (pid == 0) ? 1 : -1;
  vector<pair<pair<int,int>,pair<int,int>>> lis;
  for(int i = 0; i < 11; i++){
    for(int j = 0; j < 11; j++){
      if(temp[i][j] != marker){
        continue;
      }
      bool isrow = true;
      for(int k = 1; k < 5; k++){
        if(temp[i][j+k*2] != marker){
          isrow = false;
          break;
        }
      }
      if(!isrow){
        continue;
      }
      lis.push_back(make_pair(make_pair(i,j),make_pair(i,j+8)));
    }
  }
  for(int i = 0; i < 7; i++){
    for(int j = 4; j < 19; j++){
      if(temp[i][j] != marker){
        continue;
      }
      bool isrow = true;
      for(int k = 1; k < 5; k++){
        if(temp[i+k][j-k] != marker){
          isrow = false;
          break;
        }
      }
      if(!isrow){
        continue;
      }
      lis.push_back(make_pair(make_pair(i,j),make_pair(i+4,j-4)));
    }
  }
  for(int i = 0; i < 7; i++){
    for(int j = 0; j < 15; j++){
      if(temp[i][j] != marker){
        continue;
      }
      bool isrow = true;
      for(int k = 1; k < 5; k++){
        if(temp[i][j+k*2] != marker){
          isrow = false;
          break;
        }
      }
      if(!isrow){
        continue;
      }
      lis.push_back(make_pair(make_pair(i,j),make_pair(i+4,j+4)));
    }
  }
  return lis;
}

class Node{
public:
  vector<vector<int>> board;
  string move;
  vector<Node> list_children;
  int won;
  int num_ring;
  int utility;

  Node(vector<vector<int>> b, string m, vector<Node> lis,int rings_num, int w){
    this->board = b;
    this->move = m;
    this->num_ring = rings_num;
    this->list_children = lis;
    this->utility = 0;
    this->won = w;
  }

  void append_children(int num, int player){
    int ring,marker;
    if(num == 0){
      for(int i = 0; i < 11; i++){
        for(int j = 0; j < 19; j++){
          if(board[i][j] == 0){
            string temp_move = "P " + to_string(i) + " " + to_string(j);
            vector<vector<int>> b = this->board;
            vector<vector<int>> temp_board = execute(b,temp_move,player);
            Node a(temp_board,temp_move, {} ,0,0);
            (this->list_children).push_back(a);
          }
        }
      }
    }
    if(num == 1){
      if(player == 0){
        ring = 2;
        marker = 1;
      }
      else{
        ring = -2;
        marker = -1;
      }
      if(won == 0){
        while(rows_formed(board,0).size() != 0){
          vector<pair<pair<int,int>,pair<int,int>>> temp = rows_formed(board,0);
          vector<Node> lol;
          for(int j = 0; j < temp.size(); j++){
            string temp_move = "RS " + to_string(temp[j].first.first) + " " + to_string(temp[j].first.second) + " RE " + to_string(temp[j].second.first) + " " + to_string(temp[j].second.second);
            lol.push_back(Node(execute(board,temp_move,player),temp_move, {}, num_ring, won));
          }
          vector<Node> lol1;
          for(int i = 0; i < lol.size(); i++){
            for(int j = 0; j < 11; j++){
              for(int k = 0; k < 19; k++){
                if(lol1[i].board[j][k] == ring){
                  string temp_move = lol1[i].move + " X " + to_string(j) + " " + to_string(k);
                  int ring_num = num_ring + 1;
                  if(ring_num > 2){
                    lol1.push_back(Node(execute(lol1[i].board,temp_move,player),temp_move, lol1[i].list_children, ring_num, 1));
                  }
                  else{
                    lol1.push_back(Node(execute(lol1[i].board,temp_move,player),temp_move, lol1[i].list_children, ring_num, 0));
                  }
                }
              }
            }
          }
          int max_score = INT_MIN;
          int index = -1;
          Node max_node({},"",{},0,0);

          for(int i = 0; i < lol1.size(); i++){
            int score = evaluate(lol1[i].board, 0);
            if(score > max_score){
              max_score = score;
              max_node = lol1[i];
              index = i;
            }
          }
          this->board = lol1[index].board;
          this->move = lol1[index].move;
          this->won = lol1[index].won;
          this->num_ring = lol1[index].num_ring;
          this->list_children = lol1[index].list_children;
        }
        if(rows_formed(board,0).size() == 0){
          for(int i = 0; i < 11; i++){
            for(int j = 0; j < 19; j++){
              if(board[i][j] == ring){
                vector<pair<int, int>> moves_list = valid_moves_list(board,make_pair(i,j));
                for(int k = 0; k < moves_list.size(); k++){
                  string temp_move = "S " + to_string(i) + " " + to_string(j) + " M " + to_string(moves_list[k].first) + " " + to_string(moves_list[k].second);
                   list_children.push_back(Node(execute(board,temp_move,player), temp_move, {}, num_ring, won));
                }
              }
            }
          }
          vector<Node>::iterator it;
          for(it = list_children.begin(); it != list_children.end(); it++){
            if(rows_formed((*it).board,0).size() != 0 || rows_formed((*it).board,1).size() != 0){
              if(won == 0){
                it = list_children.erase(it);
                --it;
                vector<pair<pair<int,int>,pair<int,int>>> temp_rows = rows_formed(board,0);
                vector<Node> temp;
                for(int j = 0; j < temp_rows.size();j++){
                  string temp_move = (*it).move + " RS " + to_string(temp_rows[j].first.first) + " " + to_string(temp_rows[j].first.second) + " RE " + to_string(temp_rows[j].second.first) + " "  + to_string(temp_rows[j].second.second);
                  temp.push_back(Node(execute((*it).board, temp_move, player), temp_move, (*it).list_children, (*it).num_ring, (*it).won));
                }
                vector<Node> temp1;
                for(int j = 0; j < temp.size(); j++){
                  for(int k = 0; k < 11; k++){
                    for(int l = 0; l < 19; l++){
                      if(temp[j].board[k][l] == ring){
                        string temp_move = temp[j].move + " X " +to_string(k) + " " + to_string(l);
                        int rings_num = temp[j].num_ring + 1;
                        if(rings_num > 2){
                          temp1.push_back(Node(execute(temp[j].board, temp_move, player), temp_move, temp[j].list_children, rings_num, 1));
                        }
                        else{
                          temp1.push_back(Node(execute(temp[j].board, temp_move, player), temp_move, temp[j].list_children, rings_num, 0));
                        }
                      }
                    }
                  }
                }
                vector<Node>:: iterator it1;
                for(it1 = temp1.begin(); it1 != temp1.end(); it1++){
                  list_children.push_back((*it1));
                }
              }
            }
          }
        }
      }
    }
  }
};

Node get_tree(int num,vector<vector<int>> b, int num_moves){
  Node root = Node(b, " ", {}, 0, 0);
  if(num == 0){
    root.append_children(num, 0);
    for(auto it = root.list_children.begin(); it != root.list_children.end(); it++){
      (*it).append_children(num,1);
    //  for(auto jt = (*it).list_children.begin(); jt != (*it).list_children.end(); jt++){
    //    (*jt).append_children(num,0);
    //  }
    }
    return root;
  }
  if(num == 1){
    if(num_moves < 30){
      root.append_children(num,0);
      for(auto it = root.list_children.begin(); it != root.list_children.end(); it++){
        (*it).append_children(num,1);
      // for(auto jt = (*it).list_children.begin(); jt != (*it).list_children.end(); jt++){
      //    (*jt).append_children(num,0);
        //}
      }
    }
    else{
      root.append_children(num,0);
      for(auto it = root.list_children.begin(); it != root.list_children.end(); it++){
        (*it).append_children(num,1);
        for(auto jt = (*it).list_children.begin(); jt != (*it).list_children.end(); jt++){
          (*jt).append_children(num,0);
          //for(auto kt = (*jt).list_children.begin(); kt != (*jt).list_children.end(); kt++){
            //(*kt).append_children(num,1);
            //for(auto lt = (*kt).list_children.begin(); lt != (*kt).list_children.end(); lt++){
            //  (*lt).append_children(num,0);
            //}
          //}
        }
      }
    }
    return root;
  }
  return root;
}
int max_val(Node node, int alpha, int beta, int player);

int min_val(Node node, int alpha, int beta, int player){
//  cout << "In min : size of children " << node.list_children.size() << endl;
  if(node.list_children.size() == 0){
  //  cout << "before evaluate " << endl;
    node.utility = evaluate(node.board, player);
  //  cout << "after evaluate " << endl;
    return node.utility;
  }

  int value = INT_MAX;

  vector<Node> children = node.list_children;

  for(auto it = children.begin(); it != children.end(); it++){
    //cout << "move " << (*it).move << endl;
    Node child = *it;
    value = min(value, max_val(child,alpha,beta, 1-player));
  //  cout << "value " << value << "alpha "<< alpha <<endl;
    if(value <= alpha){
      return value;
    }
    beta = min(beta, value);
  }
  return value;
}

int max_val(Node node, int alpha, int beta, int player){
//  cout << "In max " << node.move << endl;
  if(node.list_children.size() == 0){
    node.utility = evaluate(node.board, player);
    return node.utility;
  }

  int value = INT_MIN;

  vector<Node> children = node.list_children;

  for(auto it = children.begin(); it != children.end(); it++){
    Node child = *it;
    value = max(value, min_val(child,alpha,beta, 1-player));
  //  cout << "value " << value << "beta "<< beta <<endl;
    if(value >= beta){
      return value;
    }
    alpha = max(alpha, value);
  }
  return value;
}

Node main_minimax(Node node){
  int best_val = INT_MIN;
  int beta = INT_MAX;

  vector<Node> children = node.list_children;
  Node best_child({},"",{},0,0);
  for(auto it = children.begin(); it != children.end(); it++){
    //cout <<"size of children  "<< children.size() << endl;
    //cout << "size of list_children " << node.list_children.size() << endl;
    //cout << "In main minimax "<<(*child).move << endl;
    Node child = *it;
    int value = max_val(child,best_val,beta, 0);
  //  cout << "after max_val in main minmax" << endl;
    if(value > best_val){
      best_val = value;
      best_child.board = child.board;
      best_child.move = child.move;
      best_child.list_children = child.list_children;
      best_child.won = child.won;
    }
  }
  //cout << best_child.move << endl;
  return best_child;
}

string minimax(int num_moves, vector<vector<int>> b){
  //cout << "In minimax" << endl;
  Node tree({},"",{},0,0);
  if(num_moves < 5){
    tree = get_tree(0,b,num_moves);
    //cout << "get_tree working" << endl;
  }
  else{
    tree = get_tree(1,b,num_moves);
  }
  //for(auto it = tree.list_children.begin(); it != tree.list_children.end();it++){
  //  cout << (*it).move << endl;
  //}
  Node child = main_minimax(tree);
  return child.move;
}

pair<int,int> null = make_pair(-10,-10);
vector<vector<pair<int,int>>> b_to_h = {{null, null, null, null, null, null, make_pair(5,24), null, make_pair(5,23), null, make_pair(5,22), null, make_pair(5,21), null, null, null, null, null, null}, {null, null, null, make_pair(5,26), null, make_pair(4,20), null, make_pair(4,19), null, make_pair(4,18), null, make_pair(4,17), null, make_pair(4,16), null, make_pair(5,19), null, null, null}, {null, null, make_pair(5,27), null, make_pair(4,21), null, make_pair(3,15), null, make_pair(3,14), null, make_pair(3,13), null, make_pair(3,12), null, make_pair(4,15), null, make_pair(5,18), null, null}, {null, make_pair(5,28), null, make_pair(4,22), null, make_pair(3,16), null, make_pair(2,10), null, make_pair(2,9), null, make_pair(2,8), null, make_pair(3,11), null, make_pair(4,14), null, make_pair(5,17), null}, {make_pair(5,29), null, make_pair(4,23), null, make_pair(3,17), null, make_pair(2,11), null, make_pair(1,5), null, make_pair(1,4), null, make_pair(2,7), null, make_pair(3,10), null, make_pair(4,13), null, make_pair(5,16)}, {null, make_pair(4,0), null, make_pair(3,0), null, make_pair(2,0), null, make_pair(1,0), null, make_pair(0,0), null, make_pair(1,3), null, make_pair(2,6), null, make_pair(3,9), null, make_pair(4,12), null}, {make_pair(5,1), null, make_pair(4,1), null, make_pair(3,1), null, make_pair(2,1), null, make_pair(1,1), null, make_pair(1,2), null, make_pair(2,5), null, make_pair(3,8), null, make_pair(4,11), null, make_pair(5,14)}, {null, make_pair(5,2), null, make_pair(4,2), null, make_pair(3,2), null, make_pair(2,2), null, make_pair(2,3), null, make_pair(2,4), null, make_pair(3,7), null, make_pair(4,10), null, make_pair(5,13), null}, {null, null, make_pair(5,3), null, make_pair(4,3), null, make_pair(3,3), null, make_pair(3,4), null, make_pair(3,5), null, make_pair(3,6), null, make_pair(4,9), null, make_pair(5,12), null, null}, {null, null, null, make_pair(5,4), null, make_pair(4,4), null, make_pair(4,5), null, make_pair(4,6), null, make_pair(4,7), null, make_pair(4,8), null, make_pair(5,11), null, null, null}, {null, null, null, null, null, null, make_pair(5,6), null, make_pair(5,7), null, make_pair(5,8), null, make_pair(5,9), null, null, null, null, null, null}};

vector<vector<pair<int,int>>> h_to_b = {{make_pair(5,9)},{make_pair(5,7),make_pair(6,8),make_pair(6,10),make_pair(5,11),make_pair(4,10),make_pair(4,8)},{make_pair(5,5),make_pair(6,6),make_pair(7,7),make_pair(7,9),make_pair(7,11),make_pair(6,12),make_pair(5,13),make_pair(4,12),make_pair(3,11),make_pair(3,9),make_pair(3,7),make_pair(4,6)},{make_pair(5,3),make_pair(6,4),make_pair(7,5),make_pair(8,6),make_pair(8,8),make_pair(8,10),make_pair(8,12),make_pair(7,13),make_pair(6,14),make_pair(5,15),make_pair(4,14),make_pair(3,13),make_pair(2,12),make_pair(2,10),make_pair(2,8),make_pair(2,6),make_pair(3,5),make_pair(4,4)},{make_pair(5,1),make_pair(6,2),make_pair(7,3),make_pair(8,4),make_pair(9,5),make_pair(9,7),make_pair(9,9),make_pair(9,11),make_pair(9,13),make_pair(8,14),make_pair(7,15),make_pair(6,16),make_pair(5,17),make_pair(4,16),make_pair(3,15),make_pair(2,14),make_pair(1,13),make_pair(1,11),make_pair(1,9),make_pair(1,7),make_pair(1,5),make_pair(2,4),make_pair(3,3),make_pair(4,2)},{null,make_pair(6,0),make_pair(7,1),make_pair(8,2),make_pair(9,3),null,make_pair(10,6),make_pair(10,8),make_pair(10,10),make_pair(10,12),null,make_pair(9,15),make_pair(8,16),make_pair(7,17),make_pair(6,18),null,make_pair(4,18),make_pair(3,17),make_pair(2,16),make_pair(1,15),null,make_pair(0,12),make_pair(0,10),make_pair(0,8),make_pair(0,6),null,make_pair(1,3),make_pair(2,2),make_pair(3,1),make_pair(4,0)}};

string get_board_move(string move){
  vector<string> results = {};
  boost::split(results, move, [](char c){return (c == ' ');});
  vector<string> finals = {};
  int turn = results.size();
  int i = 0;
  while(turn > 0){
    if(i % 3 == 0){
      finals.push_back(results[i]);
      i++;
      turn--;
    }
    else{
      pair<int,int> points = h_to_b[stoi(results[i])][stoi(results[i+1])];
      finals.push_back(to_string(points.first));
      finals.push_back(to_string(points.second));
      i += 2;
      turn -= 2;
    }
  }
//  string result = "";
//  for(int i = 0; i < finals.size(); i++){
    //cout << "results[i] " << results[i] << endl;
//    result = result + finals[i] + " ";
//  }
  string result;
  for (auto const& s : finals) { result = result + s + " "; };
  return result.substr(0, result.length() - 1);
}

string get_hex_move(string move){
  vector<string> results = {};
  boost::split(results, move, [](char c){return (c == ' ');});
  vector<string> finals = {};
  int turn = results.size();
  int i = 0;
  while(turn > 0){
    if(i % 3 == 0){
      finals.push_back(results[i]);
      i++;
      turn--;
    }
    else{
      pair<int,int> points = b_to_h[stoi(results[i])][stoi(results[i+1])];
      finals.push_back(to_string(points.first));
      finals.push_back(to_string(points.second));
      i += 2;
      turn -= 2;
    }
  }
  string result;
  for (auto const& s : finals) { result = result + s + " "; }
  return result.substr(0,result.length() -1);
}

void print(vector<vector<int>> board){
  for(int i = 0; i < 19; i++){
    for(int j = 0; j < 11; j++){
      if(board[j][i] == -100){
          cout <<"*" <<"\t";
      }
      else{
        cout << board[j][i] << "\t";
      }
    }
    cout << "\n";
  }
  cout <<"\n--------------------------------------------\n";
}

int main(){
  vector<vector<int>> board;
  vector<int> column;
  for(int i = 0; i < 11; i++){
    column = {};
    for(int j = 0; j < 19; j++){
      column.push_back(-100);
    }
    board.push_back(column);
  }

  for(auto i = h_to_b.begin(); i != h_to_b.end(); i++){
    for(auto j = (*i).begin(); j != (*i).end(); j++){
      if((*j) != null){
        board[(*j).first][(*j).second] = 0;
      }
    }
  }
//  print(board);
  int num_moves = 0;
  int flag = 0;
  int current_player, board_size, time_limit;
  string data;
  cin >> current_player >> board_size >> time_limit;
  cin.ignore();
    //boost::split(res, move, [](char c){return (c == ' ');});

  int player = current_player -1;
  string op_move;
  while(true){
    if((flag == 0) && (player == 0)){
      string my_move = "P 5 9\n" ;
      board = execute(board,my_move, 0);
  //    print(board);
      num_moves++;
      flag = 1;
      cout << "P 0 0" << endl;
    }
    else{
      getline(cin,op_move);
      //cout << "op_move " << op_move << endl;
      op_move = get_board_move(op_move);
      //cout << "op_move " << op_move << endl;
    // cout << "\n";
      board = execute(board,op_move,1);
    //  cout << "opponent" << endl;
    //  print(board);
      string my_move = minimax(num_moves,board);
    //  cout << "my" << endl;
      board = execute(board,my_move, 0);
      my_move = get_hex_move(my_move);
    //  print(board);
      num_moves += 1;
      cout << my_move << endl;
    }
  }
  return 0;
}


text:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <boost/tokenizer.hpp>

void string_to_vector ( const std::string & input , std::vector<std::string> & words ) {
   boost::tokenizer<> tok( input ) ;
   for ( boost::tokenizer<>::iterator beg = tok.begin( ) ; beg != tok.end( ) ; ++beg )
      words.push_back( *beg ) ;
}

int main( ) {
   std::string startphrase ( "rosetta code phrase reversal" ) ;
   std::cout << "Input : " << startphrase << '\n' ;
   std::string local_copy ( startphrase ) ;
   std::reverse ( local_copy.begin( ) , local_copy.end( ) ) ;
   std::cout << "Input reversed : " << local_copy << '\n' ;
   std::vector<std::string> words ;
   string_to_vector ( startphrase , words ) ;
   //copy the vector with the original words to reverse their order later
   std::vector<std::string> original_words ( words ) ;
   //reverse each word in the string
   std::cout << "Each word reversed : " ;
   for ( std::string word : words ) {
      std::reverse ( word.begin( ) , word.end( ) ) ;
      std::cout << word << " " ;
   }
   std::cout << '\n' ;
   std::cout << "Original word order reversed : " ;
   for ( std::vector<std::string>::const_reverse_iterator cri = original_words.rbegin( ) ;
	 cri != original_words.rend( ) ; cri++ ) {
      std::cout << *cri << " " ;
   }
   std::cout << '\n' ;
   return 0 ;
}

ext: cpp

max_stars_repo_name: djgoku/RosettaCodeData

max_issues_repo_name: djgoku/RosettaCodeData

max_forks_repo_name: djgoku/RosettaCodeData


text:
#include "../include/kotek_file.h"
#include "../include/kotek_main_manager.h"
#include "../include/kotek_std.h"
#include <boost/test/unit_test.hpp>

namespace Kotek
{
	namespace Core
	{
		void RegisterTests_Filesystem_ForModule_Core(void)
		{
#ifdef KOTEK_USE_TESTS
			KOTEK_MESSAGE("registered!");
#endif
		}

#ifdef KOTEK_USE_TESTS
	#ifdef KOTEK_DEBUG
		BOOST_AUTO_TEST_CASE(filesystem_check_folder_tests_for_existance)
		{
			ktkFileSystem instance;

			instance.Initialize();

			bool status = instance.IsValidPath(instance.GetFolderByEnum(
				folder_index_t::kFolderIndex_UserTests));

			BOOST_REQUIRE(status);

			instance.Shutdown();
		}

		BOOST_AUTO_TEST_CASE(file_create_pretty_output)
		{
			ktkFileSystem fs;

			fs.Initialize();

			ktkFile instance("pretty");

			ktk::string path =
				fs.GetFolderByEnum(folder_index_t::kFolderIndex_UserTests);

			ktk::string test(KOTEK_TEXT("いくつか"));

			instance.Write("test_field1", "data");
			instance.Write("test_field2", "data2");
			instance.Write<const ktk::string&>("ktk::string", test);

		#ifdef KOTEK_USE_UNICODE
			instance.Write<const ktk::string&>(
				"KOTEK_TEXT", KOTEK_TEXT("いくつか"));
			instance.Write("wchar_t", L"いくつか");
			instance.Write("char8_t", u8"いくつか");
			instance.Write("char16_t", u"いくつか");
			instance.Write("char32_t", U"いくつか");
		#endif
			instance.Save(&fs, path);

			bool status = fs.IsValidPath(path);

			BOOST_REQUIRE(status);

			fs.Shutdown();
		}
	#endif
#endif
	} // namespace Core
} // namespace Kotek


text:
// This code is forked from
//   boost_1_67_0/libs/beast/example/http/client/coro/http_client_coro.cpp
// and modified by xhawk18 to use promise-cpp for better async control.
// Copyright (c) 2018, xhawk18
// at gmail.com

// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//

//------------------------------------------------------------------------------
//
// Example: HTTP client, asynchronous with promise-cpp
//
//------------------------------------------------------------------------------

#include <boost/version.hpp>
#if BOOST_VERSION < 106600
#   error "This program need boost 1.66.0 or higher!"
#endif
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <algorithm>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <regex>
#include "add_ons/asio/io.hpp"

using namespace promise;
namespace asio   = boost::asio;
using     tcp    = boost::asio::ip::tcp;
namespace http   = boost::beast::http;
namespace beast  = boost::beast;

//------------------------------------------------------------------------------

//From https://stackoverflow.com/a/11044337
struct Uri
{
public:
    std::string QueryString, Path, Protocol, Host, Port;

    static Uri Parse(const std::string &uri)
    {
        Uri result;

        typedef std::string::const_iterator iterator_t;

        if (uri.length() == 0)
            return result;

        iterator_t uriEnd = uri.end();

        // get query start
        iterator_t queryStart = std::find(uri.begin(), uriEnd, '?');

        // protocol
        iterator_t protocolStart = uri.begin();
        iterator_t protocolEnd = std::find(protocolStart, uriEnd, ':');            //"://");

        if (protocolEnd != uriEnd)
        {
            std::string prot = &*(protocolEnd);
            if ((prot.length() > 3) && (prot.substr(0, 3) == "://"))
            {
                result.Protocol = std::string(protocolStart, protocolEnd);
                protocolEnd += 3;   //      ://
            }
            else
                protocolEnd = uri.begin();  // no protocol
        }
        else
            protocolEnd = uri.begin();  // no protocol

        // host
        iterator_t hostStart = protocolEnd;
        iterator_t pathStart = std::find(hostStart, uriEnd, '/');  // get pathStart

        iterator_t hostEnd = std::find(protocolEnd,
            (pathStart != uriEnd) ? pathStart : queryStart,
            L':');  // check for port

        result.Host = std::string(hostStart, hostEnd);

        // port
        if ((hostEnd != uriEnd) && ((&*(hostEnd))[0] == ':'))  // we have a port
        {
            hostEnd++;
            iterator_t portEnd = (pathStart != uriEnd) ? pathStart : queryStart;
            result.Port = std::string(hostEnd, portEnd);
        }

        // path
        if (pathStart != uriEnd)
            result.Path = std::string(pathStart, queryStart);

        // query
        if (queryStart != uriEnd)
            result.QueryString = std::string(queryStart, uri.end());

        return result;

    }   // Parse
};  // uri

// Performs an HTTP GET and prints the response
Promise do_session(
    std::string const& host,
    std::string const& port,
    std::string const& target,
    int version,
    asio::io_context& ioc) {

    struct Session {
        tcp::resolver resolver_;
        tcp::socket socket_;
        beast::flat_buffer buffer_;
        http::request<http::empty_body> req_;
        http::response<http::string_body> res_;

        explicit Session(asio::io_context& ioc)
            : resolver_(ioc)
            , socket_(ioc) {
        }
    };

    // (Must persist in io_context ioc)
    auto session = std::make_shared<Session>(ioc);

    // Set up an HTTP GET request message
    session->req_.version(version);
    session->req_.method(http::verb::get);
    session->req_.target(target);
    session->req_.set(http::field::host, host);
    session->req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

    //<1> Resolve the host
    return async_resolve(session->resolver_, host, port)

    .then([=](tcp::resolver::results_type &results) {
        //<2> Connect to the host
        return async_connect(session->socket_, results);

    }).then([=]() {
        //<3> Write the request
        return async_write(session->socket_, session->req_);

    }).then([=](size_t bytes_transferred) {
        boost::ignore_unused(bytes_transferred);
        //<4> Read the response
        return async_read(session->socket_, session->buffer_, session->res_);

    }).then([=](size_t bytes_transferred) {
        boost::ignore_unused(bytes_transferred);
        //<5> Write the message to standard out
        std::cout << session->res_ << std::endl;

    }).then([]() {
        //<6> success, return default error_code
        return boost::system::error_code();
    }, [](const boost::system::error_code err) {
        //<6> failed, return the error_code
        return err;

    }).then([=](boost::system::error_code &err) {
        //<7> Gracefully close the socket
        std::cout << "shutdown..." << std::endl;
        session->socket_.shutdown(tcp::socket::shutdown_both, err);
    });
}

Promise download(asio::io_context &ioc, const std::string &url) {
    const Uri &uri = Uri::Parse(url);
    if (uri.Protocol != "http") {
        std::cerr << "Support http protocol only!\n";
        return promise::reject();
    }

    std::string port = (uri.Port.empty() ? "80" : uri.Port);
    std::string target = uri.Path + uri.QueryString;

    std::cout << target << "\n";
    std::cout << port << "\n";
    std::cout << uri.Host << "\n";

    int http_version = 10;
    return do_session(uri.Host, port, target, http_version, ioc);

}

//------------------------------------------------------------------------------

int main(int argc, char** argv) {
    // The io_context is required for all I/O
    asio::io_context ioc;

    // Launch the asynchronous operation
    download(ioc, "http://www.163.com/")
    .then([&]() {
        return download(ioc, "http://baidu.com/");
    }).then([&]() {
        return download(ioc, "http://qq.com");
    }).then([&]() {
        return download(ioc, "http://github.com/xhawk18");
    });

    // Run the I/O service. The call will return when
    // the get operation is complete.
    ioc.run();

    return EXIT_SUCCESS;
}

max_stars_repo_name: GerHobbelt/promise-cpp

max_issues_repo_name: GerHobbelt/promise-cpp

max_forks_repo_name: GerHobbelt/promise-cpp


text:
#include "driver.hpp"
#include <algorithm>
#include <boost/math/constants/constants.hpp>
#include <fstream>

namespace ccalc
{
    namespace mc = boost::math::constants;

    void Driver::parse(std::string filename) {
        std::ifstream file(filename);
        if (!file) {
            std::cerr << "Failed to open file \"" << filename << "\"\n";
            exit(EXIT_FAILURE);
        }
        loc.initialize(&filename);
        parse(file);
        loc.initialize();
    }

    void Driver::endParse() {
        shouldEnd = true;
    }

    void Driver::setMode(Mode m) {
        driverMode = m;
    }

    Mode Driver::getMode() const {
        return driverMode;
    }

    ccalc::location& Driver::getLocation() {
        return loc;
    }

    void ccalc::Driver::setLastResult(const Float& f) {
        lastResult = f;
    }

    Float Driver::getLastResult() const {
        return lastResult;
    }

    void Driver::addVariable(const std::string& name, Float value) {
        variables[name] = value;
    }

    Float Driver::getVariable(const std::string& name) const {
        try {
            const auto p = predefinedVariables.find(name);
            return p != predefinedVariables.end() ? p->second : variables.at(name);
        } catch (const std::out_of_range&) {
            throw UndefinedIdentifier("Variable \"" + name + "\" does not exist.");
        }
    }

    Float Driver::call(const std::string& name, const std::vector<Float>& args) const {
        try {
            return functions.at(name)(args);
        } catch (const std::out_of_range&) {
            throw UndefinedIdentifier("\"" + name + "\" is not a function.");
        }
    }

    void Driver::callSysFunction(const std::string& name, const std::vector<Float>& args) const {
        try {
            sysFunctions.at(name)(args);
        } catch (const std::out_of_range&) {
            throw UndefinedIdentifier("\"" + name + "\" is not a system function.");
        }
    }

    // clang-format off
    const std::unordered_map<std::string, Float> Driver::predefinedVariables = {
        {"pi", mc::pi<Float>()},
        {"e", mc::e<Float>()},
        {"degree", mc::degree<Float>()},
        {"radian", mc::radian<Float>()}
    };

    const std::unordered_map<std::string, std::function<Float(const std::vector<Float>&)>> Driver::functions = {
        {"abs", builtin::abs},
        {"sqrt", builtin::sqrt},
        {"max", builtin::max},
        {"min", builtin::min},
        {"sin", builtin::sin},
        {"cos", builtin::cos},
        {"tan", builtin::tan},
    };

    const std::unordered_map<std::string, std::function<void(const std::vector<Float>&)>> Driver::sysFunctions = {
        {"setPrecision", sys::setPrecision}
    };
    // clang-format on

    // Definition of built-in functions
    namespace builtin
    {
        Float abs(const std::vector<Float>& args) {
            if (args.size() != 1)
                throw InvalidArgument("Function \"abs\" takes exactly 1 argument.");
            return mp::abs(args[0]);
        }

        Float sqrt(const std::vector<Float>& args) {
            if (args.size() != 1)
                throw InvalidArgument("Function \"sqrt\" takes exactly 1 argument.");
            return mp::sqrt(args[0]);
        }

        Float max(const std::vector<Float>& args) {
            if (args.size() < 2)
                throw InvalidArgument("Function \"max\" takes at least 2 arguments.");
            return *std::max_element(args.begin(), args.end());
        }

        Float min(const std::vector<Float>& args) {
            if (args.size() < 2)
                throw InvalidArgument("Function \"min\" takes at least 2 arguments.");
            return *std::min_element(args.begin(), args.end());
        }

        Float sin(const std::vector<Float>& args) {
            if (args.size() != 1)
                throw InvalidArgument("Function \"sin\" takes exactly 1 argument.");
            const ccalc::Float res = mp::sin(args[0]);
            return mp::abs(res) > std::numeric_limits<ccalc::Float>::epsilon() ? res : ccalc::Float(0);
        }

        Float cos(const std::vector<Float>& args) {
            if (args.size() != 1)
                throw InvalidArgument("Function \"cos\" takes exactly 1 argument.");
            const ccalc::Float res = mp::cos(args[0]);
            return mp::abs(res) > std::numeric_limits<ccalc::Float>::epsilon() ? res : ccalc::Float(0);
        }

        Float tan(const std::vector<Float>& args) {
            if (args.size() != 1)
                throw InvalidArgument("Function \"tan\" takes exactly 1 argument.");
            // return mp::tan(args[0]);
            return sin(args) / cos(args);
        }
    } // namespace builtin

    namespace sys
    {
        void setPrecision(const std::vector<Float>& args) {
            if (args.size() != 1)
                throw InvalidArgument("Function \"setPrecision\" takes exactly 1 argument.");
            const int p = static_cast<int>(mp::round(args[0]));
            if (p < 0)
                throw InvalidArgument("setPrecision expects a positive argument or 0 for the maximum number of significant digits");
            std::cout.precision(p);
        }
    } // namespace sys
} // namespace ccalc


text:
//<developer>
//    <name>linapex 曹一峰</name>
//    <email>linapex@163.com</email>
//    <wx>superexc</wx>
//    <qqgroup>128148617</qqgroup>
//    <url>https://jsq.ink</url>
//    <role>pku engineer</role>
//    <date>2019-03-16 19:44:18</date>
//</624457053376614400>

/*
 *@文件
 *@eos/license中定义的版权
 **/

#include <eosio/chain/config.hpp>
#include <eosio/state_history_plugin/state_history_log.hpp>
#include <eosio/state_history_plugin/state_history_serialization.hpp>

#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/host_name.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/signals2/connection.hpp>

using tcp    = boost::asio::ip::tcp;
namespace ws = boost::beast::websocket;

extern const char* const state_history_plugin_abi;

namespace eosio {
using namespace chain;
using boost::signals2::scoped_connection;

static appbase::abstract_plugin& _state_history_plugin = app().register_plugin<state_history_plugin>();

template <typename F>
auto catch_and_log(F f) {
   try {
      return f();
   } catch (const fc::exception& e) {
      elog("${e}", ("e", e.to_detail_string()));
   } catch (const std::exception& e) {
      elog("${e}", ("e", e.what()));
   } catch (...) {
      elog("unknown exception");
   }
}

namespace bio = boost::iostreams;
static bytes zlib_compress_bytes(bytes in) {
   bytes                  out;
   bio::filtering_ostream comp;
   comp.push(bio::zlib_compressor(bio::zlib::default_compression));
   comp.push(bio::back_inserter(out));
   bio::write(comp, in.data(), in.size());
   bio::close(comp);
   return out;
}

struct state_history_plugin_impl : std::enable_shared_from_this<state_history_plugin_impl> {
   chain_plugin*                                        chain_plug = nullptr;
   fc::optional<state_history_log>                      trace_log;
   fc::optional<state_history_log>                      chain_state_log;
   bool                                                 stopping = false;
   fc::optional<scoped_connection>                      applied_transaction_connection;
   fc::optional<scoped_connection>                      accepted_block_connection;
   string                                               endpoint_address = "0.0.0.0";
   uint16_t                                             endpoint_port    = 8080;
   std::unique_ptr<tcp::acceptor>                       acceptor;
   std::map<transaction_id_type, transaction_trace_ptr> cached_traces;
   transaction_trace_ptr                                onblock_trace;

   void get_log_entry(state_history_log& log, uint32_t block_num, fc::optional<bytes>& result) {
      if (block_num < log.begin_block() || block_num >= log.end_block())
         return;
      state_history_log_header header;
      auto&                    stream = log.get_entry(block_num, header);
      uint32_t                 s;
      stream.read((char*)&s, sizeof(s));
      result.emplace();
      result->resize(s);
      if (s)
         stream.read(result->data(), s);
   }

   void get_block(uint32_t block_num, fc::optional<bytes>& result) {
      chain::signed_block_ptr p;
      try {
         p = chain_plug->chain().fetch_block_by_number(block_num);
      } catch (...) {
         return;
      }
      result = fc::raw::pack(*p);
   }

   fc::optional<chain::block_id_type> get_block_id(uint32_t block_num) {
      if (trace_log && block_num >= trace_log->begin_block() && block_num < trace_log->end_block())
         return trace_log->get_block_id(block_num);
      if (chain_state_log && block_num >= chain_state_log->begin_block() && block_num < chain_state_log->end_block())
         return chain_state_log->get_block_id(block_num);
      try {
         auto block = chain_plug->chain().fetch_block_by_number(block_num);
         if (block)
            return block->id();
      } catch (...) {
      }
      return {};
   }

   struct session : std::enable_shared_from_this<session> {
      std::shared_ptr<state_history_plugin_impl> plugin;
      std::unique_ptr<ws::stream<tcp::socket>>   socket_stream;
      bool                                       sending  = false;
      bool                                       sent_abi = false;
      std::vector<std::vector<char>>             send_queue;
      fc::optional<get_blocks_request_v0>        current_request;
      bool                                       need_to_send_update = false;

      session(std::shared_ptr<state_history_plugin_impl> plugin)
          : plugin(std::move(plugin)) {}

      void start(tcp::socket socket) {
         ilog("incoming connection");
         socket_stream = std::make_unique<ws::stream<tcp::socket>>(std::move(socket));
         socket_stream->binary(true);
         socket_stream->next_layer().set_option(boost::asio::ip::tcp::no_delay(true));
         socket_stream->next_layer().set_option(boost::asio::socket_base::send_buffer_size(1024 * 1024));
         socket_stream->next_layer().set_option(boost::asio::socket_base::receive_buffer_size(1024 * 1024));
         socket_stream->async_accept([self = shared_from_this(), this](boost::system::error_code ec) {
            callback(ec, "async_accept", [&] {
               start_read();
               send(state_history_plugin_abi);
            });
         });
      }

      void start_read() {
         auto in_buffer = std::make_shared<boost::beast::flat_buffer>();
         socket_stream->async_read(
             *in_buffer, [self = shared_from_this(), this, in_buffer](boost::system::error_code ec, size_t) {
                callback(ec, "async_read", [&] {
                   auto d = boost::asio::buffer_cast<char const*>(boost::beast::buffers_front(in_buffer->data()));
                   auto s = boost::asio::buffer_size(in_buffer->data());
                   fc::datastream<const char*> ds(d, s);
                   state_request               req;
                   fc::raw::unpack(ds, req);
                   req.visit(*this);
                   start_read();
                });
             });
      }

      void send(const char* s) {
         send_queue.push_back({s, s + strlen(s)});
         send();
      }

      template <typename T>
      void send(T obj) {
         send_queue.push_back(fc::raw::pack(state_result{std::move(obj)}));
         send();
      }

      void send() {
         if (sending)
            return;
         if (send_queue.empty())
            return send_update();
         sending = true;
         socket_stream->binary(sent_abi);
         sent_abi = true;
socket_stream->async_write( //
             boost::asio::buffer(send_queue[0]),
             [self = shared_from_this(), this](boost::system::error_code ec, size_t) {
                callback(ec, "async_write", [&] {
                   send_queue.erase(send_queue.begin());
                   sending = false;
                   send();
                });
             });
      }

      using result_type = void;
      void operator()(get_status_request_v0&) {
         auto&                chain = plugin->chain_plug->chain();
         get_status_result_v0 result;
         result.head              = {chain.head_block_num(), chain.head_block_id()};
         result.last_irreversible = {chain.last_irreversible_block_num(), chain.last_irreversible_block_id()};
         if (plugin->trace_log) {
            result.trace_begin_block = plugin->trace_log->begin_block();
            result.trace_end_block   = plugin->trace_log->end_block();
         }
         if (plugin->chain_state_log) {
            result.chain_state_begin_block = plugin->chain_state_log->begin_block();
            result.chain_state_end_block   = plugin->chain_state_log->end_block();
         }
         send(std::move(result));
      }

      void operator()(get_blocks_request_v0& req) {
         for (auto& cp : req.have_positions) {
            if (req.start_block_num <= cp.block_num)
               continue;
            auto id = plugin->get_block_id(cp.block_num);
            if (!id || *id != cp.block_id)
               req.start_block_num = std::min(req.start_block_num, cp.block_num);
         }
         req.have_positions.clear();
         current_request = req;
         send_update(true);
      }

      void operator()(get_blocks_ack_request_v0& req) {
         if (!current_request)
            return;
         current_request->max_messages_in_flight += req.num_messages;
         send_update();
      }

      void send_update(bool changed = false) {
         if (changed)
            need_to_send_update = true;
         if (!send_queue.empty() || !need_to_send_update || !current_request ||
             !current_request->max_messages_in_flight)
            return;
         auto&                chain = plugin->chain_plug->chain();
         get_blocks_result_v0 result;
         result.head              = {chain.head_block_num(), chain.head_block_id()};
         result.last_irreversible = {chain.last_irreversible_block_num(), chain.last_irreversible_block_id()};
         uint32_t current =
             current_request->irreversible_only ? result.last_irreversible.block_num : result.head.block_num;
         if (current_request->start_block_num <= current &&
             current_request->start_block_num < current_request->end_block_num) {
            auto block_id = plugin->get_block_id(current_request->start_block_num);
            if (block_id) {
               result.this_block  = block_position{current_request->start_block_num, *block_id};
               auto prev_block_id = plugin->get_block_id(current_request->start_block_num - 1);
               if (prev_block_id)
                  result.prev_block = block_position{current_request->start_block_num - 1, *prev_block_id};
               if (current_request->fetch_block)
                  plugin->get_block(current_request->start_block_num, result.block);
               if (current_request->fetch_traces && plugin->trace_log)
                  plugin->get_log_entry(*plugin->trace_log, current_request->start_block_num, result.traces);
               if (current_request->fetch_deltas && plugin->chain_state_log)
                  plugin->get_log_entry(*plugin->chain_state_log, current_request->start_block_num, result.deltas);
            }
            ++current_request->start_block_num;
         }
         send(std::move(result));
         --current_request->max_messages_in_flight;
         need_to_send_update = current_request->start_block_num <= current &&
                               current_request->start_block_num < current_request->end_block_num;
      }

      template <typename F>
      void catch_and_close(F f) {
         try {
            f();
         } catch (const fc::exception& e) {
            elog("${e}", ("e", e.to_detail_string()));
            close();
         } catch (const std::exception& e) {
            elog("${e}", ("e", e.what()));
            close();
         } catch (...) {
            elog("unknown exception");
            close();
         }
      }

      template <typename F>
      void callback(boost::system::error_code ec, const char* what, F f) {
         if (plugin->stopping)
            return;
         if (ec)
            return on_fail(ec, what);
         catch_and_close(f);
      }

      void on_fail(boost::system::error_code ec, const char* what) {
         try {
            elog("${w}: ${m}", ("w", what)("m", ec.message()));
            close();
         } catch (...) {
            elog("uncaught exception on close");
         }
      }

      void close() {
         socket_stream->next_layer().close();
         plugin->sessions.erase(this);
      }
   };
   std::map<session*, std::shared_ptr<session>> sessions;

   void listen() {
      boost::system::error_code ec;

      auto address  = boost::asio::ip::make_address(endpoint_address);
      auto endpoint = tcp::endpoint{address, endpoint_port};
      acceptor      = std::make_unique<tcp::acceptor>(app().get_io_service());

      auto check_ec = [&](const char* what) {
         if (!ec)
            return;
         elog("${w}: ${m}", ("w", what)("m", ec.message()));
         EOS_ASSERT(false, plugin_exception, "unable to open listen socket");
      };

      acceptor->open(endpoint.protocol(), ec);
      check_ec("open");
      acceptor->set_option(boost::asio::socket_base::reuse_address(true));
      acceptor->bind(endpoint, ec);
      check_ec("bind");
      acceptor->listen(boost::asio::socket_base::max_listen_connections, ec);
      check_ec("listen");
      do_accept();
   }

   void do_accept() {
      auto socket = std::make_shared<tcp::socket>(app().get_io_service());
      acceptor->async_accept(*socket, [self = shared_from_this(), socket, this](auto ec) {
         if (stopping)
            return;
         if (ec) {
            if (ec == boost::system::errc::too_many_files_open)
               catch_and_log([&] { do_accept(); });
            return;
         }
         catch_and_log([&] {
            auto s            = std::make_shared<session>(self);
            sessions[s.get()] = s;
            s->start(std::move(*socket));
         });
         catch_and_log([&] { do_accept(); });
      });
   }

   static bool is_onblock(const transaction_trace_ptr& p) {
      if (p->action_traces.size() != 1)
         return false;
      auto& act = p->action_traces[0].act;
      if (act.account != eosio::chain::config::system_account_name || act.name != N(onblock) ||
          act.authorization.size() != 1)
         return false;
      auto& auth = act.authorization[0];
      return auth.actor == eosio::chain::config::system_account_name &&
             auth.permission == eosio::chain::config::active_name;
   }

   void on_applied_transaction(const transaction_trace_ptr& p) {
      if (p->receipt) {
         if (is_onblock(p))
            onblock_trace = p;
         else if (p->failed_dtrx_trace)
            cached_traces[p->failed_dtrx_trace->id] = p;
         else
            cached_traces[p->id] = p;
      }
   }

   void on_accepted_block(const block_state_ptr& block_state) {
      store_traces(block_state);
      store_chain_state(block_state);
      for (auto& s : sessions) {
         auto& p = s.second;
         if (p) {
            if (p->current_request && block_state->block_num < p->current_request->start_block_num)
               p->current_request->start_block_num = block_state->block_num;
            p->send_update(true);
         }
      }
   }

   void store_traces(const block_state_ptr& block_state) {
      if (!trace_log)
         return;
      std::vector<transaction_trace_ptr> traces;
      if (onblock_trace)
         traces.push_back(onblock_trace);
      for (auto& r : block_state->block->transactions) {
         transaction_id_type id;
         if (r.trx.contains<transaction_id_type>())
            id = r.trx.get<transaction_id_type>();
         else
            id = r.trx.get<packed_transaction>().id();
         auto it = cached_traces.find(id);
         EOS_ASSERT(it != cached_traces.end() && it->second->receipt, plugin_exception,
                    "missing trace for transaction ${id}", ("id", id));
         traces.push_back(it->second);
      }
      cached_traces.clear();
      onblock_trace.reset();

      auto& db         = chain_plug->chain().db();
      auto  traces_bin = zlib_compress_bytes(fc::raw::pack(make_history_serial_wrapper(db, traces)));
      EOS_ASSERT(traces_bin.size() == (uint32_t)traces_bin.size(), plugin_exception, "traces is too big");

      state_history_log_header header{.block_num    = block_state->block->block_num(),
                                      .block_id     = block_state->block->id(),
                                      .payload_size = sizeof(uint32_t) + traces_bin.size()};
      trace_log->write_entry(header, block_state->block->previous, [&](auto& stream) {
         uint32_t s = (uint32_t)traces_bin.size();
         stream.write((char*)&s, sizeof(s));
         if (!traces_bin.empty())
            stream.write(traces_bin.data(), traces_bin.size());
      });
   }

   void store_chain_state(const block_state_ptr& block_state) {
      if (!chain_state_log)
         return;
      bool fresh = chain_state_log->begin_block() == chain_state_log->end_block();
      if (fresh)
         ilog("Placing initial state in block ${n}", ("n", block_state->block->block_num()));

      std::vector<table_delta> deltas;
      auto&                    db = chain_plug->chain().db();

      const auto&                                table_id_index = db.get_index<table_id_multi_index>();
      std::map<uint64_t, const table_id_object*> removed_table_id;
      for (auto& rem : table_id_index.stack().back().removed_values)
         removed_table_id[rem.first._id] = &rem.second;

      auto get_table_id = [&](uint64_t tid) -> const table_id_object& {
         auto obj = table_id_index.find(tid);
         if (obj)
            return *obj;
         auto it = removed_table_id.find(tid);
         EOS_ASSERT(it != removed_table_id.end(), chain::plugin_exception, "can not found table id ${tid}",
                    ("tid", tid));
         return *it->second;
      };

      auto pack_row          = [&](auto& row) { return fc::raw::pack(make_history_serial_wrapper(db, row)); };
      auto pack_contract_row = [&](auto& row) {
         return fc::raw::pack(make_history_context_wrapper(db, get_table_id(row.t_id._id), row));
      };

      auto process_table = [&](auto* name, auto& index, auto& pack_row) {
         if (fresh) {
            if (index.indices().empty())
               return;
            deltas.push_back({});
            auto& delta = deltas.back();
            delta.name  = name;
            for (auto& row : index.indices())
               delta.rows.obj.emplace_back(true, pack_row(row));
         } else {
            if (index.stack().empty())
               return;
            auto& undo = index.stack().back();
            if (undo.old_values.empty() && undo.new_ids.empty() && undo.removed_values.empty())
               return;
            deltas.push_back({});
            auto& delta = deltas.back();
            delta.name  = name;
            for (auto& old : undo.old_values) {
               auto& row = index.get(old.first);
               delta.rows.obj.emplace_back(true, pack_row(row));
            }
            for (auto& old : undo.removed_values)
               delta.rows.obj.emplace_back(false, pack_row(old.second));
            for (auto id : undo.new_ids) {
               auto& row = index.get(id);
               delta.rows.obj.emplace_back(true, pack_row(row));
            }
         }
      };

      process_table("account", db.get_index<account_index>(), pack_row);

      process_table("contract_table", db.get_index<table_id_multi_index>(), pack_row);
      process_table("contract_row", db.get_index<key_value_index>(), pack_contract_row);
      process_table("contract_index64", db.get_index<index64_index>(), pack_contract_row);
      process_table("contract_index128", db.get_index<index128_index>(), pack_contract_row);
      process_table("contract_index256", db.get_index<index256_index>(), pack_contract_row);
      process_table("contract_index_double", db.get_index<index_double_index>(), pack_contract_row);
      process_table("contract_index_long_double", db.get_index<index_long_double_index>(), pack_contract_row);

      process_table("global_property", db.get_index<global_property_multi_index>(), pack_row);
      process_table("generated_transaction", db.get_index<generated_transaction_multi_index>(), pack_row);

      process_table("permission", db.get_index<permission_index>(), pack_row);
      process_table("permission_link", db.get_index<permission_link_index>(), pack_row);

      process_table("resource_limits", db.get_index<resource_limits::resource_limits_index>(), pack_row);
      process_table("resource_usage", db.get_index<resource_limits::resource_usage_index>(), pack_row);
      process_table("resource_limits_state", db.get_index<resource_limits::resource_limits_state_index>(), pack_row);
      process_table("resource_limits_config", db.get_index<resource_limits::resource_limits_config_index>(), pack_row);

      auto deltas_bin = zlib_compress_bytes(fc::raw::pack(deltas));
      EOS_ASSERT(deltas_bin.size() == (uint32_t)deltas_bin.size(), plugin_exception, "deltas is too big");
      state_history_log_header header{.block_num    = block_state->block->block_num(),
                                      .block_id     = block_state->block->id(),
                                      .payload_size = sizeof(uint32_t) + deltas_bin.size()};
      chain_state_log->write_entry(header, block_state->block->previous, [&](auto& stream) {
         uint32_t s = (uint32_t)deltas_bin.size();
         stream.write((char*)&s, sizeof(s));
         if (!deltas_bin.empty())
            stream.write(deltas_bin.data(), deltas_bin.size());
      });
} //商店连锁店
};   //状态\历史\插件\执行

state_history_plugin::state_history_plugin()
    : my(std::make_shared<state_history_plugin_impl>()) {}

state_history_plugin::~state_history_plugin() {}

void state_history_plugin::set_program_options(options_description& cli, options_description& cfg) {
   auto options = cfg.add_options();
   options("state-history-dir", bpo::value<bfs::path>()->default_value("state-history"),
           "the location of the state-history directory (absolute path or relative to application data dir)");
   cli.add_options()("delete-state-history", bpo::bool_switch()->default_value(false), "clear state history files");
   options("trace-history", bpo::bool_switch()->default_value(false), "enable trace history");
   options("chain-state-history", bpo::bool_switch()->default_value(false), "enable chain state history");
   options("state-history-endpoint", bpo::value<string>()->default_value("0.0.0.0:8080"),
           "the endpoint upon which to listen for incoming connections");
}

void state_history_plugin::plugin_initialize(const variables_map& options) {
   try {
      EOS_ASSERT(options.at("disable-replay-opts").as<bool>(), plugin_exception,
                 "state_history_plugin requires --disable-replay-opts");

      my->chain_plug = app().find_plugin<chain_plugin>();
      EOS_ASSERT(my->chain_plug, chain::missing_chain_plugin_exception, "");
      auto& chain = my->chain_plug->chain();
      my->applied_transaction_connection.emplace(
          chain.applied_transaction.connect([&](const transaction_trace_ptr& p) { my->on_applied_transaction(p); }));
      my->accepted_block_connection.emplace(
          chain.accepted_block.connect([&](const block_state_ptr& p) { my->on_accepted_block(p); }));

      auto                    dir_option = options.at("state-history-dir").as<bfs::path>();
      boost::filesystem::path state_history_dir;
      if (dir_option.is_relative())
         state_history_dir = app().data_dir() / dir_option;
      else
         state_history_dir = dir_option;

      auto ip_port         = options.at("state-history-endpoint").as<string>();
      auto port            = ip_port.substr(ip_port.find(':') + 1, ip_port.size());
      auto host            = ip_port.substr(0, ip_port.find(':'));
      my->endpoint_address = host;
      my->endpoint_port    = std::stoi(port);
      idump((ip_port)(host)(port));

      if (options.at("delete-state-history").as<bool>()) {
         ilog("Deleting state history");
         boost::filesystem::remove_all(state_history_dir);
      }
      boost::filesystem::create_directories(state_history_dir);

      if (options.at("trace-history").as<bool>())
         my->trace_log.emplace("trace_history", (state_history_dir / "trace_history.log").string(),
                               (state_history_dir / "trace_history.index").string());
      if (options.at("chain-state-history").as<bool>())
         my->chain_state_log.emplace("chain_state_history", (state_history_dir / "chain_state_history.log").string(),
                                     (state_history_dir / "chain_state_history.index").string());
   }
   FC_LOG_AND_RETHROW()
} //状态\u历史\u插件：：插件\u初始化

void state_history_plugin::plugin_startup() { my->listen(); }

void state_history_plugin::plugin_shutdown() {
   my->applied_transaction_connection.reset();
   my->accepted_block_connection.reset();
   while (!my->sessions.empty())
      my->sessions.begin()->second->close();
   my->stopping = true;
}

} //命名空间EOSIO

max_stars_repo_name: linapex/eos-chinese

max_issues_repo_name: linapex/eos-chinese

max_forks_repo_name: linapex/eos-chinese


text:
/**
 * @file test_mathlib.cpp
 * @brief This file defines the test cases for the math library.
 *
 * @copyright Copyright (c) 2022
 *
 */

#include <array>
#include <boost/test/tools/floating_point_comparison.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <random>
#include <thread>

#include "proseco_planning/math/mathlib.h"

using namespace proseco_planning;

BOOST_AUTO_TEST_SUITE(mathlibTest)

BOOST_AUTO_TEST_CASE(local_random_engine_basic) {
  std::mt19937_64::result_type a, b, c;
  std::thread ta([&a]() { a = math::Random::engine()(); });
  std::thread tb([&b]() { b = math::Random::engine()(); });
  std::thread tc([&c]() { c = math::Random::engine()(); });

  ta.join();
  tb.join();
  tc.join();

  BOOST_CHECK_NE(a, b);
  BOOST_CHECK_NE(a, c);
}

BOOST_AUTO_TEST_CASE(local_random_engine_seed) {
  std::mt19937_64::result_type seed = 0;
  math::Random::g_seed              = seed;

  std::array<std::mt19937_64::result_type, 2> a, b, c;
  std::thread ta([&a]() { a = {math::Random::engine()(), math::Random::engine()()}; });
  std::thread tb([&b]() { b = {math::Random::engine()(), math::Random::engine()()}; });
  std::thread tc([&c]() { c = {math::Random::engine()(), math::Random::engine()()}; });

  ta.join();
  tb.join();
  tc.join();

  BOOST_CHECK_NE(a[0], b[0]);
  BOOST_CHECK_NE(a[0], c[0]);
  BOOST_CHECK_NE(a[1], b[1]);
  BOOST_CHECK_NE(a[1], c[1]);

  BOOST_CHECK_NE(a[0], a[1]);
  BOOST_CHECK_NE(b[0], b[1]);
  BOOST_CHECK_NE(c[0], c[1]);
}

BOOST_AUTO_TEST_CASE(random_engine_update_global_seed) {
  math::Random::g_seed = 0;

  std::mt19937_64::result_type a1, a2, a3, a4;
  a1 = math::Random::engine()();
  a2 = math::Random::engine()();

  // update the global seed value
  math::Random::g_seed = 7;

  a3 = math::Random::engine()();
  a4 = math::Random::engine()();

  BOOST_CHECK_NE(a1, a2);
  BOOST_CHECK_NE(a3, a4);
}

BOOST_AUTO_TEST_CASE(local_random_engine_fixed) {
  std::mt19937_64::result_type seed = 0;
  std::mt19937_64 ref(seed);
  std::array<std::mt19937_64::result_type, 2> r = {ref(), ref()};

  std::array<std::mt19937_64::result_type, 2> a, b, c;

  std::thread ta([&a, seed]() {
    math::Random::engine() = std::mt19937_64(seed);
    a                      = {math::Random::engine()(), math::Random::engine()()};
  });
  std::thread tb([&b, seed]() {
    math::Random::engine() = std::mt19937_64(seed);
    b                      = {math::Random::engine()(), math::Random::engine()()};
  });
  std::thread tc([&c, seed]() {
    math::Random::engine() = std::mt19937_64(seed);
    c                      = {math::Random::engine()(), math::Random::engine()()};
  });

  ta.join();
  tb.join();
  tc.join();

  BOOST_CHECK_EQUAL(r[0], a[0]);
  BOOST_CHECK_EQUAL(r[0], b[0]);
  BOOST_CHECK_EQUAL(r[0], c[0]);

  BOOST_CHECK_EQUAL(r[1], a[1]);
  BOOST_CHECK_EQUAL(r[1], b[1]);
  BOOST_CHECK_EQUAL(r[1], c[1]);
}

BOOST_AUTO_TEST_CASE(cumulative_moving_average) {
  BOOST_CHECK_CLOSE(math::cumulativeMovingAverage(1, 10, 5), 7.5, 0.0001);
  BOOST_CHECK_CLOSE(math::cumulativeMovingAverage(100, 10, 5), 9.950495, 0.0001);
}

BOOST_AUTO_TEST_CASE(linearly_spaced_vector) {
  auto v = math::linspace(0.0f, 2.0f, 5);
  // expected vector
  std::vector<float> exp_v{0.0f, 0.5f, 1.0f, 1.5f, 2.0f};

  BOOST_CHECK_EQUAL_COLLECTIONS(v.begin(), v.end(), exp_v.begin(), exp_v.end());
}

BOOST_AUTO_TEST_CASE(subvector_from_vector) {
  std::vector<int> v{0, 1, 2, 3, 4};
  auto sub_v = math::getSubvectorFromVector(v, 0, 2);
  // expected subvector
  std::vector<int> exp_sub_v{0, 1, 2};

  BOOST_CHECK_EQUAL_COLLECTIONS(sub_v.begin(), sub_v.end(), exp_sub_v.begin(), exp_sub_v.end());
}

BOOST_AUTO_TEST_CASE(absolute_sum_of_vector) {
  std::vector<float> v{0.5f, 1.5f, 3.0f, -4.0f};
  BOOST_CHECK_CLOSE(math::absSum(v), 9.0f, 0.0001);
}

BOOST_AUTO_TEST_CASE(sum_of_vector) {
  std::vector<float> v{0.5f, 1.5f, 3.0f, -4.0f};
  BOOST_CHECK_CLOSE(math::sumFromVector(v), 1.0f, 0.0001);
}

BOOST_AUTO_TEST_CASE(mean_of_vector) {
  std::vector<float> v{0.5f, 1.5f, 3.0f, -4.0f};
  BOOST_CHECK_CLOSE(math::meanFromVector(v), 0.25f, 0.0001);
}

BOOST_AUTO_TEST_CASE(variance_of_vector) {
  std::vector<float> v{0.5f, 1.5f, 3.0f, -4.0f};
  BOOST_CHECK_CLOSE(math::varFromVector(v), 6.8125f, 0.0001);
}

BOOST_AUTO_TEST_CASE(std_of_vector) {
  std::vector<float> v{0.5f, 1.5f, 3.0f, -4.0f};
  BOOST_CHECK_CLOSE(math::stdFromVector(v), 2.61007667f, 0.0001);
}

BOOST_AUTO_TEST_CASE(map_values_to_vector) {
  std::map<int, float> map{{0, 0.5f}, {1, 1.5f}, {2, 3.0f}, {3, -4.0f}};
  std::vector<float> vector = math::mapValuesToVector(map);
  for (size_t i = 0; i < vector.size(); ++i) {
    BOOST_CHECK_CLOSE(vector[i], map[i], 0.0001);
  }
}

BOOST_AUTO_TEST_SUITE_END()


text:
/**
  @author Shin'ichiro Nakaoka
*/

#include <boost/python.hpp>
#include "omniORBpy.h"
#include <cnoid/CorbaUtil>

using namespace std;
using namespace boost;
using namespace cnoid;

namespace {

    omniORBpyAPI* api;

    PyObject* getPyORB()
    {
        CORBA::ORB_ptr orb = getORB();
        PyObject* pyOrb = api->cxxObjRefToPyObjRef(orb, true);
        return pyOrb;
    }
}

BOOST_PYTHON_MODULE(Corba)
{
    PyObject* omnipy = PyImport_ImportModule((char*)"_omnipy");
    PyObject* pyapi = PyObject_GetAttrString(omnipy, (char*)"API");
    api = (omniORBpyAPI*)PyCObject_AsVoidPtr(pyapi);
    Py_DECREF(pyapi);

    python::def("getORB", &getPyORB);
}

max_stars_repo_name: snozawa/choreonoid

max_issues_repo_name: snozawa/choreonoid

max_forks_repo_name: snozawa/choreonoid


text:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) DreamWorks Animation LLC
//
// All rights reserved. This software is distributed under the
// Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
//
// Redistributions of source code must retain the above copyright
// and license notice and the following restrictions and disclaimer.
//
// *     Neither the name of DreamWorks Animation nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
// LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
//
///////////////////////////////////////////////////////////////////////////

#include <boost/python.hpp>
#include "openvdb/openvdb.h"
#include "pyutil.h"

namespace py = boost::python;
using namespace openvdb::OPENVDB_VERSION_NAME;

namespace pyTransform {

inline void scale1(math::Transform& t, double s) { t.preScale(s); }
inline void scale3(math::Transform& t, const Vec3d& xyz) { t.preScale(xyz); }

inline Vec3d voxelDim0(math::Transform& t) { return t.voxelSize(); }
inline Vec3d voxelDim1(math::Transform& t, const Vec3d& p) { return t.voxelSize(p); }

inline double voxelVolume0(math::Transform& t) { return t.voxelVolume(); }
inline double voxelVolume1(math::Transform& t, const Vec3d& p) { return t.voxelVolume(p); }

inline Vec3d indexToWorld(math::Transform& t, const Vec3d& p) { return t.indexToWorld(p); }
inline Vec3d worldToIndex(math::Transform& t, const Vec3d& p) { return t.worldToIndex(p); }

inline Coord worldToIndexCellCentered(math::Transform& t, const Vec3d& p) {
    return t.worldToIndexCellCentered(p);
}
inline Coord worldToIndexNodeCentered(math::Transform& t, const Vec3d& p) {
    return t.worldToIndexNodeCentered(p);
}

inline std::string
info(math::Transform& t)
{
    std::ostringstream ostr;
    t.print(ostr);
    return ostr.str();
}

inline math::Transform::Ptr
createLinearFromDim(double dim)
{
    return math::Transform::createLinearTransform(dim);
}

inline math::Transform::Ptr
createLinearFromMat(py::object obj)
{
    Mat4R m;

    // Verify that obj is a four-element sequence.
    bool is4x4Seq = (PySequence_Check(obj.ptr()) && PySequence_Length(obj.ptr()) == 4);
    if (is4x4Seq) {
        for (int row = 0; is4x4Seq && row < 4; ++row) {
            // Verify that each element of obj is itself a four-element sequence.
            py::object rowObj = obj[row];
            if (PySequence_Check(rowObj.ptr()) && PySequence_Length(rowObj.ptr()) == 4) {
                // Extract four numeric values from this row of the sequence.
                for (int col = 0; is4x4Seq && col < 4; ++col) {
                    if (py::extract<double>(rowObj[col]).check()) {
                        m[row][col] = py::extract<double>(rowObj[col]);
                    } else {
                        is4x4Seq = false;
                    }
                }
            } else {
                is4x4Seq = false;
            }
        }
    }
    if (!is4x4Seq) {
        PyErr_Format(PyExc_ValueError, "expected a 4 x 4 sequence of numeric values");
        py::throw_error_already_set();
    }

    return math::Transform::createLinearTransform(m);
}

inline math::Transform::Ptr
createFrustum(const Coord& xyzMin, const Coord& xyzMax,
    double taper, double depth, double voxelDim = 1.0)
{
    return math::Transform::createFrustumTransform(
        BBoxd(xyzMin.asVec3d(), xyzMax.asVec3d()), taper, depth, voxelDim);
}

////////////////////////////////////////

struct PickleSuite: public py::pickle_suite
{
    enum { STATE_DICT = 0, STATE_MAJOR, STATE_MINOR, STATE_FORMAT, STATE_XFORM };

    /// Return @c true, indicating that this pickler preserves a Transform's __dict__.
    static bool getstate_manages_dict() { return true; }

    /// Return a tuple representing the state of the given Transform.
    static py::tuple getstate(py::object xformObj)
    {
        py::tuple state;
        py::extract<math::Transform> x(xformObj);
        if (x.check()) {
            // Extract a Transform from the Python object.
            math::Transform xform = x();
            std::ostringstream ostr(std::ios_base::binary);
            // Serialize the Transform to a string.
            xform.write(ostr);

            // Construct a state tuple comprising the Python object's __dict__,
            // the version numbers of the serialization format,
            // and the serialized Transform.
#if PY_MAJOR_VERSION >= 3
            // Convert the byte string to a "bytes" sequence.
            const std::string s = ostr.str();
            py::object bytesObj = pyutil::pyBorrow(PyBytes_FromStringAndSize(s.data(), s.size()));
#else
            py::str bytesObj(ostr.str());
#endif
            state = py::make_tuple(
                xformObj.attr("__dict__"),
                uint32_t(OPENVDB_LIBRARY_MAJOR_VERSION),
                uint32_t(OPENVDB_LIBRARY_MINOR_VERSION),
                uint32_t(OPENVDB_FILE_VERSION),
                bytesObj);
        }
        return state;
    }

    /// Restore the given Transform to a saved state.
    static void setstate(py::object xformObj, py::object stateObj)
    {
        math::Transform* xform = nullptr;
        {
            py::extract<math::Transform*> x(xformObj);
            if (x.check()) xform = x();
            else return;
        }

        py::tuple state;
        {
            py::extract<py::tuple> x(stateObj);
            if (x.check()) state = x();
        }
        bool badState = (py::len(state) != 5);

        if (!badState) {
            // Restore the object's __dict__.
            py::extract<py::dict> x(state[int(STATE_DICT)]);
            if (x.check()) {
                py::dict d = py::extract<py::dict>(xformObj.attr("__dict__"))();
                d.update(x());
            } else {
                badState = true;
            }
        }

        openvdb::VersionId libVersion;
        uint32_t formatVersion = 0;
        if (!badState) {
            // Extract the serialization format version numbers.
            const int idx[3] = { STATE_MAJOR, STATE_MINOR, STATE_FORMAT };
            uint32_t version[3] = { 0, 0, 0 };
            for (int i = 0; i < 3 && !badState; ++i) {
                py::extract<uint32_t> x(state[idx[i]]);
                if (x.check()) version[i] = x();
                else badState = true;
            }
            libVersion.first = version[0];
            libVersion.second = version[1];
            formatVersion = version[2];
        }

        std::string serialized;
        if (!badState) {
            // Extract the sequence containing the serialized Transform.
            py::object bytesObj = state[int(STATE_XFORM)];
#if PY_MAJOR_VERSION >= 3
            badState = true;
            if (PyBytes_Check(bytesObj.ptr())) {
                // Convert the "bytes" sequence to a byte string.
                char* buf = NULL;
                Py_ssize_t length = 0;
                if (-1 != PyBytes_AsStringAndSize(bytesObj.ptr(), &buf, &length)) {
                    if (buf != NULL && length > 0) {
                        serialized.assign(buf, buf + length);
                        badState = false;
                    }
                }
            }
#else
            py::extract<std::string> x(bytesObj);
            if (x.check()) serialized = x();
            else badState = true;
#endif
        }

        if (badState) {
            PyErr_SetObject(PyExc_ValueError,
#if PY_MAJOR_VERSION >= 3
                ("expected (dict, int, int, int, bytes) tuple in call to __setstate__; found %s"
#else
                ("expected (dict, int, int, int, str) tuple in call to __setstate__; found %s"
#endif
                     % stateObj.attr("__repr__")()).ptr());
            py::throw_error_already_set();
        }

        // Restore the internal state of the C++ object.
        std::istringstream istr(serialized, std::ios_base::binary);
        io::setVersion(istr, libVersion, formatVersion);
        xform->read(istr);
    }
}; // struct PickleSuite

} // namespace pyTransform

void exportTransform();

void
exportTransform()
{
    py::enum_<math::Axis>("Axis")
        .value("X", math::X_AXIS)
        .value("Y", math::Y_AXIS)
        .value("Z", math::Z_AXIS);

    py::class_<math::Transform>("Transform", py::init<>())

        .def("deepCopy", &math::Transform::copy,
            "deepCopy() -> Transform\n\n"
            "Return a copy of this transform.")

        /// @todo Should this also be __str__()?
        .def("info", &pyTransform::info,
            "info() -> str\n\n"
            "Return a string containing a description of this transform.\n")

        .def_pickle(pyTransform::PickleSuite())

        .add_property("typeName", &math::Transform::mapType,
            "name of this transform's type")
        .add_property("isLinear", &math::Transform::isLinear,
            "True if this transform is linear")

        .def("rotate", &math::Transform::preRotate,
            (py::arg("radians"), py::arg("axis") = math::X_AXIS),
            "rotate(radians, axis)\n\n"
            "Accumulate a rotation about either Axis.X, Axis.Y or Axis.Z.")
        .def("translate", &math::Transform::postTranslate, py::arg("xyz"),
            "translate((x, y, z))\n\n"
            "Accumulate a translation.")
        .def("scale", &pyTransform::scale1, py::arg("s"),
            "scale(s)\n\n"
            "Accumulate a uniform scale.")
        .def("scale", &pyTransform::scale3, py::arg("sxyz"),
            "scale((sx, sy, sz))\n\n"
            "Accumulate a nonuniform scale.")
        .def("shear", &math::Transform::preShear,
            (py::arg("s"), py::arg("axis0"), py::arg("axis1")),
            "shear(s, axis0, axis1)\n\n"
            "Accumulate a shear (axis0 and axis1 are either\n"
            "Axis.X, Axis.Y or Axis.Z).")

        .def("voxelSize", &pyTransform::voxelDim0,
            "voxelSize() -> (dx, dy, dz)\n\n"
            "Return the size of voxels of the linear component of this transform.")
        .def("voxelSize", &pyTransform::voxelDim1, py::arg("xyz"),
            "voxelSize((x, y, z)) -> (dx, dy, dz)\n\n"
            "Return the size of the voxel at position (x, y, z).")

        .def("voxelVolume", &pyTransform::voxelVolume0,
            "voxelVolume() -> float\n\n"
            "Return the voxel volume of the linear component of this transform.")
        .def("voxelVolume", &pyTransform::voxelVolume1, py::arg("xyz"),
            "voxelVolume((x, y, z)) -> float\n\n"
            "Return the voxel volume at position (x, y, z).")

        .def("indexToWorld", &pyTransform::indexToWorld, py::arg("xyz"),
            "indexToWorld((x, y, z)) -> (x', y', z')\n\n"
            "Apply this transformation to the given coordinates.")
        .def("worldToIndex", &pyTransform::worldToIndex, py::arg("xyz"),
            "worldToIndex((x, y, z)) -> (x', y', z')\n\n"
            "Apply the inverse of this transformation to the given coordinates.")
        .def("worldToIndexCellCentered", &pyTransform::worldToIndexCellCentered,
            py::arg("xyz"),
            "worldToIndexCellCentered((x, y, z)) -> (i, j, k)\n\n"
            "Apply the inverse of this transformation to the given coordinates\n"
            "and round the result to the nearest integer coordinates.")
        .def("worldToIndexNodeCentered", &pyTransform::worldToIndexNodeCentered,
            py::arg("xyz"),
            "worldToIndexNodeCentered((x, y, z)) -> (i, j, k)\n\n"
            "Apply the inverse of this transformation to the given coordinates\n"
            "and round the result down to the nearest integer coordinates.")

        // Allow Transforms to be compared for equality and inequality.
        .def(py::self == py::other<math::Transform>())
        .def(py::self != py::other<math::Transform>())
        ;

    py::def("createLinearTransform", &pyTransform::createLinearFromMat, py::arg("matrix"),
        "createLinearTransform(matrix) -> Transform\n\n"
        "Create a new linear transform from a 4 x 4 matrix given as a sequence\n"
        "of the form [[a, b, c, d], [e, f, g, h], [i, j, k, l], [m, n, o, p]],\n"
        "where [m, n, o, p] is the translation component.");

    py::def("createLinearTransform", &pyTransform::createLinearFromDim,
        (py::arg("voxelSize") = 1.0),
        "createLinearTransform(voxelSize) -> Transform\n\n"
        "Create a new linear transform with the given uniform voxel size.");

    py::def("createFrustumTransform", &pyTransform::createFrustum,
        (py::arg("xyzMin"), py::arg("xyzMax"),
         py::arg("taper"), py::arg("depth"), py::arg("voxelSize") = 1.0),
        "createFrustumTransform(xyzMin, xyzMax, taper, depth, voxelSize) -> Transform\n\n"
        "Create a new frustum transform with unit bounding box (xyzMin, xyzMax)\n"
        "and the given taper, depth and uniform voxel size.");

    // allows Transform::Ptr Grid::getTransform() to work
    py::register_ptr_to_python<math::Transform::Ptr>();
}

// Copyright (c) DreamWorks Animation LLC
// All rights reserved. This software is distributed under the
// Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )

ext: cc

max_stars_repo_name: ibfernandes/NarvalEngine

max_issues_repo_name: ibfernandes/NarvalEngine

max_forks_repo_name: ibfernandes/NarvalEngine