<commit_before>function _isValidVector( vector )
{
  if(vector instanceof(THREE.Vector3)) //elimination of zero vectors
  {
    if(vector.equals(new THREE.Vector3()))
    {
      return false;
    }
    return true;
  }

  if(vector instanceof(THREE.Vector2)) //elimination of zero vectors
  {
    if(vector.equals(new THREE.Vector2()))
    {
      return false;
    }
    return true;
  }
}

function toTitleCase(str)
{
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

function uncapitalizeFirstLetter( str )
{
  return str.substr(0, 1).toLowerCase() + str.substr(1);
}


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

function CodeGenerator()
{
  this._lastTarget = null;
}

CodeGenerator.prototype.generateFromOperations=function(operations)
{
  this._lastTarget = null;
  
  var collapsedOps = this.collapseOperations( operations );
  var code = this.generateCodeFromOperationsList( collapsedOps );
  
  return code;
}

/*Collapses a list of operation into an equal but reduced list:
Multiple translations in a row can be collapsed into a single one
Multiple rotations in a row can be collapsed into a single one
Multiple scalings in a row can be collapsed into a single one
*/
CodeGenerator.prototype.collapseOperations=function(operations)
{
  //TODO: add "hardcore/compact mode" that generates matrix operations instead of multiple translate/rotate/scale operations
  var collapsedHistory = [];
  var operation = null;
  var prevOperation = operation;
  
  /*if(operations === undefined || operations.length==0)
  { return collapsedHistory }*/

  for( var i=0; i<operations.length;i++)
  {
    var operation = operations[i].clone();
    //console.log("operation.value",operation.value);
    if(prevOperation != null && operation.type == prevOperation.type && operation.target == prevOperation.target && operation.value)
    {
      //console.log("type",operation.type, "value", operation.value.clone().add(prevOperation.value), "target", operation.target);
      //todo use correct operands ("add", "+" etc)
      if(operation.value instanceof(THREE.Vector3) || operation.value instanceof(THREE.Vector2))
      {
        //console.log("updating", prevOperation.value ,"with", operation.value);
        prevOperation.value.add( operation.value );
      }
      else if (operation.value instanceof(THREE.Euler) )
      {
        prevOperation.value.set( prevOperation.value.x+operation.value.x, prevOperation.value.y+operation.value.y, prevOperation.value.z+operation.value.z); 
      }
      else
      {
        prevOperation.value += operation.value;
      }
    }
    else
    {
      collapsedHistory.push( operation );
      prevOperation = operation;
    }
    
  }
  //console.log("original ops", operations);
  console.log("collapse ops", collapsedHistory);
  return collapsedHistory;
}


CodeGenerator.prototype.getOperationFormatedItemName=function(operation, attrName)
{
  if(attrName)
  { var attr = operation[attrName];
  }
  else
  {
    var attr = operation;
  }
  var itemName = attr.name.toLowerCase() || (attr.constructor.name.toLowerCase()  +new String(attr.id));
  
  itemName = toTitleCase( itemName );//Capitalize each char after space/tab
  itemName = itemName.replace(/ /g, '');//remove spaces/tabs
  itemName = uncapitalizeFirstLetter( itemName );
  

  return itemName;
}

CodeGenerator.prototype.generateCodeFromOperation=function(operation, precision, targetFile, targetScope)
{
  var precision = precision || 2;
  var target = operation.target;
  var type = operation.type;
  var value = operation.value;

  //we apply the operations to the actual object, not its visual representation
  if(target.sourceElement) target = target.sourceElement;
  
  var targetName = this.getOperationFormatedItemName(operation, "target"); //(target.constructor.name.toLowerCase() || target.name.toLowerCase()) +new String(target.id);//    this.";//target.name;//@
  var code = "";
  var lineCap = ";\n";
  
  //we are working on a different object, add additional newline
  if(this._lastTarget != target && this._lastTarget != null)
  {
    code += "\n";
  }
  this._lastTarget = target;
  
  //TODO: if translate, rotate etc values are integers, do not display as float, or give the option to do so
  switch(type)
  {
    case "creation":
      var type = target.constructor.name || "foo";
      
      //TODO: refactor: this same code is present multiple times, and is clumsy
      var strValue = "";
      var paramsRaw = operation.target.properties;
      var params = {}
      for(key in paramsRaw)
      {
        var value = paramsRaw[key][2];
        params[key] = value;
      }
      //var params = operation.value
      if( Object.keys(params).length !== 0 )
      {
        var strValue = JSON.stringify(params);
        strValue.replace(/\\"/g,"\uFFFF"); //U+ FFFF
        strValue = strValue.replace(/\"([^"]+)\":/g,"$1:").replace(/\uFFFF/g,"\\\"");
      }
      
      code += "var "+targetName+" = new "+ type +"("+strValue+")"+lineCap;
      var parentName = "assembly";
      code += parentName+".add( "+ targetName +" )"+lineCap;
    break;
    case "deletion":
      //TODO: how to deal with this ?
    break;
    case "clone":
      var sourceName = this.getOperationFormatedItemName(operation, "source");
      code += "var " + targetName+"= "+sourceName+".clone()"+lineCap;
    break;
    case "extrusion":
      var type = target.constructor.name || "foo";
      var sourceShapeName = this.getOperationFormatedItemName( operation, "sourceShape"  );
      var strValue = JSON.stringify(operation.value);
      strValue.replace(/\\"/g,"\uFFFF"); //U+ FFFF
      strValue = strValue.replace(/\"([^"]+)\":/g,"$1:").replace(/\uFFFF/g,"\\\"");
      code += "var "+targetName+" = "+ sourceShapeName +".extrude("+strValue+")"+lineCap;
    break;
    
    case "rotation":
      if (!("code" in target)){ target.code = ""};
      code += targetName+".rotate("+ value.x.toFixed(precision)+","+value.y.toFixed(precision)+","+value.z.toFixed(precision)+")"+lineCap;<commit_msg>- added generation of code for imports<commit_after>function _isValidVector( vector )
{
  if(vector instanceof(THREE.Vector3)) //elimination of zero vectors
  {
    if(vector.equals(new THREE.Vector3()))
    {
      return false;
    }
    return true;
  }

  if(vector instanceof(THREE.Vector2)) //elimination of zero vectors
  {
    if(vector.equals(new THREE.Vector2()))
    {
      return false;
    }
    return true;
  }
}

function toTitleCase(str)
{
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

function uncapitalizeFirstLetter( str )
{
  return str.substr(0, 1).toLowerCase() + str.substr(1);
}


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

function CodeGenerator()
{
  this._lastTarget = null;
}

CodeGenerator.prototype.generateFromOperations=function(operations)
{
  this._lastTarget = null;
  
  var collapsedOps = this.collapseOperations( operations );
  var code = this.generateCodeFromOperationsList( collapsedOps );
  
  return code;
}

/*Collapses a list of operation into an equal but reduced list:
Multiple translations in a row can be collapsed into a single one
Multiple rotations in a row can be collapsed into a single one
Multiple scalings in a row can be collapsed into a single one
*/
CodeGenerator.prototype.collapseOperations=function(operations)
{
  //TODO: add "hardcore/compact mode" that generates matrix operations instead of multiple translate/rotate/scale operations
  var collapsedHistory = [];
  var operation = null;
  var prevOperation = operation;
  
  /*if(operations === undefined || operations.length==0)
  { return collapsedHistory }*/

  for( var i=0; i<operations.length;i++)
  {
    var operation = operations[i].clone();
    //console.log("operation.value",operation.value);
    if(prevOperation != null && operation.type == prevOperation.type && operation.target == prevOperation.target && operation.value)
    {
      //console.log("type",operation.type, "value", operation.value.clone().add(prevOperation.value), "target", operation.target);
      //todo use correct operands ("add", "+" etc)
      if(operation.value instanceof(THREE.Vector3) || operation.value instanceof(THREE.Vector2))
      {
        //console.log("updating", prevOperation.value ,"with", operation.value);
        prevOperation.value.add( operation.value );
      }
      else if (operation.value instanceof(THREE.Euler) )
      {
        prevOperation.value.set( prevOperation.value.x+operation.value.x, prevOperation.value.y+operation.value.y, prevOperation.value.z+operation.value.z); 
      }
      else
      {
        prevOperation.value += operation.value;
      }
    }
    else
    {
      collapsedHistory.push( operation );
      prevOperation = operation;
    }
    
  }
  //console.log("original ops", operations);
  console.log("collapse ops", collapsedHistory);
  return collapsedHistory;
}


CodeGenerator.prototype.getOperationFormatedItemName=function(operation, attrName)
{
  if(attrName)
  { var attr = operation[attrName];
  }
  else
  {
    var attr = operation;
  }
  var itemName = attr.name.toLowerCase() || (attr.constructor.name.toLowerCase()  +new String(attr.id));
  
  itemName = toTitleCase( itemName );//Capitalize each char after space/tab
  itemName = itemName.replace(/ /g, '');//remove spaces/tabs
  itemName = uncapitalizeFirstLetter( itemName );
  

  return itemName;
}

CodeGenerator.prototype.generateCodeFromOperation=function(operation, precision, targetFile, targetScope)
{
  var precision = precision || 2;
  var target = operation.target;
  var type = operation.type;
  var value = operation.value;

  //we apply the operations to the actual object, not its visual representation
  if(target.sourceElement) target = target.sourceElement;
  
  var targetName = this.getOperationFormatedItemName(operation, "target"); //(target.constructor.name.toLowerCase() || target.name.toLowerCase()) +new String(target.id);//    this.";//target.name;//@
  var code = "";
  var lineCap = ";\n";
  
  //we are working on a different object, add additional newline
  if(this._lastTarget != target && this._lastTarget != null)
  {
    code += "\n";
  }
  this._lastTarget = target;
  
  //TODO: if translate, rotate etc values are integers, do not display as float, or give the option to do so
  switch(type)
  {
    case "creation":
      var type = target.constructor.name || "foo";
      
      //TODO: refactor: this same code is present multiple times, and is clumsy
      var strValue = "";
      var paramsRaw = operation.target.properties;
      var params = {}
      for(key in paramsRaw)
      {
        var value = paramsRaw[key][2];
        params[key] = value;
      }
      //var params = operation.value
      if( Object.keys(params).length !== 0 )
      {
        var strValue = JSON.stringify(params);
        strValue.replace(/\\"/g,"\uFFFF"); //U+ FFFF
        strValue = strValue.replace(/\"([^"]+)\":/g,"$1:").replace(/\uFFFF/g,"\\\"");
      }
      
      code += "var "+targetName+" = new "+ type +"("+strValue+")"+lineCap;
      var parentName = "assembly";
      code += parentName+".add( "+ targetName +" )"+lineCap;
    break;
    case "deletion":
      //TODO: how to deal with this ?
    break;
    case "clone":
      var sourceName = this.getOperationFormatedItemName(operation, "source");
      code += "var " + targetName+"= "+sourceName+".clone()"+lineCap;
    break;
    case "import":
      var destinationName = this.getOperationFormatedItemName(operation, "value");
      code += "var " + destinationName+'= import("'+targetName+'")'+lineCap;
    break;
    case "extrusion":
      var type = target.constructor.name || "foo";
      var sourceShapeName = this.getOperationFormatedItemName( operation, "sourceShape"  );
      var strValue = JSON.stringify(operation.value);
      strValue.replace(/\\"/g,"\uFFFF"); //U+ FFFF
      strValue = strValue.replace(/\"([^"]+)\":/g,"$1:").replace(/\uFFFF/g,"\\\"");
      code += "var "+targetName+" = "+ sourceShapeName +".extrude("+strValue+")"+lineCap;
    break;
    
    case "rotation":
      if (!("code" in target)){ target.code = ""};
      code += targetName+".rotate("+ value.x.toFixed(precision)+","+value.y.toFixed(precision)+","+value.z.toFixed(precision)+")"+lineCap;
{'fraction_non_alphanumeric': 0.1470707727309661, 'fraction_numerical': 0.0029251645405054035, 'mean_word_length': 3.31859649122807, 'pattern_counts': {'":': 15, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3228660', 'n_tokens_mistral': 3700, 'n_tokens_neox': 3672, 'n_words': 870}