<commit_before>"use strict";
var debug = true;

//create custom splice method. From user113716 @ http://stackoverflow.com/questions/4313841/javascript-how-can-i-insert-a-string-at-a-specific-index
String.prototype.splice = function (idx, rem, s) {
    return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
};

//handle document load
$(document).ready(function () {
    paper.install(window);

    paper.setup('board');
    setCanvasSize();
    drawCanvasGrid();

    //set animation
    paper.view.attach('frame', onFrame);

});

//get the grid setup
function drawCanvasGrid() {
    //get canvas width and height
    var canvas = document.getElementById("board");
    var canvasWidth = canvas.width;
    var canvasHeight = canvas.height;

    for (var i = 0; i < 10; i++) {
        //vertical lines
        var path = new Path();
        path.strokeColor = 'black';
        path.moveTo(canvas.width * (i / 10), 0);
        path.lineTo(canvas.width * (i / 10), canvasHeight);
        view.draw();

        //horizontal lines
        var path2 = new Path();
        path2.strokeColor = 'black';
        path2.moveTo(0, canvas.height * (i / 10));
        path2.lineTo(canvasWidth, canvas.height * (i / 10));
        view.draw()
    }

}

//refresh the canvas grid when the browser resizes
$(window).resize(function () {
    setCanvasSize();
    drawCanvasGrid();
});
//keep canvas size consistent to prevent blurring
function setCanvasSize() {
    /*var canvas = document.getElementById('board');
    var canvasWidth = $(window).width() * .45;
    var canvasHeight = $(window).width() * .45;
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;*/
}
//from Tim Down @ http://stackoverflow.com/questions/3410464/how-to-find-all-occurrences-of-one-string-in-another-in-javascript
function getIndicesOf(searchStr, str, caseSensitive) {
    var startIndex = 0,
        searchStrLen = searchStr.length;
    var index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
        indices.push(index);
        startIndex = index + searchStrLen;
    }
    return indices;
}

//check for likely new statements
function isNewStatementCharacter(character) {
    if (character == ' ' || character == ';' || character == ')' || character == '}' || character == '\n' || character == '\t')
        return true;
    else
        return false;
}

//finds the incdices of the items that need to have callback statements for synchronous code running
function getReplaceIndices(code) {
    var imageIndices = getIndicesOf(".setImage(", code, false);
    var moveIndices = getIndicesOf(".move(", code, false);
    var moveToIndices = getIndicesOf(".moveTo(", code, false);

    return imageIndices.concat(moveIndices).concat(moveToIndices);
}

//compile code to avoid async results conflicting
function compileCode(code) {
    var searchIndices = getReplaceIndices(code);
    //iterate through all necessary changes
    for (var i = 0; i < searchIndices.length; i++) {
        var innerCounter = searchIndices[i];

        //get index of where we should insert this time
        innerCounter = code.indexOf(")", innerCounter);

        //splice the calling function in
        var firstSplice = ",{next : function(){goToStatement" + i + "();}}";
        code = code.splice(innerCounter, 0, firstSplice);
        innerCounter += firstSplice.length + 2;

        //splice the destination
        code = code.splice(innerCounter, 0, "\nfunction goToStatement" + i + "(){");
        var tempLocation = searchIndices[i];
        while (code.charAt(tempLocation) != "\n")
            tempLocation--;
        if (code.charAt(tempLocation + 1) == "\\" && code.charAt(tempLocation + 2))
            code = code + "\n}";
        else
            code = code + "}";

        //reset the indices because the string length has changed
        searchIndices = getReplaceIndices(code);
    }
    return code;
}

/*
var sprite = new Sprite();
sprite.setImage("img/giphy.gif");
sprite.setLocation(1,1);
sprite.move("left",1,1);
sprite.move("up",1,1);
sprite.move("right",5,1);
sprite.moveTo(4,3,1);

var sprite2 = Sprite.create();
sprite2.setImage("http://media.giphy.com/media/cqqY4tX61jof6/giphy.gif");
sprite2.move();
*/

//compileCode('var sprite = Sprite.create();sprite.setImage("http://media.giphy.com/media/cqqY4tX61jof6/giphy.gif");sprite.move();');

//run student code
function runCode() {
    project.clear();
    drawCanvasGrid();
    var code = "";
    if (debug) {
        code = compileCode(myCodeMirror.getValue());
        //code = myCodeMirror.getValue();
    } else {
        code = "try{" + compileCode(myCodeMirror.getValue()) + "}catch(err) {alert(err.message)}";
    }
    window.eval(code);
}

class AnimationRequest {
    constructor(sprite, callBack, destinationX, destinationY, rotations, speed) {
        this.sprite = sprite;
        this.callBack = callBack;
        this.rotations = rotations;
        this.speed = speed;
        this.timesExecuted = 0;

        console.log("destinationX: " + destinationX + "\ndestinationY: " + destinationY);

        //get how many tiles we need to move in each direction
        var deltaX = destinationX - this.sprite.xCoord;
        var deltaY = destinationY - this.sprite.yCoord;

        console.log("deltaX: " + deltaX + "\ndeltaY: " + deltaY);

        //find out how far the total distance actually is
        this.fullDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

        //figure out if we need to move in the positive or negative direction (value will always be 1 or -1. If we divide 0/0 and get NaN, assign value to positive 1
        var xNegativeMultiplier = deltaX / Math.abs(deltaX) || 1;
        var yNegativeMultiplier = deltaY / Math.abs(deltaY) || 1;

        //get ready for multipliers
        this.maxX = 0;
        this.maxY = 0;

        //determine the multiplier for the max speed of each direction, so the sprite can get to its destination as quickly as possible
        if (Math.abs(deltaX) > Math.abs(deltaY)) {
            this.maxY = (deltaY / deltaX) * yNegativeMultiplier;
            this.maxX = 1.0 * xNegativeMultiplier;
        } else if (deltaX == deltaY) {
            this.maxX = 1.0 * xNegativeMultiplier;
            this.maxY = 1.0 * yNegativeMultiplier;
        } else {
            this.maxY = 1.0 * yNegativeMultiplier;
            this.maxX = (deltaX / deltaY) * xNegativeMultiplier;
        }
    }
}

//persitent data
var currentSpriteID = 0;
class Sprite {
    //constructor
    constructor() {
            this.id = currentSpriteID;
            this.xCoord = 0;
            this.yCoord = 0;
            this.image = new Raster();
            this.hasAttachedAnimation = false;

            //increment sprite ID before more instance creation can occur
            currentSpriteID++;
        }
        //sets the image based on the passed URL and then once the image is completed loading, continues the program flow based on the value of destination.next();
    setImage(URL, destination) {
            this.image = null;
            this.image = new Raster(URL);
            //alert(image.width);
            var tempThis = this;
            this.image.onLoad = function () {
                tempThis.setImageSize();
                //setLocation(xCoord, yCoord);
                destination.next();
            };
        }
        //sets the position of the sprite based on an X/Y coordinate (instant)
    setLocation(x, y) {
        var imageXCenter = this.image.width / 2;
        var imageYCenter = this.image.height / 2;

        var canvas = document.getElementById("board");
        var canvasWidth = canvas.width;
        var canvasHeight = canvas.height;

        var tileWidth = canvasWidth / 10;
        var tileHeight = canvasHeight / 10;

        //set position based on passed arguments and tile dimensions
        this.image.position = new Point(imageXCenter + tileWidth * x, imageYCenter + tileHeight * y);
        this.xCoord = x;
        this.yCoord = y;
    }
    move(direction, numSpaces, speed, destination) {
        //sanitize the string to remove any obscure characters
        direction = direction.replace(/[^a-zA-Z0-9! ]+/g, "");
        //make it all lower case for consistency
        direction = direction.toLowerCase();

        //get existing coordinates for further use and instantiate the final value variables
        var finalX = this.xCoord;
        var finalY = this.yCoord;

        //decide where we need to go
        if (direction == "left") {
            finalX -= numSpaces;
        } else if (direction == "right") {
            finalX += numSpaces;
        } else if (direction == "down") {
            finalY += numSpaces;
        } else if (direction == "up") {
            finalY -= numSpaces;
        } else {
            //they screwed up, the program can't continue so let's just throw an error and let them know
            throw "Direction invalid. Try the directions left, right, up, or down";
        }
        //animate it!
        this.animate(finalX, finalY, speed, null, destination);
        //update existing coordinate values
        this.yCoord = finalY;
        this.xCoord = finalX;
    }
    moveTo(x, y, speed, destination) {
            //animate it!
            this.animate(x, y, speed, null, destination);
            //update existing coordinate values
            this.yCoord = y;
            this.xCoord = x;
        }
        //appropriately size image for canvas
    setImageSize() {
        var canvas = document.getElementById("board");
        var canvasWidth = canvas.width;
        var canvasHeight = canvas.height;

        var tileWidth = canvasWidth / 10;
        var tileHeight = canvasHeight / 10;
        //get image width and height
        var imageWidth = this.image.width;
        var imageHeight = this.image.height;

        //scale image so it appropriately fits in the grid
        if (tileWidth - 5 < imageWidth || tileHeight - 5 < imageHeight) {
            if (imageWidth > imageHeight) {
                var scaleFactor = (tileWidth - 5) / imageWidth;
                this.image.width = tileWidth - 5;
                this.image.height = this.image.height * scaleFactor;
            } else if (imageWidth < imageHeight) {
                var scaleFactor = (tileHeight - 5) / imageHeight;
                this.image.width = this.image.width * scaleFactor;
                this.image.height = tileHeight - 5;
            } else {
                this.image.width = tileWidth - 5;
                this.image.height = tileHeight - 5;
            }
        }

    }
    animate(destinationX, destinationY, speed, rotateTimes, destination) {
        //create a new animation request
        console.log("Request new animation");
        var animation = new AnimationRequest(this, destination, destinationX, destinationY, null, speed);
        animationRequests.push(animation);

    }

}

var animationRequests = [];

function onFrame(event) {
    if (animationRequests.length != 0) {

        //get canvas size
        var canvas = document.getElementById("board");
        var canvasWidth = canvas.width;
        var canvasHeight = canvas.height;

        //get tile width for accurate calculations
        var tileWidth = canvasWidth / 10;
        var tileHeight = canvasHeight / 10;

        if (animationRequests[0].timesExecuted == animationRequests[0].fullDistance * tileWidth) {
            animationRequests[0].callBack.next();
            animationRequests.splice(0, 1);
            return;
        }

        animationRequests[0].sprite.image.position.x += 1 * animationRequests[0].maxX;
        animationRequests[0].sprite.image.position.y += 1 * animationRequests[0].maxY;
        animationRequests[0].timesExecuted++;
    }
}<commit_msg>Fix directional animation problems<commit_after>"use strict";
var debug = true;

//create custom splice method. From user113716 @ http://stackoverflow.com/questions/4313841/javascript-how-can-i-insert-a-string-at-a-specific-index
String.prototype.splice = function (idx, rem, s) {
    return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
};

//handle document load
$(document).ready(function () {
    paper.install(window);

    paper.setup('board');
    setCanvasSize();
    drawCanvasGrid();

    //set animation
    paper.view.attach('frame', onFrame);

});

//get the grid setup
function drawCanvasGrid() {
    //get canvas width and height
    var canvas = document.getElementById("board");
    var canvasWidth = canvas.width;
    var canvasHeight = canvas.height;

    for (var i = 0; i < 10; i++) {
        //vertical lines
        var path = new Path();
        path.strokeColor = 'black';
        path.moveTo(canvas.width * (i / 10), 0);
        path.lineTo(canvas.width * (i / 10), canvasHeight);
        view.draw();

        //horizontal lines
        var path2 = new Path();
        path2.strokeColor = 'black';
        path2.moveTo(0, canvas.height * (i / 10));
        path2.lineTo(canvasWidth, canvas.height * (i / 10));
        view.draw()
    }

}

//refresh the canvas grid when the browser resizes
$(window).resize(function () {
    setCanvasSize();
    drawCanvasGrid();
});
//keep canvas size consistent to prevent blurring
function setCanvasSize() {
    /*var canvas = document.getElementById('board');
    var canvasWidth = $(window).width() * .45;
    var canvasHeight = $(window).width() * .45;
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;*/
}
//from Tim Down @ http://stackoverflow.com/questions/3410464/how-to-find-all-occurrences-of-one-string-in-another-in-javascript
function getIndicesOf(searchStr, str, caseSensitive) {
    var startIndex = 0,
        searchStrLen = searchStr.length;
    var index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
        indices.push(index);
        startIndex = index + searchStrLen;
    }
    return indices;
}

//check for likely new statements
function isNewStatementCharacter(character) {
    if (character == ' ' || character == ';' || character == ')' || character == '}' || character == '\n' || character == '\t')
        return true;
    else
        return false;
}

//finds the incdices of the items that need to have callback statements for synchronous code running
function getReplaceIndices(code) {
    var imageIndices = getIndicesOf(".setImage(", code, false);
    var moveIndices = getIndicesOf(".move(", code, false);
    var moveToIndices = getIndicesOf(".moveTo(", code, false);

    return imageIndices.concat(moveIndices).concat(moveToIndices);
}

//compile code to avoid async results conflicting
function compileCode(code) {
    var searchIndices = getReplaceIndices(code);
    //iterate through all necessary changes
    for (var i = 0; i < searchIndices.length; i++) {
        var innerCounter = searchIndices[i];

        //get index of where we should insert this time
        innerCounter = code.indexOf(")", innerCounter);

        //splice the calling function in
        var firstSplice = ",{next : function(){goToStatement" + i + "();}}";
        code = code.splice(innerCounter, 0, firstSplice);
        innerCounter += firstSplice.length + 2;

        //splice the destination
        code = code.splice(innerCounter, 0, "\nfunction goToStatement" + i + "(){");
        var tempLocation = searchIndices[i];
        while (code.charAt(tempLocation) != "\n")
            tempLocation--;
        if (code.charAt(tempLocation + 1) == "\\" && code.charAt(tempLocation + 2))
            code = code + "\n}";
        else
            code = code + "}";

        //reset the indices because the string length has changed
        searchIndices = getReplaceIndices(code);
    }
    return code;
}

/*
var sprite = new Sprite();
sprite.setImage("img/giphy.gif");
sprite.setLocation(1,1);
sprite.move("left",1,1);
sprite.move("up",1,1);
sprite.move("right",5,1);
sprite.moveTo(4,3,1);

var sprite2 = Sprite.create();
sprite2.setImage("http://media.giphy.com/media/cqqY4tX61jof6/giphy.gif");
sprite2.move();
*/

//compileCode('var sprite = Sprite.create();sprite.setImage("http://media.giphy.com/media/cqqY4tX61jof6/giphy.gif");sprite.move();');

//run student code
function runCode() {
    project.clear();
    drawCanvasGrid();
    var code = "";
    if (debug) {
        code = compileCode(myCodeMirror.getValue());
        //code = myCodeMirror.getValue();
    } else {
        code = "try{" + compileCode(myCodeMirror.getValue()) + "}catch(err) {alert(err.message)}";
    }
    window.eval(code);
}

class AnimationRequest {
    constructor(sprite, callBack, destinationX, destinationY, rotations, speed) {
        this.sprite = sprite;
        this.callBack = callBack;
        this.rotations = rotations;
        this.speed = speed;
        this.timesExecuted = 0;

        //get how many tiles we need to move in each direction
        var deltaX = destinationX - this.sprite.xCoord;
        var deltaY = destinationY - this.sprite.yCoord;

        //find out how far the total distance actually is
        this.fullDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));

        //figure out if we need to move in the positive or negative direction (value will always be 1 or -1. If we divide 0/0 and get NaN, assign value to positive 1
        var xNegativeMultiplier = deltaX / Math.abs(deltaX) || 1;
        var yNegativeMultiplier = deltaY / Math.abs(deltaY) || 1;

        //get ready for multipliers
        this.maxX = 0;
        this.maxY = 0;

        //determine the multiplier for the max speed of each direction, so the sprite can get to its destination as quickly as possible
        if (Math.abs(deltaX) > Math.abs(deltaY)) {
            this.maxY = Math.abs(deltaY / deltaX) * yNegativeMultiplier;
            this.maxX = 1.0 * xNegativeMultiplier;
        } else if (deltaX == deltaY) {
            this.maxX = 1.0 * xNegativeMultiplier;
            this.maxY = 1.0 * yNegativeMultiplier;
        } else {
            this.maxY = 1.0 * yNegativeMultiplier;
            this.maxX = Math.abs(deltaX / deltaY) * xNegativeMultiplier;
        }
    }
}

//persitent data
var currentSpriteID = 0;
class Sprite {
    //constructor
    constructor() {
            this.id = currentSpriteID;
            this.xCoord = 0;
            this.yCoord = 0;
            this.image = new Raster();
            this.hasAttachedAnimation = false;

            //increment sprite ID before more instance creation can occur
            currentSpriteID++;
        }
        //sets the image based on the passed URL and then once the image is completed loading, continues the program flow based on the value of destination.next();
    setImage(URL, destination) {
            this.image = null;
            this.image = new Raster(URL);
            //alert(image.width);
            var tempThis = this;
            this.image.onLoad = function () {
                tempThis.setImageSize();
                //setLocation(xCoord, yCoord);
                destination.next();
            };
        }
        //sets the position of the sprite based on an X/Y coordinate (instant)
    setLocation(x, y) {
        var imageXCenter = this.image.width / 2;
        var imageYCenter = this.image.height / 2;

        var canvas = document.getElementById("board");
        var canvasWidth = canvas.width;
        var canvasHeight = canvas.height;

        var tileWidth = canvasWidth / 10;
        var tileHeight = canvasHeight / 10;

        //set position based on passed arguments and tile dimensions
        this.image.position = new Point(imageXCenter + tileWidth * x, imageYCenter + tileHeight * y);
        this.xCoord = x;
        this.yCoord = y;
    }
    move(direction, numSpaces, speed, destination) {
        //sanitize the string to remove any obscure characters
        direction = direction.replace(/[^a-zA-Z0-9! ]+/g, "");
        //make it all lower case for consistency
        direction = direction.toLowerCase();

        //get existing coordinates for further use and instantiate the final value variables
        var finalX = this.xCoord;
        var finalY = this.yCoord;

        //decide where we need to go
        if (direction == "left") {
            finalX -= numSpaces;
        } else if (direction == "right") {
            finalX += numSpaces;
        } else if (direction == "down") {
            finalY += numSpaces;
        } else if (direction == "up") {
            finalY -= numSpaces;
        } else {
            //they screwed up, the program can't continue so let's just throw an error and let them know
            throw "Direction invalid. Try the directions left, right, up, or down";
        }
        //animate it!
        this.animate(finalX, finalY, speed, null, destination);
        //update existing coordinate values
        this.yCoord = finalY;
        this.xCoord = finalX;
    }
    moveTo(x, y, speed, destination) {
            //animate it!
            this.animate(x, y, speed, null, destination);
            //update existing coordinate values
            this.yCoord = y;
            this.xCoord = x;
        }
        //appropriately size image for canvas
    setImageSize() {
        var canvas = document.getElementById("board");
        var canvasWidth = canvas.width;
        var canvasHeight = canvas.height;

        var tileWidth = canvasWidth / 10;
        var tileHeight = canvasHeight / 10;
        //get image width and height
        var imageWidth = this.image.width;
        var imageHeight = this.image.height;

        //scale image so it appropriately fits in the grid
        if (tileWidth - 5 < imageWidth || tileHeight - 5 < imageHeight) {
            if (imageWidth > imageHeight) {
                var scaleFactor = (tileWidth - 5) / imageWidth;
                this.image.width = tileWidth - 5;
                this.image.height = this.image.height * scaleFactor;
            } else if (imageWidth < imageHeight) {
                var scaleFactor = (tileHeight - 5) / imageHeight;
                this.image.width = this.image.width * scaleFactor;
                this.image.height = tileHeight - 5;
            } else {
                this.image.width = tileWidth - 5;
                this.image.height = tileHeight - 5;
            }
        }

    }
    animate(destinationX, destinationY, speed, rotateTimes, destination) {
        //create a new animation request
        console.log("Request new animation");
        var animation = new AnimationRequest(this, destination, destinationX, destinationY, null, speed);
        animationRequests.push(animation);

    }

}

var animationRequests = [];

function onFrame(event) {
    if (animationRequests.length != 0) {

        //get canvas size
        var canvas = document.getElementById("board");
        var canvasWidth = canvas.width;
        var canvasHeight = canvas.height;

        //get tile width for accurate calculations
        var tileWidth = canvasWidth / 10;
        var tileHeight = canvasHeight / 10;

        if (animationRequests[0].timesExecuted >= animationRequests[0].fullDistance * tileWidth) {
            animationRequests[0].callBack.next();
            animationRequests.splice(0, 1);
            return;
        }

        animationRequests[0].sprite.image.position.x += 1 * animationRequests[0].maxX;
        animationRequests[0].sprite.image.position.y += 1 * animationRequests[0].maxY;
        animationRequests[0].timesExecuted++;
    }
}<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

couchTests.attachments_multipart= function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;

  // mime multipart

  xhr = CouchDB.request("PUT", "/test_suite_db/multipart", {
    headers: {"Content-Type": "multipart/related;boundary=\"abc123\""},
    body:
      "--abc123\r\n" +
      "content-type: application/json\r\n" +
      "\r\n" +
      JSON.stringify({
        "body":"This is a body.",
        "_attachments":{
          "foo.txt": {
            "follows":true,
            "content_type":"application/test",
            "length":21
            },
          "bar.txt": {
            "follows":true,
            "content_type":"application/test",
            "length":20
            },
          "baz.txt": {
            "follows":true,
            "content_type":"application/test",
            "length":19
            }
          }
        }) +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 21 chars long" +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 20 chars lon" +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 19 chars lo" +
      "\r\n--abc123--"
    });

  var result = JSON.parse(xhr.responseText);

  T(result.ok);

  TEquals(201, xhr.status, "should send 201 Accepted");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/foo.txt");

  T(xhr.responseText == "this is 21 chars long");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/bar.txt");

  T(xhr.responseText == "this is 20 chars lon");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/baz.txt");

  T(xhr.responseText == "this is 19 chars lo");

  // now edit an attachment

  var doc = db.open("multipart");
  var firstrev = doc._rev;

  T(doc._attachments["foo.txt"].stub == true);
  T(doc._attachments["bar.txt"].stub == true);
  T(doc._attachments["baz.txt"].stub == true);

  //lets change attachment bar
  delete doc._attachments["bar.txt"].stub; // remove stub member (or could set to false)
  doc._attachments["bar.txt"].length = 18;
  doc._attachments["bar.txt"].follows = true;
  //lets delete attachment baz:
  delete doc._attachments["baz.txt"];

  var xhr = CouchDB.request("PUT", "/test_suite_db/multipart", {
    headers: {"Content-Type": "multipart/related;boundary=\"abc123\""},
    body:
      "--abc123\r\n" +
      "content-type: application/json\r\n" +
      "\r\n" +
      JSON.stringify(doc) +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 18 chars l" +
      "\r\n--abc123--"
    });

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/bar.txt");

  T(xhr.responseText == "this is 18 chars l");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/baz.txt");
  T(xhr.status == 404);

  // now test receiving multipart docs

  function getBoundary(xhr) {
    if (xhr instanceof XMLHttpRequest) {
      var ctype = xhr.getResponseHeader("Content-Type");
    } else {
      var ctype = xhr.headers['Content-Type'];
    }
    var ctypeArgs = ctype.split("; ").slice(1);
    var boundary = null;
    for(var i=0; i<ctypeArgs.length; i++) {
      if (ctypeArgs[i].indexOf("boundary=") == 0) {
        boundary = ctypeArgs[i].split("=")[1];
        if (boundary.charAt(0) == '"') {
          // stringified boundary, parse as json
          // (will maybe not if there are escape quotes)
          boundary = JSON.parse(boundary);
        }
      }
    }
    return boundary;
  }

  function parseMultipart(xhr) {
    var boundary = getBoundary(xhr);
    if (xhr instanceof XMLHttpRequest) {
      var mimetext = xhr.responseText;
    } else {
      var mimetext = xhr.body;
    }
    // strip off leading boundary
    var leading = "--" + boundary + "\r\n";
    var last = "\r\n--" + boundary + "--";

    // strip off leading and trailing boundary
    var leadingIdx = mimetext.indexOf(leading) + leading.length;
    var trailingIdx = mimetext.indexOf(last);
    mimetext = mimetext.slice(leadingIdx, trailingIdx);

    // now split the sections
    var sections = mimetext.split(new RegExp("\\r\\n--" + boundary));

    // spilt out the headers for each section
    for(var i=0; i < sections.length; i++) {
      var section = sections[i];
      var headerEndIdx = section.indexOf("\r\n\r\n");
      var headersraw = section.slice(0, headerEndIdx).split(/\r\n/);
      var body = section.slice(headerEndIdx + 4);
      var headers = {};
      for(var j=0; j<headersraw.length; j++) {
        var tmp = headersraw[j].split(": ");
        headers[tmp[0]] = tmp[1];
      }
      sections[i] = {"headers":headers, "body":body};
    }

    return sections;
  }

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?attachments=true",
    {headers:{"accept": "multipart/related,*/*;"}});

  T(xhr.status == 200);

  // parse out the multipart

  var sections = parseMultipart(xhr);

  T(sections.length == 3);

  // The first section is the json doc. Check it's content-type. It contains
  // the metadata for all the following attachments

  T(sections[0].headers['content-type'] == "application/json");

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].follows == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 21 chars long");
  T(sections[2].body == "this is 18 chars l");

  // now get attachments incrementally (only the attachments changes since
  // a certain rev).

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?atts_since=[\"" + firstrev + "\"]",
    {headers:{"accept": "multipart/related, */*"}});

  T(xhr.status == 200);

  var sections = parseMultipart(xhr);

  T(sections.length == 2);

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].stub == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 18 chars l");

  // try the atts_since parameter together with the open_revs parameter
  xhr = CouchDB.request(
    "GET",
    '/test_suite_db/multipart?open_revs=["' +
      doc._rev + '"]&atts_since=["' + firstrev + '"]',
    {headers: {"accept": "multipart/mixed"}}
  );

  T(xhr.status === 200);

  sections = parseMultipart(xhr);
  // 1 section, with a multipart/related Content-Type
  T(sections.length === 1);
  T(sections[0].headers['Content-Type'].indexOf('multipart/related;') === 0);

  var innerSections = parseMultipart(sections[0]);
  // 2 inner sections: a document body section plus an attachment data section
  T(innerSections.length === 2);
  T(innerSections[0].headers['content-type'] === 'application/json');

  doc = JSON.parse(innerSections[0].body);

  T(doc._attachments['foo.txt'].stub === true);
  T(doc._attachments['bar.txt'].follows === true);

  T(innerSections[1].body === "this is 18 chars l");

  // try it with a rev that doesn't exist (should get all attachments)

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?atts_since=[\"1-2897589\"]",
    {headers:{"accept": "multipart/related,*/*;"}});

  T(xhr.status == 200);

  var sections = parseMultipart(xhr);

  T(sections.length == 3);

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].follows == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 21 chars long");
  T(sections[2].body == "this is 18 chars l");

  // try it with a rev that doesn't exist, and one that does

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?atts_since=[\"1-2897589\",\"" + firstrev + "\"]",
    {headers:{"accept": "multipart/related,*/*;"}});

  T(xhr.status == 200);

  var sections = parseMultipart(xhr);

  T(sections.length == 2);

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].stub == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 18 chars l");

  // check that with the document multipart/mixed API it's possible to receive
  // attachments in compressed form (if they're stored in compressed form)

  var server_config = [
    {
      section: "attachments",
      key: "compression_level",
      value: "8"
    },
    {
      section: "attachments",
      key: "compressible_types",
      value: "text/plain"
    }
  ];

  function testMultipartAttCompression() {
    var doc = { _id: "foobar" };
    var lorem =
      CouchDB.request("GET", "/_utils/script/test/lorem.txt").responseText;
    var helloData = "hello world";

    TEquals(true, db.save(doc).ok);

    var firstRev = doc._rev;
    var xhr = CouchDB.request(
      "PUT",
      "/" + db.name + "/" + doc._id + "/data.bin?rev=" + firstRev,
      {
        body: helloData,
        headers: {"Content-Type": "application/binary"}
      }
    );
    TEquals(201, xhr.status);

    var secondRev = db.open(doc._id)._rev;
    xhr = CouchDB.request(
      "PUT",
      "/" + db.name + "/" + doc._id + "/lorem.txt?rev=" + secondRev,
      {
        body: lorem,
        headers: {"Content-Type": "text/plain"}
      }
    );
    TEquals(201, xhr.status);

    var thirdRev = db.open(doc._id)._rev;

    xhr = CouchDB.request(
      "GET",
      '/' + db.name + '/' + doc._id + '?open_revs=["' + thirdRev + '"]',
      {
        headers: {
          "Accept": "multipart/mixed",
          "X-CouchDB-Send-Encoded-Atts": "true"
        }
      }
    );
    TEquals(200, xhr.status);

    var sections = parseMultipart(xhr);
    // 1 section, with a multipart/related Content-Type
    TEquals(1, sections.length);
    TEquals(0,
      sections[0].headers['Content-Type'].indexOf('multipart/related;'));

    var innerSections = parseMultipart(sections[0]);
    // 3 inner sections: a document body section plus 2 attachment data sections
    TEquals(3, innerSections.length);
    TEquals('application/json', innerSections[0].headers['content-type']);

    doc = JSON.parse(innerSections[0].body);

    TEquals(true, doc._attachments['lorem.txt'].follows);
    TEquals("gzip", doc._attachments['lorem.txt'].encoding);
    TEquals(true, doc._attachments['data.bin'].follows);
    T(doc._attachments['data.bin'] !== "gzip");

    if (innerSections[1].body === helloData) {
      T(innerSections[2].body !== lorem);
    } else if (innerSections[2].body === helloData) {
      T(innerSections[1].body !== lorem);
    } else {
      T(false, "Could not found data.bin attachment data");
    }

    // now test that it works together with the atts_since parameter

    xhr = CouchDB.request(
      "GET",
      '/' + db.name + '/' + doc._id + '?open_revs=["' + thirdRev + '"]' +
        '&atts_since=["' + secondRev + '"]',
      {
        headers: {
          "Accept": "multipart/mixed",
          "X-CouchDB-Send-Encoded-Atts": "true"
        }
      }
    );
    TEquals(200, xhr.status);

    sections = parseMultipart(xhr);
    // 1 section, with a multipart/related Content-Type
    TEquals(1, sections.length);
    TEquals(0,
      sections[0].headers['Content-Type'].indexOf('multipart/related;'));

    innerSections = parseMultipart(sections[0]);
    // 2 inner sections: a document body section plus 1 attachment data section
    TEquals(2, innerSections.length);
    TEquals('application/json', innerSections[0].headers['content-type']);

    doc = JSON.parse(innerSections[0].body);

    TEquals(true, doc._attachments['lorem.txt'].follows);
    TEquals("gzip", doc._attachments['lorem.txt'].encoding);
    TEquals("undefined", typeof doc._attachments['data.bin'].follows);
    TEquals(true, doc._attachments['data.bin'].stub);
    T(innerSections[1].body !== lorem);
  }

  run_on_modified_server(server_config, testMultipartAttCompression);

  // cleanup
  db.deleteDb();
};
<commit_msg>Add missing option to multipart/related GETs<commit_after>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

couchTests.attachments_multipart= function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;

  // mime multipart

  xhr = CouchDB.request("PUT", "/test_suite_db/multipart", {
    headers: {"Content-Type": "multipart/related;boundary=\"abc123\""},
    body:
      "--abc123\r\n" +
      "content-type: application/json\r\n" +
      "\r\n" +
      JSON.stringify({
        "body":"This is a body.",
        "_attachments":{
          "foo.txt": {
            "follows":true,
            "content_type":"application/test",
            "length":21
            },
          "bar.txt": {
            "follows":true,
            "content_type":"application/test",
            "length":20
            },
          "baz.txt": {
            "follows":true,
            "content_type":"text/plain",
            "length":19
            }
          }
        }) +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 21 chars long" +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 20 chars lon" +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 19 chars lo" +
      "\r\n--abc123--"
    });

  var result = JSON.parse(xhr.responseText);

  T(result.ok);

  TEquals(201, xhr.status, "should send 201 Accepted");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/foo.txt");

  T(xhr.responseText == "this is 21 chars long");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/bar.txt");

  T(xhr.responseText == "this is 20 chars lon");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/baz.txt");

  T(xhr.responseText == "this is 19 chars lo");

  // now edit an attachment

  var doc = db.open("multipart", {att_encoding_info: true});
  var firstrev = doc._rev;

  T(doc._attachments["foo.txt"].stub == true);
  T(doc._attachments["bar.txt"].stub == true);
  T(doc._attachments["baz.txt"].stub == true);
  TEquals("undefined", typeof doc._attachments["foo.txt"].encoding);
  TEquals("undefined", typeof doc._attachments["bar.txt"].encoding);
  TEquals("gzip", doc._attachments["baz.txt"].encoding);

  //lets change attachment bar
  delete doc._attachments["bar.txt"].stub; // remove stub member (or could set to false)
  doc._attachments["bar.txt"].length = 18;
  doc._attachments["bar.txt"].follows = true;
  //lets delete attachment baz:
  delete doc._attachments["baz.txt"];

  var xhr = CouchDB.request("PUT", "/test_suite_db/multipart", {
    headers: {"Content-Type": "multipart/related;boundary=\"abc123\""},
    body:
      "--abc123\r\n" +
      "content-type: application/json\r\n" +
      "\r\n" +
      JSON.stringify(doc) +
      "\r\n--abc123\r\n" +
      "\r\n" +
      "this is 18 chars l" +
      "\r\n--abc123--"
    });

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/bar.txt");

  T(xhr.responseText == "this is 18 chars l");

  xhr = CouchDB.request("GET", "/test_suite_db/multipart/baz.txt");
  T(xhr.status == 404);

  // now test receiving multipart docs

  function getBoundary(xhr) {
    if (xhr instanceof XMLHttpRequest) {
      var ctype = xhr.getResponseHeader("Content-Type");
    } else {
      var ctype = xhr.headers['Content-Type'];
    }
    var ctypeArgs = ctype.split("; ").slice(1);
    var boundary = null;
    for(var i=0; i<ctypeArgs.length; i++) {
      if (ctypeArgs[i].indexOf("boundary=") == 0) {
        boundary = ctypeArgs[i].split("=")[1];
        if (boundary.charAt(0) == '"') {
          // stringified boundary, parse as json
          // (will maybe not if there are escape quotes)
          boundary = JSON.parse(boundary);
        }
      }
    }
    return boundary;
  }

  function parseMultipart(xhr) {
    var boundary = getBoundary(xhr);
    if (xhr instanceof XMLHttpRequest) {
      var mimetext = xhr.responseText;
    } else {
      var mimetext = xhr.body;
    }
    // strip off leading boundary
    var leading = "--" + boundary + "\r\n";
    var last = "\r\n--" + boundary + "--";

    // strip off leading and trailing boundary
    var leadingIdx = mimetext.indexOf(leading) + leading.length;
    var trailingIdx = mimetext.indexOf(last);
    mimetext = mimetext.slice(leadingIdx, trailingIdx);

    // now split the sections
    var sections = mimetext.split(new RegExp("\\r\\n--" + boundary));

    // spilt out the headers for each section
    for(var i=0; i < sections.length; i++) {
      var section = sections[i];
      var headerEndIdx = section.indexOf("\r\n\r\n");
      var headersraw = section.slice(0, headerEndIdx).split(/\r\n/);
      var body = section.slice(headerEndIdx + 4);
      var headers = {};
      for(var j=0; j<headersraw.length; j++) {
        var tmp = headersraw[j].split(": ");
        headers[tmp[0]] = tmp[1];
      }
      sections[i] = {"headers":headers, "body":body};
    }

    return sections;
  }

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?attachments=true",
    {headers:{"accept": "multipart/related,*/*;"}});

  T(xhr.status == 200);

  // parse out the multipart

  var sections = parseMultipart(xhr);

  T(sections.length == 3);

  // The first section is the json doc. Check it's content-type. It contains
  // the metadata for all the following attachments

  T(sections[0].headers['content-type'] == "application/json");

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].follows == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 21 chars long");
  T(sections[2].body == "this is 18 chars l");

  // now get attachments incrementally (only the attachments changes since
  // a certain rev).

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?atts_since=[\"" + firstrev + "\"]",
    {headers:{"accept": "multipart/related, */*"}});

  T(xhr.status == 200);

  var sections = parseMultipart(xhr);

  T(sections.length == 2);

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].stub == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 18 chars l");

  // try the atts_since parameter together with the open_revs parameter
  xhr = CouchDB.request(
    "GET",
    '/test_suite_db/multipart?open_revs=["' +
      doc._rev + '"]&atts_since=["' + firstrev + '"]',
    {headers: {"accept": "multipart/mixed"}}
  );

  T(xhr.status === 200);

  sections = parseMultipart(xhr);
  // 1 section, with a multipart/related Content-Type
  T(sections.length === 1);
  T(sections[0].headers['Content-Type'].indexOf('multipart/related;') === 0);

  var innerSections = parseMultipart(sections[0]);
  // 2 inner sections: a document body section plus an attachment data section
  T(innerSections.length === 2);
  T(innerSections[0].headers['content-type'] === 'application/json');

  doc = JSON.parse(innerSections[0].body);

  T(doc._attachments['foo.txt'].stub === true);
  T(doc._attachments['bar.txt'].follows === true);

  T(innerSections[1].body === "this is 18 chars l");

  // try it with a rev that doesn't exist (should get all attachments)

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?atts_since=[\"1-2897589\"]",
    {headers:{"accept": "multipart/related,*/*;"}});

  T(xhr.status == 200);

  var sections = parseMultipart(xhr);

  T(sections.length == 3);

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].follows == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 21 chars long");
  T(sections[2].body == "this is 18 chars l");

  // try it with a rev that doesn't exist, and one that does

  xhr = CouchDB.request("GET", "/test_suite_db/multipart?atts_since=[\"1-2897589\",\"" + firstrev + "\"]",
    {headers:{"accept": "multipart/related,*/*;"}});

  T(xhr.status == 200);

  var sections = parseMultipart(xhr);

  T(sections.length == 2);

  var doc = JSON.parse(sections[0].body);

  T(doc._attachments['foo.txt'].stub == true);
  T(doc._attachments['bar.txt'].follows == true);

  T(sections[1].body == "this is 18 chars l");

  // check that with the document multipart/mixed API it's possible to receive
  // attachments in compressed form (if they're stored in compressed form)

  var server_config = [
    {
      section: "attachments",
      key: "compression_level",
      value: "8"
    },
    {
      section: "attachments",
      key: "compressible_types",
      value: "text/plain"
    }
  ];

  function testMultipartAttCompression() {
    var doc = { _id: "foobar" };
    var lorem =
      CouchDB.request("GET", "/_utils/script/test/lorem.txt").responseText;
    var helloData = "hello world";

    TEquals(true, db.save(doc).ok);

    var firstRev = doc._rev;
    var xhr = CouchDB.request(
      "PUT",
      "/" + db.name + "/" + doc._id + "/data.bin?rev=" + firstRev,
      {
        body: helloData,
        headers: {"Content-Type": "application/binary"}
      }
    );
    TEquals(201, xhr.status);

    var secondRev = db.open(doc._id)._rev;
    xhr = CouchDB.request(
      "PUT",
      "/" + db.name + "/" + doc._id + "/lorem.txt?rev=" + secondRev,
      {
        body: lorem,
        headers: {"Content-Type": "text/plain"}
      }
    );
    TEquals(201, xhr.status);

    var thirdRev = db.open(doc._id)._rev;

    xhr = CouchDB.request(
      "GET",
      '/' + db.name + '/' + doc._id + '?open_revs=["' + thirdRev + '"]',
      {
        headers: {
          "Accept": "multipart/mixed",
          "X-CouchDB-Send-Encoded-Atts": "true"
        }
      }
    );
    TEquals(200, xhr.status);

    var sections = parseMultipart(xhr);
    // 1 section, with a multipart/related Content-Type
    TEquals(1, sections.length);
    TEquals(0,
      sections[0].headers['Content-Type'].indexOf('multipart/related;'));

    var innerSections = parseMultipart(sections[0]);
    // 3 inner sections: a document body section plus 2 attachment data sections
    TEquals(3, innerSections.length);
    TEquals('application/json', innerSections[0].headers['content-type']);

    doc = JSON.parse(innerSections[0].body);

    TEquals(true, doc._attachments['lorem.txt'].follows);
    TEquals("gzip", doc._attachments['lorem.txt'].encoding);
    TEquals(true, doc._attachments['data.bin'].follows);
    T(doc._attachments['data.bin'] !== "gzip");

    if (innerSections[1].body === helloData) {
      T(innerSections[2].body !== lorem);
    } else if (innerSections[2].body === helloData) {
      T(innerSections[1].body !== lorem);
    } else {
      T(false, "Could not found data.bin attachment data");
    }

    // now test that it works together with the atts_since parameter

    xhr = CouchDB.request(
      "GET",
      '/' + db.name + '/' + doc._id + '?open_revs=["' + thirdRev + '"]' +
        '&atts_since=["' + secondRev + '"]',
      {
        headers: {
          "Accept": "multipart/mixed",
          "X-CouchDB-Send-Encoded-Atts": "true"
        }
      }
    );
    TEquals(200, xhr.status);

    sections = parseMultipart(xhr);
    // 1 section, with a multipart/related Content-Type
    TEquals(1, sections.length);
    TEquals(0,
      sections[0].headers['Content-Type'].indexOf('multipart/related;'));

    innerSections = parseMultipart(sections[0]);
    // 2 inner sections: a document body section plus 1 attachment data section
    TEquals(2, innerSections.length);
    TEquals('application/json', innerSections[0].headers['content-type']);

    doc = JSON.parse(innerSections[0].body);

    TEquals(true, doc._attachments['lorem.txt'].follows);
    TEquals("gzip", doc._attachments['lorem.txt'].encoding);
    TEquals("undefined", typeof doc._attachments['data.bin'].follows);
    TEquals(true, doc._attachments['data.bin'].stub);
    T(innerSections[1].body !== lorem);
  }

  run_on_modified_server(server_config, testMultipartAttCompression);

  // cleanup
  db.deleteDb();
};
<|endoftext|>


<commit_before>var count = 0;
var idTest = "";
function createDivFailedTest(contentDiv,className,divParent,divName,file,line,message,code) {

	idTest = "idTest"+count;
	var div = document.createElement('div');
	div.id = divName;
	div.className  = className;
	var content = document.getElementById(divParent);

	div.innerHTML = '
'+contentDiv+'
'
			+'
+'+line+'
'
			+'
'+file+'
'
			+'
'+message+'<input type="image" src="images/bullet_arrow_down1.png" title="Show code" class="classButton" data-idtest='+"#"+idTest+' data-file='+file+' data-line='+line+' data-test='+contentDiv+'>
';

	content.appendChild(div);

	createDiv("","testInfo totalTests box",divName,idTest);
	count = count + 1;

}

function createDiv(contentDiv,className,divParent,divName) {
	//alert(contentDiv+" --divparent: "+divParent+" --divname "+divName);
	var div = document.createElement('div');
	div.id = divName;
	div.className  = className;
	var content = document.getElementById(divParent);
	div.innerHTML = '
'+contentDiv+"
";
	content.appendChild(div);

}

$(document).ready(function(){

	var countDivs = 0;
	var countFolder = 0;
	var countClass = 0;
	var showedClass = '';
	var showedFolder = '';

	$("#runAllTests").click(function(){
		runAllTests();
	});

	runAllTests = function (){
		$.ajax({
			url:  'http://localhost/PUWI/PUWI_LoadJSON.php',
			dataType: "json",
			type: 'POST',
		    async: true,
			data: {action:'rerun'},

			success: function(request){
				passed = request["passed"];
				failures = request["failures"];
				errors = request["errors"];
				skipped = request["skipped"];
				incomplete = request["incomplete"];
				info = request["infoFailedTests"];
				var last_idTest = "idTest"+(count-1);
				alert (last_idTest);
				$('#title').html('passed: '+passed+' failures: '+failures+' skipped: '+skipped+ ' infoFailedTests: '+info[0]['file']);

				for (i=0; i<passed.length; i++){
					var id = "#"+ passed[i].replace(/:/g,'\\:');
					if($(id).hasClass('testFailed')){
						$(id).removeClass('testFailed').addClass('testOK');
						id = id+' p.fileFT,'+id+' p.red,'+id+' p.italic';
						$(id).empty();
					}else{
						$(id).removeClass('testIncomplete').addClass('testOK');
					}
				}

				for (i=0; i<skipped.length; i++){
					var id = "#"+ skipped[i].replace(/:/g,'\\:');
					if($(id).hasClass('testFailed')){
						$(id).removeClass('testFailed').addClass('testIncomplete');
						id = id+' p.fileFT,'+id+' p.red,'+id+' p.italic';
						$(id).empty();
					}else{
						$(id).removeClass('testOK').addClass('testIncomplete');
					}
				}

				for (i=0; i<failures.length; i++){
					idTest = "idTest"+count;
					var pr ="probando variable";
					var file = info[i]["file"];
					var line = info[i]["line"];
					var id = "#"+ failures[i].replace(/:/g,'\\:');
					var new_codeDiv = 'no';

					if($(id).hasClass('testOK')){
						$(id).removeClass('testOK');
						new_codeDiv = 'yes';
					}else{
						if ($(id).hasClass('testIncomplete')){
							$(id).removeClass('testIncomplete');
							new_codeDiv = 'yes';

						}
					}

					if ($(id).hasClass('testFailed')){
						$(id).removeClass('testFailed');
						remove_content = id+' p.fileFT,'+id+' p.red,'+id+' p.italic';
						$(remove_content).empty();
						$("div.testInfo").remove();

					}

					$(id).addClass('testFailed').
					append('
'+line+'
').
					append('
'+file+'
').
					append('
'+info[i]["message"]+'<input type="image" src="images/bullet_arrow_down1.png" title="Show code2" class="classButton" data-idtest='+"#"+idTest+' data-file='+file+' data-line='+line+' data-test='+"test_setUpWorks"+'>
');

					if (new_codeDiv == 'yes'){
						createDiv(idTest,"testInfo totalTests box",failures[i],idTest);
					}

					count = count + 1;

				}

			},

			error: function(request){
				$('#title').html('request: '+request);
				alert("falla");
			}
		});
	}

	$( ".classButton" ).click(function(){
		var idTest = $(this).data('idtest');
		var file = $(this).data('file');
		var line = $(this).data('line');
		var testName = $(this).data('test');

		$(idTest).slideToggle();
		$.ajax({
			url:  'http://localhost/PUWI/PUWI_LoadJSON.php',
			dataType: "json",
			type: 'POST',
		    async: true,
			data: {action:'displayCode',file:file,line:line,testName:testName},
			success:function(request){
				$(idTest).html('
'+idTest+request['code']+'
');
			},

			error: function(request){
				alert("an error ocurred in ajax request");
			}
		});

	});

	runFirstTime = function (){
		$.ajax({
			url:  'http://localhost/PUWI/PUWI_LoadJSON.php',
			dataType: "json",
			type: 'POST',
		    async: true,
			data: {action:'rerun'},

			success: function(request){
				passed = request["passed"];
				failures = request["failures"];
				errors = request["errors"];
				skipped = request["skipped"];
				incomplete = request["incomplete"];
				groups = request["groups"];
				folders = request["folders"];
				info = request["infoFailedTests"];

				$('#projectName p').html(request["projectName"]);
				if (request["totalTests"] == 0){
					$('.totalTests p').html("
No tests executed!
");
				}else{
					$('.totalTests p').html('
'+request["totalTests"]+' test passing'
											+'<button type="button" id="runAllTests" >Run All Tests</button>'
											+'<button type="button" id="hideTestsOK">Hide/Show Passed Tests</button>
');
				}

				var array_keys = new Array();
				var array_values = new Array();
				for (var group_name in groups) {
				    array_keys.push(group_name);
				    createDiv(group_name,"groupName","content","groupName");
				    var countGroup = countDivs;
				    createDiv('','groupContent', 'content', 'groupName'+countGroup);

				    $.each(groups[group_name], function(key, value) {

					      var classNameTest = getClassNameTest(value, passed, incomplete, skipped, errors);
					      separated_values = value.split("::");
					      var className = separated_values[0];
					      var test = separated_values[1];

					      var folder = getFolder(folders,className);
					      if (!is_showedFolder(folder)){
					    	  countFolder = countDivs;
					    	  createDiv(folder,'grey','groupName'+countGroup,'folderName'+countFolder);

					      }

					      if (!is_showedClass(className)){
					    	  countClass = countDivs;
					    	  createDiv(className,'black','folderName'+countFolder, 'fileName'+countClass);
					      }
					      if (classNameTest == "testFailed box"){
					    	  var failedTest = getInfoFailedTests(value,info);
					    	  createDivFailedTest(test,classNameTest,'fileName'+countClass,className+'::'+test,failedTest['file'],failedTest['line'],
					    			  failedTest['message']);
					      }else{
					    	  createDiv(test,classNameTest,'fileName'+countClass,className+'::'+test);
					      }
					      countDivs++;
					});

				}

			},
			error: function(request){
				$('#title').html('request: '+request);
				alert("falla");
			}
		});
	}

	$("#hideTestsOK").click(function(){
		$(".testOK").slideToggle();
	});

	getClassNameTest = function(value, passed, incomplete, skipped, errors){
		var classNameTest = "";
		if($.inArray(value, passed) > -1){
			classNameTest = "testOK box";
		}else{
			if(($.inArray(value,incomplete) > -1) || ($.inArray(value,skipped) > -1)){
				classNameTest = "testIncomplete box";
			}else{
				classNameTest = "testFailed box";
			}
		}
		return classNameTest;
	}

	getFolder = function(folders,className){
		var result = "";
		 $.each(folders, function(folder, tests) {
			 $.each(folders[folder], function(index, test) {
				 var regex = new RegExp (".*"+className+".*","gi");
				 if (test.match(regex)){
					 result = folder;
				 }

			 });
		});
		return result;
	}

	is_showedClass = function(className){
		if(showedClass == className){
			return true;
		} else {
			showedClass = className;
			return false;
		}
	}

	is_showedFolder = function(folder){
		if(showedFolder == folder){
			return true;
		} else {
			showedFolder = folder;
			return false;
		}
	}

	getInfoFailedTests = function(testName,infoFailedTests){
		var result;
		$.each(infoFailedTests, function(key, value) {
		      if (value['testName'] == testName){
		    	  result = value;
		      }
		});
		return result;
	}

	runFirstTime();

});

<commit_msg>Add folder button<commit_after>

$(document).on('ready',function(){

	var countDivs = 0;
	var countFolder = 0;
	var countClass = 0;
	var showedClass = '';
	var showedFolder = '';

	var count = 0;
	var idTest = "";
	createDiv = function (contentDiv,className,divParent,divName) {
		var div = document.createElement('div');
		div.id = divName;
		div.className  = className;
		var content = document.getElementById(divParent);
		div.innerHTML = '
'+contentDiv+'
';
		content.appendChild(div);

	}
	createDivFailedTest = function (contentDiv,className,divParent,divName,file,line,message,code) {
		var idButton = "showcode"+count;
		idTest = "idTest"+count;
		var div = document.createElement('div');
		div.id = divName;
		div.className  = className;
		var content = document.getElementById(divParent);

		div.innerHTML = '
'+contentDiv+'
'
				+'
+'+line+'
'
				+'
'+file+'
'
				+'
'+message+'<input type="image" src="images/bullet_arrow_down1.png" title="Show code" id='+idButton+' class="classButton" data-idtest='+"#"+idTest+' data-file='+file+' data-line='+line+' data-test='+contentDiv+'><button type="button" class="classButton" >Trace</button>
';
		content.appendChild(div);

		createDiv("","testInfo totalTests box",divName,idTest);
		count = count + 1;

	}

	runFirstTime = function (){
		$.ajax({
			url:  'http://localhost/PUWI/PUWI_LoadJSON.php',
			dataType: "json",
			type: 'POST',
		    async: true,
			data: {action:'rerun'},

			success: function(request){

				showResults(request);
			},
			error: function(request){
				$('#title').html('request: '+request);
				alert("falla");
			}
		});
	}

	runAllTests = function(){
		$("#content").remove();
		runFirstTime();
	}

	showResults = function (request){
		passed = request["passed"];
		failures = request["failures"];
		errors = request["errors"];
		skipped = request["skipped"];
		incomplete = request["incomplete"];
		groups = request["groups"];
		folders = request["folders"];
		info = request["infoFailedTests"];

		//createDiv(contentDiv,className,divParent,divName)
		$('#projectName p').html(request["projectName"]);
		//createDiv(request["projectName"],"","content","projectName")
		if (request["totalTests"] == 0){
			$('.totalTests p').html("
No tests executed!
");
			//createDiv(request["projectName"],"","content","projectName");
		}else{
			/*createDiv(request["totalTests"]+" test pasing","totalTests box","content","");
			$('.totalTests p').append('<button type="button" id="runAllTests"  class="caca">Run All Tests</button>'
					+'<button type="button" id="hideTestsOK" class= "button">Hide/Show Passed Tests</button>');*/
			$('.totalTests p').append(request["totalTests"]+' test passing'
									+'<button type="button" id="runAllTests"  class="caca">Run All Tests</button>'
									+'<button type="button" id="hideTestsOK" class= "button">Hide/Show Passed Tests</button>');
		}
		/*$.each(groups, function(key, value) {
		      alert(key)
		});*/
		var array_keys = new Array();
		var array_values = new Array();
		for (var group_name in groups) {
		    array_keys.push(group_name);
		    createDiv(group_name,"groupName","content","groupName");
		    var countGroup = countDivs;
		    createDiv('','groupContent', 'content', 'groupName'+countGroup);

		    $.each(groups[group_name], function(key, value) {

			      var classNameTest = getClassNameTest(value, passed, incomplete, skipped, errors);
			      separated_values = value.split("::");
			      var className = separated_values[0];
			      var test = separated_values[1];

			      var folder = getFolder(folders,className);
			      if (!is_showedFolder(folder)){
			    	  countFolder = countDivs;
			    	  createDiv(folder,'grey','groupName'+countGroup,'folderName'+countFolder);
			    	  var selector = "#"+'folderName'+countFolder+" > p";
			    	  var idButton = "idButton"+countFolder;
			    	  $(selector).append('<button type="button" id='+idButton+' class= "classButton">Run folder</button>');
			      }

			      if (!is_showedClass(className)){
			    	  countClass = countDivs;
			    	  createDiv(className,'black','folderName'+countFolder, 'fileName'+countClass);
			      }
			      if (classNameTest == "testFailed box"){
			    	  var failedTest = getInfoFailedTests(value,info);
			    	  createDivFailedTest(test,classNameTest,'fileName'+countClass,className+'::'+test,failedTest['file'],failedTest['line'],
			    			  failedTest['message']);
			      }else{
			    	  createDiv(test,classNameTest,'fileName'+countClass,className+'::'+test);
			      }
			      countDivs++;
			});

		}
	}

	getClassNameTest = function(value, passed, incomplete, skipped, errors){
		var classNameTest = "";
		if($.inArray(value, passed) > -1){
			classNameTest = "testOK box";
		}else{
			if(($.inArray(value,incomplete) > -1) || ($.inArray(value,skipped) > -1)){
				classNameTest = "testIncomplete box";
			}else{
				classNameTest = "testFailed box";
			}
		}
		return classNameTest;
	}

	getFolder = function(folders,className){
		var result = "";
		 $.each(folders, function(folder, tests) {
			 $.each(folders[folder], function(index, test) {
				 var regex = new RegExp (".*"+className+".*","gi");
				 if (test.match(regex)){
					 result = folder;
				 }

			 });
		});
		return result;
	}

	is_showedClass = function(className){
		if(showedClass == className){
			return true;
		} else {
			showedClass = className;
			return false;
		}
	}

	is_showedFolder = function(folder){
		if(showedFolder == folder){
			return true;
		} else {
			showedFolder = folder;
			return false;
		}
	}

	getInfoFailedTests = function(testName,infoFailedTests){
		var result;
		$.each(infoFailedTests, function(key, value) {
		      if (value['testName'] == testName){
		    	  result = value;
		      }
		});
		return result;
	}

	$(".totalTests").on('click','#runAllTests', function() {
		alert("Ejecutar todos...");
		//runAllTests();
	});

	$(".grey").on('click',"#idButton0", function() {
		alert("foldeer");
	});

		$(".totalTests").on('click','#hideTestsOK', function() {
			$(".testOK").slideToggle();
		});

	$( "p.italic" ).on('click',"#showcode"+count, function(){
		alert("POR FIINNN");
		/*var idTest = $(this).data('idtest');
		var file = $(this).data('file');
		var line = $(this).data('line');
		var testName = $(this).data('test');

		$(idTest).slideToggle();
		$.ajax({
			url:  'http://localhost/PUWI/PUWI_LoadJSON.php',
			dataType: "json",
			type: 'POST',
		    async: true,
			data: {action:'displayCode',file:file,line:line,testName:testName},
			success:function(request){
				$(idTest).html('
'+idTest+request['code']+'
');
			},

			error: function(request){
				alert("an error ocurred in ajax request");
			}
		});
		*/
	});

	runFirstTime();

});

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
  * Swagger-parser library(https://apidevtools.org/swagger-parser/) is used for parsing the swagger YAML file
  * Prism-HTTP module is used for generating the mock data from the swagger definition
  */
import { generateStatic } from '@stoplight/prism-http/dist/mocker/generator/JSONSchema';

/**
 *
 * Return sample mocked model data for given definition name
 * @export
 * @param {string} modelName model name
 * @returns {*} Mocked API model
 */
export default async function getMockedModel(modelName) {
    const swagger = await apiDef;
    return generateStatic(swagger.definitions[modelName]);
}

/**
 *
 * Return all the available scopes under securityDefinitions in publisher-api.yaml
 * @export
 * @returns {Array} All the scopes available in publisher-api swagger
 */
export async function getAllScopes() {
    const swagger = await apiDef;
    return Object.keys(swagger.securityDefinitions.OAuth2Security.scopes);
}

/**
 *
 * Returns the example identified by the 'id' from the swagger extension 'x-examples' for the particular path and verb.
 * The example will contain both request and response information.
 * @param {string} resource resource path
 * @param {string} verb http verb
 * @param {string} id id of the example
 * @returns {Promise<*>} the example for the given operation and id
 */
export async function getExampleById(resource, verb, id) {
    const swagger = await apiDef;
    return swagger.paths[resource][verb]['x-examples'].find((x) => x.id === id);
}

/**
 *
 * Returns the example identified by the 'id' from the swagger extension 'x-examples' for the particular path and verb.
 * The example will only contain response information (status and body).
 * @param {string} resource resource path
 * @param {string} verb http verb
 * @param {string} id id of the example
 * @returns {Promise<*>} the example response for the given operation and id
 */
export async function getExampleResponseById(resource, verb, id) {
    const example = await getExampleById(resource, verb, id);
    return example.response;
}

/**
 *
 * Returns the example identified by the 'id' from the swagger extension 'x-examples' for the particular path and verb.
 * The example will only contain response body.
 * @param {string} resource resource path
 * @param {string} verb http verb
 * @param {string} id id of the example
 * @returns {Promise<*>} the example response body for the given operation and id
 */
export async function getExampleBodyById(resource, verb, id) {
    const example = await getExampleResponseById(resource, verb, id);
    return example.body;
}
<commit_msg>Update UI testcase with OAS changes<commit_after>/*
 * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
  * Swagger-parser library(https://apidevtools.org/swagger-parser/) is used for parsing the swagger YAML file
  * Prism-HTTP module is used for generating the mock data from the swagger definition
  */
import { generateStatic } from '@stoplight/prism-http/dist/mocker/generator/JSONSchema';

/**
 *
 * Return sample mocked model data for given definition name
 * @export
 * @param {string} modelName model name
 * @returns {*} Mocked API model
 */
export default async function getMockedModel(modelName) {
    const swagger = await apiDef;
    return generateStatic(swagger.components.schemas[modelName]);
}

/**
 *
 * Return all the available scopes under securityDefinitions in publisher-api.yaml
 * @export
 * @returns {Array} All the scopes available in publisher-api swagger
 */
export async function getAllScopes() {
    const swagger = await apiDef;
    return Object.keys(swagger.components.securitySchemes.OAuth2Security.flows.password.scopes);
}

/**
 *
 * Returns the example identified by the 'id' from the swagger extension 'x-examples' for the particular path and verb.
 * The example will contain both request and response information.
 * @param {string} resource resource path
 * @param {string} verb http verb
 * @param {string} id id of the example
 * @returns {Promise<*>} the example for the given operation and id
 */
export async function getExampleById(resource, verb, id) {
    const swagger = await apiDef;
    return swagger.paths[resource][verb]['x-examples'].find((x) => x.id === id);
}

/**
 *
 * Returns the example identified by the 'id' from the swagger extension 'x-examples' for the particular path and verb.
 * The example will only contain response information (status and body).
 * @param {string} resource resource path
 * @param {string} verb http verb
 * @param {string} id id of the example
 * @returns {Promise<*>} the example response for the given operation and id
 */
export async function getExampleResponseById(resource, verb, id) {
    const example = await getExampleById(resource, verb, id);
    return example.response;
}

/**
 *
 * Returns the example identified by the 'id' from the swagger extension 'x-examples' for the particular path and verb.
 * The example will only contain response body.
 * @param {string} resource resource path
 * @param {string} verb http verb
 * @param {string} id id of the example
 * @returns {Promise<*>} the example response body for the given operation and id
 */
export async function getExampleBodyById(resource, verb, id) {
    const example = await getExampleResponseById(resource, verb, id);
    return example.body;
}
<|endoftext|>


<commit_before>var todo = {};

todo.Todo = function(data) {
  this.description = m.prop(data.description);
  this.done = data.done ? m.prop(data.done) : m.prop(false);
};

todo.Pouch = function() {
  this.db = new PouchDB({ name: 'mithril-todo', auto_compaction: true });

  this.load = function() {
    return this.db.get('todos')
      .then(function(retrieved) {
        if (retrieved)
          return JSON.parse(retrieved.todos).map(function(parsed) { return new todo.Todo(parsed); });
        else
          return [];
      })
      .catch(function(error) {
        console.error('error loading!', error);
        return [];
      });
  };

  this.store = function(todos) {
    this.db.upsert('todos', function() {
      return { todos: JSON.stringify(todos) };
    }).catch(function(error) {
      console.error('store failed!', error);
    });
  };
};

todo.TodoList = function() {
  var db = new todo.Pouch();
  var todos = [];
  db.load()
    .then(function(retrieved) {
      console.log('retrieved', retrieved);
      todos = retrieved;
      m.redraw();
    });

  this.push = function(todo) {
    todos.push(todo);
    db.store(todos);
  };

  this.update = function(todo) {
    todos[todos.indexOf(todo)] = todo;
    db.store(todos);
  };

  this.map = function(func) {
    return todos.map(func);
  };
};

todo.vm = {
  init: function() {
          todo.vm.list = new todo.TodoList();

          todo.vm.description = m.prop('');

          todo.vm.add = function() {
            if (todo.vm.description()) {
              todo.vm.list.push(new todo.Todo({ description: todo.vm.description() }));
              todo.vm.description('');
            }
          };

          todo.vm.toggle = function() {
            this.done(!this.done());
            todo.vm.list.update(this);
          };
        }
};

todo.controller = function() {
  todo.vm.init();
};

todo.view = function() {
  return

            <input value={ todo.vm.description() } onchange={ m.withAttr('value', todo.vm.description) } />
            <button onclick={ todo.vm.add }>Add</button>

              {
                todo.vm.list.map(function(task, index) {
                  return

                          <input type="checkbox" checked={ task.done() } onclick={ todo.vm.toggle.bind(task) } />
                          { task.description() }

                })
              }

};

m.mount(document, todo);<commit_msg>Slightly neater but less obvious approach to initial loading case, minor race condition unhandled<commit_after>var todo = {};

todo.Todo = function(data) {
  this.description = m.prop(data.description);
  this.done = data.done ? m.prop(data.done) : m.prop(false);
};

todo.Pouch = function() {
  this.db = new PouchDB({ name: 'mithril-todo', auto_compaction: true });

  this.load = function() {
    return this.db.get('todos')
      .then(function(retrieved) {
        if (retrieved)
          return JSON.parse(retrieved.todos).map(function(parsed) { return new todo.Todo(parsed); });
        else
          return [];
      })
      .catch(function(error) {
        console.error('error loading!', error);
        return [];
      });
  };

  this.store = function(todos) {
    this.db.upsert('todos', function() {
      return { todos: JSON.stringify(todos) };
    }).catch(function(error) {
      console.error('store failed!', error);
    });
  };
};

todo.TodoList = function() {
  var db = new todo.Pouch();
  var todos = m.prop(db.load());
  todos.then(todos);

  this.push = function(todo) {
    todos().push(todo);
    db.store(todos());
  };

  this.update = function(todo) {
    var dos = todos();
    dos[dos.indexOf(todo)] = todo;
    todos(dos);
    db.store(todos);
  };

  this.map = function(func) {
    var dos = todos();
    if (dos)
      return dos.map(func);
    else
      todos.then(m.redraw);
  };
};

todo.vm = {
  init: function() {
          todo.vm.list = new todo.TodoList();

          todo.vm.description = m.prop('');

          todo.vm.add = function() {
            if (todo.vm.description()) {
              todo.vm.list.push(new todo.Todo({ description: todo.vm.description() }));
              todo.vm.description('');
            }
          };

          todo.vm.toggle = function() {
            this.done(!this.done());
            todo.vm.list.update(this);
          };
        }
};

todo.controller = function() {
  todo.vm.init();
};

todo.view = function() {
  return

            <input value={ todo.vm.description() } onchange={ m.withAttr('value', todo.vm.description) } />
            <button onclick={ todo.vm.add }>Add</button>

              {
                todo.vm.list.map(function(task, index) {
                  return

                          <input type="checkbox" checked={ task.done() } onclick={ todo.vm.toggle.bind(task) } />
                          { task.description() }

                })
              }

};

m.mount(document, todo);<|endoftext|>


<commit_before>function transformer (filename) {
  const re = /^(\d\d)\s-\s(.+)\s-\s(.+)\.(flac|ogg|wav)$/;
  const result = re.exec(filename);

  const track = result[1];
  const artist = result[2];
  const title = result[3];
  const type = result[4];

  console.log(track, artist, title, type);

  return `${track} - ${title}.${type}`;
}

module.exports = transformer;
<commit_msg>rework transformer to fix bug when song title has a dash<commit_after>function transformer (filename) {
  const re = /^(?:(\d\d)\s-\s)(.+)\.(flac|ogg|wav)$/;
  const result = re.exec(filename);

  if (!result) {
    return filename;
  }

  const track = result[1];
  const title = getSongTitle(result[2]);
  const type = result[3];

  // console.log(`${track}, ${artist}, ${title}, ${type}`);

  return `${track} - ${title}.${type}`;
}

function getSongTitle (artistAndTitle) {
  return artistAndTitle.split('-').slice(1)
    .map(str => str.trim())
    .join(' - ');
}

module.exports = transformer;
<|endoftext|>


<commit_before>var fs = require('fs-extra');
// var handlebars = require('handlebars');
var msg = require('./message');
// var inflector = require('./inflector');
// var config = require('./config');

module.exports = fs;

var mkdirpSync = fs.mkdirpSync;
fs.mkdirpSync = function(path) {
  var result = mkdirpSync(path);
  if (result) {
    msg.fileCreated(path);
  } else {
    msg.fileSkipped(path);
  }
};

var writeFileSync = fs.writeFileSync;
fs.writeFileSync = function(fileName, data, force) {
  if (force != 'force' && fs.existsSync(fileName)) {
    if (!msg.confirm(fileName+' exists, overwrite?')) {
      return msg.fileSkipped(fileName);
    }
  }
  fs.createFileSync(fileName);
  writeFileSync(fileName, data);
  return msg.fileCreated(fileName);
};

fs.writeTemplate = function(command, templateName, locals, savePath, force) {
  var templatePath = __dirname+'/../templates/'+command+'/'+templateName+'.hbs';
  var src = fs.renderTemplate(templatePath, locals);
  savePath = savePath || config().jsPath+'/'+command+'/'+templateName;
  fs.writeFileSync(savePath, src, force);
};

fs.writeGenerator = function(generatorType, resourceName, locals) {
  var ext = (generatorType == 'template') ? '.hbs' : '.js';
  var pluralType = inflector.pluralize(generatorType);
  var savePath = config().jsPath+'/'+pluralType+'/'+resourceName+ext;
  fs.writeTemplate('generate', generatorType+ext, locals, savePath);
};

fs.writeComponentTemplate = function(resourceName, locals) {
  templateName = resourceName+'.hbs';
  var savePath = config().jsPath+'/templates/'+templateName;
  var templatePath = __dirname+'/../templates/generate/component_template.hbs.hbs';
  var src = fs.renderTemplate(templatePath, locals);
  fs.writeFileSync(savePath, src);
};

fs.renderTemplate = function(templatePath, locals) {
  var template = fs.readFileSync(templatePath).toString();
  var compiled = handlebars.compile(template);
  return compiled(locals);
};

<commit_msg>remove the utils fs.js, it is not being used at the moment<commit_after><|endoftext|>


<commit_before>/**
 * @license
 * Visual Blocks Language
 *
 * Copyright 2012 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Generating JavaScript for variable blocks.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.provide('Blockly.JavaScript.variables');

goog.require('Blockly.JavaScript');

Blockly.JavaScript['variables_get'] = function(block) {
  // Variable getter.
  var code = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'),
      Blockly.Variables.NAME_TYPE);
  return ['_dict_variables.' + code, Blockly.JavaScript.ORDER_ATOMIC];
};

Blockly.JavaScript['variables_set'] = function(block) {
  // Variable setter.
  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
      Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
  var varName = Blockly.JavaScript.variableDB_.getName(
      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
  //return 'var ' + varName + ' = ' + argument0 + ';\n';
  return '_dict_variables.' + varName + ' = ' + argument0 + '; postMessage(workerProtocol.getMessage(_worker_id, workerProtocol._TYPE_RES_SET_VARIABLE, _dict_variables));';
};
<commit_msg>tvpl: Add newline<commit_after>/**
 * @license
 * Visual Blocks Language
 *
 * Copyright 2012 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Generating JavaScript for variable blocks.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.provide('Blockly.JavaScript.variables');

goog.require('Blockly.JavaScript');

Blockly.JavaScript['variables_get'] = function(block) {
  // Variable getter.
  var code = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'),
      Blockly.Variables.NAME_TYPE);
  return ['_dict_variables.' + code, Blockly.JavaScript.ORDER_ATOMIC];
};

Blockly.JavaScript['variables_set'] = function(block) {
  // Variable setter.
  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
      Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
  var varName = Blockly.JavaScript.variableDB_.getName(
      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
  //return 'var ' + varName + ' = ' + argument0 + ';\n';
  return '_dict_variables.' + varName + ' = ' + argument0 + ';\n  postMessage(workerProtocol.getMessage(_worker_id, workerProtocol._TYPE_RES_SET_VARIABLE, _dict_variables));';
};
<|endoftext|>


<commit_before>import { db } from './clients.js';
import { lineCoordStringToWKT, pointGeographyToCoordinates } from './utilities.js';

export async function createRoute({ user_id, geog, start_time, end_time, submit_date }) {
  const routeInsertResult = await db('routes').insert(
    {
      user_id,
      geog: lineCoordStringToWKT(geog),
      start_time,
      end_time,
      submit_date,
    },
    'route_id'
  );

  return routeInsertResult[0].route_id;
}

export async function getRoute(routeId, userId) {
  const route = await db('routes as r')
    .select(
      'r.route_id',
      // simplify with a tolerance of 100 meters
      db.raw('ST_asText(ST_Transform(ST_Simplify(ST_Transform(r.geog::geometry, 26912), 50), 4326)) as geog'),
      db.raw('ST_asText(ST_Envelope(r.geog::geometry)) as extent'),
      db.raw('ST_Length(geog) as distance'),
      'r.start_time',
      'r.end_time',
      'r.submit_date'
    )
    .where({ 'r.route_id': routeId, 'r.user_id': userId })
    .first();

  const pickups = await db('report_infos as r')
    .leftJoin('pickup_reports as pick', 'pick.report_id', 'r.report_id')
    .select(
      'r.report_id',
      'r.photo_id',
      'r.submit_date',
      'r.common_name',
      db.raw(pointGeographyToCoordinates('animal_location'))
    )
    .orderBy('r.submit_date', 'desc')
    .limit(100)
    .where({
      'r.user_id': userId,
      'pick.route_id': routeId,
    });

  return {
    ...route,
    pickups,
  };
}
<commit_msg>fix(back): handle routes with very small extents<commit_after>import { db } from './clients.js';
import { lineCoordStringToWKT, pointGeographyToCoordinates } from './utilities.js';

export async function createRoute({ user_id, geog, start_time, end_time, submit_date }) {
  const routeInsertResult = await db('routes').insert(
    {
      user_id,
      geog: lineCoordStringToWKT(geog),
      start_time,
      end_time,
      submit_date,
    },
    'route_id'
  );

  return routeInsertResult[0].route_id;
}

export async function getRoute(routeId, userId) {
  const route = await db('routes as r')
    .select(
      'r.route_id',
      // simplify with a tolerance of 100 meters
      db.raw('ST_asText(ST_Transform(ST_Simplify(ST_Transform(r.geog::geometry, 26912), 50), 4326)) as geog'),
      // using a tiny expand to guarantee that we always get a polygon
      // for points and vertical lines,ST_Envelope will return a point or line
      db.raw('ST_asText(ST_Envelope(ST_Expand(r.geog::geometry, 0.0000001))) as extent'),
      db.raw('ST_Length(geog) as distance'),
      'r.start_time',
      'r.end_time',
      'r.submit_date'
    )
    .where({ 'r.route_id': routeId, 'r.user_id': userId })
    .first();

  const pickups = await db('report_infos as r')
    .leftJoin('pickup_reports as pick', 'pick.report_id', 'r.report_id')
    .select(
      'r.report_id',
      'r.photo_id',
      'r.submit_date',
      'r.common_name',
      db.raw(pointGeographyToCoordinates('animal_location'))
    )
    .orderBy('r.submit_date', 'desc')
    .limit(100)
    .where({
      'r.user_id': userId,
      'pick.route_id': routeId,
    });

  return {
    ...route,
    pickups,
  };
}
<|endoftext|>