<commit_before>// DON'T MODIFY THIS FILE

// this is an immediately-invoked function expression (IIFE)
(function(){

    const penBrush = {
        name: 'Pen',
        draw: function(ctx, strokeStyle, x, y, r){
            ctx.lineJoin = ctx.lineCap = 'round';
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r;
            ctx.lineTo(x, y);
            ctx.stroke();
        }
    };

    const crossBrush = {
        name : "Cross",

        draw : function (ctx, strokeStyle, x, y, r){
            let l = r / Math.PI;

            //do the actual drawing
            ctx.lineJoin = 'miter';
            ctx.lineCap = 'butt';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.scale(l, l);
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = Math.ceil(l/10);
            ctx.lineTo(0, l);
            ctx.lineTo(0, -l);
            ctx.closePath();
            ctx.stroke();
            ctx.beginPath();
            ctx.lineTo(l, 0);
            ctx.lineTo(-l, 0);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();
        }
    };

    const squareBrush = {
        name : "Square",
        draw : function (ctx, strokeStyle, x, y, r) {
            let l = r * Math.PI;
            ctx.lineJoin = 'mitter';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            // ctx.scale(r);
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            ctx.lineTo(-l, l);
            ctx.lineTo(l, l);
            ctx.lineTo(l, -l);
            ctx.lineTo(-l, -l);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();

        }
    };

    const circleBrush = {
        name : "Circle",
        draw : function (ctx, strokeStyle, x, y, r) {
            let l = r * Math.PI;
            ctx.lineJoin = 'mitter';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            ctx.arc(0, 0, l, 0, 360, false);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();

        }
    };

    const triangularBrush = {
        name : "Triangle",
        draw : function (ctx, strokeStyle, x, y, r) {
            let l = r * 2 * Math.PI;

            ctx.lineJoin = 'mitter';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            ctx.lineTo(0, -l/2);
            ctx.lineTo(-l/2, (l/2)*(Math.sqrt(3)-1));
            ctx.lineTo(l/2, (l/2)*(Math.sqrt(3)-1));
            ctx.closePath();
            ctx.stroke();
            ctx.restore();
        }
    };

    const starBrush = {
        name : 'Star',

        draw : function (ctx, strokeStyle, x, y, r){
            let l = r * Math.PI;
            ctx.lineJoin = 'miter';
            ctx.lineCap = 'butt';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.rotate(Math.PI / 180);
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            for (let i = 5; i--;) {
                ctx.lineTo(0, l);
                ctx.translate(0, l);
                ctx.rotate((Math.PI * 2 / 10));
                ctx.lineTo(0, -l);
                ctx.translate(0, -l);
                ctx.rotate(-(Math.PI * 6 / 10));
            }
            ctx.lineTo(0, l);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();
        }
    };

    const FillCanvas = {
        name : 'FillCanvas',
        draw : function (ctx, strokeStyle, w, h) {
            ctx.lineJoin = ctx.lineCap = 'miter';
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = 1;
            ctx.fillStyle = strokeStyle;
            ctx.rect(0, 0, w, h);
            ctx.fill ();
            ctx.stroke();
        }
    };

    window.brushes = [penBrush, circleBrush, triangularBrush, squareBrush, starBrush, crossBrush];
    window.fillCanvas = [FillCanvas];
})();
<commit_msg>Deleted some code that I ended up not using<commit_after>// DON'T MODIFY THIS FILE

// this is an immediately-invoked function expression (IIFE)
(function(){

    const penBrush = {
        name: 'Pen',
        draw: function(ctx, strokeStyle, x, y, r){
            ctx.lineJoin = ctx.lineCap = 'round';
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r;
            ctx.lineTo(x, y);
            ctx.stroke();
        }
    };

    const crossBrush = {
        name : "Cross",

        draw : function (ctx, strokeStyle, x, y, r){
            let l = r / Math.PI;

            //do the actual drawing
            ctx.lineJoin = 'miter';
            ctx.lineCap = 'butt';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.scale(l, l);
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = Math.ceil(l/10);
            ctx.lineTo(0, l);
            ctx.lineTo(0, -l);
            ctx.closePath();
            ctx.stroke();
            ctx.beginPath();
            ctx.lineTo(l, 0);
            ctx.lineTo(-l, 0);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();
        }
    };

    const squareBrush = {
        name : "Square",
        draw : function (ctx, strokeStyle, x, y, r) {
            let l = r * Math.PI;
            ctx.lineJoin = 'mitter';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            // ctx.scale(r);
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            ctx.lineTo(-l, l);
            ctx.lineTo(l, l);
            ctx.lineTo(l, -l);
            ctx.lineTo(-l, -l);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();

        }
    };

    const circleBrush = {
        name : "Circle",
        draw : function (ctx, strokeStyle, x, y, r) {
            let l = r * Math.PI;
            ctx.lineJoin = 'mitter';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            ctx.arc(0, 0, l, 0, 360, false);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();

        }
    };

    const triangularBrush = {
        name : "Triangle",
        draw : function (ctx, strokeStyle, x, y, r) {
            let l = r * 2 * Math.PI;

            ctx.lineJoin = 'mitter';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            ctx.lineTo(0, -l/2);
            ctx.lineTo(-l/2, (l/2)*(Math.sqrt(3)-1));
            ctx.lineTo(l/2, (l/2)*(Math.sqrt(3)-1));
            ctx.closePath();
            ctx.stroke();
            ctx.restore();
        }
    };

    const starBrush = {
        name : 'Star',

        draw : function (ctx, strokeStyle, x, y, r){
            let l = r * Math.PI;
            ctx.lineJoin = 'miter';
            ctx.lineCap = 'butt';
            ctx.save();
            ctx.translate(x, y);
            ctx.beginPath();
            ctx.rotate(Math.PI / 180);
            ctx.strokeStyle = strokeStyle;
            ctx.lineWidth = r/4;
            for (let i = 5; i--;) {
                ctx.lineTo(0, l);
                ctx.translate(0, l);
                ctx.rotate((Math.PI * 2 / 10));
                ctx.lineTo(0, -l);
                ctx.translate(0, -l);
                ctx.rotate(-(Math.PI * 6 / 10));
            }
            ctx.lineTo(0, l);
            ctx.closePath();
            ctx.stroke();
            ctx.restore();
        }
    };

    window.brushes = [penBrush, circleBrush, triangularBrush, squareBrush, starBrush, crossBrush];
})();
<|endoftext|>


<commit_before><commit_msg>Update keycode.js<commit_after><|endoftext|>


<commit_before><commit_msg>Added comments to scope sample (5).<commit_after><|endoftext|>


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

  angular.module('RkyApp.directives')
    .directive('d3Bars', ['d3', function(d3) {
      return {
        restrict: 'EA',
        scope: {
          data: "=",
          label: "@",
          onClick: "&"
        },
        link: function(scope, iElement, iAttrs) {
          var svg = d3.select(iElement[0])
              .append("svg")
              .attr("width", "100%");

          // on window resize, re-render d3 canvas
          window.onresize = function() {
            return scope.$apply();
          };
          scope.$watch(function(){
              return angular.element(window)[0].innerWidth;
            }, function(){
              return scope.render(scope.data);
            }
          );

          // watch for data changes and re-render
          scope.$watch('data', function(newVals, oldVals) {
            return scope.render(newVals);
          }, true);

          // define render function
          scope.render = function(data){
            // remove all previous items before render
            svg.selectAll("*").remove();

            // setup variables
            var width, height, max;
            width = d3.select(iElement[0])[0][0].offsetWidth - 20;
              // 20 is for margins and can be changed
            height = scope.data.length * 35;
              // 35 = 30(bar height) + 5(margin between bars)
            max = 98;
              // this can also be found dynamically when the data is not static
              // max = Math.max.apply(Math, _.map(data, ((val)-> val.count)))

            // set the height based on the calculations above
            svg.attr('height', height);

            //create the rectangles for the bar chart
            svg.selectAll("rect")
              .data(data)
              .enter()
                .append("rect")
                .on("click", function(d, i){return scope.onClick({item: d});})
                .attr("height", 30) // height of each bar
                .attr("width", 0) // initial width of 0 for transition
                .attr("x", 10) // half of the 20 side margin specified above
                .attr("y", function(d, i){
                  return i * 35;
                }) // height + margin between bars
                .transition()
                  .duration(1000) // time of duration
                  .attr("width", function(d){
                    return d.value/(max/width);
                  }); // width based on scale

            svg.selectAll("text")
              .data(data)
              .enter()
                .append("text")
                .attr("fill", "#fff")
                .attr("y", function(d, i){return i * 35 + 22;})
                .attr("x", 15)
                .text(function(d){return d[scope.label];});

          };
        }
      };
    }]);

}());

// -- by e-Coucou

(function () {
  'use strict';

  angular.module('RkyApp.directives')
    .directive('d3Lines', ['d3', function(d3) {
      return {
        restrict: 'EA',
        scope: {
          data: "=",
          label: "@",
          moyn: "=",
          onClick: "&"
        },
        link: function(scope, iElement, iAttrs) {
        // Dimensions.
        var margin = {top: 20, right: 20, bottom: 30, left: 40},
            width = 1080 - margin.right-margin.left,
            height = 450 - margin.top - margin.bottom;
        // creation du contenair
        console.log(iElement[0]);
        var svg = d3.select(iElement[0])
              .append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom)
            .append("g")
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

          // on window resize, re-render d3 canvas
          window.onresize = function() {
            return scope.$apply();
          };
          scope.$watch(function(){
              return angular.element(window)[0].innerWidth;
            }, function(){
              return scope.render(scope.data);
            }
          );

          // watch for data changes and re-render
          scope.$watch('data', function(newVals, oldVals) {
            return scope.render(newVals);
          }, true);
          // define render function
          scope.render = function(data,moyn){

            // setup variables
            var max,maxi, min,mini;
            var padding = 1;

            // accessor
            function x(d,i) { return i * (width / data.length);}
            function y(d) { return (height - (d.value-min)/((max-min)/height)); }
            function h(d) { return ((d.value-min)/((max-min)/height));}

            // fonction
            function info(d,i) {
              var s_date = d.date.split('/');
              var s_heure = d.heure.split(':');
              var date_text = s_date[1]+'/'+s_date[0]+'\n'+s_heure[0]+':'+s_heure[1];
              label.text(Math.round(d.value*100)/100) ;
              var datac = [ { "x" : x(d,i), "y" : 20 }, { "x" : x(d,i), "y" : height } ];
              d3.selectAll(".curseur").remove();
              d3.selectAll(".date").remove();
              var datadate = [{"x" : x(d,i), "text":d.heure}];
              svg.append("text")
                 .data(datadate)
                 .attr("class", "date label")
                 .attr("text-anchor", "middle")
                 .attr("x",  function(d) {return d.x;} )
                 .attr("y", 0)
                 .text(function(d) {return date_text;});

              svg.append("path")
                .datum(datac)
                .attr("class", "curseur")
                .attr("d", curseur);
              }
            // remove all previous items before render
            svg.selectAll("*").remove();

             console.log(d3.select(iElement[0])[0][0].offsetHeight);
            console.log(d3.select(iElement[0])[0][0].offsetWidth);
//            console.log(height,width);
              // 20 is for margins and can be changed
//            width = 1160 ;//scope.data.length * 35;
//            width = 1000;
//            height = 450 ;
            if (data.length > 500 ) { padding = 0; } // no padding si trop de data
            maxi = Math.max.apply(Math, data.map(function(x) {return x.value; }));
            mini = Math.min.apply(Math, data.map(function(x) {return x.value; }));
//            console.log("max: ",maxi,"min: ",mini, "moyenne: ",scope.moyn);

            max = maxi + 0.07 * (maxi-mini);
            min = mini - 0.15 * (maxi-mini);

            // set the height based on the calculations above
            svg.attr('height', height)
               .attr('width',  width);

// Add the year label; the value is set on transition.
var label = svg.append("text")
    .attr("class", "year label")
    .attr("text-anchor", "end")
    .attr("y",  55)
    .attr("x", width)
    .text('VALEUR');

var curseur = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

var repere_min = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

var repere_max = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

var repere_moy = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

// Add a y-axis label.
var yScale = d3.scale.linear().domain([max, min]).range([0,height]),
    yAxis = d3.svg.axis().scale(yScale).orient("left");

svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

svg.append("text")
    .attr("class", "y label")
    .attr("text-anchor", "end")
    .attr("y", 6)
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90)")
    .text("mesure");

            //create the rectangles for the bar chart
            svg.selectAll("rect")
              .data(data)
              .enter()
                .append("rect")
                .on("click", function(d, i){return scope.onClick({item: d});})
                .on("mouseover",function (d,i) { return info(d,i);})
                .attr("height", 0) // height of each bar
                .attr("width", width / data.length - padding)
                .attr("x", function(d,i) { return x(d, i);})  // height + margin between bars
                .attr("fill","yellow")
                .transition()
                  .duration(3000) // time of duration
                  .attr("stroke-width",0)
                  .attr("fill", function(d) {
                    var val = ((d.value -min)/((max-min)/16));
                    return "rgb(10, 160, " + val*16 + ")";
                    })
                  .attr("height", function (d) { return h(d); }) // half of the 20 side margin specified above
                  .attr("y", function (d) { return y(d);}); // width based on scale

            // position des repères
            var ordonne = height - (mini-min)/((max-min)/height);
            var datac = [ { "x" : 0, "y" : ordonne }, { "x" : width, "y" : ordonne } ];
            d3.selectAll(".repere_min").remove();
            svg.append("path")
              .datum(datac)
              .attr("class", "repere")
              .style("stroke-dasharray", ("10,5,2,5"))
              .attr("d", repere_min);
            ordonne = height - (maxi-min)/((max-min)/height);
            datac = [ { "x" : 0, "y" : ordonne }, { "x" : width, "y" : ordonne } ];
            d3.selectAll(".repere_max").remove();
            svg.append("path")
              .datum(datac)
              .attr("class", "repere")
              .style("stroke-dasharray", ("10,5,2,5"))
              .attr("d", repere_max);
            ordonne = height - (scope.moyn-min)/((max-min)/height);
            datac = [ { "x" : 0, "y" : ordonne }, { "x" : width, "y" : ordonne } ];
            d3.selectAll(".repere_moy").remove();
            svg.append("path")
              .datum(datac)
              .attr("class", "repere")
              .style("stroke-dasharray", ("10,5,2,5"))
              .attr("d", repere_moy);

            svg.selectAll("text")
              .data(data)
              .enter()
                .append("text")
                .attr("fill", "#fff")
                .attr("y", function(d, i){return i * 35 + 22;})
                .attr("x", 15)
                .text(function(d){return d[scope.label];});

          };
        }
      };
    }]);

}());<commit_msg>element<commit_after>(function () {
  'use strict';

  angular.module('RkyApp.directives')
    .directive('d3Bars', ['d3', function(d3) {
      return {
        restrict: 'EA',
        scope: {
          data: "=",
          label: "@",
          onClick: "&"
        },
        link: function(scope, iElement, iAttrs) {
          var svg = d3.select(iElement[0])
              .append("svg")
              .attr("width", "100%");

          // on window resize, re-render d3 canvas
          window.onresize = function() {
            return scope.$apply();
          };
          scope.$watch(function(){
              return angular.element(window)[0].innerWidth;
            }, function(){
              return scope.render(scope.data);
            }
          );

          // watch for data changes and re-render
          scope.$watch('data', function(newVals, oldVals) {
            return scope.render(newVals);
          }, true);

          // define render function
          scope.render = function(data){
            // remove all previous items before render
            svg.selectAll("*").remove();

            // setup variables
            var width, height, max;
            width = d3.select(iElement[0])[0][0].offsetWidth - 20;
              // 20 is for margins and can be changed
            height = scope.data.length * 35;
              // 35 = 30(bar height) + 5(margin between bars)
            max = 98;
              // this can also be found dynamically when the data is not static
              // max = Math.max.apply(Math, _.map(data, ((val)-> val.count)))

            // set the height based on the calculations above
            svg.attr('height', height);

            //create the rectangles for the bar chart
            svg.selectAll("rect")
              .data(data)
              .enter()
                .append("rect")
                .on("click", function(d, i){return scope.onClick({item: d});})
                .attr("height", 30) // height of each bar
                .attr("width", 0) // initial width of 0 for transition
                .attr("x", 10) // half of the 20 side margin specified above
                .attr("y", function(d, i){
                  return i * 35;
                }) // height + margin between bars
                .transition()
                  .duration(1000) // time of duration
                  .attr("width", function(d){
                    return d.value/(max/width);
                  }); // width based on scale

            svg.selectAll("text")
              .data(data)
              .enter()
                .append("text")
                .attr("fill", "#fff")
                .attr("y", function(d, i){return i * 35 + 22;})
                .attr("x", 15)
                .text(function(d){return d[scope.label];});

          };
        }
      };
    }]);

}());

// -- by e-Coucou

(function () {
  'use strict';

  angular.module('RkyApp.directives')
    .directive('d3Lines', ['d3', function(d3) {
      return {
        restrict: 'EA',
        scope: {
          data: "=",
          label: "@",
          moyn: "=",
          onClick: "&"
        },
        link: function(scope, iElement, iAttrs) {
        // Dimensions.
        var margin = {top: 20, right: 20, bottom: 30, left: 40},
            width = 1080 - margin.right-margin.left,
            height = 450 - margin.top - margin.bottom;
        // creation du contenair
        console.log(iElement[0]);
        var svg = d3.select(iElement[0])
              .append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom)
            .append("g")
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

          // on window resize, re-render d3 canvas
          window.onresize = function() {
            return scope.$apply();
          };
          scope.$watch(function(){
              return angular.element(window)[0].innerWidth;
            }, function(){
              return scope.render(scope.data);
            }
          );

          // watch for data changes and re-render
          scope.$watch('data', function(newVals, oldVals) {
            return scope.render(newVals);
          }, true);
          // define render function
          scope.render = function(data,moyn){

             console.log(d3.select(iElement[0])[0][0].offsetHeight);
            console.log(d3.select(iElement[0])[0][0].offsetWidth);
            // setup variables
            var max,maxi, min,mini;
            var padding = 1;

            // accessor
            function x(d,i) { return i * (width / data.length);}
            function y(d) { return (height - (d.value-min)/((max-min)/height)); }
            function h(d) { return ((d.value-min)/((max-min)/height));}

            // fonction
            function info(d,i) {
              var s_date = d.date.split('/');
              var s_heure = d.heure.split(':');
              var date_text = s_date[1]+'/'+s_date[0]+'\n'+s_heure[0]+':'+s_heure[1];
              label.text(Math.round(d.value*100)/100) ;
              var datac = [ { "x" : x(d,i), "y" : 20 }, { "x" : x(d,i), "y" : height } ];
              d3.selectAll(".curseur").remove();
              d3.selectAll(".date").remove();
              var datadate = [{"x" : x(d,i), "text":d.heure}];
              svg.append("text")
                 .data(datadate)
                 .attr("class", "date label")
                 .attr("text-anchor", "middle")
                 .attr("x",  function(d) {return d.x;} )
                 .attr("y", 0)
                 .text(function(d) {return date_text;});

              svg.append("path")
                .datum(datac)
                .attr("class", "curseur")
                .attr("d", curseur);
              }
            // remove all previous items before render
            svg.selectAll("*").remove();

//            console.log(height,width);
              // 20 is for margins and can be changed
//            width = 1160 ;//scope.data.length * 35;
//            width = 1000;
//            height = 450 ;
            if (data.length > 500 ) { padding = 0; } // no padding si trop de data
            maxi = Math.max.apply(Math, data.map(function(x) {return x.value; }));
            mini = Math.min.apply(Math, data.map(function(x) {return x.value; }));
//            console.log("max: ",maxi,"min: ",mini, "moyenne: ",scope.moyn);

            max = maxi + 0.07 * (maxi-mini);
            min = mini - 0.15 * (maxi-mini);

            // set the height based on the calculations above
            svg.attr('height', height)
               .attr('width',  width);

// Add the year label; the value is set on transition.
var label = svg.append("text")
    .attr("class", "year label")
    .attr("text-anchor", "end")
    .attr("y",  55)
    .attr("x", width)
    .text('VALEUR');

var curseur = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

var repere_min = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

var repere_max = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

var repere_moy = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; });

// Add a y-axis label.
var yScale = d3.scale.linear().domain([max, min]).range([0,height]),
    yAxis = d3.svg.axis().scale(yScale).orient("left");

svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

svg.append("text")
    .attr("class", "y label")
    .attr("text-anchor", "end")
    .attr("y", 6)
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90)")
    .text("mesure");

            //create the rectangles for the bar chart
            svg.selectAll("rect")
              .data(data)
              .enter()
                .append("rect")
                .on("click", function(d, i){return scope.onClick({item: d});})
                .on("mouseover",function (d,i) { return info(d,i);})
                .attr("height", 0) // height of each bar
                .attr("width", width / data.length - padding)
                .attr("x", function(d,i) { return x(d, i);})  // height + margin between bars
                .attr("fill","yellow")
                .transition()
                  .duration(3000) // time of duration
                  .attr("stroke-width",0)
                  .attr("fill", function(d) {
                    var val = ((d.value -min)/((max-min)/16));
                    return "rgb(10, 160, " + val*16 + ")";
                    })
                  .attr("height", function (d) { return h(d); }) // half of the 20 side margin specified above
                  .attr("y", function (d) { return y(d);}); // width based on scale

            // position des repères
            var ordonne = height - (mini-min)/((max-min)/height);
            var datac = [ { "x" : 0, "y" : ordonne }, { "x" : width, "y" : ordonne } ];
            d3.selectAll(".repere_min").remove();
            svg.append("path")
              .datum(datac)
              .attr("class", "repere")
              .style("stroke-dasharray", ("10,5,2,5"))
              .attr("d", repere_min);
            ordonne = height - (maxi-min)/((max-min)/height);
            datac = [ { "x" : 0, "y" : ordonne }, { "x" : width, "y" : ordonne } ];
            d3.selectAll(".repere_max").remove();
            svg.append("path")
              .datum(datac)
              .attr("class", "repere")
              .style("stroke-dasharray", ("10,5,2,5"))
              .attr("d", repere_max);
            ordonne = height - (scope.moyn-min)/((max-min)/height);
            datac = [ { "x" : 0, "y" : ordonne }, { "x" : width, "y" : ordonne } ];
            d3.selectAll(".repere_moy").remove();
            svg.append("path")
              .datum(datac)
              .attr("class", "repere")
              .style("stroke-dasharray", ("10,5,2,5"))
              .attr("d", repere_moy);

            svg.selectAll("text")
              .data(data)
              .enter()
                .append("text")
                .attr("fill", "#fff")
                .attr("y", function(d, i){return i * 35 + 22;})
                .attr("x", 15)
                .text(function(d){return d[scope.label];});

          };
        }
      };
    }]);

}());<|endoftext|>


<commit_before>
// var testLetters = [ "A", "B", "C", "F", "P", "O", "O", "T", "R", "S","C","V","D","I","I","N","N","M","M","E","R","R","T","L","L","Q","Z","H","J","G","_"];
// var initialBag = [];
// for (var i = 0; i < 15; i++) {
//   // this is testing code;  later, check actual letterValues
//   var tiles = new Tile(testLetters[i], i, 2);
//   initialBag.push(tile);
// }

var initialBag = JSON.parse(bag);
console.log(initialBag);

// test dictionary
var dictionary = ["cat", "tree", "rain", "wind"];

function Bag() {
  this.bagTiles = [];
};

function Game() {

  this.board = [];

};

function Player(name, rack) {
  this.name = name;
  this.score = 0;
  this.rack = rack;
  this.partialWord = [];
};

function Tile() {
  this.letter;
  this.letterValue;
};

function Cell(x, y) {
  this.x = x;
  this.y = y;
  this.pointMultiplier = "";
  this.occupied = false;
  this.tile = {};
}

function Rack() {
  this.rackTiles = [];
  this.needNumber = 7;
};

Player.prototype.buildWordSection = function (cell) {
  this.partialWord.push(cell);
};

Game.prototype.generateBoard = function () {
  for (var i = 0; i < 15; i++) {
    for (var j = 0; j < 15; j++) {
      var cell = new Cell (i, j)
      this.board.push(cell);
    }
  }
};

Game.prototype.completeHorizontalWord = function (partialWord) {
  var completeWord = [];
  var horizontal = this.board[partialWord[0].y];// take whole horizontal array from board with y coord
  var firstX = partialWord[0].x;
  var lastX = partialWord[partialWord.length-1].x;

// TODO: sort (cells) partialWord array

// because a user might not drop in a straightforward order

  for (var i = partialWord[0].x; i <= partialWord[partialWord.length-1].x; i++) {
    if (typeof horizontal[i].tile != 'undefined') {
      completeWord.push(horizontal[i]);
    } else {
      return false;
    }
  }

  // debugger;
// Check the beginning of horiz array to see if empty
// also check if we're at the edge of the board

  while ((firstX-1)>=0 && (typeof horizontal[firstX-1].tile != 'undefined')) {
    completeWord.unshift(horizontal[firstX-1]);
    firstX--;
  }

// Check the end of horiz array to see if empty

  while ((lastX+1<=14)&& (typeof horizontal[lastX+1].tile != 'undefined')) {
    completeWord.push(horizontal[lastX+1]);
    lastX++;
  }
  return completeWord;
};

Game.prototype.completeVerticalWord = function (partialWord) {

  var completeWord = [];
  var vertical = this.board[partialWord[0].x]; //take whole vertical array
  var firstY = partialWord][0].y;
  var lastY = partialWord[partialWord.length-1].y;

  // TODO: sort (cells) partialWord array
  // because a user might not drop in a straightforward order

  for (var i = partialWord[0].y; i <=partialWord[partialWord.length].y; i++) {
    if (typeof vertical[i].tile != 'undefined') {
      completeWord.push(vertical[i]);
    } else {
      return false;
    }
  }
  debugger;
  // Check the beginning of horiz array to see if empty
  // also check if we're at the edge of the board
  while ( (firstY-1)>=0 && (typeof vertical[firstY-1].tile != 'undefined')) {
    completeWord.unshift(vertical[firstY-1]);
    firstY--;
  }
  while ( (lastY+1<=14) && (typeof vertical[lastY+1].tile != 'undefined')) {
    completeWord.push(horizontal[lastY+1]);
    lastY++;
  }
  return completeWord;
};

Player.prototype.buildWord = function (tile) {

};

Player.prototype.playerScore = function (wordScore) {
  // debugger;
  // console.log("wordScore inside function = ", wordScore);
  return this.score += wordScore;
};

Rack.prototype.generateRack = function (needNumber,initialBag) {
  for (var i = 0; i < needNumber; i++) {
    var currentRandomInt = getRandomInt(0, initialBag.length-1);
    this.rackTiles.push(initialBag[currentRandomInt]);
    initialBag.splice(currentRandomInt, 1);
  };
}

Game.prototype.checkVerticalPosition = function () {
  var checkVertical;
  for (var i = 0; i < .length-1; i++) {
    if ([i].x === [i+1].x) {
      checkVertical = true;
    } else {
      checkVertical = false;
    }
  }
  return checkVertical;
};

Game.prototype.checkHorizontalPosition = function () {
  var checkHorizontal;
  for (var i = 0; i < .length-1; i++) {
    if ([i].y === [i+1].y) {
      checkHorizontal = true;
    } else {
      checkHorizontal = false;
    }
  }
  return checkHorizontal;
};

Game.prototype.checkValidWord = function () {
  var wordString ="";
  for (var i = 0; i < .length; i++) {
    wordString+=[i].letterValue;
  }
  return dictionary.includes(wordString);

};

Game.prototype.countScore = function() {
  var Score = 0;
  debugger;
  for (var i = 0; i < .length-1; i++) {
    if ([i].pointMultiplier === parseInt("2")) {
      Score += [i].letterValue * 2;

    }
    // multiply any word-level multipliers (2w, 3W);
    if ([i].pointMultiplier === "2W") {
      Score *= 2;
    } else {
      Score += [i].letterValue;
    }
  }
  console.log("current word score = ", Score);
  return Score;

};

//===========================================================================

$(function () {
  var scrabbleGame = new Game();
  scrabbleGame.generateBoard();
  console.log(scrabbleGame.board);

  var rack = new Rack();
  rack.generateRack(7, initialBag);

  var player = new Player ("Tom", rack);

  console.log(player.);
  scrabbleGame.buildHorizontalWord(player.);

  //var score = scrabbleGame.countScore(player., cells)
  // console.log("word score1 = ", score);
  // player.playerScore(score);
  // scrabbleGame.countScore(player., cells);
  // player.playerScore(score);
  // console.log("word score2 = ", score);
  //
  // console.log("player score  ", score);

});

function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
};

//  };

////////////////////// USER INTERFACE

$(document).ready(function(){
//DRAG AND DROP SQUARES
  // $(".makeMeDraggable").draggable({
  //   containment: '.container',
  //   snap: '.cell, .makeMeDraggable',
  //   snapMode: 'outter'
  // });
  // $(".makeMeDroppable").droppable({
  //   drop: handleDropEvent
  // });
  // function handleDropEvent(event, ui) {
  //   var draggable = ui.draggable;
  //   console.log('The tile ' + $(".makeMeDraggable").draggable(0).attr('id') + ' is now in "' + $(this).droppable(0).attr('id') + '" square')
  // };
  $("div.makeMeDraggable").draggable( {
    opacity: .4,
    create: function(){
      $(this).data('position',$(this).position())
    },
    cursorAt: {left:15},
    cursor: 'move',
    start: function(){
      $(this).stop(true,true)
      console.log("DRAGGABLE")
    }
  });

  $('div.row').find('.cell').droppable({
    drop:function(event, ui){
       snapToMiddle(ui.draggable,$(this));
       console.log("DROPPABLE");
    }
  });

  function snapToMiddle(dragger, target){
    // debugger;
    var offset = target.offset();
    var topMove = (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
    var leftMove= (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
    dragger.offset({ top: topMove + offset.top, left: leftMove + offset.left });
  };

//TILE BAG USER INTERFACE
  $(".clickable img").click(function(){
    console.log("MOAR TILES");
  });

//PLAYER BUTTON INPUT
  $("button#score").click(function(){
    console.log("SCORE!");
  });

  $("button#reset").click(function(){
    console.log("RESET");
  });

  $("button#pass").click(function(){
    console.log("PASS");
  });
});
<commit_msg>re-re-re fixing minor syntax errors that were posted to the main master<commit_after>
// var testLetters = [ "A", "B", "C", "F", "P", "O", "O", "T", "R", "S","C","V","D","I","I","N","N","M","M","E","R","R","T","L","L","Q","Z","H","J","G","_"];
// var initialBag = [];
// for (var i = 0; i < 15; i++) {
//   // this is testing code;  later, check actual letterValues
//   var tiles = new Tile(testLetters[i], i, 2);
//   initialBag.push(tile);
// }

var initialBag = JSON.parse(bag);
console.log(initialBag);

// test dictionary
var dictionary = ["cat", "tree", "rain", "wind"];

function Bag() {
  this.bagTiles = [];
};

function Game() {

  this.board = [];

};

function Player(name, rack) {
  this.name = name;
  this.score = 0;
  this.rack = rack;
  this.partialWord = [];
};

function Tile() {
  this.letter;
  this.letterValue;
};

function Cell(x, y) {
  this.x = x;
  this.y = y;
  this.pointMultiplier = "";
  this.occupied = false;
  this.tile = {};
}

function Rack() {
  this.rackTiles = [];
  this.needNumber = 7;
};

Player.prototype.buildWordSection = function (cell) {
  this.partialWord.push(cell);
};

Game.prototype.generateBoard = function () {
  for (var i = 0; i < 15; i++) {
    for (var j = 0; j < 15; j++) {
      var cell = new Cell (i, j)
      this.board.push(cell);
    }
  }
};

Game.prototype.completeHorizontalWord = function (partialWord) {
  var completeWord = [];
  var horizontal = this.board[partialWord[0].y];// take whole horizontal array from board with y coord
  var firstX = partialWord[0].x;
  var lastX = partialWord[partialWord.length-1].x;

// TODO: sort (cells) partialWord array

// because a user might not drop in a straightforward order

  for (var i = partialWord[0].x; i <= partialWord[partialWord.length-1].x; i++) {
    if (typeof horizontal[i].tile != 'undefined') {
      completeWord.push(horizontal[i]);
    } else {
      return false;
    }
  }

  // debugger;
// Check the beginning of horiz array to see if empty
// also check if we're at the edge of the board

  while ((firstX-1)>=0 && (typeof horizontal[firstX-1].tile != 'undefined')) {
    completeWord.unshift(horizontal[firstX-1]);
    firstX--;
  }

// Check the end of horiz array to see if empty

  while ((lastX+1<=14)&& (typeof horizontal[lastX+1].tile != 'undefined')) {
    completeWord.push(horizontal[lastX+1]);
    lastX++;
  }
  return completeWord;
};

Game.prototype.completeVerticalWord = function (partialWord) {

  var completeWord = [];
  var vertical = this.board[partialWord[0].x]; //take whole vertical array
  var firstY = partialWord[0].y;
  var lastY = partialWord[partialWord.length-1].y;

  // TODO: sort (cells) partialWord array
  // because a user might not drop in a straightforward order

  for (var i = partialWord[0].y; i <=partialWord[partialWord.length].y; i++) {
    if (typeof vertical[i].tile != 'undefined') {
      completeWord.push(vertical[i]);
    } else {
      return false;
    }
  }
  debugger;
  // Check the beginning of horiz array to see if empty
  // also check if we're at the edge of the board
  while ( (firstY-1)>=0 && (typeof vertical[firstY-1].tile != 'undefined')) {
    completeWord.unshift(vertical[firstY-1]);
    firstY--;
  }
  while ( (lastY+1<=14) && (typeof vertical[lastY+1].tile != 'undefined')) {
    completeWord.push(horizontal[lastY+1]);
    lastY++;
  }
  return completeWord;
};

Player.prototype.buildWord = function (tile) {

};

Player.prototype.playerScore = function (wordScore) {
  // debugger;
  // console.log("wordScore inside function = ", wordScore);
  return this.score += wordScore;
};

Rack.prototype.generateRack = function (needNumber,initialBag) {
  for (var i = 0; i < needNumber; i++) {
    var currentRandomInt = getRandomInt(0, initialBag.length-1);
    this.rackTiles.push(initialBag[currentRandomInt]);
    initialBag.splice(currentRandomInt, 1);
  };
}

Game.prototype.checkVerticalPosition = function () {
  var checkVertical;
  for (var i = 0; i < partialWord.length-1; i++) {
    if ([i].x === [i+1].x) {
      checkVertical = true;
    } else {
      checkVertical = false;
    }
  }
  return checkVertical;
};

Game.prototype.checkHorizontalPosition = function () {
  var checkHorizontal;
  for (var i = 0; i < partialWord.length-1; i++) {
    if ([i].y === [i+1].y) {
      checkHorizontal = true;
    } else {
      checkHorizontal = false;
    }
  }
  return checkHorizontal;
};

Game.prototype.checkValidWord = function () {
  var wordString ="";
  for (var i = 0; i < currentWord.length; i++) {
    wordString+=[i].letterValue;
  }
  return dictionary.includes(wordString);

};

Game.prototype.countScore = function() {
  var Score = 0;
  debugger;
  for (var i = 0; i < currentWord.length-1; i++) {
    if ([i].pointMultiplier === parseInt("2")) {
      Score += [i].letterValue * 2;

    }
    // multiply any word-level multipliers (2w, 3W);
    if ([i].pointMultiplier === "2W") {
      Score *= 2;
    } else {
      Score += [i].letterValue;
    }
  }
  console.log("current word score = ", Score);
  return Score;

};

//===========================================================================

$(function () {
  var scrabbleGame = new Game();
  scrabbleGame.generateBoard();
  console.log(scrabbleGame.board);

  var rack = new Rack();
  rack.generateRack(7, initialBag);

  var player = new Player ("Tom", rack);

  //var score = scrabbleGame.countScore(player., cells)
  // console.log("word score1 = ", score);
  // player.playerScore(score);
  // scrabbleGame.countScore(player., cells);
  // player.playerScore(score);
  // console.log("word score2 = ", score);
  //
  // console.log("player score  ", score);

});

function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
};

//  };

////////////////////// USER INTERFACE

$(document).ready(function(){
//DRAG AND DROP SQUARES
  // $(".makeMeDraggable").draggable({
  //   containment: '.container',
  //   snap: '.cell, .makeMeDraggable',
  //   snapMode: 'outter'
  // });
  // $(".makeMeDroppable").droppable({
  //   drop: handleDropEvent
  // });
  // function handleDropEvent(event, ui) {
  //   var draggable = ui.draggable;
  //   console.log('The tile ' + $(".makeMeDraggable").draggable(0).attr('id') + ' is now in "' + $(this).droppable(0).attr('id') + '" square')
  // };
  $("div.makeMeDraggable").draggable( {
    opacity: .4,
    create: function(){
      $(this).data('position',$(this).position())
    },
    cursorAt: {left:15},
    cursor: 'move',
    start: function(){
      $(this).stop(true,true)
      console.log("DRAGGABLE")
    }
  });

  $('div.row').find('.cell').droppable({
    drop:function(event, ui){
       snapToMiddle(ui.draggable,$(this));
       console.log("DROPPABLE");
    }
  });

  function snapToMiddle(dragger, target){
    // debugger;
    var offset = target.offset();
    var topMove = (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
    var leftMove= (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
    dragger.offset({ top: topMove + offset.top, left: leftMove + offset.left });
  };

//TILE BAG USER INTERFACE
  $(".clickable img").click(function(){
    console.log("MOAR TILES");
  });

//PLAYER BUTTON INPUT
  $("button#score").click(function(){
    console.log("SCORE!");
  });

  $("button#reset").click(function(){
    console.log("RESET");
  });

  $("button#pass").click(function(){
    console.log("PASS");
  });
});
<|endoftext|>


<commit_before>/****************************************
 *     PENN STATE DIRECTORY API         *
 ****************************************/
(function() {

    /* Imports */
    var request = require('request');
    var querystring = require('querystring');
    var cheerio = require('cheerio');

    /* Public object that will contain the public functions that are going to be exported */
    var pub = {};
    /* Private object that  will contain the private functions that will not be exported */
    var priv = {};

    /**
     * psd-api namespace
     *
     */
    var getStudent = function(options, callbackOne) {
        priv.Student = {}, // student
            priv.form = {}, // form
            priv.desc = [], // description elements from the directory page
            priv.data = []; // data elements from the directory page

        /* Selectors used for searching HTML */
        priv.selectors = {
            MATCHES: "b", // the number of MATCHES for each student
            DESC: "th", // the descriptions of the student such as name, email, etc
            DATA: "td" // the data for the descriptions
        };

        /* Generates new query object for the form */
        priv.newQuery = function(firstName, lastName, userID, email) {
            return {
                'cn': firstName,
                'sn': lastName,
                'uid': userID, // name=uid attribute in search page
                'mail': email // name=mail attribute in search page
            };
        };

        /* Validation object that contains the different validation methods */
        priv.validate = {
            /* Validates the passed in parameter options */
            options: function(str) {
                return /^[a-zA-Z]+$/.test(str);
            },

            /* Checks if passed in parameter is an email */
            email: function(str) {
                return str.endsWith("@psu.edu");
            },

            /* Checks if passed in parameter contains a number, which means it is an id */
            /* This validation happens AFTER checking if the string is an email */
            userID: function(str) {
                var isNumber, userID = str.match(/\d+/g);
                if (userID != null) {
                    isNumber = true;
                }
                else {
                    isNumber = false;
                }
                return isNumber;
            },

            /* Determines if the option parameter is an object */
            isobjectValid: function() {
                /* Checks every value in the options object and Incase the string contains non-alphabet characters */
                for (var optKey in options) {
                    /* Validates first and last name */
                    if (optKey === "firstName" || optKey === "lastName") {
                        if ((typeof options[optKey] != "string")) {
                            throw new Error("Invalid Object format!");
                        }
                    }

                    /* Validates the user id */
                    else if (optKey === "userID") {
                        if (priv.validate.userID(options["userID"])) return true;
                        else return false;
                    }

                    /* Validates the email */
                    else if (optKey === "email") {
                        if ((priv.validate.email(options[optKey]) === false)) {
                            throw new Error("Invalid Object format!");
                        }
                    }
                    else {
                        throw new Error("Invalid Object format!");
                    }
                }
                return true;
            }
        };

        /* Fills the student info object  */
        priv.fillStudentObj = function(firstName, lastName, userID, email) {
            priv.Student.firstName = firstName;
            priv.Student.lastName = lastName;
            priv.Student.userID = userID;
            priv.Student.email = email;
        };

        /* Initializes the Student object depending on the passed in string */
        priv.initStrStudent = function() {
            /* Checks if passed in parameter is an email */
            if (priv.validate.email(options)) {
                priv.fillStudentObj("", "", "", options);
            }

            /* Checks if passed in parameter is an id */
            else if (priv.validate.userID(options)) {
                priv.fillStudentObj("", "", options, "");
            }

            /* Passed in parameter is not an object, email, or id, so it must be a name */
            else {
                var input = options.split(" ");
                if (input.length === 2) {
                    priv.fillStudentObj(input[0], input[1]);
                }
                else {
                    priv.fillStudentObj(input[0], "", "", "");
                }
            }
        };

        /* Initializes the student information passed in as options */
        priv.initStudent = function() {
            /* Checks if the passed in is valid object */
            if (typeof options === "object") {
                if (priv.validate.isobjectValid()) {
                    Object.assign(priv.Student, options);
                }
            }

            /* Checks if the passed in parameter is a string */
            else if (typeof options === "string") {
                priv.initStrStudent();
            }
        }();

        /* Form object that will contain the form data that will be sent in the post request */
        priv.form.data = priv.newQuery(priv.Student.firstName, priv.Student.lastName, priv.Student.userID, priv.Student.email);
        priv.form.stringFormData = querystring.stringify(priv.form.data); /* Contains the stringified data */
        priv.form.contentLength = priv.form.stringFormData.length; /* Contains the size of the data that is sent in post request */
        priv.form.dirLink = 'http://www.work.psu.edu/cgi-bin/ldap/ldap_query.cgi'; /* Penn State Directory link for scraping */

        /* Request options that contain the appropriate request headers, url, body, and method for sending the post request */
        priv.form.reqOptions = {
            headers: {
                'Content-Length': priv.form.contentLength,
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            url: priv.form.dirLink,
            body: priv.form.stringFormData,
            method: 'POST'
        };

        /* Removes all line breaks and colons in the data retrieved */
        priv.removeLinBr = function(arr) {
            for (var str in arr) {
                arr[str] = arr[str].trim();
                arr[str] = arr[str].replace(/:/g, '');

                /* Seperates the emails with commas */
                if (priv.validate.email(arr[str])) {
                    arr[str] = arr[str].replace(/\n+/g, ', ');
                }
            }
        };

        /* Finds if there is a match */
        priv.isStudentFound = function($) {
            if ($(priv.selectors.MATCHES).text().indexOf("0 matches", 0) == 0 || options === "") {
                return false;
            }
            else {
                return true;
            }
        };

        /* Formats the data that is received from the html page by removing first entry and line breaks */
        priv.formatData = function() {
            priv.desc.shift();
            priv.removeLinBr(priv.desc);
            priv.removeLinBr(priv.data);
        };

        /* Queries the html page for the students information */
        priv.extractData = function($) {
            priv.data = [], priv.desc = []; // reset
            $(priv.selectors.DESC).each(function() {
                priv.desc.push($(this).text());
            });

            $(priv.selectors.DATA).each(function() {
                priv.data.push($(this).text());
            });

        };

        /* Initializes the Student object with the correct properties and values */
        priv.initStudentData = function() {
            priv.Student = {};
            for (var studKey in priv.data) {
                var studProp = priv.desc[studKey];
                priv.Student[studProp] = priv.data[studKey];
            }
        };

        /* Queries the student page for the table headers and table data */
        priv.getStudentInfo = function($) {
            priv.extractData($);
            priv.formatData();
            priv.initStudentData();
        };

        /* Finds the students info on the given html page */
        priv.findStudent = function(htmlPage) {
            /* Library used to parse html  */
            var $ = cheerio.load(htmlPage);

            /* Checks if the student is found */
            if (priv.isStudentFound($)) {
                priv.getStudentInfo($);
            }
            else {
                if (options != "") console.error("Student was not found!");
                else console.error("Please enter a student!");
            }
        };

        /* Scrapes the students html page that is received from the server */
        priv.scrape = function(htmlPage) {
            priv.findStudent(htmlPage);
        };

        /* Callback that executes after the student information is returned */
        var callback = function(err, res, html) {
            if (err) throw new Error('Error in retrieving student informaton');
            priv.scrape(res.body);
            callbackOne(priv.Student);
        };

        /* Sends the request */
        request(priv.form.reqOptions, callback);
    };

    /* Allows you to pass in array of students for searching */
    pub.get = function(input, callbackOne) {
        /* Validates if the number of parameter passed in is 2 and the second parameter is a callback */
        if (arguments.length != 2 || typeof callbackOne != "function") {
            console.error("Please provide the correct number of parameters and a callback function!");
            return;
        }

        /* If an array is passed in then loops through and gets each student */
        if (Array.isArray(input)) {
            for (var student in input) {
                getStudent(input[student], callbackOne);
            }
        }
        else {
            getStudent(input, callbackOne);
        }
    };
    /* EXPORTS the psd-api in node */
    module.exports = pub;

}).call(this);
<commit_msg>update spacing and comments<commit_after>/****************************************
 *     PENN STATE DIRECTORY API         *
 ****************************************/
(function() {

    /* Imports */
    var request = require('request');
    var querystring = require('querystring');
    var cheerio = require('cheerio');

    /* Public object that will contain the public functions that are going to be exported */
    var pub = {};
    /* Private object that  will contain the private functions that will not be exported */
    var priv = {};

    /**
     * psd-api namespace
     *
     */
    var getStudent = function(options, callbackOne) {
        priv.Student = {}, // student
            priv.form = {}, // form
            priv.desc = [], // description elements from the directory page
            priv.data = []; // data elements from the directory page

        /* Selectors used for searching HTML */
        priv.selectors = {
            MATCHES: "b", // the number of MATCHES for each student
            DESC: "th", // the descriptions of the student such as name, email, etc
            DATA: "td" // the data for the descriptions
        };

        /* Generates new query object for the form */
        priv.newQuery = function(firstName, lastName, userID, email) {
            return {
                'cn': firstName,
                'sn': lastName,
                'uid': userID, // name=uid attribute in search page
                'mail': email // name=mail attribute in search page
            };
        };

        /* Validation object that contains the different validation methods */
        priv.validate = {
            /* Validates the passed in parameter options */
            options: function(str) {
                return /^[a-zA-Z]+$/.test(str);
            },

            /* Checks if passed in parameter is an email */
            email: function(str) {
                return str.endsWith("@psu.edu");
            },

            /* Checks if passed in parameter contains a number, which means it is an id */
            /* This validation happens AFTER checking if the string is an email */
            userID: function(str) {
                var isNumber, userID = str.match(/\d+/g);
                if (userID != null) {
                    isNumber = true;
                }
                else {
                    isNumber = false;
                }
                return isNumber;
            },

            /* Determines if the option parameter is an object */
            isobjectValid: function() {
                /* Checks every value in the options object and Incase the string contains non-alphabet characters */
                for (var optKey in options) {
                    /* Validates first and last name */
                    if (optKey === "firstName" || optKey === "lastName") {
                        if ((typeof options[optKey] != "string")) {
                            throw new Error("Invalid Object format!");
                        }
                    }

                    /* Validates the user id */
                    else if (optKey === "userID") {
                        if (priv.validate.userID(options["userID"])) return true;
                        else return false;
                    }

                    /* Validates the email */
                    else if (optKey === "email") {
                        if ((priv.validate.email(options[optKey]) === false)) {
                            throw new Error("Invalid Object format!");
                        }
                    }
                    else {
                        throw new Error("Invalid Object format!");
                    }
                }
                return true;
            }
        };

        /* Fills the student info object  */
        priv.fillStudentObj = function(firstName, lastName, userID, email) {
            priv.Student.firstName = firstName;
            priv.Student.lastName = lastName;
            priv.Student.userID = userID;
            priv.Student.email = email;
        };

        /* Initializes the Student object depending on the passed in string */
        priv.initStrStudent = function() {
            /* Checks if passed in parameter is an email */
            if (priv.validate.email(options)) {
                priv.fillStudentObj("", "", "", options);
            }

            /* Checks if passed in parameter is an id */
            else if (priv.validate.userID(options)) {
                priv.fillStudentObj("", "", options, "");
            }

            /* Passed in parameter is not an object, email, or id, so it must be a name */
            else {
                var input = options.split(" ");
                if (input.length === 2) {
                    priv.fillStudentObj(input[0], input[1]);
                }
                else {
                    priv.fillStudentObj(input[0], "", "", "");
                }
            }
        };

        /* Initializes the student information passed in as options */
        priv.initStudent = function() {
            /* Checks if the passed in is valid object */
            if (typeof options === "object") {
                if (priv.validate.isobjectValid()) {
                    Object.assign(priv.Student, options);
                }
            }

            /* Checks if the passed in parameter is a string */
            else if (typeof options === "string") {
                priv.initStrStudent();
            }
        }();

        /* Form object that will contain the form data that will be sent in the post request */
        priv.form.data = priv.newQuery(priv.Student.firstName, priv.Student.lastName, priv.Student.userID, priv.Student.email);
        priv.form.stringFormData = querystring.stringify(priv.form.data); /* Contains the stringified data */
        priv.form.contentLength = priv.form.stringFormData.length; /* Contains the size of the data that is sent in post request */
        priv.form.dirLink = 'http://www.work.psu.edu/cgi-bin/ldap/ldap_query.cgi'; /* Penn State Directory link for scraping */

        /* Request options that contain the appropriate request headers, url, body, and method for sending the post request */
        priv.form.reqOptions = {
            headers: {
                'Content-Length': priv.form.contentLength,
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            url: priv.form.dirLink,
            body: priv.form.stringFormData,
            method: 'POST'
        };

        /* Removes all line breaks and colons in the data retrieved */
        priv.removeLinBr = function(arr) {
            for (var str in arr) {
                arr[str] = arr[str].trim();
                arr[str] = arr[str].replace(/:/g, '');

                /* Seperates the emails with commas */
                if (priv.validate.email(arr[str])) {
                    arr[str] = arr[str].replace(/\n+/g, ', ');
                }
            }
        };

        /* Finds if there is a match */
        priv.isStudentFound = function($) {
            if ($(priv.selectors.MATCHES).text().indexOf("0 matches", 0) == 0 || options === "") {
                return false;
            } else {
                return true;
            }
        };

        /* Formats the data that is received from the HTML page by removing first entry and line breaks */
        priv.formatData = function() {
            priv.desc.shift();
            priv.removeLinBr(priv.desc);
            priv.removeLinBr(priv.data);
        };

        /* Queries the HTML page for the students information */
        priv.extractData = function($) {
            priv.data = [], priv.desc = []; // reset

            $(priv.selectors.DESC).each(function() {
                priv.desc.push($(this).text());
            });

            $(priv.selectors.DATA).each(function() {
                priv.data.push($(this).text());
            });
        };

        /* Initializes the Student object with the correct properties and values */
        priv.initStudentData = function() {
            priv.Student = {};

            for (var studKey in priv.data) {
                var studProp = priv.desc[studKey];
                priv.Student[studProp] = priv.data[studKey];
            }
        };

        /* Queries the student page for the table headers and table data */
        priv.getStudentInfo = function($) {
            priv.extractData($);
            priv.formatData();
            priv.initStudentData();
        };

        /* Finds the students info on the given HTML page */
        priv.findStudent = function(htmlPage) {
            /* Library used to parse HTML  */
            var $ = cheerio.load(htmlPage);

            /* Checks if the student is found */
            if (priv.isStudentFound($)) {
                priv.getStudentInfo($);
            }
            else {
                if (options != "") console.error("Student was not found!");
                else console.error("Please enter a student!");
            }
        };

        /* Scrapes the students HTML page that is received from the server */
        priv.scrape = function(htmlPage) {
            priv.findStudent(htmlPage);
        };

        /* Callback that executes after the student information is returned */
        var callback = function(err, res, html) {
            if (err) throw new Error('Error in retrieving student informaton');
            priv.scrape(res.body);
            callbackOne(priv.Student);
        };

        /* Sends the request */
        request(priv.form.reqOptions, callback);
    };

    /* Allows you to pass in array of students for searching */
    pub.get = function(input, callbackOne) {
        /* Validates if the number of parameter passed in is 2 and the second parameter is a callback */
        if (arguments.length != 2 || typeof callbackOne != "function") {
            console.error("Please provide the correct number of parameters and a callback function!");
            return;
        }

        /* If an array is passed in then loops through and gets each student */
        if (Array.isArray(input)) {
            for (var student in input) {
                getStudent(input[student], callbackOne);
            }
        }
        else {
            getStudent(input, callbackOne);
        }
    };
    /* EXPORTS the psd-api in node */
    module.exports = pub;

}).call(this);
<|endoftext|>


<commit_before>var _ = require('underscore');
var assert = require('assert');
var crypto = require('crypto');
var dot = require('dot');
var step = require('step');
var MapConfig = require('windshaft').model.MapConfig;
var templateName = require('../../../backends/template_maps').templateName;
var QueryTables = require('cartodb-query-tables');
var SqlWrapMapConfigAdapter = require('./../adapter/sql-wrap-mapconfig-adapter');

/**
 * @constructor
 * @type {NamedMapMapConfigProvider}
 */
function NamedMapMapConfigProvider(templateMaps, pgConnection, metadataBackend, userLimitsApi,
                                   namedLayersAdapter, overviewsAdapter, turboCartoAdapter, analysisMapConfigAdapter,
                                   owner, templateId, config, authToken, params) {
    this.templateMaps = templateMaps;
    this.pgConnection = pgConnection;
    this.metadataBackend = metadataBackend;
    this.userLimitsApi = userLimitsApi;
    this.namedLayersAdapter = namedLayersAdapter;
    this.turboCartoAdapter = turboCartoAdapter;
    this.analysisMapConfigAdapter = analysisMapConfigAdapter;
    this.overviewsAdapter = overviewsAdapter;
    this.sqlWrapMapConfigAdapter = new SqlWrapMapConfigAdapter();

    this.owner = owner;
    this.templateName = templateName(templateId);
    this.config = config;
    this.authToken = authToken;
    this.params = params;

    this.cacheBuster = Date.now();

    // use template after call to mapConfig
    this.template = null;

    this.affectedTablesAndLastUpdate = null;

    // providing
    this.err = null;
    this.mapConfig = null;
    this.rendererParams = null;
    this.context = {};
    this.analysesResults = [];
}

module.exports = NamedMapMapConfigProvider;

NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
    if (!!this.err || this.mapConfig !== null) {
        return callback(this.err, this.mapConfig, this.rendererParams, this.context);
    }

    var self = this;

    var mapConfig = null;
    var rendererParams;
    var apiKey;

    var user = this.owner;
    var context = {};

    step(
        function getTemplate() {
            self.getTemplate(this);
        },
        function prepareDbParams(err, tpl) {
            assert.ifError(err);
            self.template = tpl;

            rendererParams = _.extend({}, self.params, {
                user: self.owner
            });
            self.setDBParams(self.owner, rendererParams, this);
        },
        function getUserApiKey(err) {
            assert.ifError(err);
            self.metadataBackend.getUserMapKey(self.owner, this);
        },
        function prepareParams(err, _apiKey) {
            assert.ifError(err);

            apiKey = _apiKey;

            var templateParams = {};
            if (self.config) {
                try {
                    templateParams = _.isString(self.config) ? JSON.parse(self.config) : self.config;
                } catch (e) {
                    throw new Error('malformed config parameter, should be a valid JSON');
                }
            }

            return templateParams;
        },
        function instantiateTemplate(err, templateParams) {
            assert.ifError(err);
            return self.templateMaps.instance(self.template, templateParams);
        },
        function prepareAdapterMapConfig(err, requestMapConfig) {
            assert.ifError(err);
            context.analysisConfiguration = {
                db: {
                    host: rendererParams.dbhost,
                    port: rendererParams.dbport,
                    dbname: rendererParams.dbname,
                    user: rendererParams.dbuser,
                    pass: rendererParams.dbpassword
                },
                batch: {
                    username: self.owner,
                    apiKey: apiKey
                }
            };
            return requestMapConfig;
        },
        function prepareSqlWrap(err, requestMapConfig) {
            assert.ifError(err);
            self.sqlWrapMapConfigAdapter.getMapConfig(user, requestMapConfig, rendererParams, context, this);
        },
        function prepareAnalysisLayers(err, requestMapConfig) {
            assert.ifError(err);
            self.analysisMapConfigAdapter.getMapConfig(user, requestMapConfig, rendererParams, context, this);
        },
        function prepareLayergroup(err, _mapConfig) {
            assert.ifError(err);
            self.analysesResults = context.analysesResults || [];
            self.namedLayersAdapter.getMapConfig(self.owner, _mapConfig, rendererParams, context, this);
        },
        function addOverviewsInformation(err, _mapConfig) {
            assert.ifError(err);
            self.overviewsAdapter.getMapConfig(self.owner, _mapConfig, rendererParams, context, this);
        },
        function parseTurboCarto(err, _mapConfig) {
            assert.ifError(err);
            self.turboCartoAdapter.getMapConfig(self.owner, _mapConfig, rendererParams, context, this);
        },
        function prepareContextLimits(err, _mapConfig) {
            assert.ifError(err);
            mapConfig = _mapConfig;
            self.userLimitsApi.getRenderLimits(self.owner, this);
        },
        function cacheAndReturnMapConfig(err, renderLimits) {
            self.err = err;
            self.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource);
            self.rendererParams = rendererParams;
            self.context.limits = renderLimits || {};
            return callback(self.err, self.mapConfig, self.rendererParams, self.context);
        }
    );
};

NamedMapMapConfigProvider.prototype.getTemplate = function(callback) {
    var self = this;

    if (!!this.err || this.template !== null) {
        return callback(this.err, this.template);
    }

    step(
        function getTemplate() {
            self.templateMaps.getTemplate(self.owner, self.templateName, this);
        },
        function checkExists(err, tpl) {
            assert.ifError(err);
            if (!tpl) {
                var notFoundErr = new Error(
                        "Template '" + self.templateName + "' of user '" + self.owner + "' not found"
                );
                notFoundErr.http_status = 404;
                throw notFoundErr;
            }
            return tpl;
        },
        function checkAuthorized(err, tpl) {
            assert.ifError(err);

            var authorized = false;
            try {
                authorized = self.templateMaps.isAuthorized(tpl, self.authToken);
            } catch (err) {
                // we catch to add http_status
                var authorizationFailedErr = new Error('Failed to authorize template');
                authorizationFailedErr.http_status = 403;
                throw authorizationFailedErr;
            }
            if ( ! authorized ) {
                var unauthorizedErr = new Error('Unauthorized template instantiation');
                unauthorizedErr.http_status = 403;
                throw unauthorizedErr;
            }

            return tpl;
        },
        function cacheAndReturnTemplate(err, template) {
            self.err = err;
            self.template = template;
            return callback(self.err, self.template);
        }
    );
};

NamedMapMapConfigProvider.prototype.getKey = function() {
    return this.createKey(false);
};

NamedMapMapConfigProvider.prototype.getCacheBuster = function() {
    return this.cacheBuster;
};

NamedMapMapConfigProvider.prototype.reset = function() {
    this.template = null;

    this.affectedTablesAndLastUpdate = null;

    this.err = null;
    this.mapConfig = null;

    this.cacheBuster = Date.now();
};

NamedMapMapConfigProvider.prototype.filter = function(key) {
    var regex = new RegExp('^' + this.createKey(true) + '.*');
    return key && key.match(regex);
};

// Configure bases for cache keys suitable for string interpolation
var baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}';
var rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}';

var baseKeyTpl = dot.template(baseKey);
var rendererKeyTpl = dot.template(rendererKey);

NamedMapMapConfigProvider.prototype.createKey = function(base) {
    var tplValues = _.defaults({}, this.params, {
        dbname: '',
        owner: this.owner,
        templateName: this.templateName,
        authToken: this.authToken || '',
        configHash: configHash(this.config),
        layer: '',
        scale_factor: 1
    });
    return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues);
};

function configHash(config) {
    if (!config) {
        return '';
    }
    return crypto.createHash('md5').update(JSON.stringify(config)).digest('hex').substring(0,8);
}

module.exports.configHash = configHash;

NamedMapMapConfigProvider.prototype.setDBParams = function(cdbuser, params, callback) {
    var self = this;
    step(
        function setAuth() {
            self.pgConnection.setDBAuth(cdbuser, params, this);
        },
        function setConn(err) {
            assert.ifError(err);
            self.pgConnection.setDBConn(cdbuser, params, this);
        },
        function finish(err) {
            callback(err);
        }
    );
};

NamedMapMapConfigProvider.prototype.getTemplateName = function() {
    return this.templateName;
};

NamedMapMapConfigProvider.prototype.getAffectedTablesAndLastUpdatedTime = function(callback) {
    var self = this;

    if (this.affectedTablesAndLastUpdate !== null) {
        return callback(null, this.affectedTablesAndLastUpdate);
    }

    step(
        function getMapConfig() {
            self.getMapConfig(this);
        },
        function getSql(err, mapConfig) {
            assert.ifError(err);
            return mapConfig.getLayers().map(function(layer) {
                return layer.options.sql;
            }).join(';');
        },
        function getAffectedTables(err, sql) {
            assert.ifError(err);
            step(
                function getConnection() {
                    self.pgConnection.getConnection(self.owner, this);
                },
                function getAffectedTables(err, connection) {
                    assert.ifError(err);
                    QueryTables.getAffectedTablesFromQuery(connection, sql, this);
                },
                this
            );
        },
        function finish(err, result) {
            self.affectedTablesAndLastUpdate = result;
            return callback(err, result);
        }
    );
};
<commit_msg>Use generic adapter in named maps<commit_after>var _ = require('underscore');
var assert = require('assert');
var crypto = require('crypto');
var dot = require('dot');
var step = require('step');
var MapConfig = require('windshaft').model.MapConfig;
var templateName = require('../../../backends/template_maps').templateName;
var QueryTables = require('cartodb-query-tables');
var SqlWrapMapConfigAdapter = require('./../adapter/sql-wrap-mapconfig-adapter');
var MapConfigAdapter = require('./../adapter');

/**
 * @constructor
 * @type {NamedMapMapConfigProvider}
 */
function NamedMapMapConfigProvider(templateMaps, pgConnection, metadataBackend, userLimitsApi,
                                   namedLayersAdapter, overviewsAdapter, turboCartoAdapter, analysisMapConfigAdapter,
                                   owner, templateId, config, authToken, params) {
    this.templateMaps = templateMaps;
    this.pgConnection = pgConnection;
    this.metadataBackend = metadataBackend;
    this.userLimitsApi = userLimitsApi;
    this.namedLayersAdapter = namedLayersAdapter;
    this.turboCartoAdapter = turboCartoAdapter;
    this.analysisMapConfigAdapter = analysisMapConfigAdapter;
    this.overviewsAdapter = overviewsAdapter;
    this.sqlWrapMapConfigAdapter = new SqlWrapMapConfigAdapter();

    this.mapConfigAdapter = new MapConfigAdapter([
        this.sqlWrapMapConfigAdapter,
        this.analysisMapConfigAdapter,
        this.namedLayersAdapter,
        this.overviewsAdapter,
        this.turboCartoAdapter
    ]);

    this.owner = owner;
    this.templateName = templateName(templateId);
    this.config = config;
    this.authToken = authToken;
    this.params = params;

    this.cacheBuster = Date.now();

    // use template after call to mapConfig
    this.template = null;

    this.affectedTablesAndLastUpdate = null;

    // providing
    this.err = null;
    this.mapConfig = null;
    this.rendererParams = null;
    this.context = {};
    this.analysesResults = [];
}

module.exports = NamedMapMapConfigProvider;

NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
    if (!!this.err || this.mapConfig !== null) {
        return callback(this.err, this.mapConfig, this.rendererParams, this.context);
    }

    var self = this;

    var mapConfig = null;
    var rendererParams;
    var apiKey;

    var user = this.owner;
    var context = {};

    step(
        function getTemplate() {
            self.getTemplate(this);
        },
        function prepareDbParams(err, tpl) {
            assert.ifError(err);
            self.template = tpl;

            rendererParams = _.extend({}, self.params, {
                user: self.owner
            });
            self.setDBParams(self.owner, rendererParams, this);
        },
        function getUserApiKey(err) {
            assert.ifError(err);
            self.metadataBackend.getUserMapKey(self.owner, this);
        },
        function prepareParams(err, _apiKey) {
            assert.ifError(err);

            apiKey = _apiKey;

            var templateParams = {};
            if (self.config) {
                try {
                    templateParams = _.isString(self.config) ? JSON.parse(self.config) : self.config;
                } catch (e) {
                    throw new Error('malformed config parameter, should be a valid JSON');
                }
            }

            return templateParams;
        },
        function instantiateTemplate(err, templateParams) {
            assert.ifError(err);
            return self.templateMaps.instance(self.template, templateParams);
        },
        function prepareAdapterMapConfig(err, requestMapConfig) {
            assert.ifError(err);
            context.analysisConfiguration = {
                db: {
                    host: rendererParams.dbhost,
                    port: rendererParams.dbport,
                    dbname: rendererParams.dbname,
                    user: rendererParams.dbuser,
                    pass: rendererParams.dbpassword
                },
                batch: {
                    username: self.owner,
                    apiKey: apiKey
                }
            };
            self.mapConfigAdapter.getMapConfig(self.owner, requestMapConfig, rendererParams, context, this);
        },
        function prepareContextLimits(err, _mapConfig) {
            assert.ifError(err);
            mapConfig = _mapConfig;
            self.userLimitsApi.getRenderLimits(self.owner, this);
        },
        function cacheAndReturnMapConfig(err, renderLimits) {
            self.err = err;
            self.mapConfig = (mapConfig === null) ? null : new MapConfig(mapConfig, context.datasource);
            self.analysesResults = context.analysesResults || [];
            self.rendererParams = rendererParams;
            self.context.limits = renderLimits || {};
            return callback(self.err, self.mapConfig, self.rendererParams, self.context);
        }
    );
};

NamedMapMapConfigProvider.prototype.getTemplate = function(callback) {
    var self = this;

    if (!!this.err || this.template !== null) {
        return callback(this.err, this.template);
    }

    step(
        function getTemplate() {
            self.templateMaps.getTemplate(self.owner, self.templateName, this);
        },
        function checkExists(err, tpl) {
            assert.ifError(err);
            if (!tpl) {
                var notFoundErr = new Error(
                        "Template '" + self.templateName + "' of user '" + self.owner + "' not found"
                );
                notFoundErr.http_status = 404;
                throw notFoundErr;
            }
            return tpl;
        },
        function checkAuthorized(err, tpl) {
            assert.ifError(err);

            var authorized = false;
            try {
                authorized = self.templateMaps.isAuthorized(tpl, self.authToken);
            } catch (err) {
                // we catch to add http_status
                var authorizationFailedErr = new Error('Failed to authorize template');
                authorizationFailedErr.http_status = 403;
                throw authorizationFailedErr;
            }
            if ( ! authorized ) {
                var unauthorizedErr = new Error('Unauthorized template instantiation');
                unauthorizedErr.http_status = 403;
                throw unauthorizedErr;
            }

            return tpl;
        },
        function cacheAndReturnTemplate(err, template) {
            self.err = err;
            self.template = template;
            return callback(self.err, self.template);
        }
    );
};

NamedMapMapConfigProvider.prototype.getKey = function() {
    return this.createKey(false);
};

NamedMapMapConfigProvider.prototype.getCacheBuster = function() {
    return this.cacheBuster;
};

NamedMapMapConfigProvider.prototype.reset = function() {
    this.template = null;

    this.affectedTablesAndLastUpdate = null;

    this.err = null;
    this.mapConfig = null;

    this.cacheBuster = Date.now();
};

NamedMapMapConfigProvider.prototype.filter = function(key) {
    var regex = new RegExp('^' + this.createKey(true) + '.*');
    return key && key.match(regex);
};

// Configure bases for cache keys suitable for string interpolation
var baseKey = '{{=it.dbname}}:{{=it.owner}}:{{=it.templateName}}';
var rendererKey = baseKey + ':{{=it.authToken}}:{{=it.configHash}}:{{=it.format}}:{{=it.layer}}:{{=it.scale_factor}}';

var baseKeyTpl = dot.template(baseKey);
var rendererKeyTpl = dot.template(rendererKey);

NamedMapMapConfigProvider.prototype.createKey = function(base) {
    var tplValues = _.defaults({}, this.params, {
        dbname: '',
        owner: this.owner,
        templateName: this.templateName,
        authToken: this.authToken || '',
        configHash: configHash(this.config),
        layer: '',
        scale_factor: 1
    });
    return (base) ? baseKeyTpl(tplValues) : rendererKeyTpl(tplValues);
};

function configHash(config) {
    if (!config) {
        return '';
    }
    return crypto.createHash('md5').update(JSON.stringify(config)).digest('hex').substring(0,8);
}

module.exports.configHash = configHash;

NamedMapMapConfigProvider.prototype.setDBParams = function(cdbuser, params, callback) {
    var self = this;
    step(
        function setAuth() {
            self.pgConnection.setDBAuth(cdbuser, params, this);
        },
        function setConn(err) {
            assert.ifError(err);
            self.pgConnection.setDBConn(cdbuser, params, this);
        },
        function finish(err) {
            callback(err);
        }
    );
};

NamedMapMapConfigProvider.prototype.getTemplateName = function() {
    return this.templateName;
};

NamedMapMapConfigProvider.prototype.getAffectedTablesAndLastUpdatedTime = function(callback) {
    var self = this;

    if (this.affectedTablesAndLastUpdate !== null) {
        return callback(null, this.affectedTablesAndLastUpdate);
    }

    step(
        function getMapConfig() {
            self.getMapConfig(this);
        },
        function getSql(err, mapConfig) {
            assert.ifError(err);
            return mapConfig.getLayers().map(function(layer) {
                return layer.options.sql;
            }).join(';');
        },
        function getAffectedTables(err, sql) {
            assert.ifError(err);
            step(
                function getConnection() {
                    self.pgConnection.getConnection(self.owner, this);
                },
                function getAffectedTables(err, connection) {
                    assert.ifError(err);
                    QueryTables.getAffectedTablesFromQuery(connection, sql, this);
                },
                this
            );
        },
        function finish(err, result) {
            self.affectedTablesAndLastUpdate = result;
            return callback(err, result);
        }
    );
};
<|endoftext|>


<commit_before><commit_msg>Updated the 'updates' banner<commit_after><|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "<commit_msg>Fixed memory parsing error #1337<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "F<|endoftext|>