Пример #1
0
/**
* Click and drag absolute: move to a relative coordinate within the window
* windowname, clamped.
*/
bool clickAndDragAbsolute(std::string window_name, nlohmann::json action){
   //populate the window variables. 
  int x_start, x_end, y_start, y_end, mouse_button;
  bool no_clamp = false; 
  bool success = populateClickAndDragValues(action, window_name, x_start,
                       x_end, y_start, y_end, mouse_button, no_clamp);
  
  //if we couldn't populate the values, do nothing (window doesn't exist)
  if(!success){ 
    std::cout << "Click and drag unsuccessful due to failure to populate click and drag values." << std::endl;
    return false;
  }


  int start_x_position = action.value("start_x", -1);
  int start_y_position = action.value("start_y", -1);

  int end_x_position = action.value("end_x", -1);
  int end_y_position = action.value("end_y", -1);

  if (start_x_position == end_x_position && start_y_position == end_y_position){
    std::cout << "Error, the click and drag action did not specify movement." << std::endl;
    return false;
  }

  if(end_x_position == -1 || end_y_position == -1){
    std::cout << "ERROR: the click and drag action must include an ending position" << std::endl;
    return false;
  }
  


  //get the mouse into starting position if they are specified.
  if(start_x_position != -1 && start_y_position != -1){ 
    start_x_position = start_x_position + x_start;
    start_y_position = start_y_position + y_start;

    //don't move out of the window.
    clamp(start_x_position, x_start, x_end); 
    clamp(start_y_position, y_start, y_end);
    mouse_move(window_name, start_x_position, start_y_position,x_start, x_end, 
                                                        y_start, y_end, false); 
  }
  
  end_x_position = end_x_position + x_start;
  end_y_position = end_y_position + y_start;
  
  //clamp the end position so we don't exit the window. 
  clamp(end_x_position, x_start, x_end); 
  clamp(end_y_position, y_start, y_end);

  //These functions won't do anything if the window doesn't exist. 
  mouseDown(window_name,mouse_button); 
  mouse_move(window_name, end_x_position, end_y_position,x_start, x_end, 
                                                  y_start, y_end, false);
  mouseUp(window_name,mouse_button);  

  return true;
}
Пример #2
0
/**
* This function sets the window variables (using populateWindowData), and 
* mouse_button (pressed) destination (an x,y tuple we are dragging to), and 
* no_clamp (which is currently disabled/false). returns false on failure. 
* It is on the programmer to check.
*/
bool populateClickAndDragValues(nlohmann::json action, std::string window_name, 
      int& window_left, int& window_right, int& window_top, int& window_bottom, int& mouse_button, 
                                bool& no_clamp){
  int height, width;
  //Get the window dimensions.
  populateWindowData(window_name,height,width,window_left,window_right,window_top,window_bottom);


  // if(command.find("no clamp") != std::string::npos){
  //   std::cout << "Multiple windows are not yet supported. (No 'no clamp' option available)" << std::endl;
  //   no_clamp = false;
  // }

  std::string mouse_button_string = action.value("mouse_button", "left");

  if(mouse_button_string == "left"){
    mouse_button = 1;
  }
  else if (mouse_button_string == "middle"){
    mouse_button = 2;
  }
  else if (mouse_button_string == "right"){
    mouse_button = 3;
  }
  else{ //default.
    mouse_button = 1; 
  }
  return true;
}
Пример #3
0
bool ReadTexturesFromJson(const nlohmann::json& json_textures, const filesystem::path& base_path, ID3D11Device* device, std::vector<TextureIdentifier>* textures) {
  const auto& json_textures_array = json_textures.value("textures", nlohmann::json::array({}));

  if (!json_textures_array.is_array()) {
    DXFW_TRACE(__FILE__, __LINE__, false, "Invalid textures JSON %S", json_textures_array.dump().c_str());
    return false;
  }

  for (const auto& json_texture : json_textures_array) {
    if (!json_texture.is_object()) {
      DXFW_TRACE(__FILE__, __LINE__, false, "Invalid textures entry %S", json_texture.dump().c_str());
      continue;
    }

    const auto& json_texture_name_it = json_texture.find("name");
    if (json_texture_name_it == json_texture.end() || !json_texture_name_it->is_string()) {
      DXFW_TRACE(__FILE__, __LINE__, false, "Invalid texture name %S", json_texture_name_it->dump().c_str());
      continue;
    }

    const auto& json_texture_path_it = json_texture.find("filename");
    if (json_texture_path_it == json_texture.end() || !(json_texture_path_it->is_string() || json_texture_path_it->is_array())) {
      DXFW_TRACE(__FILE__, __LINE__, false, "Invalid texture filename(s) %S", json_texture_path_it->dump().c_str());
      continue;
    }

    TextureIdentifier identifier;
    identifier.Hash = std::hash<std::string>()(*json_texture_name_it);

    if (json_texture_path_it->is_string()) {
      identifier.Texture = ReadSingleTexture(identifier.Hash, *json_texture_path_it, base_path, device);
    } else {  // Array
      identifier.Texture = ReadMipmapTexture(identifier.Hash, *json_texture_path_it, base_path, device);
    }

    if (!identifier.Texture.IsValid()) {
      DXFW_TRACE(__FILE__, __LINE__, false, "Error creating texture %S", json_texture_name_it->dump().c_str());
      continue;
    }

    textures->emplace_back(std::move(identifier));
  }

  return true;
}
Пример #4
0
/**
* This function defines which actions are inherently bound for a GUI/window.
**/
bool isWindowedAction(const nlohmann::json action){
  std::string action_str = action.value("action", "");
  if (action_str == ""){
    std::cout << "ERROR: poorly formatted action (no 'action' type specified)" << std::endl;
    return false;
  }
  else{

    if(action_str.find("screenshot") != std::string::npos){
      return true;
    }
    else if(action_str.find("type") != std::string::npos){
      return true;
    }
    else if(action_str.find("key") != std::string::npos){
      return true;
    }
    else if(action_str.find("click and drag") != std::string::npos){
      return true;
    }
    else if(action_str.find("click") != std::string::npos){
      return true;
    }
    else if(action_str.find("move mouse") != std::string::npos){
      return true;
    }
    else if(action_str.find("center") != std::string::npos){
      return true;
    }
    else if(action_str.find("origin") != std::string::npos){
      return true;
    }
    else{
      return false;
    }
  }


}
Пример #5
0
void IO::from_json(const nlohmann::json& j, IO::CPParam& p)
{
    for(const auto& pair: CPParam::str2section){
        p.*pair.second = j.value(pair.first, CPParam::Section{});
    }
}
Пример #6
0
void Difference::PrepareGrade(const nlohmann::json& j) {
  std::cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
  std::cout << "PREPARE GRADE" << std::endl;


  // --------------------------------------------------------
  //std::cout << "json " << j.dump(4) << std::endl;
  if (j.find("max_char_changes") != j.end()) {
    std::cout << "MAX CHAR CHANGES" << std::endl;

    int max_char_changes = j.value("max_char_changes", -1);
    assert (max_char_changes > 0);
    int min_char_changes = j.value("min_char_changes",0);
    assert (min_char_changes >= 0);
    assert (min_char_changes < max_char_changes);

    assert (total_char > 0);
    if (max_char_changes > total_char) {
      std::cout << "WARNING!  max_char_changes > total_char)" << std::endl;
      max_char_changes = total_char;
      if (min_char_changes > max_char_changes) {
        min_char_changes = max_char_changes-1;
      }
      assert (min_char_changes >= 0);
    }
    assert (max_char_changes <= total_char);

    int char_changes = char_added + char_deleted;

    std::cout << "char_changes=" << char_changes << " min=" << min_char_changes << " max=" << max_char_changes << std::endl;

    int min_max_diff = max_char_changes-min_char_changes;
    int lower_bar = std::max(0,min_char_changes-min_max_diff);
    int upper_bar = max_char_changes + min_max_diff;

    assert (0 <= lower_bar &&
      lower_bar <= min_char_changes &&
      min_char_changes <= max_char_changes &&
      max_char_changes <= upper_bar);

    float grade;
    if (char_changes < lower_bar) {
      std::cout << "too few char changes (zero credit)" << std::endl;
      messages.push_back(std::make_pair(MESSAGE_FAILURE,"ERROR!  Approx " + std::to_string(char_changes) + " characters added and/or deleted.  Significantly fewer character changes than allowed."));
    } else if (char_changes < min_char_changes) {
      std::cout << "less than min char changes (partial credit)" << std::endl;
      float numer = min_char_changes - char_changes;
      float denom = min_max_diff;
      std::cout << "numer " << numer << " denom= " << denom << std::endl;
      assert (denom > 0);
      grade = 1 - numer/denom;
      messages.push_back(std::make_pair(MESSAGE_FAILURE,"ERROR!  Approx " + std::to_string(char_changes) + " characters added and/or deleted.  Fewer character changes than allowed."));
    } else if (char_changes < max_char_changes) {
      messages.push_back(std::make_pair(MESSAGE_SUCCESS,"Approx " + std::to_string(char_changes) + " characters added and/or deleted.  Character changes within allowed range."));
      std::cout << "between min and max char changes (full credit)" << std::endl;
      grade = 1.0;
    } else if (char_changes < upper_bar) {
      std::cout << "more than max char changes (partial credit)" << std::endl;
      float numer = char_changes - max_char_changes;
      float denom = min_max_diff;
      assert (denom > 0);
      grade = 1 - numer/denom;
      std::cout << "numer " << numer << " denom= " << denom << std::endl;
      messages.push_back(std::make_pair(MESSAGE_FAILURE,"ERROR!  Approx " + std::to_string(char_changes) + " characters added and/or deleted.  More character changes than allowed."));
    } else {
      std::cout << "too many char changes (zero credit)" << std::endl;
      messages.push_back(std::make_pair(MESSAGE_FAILURE,"ERROR!  Approx " + std::to_string(char_changes) + " characters added and/or deleted.  Significantly more character changes than allowed."));
      grade = 0.0;
    }
    std::cout << "grade " << grade << std::endl;
    assert (grade >= -0.00001 & grade <= 1.00001);
    this->setGrade(grade);
  }

  // --------------------------------------------------------
  else if (this->extraStudentOutputOk) {
    // only missing lines (deletions) are a problem
    int count_of_missing_lines = 0;
    for (int x = 0; x < this->changes.size(); x++) {
      int num_b_lines = this->changes[x].b_changes.size();
      if (num_b_lines > 0) {
        count_of_missing_lines += num_b_lines;
      }
    }
    int output_length = this->output_length_b;
    std::cout << "COMPARE outputlength=" << output_length << " missinglines=" << count_of_missing_lines << std::endl;
    assert (count_of_missing_lines <= output_length);
    float grade = 1.0;
    if (output_length > 0) {
      //std::cout << "SES [ESOO] calculating grade " << this->distance << "/" << output_length << std::endl;
      //grade -= (this->distance / (float) output_length );
      grade -= count_of_missing_lines / float(output_length);
      std::cout <<
        "grade:  missing_lines [ " << count_of_missing_lines <<
        "] / output_length " << output_length << "]\n";
      //std::cout << "SES [ESOO] calculated grade = " << std::setprecision(1) << std::fixed << std::setw(5) << grade << " " << std::setw(5) << (int)floor(5*grade) << std::endl;
      if (grade < 1.0 && this->only_whitespace_changes) {
        std::cout << "ONLY WHITESPACE DIFFERENCES! adjusting grade: " << grade << " -> ";
        // FIXME:  Ugly, but with rounding, this will be only a -1 point grade for this test case
        grade = std::max(grade,0.99f);
        std::cout << grade << std::endl;
      } else {
        std::cout << "MORE THAN JUST WHITESPACE DIFFERENCES! " << std::endl;
      }
    } else {
      assert (output_length == 0);
      std::cout << "NO OUTPUT, GRADE IS ZERO" << std::endl;
      grade = 0;
    }

    std::cout << "this test grade = " << grade << std::endl;
    this->setGrade(grade);
  }

  // --------------------------------------------------------
  else {
    // both missing lines (deletions) and extra lines are a deduction
    int max_output_length = std::max(this->output_length_a, this->output_length_b);
    float grade = 1.0;
    if (max_output_length == 0) {
      grade = 0;
    } else {
      //std::cout << "SES  calculating grade " << this->distance << "/" << max_output_length << std::endl;
      grade -= (this->distance / (float) max_output_length );
      std::cout <<
        "grade:  this->distance [ " << this->distance <<
        "] / max_output_length " << max_output_length << "]\n";
      //std::cout << "SES calculated grade = " << grade << std::endl;
    }
    this->setGrade(grade);
  }
  // ===================================================
  std::cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
}
Пример #7
0
void Vipster::IO::from_json(const nlohmann::json &j, IO::PWConfig& c)
{
    c.atoms = j.value("atomfmt", IO::PWConfig::AtomFmt::Current);
    c.cell = j.value("cellfmt", IO::PWConfig::CellFmt::Current);
}
Пример #8
0
/**
* The 'delta' version of the click and drag command. This function moves an xy
* distance from a startpoint. This distance is 'wrapping', so if it is outside 
* of the window, we mouseup, return to the start position, mousedown, and then
* move again. We give a one pixel border at each side of the window and clamp 
* using that value to avoid accidental resizing.
*/
bool clickAndDragDelta(std::string window_name, nlohmann::json action){
  //get the values of the student's window.
  int x_start, x_end, y_start, y_end, mouse_button; 
  bool no_clamp = false; 
  bool success = populateClickAndDragValues(action, window_name, x_start, 
                      x_end, y_start, y_end, mouse_button, no_clamp);
  
  //if we can't populate the click and drag values, do nothing.
  if(!success){ 
    std::cout << "Could not populate the click and drag values."<< std::endl;
    return false;
  }
  
  //Define the corners of our window. (We use vectors as 2d points.)
  std::vector<int> upper_left, upper_right, lower_left, lower_right; 
  upper_left.push_back(x_start); upper_left.push_back(y_start);
  upper_right.push_back(x_end); upper_right.push_back(y_start);
  lower_left.push_back(x_start); lower_left.push_back(y_end);
  lower_right.push_back(x_end); lower_right.push_back(y_end);

  
  //delta version, 2 values movement x and movement y.
  int amt_x_movement_remaining = action.value("x_distance", 0);
  int amt_y_movement_remaining = action.value("y_distance", 0);
  std::string start_location   = action.value("start_location", "center");

  //This shouldn't fail unless there isn't a mouse.
  std::string mouse_location_string = output_of_system_command("xdotool getmouselocation"); 
  std::vector<int> xy = extractIntsFromString(mouse_location_string);                      
  
  //if the mouse isn't detected, fail.
  if(xy.size() < 2){ 
    std::cout << "Mouse coordinates couldn't be found. Mouse undetected." 
                << std::endl;
    return false;
  }
  //get the current mouse location
  int start_mouse_x = xy[0];
  int start_mouse_y = xy[1];
  //clamp the mouse within the screen (and move in by a pixel).
  clamp(start_mouse_x, x_start+1, x_end-1); 
  clamp(start_mouse_y, y_start+1, y_end-1);

  //get the center of the window
  int width  = x_end - x_start;
  int height = y_end - y_start;
  int x_middle = x_start + (width/2);
  int y_middle = y_start+(height/2);

  //NOTE: check my arithmetic. 
  /**
  * The process that this algorithm goes through is as follows:
  * 1) Determine the slope of the dragged line and its distance.
  * 2) while we have not traversed the necessary distance
  * 3) project a line from the current mouse position towards the end 
  *      position with length equal to the remaining distance. 
  * 4) Now that we have a line segment defined, find where/if it intersects
  *      any of the window's edges
  * 5) if it does intersect, cut it off at the point of intersection, and only
  *      drag that far. Else, if it doesn't intersect, we can assume we are 
  *      inside of the window, due to the clamp, and can drag.
  * 6) update remaining distance and continue to loop.
  */

  //rise / run
  float slope=(float)amt_y_movement_remaining/(float)amt_x_movement_remaining;
  float total_distance_needed = sqrt(pow(amt_x_movement_remaining, 2) 
                                    + pow (amt_y_movement_remaining, 2)); 

  //remaining distance needed.
  float remaining_distance_needed = total_distance_needed; 

  int action_start_x = (start_location == "current") ? start_mouse_x : x_middle;
  int action_start_y = (start_location == "current") ? start_mouse_y : y_middle;

  std::cout << "start x " << start_mouse_x << " our x " << action_start_x;
  std::cout << "start y " << start_mouse_y << " our y " << action_start_y;

  //The functions called within this loop will not fire if the window doesn't 
  // exist. This check just short circuits to avoid additional printing.
  while(remaining_distance_needed >= 1 && windowExists(window_name)){ 
    int curr_x = action_start_x;                                             
    int curr_y = action_start_y;                                              
    int moved_mouse_x, moved_mouse_y;
    //reset the mouse to the start location.
    mouse_move(window_name, action_start_x, action_start_y, x_start, x_end, y_start, y_end,
                                                                        false); 
    //determine how far we've come.
    float fraction_of_distance_remaining = remaining_distance_needed 
                                            / total_distance_needed; 
    //project in the direction of the move to find the end of our line segment.
    float projected_x = action_start_x + (amt_x_movement_remaining * fraction_of_distance_remaining); 
    float projected_y = action_start_y + (amt_y_movement_remaining * fraction_of_distance_remaining);  

    //we are using vectors as 2d points.
    std::vector<int> current_point, projected_point;  
    current_point.push_back(curr_x); current_point.push_back(curr_y);
    projected_point.push_back(projected_x); 
    projected_point.push_back(projected_y);

    std::vector<float> intersection_point; 
    intersection_point=getLineIntersectionPoint(current_point,projected_point,
                                                      upper_left, upper_right);
    

    /**
    * TODO make this block smaller. 
    * These if statements just test all edges of the window against our 
    * projected line.
    */

    //found is just a quick short-circuit to keep the code from ballooning.
    bool found = false; 
    if(intersection_point.size() != 0){ //TOP
      std::cout << "intersected top" << std::endl;
      moved_mouse_x = (int)intersection_point[0]; 
      moved_mouse_y = (int)intersection_point[1];
      found = true;
    }

    if(!found) //RIGHT
    {
      intersection_point = getLineIntersectionPoint(current_point, 
                            projected_point, upper_right, lower_right);
      if(intersection_point.size() != 0){ 
        std::cout << "intersected right" << std::endl;
        moved_mouse_x = (int)intersection_point[0]; 
        moved_mouse_y = (int)intersection_point[1];
        found = true;
      }
    }

    if(!found) //BOTTOM
    {
      intersection_point = getLineIntersectionPoint(current_point, 
                              projected_point, lower_right, lower_left);
      if(intersection_point.size() != 0){
        std::cout << "intersected bottom" << std::endl;
        moved_mouse_x = (int)intersection_point[0]; 
        moved_mouse_y = (int)intersection_point[1];
        found = true;
      }
    }

    if(!found) //LEFT
    {
      intersection_point = getLineIntersectionPoint(current_point,
                             projected_point, lower_left, upper_left);
      if(intersection_point.size() != 0){
        std::cout << "intersected left" << std::endl;
        moved_mouse_x = (int)intersection_point[0]; 
        moved_mouse_y = (int)intersection_point[1];
        found = true;
      }
    }

    //if we didn't intersect, we are inside of the box (guaranteed by clamp)
    // so we can move freely.
    if(!found) 
    {
      std::cout << "No intersection at all"<< std::endl;
      moved_mouse_x = projected_x;
      moved_mouse_y = projected_y;
    }

    //the distance we can move
    float distance_of_move = sqrt(pow(moved_mouse_x - action_start_x, 2) 
                                    + pow (moved_mouse_y - action_start_y, 2)); 
    //we are moving distance_of_move
    remaining_distance_needed -= distance_of_move; 
    std::cout << "after the move, we had " << remaining_distance_needed 
                                          << " distance left " << std::endl;
    mouseDown(window_name,mouse_button); //click
    mouse_move(window_name, moved_mouse_x, moved_mouse_y,x_start, x_end, //drag
                                                        y_start, y_end, false); 
    mouseUp(window_name,mouse_button); //release
  } //end loop.

  //to preserve backwards compatibility.
  if(start_location != "current"){
    //put the mouse back where we found it.
    mouse_move(window_name, start_mouse_x, start_mouse_y, x_start, x_end, y_start, y_end,false);
  }

  return true;
}