<commit_before>// Pixelate function: (C) Ken Fyrstenberg, Epistemex, License: CC3.0-attr
var ctx = canvas.getContext('2d');
var animated = false;

// Turn off image smoothing for pixelation effect
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;

var image = document.getElementById('species-image');
var slider = document.getElementById('pixel_factor');

// Get number of pixels for native image at full resolution
var originalNumPixels = image.width * image.height;

// Grab initial slider value (equal to species population)
// MUST be parsed as numerical values to avoid bug where the values
// are treated as Strings in some places, but Ints in others
// e.g. (100 - 30 = 70, but 100 + 30 = 10030)
var PIXEL_FACTOR_OLD = parseInt(slider.value);
var PIXEL_FACTOR_CURR = parseInt(slider.value);

// Add trigger to animate whenever the slider value changes
pixel_factor.addEventListener('change', animate_update, false);

// wait until image has finished loading before attaching pixelate()
image.onload = pixelate;

/** Main Pixelation function
 *
 * Pixelate image to desired number of pixels.
 * Shrinks and grows image w/o smoothing for automatic pixelation.
 */
function pixelate(v) {
    // v was originally used to represent the percentage to scale dimension down to;
    // numPixelsWidth = # pixels wide, numPixelsHeight = # pixels tall

    // var size = v * 0.01;
    // numPixelsWidth = canvas.width * size,
    // numPixelsHeight = canvas.height * size;

    // Grab number of total pixels the image should have
    var totalPixels = animated? v : pixel_factor.value;

    // TODO: Add condition for when something is to be considered rectangular
    // Generate ratio > 1 if image is sufficiently non-square
    var size = (canvas.width == canvas.height) ? ("square") : (canvas.width > canvas.height ? "wide" : "tall");
    if (size == "wide") {
        ratio = canvas.width / canvas.height;   // wide image
    } else if (size == "tall") {
        ratio = canvas.height / canvas.width;   // tall image
    }

    var [a, b, c] = getFactors(totalPixels);
    // console.log(a, b, c);

    var numPixelsWidth = Math.sqrt(totalPixels);
    var numPixelsHeight = Math.sqrt(totalPixels);

    // if (size == "wide") {
    //     numPixelsWidth = Math.max(a, b);
    //     numPixelsHeight = Math.min(a, b);
    // } else if (size == "tall") {
    //     numPixelsWidth = Math.min(a, b);
    //     numPixelsHeight = Math.max(a, b);
    // }

    // Draw scaled-down image
    ctx.drawImage(image, 0, 0, numPixelsWidth, numPixelsHeight);

    // Scale image back up to full canvas size; automatic pixelation because image smoothing is off
    ctx.drawImage(canvas,
                    0, 0, numPixelsWidth, numPixelsHeight,
                    0, 0, canvas.width, canvas.height);
}

// Find factors
// function getFactors(n) {
//     square_root = Math.ceil(Math.sqrt(n));
//     foundSolution = false;
//     val = square_root;
//     while (!foundSolution) {
//         val2 = Math.floor(n/val);
//         if (val2 * val == n) {
//             foundSolution = true;
//         } else {
//             val -= 1;
//         }
//     }
//     return [val, val2, n];
// }

/** Function to animate transition between two pixelation values;
 * Changes number of pixels until we hit `endpoint` pixels.
 */
function animate_update(endpoint) {
    // target = desired endpoint for pixelation
    var target = pixel_factor.value;
    // dx = speed of pixelation (# pixels/tick)
    var dx = 10;
    // var dx = Math.abs(PIXEL_FACTOR_CURR - target) / 10;
    animated = true;
    var underTarget = false;
    doAnimation();

    function doAnimation() {

        if (PIXEL_FACTOR_CURR < target) {
            PIXEL_FACTOR_CURR += dx;
            // "Binary Search" approach to home in on exact value since dx > 1
            if (!underTarget) {
                dx -= 1;
            }
            underTarget = true;
        } else if (PIXEL_FACTOR_CURR > target) {
            PIXEL_FACTOR_CURR -= dx;
            // "Binary Search" approach to home in on exact value since dx > 1
            if (underTarget) {
                dx -= 1;
            }
            underTarget = false;
        } else {
            animated = false;
            return;
        }

        pixelate(PIXEL_FACTOR_CURR);

        if (animated) {
            requestAnimationFrame(doAnimation);
        }
    }
}

/** When mouse enters canvas, animate transition to original, full-resolution image.
 *
 * Zoom out to original, full-resolution image.
 */
 function animateToFullResolution() {
    console.log("START");
    // TODO: Change speed parameters to be a function of the original resolution.
    // TODO: Ease functions?
    var range = originalNumPixels - PIXEL_FACTOR_CURR;
    var animationCompletionPercentage = 0;
    console.log(PIXEL_FACTOR_OLD, PIXEL_FACTOR_CURR, range);
    // "speed" parameter. Must be different than parameter for other animation fn
    // var dx = (originalNumPixels - PIXEL_FACTOR_CURR) / 100;
    // PIXEL_FACTOR_OLD = PIXEL_FACTOR_CURR;
    // var dx = 2000;
    animated = true;
    doAnimation();

    function doAnimation() {
        // PIXEL_FACTOR_CURR += dx;
        var easeOutput = calculateEaseValue(animationCompletionPercentage);
        PIXEL_FACTOR_CURR = Math.round(originalNumPixels - range * (1 - easeOutput));

        if (PIXEL_FACTOR_CURR >= originalNumPixels) {
            animated = false;
            console.log("HIT MAX");
            console.log(originalNumPixels);
            console.log(PIXEL_FACTOR_OLD, PIXEL_FACTOR_CURR, range);
            return;
        }

        pixelate(PIXEL_FACTOR_CURR);

        if (animated) {
            requestAnimationFrame(doAnimation);
        }

        animationCompletionPercentage += 2;
    }
}

/** After mouse leaves canvas, animate transition to previous pixelation amount
 *
 * Zoom back in to old number of pixels.
 */
function animateToOldResolution() {
    console.log("START");
    // "speed" parameter. Must be different than parameter for other animation fn
    // var dx = (PIXEL_FACTOR_CURR - PIXEL_FACTOR_OLD) / 50;
    // var dx = 4000;
    var range = PIXEL_FACTOR_CURR - PIXEL_FACTOR_OLD;
    var animationCompletionPercentage = 0;
    console.log(PIXEL_FACTOR_OLD, PIXEL_FACTOR_CURR, range);
    animated = true;
    doAnimation();

    function doAnimation() {
        var easeOutput = calculateEaseValue(animationCompletionPercentage);
        console.log("PIXEL_FACTOR_CURR OLD: " + PIXEL_FACTOR_CURR);
        console.log("EASE: " + easeOutput);
        console.log("1 - EASE: " + (1 - easeOutput));
        console.log("OFFSET: " + range * (1 - easeOutput));
        console.log("PIXEL_FACTOR_OLD: " + PIXEL_FACTOR_OLD);
        console.log("NEW VAL: " + (PIXEL_FACTOR_OLD + range * ( 1 - easeOutput)) );
        console.log("NEW VAL: " + ((PIXEL_FACTOR_OLD) + (range * ( 1 - easeOutput))) );
        console.log("NEW VAL: " + (parseInt(PIXEL_FACTOR_OLD) + parseInt(range * ( 1 - easeOutput))) );
        PIXEL_FACTOR_CURR = Math.round(PIXEL_FACTOR_OLD + range * (1 - easeOutput));
        console.log("PIXEL_FACTOR_CURR NEW: " + PIXEL_FACTOR_CURR);

        pixelate(PIXEL_FACTOR_CURR);

        if (animationCompletionPercentage >= 100) {
            animated = false;
            console.log("HIT OLD VALUE");
            console.log(PIXEL_FACTOR_OLD, PIXEL_FACTOR_CURR, range);
            return;
        }

        if (animated) {
            requestAnimationFrame(doAnimation);
        }

        animationCompletionPercentage += 2;
    }
}

// Map 3animation completion percentage to pixelation factor
function calculateEaseValue(x) {
    // Map [0, 100] to [0, 1]
    x /= 100;
    //InOutQuart ease function, GPL-3.0 license, https://github.com/ai/easings.net
    factor = x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2;
    return factor;
    // return x/100;
}

// Stand-in code for older browsers that don't support the animation
window.requestAnimationFrame = (function () {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
        window.setTimeout(callback, 1000 / 60);
    };
})();
<commit_msg>Add comments<commit_after>// Pixelate function: original code (C) Ken Fyrstenberg, Epistemex, License: CC3.0-attr
var ctx = canvas.getContext('2d');
var animated = false;

// Turn off image smoothing for pixelation effect
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;

var image = document.getElementById('species-image');
var slider = document.getElementById('pixel_factor');

// Get number of pixels for native image at full resolution
var originalNumPixels = image.width * image.height;

// Grab initial slider value (equal to species population)
// MUST be parsed as numerical values to avoid bug where the values
// are treated as Strings in some places, but Ints in others
// e.g. (100 - 30 = 70, but 100 + 30 = 10030)
var PIXEL_FACTOR_OLD = parseInt(slider.value);
var PIXEL_FACTOR_CURR = parseInt(slider.value);

// Add trigger to animate whenever the slider value changes
pixel_factor.addEventListener('change', animate_update, false);

// wait until image has finished loading before attaching pixelate()
image.onload = pixelate;

/** Main Pixelation function
 *
 * Pixelate image to desired number of pixels.
 * Accomplished by shrinking and enlarging the image
 * w/o image smoothing to create rough edges that automatically
 * simulate a pixelation effect.
 */
function pixelate(v) {
    // v was originally used to represent the percentage to scale dimension down to;
    // numPixelsWidth = # pixels wide, numPixelsHeight = # pixels tall

    // var size = v * 0.01;
    // numPixelsWidth = canvas.width * size,
    // numPixelsHeight = canvas.height * size;

    // Grab number of total pixels the image should have
    var totalPixels = animated? v : pixel_factor.value;

    // TODO: Add condition for when something is to be considered rectangular
    // Generate ratio > 1 if image is sufficiently non-square
    var size = (canvas.width == canvas.height) ? ("square") : (canvas.width > canvas.height ? "wide" : "tall");
    if (size == "wide") {
        ratio = canvas.width / canvas.height;   // wide image
    } else if (size == "tall") {
        ratio = canvas.height / canvas.width;   // tall image
    }

    var numPixelsWidth = Math.sqrt(totalPixels);
    var numPixelsHeight = Math.sqrt(totalPixels);

    // if (size == "wide") {
    //     numPixelsWidth = Math.max(a, b);
    //     numPixelsHeight = Math.min(a, b);
    // } else if (size == "tall") {
    //     numPixelsWidth = Math.min(a, b);
    //     numPixelsHeight = Math.max(a, b);
    // }

    // Draw scaled-down image
    ctx.drawImage(image, 0, 0, numPixelsWidth, numPixelsHeight);

    // Scale image back up to full canvas size; automatic pixelation because image smoothing is off
    ctx.drawImage(canvas,
                    0, 0, numPixelsWidth, numPixelsHeight,
                    0, 0, canvas.width, canvas.height);
}

// // find factors
// function getFactors(n) {
//     square_root = Math.ceil(Math.sqrt(n));
//     foundSolution = false;
//     val = square_root;
//     while (!foundSolution) {
//         val2 = Math.floor(n/val);
//         if (val2 * val == n) {
//             foundSolution = true;
//         } else {
//             val -= 1;
//         }
//     }
//     return [val, val2, n];
// }

/** Function to animate transition between two pixelation values;
 * Changes number of pixels until we hit `target` pixels.
 */
function animate_update() {
    // target = desired endpoint for pixelation taken from current slider value
    var target = pixel_factor.value;
    // dx = speed of pixelation (# pixels/tick)
    var dx = 10;
    // var dx = Math.abs(PIXEL_FACTOR_CURR - target) / 10;
    animated = true;
    var underTarget = false;
    doAnimation();

    function doAnimation() {

        if (PIXEL_FACTOR_CURR < target) {
            PIXEL_FACTOR_CURR += dx;
            // "Binary Search" approach to home in on exact value since dx > 1
            if (!underTarget) {
                dx -= 1;
            }
            underTarget = true;
        } else if (PIXEL_FACTOR_CURR > target) {
            PIXEL_FACTOR_CURR -= dx;
            // "Binary Search" approach to home in on exact value since dx > 1
            if (underTarget) {
                dx -= 1;
            }
            underTarget = false;
        } else {
            animated = false;
            return;
        }

        // Run pixelate function to render `PIXEL_FACTOR_CURR` pixels
        pixelate(PIXEL_FACTOR_CURR);

        // Actually update the canvas we see with the new animation
        if (animated) {
            requestAnimationFrame(doAnimation);
        }
    }
}

/*
 * When mouse enters canvas containing image, this activates
 * an animation that gradually "un-pixelates" the image until it
 * reaches the original, full-resolution image, creating a
 * "Zoom out" effect.
 */
 function animateToFullResolution() {
    // TODO: Change speed parameters to be a function of the original resolution.

    var range = originalNumPixels - PIXEL_FACTOR_CURR;
    var animationCompletionPercentage = 0;
    console.log(PIXEL_FACTOR_OLD, PIXEL_FACTOR_CURR, range);

    animated = true;
    doAnimation();

    function doAnimation() {
        // Calculate ease function value
        var easeOutput = calculateEaseValue(animationCompletionPercentage);

        /** Use ease value to calculate proportional increase in # of pixels
         *
         * If easeOutput = 0, we just started the animation:
         * `originalNumPixels - range * (1 - 0) = originalNUmPixels - (originalNumPixels - PIXEL_FACTOR_CURR) = PIXEL_FACTOR_CURR`
         *
         * If easeOutput = 1, we just finished the animation:
         * `originalNumPixels - range * (1 - 1) = originalNumPixels` */
        PIXEL_FACTOR_CURR = Math.round(originalNumPixels - range * (1 - easeOutput));

        // If we've hit 100% completion of the animation (i.e. reached full resolution), stop
        if (animationCompletionPercentage >= 100) {
            animated = false;
            // console.log("Reached original resolution: " + PIXEL_FACTOR_OLD + " " + PIXEL_FACTOR_CURR + " " + originalNumPixels + " " + range);
            return;
        }

        // Run pixelate function to render `PIXEL_FACTOR_CURR` pixels
        pixelate(PIXEL_FACTOR_CURR);

        // Actually update the canvas we see with the new animation
        if (animated) {
            requestAnimationFrame(doAnimation);
        }

        // Increment animation completion percentage by 2% (larger value = animates faster)
        animationCompletionPercentage += 2;
    }
}

/*
 * When mouse leaves canvas containing image, this activates
 * an animation that gradually "re-pixelates" the image until it
 * reaches the previous pixelation level, leaving the image looking
 * as it did when the mouse first entered the canvas.
 */
function animateToOldResolution() {
    var range = PIXEL_FACTOR_CURR - PIXEL_FACTOR_OLD;
    var animationCompletionPercentage = 0;
    // console.log(PIXEL_FACTOR_OLD, PIXEL_FACTOR_CURR, range);
    animated = true;
    doAnimation();

    function doAnimation() {
        // Calculate ease function value
        var easeOutput = calculateEaseValue(animationCompletionPercentage);
        // console.log((PIXEL_FACTOR_OLD + range * ( 1 - easeOutput)));
        // console.log(((PIXEL_FACTOR_OLD) + (range * ( 1 - easeOutput))));
        // console.log((parseInt(PIXEL_FACTOR_OLD) + parseInt(range * ( 1 - easeOutput))));

        /** Use ease value to calculate proportional increase in # of pixels
         *
         * If easeOutput = 0, we just started the animation:
         * `PIXEL_FACTOR_OLD + range * (1 - 0) = PIXEL_FACTOR_OLD + (PIXEL_FACTOR_CURR - PIXEL_FACTOR_OLD) = PIXEL_FACTOR_CURR`
         *
         * If easeOutput = 1, we just finished the animation:
         * `PIXEL_FACTOR_OLD + range * (1 - 1) = PIXEL_FACTOR_OLD` */
        PIXEL_FACTOR_CURR = Math.round(PIXEL_FACTOR_OLD + range * (1 - easeOutput));

        // console.log(PIXEL_FACTOR_CURR);

        // Run pixelate function to render `PIXEL_FACTOR_CURR` pixels
        pixelate(PIXEL_FACTOR_CURR);

        // If we've hit 100% completion of the animation (i.e. reached old resolution), stop
        if (animationCompletionPercentage >= 100) {
            animated = false;
            // console.log("Reached old resolution: " + PIXEL_FACTOR_OLD + " " + PIXEL_FACTOR_CURR + " " + originalNumPixels + " " + range);
            return;
        }

        // Actually update the canvas we see with the new animation
        if (animated) {
            requestAnimationFrame(doAnimation);
        }

        // Increment animation completion percentage by 2% (larger value = animates faster)
        animationCompletionPercentage += 2;
    }
}

// Map animation completion percentage to pixelation factor
function calculateEaseValue(x) {
    // Map [0, 100] to [0, 1]
    x /= 100;
    //InOutQuart ease function, GPL-3.0 license, https://github.com/ai/easings.net
    factor = x < 0.5 ? 8 * x * x * x * x : 1 - Math.pow(-2 * x + 2, 4) / 2;
    return factor;
    // return x/100;
}

// Stand-in code for older browsers that don't support the animation
window.requestAnimationFrame = (function () {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
        window.setTimeout(callback, 1000 / 60);
    };
})();
<|endoftext|>


<commit_before>(function() {
  'use strict';

  var crypto = require('crypto');

  /**
  * Simple express middleware module to authenticate Inbound Mandrill Webhook requests
  * @module MandrillWebhookAuthenticator
  */

  /**
  * @const { string } MANDRILL_SIGNATURE_HEADER - Mandrill Signature HTTP header
  */
  var MANDRILL_SIGNATURE_HEADER = 'x-mandrill-signature';

  /**
  * @const { string } NOT_AUTHORIZED
  */
  var NOT_AUTHORIZED = 'Not Authorized';

  /**
  * @const { string } FORBIDDEN
  */
  var FORBIDDEN = 'Forbidden';

  /**
  * @const { Error } CONFIGURATION_ERROR
  */
  var CONFIGURATION_ERROR = new Error('Configuration is incomplete, please check documentation');

  /**
  * Creates the middleware function to be used to authenticate the inbound Mandrill webhook
  *
  * @alias Authenticator
  * @constructor
  * @param { object } options - Set of configuration values
  * @param { string } options.webhookAuthKey - Key of the Inbound Webhook provied by Mandrill
  * @param { string } options.domain - Domain of the Inbound Webhook url as set up on Mandrill
  * @returns { function } @see {@link Authenticator~authenticate}
  */
  var Authenticator = function(options) {

    // Guard to ensure that Authenticator is always called with new
    if (!(this instanceof Authenticator)) {
      return new Authenticator(options);
    }

    // Default options
    options = options || {};

    // Validate provided options
    if (!options.webhookAuthKey || !options.domain) {
      throw CONFIGURATION_ERROR;
    }

    /**
    * Generate the signature from the full url and sorted post data to compart to the one provided
    * @param { string } fullUrl - domain and url of request - should match exactly the url specified in the webhook
    * @param { string } body - request body
    * @param { string } key - Mandrill Inbound Webhook auth key
    * @param { string } signature - signature provided in the 'x-mandrill-signature' header
    * @returns { boolean } True is signature is valid otherwise false
    */
    var isValidMandrillSignature = function(fullUrl, body, key, signature) {
      var data = fullUrl + sortPostParameters(body);
      var expected = getHash(data, key);
      return expected === signature;
    };

    /**
    * Sort the post parameters alphabetically and append each POST variable's key and value with no delimiter.
    * @param { string } body - Post body
    * @returns { string } string of sorted key values with no delimiter
    */
    var sortPostParameters = function(body) {
      body = Object(body);
      var sortedKeys = Object.keys(body).sort();
      return sortedKeys.reduce(function(signature, key) {
         return signature + key + body[key];
       }, '');
    };

    /**
    * Hash the resulting string with HMAC-SHA1, using your webhook's authentication key to generate a binary signature and Base64 encode.
    * @param { string } text - Full URL and sorted post data
    * @param { string } key - Mandrill Inbound Webhook auth key
    */
    var getHash = function(text, key) {
      var hmac = crypto.createHmac('sha1', key);
      hmac.setEncoding('base64');
      hmac.write(text);
      hmac.end();
      return hmac.read();
    };

    /**
    * Utility function to set http reponse status and message, uses HTTP compatible properties so express is not required
    * @param { Response } res - Response
    * @param { int } status - HTTP status code
    * @param { string } message - Response body
    */
    var respondWith = function(res, status, message) {
      res.writeHead(status);
      res.end(message);
    };

    /**
    * Express middleware compatible function to process requests and only continure if the signature is valid. It does not update the request.
    * @param { Request } req
    * @param { Response } res
    * @param { function } next
    */
    var authenticate = function(req, res, next) {
      if (!req.headers[MANDRILL_SIGNATURE_HEADER]) {
        respondWith(res, 401, NOT_AUTHORIZED);
      }else if (!isValidMandrillSignature(options.domain + req.url, req.body, options.webhookAuthKey, req.headers[MANDRILL_SIGNATURE_HEADER])) {
        respondWith(res, 403, FORBIDDEN);
      } else {
        next();
      }
    };

    return authenticate;
  };

  module.exports = Authenticator;

})();
<commit_msg>Chore: line endings<commit_after>(function() {
  'use strict';

  var crypto = require('crypto');

  /**
  * Simple express middleware module to authenticate Inbound Mandrill Webhook requests
  * @module MandrillWebhookAuthenticator
  */

  /**
  * @const { string } MANDRILL_SIGNATURE_HEADER - Mandrill Signature HTTP header
  */
  var MANDRILL_SIGNATURE_HEADER = 'x-mandrill-signature';

  /**
  * @const { string } NOT_AUTHORIZED
  */
  var NOT_AUTHORIZED = 'Not Authorized';

  /**
  * @const { string } FORBIDDEN
  */
  var FORBIDDEN = 'Forbidden';

  /**
  * @const { Error } CONFIGURATION_ERROR
  */
  var CONFIGURATION_ERROR = new Error('Configuration is incomplete, please check documentation');

  /**
  * Creates the middleware function to be used to authenticate the inbound Mandrill webhook
  *
  * @alias Authenticator
  * @constructor
  * @param { object } options - Set of configuration values
  * @param { string } options.webhookAuthKey - Key of the Inbound Webhook provied by Mandrill
  * @param { string } options.domain - Domain of the Inbound Webhook url as set up on Mandrill
  * @returns { function } @see {@link Authenticator~authenticate}
  */
  var Authenticator = function(options) {

    // Guard to ensure that Authenticator is always called with new
    if (!(this instanceof Authenticator)) {
      return new Authenticator(options);
    }

    // Default options
    options = options || {};

    // Validate provided options
    if (!options.webhookAuthKey || !options.domain) {
      throw CONFIGURATION_ERROR;
    }

    /**
    * Generate the signature from the full url and sorted post data to compart to the one provided
    * @param { string } fullUrl - domain and url of request - should match exactly the url specified in the webhook
    * @param { string } body - request body
    * @param { string } key - Mandrill Inbound Webhook auth key
    * @param { string } signature - signature provided in the 'x-mandrill-signature' header
    * @returns { boolean } True is signature is valid otherwise false
    */
    var isValidMandrillSignature = function(fullUrl, body, key, signature) {
      var data = fullUrl + sortPostParameters(body);
      var expected = getHash(data, key);
      return expected === signature;
    };

    /**
    * Sort the post parameters alphabetically and append each POST variable's key and value with no delimiter.
    * @param { string } body - Post body
    * @returns { string } string of sorted key values with no delimiter
    */
    var sortPostParameters = function(body) {
      body = Object(body);
      var sortedKeys = Object.keys(body).sort();
      return sortedKeys.reduce(function(signature, key) {
         return signature + key + body[key];
       }, '');
    };

    /**
    * Hash the resulting string with HMAC-SHA1, using your webhook's authentication key to generate a binary signature and Base64 encode.
    * @param { string } text - Full URL and sorted post data
    * @param { string } key - Mandrill Inbound Webhook auth key
    */
    var getHash = function(text, key) {
      var hmac = crypto.createHmac('sha1', key);
      hmac.setEncoding('base64');
      hmac.write(text);
      hmac.end();
      return hmac.read();
    };

    /**
    * Utility function to set http reponse status and message, uses HTTP compatible properties so express is not required
    * @param { Response } res - Response
    * @param { int } status - HTTP status code
    * @param { string } message - Response body
    */
    var respondWith = function(res, status, message) {
      res.writeHead(status);
      res.end(message);
    };

    /**
    * Express middleware compatible function to process requests and only continure if the signature is valid. It does not update the request.
    * @param { Request } req
    * @param { Response } res
    * @param { function } next
    */
    var authenticate = function(req, res, next) {
      if (!req.headers[MANDRILL_SIGNATURE_HEADER]) {
        respondWith(res, 401, NOT_AUTHORIZED);
      }else if (!isValidMandrillSignature(options.domain + req.url, req.body, options.webhookAuthKey, req.headers[MANDRILL_SIGNATURE_HEADER])) {
        respondWith(res, 403, FORBIDDEN);
      } else {
        next();
      }
    };

    return authenticate;
  };

  module.exports = Authenticator;

})();
<|endoftext|>


<commit_before>var gameField;
var currentPlayer;

function newGame(){
  var xMax = 7;
  var yMax = 6;
  gameField = new Array();
  for (i=0;i<xMax;i++) {
    gameField[i]=new Array();
    for (j=0;j<yMax;j++) {
      gameField[i][j]=0;
    }
  }

  currentPlayer = "red";
};

function placePiece(column){
  // insert piece into column at lowest unoccupied position
  var row = whichRow(column);
  var rowId = "#row-" + row;
  var colId = "#col-" + column;
  var selector = $(rowId + colId)
  $(rowId + " " + colId).css("background-color", currentPlayer)
  gameField[column - 1][row - 1] = "taken"
  //  hasWinner();
}

function whichRow(column) {
  var col = gameField[column - 1];
  return col.lastIndexOf(0) + 1;
}

function hasWinner(){
// analyze the board for 4 in a row || 4 in a column
// if yes
// endGame();
// else switchPlayer()
}

function switchPlayer(){
  if (currentPlayer === "red") {
    currentPlayer = "black";
  } else {
    currentPlayer = "red";
  }
};

function endGame(){
  return currentPlayer;
}

$(document).ready(function() {

  newGame();

  $(".tg").on("click", "td", function() {
    var col = $(this).attr("id").slice(-1);
    // $(this).html(col)
    placePiece(parseInt(col));
  })

});
<commit_msg>implement switchplayer in placepiece<commit_after>var gameField;
var currentPlayer;

function newGame(){
  var xMax = 7;
  var yMax = 6;
  gameField = new Array();
  for (i=0;i<xMax;i++) {
    gameField[i]=new Array();
    for (j=0;j<yMax;j++) {
      gameField[i][j]=0;
    }
  }

  currentPlayer = "red";
};

function placePiece(column){
  // insert piece into column at lowest unoccupied position
  var row = whichRow(column);
  var rowId = "#row-" + row;
  var colId = "#col-" + column;
  var selector = $(rowId + colId)
  $(rowId + " " + colId).css("background-color", currentPlayer)
  gameField[column - 1][row - 1] = "taken"
  switchPlayer();
  //  hasWinner();
}

function whichRow(column) {
  var col = gameField[column - 1];
  return col.lastIndexOf(0) + 1;
}

function hasWinner(){
// analyze the board for 4 in a row || 4 in a column
// if yes
// endGame();
// else switchPlayer()
}

function switchPlayer(){
  if (currentPlayer === "red") {
    currentPlayer = "black";
  } else {
    currentPlayer = "red";
  }
};

function endGame(){
  return currentPlayer;
}

$(document).ready(function() {

  newGame();

  $(".tg").on("click", "td", function() {
    var col = $(this).attr("id").slice(-1);
    // $(this).html(col)
    placePiece(parseInt(col));
  })

});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { IndexLink } from 'react-router';
import { LinkContainer } from 'react-router-bootstrap';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import Helmet from 'react-helmet';
import { isLoaded as isInfoLoaded, load as loadInfo } from 'redux/modules/info';
import { isLoaded as isAuthLoaded, load as loadAuth, logout } from 'redux/modules/auth';
import { InfoBar } from 'components';
import { push } from 'react-router-redux';
import config from '../../config';
import { asyncConnect } from 'redux-async-connect';
import cookie from 'react-cookie';

@asyncConnect([{
  promise: ({store: {dispatch, getState}}) => {
    const promises = [];

    if (!isInfoLoaded(getState())) {
      promises.push(dispatch(loadInfo()));
    }
    if (!isAuthLoaded(getState())) {
      promises.push(dispatch(loadAuth()));
    }

    return Promise.all(promises);
  }
}])

@connect((store) => {
  return {
    registerNewUserState: store.registerNewUser.user,
  };
})

export default class App extends Component {
    static propTypes = {
      children: PropTypes.object.isRequired,
      user: PropTypes.object,
      logout: PropTypes.func.isRequired,
      pushState: PropTypes.func.isRequired
    };

    static contextTypes = {
      store: PropTypes.object.isRequired
    };

    state = {
      navExpanded: false,
      loginEmail: cookie.load('ck_email')
    }

    componentWillReceiveProps(nextProps) {
      if (!this.props.user && nextProps.user) {
        // login
        this.props.pushState('/loginSuccess');
      } else if (this.props.user && !nextProps.user) {
        // logout
        this.props.pushState('/');
      }
    }

    onNavItemClick = () => {
      this.setState({ navExpanded: false });
    }
    onNavbarToggle = () => {
      this.setState({ navExpanded: ! this.state.navExpanded });
    }
    handleLogout = (event) => {
      event.preventDefault();
      this.props.logout();
    }

    render() {
      const styles = require('./App.scss');
      const { registerNewUserState } = this.props;

      var userNavLoggedIn = 0;
      if(this.state.loginEmail !== undefined){
        userNavLoggedIn = 1;
      }
      if(registerNewUserState.email !== null){
        userNavLoggedIn = 1;
      }
      console.log('userNavLoggedIn: ' + userNavLoggedIn + ', cookie.load(ck_email): ' + this.state.loginEmail + ', registerNewUserState.email: '+registerNewUserState.email);

      return (

          <Helmet {...config.app.head}/>

          <Navbar fixedTop expanded={ this.state.navExpanded } onToggle={ this.onNavbarToggle }>
            <Navbar.Header>
              <Navbar.Brand>
                <IndexLink to="/" activeStyle={{color: '#d52b1e'}}>

                    {config.app.title}

                </IndexLink>
              </Navbar.Brand>
              <Navbar.Toggle/>
            </Navbar.Header>

            <Navbar.Collapse>

                <LinkContainer to="/community">
                  <NavItem eventKey={1} onClick={ this.onNavItemClick }>Community</NavItem>
                </LinkContainer>
                { userNavLoggedIn === 1 ?
                <LinkContainer to="/registrieren0">
                  <NavItem eventKey={2} onClick={ this.onNavItemClick }>Mein Profil</NavItem>
                </LinkContainer>
                :
                <LinkContainer to="/registrieren">
                  <NavItem eventKey={3} onClick={ this.onNavItemClick }>Mitglied werden</NavItem>
                </LinkContainer>
                }
                <LinkContainer to="/kontakt">
                  <NavItem eventKey={4} onClick={ this.onNavItemClick }>Kontakt</NavItem>
                </LinkContainer>
                { userNavLoggedIn === 1 ?
                  <LinkContainer to="/registrieren1">
                    <NavItem eventKey={5} onClick={ this.onNavItemClick }>Logout</NavItem>
                  </LinkContainer>
                  :
                  <LinkContainer to="/registrieren2">
                    <NavItem eventKey={6} onClick={ this.onNavItemClick }>Login</NavItem>
                  </LinkContainer>
                }

            </Navbar.Collapse>
          </Navbar>

            {this.props.children}

          <InfoBar/>

            Copyright { new Date().getFullYear() } | Swiss React Community | React, Redux, Flux, React Native | Swiss-react.ch

      );
    }
  }
<commit_msg>blog mongoose 3.23vsssssddsssd 1s<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { IndexLink } from 'react-router';
import { LinkContainer } from 'react-router-bootstrap';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import Helmet from 'react-helmet';
import { isLoaded as isInfoLoaded, load as loadInfo } from 'redux/modules/info';
import { isLoaded as isAuthLoaded, load as loadAuth, logout } from 'redux/modules/auth';
import { InfoBar } from 'components';
import { push } from 'react-router-redux';
import config from '../../config';
import { asyncConnect } from 'redux-async-connect';
import cookie from 'react-cookie';

@asyncConnect([{
  promise: ({store: {dispatch, getState}}) => {
    const promises = [];

    if (!isInfoLoaded(getState())) {
      promises.push(dispatch(loadInfo()));
    }
    if (!isAuthLoaded(getState())) {
      promises.push(dispatch(loadAuth()));
    }

    return Promise.all(promises);
  }
}])

@connect((store) => {
  return {
    registerNewUserState: store.registerNewUser.user,
  };
})

export default class App extends Component {
    state = {
      loaded: false,
      navExpanded: false
    }

    static propTypes = {
      children: PropTypes.object.isRequired,
      user: PropTypes.object,
      logout: PropTypes.func.isRequired,
      pushState: PropTypes.func.isRequired
    };

    static contextTypes = {
      store: PropTypes.object.isRequired
    };

    componentDidMount() {
      this.state.loaded = true;
      console.log("component componentDidMount ----------------");
    }

    componentWillReceiveProps(nextProps) {
      console.log("component componentWillReceiveProps ----------------");
      if (!this.props.user && nextProps.user) {
        // login
        this.props.pushState('/loginSuccess');
      } else if (this.props.user && !nextProps.user) {
        // logout
        this.props.pushState('/');
      }
    }

    onNavItemClick = () => {
      this.setState({ navExpanded: false });
    }
    onNavbarToggle = () => {
      this.setState({ navExpanded: ! this.state.navExpanded });
    }
    handleLogout = (event) => {
      event.preventDefault();
      this.props.logout();
    }

    render() {
      const styles = require('./App.scss');
      const {loaded} = this.state;
      const { registerNewUserState } = this.props;

      var userNavLoggedIn = 0;
      if(this.state.loginEmail !== undefined){
        userNavLoggedIn = 1;
      }
      if(registerNewUserState.email !== null){
        userNavLoggedIn = 1;
      }
      console.log('userNavLoggedIn: ' + userNavLoggedIn + ', cookie.load(ck_email): ' + this.state.loginEmail + ', registerNewUserState.email: '+registerNewUserState.email);

      return (

          <Helmet {...config.app.head}/>

          {loaded === true ?
          <Navbar fixedTop expanded={ this.state.navExpanded } onToggle={ this.onNavbarToggle }>
            <Navbar.Header>
              <Navbar.Brand>
                <IndexLink to="/" activeStyle={{color: '#d52b1e'}}>

                    {config.app.title}

                </IndexLink>
              </Navbar.Brand>
              <Navbar.Toggle/>
            </Navbar.Header>

            <Navbar.Collapse>

                <LinkContainer to="/community">
                  <NavItem eventKey={1} onClick={ this.onNavItemClick }>Community</NavItem>
                </LinkContainer>
                { userNavLoggedIn === 1 ?
                <LinkContainer to="/registrieren0">
                  <NavItem eventKey={2} onClick={ this.onNavItemClick }>Mein Profil</NavItem>
                </LinkContainer>
                :
                <LinkContainer to="/registrieren">
                  <NavItem eventKey={3} onClick={ this.onNavItemClick }>Mitglied werden</NavItem>
                </LinkContainer>
                }
                <LinkContainer to="/kontakt">
                  <NavItem eventKey={4} onClick={ this.onNavItemClick }>Kontakt</NavItem>
                </LinkContainer>
                { userNavLoggedIn === 1 ?
                  <LinkContainer to="/registrieren1">
                    <NavItem eventKey={5} onClick={ this.onNavItemClick }>Logout</NavItem>
                  </LinkContainer>
                  :
                  <LinkContainer to="/registrieren2">
                    <NavItem eventKey={6} onClick={ this.onNavItemClick }>Login</NavItem>
                  </LinkContainer>
                }

            </Navbar.Collapse>
          </Navbar>
          : null
          }

            {this.props.children}

          <InfoBar/>

            Copyright { new Date().getFullYear() } | Swiss React Community | React, Redux, Flux, React Native | Swiss-react.ch

      );
    }
  }
<|endoftext|>


<commit_before>import debugModule from "debug";
const debug = debugModule("debugger:data:decode");

import {BigNumber} from "bignumber.js";

import * as memory from "./memory";
import * as storage from "./storage";
import * as utils from "./utils";
import { WORD_SIZE } from "./utils";

export function read(pointer, state) {
  if (pointer.stack != undefined && state.stack && pointer.stack < state.stack.length) {
    return state.stack[pointer.stack];
  } else if (pointer.storage != undefined && state.storage) {
    return storage.readRange(state.storage, pointer.storage);
  } else if (pointer.memory != undefined && state.memory) {
    return memory.readBytes(state.memory, pointer.memory.start, pointer.memory.length);
  } else if (pointer.literal != undefined) {
    return pointer.literal;
  }
}

export function decodeValue(definition, pointer, info) {
  const { state } = info;
  debug(
    "decoding value, pointer: %o, typeClass: %s",
    pointer, utils.typeClass(definition)
  );
  let bytes = read(pointer, state);
  if (bytes == undefined) {
    debug("segfault, pointer %o, state: %O", pointer, state);
    return undefined;
  }

  switch (utils.typeClass(definition)) {
    case "bool":
      return !utils.toBigNumber(bytes).isZero();

    case "uint":
      return utils.toBigNumber(bytes);

    case "int":
      return utils.toSignedBigNumber(bytes);

    case "address":
      return utils.toHexString(bytes, true);

    case "bytes":
      debug("typeIdentifier %s %o", utils.typeIdentifier(definition), bytes);
      // HACK bytes may be getting passed in as a literal hexstring
      if (typeof bytes == "string") {
        return bytes;
      }
      let length = utils.specifiedSize(definition);
      return utils.toHexString(bytes, length);

    case "string":
    case "stringliteral":
      debug("typeIdentifier %s %o", utils.typeIdentifier(definition), bytes);
      if (typeof bytes == "string") {
        return bytes;
      }
      return String.fromCharCode.apply(undefined, bytes);

    case "rational":
      debug("typeIdentifier %s %o", utils.typeIdentifier(definition), bytes);
      return utils.toBigNumber(bytes);

    default:
      debug("Unknown value type: %s", utils.typeIdentifier(definition));
      return undefined;
  }
}

export function decodeMemoryReference(definition, pointer, info) {
  const { state } = info
  debug("pointer %o", pointer);
  let rawValue = read(pointer, state)
  if (rawValue == undefined) {
    return undefined;
  }

  rawValue = utils.toBigNumber(rawValue).toNumber();

  var bytes;
  switch (utils.typeClass(definition)) {

    case "bytes":
    case "string":
      bytes = read({
        memory: { start: rawValue, length: WORD_SIZE}
      }, state); // bytes contain length

      let childPointer = {
        memory: { start: rawValue + WORD_SIZE, length: bytes }
      }

      return decodeValue(definition, childPointer, info);

    case "array":
      bytes = utils.toBigNumber(read({
        memory: { start: rawValue, length: WORD_SIZE },
      }, state)).toNumber();  // bytes contain array length

      bytes = read({ memory: {
        start: rawValue + WORD_SIZE, length: bytes * WORD_SIZE
      }}, state); // now bytes contain items

      return memory.chunk(bytes, WORD_SIZE)
        .map(
          (chunk) => decode(utils.baseDefinition(definition), {
            literal: chunk
          }, info)
        )

    case "struct":
      const { scopes } = info;

      // Declaration reference usually appears in `typeName`, but for
      // { nodeType: "FunctionCall", kind: "structConstructorCall" }, this
      // reference appears to live in `expression`
      const referencedDeclaration = (definition.typeName)
        ? definition.typeName.referencedDeclaration
        : definition.expression.referencedDeclaration;

      let { variables } = (scopes[referencedDeclaration] || {});

      return Object.assign(
        {}, ...(variables || [])
          .map(
            ({name, id}, i) => {
              let memberDefinition = scopes[id].definition;
              let memberPointer = {
                memory: { start: rawValue + i * WORD_SIZE, length: WORD_SIZE }
              };
              // let memberPointer = memory.read(state.memory, pointer + i * WORD_SIZE);

              // HACK
              memberDefinition = {
                ...memberDefinition,

                typeDescriptions: {
                  ...memberDefinition.typeDescriptions,

                  typeIdentifier:
                    memberDefinition.typeDescriptions.typeIdentifier
                      .replace(/_storage_/g, "_memory_")
                }
              };

              return {
                [name]: decode(
                  memberDefinition, memberPointer, info
                )
              };
            }
          )
      );

    default:
      debug("Unknown memory reference type: %s", utils.typeIdentifier(definition));
      return undefined;

  }

}

export function decodeStorageReference(definition, pointer, info) {
  var data;
  var bytes;
  var length;
  var slot;

  const { state } = info;

  switch (utils.typeClass(definition)) {
    case "array":
      debug("storage array! %o", pointer);
      data = read(pointer, state);
      if (!data) {
        return undefined;
      }

      length = utils.toBigNumber(data).toNumber();
      debug("length %o", length);

      const baseSize = utils.storageSize(utils.baseDefinition(definition));
      const perWord = Math.floor(WORD_SIZE / baseSize);
      debug("baseSize %o", baseSize);
      debug("perWord %d", perWord);

      const offset = (i) => {
        if (perWord == 1) {
          return i;
        }

        return Math.floor(i * baseSize / WORD_SIZE);
      }

      const index = (i) => {
        if (perWord == 1) {
          return WORD_SIZE - baseSize;
        }

        const position = perWord - i % perWord - 1;
        return position * baseSize;
      }

      let from = {
        slot: utils.normalizeSlot(pointer.storage.from.slot),
        index: pointer.storage.from.index
      };

      debug("pointer: %o", pointer);
      return [...Array(length).keys()]
        .map( (i) => {
          let childFrom = {
            slot: {
              path: (from.slot.path instanceof Array)
                ? from.slot.path
                : [from.slot],
              offset: offset(i),
            },
            index: index(i)
          };
          return childFrom;
        })
        .map( (childFrom, idx) => {
          debug("childFrom %d, %o", idx, childFrom);
          return decode(utils.baseDefinition(definition), { storage: {
            from: childFrom,
            length: baseSize
          }}, info);
        });

    case "bytes":
    case "string":
      data = read(pointer, state);
      if (data == undefined) {
        return undefined;
      }

      debug("data %O", data);
      let lengthByte = data[WORD_SIZE - 1];
      if (!lengthByte) {
        lengthByte = 0;
      }

      if (lengthByte % 2 == 0) {
        // string lives in word, length is last byte / 2
        length = lengthByte / 2;
        debug("in-word; length %o", length);
        if (length == 0) {
          return "";
        }

        return decodeValue(definition, { storage: {
          from: { slot: pointer.storage.from.slot, index: 0 },
          to: { slot: pointer.storage.from.slot, index: length - 1}
        }}, info);

      } else {
        length = utils.toBigNumber(data).minus(1).div(2).toNumber();
        debug("new-word, length %o", length);

        return decodeValue(definition, { storage: {
          from: { slot: [pointer.storage.from.slot], index: 0 },
          length
        }}, info);
      }

    case "struct":
      const { scopes } = info;

      const referencedDeclaration = (definition.typeName)
        ? definition.typeName.referencedDeclaration
        : definition.referencedDeclaration;

      const { variables } = (scopes[referencedDeclaration] || {});

      const allocation = utils.allocateDeclarations(
        variables || [], scopes, pointer.storage.from.slot
      );

      return Object.assign(
        {}, ...Object.entries(allocation.children)
          .map( ([id, childPointer]) => ({
            [childPointer.name]: decode(
              scopes[id].definition, { storage: childPointer }, info
            )
          }))
      );

    default:
      debug("Unknown storage reference type: %s", utils.typeIdentifier(definition));
      return undefined;
  }
}

export function decodeMapping(definition, pointer, info) {
  if (definition.referencedDeclaration) {
    // attempting to decode reference to mapping, thus missing valid pointer
    return undefined;
  }

  const { mappingKeys } = info;

  debug("mapping %O", pointer);
  debug("mapping definition %O", definition);
  let keys = mappingKeys[definition.id] || [];
  debug("known keys %o", keys);

  let keyDefinition = definition.typeName.keyType;
  let valueDefinition = definition.typeName.valueType;

  let baseSlot = pointer.storage.from.slot;
  if (!Array.isArray(baseSlot)) {
    baseSlot = [baseSlot];
  }

  let mapping = {};
  debug("mapping %O", mapping);
  for (let key of keys) {
    let keyPointer = { "literal": key };
    let valuePointer = {
      storage: {
        from: {
          slot: [key, ...baseSlot],
          index: 0
        },
        to: {
          slot: [key, ...baseSlot],
          index: 31
        }
      }
    };
    debug("keyPointer %o", keyPointer);

    // NOTE mapping keys are potentially lossy because JS only likes strings
    let keyValue = decode(keyDefinition, keyPointer, info);
    debug("keyValue %o", keyValue);
    if (keyValue != undefined) {
      mapping[keyValue.toString()] =
        decode(valueDefinition, valuePointer, info);
    }
  }

  return mapping;
}

export default function decode(definition, pointer, info) {
  if (pointer.literal != undefined) {
    return decodeValue(definition, pointer, info);
  }

  const identifier = utils.typeIdentifier(definition);
  if (utils.isReference(definition)) {
    switch (utils.referenceType(definition)) {
      case "memory":
        debug("decoding memory reference, type: %s", identifier);
        return decodeMemoryReference(definition, pointer, info);
      case "storage":
        debug("decoding storage reference, type: %s", identifier);
        return decodeStorageReference(definition, pointer, info);
      default:
        debug("Unknown reference category: %s", utils.typeIdentifier(definition));
        return undefined;
    }
  }

  if (utils.isMapping(definition)) {
    debug("decoding mapping, type: %s", identifier);
    return decodeMapping(definition, pointer, info);
  }

  debug("decoding value, type: %s", identifier);
  return decodeValue(definition, pointer, info);
}
<commit_msg>Dereference stack/memory pointers to storage vars<commit_after>import debugModule from "debug";
const debug = debugModule("debugger:data:decode");

import {BigNumber} from "bignumber.js";

import * as memory from "./memory";
import * as storage from "./storage";
import * as utils from "./utils";
import { WORD_SIZE } from "./utils";

export function read(pointer, state) {
  if (pointer.stack != undefined && state.stack && pointer.stack < state.stack.length) {
    return state.stack[pointer.stack];
  } else if (pointer.storage != undefined && state.storage) {
    return storage.readRange(state.storage, pointer.storage);
  } else if (pointer.memory != undefined && state.memory) {
    return memory.readBytes(state.memory, pointer.memory.start, pointer.memory.length);
  } else if (pointer.literal != undefined) {
    return pointer.literal;
  }
}

export function decodeValue(definition, pointer, info) {
  const { state } = info;
  debug(
    "decoding value, pointer: %o, typeClass: %s",
    pointer, utils.typeClass(definition)
  );
  let bytes = read(pointer, state);
  if (bytes == undefined) {
    debug("segfault, pointer %o, state: %O", pointer, state);
    return undefined;
  }

  switch (utils.typeClass(definition)) {
    case "bool":
      return !utils.toBigNumber(bytes).isZero();

    case "uint":
      return utils.toBigNumber(bytes);

    case "int":
      return utils.toSignedBigNumber(bytes);

    case "address":
      return utils.toHexString(bytes, true);

    case "bytes":
      debug("typeIdentifier %s %o", utils.typeIdentifier(definition), bytes);
      // HACK bytes may be getting passed in as a literal hexstring
      if (typeof bytes == "string") {
        return bytes;
      }
      let length = utils.specifiedSize(definition);
      return utils.toHexString(bytes, length);

    case "string":
    case "stringliteral":
      debug("typeIdentifier %s %o", utils.typeIdentifier(definition), bytes);
      if (typeof bytes == "string") {
        return bytes;
      }
      return String.fromCharCode.apply(undefined, bytes);

    case "rational":
      debug("typeIdentifier %s %o", utils.typeIdentifier(definition), bytes);
      return utils.toBigNumber(bytes);

    default:
      debug("Unknown value type: %s", utils.typeIdentifier(definition));
      return undefined;
  }
}

export function decodeMemoryReference(definition, pointer, info) {
  const { state } = info
  debug("pointer %o", pointer);
  let rawValue = read(pointer, state)
  if (rawValue == undefined) {
    return undefined;
  }

  rawValue = utils.toBigNumber(rawValue).toNumber();

  var bytes;
  switch (utils.typeClass(definition)) {

    case "bytes":
    case "string":
      bytes = read({
        memory: { start: rawValue, length: WORD_SIZE}
      }, state); // bytes contain length

      let childPointer = {
        memory: { start: rawValue + WORD_SIZE, length: bytes }
      }

      return decodeValue(definition, childPointer, info);

    case "array":
      bytes = utils.toBigNumber(read({
        memory: { start: rawValue, length: WORD_SIZE },
      }, state)).toNumber();  // bytes contain array length

      bytes = read({ memory: {
        start: rawValue + WORD_SIZE, length: bytes * WORD_SIZE
      }}, state); // now bytes contain items

      return memory.chunk(bytes, WORD_SIZE)
        .map(
          (chunk) => decode(utils.baseDefinition(definition), {
            literal: chunk
          }, info)
        )

    case "struct":
      const { scopes } = info;

      // Declaration reference usually appears in `typeName`, but for
      // { nodeType: "FunctionCall", kind: "structConstructorCall" }, this
      // reference appears to live in `expression`
      const referencedDeclaration = (definition.typeName)
        ? definition.typeName.referencedDeclaration
        : definition.expression.referencedDeclaration;

      let { variables } = (scopes[referencedDeclaration] || {});

      return Object.assign(
        {}, ...(variables || [])
          .map(
            ({name, id}, i) => {
              let memberDefinition = scopes[id].definition;
              let memberPointer = {
                memory: { start: rawValue + i * WORD_SIZE, length: WORD_SIZE }
              };
              // let memberPointer = memory.read(state.memory, pointer + i * WORD_SIZE);

              // HACK
              memberDefinition = {
                ...memberDefinition,

                typeDescriptions: {
                  ...memberDefinition.typeDescriptions,

                  typeIdentifier:
                    memberDefinition.typeDescriptions.typeIdentifier
                      .replace(/_storage_/g, "_memory_")
                }
              };

              return {
                [name]: decode(
                  memberDefinition, memberPointer, info
                )
              };
            }
          )
      );

    default:
      debug("Unknown memory reference type: %s", utils.typeIdentifier(definition));
      return undefined;

  }

}

export function decodeStorageReference(definition, pointer, info) {
  var data;
  var bytes;
  var length;
  var slot;

  const { state } = info;

  switch (utils.typeClass(definition)) {
    case "array":
      debug("storage array! %o", pointer);
      data = read(pointer, state);
      if (!data) {
        return undefined;
      }

      length = utils.toBigNumber(data).toNumber();
      debug("length %o", length);

      const baseSize = utils.storageSize(utils.baseDefinition(definition));
      const perWord = Math.floor(WORD_SIZE / baseSize);
      debug("baseSize %o", baseSize);
      debug("perWord %d", perWord);

      const offset = (i) => {
        if (perWord == 1) {
          return i;
        }

        return Math.floor(i * baseSize / WORD_SIZE);
      }

      const index = (i) => {
        if (perWord == 1) {
          return WORD_SIZE - baseSize;
        }

        const position = perWord - i % perWord - 1;
        return position * baseSize;
      }

      let from = {
        slot: utils.normalizeSlot(pointer.storage.from.slot),
        index: pointer.storage.from.index
      };

      debug("pointer: %o", pointer);
      return [...Array(length).keys()]
        .map( (i) => {
          let childFrom = {
            slot: {
              path: (from.slot.path instanceof Array)
                ? from.slot.path
                : [from.slot],
              offset: offset(i),
            },
            index: index(i)
          };
          return childFrom;
        })
        .map( (childFrom, idx) => {
          debug("childFrom %d, %o", idx, childFrom);
          return decode(utils.baseDefinition(definition), { storage: {
            from: childFrom,
            length: baseSize
          }}, info);
        });

    case "bytes":
    case "string":
      data = read(pointer, state);
      if (data == undefined) {
        return undefined;
      }

      debug("data %O", data);
      let lengthByte = data[WORD_SIZE - 1];
      if (!lengthByte) {
        lengthByte = 0;
      }

      if (lengthByte % 2 == 0) {
        // string lives in word, length is last byte / 2
        length = lengthByte / 2;
        debug("in-word; length %o", length);
        if (length == 0) {
          return "";
        }

        return decodeValue(definition, { storage: {
          from: { slot: pointer.storage.from.slot, index: 0 },
          to: { slot: pointer.storage.from.slot, index: length - 1}
        }}, info);

      } else {
        length = utils.toBigNumber(data).minus(1).div(2).toNumber();
        debug("new-word, length %o", length);

        return decodeValue(definition, { storage: {
          from: { slot: [pointer.storage.from.slot], index: 0 },
          length
        }}, info);
      }

    case "struct":
      const { scopes } = info;

      const referencedDeclaration = (definition.typeName)
        ? definition.typeName.referencedDeclaration
        : definition.referencedDeclaration;

      const variables = (scopes[referencedDeclaration] || {}).variables || [];

      let slot;
      if (pointer.storage != undefined) {
        slot = pointer.storage.from.slot;
      } else {
        slot = utils.normalizeSlot(utils.toBigNumber(read(pointer, state)));
      }

      const allocation = utils.allocateDeclarations(variables, scopes, slot);

      return Object.assign(
        {}, ...Object.entries(allocation.children)
          .map( ([id, childPointer]) => ({
            [childPointer.name]: decode(
              scopes[id].definition, { storage: childPointer }, info
            )
          }))
      );

    default:
      debug("Unknown storage reference type: %s", utils.typeIdentifier(definition));
      return undefined;
  }
}

export function decodeMapping(definition, pointer, info) {
  if (definition.referencedDeclaration) {
    // attempting to decode reference to mapping, thus missing valid pointer
    return undefined;
  }

  const { mappingKeys } = info;

  debug("mapping %O", pointer);
  debug("mapping definition %O", definition);
  let keys = mappingKeys[definition.id] || [];
  debug("known keys %o", keys);

  let keyDefinition = definition.typeName.keyType;
  let valueDefinition = definition.typeName.valueType;

  let baseSlot = pointer.storage.from.slot;
  if (!Array.isArray(baseSlot)) {
    baseSlot = [baseSlot];
  }

  let mapping = {};
  debug("mapping %O", mapping);
  for (let key of keys) {
    let keyPointer = { "literal": key };
    let valuePointer = {
      storage: {
        from: {
          slot: [key, ...baseSlot],
          index: 0
        },
        to: {
          slot: [key, ...baseSlot],
          index: 31
        }
      }
    };
    debug("keyPointer %o", keyPointer);

    // NOTE mapping keys are potentially lossy because JS only likes strings
    let keyValue = decode(keyDefinition, keyPointer, info);
    debug("keyValue %o", keyValue);
    if (keyValue != undefined) {
      mapping[keyValue.toString()] =
        decode(valueDefinition, valuePointer, info);
    }
  }

  return mapping;
}

export default function decode(definition, pointer, info) {
  if (pointer.literal != undefined) {
    return decodeValue(definition, pointer, info);
  }

  const identifier = utils.typeIdentifier(definition);
  if (utils.isReference(definition)) {
    switch (utils.referenceType(definition)) {
      case "memory":
        debug("decoding memory reference, type: %s", identifier);
        return decodeMemoryReference(definition, pointer, info);
      case "storage":
        debug("decoding storage reference, type: %s", identifier);
        return decodeStorageReference(definition, pointer, info);
      default:
        debug("Unknown reference category: %s", utils.typeIdentifier(definition));
        return undefined;
    }
  }

  if (utils.isMapping(definition)) {
    debug("decoding mapping, type: %s", identifier);
    return decodeMapping(definition, pointer, info);
  }

  debug("decoding value, type: %s", identifier);
  return decodeValue(definition, pointer, info);
}
<|endoftext|>


<commit_before>/**
 * @preserve console-shim 1.0.1
 * https://github.com/kayahr/console-shim
 * Copyright (C) 2011 Klaus Reimer <k@ailis.de>
 * Licensed under the MIT license
 * (See http://www.opensource.org/licenses/mit-license)
 */

(function(){
'use strict';

/**
 * Returns a function which calls the specified function in the specified
 * scope.
 *
 * @param {Function} func
 *            The function to call.
 * @param {Object} scope
 *            The scope to call the function in.
 * @param {...*} args
 *            Additional arguments to pass to the bound function.
 * @return {Function}
 *            The bound function.
 */
var bind = function(func, scope, args)
{
    var fixedArgs = Array.prototype.slice.call(arguments, 2);
    return function()
    {
        var args = fixedArgs.concat(Array.prototype.slice.call(arguments, 0));
        (/** @type {Function} */ func).apply(scope, args);
    };
};

// Create console if not present
if (!window["console"]) window.console = {};
var console = (/** @type {Object} */ window.console);

// Implement console log if needed
if (!console["log"])
{
    // Use log4javascript if present
    if (window["log4javascript"])
    {
        var log = log4javascript.getDefaultLogger();
        console.log = bind(log.info, log);
        console.debug = bind(log.debug, log);
        console.info = bind(log.info, log);
        console.warn = bind(log.warn, log);
        console.error = bind(log.error, log);
    }

    // Use empty dummy implementation to ignore logging
    else
    {
        console.log = (/** @param {...*} args */ function(args) {});
    }
}

// Implement other log levels to console.log if missing
if (!console["debug"]) console.debug = console.log;
if (!console["info"]) console.info = console.log;
if (!console["warn"]) console.warn = console.log;
if (!console["error"]) console.error = console.log;

// Wrap the log methods in IE (<=9) because their argument handling is wrong
// This wrapping is also done if the __consoleShimTest__ symbol is set. This
// is needed for unit testing.
if ((window["__consoleShimTest__"] != null) /*@cc_on || @_jscript_version <= 9 @*/)
{
    /**
     * Wraps the call to a real IE logging method. Modifies the arguments so
     * parameters which are not represented by a placeholder are properly
     * printed with a space character as separator.
     *
     * @param {...*} args
     *            The function arguments. First argument is the log function
     *            to call, the other arguments are the log arguments.
     */
    var wrap = function(args)
    {
        var i, max, match, log;

        // Convert argument list to real array
        args = Array.prototype.slice.call(arguments, 0);

        // First argument is the log method to call
        log = args.shift();

        max = args.length;
        if (max > 1 && window["__consoleShimTest__"] !== false)
        {
            // When first parameter is not a string then add a format string to
            // the argument list so we are able to modify it in the next stop
            if (typeof(args[0]) != "string")
            {
                args.unshift("%o");
                max += 1;
            }

            // For each additional parameter which has no placeholder in the
            // format string we add another placeholder separated with a
            // space character.
            match = args[0].match(/%[a-z]/g);
            for (i = match ? match.length + 1 : 1; i < max; i += 1)
            {
                args[0] += " %o";
            }
        }
        Function.apply.call(log, console, args);
    }

    // Wrap the native log methods of IE to fix argument output problems
    console.log = bind(wrap, window, console.log);
    console.debug = bind(wrap, window, console.debug);
    console.info = bind(wrap, window, console.info);
    console.warn = bind(wrap, window, console.warn);
    console.error = bind(wrap, window, console.error);
}

// Implement console.assert if missing
if (!console["assert"])
{
    console["assert"] = function()
    {
        var args = Array.prototype.slice.call(arguments, 0);
        var expr = args.shift();
        if (!expr)
        {
            args[0] = "Assertion failed: " + args[0];
            console.error.apply(console, args);
        }
    };
}

// Linking console.dir and console.dirxml to the console.log method if
// missing. Hopefully the browser already logs objects and DOM nodes as a
// tree.
if (!console["dir"]) console["dir"] = console.log;
if (!console["dirxml"]) console["dirxml"] = console.log;

// Linking console.exception to console.error. This is not the same but
// at least some error message is displayed.
if (!console["exception"]) console["exception"] = console.error;

// Implement console.time and console.timeEnd if one of them is missing
if (!console["time"] || !console["timeEnd"])
{
    var timers = {};
    console["time"] = function(id)
    {
        timers[id] = new Date().getTime();
    };
    console["timeEnd"] = function(id)
    {
        var start = timers[id];
        if (start)
        {
            console.log(id + ": " + (new Date().getTime() - start) + "ms");
            delete timers[id];
        }
    };
}

// Implement console.table if missing
if (!console["table"])
{
    console["table"] = function(data, columns)
    {
        var i, iMax, row, j, jMax, k;

        // Do nothing if data has wrong type or no data was specified
        if (!data || !(data instanceof Array) || !data.length) return;

        // Auto-calculate columns array if not set
        if (!columns || !(columns instanceof Array))
        {
            columns = [];
            for (k in data[0])
            {
                if (!data[0].hasOwnProperty(k)) continue;
                columns.push(k);
            }
        }

        for (i = 0, iMax = data.length; i < iMax; i += 1)
        {
            row = [];
            for (j = 0, jMax = columns.length; j < jMax; j += 1)
            {
                row.push(data[i][columns[j]]);
            }

            Function.apply.call(console.log, console, row);
        }
    };
}

// Dummy implementations of other console features to prevent error messages
// in browsers not supporting it.
if (!console["clear"]) console["clear"] = function() {};
if (!console["trace"]) console["trace"] = function() {};
if (!console["group"]) console["group"] = function() {};
if (!console["groupCollapsed"]) console["groupCollapsed"] = function() {};
if (!console["groupEnd"]) console["groupEnd"] = function() {};
if (!console["timeStamp"]) console["timeStamp"] = function() {};
if (!console["profile"]) console["profile"] = function() {};
if (!console["profileEnd"]) console["profileEnd"] = function() {};
if (!console["count"]) console["count"] = function() {};

})();
<commit_msg>Fix closure hinting (latest version)<commit_after>/**
 * @preserve console-shim 1.0.1
 * https://github.com/kayahr/console-shim
 * Copyright (C) 2011 Klaus Reimer <k@ailis.de>
 * Licensed under the MIT license
 * (See http://www.opensource.org/licenses/mit-license)
 */

(function(){
'use strict';

/**
 * Returns a function which calls the specified function in the specified
 * scope.
 *
 * @param {Function} func
 *            The function to call.
 * @param {Object} scope
 *            The scope to call the function in.
 * @param {...*} args
 *            Additional arguments to pass to the bound function.
 * @returns {function(...[*]): undefined}
 *            The bound function.
 */
var bind = function(func, scope, args)
{
    var fixedArgs = Array.prototype.slice.call(arguments, 2);
    return function()
    {
        var args = fixedArgs.concat(Array.prototype.slice.call(arguments, 0));
        (/** @type {Function} */ func).apply(scope, args);
    };
};

// Create console if not present
if (!window["console"]) window.console = /** @type {Console} */ ({});
var console = (/** @type {Object} */ window.console);

// Implement console log if needed
if (!console["log"])
{
    // Use log4javascript if present
    if (window["log4javascript"])
    {
        var log = log4javascript.getDefaultLogger();
        console.log = bind(log.info, log);
        console.debug = bind(log.debug, log);
        console.info = bind(log.info, log);
        console.warn = bind(log.warn, log);
        console.error = bind(log.error, log);
    }

    // Use empty dummy implementation to ignore logging
    else
    {
        console.log = (/** @param {...*} args */ function(args) {});
    }
}

// Implement other log levels to console.log if missing
if (!console["debug"]) console.debug = console.log;
if (!console["info"]) console.info = console.log;
if (!console["warn"]) console.warn = console.log;
if (!console["error"]) console.error = console.log;

// Wrap the log methods in IE (<=9) because their argument handling is wrong
// This wrapping is also done if the __consoleShimTest__ symbol is set. This
// is needed for unit testing.
if ((window["__consoleShimTest__"] != null) /*@cc_on || @_jscript_version <= 9 @*/)
{
    /**
     * Wraps the call to a real IE logging method. Modifies the arguments so
     * parameters which are not represented by a placeholder are properly
     * printed with a space character as separator.
     *
     * @param {...*} args
     *            The function arguments. First argument is the log function
     *            to call, the other arguments are the log arguments.
     */
    var wrap = function(args)
    {
        var i, max, match, log;

        // Convert argument list to real array
        args = Array.prototype.slice.call(arguments, 0);

        // First argument is the log method to call
        log = args.shift();

        max = args.length;
        if (max > 1 && window["__consoleShimTest__"] !== false)
        {
            // When first parameter is not a string then add a format string to
            // the argument list so we are able to modify it in the next stop
            if (typeof(args[0]) != "string")
            {
                args.unshift("%o");
                max += 1;
            }

            // For each additional parameter which has no placeholder in the
            // format string we add another placeholder separated with a
            // space character.
            match = args[0].match(/%[a-z]/g);
            for (i = match ? match.length + 1 : 1; i < max; i += 1)
            {
                args[0] += " %o";
            }
        }
        Function.apply.call(log, console, args);
    }

    // Wrap the native log methods of IE to fix argument output problems
    console.log = bind(wrap, window, console.log);
    console.debug = bind(wrap, window, console.debug);
    console.info = bind(wrap, window, console.info);
    console.warn = bind(wrap, window, console.warn);
    console.error = bind(wrap, window, console.error);
}

// Implement console.assert if missing
if (!console["assert"])
{
    console["assert"] = function()
    {
        var args = Array.prototype.slice.call(arguments, 0);
        var expr = args.shift();
        if (!expr)
        {
            args[0] = "Assertion failed: " + args[0];
            console.error.apply(console, args);
        }
    };
}

// Linking console.dir and console.dirxml to the console.log method if
// missing. Hopefully the browser already logs objects and DOM nodes as a
// tree.
if (!console["dir"]) console["dir"] = console.log;
if (!console["dirxml"]) console["dirxml"] = console.log;

// Linking console.exception to console.error. This is not the same but
// at least some error message is displayed.
if (!console["exception"]) console["exception"] = console.error;

// Implement console.time and console.timeEnd if one of them is missing
if (!console["time"] || !console["timeEnd"])
{
    var timers = {};
    console["time"] = function(id)
    {
        timers[id] = new Date().getTime();
    };
    console["timeEnd"] = function(id)
    {
        var start = timers[id];
        if (start)
        {
            console.log(id + ": " + (new Date().getTime() - start) + "ms");
            delete timers[id];
        }
    };
}

// Implement console.table if missing
if (!console["table"])
{
    console["table"] = function(data, columns)
    {
        var i, iMax, row, j, jMax, k;

        // Do nothing if data has wrong type or no data was specified
        if (!data || !(data instanceof Array) || !data.length) return;

        // Auto-calculate columns array if not set
        if (!columns || !(columns instanceof Array))
        {
            columns = [];
            for (k in data[0])
            {
                if (!data[0].hasOwnProperty(k)) continue;
                columns.push(k);
            }
        }

        for (i = 0, iMax = data.length; i < iMax; i += 1)
        {
            row = [];
            for (j = 0, jMax = columns.length; j < jMax; j += 1)
            {
                row.push(data[i][columns[j]]);
            }

            Function.apply.call(console.log, console, row);
        }
    };
}

// Dummy implementations of other console features to prevent error messages
// in browsers not supporting it.
if (!console["clear"]) console["clear"] = function() {};
if (!console["trace"]) console["trace"] = function() {};
if (!console["group"]) console["group"] = function() {};
if (!console["groupCollapsed"]) console["groupCollapsed"] = function() {};
if (!console["groupEnd"]) console["groupEnd"] = function() {};
if (!console["timeStamp"]) console["timeStamp"] = function() {};
if (!console["profile"]) console["profile"] = function() {};
if (!console["profileEnd"]) console["profileEnd"] = function() {};
if (!console["count"]) console["count"] = function() {};

})();
<|endoftext|>


<commit_before>import { Vector2 } from '../math/Vector2.js';
import { MeshStandardMaterial } from './MeshStandardMaterial.js';
import { Color } from '../math/Color.js';

/**
 * parameters = {
 *  clearcoat: <float>,
 *  clearcoatMap: new THREE.Texture( <Image> ),
 *  clearcoatRoughness: <float>,
 *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
 *  clearcoatNormalScale: <Vector2>,
 *  clearcoatNormalMap: new THREE.Texture( <Image> ),
 *
 *  reflectivity: <float>,
 *
 *  sheen: <Color>,
 *
 *  transmission: <float>,
 *  transmissionMap: new THREE.Texture( <Image> )
 * }
 */

function MeshPhysicalMaterial( parameters ) {

	MeshStandardMaterial.call( this );

	this.defines = {

		'STANDARD': '',
		'PHYSICAL': ''

	};

	this.type = 'MeshPhysicalMaterial';

	this.clearcoat = 0.0;
	this.clearcoatMap = null;
	this.clearcoatRoughness = 0.0;
	this.clearcoatRoughnessMap = null;
	this.clearcoatNormalScale = new Vector2( 1, 1 );
	this.clearcoatNormalMap = null;

	this.reflectivity = 0.5; // maps to F0 = 0.04

	this.sheen = null; // null will disable sheen bsdf

	this.transmission = 0.0;
	this.transmissionMap = null;

	this.setValues( parameters );

}

MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;

MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;

MeshPhysicalMaterial.prototype.copy = function ( source ) {

	MeshStandardMaterial.prototype.copy.call( this, source );

	this.defines = {

		'STANDARD': '',
		'PHYSICAL': ''

	};

	this.clearcoat = source.clearcoat;
	this.clearcoatMap = source.clearcoatMap;
	this.clearcoatRoughness = source.clearcoatRoughness;
	this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
	this.clearcoatNormalMap = source.clearcoatNormalMap;
	this.clearcoatNormalScale.copy( source.clearcoatNormalScale );

	this.reflectivity = source.reflectivity;

	if ( source.sheen ) {

		this.sheen = ( this.sheen || new Color() ).copy( source.sheen );

	} else {

		this.sheen = null;

	}

	this.transmission = source.transmission;
	this.transmissionMap = source.transmissionMap;

	return this;

};

export { MeshPhysicalMaterial };
<commit_msg>Added .ior property<commit_after>import { Vector2 } from '../math/Vector2.js';
import { MeshStandardMaterial } from './MeshStandardMaterial.js';
import { Color } from '../math/Color.js';
import { MathUtils } from '../math/MathUtils.js';

/**
 * parameters = {
 *  clearcoat: <float>,
 *  clearcoatMap: new THREE.Texture( <Image> ),
 *  clearcoatRoughness: <float>,
 *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
 *  clearcoatNormalScale: <Vector2>,
 *  clearcoatNormalMap: new THREE.Texture( <Image> ),
 *
 *  reflectivity: <float>,
 *  ior: <float>,
 *
 *  sheen: <Color>,
 *
 *  transmission: <float>,
 *  transmissionMap: new THREE.Texture( <Image> )
 * }
 */

function MeshPhysicalMaterial( parameters ) {

	MeshStandardMaterial.call( this );

	this.defines = {

		'STANDARD': '',
		'PHYSICAL': ''

	};

	this.type = 'MeshPhysicalMaterial';

	this.clearcoat = 0.0;
	this.clearcoatMap = null;
	this.clearcoatRoughness = 0.0;
	this.clearcoatRoughnessMap = null;
	this.clearcoatNormalScale = new Vector2( 1, 1 );
	this.clearcoatNormalMap = null;

	this.reflectivity = 0.5; // maps to F0 = 0.04

	Object.defineProperty( this, 'ior', {
		get: function () {

			return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity );

		},
		set: function ( ior ) {

			this.reflectivity = MathUtils.clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 );

		}
	} );

	this.sheen = null; // null will disable sheen bsdf

	this.transmission = 0.0;
	this.transmissionMap = null;

	this.setValues( parameters );

}

MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;

MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;

MeshPhysicalMaterial.prototype.copy = function ( source ) {

	MeshStandardMaterial.prototype.copy.call( this, source );

	this.defines = {

		'STANDARD': '',
		'PHYSICAL': ''

	};

	this.clearcoat = source.clearcoat;
	this.clearcoatMap = source.clearcoatMap;
	this.clearcoatRoughness = source.clearcoatRoughness;
	this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
	this.clearcoatNormalMap = source.clearcoatNormalMap;
	this.clearcoatNormalScale.copy( source.clearcoatNormalScale );

	this.reflectivity = source.reflectivity;

	if ( source.sheen ) {

		this.sheen = ( this.sheen || new Color() ).copy( source.sheen );

	} else {

		this.sheen = null;

	}

	this.transmission = source.transmission;
	this.transmissionMap = source.transmissionMap;

	return this;

};

export { MeshPhysicalMaterial };
<|endoftext|>


<commit_before>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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.
 */

/**
  AbstractClass is the root of FOAM's class hierarchy.
  The FObject Class extends AbstractClass.
 */
foam.LIB({
  name: 'foam.AbstractClass',

  // documentation: "Root prototype for all classes.",

  constants: {
    prototype: Object.prototype,
    axiomMap_: {}
  },

  methods: [
    /**
      Create a new instance of this class.
      Configured from values taken from 'args', if supplifed.
    */
    function create(args, opt_parent) {
      var obj = Object.create(this.prototype);

      // Properties have their values stored in instance_ instead
      // of on the object directly. This lets us defineProperty on
      // the object itself so that we can add extra behaviour
      // to properties (things like preSet, postSet, firing property-
      // change events, etc.).
      obj.instance_ = {};

      // initArgs() is the standard argument extraction method.
      obj.initArgs(args, opt_parent);

      // init(), if defined, is called when object is created.
      // This is where class specific initialization code should
      // be put (not in initArgs).
      obj.init && obj.init();

      return obj;
    },

    /**
      Install Axioms into the class and prototype.
      Invalidate the axiom-cache, used by getAxiomsByName().

      FUTURE: Wait for first object to be created before creating prototype.
      Currently it installs axioms into the protoype immediately, but in should
      wait until the first object is created. This will provide
      better startup performance.
    */
    function installAxioms(axs) {
      this.private_.axiomCache = {};

      for ( var i = 0 ; i < axs.length ; i++ ) {
        var a = axs[i];

        // Store the destination class in the Axiom.  Used by describe().
        // Store source class on a clone of 'a' so that the Axiom can be
        // reused without corrupting the sourceCls_.
        // Disabled: is causing dramatic performance slow-down.
        // a = Object.create(a);
        a.sourceCls_ = this;

        this.axiomMap_[a.name] = a;
      }

      for ( var i = 0 ; i < axs.length ; i++ ) {
        var a = axs[i];

        a.installInClass && a.installInClass(this);
        a.installInProto && a.installInProto(this.prototype);

        if ( a.name ) {
          this.pubsub_ && this.pubsub_.pub('installAxiom', a.name, a);
        }
      }
    },

    function installAxiom(a) {
      this.installAxioms([a]);
    },

    /**
      Determine if an object is an instance of this class
      or one of its sub-classes.
    */
    function isInstance(o) {
      return !! ( o && o.cls_ && this.isSubClass(o.cls_) );
    },

    /**
      Determine if a class is either this class, a sub-class, or
      if it implements this class (directly or indirectly.
    */
    function isSubClass(c) {
      if ( ! c ) return false;

      var cache = this.private_.isSubClassCache ||
        ( this.private_.isSubClassCache = {} );

      if ( cache[c.id] === undefined ) {
        cache[c.id] = ( c === this.prototype.cls_ ) ||
          ( c.getAxiomByName && !! c.getAxiomByName('implements_' + this.id) ) ||
          this.isSubClass(c.__proto__);
      }

      return cache[c.id];
    },

    /** Find an axiom by the specified name from either this class or an ancestor. */
    function getAxiomByName(name) {
      return this.axiomMap_[name];
    },

    /**
      Returns all axioms defined on this class or its parent classes
      that are instances of the specified class.
    */
    function getAxiomsByClass(cls) {
      // FUTURE: Add efficient support for:
      //    .where() .orderBy() .groupBy()
      var as = this.private_.axiomCache[cls.id];
      if ( ! as ) {
        as = [];
        for ( var key in this.axiomMap_ ) {
          var a = this.axiomMap_[key];
          if ( cls.isInstance(a) ) as.push(a);
        }
        this.private_.axiomCache[cls.id] = as;
      }

      return as;
    },

    /**
      Return true if an axiom named "name" is defined on this class
      directly, regardless of what parent classes define.
    */
    function hasOwnAxiom(name) {
      return this.axiomMap_.hasOwnProperty(name);
    },

    /** Returns all axioms defined on this class or its parent classes. */
    function getAxioms() {
      // The full axiom list is stored in the regular cache with '' as a key.
      var as = this.private_.axiomCache[''];
      if ( ! as ) {
        as = [];
        for ( var key in this.axiomMap_ ) as.push(this.axiomMap_[key]);
        this.private_.axiomCache[''] = as;
      }
      return as;
    },

    // NOP, is replaced if debug.js is loaded
    function validate() { },

    function toString() { return this.name + 'Class'; },

    /**
      Temporary Bootstrap Implementation

      This is a temporary version of installModel.
      When the bootstrap is finished, it will be replaced by a
      version that only knows how to install axioms.

      It is easier to start with hard-coded method and property
      support because Axioms need methods to install themselves
      and Property Axioms themselves have properties.

      However, once we've bootstrapped proper Property and Method
      Axioms, we can remove this support and just install Axioms.
    */
    function installModel(m) {
      if ( m.methods ) {
        for ( var i = 0 ; i < m.methods.length ; i++ ) {
          var a = m.methods[i];
          if ( typeof a === 'function' ) {
            m.methods[i] = a = { name: a.name, code: a };
          }
          this.prototype[a.name] = a.code;
        }
      }

      /*
        Properties can be defined using three formats:
        1. Short-form String: Ex.: 'firstName' or 'sex'
        2. Medium-form Array: Ex.: [ 'firstName', 'John' ] or [ 'sex', 'Male' ]
           The first element of the array is the name and the second is the default value.
        3. Long-form JSON: Ex.: [ name: 'firstName', value: 'John' ] or
           { class: 'String', name: 'sex', value: 'Male' }
           The long-form supports many options, but only 'name' is mandatory.
       */
      if ( foam.core.Property && m.properties ) {
        for ( var i = 0 ; i < m.properties.length ; i++ ) {
          var a = m.properties[i];

          if ( Array.isArray(a) ) {
            m.properties[i] = a = { name: a[0], value: a[1] };
          } else if ( typeof a === 'string' ) {
            m.properties[i] = a = { name: a };
          }

          var type = foam.lookup(a.class, true) || foam.core.Property;
          console.assert(
            type !== a.cls_,
            'Property', a.name, 'on', m.name,
            'has already been upgraded to a Property.');

          a = type.create(a);

          this.installAxiom(a);
        }
      }
    }
  ]
});
<commit_msg>Added getOwnAxiomsByClass() to AbstractClass.<commit_after>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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.
 */

/**
  AbstractClass is the root of FOAM's class hierarchy.
  The FObject Class extends AbstractClass.
 */
foam.LIB({
  name: 'foam.AbstractClass',

  // documentation: "Root prototype for all classes.",

  constants: {
    prototype: Object.prototype,
    axiomMap_: {}
  },

  methods: [
    /**
      Create a new instance of this class.
      Configured from values taken from 'args', if supplifed.
    */
    function create(args, opt_parent) {
      var obj = Object.create(this.prototype);

      // Properties have their values stored in instance_ instead
      // of on the object directly. This lets us defineProperty on
      // the object itself so that we can add extra behaviour
      // to properties (things like preSet, postSet, firing property-
      // change events, etc.).
      obj.instance_ = {};

      // initArgs() is the standard argument extraction method.
      obj.initArgs(args, opt_parent);

      // init(), if defined, is called when object is created.
      // This is where class specific initialization code should
      // be put (not in initArgs).
      obj.init && obj.init();

      return obj;
    },

    /**
      Install Axioms into the class and prototype.
      Invalidate the axiom-cache, used by getAxiomsByName().

      FUTURE: Wait for first object to be created before creating prototype.
      Currently it installs axioms into the protoype immediately, but in should
      wait until the first object is created. This will provide
      better startup performance.
    */
    function installAxioms(axs) {
      this.private_.axiomCache = {};

      for ( var i = 0 ; i < axs.length ; i++ ) {
        var a = axs[i];

        // Store the destination class in the Axiom.  Used by describe().
        // Store source class on a clone of 'a' so that the Axiom can be
        // reused without corrupting the sourceCls_.
        // Disabled: is causing dramatic performance slow-down.
        // a = Object.create(a);
        a.sourceCls_ = this;

        this.axiomMap_[a.name] = a;
      }

      for ( var i = 0 ; i < axs.length ; i++ ) {
        var a = axs[i];

        a.installInClass && a.installInClass(this);
        a.installInProto && a.installInProto(this.prototype);

        if ( a.name ) {
          this.pubsub_ && this.pubsub_.pub('installAxiom', a.name, a);
        }
      }
    },

    function installAxiom(a) {
      this.installAxioms([a]);
    },

    /**
      Determine if an object is an instance of this class
      or one of its sub-classes.
    */
    function isInstance(o) {
      return !! ( o && o.cls_ && this.isSubClass(o.cls_) );
    },

    /**
      Determine if a class is either this class, a sub-class, or
      if it implements this class (directly or indirectly.
    */
    function isSubClass(c) {
      if ( ! c ) return false;

      var cache = this.private_.isSubClassCache ||
        ( this.private_.isSubClassCache = {} );

      if ( cache[c.id] === undefined ) {
        cache[c.id] = ( c === this.prototype.cls_ ) ||
          ( c.getAxiomByName && !! c.getAxiomByName('implements_' + this.id) ) ||
          this.isSubClass(c.__proto__);
      }

      return cache[c.id];
    },

    /** Find an axiom by the specified name from either this class or an ancestor. */
    function getAxiomByName(name) {
      return this.axiomMap_[name];
    },

    /**
      Returns all axioms defined on this class or its parent classes
      that are instances of the specified class.
    */
    function getAxiomsByClass(cls) {
      // FUTURE: Add efficient support for:
      //    .where() .orderBy() .groupBy()
      var as = this.private_.axiomCache[cls.id];
      if ( ! as ) {
        as = [];
        for ( var key in this.axiomMap_ ) {
          var a = this.axiomMap_[key];
          if ( cls.isInstance(a) ) as.push(a);
        }
        this.private_.axiomCache[cls.id] = as;
      }

      return as;
    },

    function getOwnAxiomsByClass(cls) {
      return this.getAxiomsByClass(cls).filter(function(a) {
        return this.hasOwnAxiom(a.name);
      }.bind(this));
    },

    /**
      Return true if an axiom named "name" is defined on this class
      directly, regardless of what parent classes define.
    */
    function hasOwnAxiom(name) {
      return this.axiomMap_.hasOwnProperty(name);
    },

    /** Returns all axioms defined on this class or its parent classes. */
    function getAxioms() {
      // The full axiom list is stored in the regular cache with '' as a key.
      var as = this.private_.axiomCache[''];
      if ( ! as ) {
        as = [];
        for ( var key in this.axiomMap_ ) as.push(this.axiomMap_[key]);
        this.private_.axiomCache[''] = as;
      }
      return as;
    },

    // NOP, is replaced if debug.js is loaded
    function validate() { },

    function toString() { return this.name + 'Class'; },

    /**
      Temporary Bootstrap Implementation

      This is a temporary version of installModel.
      When the bootstrap is finished, it will be replaced by a
      version that only knows how to install axioms.

      It is easier to start with hard-coded method and property
      support because Axioms need methods to install themselves
      and Property Axioms themselves have properties.

      However, once we've bootstrapped proper Property and Method
      Axioms, we can remove this support and just install Axioms.
    */
    function installModel(m) {
      if ( m.methods ) {
        for ( var i = 0 ; i < m.methods.length ; i++ ) {
          var a = m.methods[i];
          if ( typeof a === 'function' ) {
            m.methods[i] = a = { name: a.name, code: a };
          }
          this.prototype[a.name] = a.code;
        }
      }

      /*
        Properties can be defined using three formats:
        1. Short-form String: Ex.: 'firstName' or 'sex'
        2. Medium-form Array: Ex.: [ 'firstName', 'John' ] or [ 'sex', 'Male' ]
           The first element of the array is the name and the second is the default value.
        3. Long-form JSON: Ex.: [ name: 'firstName', value: 'John' ] or
           { class: 'String', name: 'sex', value: 'Male' }
           The long-form supports many options, but only 'name' is mandatory.
       */
      if ( foam.core.Property && m.properties ) {
        for ( var i = 0 ; i < m.properties.length ; i++ ) {
          var a = m.properties[i];

          if ( Array.isArray(a) ) {
            m.properties[i] = a = { name: a[0], value: a[1] };
          } else if ( typeof a === 'string' ) {
            m.properties[i] = a = { name: a };
          }

          var type = foam.lookup(a.class, true) || foam.core.Property;
          console.assert(
            type !== a.cls_,
            'Property', a.name, 'on', m.name,
            'has already been upgraded to a Property.');

          a = type.create(a);

          this.installAxiom(a);
        }
      }
    }
  ]
});
<|endoftext|>


<commit_before>var Benchtap = require('benchtap'),
	gen = require('../../generate'),
	dv = require('./datavore');

var benchtap = new Benchtap();
function generate_data(N) {
    function randn(n) {
        return Math.max(0, Math.floor(n*(Math.random()-0.001)));
    }

    // generate synthetic data set
    var cols = [[],[]],  // data columns
        am = ["a","b","c"]; // domain of 1st col

    // generate rows from random data
    for (var i=0; i<N-1; ++i) {
        cols[0].push(am[randn(am.length)]);
        //cols[1].push(bm[randn(bm.length)]);
        cols[1].push(randn(10000));
    }

    /*
    // add one extra row to introduce sparsity
    cols[0].push("d");
    cols[1].push(1);
    cols[2].push(10);
    */

    // construct datavore table
    /*
    var names = ["a","b","x"],                   // column names
        types = ["nominal","nominal","numeric"]; // dv.type constants
    */

    var names = ["a", "x"],                   // column names
        types = ["nominal", "numeric"]; // dv.type constants
    return dv.table(cols.map(function(d,i) {
        return {name:names[i], type:types[i], values:d};
    }));
}

var N = 1e6;
var K = 3;

/*
var groupCol = gen.Array.int(N, K);
var valueCol = gen.Array.int(N, 10000);

groupCol = groupCol.map(i => ["a", "b", "c"][i]);

// create table
table = dv.table([
	{name:"group-col", type:"nominal", values:groupCol},
	{name:"reduce-col", type:"numeric", values:valueCol}
]);
*/
var table = generate_data(N);

function createSetup(N, K){
	return function(event){
		// generate data
		/*
		var groupCol = gen.Array.int(N, K);
		var valueCol = gen.Array.int(N, 10000);

		groupCol = groupCol.map(i => ["a", "b", "c"][i]);

		// create table
		this.table = dv.table([
			{name:"group-col", type:"nominal", values:groupCol},
			{name:"reduce-col", type:"numeric", values:valueCol}
		]);
		*/
		/*
		this.table = dv.table();
		this.table.addColumn("group-col", groupCol, dv.type.nominal);
		this.table.addColumn("reduce-col", valueCol, dv.type.numeric);
		*/

	};
}

function test(){

	var result = table.query({
		"dims" : [0],
		"vals" : [dv.sum("x")]
	});
}

/*
var N = 100000,
	K = 3;

var name = "table.query.sum: " + N + "x" + K;

benchtap.add(name, createSetup(N, K), test, N);

var K = 3;
var N = 1000000;
*/

name = "table.query.sum: " + N + "x" + K;

benchtap.add(name, createSetup(N, K), test, N);

benchtap.run();
<commit_msg>revert datavore benchmark data to current standard test set<commit_after>var Benchtap = require('benchtap'),
	gen = require('../../generate'),
	dv = require('./datavore');

var benchtap = new Benchtap();

function createSetup(N, K){
	return function(event){

		var groupCol = gen.Array.int(N, K);
		var valueCol = gen.Array.int(N, 100);

		//groupCol = groupCol.map(i => ["a", "b", "c"][i]);

		// create table
		this.table = dv.table([
			{name:"group-col", type:"nominal", values:groupCol},
			{name:"reduce-col", type:"numeric", values:valueCol}
		]);

		// generate data
		/*
		this.table = dv.table();
		this.table.addColumn("group-col", groupCol, dv.type.nominal);
		this.table.addColumn("reduce-col", valueCol, dv.type.numeric);
		*/

	};
}

function test(){

	var result = this.table.query({
		"dims" : [0],
		"vals" : [dv.sum("reduce-col")]
	});
}

var N = 100000,
	K = 3;

var name = "table.query.sum: " + N + "x" + K;

//benchtap.add(name, createSetup(N, K), test, N);

var N = 1000000;

name = "table.query.sum: " + N + "x" + K;

benchtap.add(name, createSetup(N, K), test, N);

benchtap.run();
<|endoftext|>