<commit_before>/* global bundle, $ */

/**
 * updateGraph
 *
 * Update the graph with some new data and remove the old one.
 *
 * @newData: New tuples of data to update the graph with
 */
function updateGraph(newData) {
  var svg;
  var rects;

  /* Drop any existing SVG elements */
  Array.prototype.forEach.call(document.getElementsByClassName("chart"),
                               function dropInnerHTMLOf(element) {
                                 /* Drop everything inside this chart */
                                 element.innerHTML = "";  // eslint-disable-line no-param-reassign
                               });

  svg = bundle.select("div.chart")
          .append("svg")
          .attr("class", "svgchart")
          .attr("width", function computeWidth() {
            return this.parentNode.clientWidth * 0.80;
          })
          .attr("height", function computeHeight() {
            return this.parentNode.clientHeight * 0.80;
          })
          .attr("style", function computeTransform() {
            var x = this.parentNode.clientWidth * 0.10;
            var y = this.parentNode.clientHeight * 0.10;
            return ["transform: translate(", x, "px,", y, "px", ")"].join("");
          });

  rects = svg.selectAll("rect")
             .data(newData)
             .enter()
             .append("rect");

  rects.attr("width", function computeBarWidth(d) {
    var x = bundle.scaleLinear()
                 .domain([0, bundle.max(newData)])
                 .range([0, this.parentNode.clientWidth]);
    return x(d);
  })
  .attr("height", function computeBarHeight() {
    var chartHeight = this.parentNode.clientHeight;
    var barSpacing = 10;
    return (chartHeight - (barSpacing * newData.length)) / newData.length;
  })
  .attr("y", function computeBarY(d, i) {
    var chartHeight = this.parentNode.clientHeight;
    var barSpacing = 10;
    var barHeight = ((chartHeight - (barSpacing * newData.length)) /
                     newData.length);

    return (i * barSpacing) + (i * barHeight);
  });
}

function postGraphUpdateRequest(name) {
  $.ajax({
    url: "/get_bar_chart",
    data: {
      name: name
    },
    success: function onXHRSuccess(data) {
      updateGraph(data.data.map(function onEachPoint(w) {
        return w.value;
      }));
    }
  });
}

/**
 * updateSelection
 *
 * Get the new value from the graph selection and update the graph with it.
 */
function updateSelection() {
  postGraphUpdateRequest(document.getElementById("graphs").value);
}

document.addEventListener("DOMContentLoaded", function() {
  $('#chartSelectionDropdown ul li a').click(function(event) {
    var div = $(this).parent().parent().parent();
    var button = div.find('button');

    button.html(this.text + ' ');
    div.removeClass('open');
    event.preventDefault();

    postGraphUpdateRequest($(this).attr("data-selection-id"));
    return false;
  });
});
<commit_msg>retraction: Explicit function names<commit_after>/* global bundle, $ */

/**
 * updateGraph
 *
 * Update the graph with some new data and remove the old one.
 *
 * @newData: New tuples of data to update the graph with
 */
function updateGraph(newData) {
  var svg;
  var rects;

  /* Drop any existing SVG elements */
  Array.prototype.forEach.call(document.getElementsByClassName("chart"),
                               function dropInnerHTMLOf(element) {
                                 /* Drop everything inside this chart */
                                 element.innerHTML = "";  // eslint-disable-line no-param-reassign
                               });

  svg = bundle.select("div.chart")
          .append("svg")
          .attr("class", "svgchart")
          .attr("width", function computeWidth() {
            return this.parentNode.clientWidth * 0.80;
          })
          .attr("height", function computeHeight() {
            return this.parentNode.clientHeight * 0.80;
          })
          .attr("style", function computeTransform() {
            var x = this.parentNode.clientWidth * 0.10;
            var y = this.parentNode.clientHeight * 0.10;
            return ["transform: translate(", x, "px,", y, "px", ")"].join("");
          });

  rects = svg.selectAll("rect")
             .data(newData)
             .enter()
             .append("rect");

  rects.attr("width", function computeBarWidth(d) {
    var x = bundle.scaleLinear()
                 .domain([0, bundle.max(newData)])
                 .range([0, this.parentNode.clientWidth]);
    return x(d);
  })
  .attr("height", function computeBarHeight() {
    var chartHeight = this.parentNode.clientHeight;
    var barSpacing = 10;
    return (chartHeight - (barSpacing * newData.length)) / newData.length;
  })
  .attr("y", function computeBarY(d, i) {
    var chartHeight = this.parentNode.clientHeight;
    var barSpacing = 10;
    var barHeight = ((chartHeight - (barSpacing * newData.length)) /
                     newData.length);

    return (i * barSpacing) + (i * barHeight);
  });
}

function postGraphUpdateRequest(name) {
  $.ajax({
    url: "/get_bar_chart",
    data: {
      name: name
    },
    success: function onXHRSuccess(data) {
      updateGraph(data.data.map(function onEachPoint(w) {
        return w.value;
      }));
    }
  });
}

/**
 * updateSelection
 *
 * Get the new value from the graph selection and update the graph with it.
 */
function updateSelection() {
  postGraphUpdateRequest(document.getElementById("graphs").value);
}

document.addEventListener("DOMContentLoaded", function onDOMLoaded() {
  $('#chartSelectionDropdown ul li a').click(function onDropdownClick(event) {
    var div = $(this).parent().parent().parent();
    var button = div.find('button');

    button.html(this.text + ' ');
    div.removeClass('open');
    event.preventDefault();

    postGraphUpdateRequest($(this).attr("data-selection-id"));
    return false;
  });
});
<|endoftext|>


<commit_before>/* jshint jquery: false */
"use strict";

var resources = {};

var dottemplates = require("./dottemplates.js"),
    mime         = require("./mime.js"),
    pkg          = require("./../../package.json"),
    paths        = require("./paths.js").get();

var async        = require("async"),
    autoprefixer = require("autoprefixer-core"),
    cheerio      = require("cheerio"),
    cleanCSS     = require("clean-css"),
    crypto       = require("crypto"),
    fs           = require("graceful-fs"),
    htmlMinifier = require("html-minifier"),
    path         = require("path"),
    uglify       = require("uglify-js"),
    vm           = require("vm"),
    zlib         = require("zlib");

var doMinify, svgData = {}, $,
    themesPath   = path.join(paths.mod, "/node_modules/codemirror/theme"),
    modesPath    = path.join(paths.mod, "/node_modules/codemirror/mode");

var opts = {
    get uglify() {
        return {
            fromString: true,
            compress: {
                unsafe: true,
                screw_ie8: true
            }
        };
    },
    get cleanCSS() {
        return {
            advanced : true,
            keepSpecialComments : 0
        };
    },
    get htmlMinifier() {
        return {
            removeComments: true,
            collapseWhitespace: true,
            collapseBooleanAttributes: true,
            removeAttributeQuotes: true,
            removeOptionalTags: true,
            removeRedundantAttributes: true,
            caseSensitive: true,
            minifyCSS: cleanCSS
        };
    }
};

cleanCSS = new cleanCSS(opts.cleanCSS);

resources.files = {
        css: [
            "node_modules/codemirror/lib/codemirror.css",
            "client/style.css",
            "client/sprites.css"
        ],
        js: [
            "node_modules/jquery/dist/jquery.js",
            "node_modules/draggabilly/dist/draggabilly.pkgd.min.js",
            "node_modules/pretty-bytes/pretty-bytes.js",
            "node_modules/codemirror/lib/codemirror.js",
            "node_modules/codemirror/mode/meta.js",
            "node_modules/codemirror/addon/dialog/dialog.js",
            "node_modules/codemirror/addon/selection/active-line.js",
            "node_modules/codemirror/addon/selection/mark-selection.js",
            "node_modules/codemirror/addon/search/searchcursor.js",
            "node_modules/codemirror/addon/edit/matchbrackets.js",
            "node_modules/codemirror/addon/search/search.js",
            "node_modules/codemirror/keymap/sublime.js",
            "client/client.js"
        ],
        html: [
            "client/html/base.html",
            "client/html/auth.html",
            "client/html/main.html"
        ],
        templates: [
            "client/templates/views/directory.dotjs",
            "client/templates/views/document.dotjs",
            "client/templates/views/media.dotjs",
            "client/templates/options.dotjs"
        ],
        other: [
            "client/Roboto.woff",
            "client/images/logo.svg",
            "client/images/logo16.png",
            "client/images/logo32.png",
            "client/images/logo128.png",
            "client/images/logo152.png",
            "client/images/logo180.png",
            "client/images/logo192.png",
            "client/images/favicon.ico"
        ]
    };

// On-demand loadable libs, preferably minified. Will be available as ?!/[property value]
var libs = {
    "node_modules/video.js/dist/video-js/video.js"         : "video.js/vjs.js",
    "node_modules/video.js/dist/video-js/video-js.min.css" : "video.js/vjs.css",
    "node_modules/video.js/dist/video-js/video-js.swf"     : "video.js/vjs.swf",
    "node_modules/video.js/dist/video-js/font/vjs.eot"     : "video.js/font/vjs.eot",
    "node_modules/video.js/dist/video-js/font/vjs.svg"     : "video.js/font/vjs.svg",
    "node_modules/video.js/dist/video-js/font/vjs.ttf"     : "video.js/font/vjs.ttf",
    "node_modules/video.js/dist/video-js/font/vjs.woff"    : "video.js/font/vjs.woff"
};

resources.init = function init(minify, callback) {
    doMinify = minify;
    async.series([compileAll, readThemes, readModes, readLibs], function (err, results) {
        if (err) return callback(err);
        var cache = { res: results[0], themes: {}, modes: {}, lib: {} };

        Object.keys(results[1]).forEach(function (theme) {
            cache.themes[theme] = {data: results[1][theme], etag: etag(), mime: mime.lookup("css")};
        });

        Object.keys(results[2]).forEach(function (mode) {
            cache.modes[mode] = {data: results[2][mode], etag: etag(), mime: mime.lookup("js")};
        });

        Object.keys(results[3]).forEach(function (file) {
            cache.lib[file] = {data: results[3][file], etag: etag(), mime: mime.lookup(path.basename(file))};
        });

        addGzip(cache, function (err, cache) {
            cache.etags = {};
            callback(err, cache);
        });
    });
};

// Create gzip compressed data
function addGzip(cache, callback) {
    var types = Object.keys(cache), funcs = [];
    types.forEach(function (type) {
        funcs.push(function (cb) {
            gzipMap(cache[type], cb);
        });
    });
    async.parallel(funcs, function (err, results) {
        if (err) return callback(err);
        types.forEach(function (type, index) {
            cache[type] = results[index];
        });
        callback(null, cache);
    });
}

function gzipMap(map, callback) {
    var names = Object.keys(map), funcs = [];
    names.forEach(function (name) {
        funcs.push(function (cb) {
            gzip(map[name].data, cb);
        });
    });
    async.parallel(funcs, function (err, results) {
        if (err) return callback(err);
        names.forEach(function (name, index) {
            map[name].gzip = results[index];
        });
        callback(null, map);
    });
}

function gzip(data, callback) {
    zlib.gzip(data, function (err, gzipped) {
        if (err) return callback(err);
        callback(null, gzipped);
    });
}

function readThemes(callback) {
    var themes = {};
    fs.readdir(themesPath, function (err, filenames) {
        if (err) return callback(err);

        var files = filenames.map(function (name) {
            return path.join(themesPath, name);
        });

        async.map(files, fs.readFile, function (err, data) {
            if (err) return callback(err);

            filenames.forEach(function (name, index) {
                var css = String(data[index]);
                themes[name.replace(/\.css$/, "")] = new Buffer(doMinify ?  cleanCSS.minify(css).styles : css);
            });

            // add our own theme
            var css = fs.readFileSync(path.join(paths.mod, "/client/cmtheme.css"));
            themes.droppy = new Buffer(doMinify ?  cleanCSS.minify(css).styles : css);

            callback(err, themes);
        });
    });
}

function readModes(callback) {
    var modes = {};

    // parse meta.js from CM for supported modes
    fs.readFile(path.join(paths.mod, "/node_modules/codemirror/mode/meta.js"), function (err, js) {
        if (err) return callback(err);
        var sandbox = { CodeMirror : {} };

        // Execute meta.js in a sandbox
        vm.runInNewContext(js, sandbox);
        sandbox.CodeMirror.modeInfo.forEach(function (entry) {
            if (entry.mode !== "null") modes[entry.mode] = null;
        });

        async.map(Object.keys(modes), function (mode, cb) {
            fs.readFile(path.join(modesPath, mode, mode + ".js"), function (err, data) {
                cb(err, doMinify ? new Buffer(uglify.minify(data.toString(), opts.uglify).code) : data);
            });
        }, function (err, result) {
            Object.keys(modes).forEach(function (mode, i) {
                modes[mode] = result[i];
            });
            callback(err, modes);
        });
    });
}

function readLibs(callback) {
    var ret = {};
    async.each(Object.keys(libs), function (p, cb) {
        fs.readFile(path.join(paths.mod, p), function (err, data) {
            ret[libs[p]] = data;
            cb(err);
        });
    }, function (err) {
        callback(err, ret);
    });
}

function readSVG() {
    fs.readdirSync(paths.svg).forEach(function (name) {
        var className = name.slice(0, name.length - ".svg".length);
        $ = cheerio.load(fs.readFileSync(path.join(paths.svg, name)).toString(), {xmlMode: true});
        $("svg").addClass(className);
        svgData[className] = $.html();
    });
}

function addSVG(html) {
    $ = cheerio.load(html);
    $("svg").each(function () {
        $(this).replaceWith($("svg", svgData[$(this).attr("class")]));
    });
    return $.html();
}

resources.compileJS = function compileJS(minify) {
    var js = "";
    resources.files.js.forEach(function (file) {
        js += fs.readFileSync(path.join(paths.mod, file)).toString("utf8") + ";";
    });

    // Add SVG object
    js = js.replace("/* {{ svg }} */", "droppy.svg = " + JSON.stringify(svgData) + ";");

    // Insert Templates Code
    var templateCode = "droppy.templates = {fn:{},views:{}};";
    resources.files.templates.forEach(function (file, index) {
        var data = fs.readFileSync(path.join(paths.mod, file)).toString("utf8");
        // Produce the doT functions
        templateCode += dottemplates
            .produceFunction("droppy.templates." + resources.files.templates[index].replace(/\.dotjs$/, "")
            .split("/").slice(2).join("."), data) + ";";
    });
    js = js.replace("/* {{ templates }} */", templateCode);

    // Minify
    if (minify) js = uglify.minify(js, opts.uglify).code;

    return {data: new Buffer(js), etag: etag(), mime: mime.lookup("js")};
};

resources.compileCSS = function compileCSS(minify) {
    var css = "";
    resources.files.css.forEach(function (file) {
        css += fs.readFileSync(path.join(paths.mod, file)).toString("utf8") + "\n";
    });

    // Venodor prefixes
    css = autoprefixer.process(css).css;

    // Minify
    if (minify) css = cleanCSS.minify(css).styles;

    return {data: new Buffer(css), etag: etag(), mime: mime.lookup("css")};
};

resources.compileHTML = function compileHTML(res, minify) {
    var html = {};
    resources.files.html.forEach(function (file) {
        var data = fs.readFileSync(path.join(paths.mod, file)).toString("utf8")
            .replace(/\{\{version\}\}/gm, pkg.version)
            .replace(/\{\{name\}\}/gm, pkg.name)
            .replace(/\{\{engine\}\}/gm, require("detect-engine") + " " + process.version.substring(1));

        // Add SVGs
        data = addSVG(data);

        // Minify
        if (minify) data = htmlMinifier.minify(data, opts.htmlMinifier);

        html[path.basename(file)] = data;
    });

    // Combine pages
    $ = cheerio.load(html["base.html"]);
    $("html").attr("data-type", "main");
    res["main.html"] = {
        data: new Buffer($("#page").replaceWith(html["main.html"]).end().html()),
        etag: etag(),
        mime: mime.lookup("html")
    };

    $ = cheerio.load(html["base.html"]);
    $("html").attr("data-type", "auth");
    res["auth.html"] = {
        data: new Buffer($("#page").replaceWith(html["auth.html"]).end().html()),
        etag: etag(),
        mime: mime.lookup("html")
    };

    $ = cheerio.load(html["base.html"]);
    $("html").attr("data-type", "firstrun");
    res["firstrun.html"] = {
        data: new Buffer($("#page").replaceWith(html["auth.html"]).end().html()),
        etag: etag(),
        mime: mime.lookup("html")
    };

    return res;
};

function compileAll(callback) {
    var res = {};

    readSVG();
    res["client.js"] = resources.compileJS(doMinify);
    res["style.css"] = resources.compileCSS(doMinify);
    res = resources.compileHTML(res, doMinify);

    // Read misc files
    resources.files.other.forEach(function (file) {
        var data, date,
            name     = path.basename(file),
            fullPath = path.join(paths.mod, file);

        try {
            data = fs.readFileSync(fullPath);
            date = fs.statSync(fullPath).mtime;
        } catch (err) {
            callback(err);
        }

        res[name] = {
            data: data,
            etag: crypto.createHash("md5").update(String(date)).digest("hex"),
            mime: mime.lookup(name)
        };
    });
    callback(null, res);
}

function etag () {
    return crypto.createHash("md5").update(String(Date.now())).digest("hex");
}

exports = module.exports = resources;
<commit_msg>Simplify readSVG<commit_after>/* jshint jquery: false */
"use strict";

var resources = {};

var dottemplates = require("./dottemplates.js"),
    mime         = require("./mime.js"),
    pkg          = require("./../../package.json"),
    paths        = require("./paths.js").get();

var async        = require("async"),
    autoprefixer = require("autoprefixer-core"),
    cheerio      = require("cheerio"),
    cleanCSS     = require("clean-css"),
    crypto       = require("crypto"),
    fs           = require("graceful-fs"),
    htmlMinifier = require("html-minifier"),
    path         = require("path"),
    uglify       = require("uglify-js"),
    vm           = require("vm"),
    zlib         = require("zlib");

var doMinify, svgData = {}, $,
    themesPath   = path.join(paths.mod, "/node_modules/codemirror/theme"),
    modesPath    = path.join(paths.mod, "/node_modules/codemirror/mode");

var opts = {
    get uglify() {
        return {
            fromString: true,
            compress: {
                unsafe: true,
                screw_ie8: true
            }
        };
    },
    get cleanCSS() {
        return {
            advanced : true,
            keepSpecialComments : 0
        };
    },
    get htmlMinifier() {
        return {
            removeComments: true,
            collapseWhitespace: true,
            collapseBooleanAttributes: true,
            removeAttributeQuotes: true,
            removeOptionalTags: true,
            removeRedundantAttributes: true,
            caseSensitive: true,
            minifyCSS: cleanCSS
        };
    }
};

cleanCSS = new cleanCSS(opts.cleanCSS);

resources.files = {
        css: [
            "node_modules/codemirror/lib/codemirror.css",
            "client/style.css",
            "client/sprites.css"
        ],
        js: [
            "node_modules/jquery/dist/jquery.js",
            "node_modules/draggabilly/dist/draggabilly.pkgd.min.js",
            "node_modules/pretty-bytes/pretty-bytes.js",
            "node_modules/codemirror/lib/codemirror.js",
            "node_modules/codemirror/mode/meta.js",
            "node_modules/codemirror/addon/dialog/dialog.js",
            "node_modules/codemirror/addon/selection/active-line.js",
            "node_modules/codemirror/addon/selection/mark-selection.js",
            "node_modules/codemirror/addon/search/searchcursor.js",
            "node_modules/codemirror/addon/edit/matchbrackets.js",
            "node_modules/codemirror/addon/search/search.js",
            "node_modules/codemirror/keymap/sublime.js",
            "client/client.js"
        ],
        html: [
            "client/html/base.html",
            "client/html/auth.html",
            "client/html/main.html"
        ],
        templates: [
            "client/templates/views/directory.dotjs",
            "client/templates/views/document.dotjs",
            "client/templates/views/media.dotjs",
            "client/templates/options.dotjs"
        ],
        other: [
            "client/Roboto.woff",
            "client/images/logo.svg",
            "client/images/logo16.png",
            "client/images/logo32.png",
            "client/images/logo128.png",
            "client/images/logo152.png",
            "client/images/logo180.png",
            "client/images/logo192.png",
            "client/images/favicon.ico"
        ]
    };

// On-demand loadable libs, preferably minified. Will be available as ?!/[property value]
var libs = {
    "node_modules/video.js/dist/video-js/video.js"         : "video.js/vjs.js",
    "node_modules/video.js/dist/video-js/video-js.min.css" : "video.js/vjs.css",
    "node_modules/video.js/dist/video-js/video-js.swf"     : "video.js/vjs.swf",
    "node_modules/video.js/dist/video-js/font/vjs.eot"     : "video.js/font/vjs.eot",
    "node_modules/video.js/dist/video-js/font/vjs.svg"     : "video.js/font/vjs.svg",
    "node_modules/video.js/dist/video-js/font/vjs.ttf"     : "video.js/font/vjs.ttf",
    "node_modules/video.js/dist/video-js/font/vjs.woff"    : "video.js/font/vjs.woff"
};

resources.init = function init(minify, callback) {
    doMinify = minify;
    async.series([compileAll, readThemes, readModes, readLibs], function (err, results) {
        if (err) return callback(err);
        var cache = { res: results[0], themes: {}, modes: {}, lib: {} };

        Object.keys(results[1]).forEach(function (theme) {
            cache.themes[theme] = {data: results[1][theme], etag: etag(), mime: mime.lookup("css")};
        });

        Object.keys(results[2]).forEach(function (mode) {
            cache.modes[mode] = {data: results[2][mode], etag: etag(), mime: mime.lookup("js")};
        });

        Object.keys(results[3]).forEach(function (file) {
            cache.lib[file] = {data: results[3][file], etag: etag(), mime: mime.lookup(path.basename(file))};
        });

        addGzip(cache, function (err, cache) {
            cache.etags = {};
            callback(err, cache);
        });
    });
};

// Create gzip compressed data
function addGzip(cache, callback) {
    var types = Object.keys(cache), funcs = [];
    types.forEach(function (type) {
        funcs.push(function (cb) {
            gzipMap(cache[type], cb);
        });
    });
    async.parallel(funcs, function (err, results) {
        if (err) return callback(err);
        types.forEach(function (type, index) {
            cache[type] = results[index];
        });
        callback(null, cache);
    });
}

function gzipMap(map, callback) {
    var names = Object.keys(map), funcs = [];
    names.forEach(function (name) {
        funcs.push(function (cb) {
            gzip(map[name].data, cb);
        });
    });
    async.parallel(funcs, function (err, results) {
        if (err) return callback(err);
        names.forEach(function (name, index) {
            map[name].gzip = results[index];
        });
        callback(null, map);
    });
}

function gzip(data, callback) {
    zlib.gzip(data, function (err, gzipped) {
        if (err) return callback(err);
        callback(null, gzipped);
    });
}

function readThemes(callback) {
    var themes = {};
    fs.readdir(themesPath, function (err, filenames) {
        if (err) return callback(err);

        var files = filenames.map(function (name) {
            return path.join(themesPath, name);
        });

        async.map(files, fs.readFile, function (err, data) {
            if (err) return callback(err);

            filenames.forEach(function (name, index) {
                var css = String(data[index]);
                themes[name.replace(/\.css$/, "")] = new Buffer(doMinify ?  cleanCSS.minify(css).styles : css);
            });

            // add our own theme
            var css = fs.readFileSync(path.join(paths.mod, "/client/cmtheme.css"));
            themes.droppy = new Buffer(doMinify ?  cleanCSS.minify(css).styles : css);

            callback(err, themes);
        });
    });
}

function readModes(callback) {
    var modes = {};

    // parse meta.js from CM for supported modes
    fs.readFile(path.join(paths.mod, "/node_modules/codemirror/mode/meta.js"), function (err, js) {
        if (err) return callback(err);
        var sandbox = { CodeMirror : {} };

        // Execute meta.js in a sandbox
        vm.runInNewContext(js, sandbox);
        sandbox.CodeMirror.modeInfo.forEach(function (entry) {
            if (entry.mode !== "null") modes[entry.mode] = null;
        });

        async.map(Object.keys(modes), function (mode, cb) {
            fs.readFile(path.join(modesPath, mode, mode + ".js"), function (err, data) {
                cb(err, doMinify ? new Buffer(uglify.minify(data.toString(), opts.uglify).code) : data);
            });
        }, function (err, result) {
            Object.keys(modes).forEach(function (mode, i) {
                modes[mode] = result[i];
            });
            callback(err, modes);
        });
    });
}

function readLibs(callback) {
    var ret = {};
    async.each(Object.keys(libs), function (p, cb) {
        fs.readFile(path.join(paths.mod, p), function (err, data) {
            ret[libs[p]] = data;
            cb(err);
        });
    }, function (err) {
        callback(err, ret);
    });
}

function readSVG() {
    fs.readdirSync(paths.svg).forEach(function (name) {
        var className = name.slice(0, name.length - ".svg".length);
        $ = cheerio.load(fs.readFileSync(path.join(paths.svg, name)).toString(), {xmlMode: true});
        $("svg").addClass(className);
        svgData[className] = $.html();
    });
}

function addSVG(html) {
    $ = cheerio.load(html);
    $("svg").each(function () {
        $(this).replaceWith(svgData[$(this).attr("class")]);
    });
    return $.html();
}

resources.compileJS = function compileJS(minify) {
    var js = "";
    resources.files.js.forEach(function (file) {
        js += fs.readFileSync(path.join(paths.mod, file)).toString("utf8") + ";";
    });

    // Add SVG object
    js = js.replace("/* {{ svg }} */", "droppy.svg = " + JSON.stringify(svgData) + ";");

    // Insert Templates Code
    var templateCode = "droppy.templates = {fn:{},views:{}};";
    resources.files.templates.forEach(function (file, index) {
        var data = fs.readFileSync(path.join(paths.mod, file)).toString("utf8");
        // Produce the doT functions
        templateCode += dottemplates
            .produceFunction("droppy.templates." + resources.files.templates[index].replace(/\.dotjs$/, "")
            .split("/").slice(2).join("."), data) + ";";
    });
    js = js.replace("/* {{ templates }} */", templateCode);

    // Minify
    if (minify) js = uglify.minify(js, opts.uglify).code;

    return {data: new Buffer(js), etag: etag(), mime: mime.lookup("js")};
};

resources.compileCSS = function compileCSS(minify) {
    var css = "";
    resources.files.css.forEach(function (file) {
        css += fs.readFileSync(path.join(paths.mod, file)).toString("utf8") + "\n";
    });

    // Venodor prefixes
    css = autoprefixer.process(css).css;

    // Minify
    if (minify) css = cleanCSS.minify(css).styles;

    return {data: new Buffer(css), etag: etag(), mime: mime.lookup("css")};
};

resources.compileHTML = function compileHTML(res, minify) {
    var html = {};
    resources.files.html.forEach(function (file) {
        var data = fs.readFileSync(path.join(paths.mod, file)).toString("utf8")
            .replace(/\{\{version\}\}/gm, pkg.version)
            .replace(/\{\{name\}\}/gm, pkg.name)
            .replace(/\{\{engine\}\}/gm, require("detect-engine") + " " + process.version.substring(1));

        // Add SVGs
        data = addSVG(data);

        // Minify
        if (minify) data = htmlMinifier.minify(data, opts.htmlMinifier);

        html[path.basename(file)] = data;
    });

    // Combine pages
    $ = cheerio.load(html["base.html"]);
    $("html").attr("data-type", "main");
    res["main.html"] = {
        data: new Buffer($("#page").replaceWith(html["main.html"]).end().html()),
        etag: etag(),
        mime: mime.lookup("html")
    };

    $ = cheerio.load(html["base.html"]);
    $("html").attr("data-type", "auth");
    res["auth.html"] = {
        data: new Buffer($("#page").replaceWith(html["auth.html"]).end().html()),
        etag: etag(),
        mime: mime.lookup("html")
    };

    $ = cheerio.load(html["base.html"]);
    $("html").attr("data-type", "firstrun");
    res["firstrun.html"] = {
        data: new Buffer($("#page").replaceWith(html["auth.html"]).end().html()),
        etag: etag(),
        mime: mime.lookup("html")
    };

    return res;
};

function compileAll(callback) {
    var res = {};

    readSVG();
    res["client.js"] = resources.compileJS(doMinify);
    res["style.css"] = resources.compileCSS(doMinify);
    res = resources.compileHTML(res, doMinify);

    // Read misc files
    resources.files.other.forEach(function (file) {
        var data, date,
            name     = path.basename(file),
            fullPath = path.join(paths.mod, file);

        try {
            data = fs.readFileSync(fullPath);
            date = fs.statSync(fullPath).mtime;
        } catch (err) {
            callback(err);
        }

        res[name] = {
            data: data,
            etag: crypto.createHash("md5").update(String(date)).digest("hex"),
            mime: mime.lookup(name)
        };
    });
    callback(null, res);
}

function etag () {
    return crypto.createHash("md5").update(String(Date.now())).digest("hex");
}

exports = module.exports = resources;
<|endoftext|>


<commit_before>const fs = require("fs-extra");
const path = require("path");

const migrationsDir = require("../env/migrationsDir");
const configFile = require("../env/configFile");

function copySampleConfigFile() {
  const source = path.join(__dirname, "../../samples/migrate-mongo-config.js");
  const destination = path.join(process.cwd(), configFile.DEFAULT_CONFIG_FILE_NAME);
  return fs.copy(source, destination);
}

function createMigrationsDirectory() {
  return fs.mkdirs(path.join(process.cwd(), "migrations"));
}

module.exports = async () => {
  await migrationsDir.shouldNotExist();
  await configFile.shouldNotExist();
  await copySampleConfigFile();
  return createMigrationsDirectory();
};
<commit_msg>Fix prettier<commit_after>const fs = require("fs-extra");
const path = require("path");

const migrationsDir = require("../env/migrationsDir");
const configFile = require("../env/configFile");

function copySampleConfigFile() {
  const source = path.join(__dirname, "../../samples/migrate-mongo-config.js");
  const destination = path.join(
    process.cwd(),
    configFile.DEFAULT_CONFIG_FILE_NAME
  );
  return fs.copy(source, destination);
}

function createMigrationsDirectory() {
  return fs.mkdirs(path.join(process.cwd(), "migrations"));
}

module.exports = async () => {
  await migrationsDir.shouldNotExist();
  await configFile.shouldNotExist();
  await copySampleConfigFile();
  return createMigrationsDirectory();
};
<|endoftext|>


<commit_before>const connectToFirebase = () => {
    const admin = require("firebase-admin");
    let serviceAccount = require("./config/quizchatbot-ce222-firebase-adminsdk.json")
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://quizchatbot-ce222.firebaseio.com"
    })
    return admin
}

const admin = connectToFirebase()

//get total number of questions
const getNumberOfQuestions = async () => {
    let keys = await getAllQuestionKeys()
    let numberOfQuestions = keys.length
    return numberOfQuestions
}

//get all questions from firebase
const getQuestionsFromFirebase = async () => {
    // Get a database reference to our posts
    let db = admin.database()
    let ref = db.ref("/Quests")

    let questionSnapshots
    // Attach an asynchronous callback to read the data at our posts reference
    const result = await new Promise(function (resolve, reject) {
        ref.on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("Cannot get questions from firebase : " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return errorObject.code
    })

    return result
}

//get all answers from that question by id
const getAllAnswersFromQuestion = async (id) => {
    let db = admin.database()
    let ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).child("choices").on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("Cannot get all answers from question id : " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return "Reject Cannot get all answers from question id : " + errorObject.code
    })

    return result
}

//get question by id
const getQuestionFromId = async (id) => {
    let db = admin.database()
    let ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("Cannot get question from id : " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return "Reject Cannot get question from id : " + errorObject.code
    })

    return result
}

//get all questions' keys from firebase
const getAllQuestionKeys = () => new Promise(async (resolve, reject) => {
    const db = admin.database()
    const ref = db.ref("/Quests")

    ref.orderByKey().once("value", (snapshot) => {
        let keys = Object.keys(snapshot.val())
        console.log("keys in getAllQuestionKeys =  " + keys)
        resolve(keys)
    }, (errorObject) => {
        console.log("Cannot get all question keys = " + errorObject.code)
        reject(errorObject)
    })
})

//get key of questions already done by that user
//query only question that done in that round
const getQuestionDone = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                //get keys of questions done if that round
                if (resultSnapshot[property].round == round) {
                    keysDone.push(resultSnapshot[property].question)
                }
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const getGrade = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let grade
    ref.child("summary").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                if (resultSnapshot[property].round == round) {
                    grade = resultSnapshot[property].grade
                    console.log("__Grade in loop = ", grade)
                    console.log("__Grade = ", resultSnapshot[property].grade)
                }
            }
        }
        console.log("__Grade out loop= ", grade)
        resolve(grade)

    }, (errorObject) => {
        console.log("Cannot get grade of user  = " + errorObject.code)
    })

})

//save result of answered question
const saveResultToFirebase = async (senderID, prepareResult) => {
    let result = prepareResult[0]
    let keyQuestion = result.question
    console.log("key = ", keyQuestion)
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    //create new key when push
    ref.child("results").push({
        "answer": result.answer,
        "doneAt": result.doneAt,
        "startedAt": result.startedAt,
        "duration": result.duration,
        "point": result.point,
        "question": result.question,
        "result": result.result,
        "round": result.round,
        "score": result.score
    })
}

const saveUserToFirebase = (senderID, user) => {
    console.log("User in firebase= ", user)
    let db = admin.database()
    let ref = db.ref("/Developer/")
    let hasUser = false
    //check if firebase has that user data
    ref.once("value")
        .then((snapshot) => {
            snapshot.forEach((childSnapshot) => {
                if (childSnapshot.key == senderID) {
                    console.log("Already have user information")
                    hasUser = true
                    return
                }
            })
        })

    //if firebase doesn't have user data
    ref = db.ref("/Developer/" + senderID)
    ref.update({ profile: user })
}

const saveSummaryToFirebase = (senderID, summary) => {
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("summary").child(summary.round).update({
        "round": summary.round,
        "done": summary.done,
        "isDone": summary.isDone,
        "keysQuestionLeft": summary.keysQuestionLeft,
        "skill": summary.skill,
        "grade": summary.grade,
        "score": summary.score,
        "totalScore": summary.totalScore
    })
}

module.exports = {
    connectToFirebase, getQuestionsFromFirebase, getAllAnswersFromQuestion, getQuestionFromId,
    getAllQuestionKeys, saveResultToFirebase, saveUserToFirebase, saveSummaryToFirebase, getNumberOfQuestions, getQuestionDone,
    getGrade
}

<commit_msg>show grade<commit_after>const connectToFirebase = () => {
    const admin = require("firebase-admin");
    let serviceAccount = require("./config/quizchatbot-ce222-firebase-adminsdk.json")
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://quizchatbot-ce222.firebaseio.com"
    })
    return admin
}

const admin = connectToFirebase()

//get total number of questions
const getNumberOfQuestions = async () => {
    let keys = await getAllQuestionKeys()
    let numberOfQuestions = keys.length
    return numberOfQuestions
}

//get all questions from firebase
const getQuestionsFromFirebase = async () => {
    // Get a database reference to our posts
    let db = admin.database()
    let ref = db.ref("/Quests")

    let questionSnapshots
    // Attach an asynchronous callback to read the data at our posts reference
    const result = await new Promise(function (resolve, reject) {
        ref.on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("Cannot get questions from firebase : " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return errorObject.code
    })

    return result
}

//get all answers from that question by id
const getAllAnswersFromQuestion = async (id) => {
    let db = admin.database()
    let ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).child("choices").on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("Cannot get all answers from question id : " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return "Reject Cannot get all answers from question id : " + errorObject.code
    })

    return result
}

//get question by id
const getQuestionFromId = async (id) => {
    let db = admin.database()
    let ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("Cannot get question from id : " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return "Reject Cannot get question from id : " + errorObject.code
    })

    return result
}

//get all questions' keys from firebase
const getAllQuestionKeys = () => new Promise(async (resolve, reject) => {
    const db = admin.database()
    const ref = db.ref("/Quests")

    ref.orderByKey().once("value", (snapshot) => {
        let keys = Object.keys(snapshot.val())
        console.log("keys in getAllQuestionKeys =  " + keys)
        resolve(keys)
    }, (errorObject) => {
        console.log("Cannot get all question keys = " + errorObject.code)
        reject(errorObject)
    })
})

//get key of questions already done by that user
//query only question that done in that round
const getQuestionDone = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                //get keys of questions done if that round
                if (resultSnapshot[property].round == round) {
                    keysDone.push(resultSnapshot[property].question)
                }
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const getGrade = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let grade
    ref.child("summary").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
             console.log("__prop = ", property)
            if (resultSnapshot.hasOwnProperty(property)) {
                 console.log("__resultSnapshot[propert] = ", resultSnapshot[property])
                if (resultSnapshot[property].round == round) {
                    grade = resultSnapshot[property].grade
                    console.log("__Grade in loop = ", grade)
                    console.log("__Grade = ", resultSnapshot[property].grade)
                }
            }
        }
        console.log("__Grade out loop= ", grade)
        resolve(grade)

    }, (errorObject) => {
        console.log("Cannot get grade of user  = " + errorObject.code)
    })

})

//save result of answered question
const saveResultToFirebase = async (senderID, prepareResult) => {
    let result = prepareResult[0]
    let keyQuestion = result.question
    console.log("key = ", keyQuestion)
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    //create new key when push
    ref.child("results").push({
        "answer": result.answer,
        "doneAt": result.doneAt,
        "startedAt": result.startedAt,
        "duration": result.duration,
        "point": result.point,
        "question": result.question,
        "result": result.result,
        "round": result.round,
        "score": result.score
    })
}

const saveUserToFirebase = (senderID, user) => {
    console.log("User in firebase= ", user)
    let db = admin.database()
    let ref = db.ref("/Developer/")
    let hasUser = false
    //check if firebase has that user data
    ref.once("value")
        .then((snapshot) => {
            snapshot.forEach((childSnapshot) => {
                if (childSnapshot.key == senderID) {
                    console.log("Already have user information")
                    hasUser = true
                    return
                }
            })
        })

    //if firebase doesn't have user data
    ref = db.ref("/Developer/" + senderID)
    ref.update({ profile: user })
}

const saveSummaryToFirebase = (senderID, summary) => {
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("summary").child(summary.round).update({
        "round": summary.round,
        "done": summary.done,
        "isDone": summary.isDone,
        "keysQuestionLeft": summary.keysQuestionLeft,
        "skill": summary.skill,
        "grade": summary.grade,
        "score": summary.score,
        "totalScore": summary.totalScore
    })
}

module.exports = {
    connectToFirebase, getQuestionsFromFirebase, getAllAnswersFromQuestion, getQuestionFromId,
    getAllQuestionKeys, saveResultToFirebase, saveUserToFirebase, saveSummaryToFirebase, getNumberOfQuestions, getQuestionDone,
    getGrade
}

<|endoftext|>


<commit_before>/* global bundle, $, d3plus */

var d3 = require("d3");

var COLOR_TABLE = [
  "#C8D2D9", "#97ABB8", "#FFBEB9", "#FFD1CE"
];

/* This is a poor-man's estimate, given the fact that measuring the
 * actual size of the characters (accounting for kerning) will involve
 * significant DOM mutation. */
var INDIVIDUAL_CHARACTER_SIZE = 10;

/**
 * drawBarForDataPoint
 */
function drawBarForDataPoint(svg, dataPoint, index, length, offsetAmount, dataMax) {
  var computeTextY = function computeTextY() {
    var chartHeight = this.parentNode.parentNode.clientHeight;
    var barSpacing = 10;
    var textHeight = 15;
    return (((chartHeight - (barSpacing * length)) /
            length) / 2) + (textHeight / 2);
  };
  var computeBarWidth = function computeBarWidth() {
    var parentWidth = (this.parentNode.parentNode.clientWidth -
                       offsetAmount);
    var x = d3.scaleLinear().domain([0, dataMax])
                            .range([0, parentWidth]);
    return x(dataPoint.value);
  };
  var g = svg.append("g")
             .attr("transform", function computeBarY() {
               var chartHeight = this.parentNode.clientHeight;
               var barSpacing = 10;
               var barHeight = ((chartHeight - (barSpacing *
                                                length)) /
                                length);

               var y = (index * barSpacing) + (index * barHeight);
               return "translate(0.0, " + y + ")";
             });
  g.append("rect")
   .attr("height", function computeBarHeight() {
     var chartHeight = this.parentNode.parentNode.clientHeight;
     var barSpacing = 10;
     return ((chartHeight - (barSpacing * length)) /
             length);
   })
   .transition()
   .delay(index * 50)
   .duration(750)
   .ease(d3.easeElastic.period(0.4))
   .attr("width", computeBarWidth)
   .attr("rx", "15")
   .attr("ry", "15")
   .attr("x", String(offsetAmount))
   .attr("fill", COLOR_TABLE[index % COLOR_TABLE.length]);
  g.append("text")
   .attr("fill", "#000000")
   .text(dataPoint.name)
   .attr("y", computeTextY)
   .attr("x", 10);
  g.append("text")
   .attr("fill", "#ffffff")
   .text(dataPoint.value)
   .attr("y", computeTextY)
   .transition()
   .delay(index * 50)
   .duration(750)
   .ease(d3.easeElastic.period(0.4))
   .attr("x", function computeNumberX() {
     var barWidth = computeBarWidth.call(this);
     var label = String(dataPoint.value);
     var labelSize = label.length * INDIVIDUAL_CHARACTER_SIZE;
     return (barWidth - labelSize) + offsetAmount;
   });
}

/**
 * drawBarChart
 *
 * Draws a bar chart using data on the given node.
 *
 * @data {array} - The data to use to draw the chart
 * @chartContainer {object} - The containing element for this chart
 * @returns {object} - The completed node
 */
function drawBarChart(data, chartContainer) {
  /* The individual points of data, not including labels */
  var dataPoints = data.map(function onEachDataPoint(w) {
    return w.value;
  });

  var svg = d3.select("div.chart")
              .append("svg")
              .attr("class", "svgchart")
              .attr("width", function computeWidth() {
                return this.parentNode.clientWidth * 0.80;
              })
              .attr("height", function computeHeight() {
                return this.parentNode.clientHeight * 0.80;
              })
              .attr("style", function computeTransform() {
                var x = this.parentNode.clientWidth * 0.10;
                var y = this.parentNode.clientHeight * 0.10;
                return ["transform: translate(", x, "px,", y, "px", ")"].join("");
              });

  /* Estimated sizes of the labels and the bars if no scaling was applied -
   * use this to determine whether an offset should be applied to the chart
   * based on the width of the smallest bar and its corresponding label. If
   * a bar's label size exceeds the size of the bar, we need to make
   * at least enough room on the left hand side for the bar label */
  var offsetAmount = 0;
  var postprocessedData = data.map(function onEachDataPoint(d) {
    var availableParentWidth = chartContainer.clientWidth * 0.80;
    var x = d3.scaleLinear().domain([0, d3.max(dataPoints)])
                            .range([0, availableParentWidth]);
    var label = 10 + (INDIVIDUAL_CHARACTER_SIZE * d.name.length);

    if (offsetAmount < label) {
      offsetAmount = label;
    }

    return {
      name: d.name,
      value: d.value
    };
  });

  var dataMax = d3.max(dataPoints);
  postprocessedData.forEach(function forEachDataPoint(dataPoint, index) {
    drawBarForDataPoint(svg, dataPoint, index, postprocessedData.length, offsetAmount, dataMax);
  });

  return svg;
}

/**
 * drawLineChart
 *
 * Draws a line chart using hte data on the given node.
 *
 * @svg {object} - An svg node to draw the bar chart on
 * @data {array} = The data to use to draw the chart
 * @returns {object} - The completed node
 */
function drawLineChart(data) {
  var dataset = data.map(function onEachDataPoint(d) {
    return {
      year: Number(d.name),
      retractions: d.value,
      name: "Retractions"
    };
  });

  return new d3plus.viz()  // eslint-disable-line new-cap
                   .container(".chart")
                   .data(dataset)
                   .type("line")
                   .id("name")
                   .text("name")
                   .y("retractions")
                   .x("year")
                   .draw();
}

var DrawChartDispatch = {
  countryRetraction: drawBarChart,
  authorRetraction: drawBarChart,
  topicRetraction: drawBarChart,
  retractionsOverTime: drawLineChart
};

/**
 * updateGraph
 *
 * Update the graph with some new data and remove the old one.
 *
 * @newData: New tuples of data to update the graph with
 */
function updateGraph(newData, name) {
  var chartContainer = document.getElementsByClassName("chart")[0];

  /* Drop any existing SVG elements */
  Array.prototype.forEach.call(document.getElementsByClassName("chart"),
                               function dropInnerHTMLOf(element) {
                                 /* Drop everything inside this chart */
                                 element.innerHTML = "";  // eslint-disable-line no-param-reassign
                               });

  DrawChartDispatch[name](newData, chartContainer);
}

/**
 * postGraphUpdateRequest
 *
 * Post a request to the server to get a new graph.
 *
 * @name The chart name to fetch.
 * @filter A filter string
 # @filterType What to filter on
 */
function postGraphUpdateRequest(name, filterString, filterType) {
  if (!name) {
    $("#incorrectInputAlert").html("You need to specify a chart type to display");
    $("#incorrectInputAlert").attr("style", "");
    return;
  }

  if (filterString && (!filterType || filterType === "none")) {
    $("#incorrectInputAlert").html("You need to specify what to search on");
    $("#incorrectInputAlert").attr("style", "");
    return;
  }

  $("#incorrectInputAlert").attr("style", "visibility: hidden;");

  if (name) {
    $.ajax({
      url: "/get_bar_chart",
      data: {
        name: name,
        filterString: filterString || null,
        filterType: filterType || null
      },
      success: function onXHRSuccess(data) {
        updateGraph(data.data, name);
      }
    });
  }
}

/**
 * listenForUserInteraction
 *
 * For a dropdown menu id and a it's contents' id, listen for
 * click events and then post an update request to fetch a graph.
 */
function listenForUserInteraction(dropdownSelector, menuSelector) {
  $(menuSelector + " li a").click(function onDropdownClick(event) {
    var button = $(dropdownSelector);
    var parentDiv = $(".open");

    button.html(this.text + " ");
    button.attr("selection", $(this).attr("data-selection-id"));
    parentDiv.removeClass("open");
    event.preventDefault();

    postGraphUpdateRequest($("#chartSelectionDropdown").attr("selection"),
                           $("#chartFilterInput").val(),
                           $("#filterSelectionDropdown").attr("selection"));
    return false;
  });
}

document.addEventListener("DOMContentLoaded", function onDOMLoaded() {
  listenForUserInteraction("#chartSelectionDropdown", "#chartSelectionMenu");
  listenForUserInteraction("#filterSelectionDropdown",
                           "#filterSelectionMenu");
  $("#chartFilterInput").keypress(function onKeyPress(event) {
    var keyCode = event.keyCode || event.which;
    if (keyCode === 13) {
      /* User pressed enter, respond accordingly */
      postGraphUpdateRequest($("#chartSelectionDropdown").attr("selection"),
                             $("#chartFilterInput").val(),
                             $("#filterSelectionDropdown").attr("selection"));
    }
  });
});
<commit_msg>retraction: Remove unused variable<commit_after>/* global bundle, $, d3plus */

var d3 = require("d3");

var COLOR_TABLE = [
  "#C8D2D9", "#97ABB8", "#FFBEB9", "#FFD1CE"
];

/* This is a poor-man's estimate, given the fact that measuring the
 * actual size of the characters (accounting for kerning) will involve
 * significant DOM mutation. */
var INDIVIDUAL_CHARACTER_SIZE = 10;

/**
 * drawBarForDataPoint
 */
function drawBarForDataPoint(svg, dataPoint, index, length, offsetAmount, dataMax) {
  var computeTextY = function computeTextY() {
    var chartHeight = this.parentNode.parentNode.clientHeight;
    var barSpacing = 10;
    var textHeight = 15;
    return (((chartHeight - (barSpacing * length)) /
            length) / 2) + (textHeight / 2);
  };
  var computeBarWidth = function computeBarWidth() {
    var parentWidth = (this.parentNode.parentNode.clientWidth -
                       offsetAmount);
    var x = d3.scaleLinear().domain([0, dataMax])
                            .range([0, parentWidth]);
    return x(dataPoint.value);
  };
  var g = svg.append("g")
             .attr("transform", function computeBarY() {
               var chartHeight = this.parentNode.clientHeight;
               var barSpacing = 10;
               var barHeight = ((chartHeight - (barSpacing *
                                                length)) /
                                length);

               var y = (index * barSpacing) + (index * barHeight);
               return "translate(0.0, " + y + ")";
             });
  g.append("rect")
   .attr("height", function computeBarHeight() {
     var chartHeight = this.parentNode.parentNode.clientHeight;
     var barSpacing = 10;
     return ((chartHeight - (barSpacing * length)) /
             length);
   })
   .transition()
   .delay(index * 50)
   .duration(750)
   .ease(d3.easeElastic.period(0.4))
   .attr("width", computeBarWidth)
   .attr("rx", "15")
   .attr("ry", "15")
   .attr("x", String(offsetAmount))
   .attr("fill", COLOR_TABLE[index % COLOR_TABLE.length]);
  g.append("text")
   .attr("fill", "#000000")
   .text(dataPoint.name)
   .attr("y", computeTextY)
   .attr("x", 10);
  g.append("text")
   .attr("fill", "#ffffff")
   .text(dataPoint.value)
   .attr("y", computeTextY)
   .transition()
   .delay(index * 50)
   .duration(750)
   .ease(d3.easeElastic.period(0.4))
   .attr("x", function computeNumberX() {
     var barWidth = computeBarWidth.call(this);
     var label = String(dataPoint.value);
     var labelSize = label.length * INDIVIDUAL_CHARACTER_SIZE;
     return (barWidth - labelSize) + offsetAmount;
   });
}

/**
 * drawBarChart
 *
 * Draws a bar chart using data on the given node.
 *
 * @data {array} - The data to use to draw the chart
 * @chartContainer {object} - The containing element for this chart
 * @returns {object} - The completed node
 */
function drawBarChart(data, chartContainer) {
  /* The individual points of data, not including labels */
  var dataPoints = data.map(function onEachDataPoint(w) {
    return w.value;
  });

  var svg = d3.select("div.chart")
              .append("svg")
              .attr("class", "svgchart")
              .attr("width", function computeWidth() {
                return this.parentNode.clientWidth * 0.80;
              })
              .attr("height", function computeHeight() {
                return this.parentNode.clientHeight * 0.80;
              })
              .attr("style", function computeTransform() {
                var x = this.parentNode.clientWidth * 0.10;
                var y = this.parentNode.clientHeight * 0.10;
                return ["transform: translate(", x, "px,", y, "px", ")"].join("");
              });

  /* Estimated sizes of the labels and the bars if no scaling was applied -
   * use this to determine whether an offset should be applied to the chart
   * based on the width of the smallest bar and its corresponding label. If
   * a bar's label size exceeds the size of the bar, we need to make
   * at least enough room on the left hand side for the bar label */
  var offsetAmount = 0;
  var postprocessedData = data.map(function onEachDataPoint(d) {
    var availableParentWidth = chartContainer.clientWidth * 0.80;
    var label = 10 + (INDIVIDUAL_CHARACTER_SIZE * d.name.length);

    if (offsetAmount < label) {
      offsetAmount = label;
    }

    return {
      name: d.name,
      value: d.value
    };
  });

  var dataMax = d3.max(dataPoints);
  postprocessedData.forEach(function forEachDataPoint(dataPoint, index) {
    drawBarForDataPoint(svg, dataPoint, index, postprocessedData.length, offsetAmount, dataMax);
  });

  return svg;
}

/**
 * drawLineChart
 *
 * Draws a line chart using hte data on the given node.
 *
 * @svg {object} - An svg node to draw the bar chart on
 * @data {array} = The data to use to draw the chart
 * @returns {object} - The completed node
 */
function drawLineChart(data) {
  var dataset = data.map(function onEachDataPoint(d) {
    return {
      year: Number(d.name),
      retractions: d.value,
      name: "Retractions"
    };
  });

  return new d3plus.viz()  // eslint-disable-line new-cap
                   .container(".chart")
                   .data(dataset)
                   .type("line")
                   .id("name")
                   .text("name")
                   .y("retractions")
                   .x("year")
                   .draw();
}

var DrawChartDispatch = {
  countryRetraction: drawBarChart,
  authorRetraction: drawBarChart,
  topicRetraction: drawBarChart,
  retractionsOverTime: drawLineChart
};

/**
 * updateGraph
 *
 * Update the graph with some new data and remove the old one.
 *
 * @newData: New tuples of data to update the graph with
 */
function updateGraph(newData, name) {
  var chartContainer = document.getElementsByClassName("chart")[0];

  /* Drop any existing SVG elements */
  Array.prototype.forEach.call(document.getElementsByClassName("chart"),
                               function dropInnerHTMLOf(element) {
                                 /* Drop everything inside this chart */
                                 element.innerHTML = "";  // eslint-disable-line no-param-reassign
                               });

  DrawChartDispatch[name](newData, chartContainer);
}

/**
 * postGraphUpdateRequest
 *
 * Post a request to the server to get a new graph.
 *
 * @name The chart name to fetch.
 * @filter A filter string
 # @filterType What to filter on
 */
function postGraphUpdateRequest(name, filterString, filterType) {
  if (!name) {
    $("#incorrectInputAlert").html("You need to specify a chart type to display");
    $("#incorrectInputAlert").attr("style", "");
    return;
  }

  if (filterString && (!filterType || filterType === "none")) {
    $("#incorrectInputAlert").html("You need to specify what to search on");
    $("#incorrectInputAlert").attr("style", "");
    return;
  }

  $("#incorrectInputAlert").attr("style", "visibility: hidden;");

  if (name) {
    $.ajax({
      url: "/get_bar_chart",
      data: {
        name: name,
        filterString: filterString || null,
        filterType: filterType || null
      },
      success: function onXHRSuccess(data) {
        updateGraph(data.data, name);
      }
    });
  }
}

/**
 * listenForUserInteraction
 *
 * For a dropdown menu id and a it's contents' id, listen for
 * click events and then post an update request to fetch a graph.
 */
function listenForUserInteraction(dropdownSelector, menuSelector) {
  $(menuSelector + " li a").click(function onDropdownClick(event) {
    var button = $(dropdownSelector);
    var parentDiv = $(".open");

    button.html(this.text + " ");
    button.attr("selection", $(this).attr("data-selection-id"));
    parentDiv.removeClass("open");
    event.preventDefault();

    postGraphUpdateRequest($("#chartSelectionDropdown").attr("selection"),
                           $("#chartFilterInput").val(),
                           $("#filterSelectionDropdown").attr("selection"));
    return false;
  });
}

document.addEventListener("DOMContentLoaded", function onDOMLoaded() {
  listenForUserInteraction("#chartSelectionDropdown", "#chartSelectionMenu");
  listenForUserInteraction("#filterSelectionDropdown",
                           "#filterSelectionMenu");
  $("#chartFilterInput").keypress(function onKeyPress(event) {
    var keyCode = event.keyCode || event.which;
    if (keyCode === 13) {
      /* User pressed enter, respond accordingly */
      postGraphUpdateRequest($("#chartSelectionDropdown").attr("selection"),
                             $("#chartFilterInput").val(),
                             $("#filterSelectionDropdown").attr("selection"));
    }
  });
});
<|endoftext|>


<commit_before>
var _ = require('highland');

var EventEmitter = require('events').EventEmitter;

var utils = require('./utils');

var emitter = new EventEmitter();

exports.dataStream = _('data', emitter);

// exports.statusStream = _('status', emitter);

var ls = require('lightstreamer-client');

var dd = require('./data_dictionary');

var SCHEMA = ['TimeStamp', 'Value', 'Status.Class', 'CalibratedData'];

// the data stream
var lsClient = new ls.LightstreamerClient('http://push.lightstreamer.com', 'ISSLIVE');

lsClient.connectionOptions.setSlowingEnabled(false);

// MERGE indicates that we only want to receive data when the value(s) have changed
var telemetrySub = new ls.Subscription('MERGE', dd.list, SCHEMA);
var timeSub = new ls.Subscription('MERGE', 'TIME_000001', ['Status.Class']);

var statusIdx = dd.hash.STATUS;

var telemetrySessionId;

var lastStatus;

var time00001Timeout;

function statusUpdate(connected) {

  var now = Date.now() / 1000 | 0, data;

  data = {
    k: statusIdx.toString(),
    v: connected ? 1 : 0,
    t: now,
    s: connected ? 24 : 2,  // 24 and 2 are values from telemetry
    sid: now
  };

  if (!lastStatus) {

    console.log(data);

    emitter.emit('data', data);

  } else if (lastStatus && lastStatus.s !== data.s) {

    console.log(data);

    emitter.emit('data', data);
  }

  lastStatus = data;
}

lsClient.subscribe(timeSub);
lsClient.connect();

var unsubTimeout = null;

timeSub.addListener({

  onUnsubscription: function () {

    lsClient.unsubscribe(telemetrySub);
  },

  onItemUpdate: function (update) {

    var status = update.getValue('Status.Class'),
    subscribed = telemetrySub.isSubscribed();

    if (status === '24' && unsubTimeout) {

      clearTimeout(unsubTimeout);
      unsubTimeout = null;
    }

    if (status === '24' && !subscribed) {

      lsClient.subscribe(telemetrySub);

    } else if (status !== '24' && subscribed) {

      // give 20 seconds to collect any outstanding data from lightstreamer
      unsubTimeout = setTimeout(function () {

        lsClient.unsubscribe(telemetrySub);

      }, 10000);
    }
  }
});

telemetrySub.addListener({

  onSubscription: function () {

    telemetrySessionId = utils.getTimeBasedId();

    // setup a timeout to notify clients if data is not streaming
    clearTimeout(time00001Timeout);
    time00001Timeout = setTimeout(function () { statusUpdate(false); }, 10000);
  },

  onItemUpdate: function (update) {

    var fValue = 0,

    fTimeStamp = 0,

    iStatus = 0,

    idx = dd.hash[update.getItemName()];

    try {

      fValue = parseFloat(update.getValue('Value'));
      fTimeStamp = parseFloat(update.getValue('TimeStamp'));
      iStatus = parseInt(update.getValue('Status.Class'), 10);

    } catch (ex) {

      console.error(ex);
    }

    if (fTimeStamp) {
      var now = new Date();
      var year = new Date(Date.UTC(now.getUTCFullYear(), 0)); // This year, jan 1, 00:00:00, utc
      // THE TELEMETRY TIME SEEMS TO ADD 24 HOURS TO NUMBER
      // OF HOURS IN THE YEAR SO FAR.  STRANGE.  TODO
      // so we subtract 24 from fTimeStamp, convert to seconds
      // add to number of seconds as of THIS_YEAR-01-01T00:00:00 UTC
      // truncate the decimal places for a result in seconds, aka unixtime
      fTimeStamp = (((fTimeStamp - 24) * 3600) + (year.getTime() / 1000)) | 0;
    }

    // handle TIME_000001
    if (idx === 296) {
      // in this case utilize the timestamp for the value
      fValue = fTimeStamp;

      // data is streaming, notify clients
      statusUpdate(true);
      // setup a timeout to notify clients if stops streaming
      clearTimeout(time00001Timeout);
      time00001Timeout = setTimeout(function () { statusUpdate(false); }, 10000);
    }

    var data = {
      k: idx,
      v: fValue,
      cv: update.getValue('CalibratedData'),
      t: fTimeStamp,
      s: iStatus,
      sid: telemetrySessionId
    };

    emitter.emit('data', data);

    // if(update.getItemName() === 'USLAB000024') {
    //   console.log(update.getItemName());
    //   SCHEMA.forEach(function(key) { console.log(key + ': ' + update.getValue(key)); });
    // }
  }
});
<commit_msg>added another check to determine telemetry streaming status<commit_after>
var _ = require('highland');

var EventEmitter = require('events').EventEmitter;

var utils = require('./utils');

var emitter = new EventEmitter();

exports.dataStream = _('data', emitter);

// exports.statusStream = _('status', emitter);

var ls = require('lightstreamer-client');

var dd = require('./data_dictionary');

var SCHEMA = ['TimeStamp', 'Value', 'Status.Class', 'CalibratedData'];

// the data stream
var lsClient = new ls.LightstreamerClient('http://push.lightstreamer.com', 'ISSLIVE');

lsClient.connectionOptions.setSlowingEnabled(false);

// MERGE indicates that we only want to receive data when the value(s) have changed
var telemetrySub = new ls.Subscription('MERGE', dd.list, SCHEMA);
var timeSub = new ls.Subscription('MERGE', 'TIME_000001', ['Status.Class']);

var statusIdx = dd.hash.STATUS;

var telemetrySessionId;

var lastStatus;

var time00001Timeout;

function statusUpdate(connected) {

  var now = Date.now() / 1000 | 0, data;

  data = {
    k: statusIdx.toString(),
    v: connected ? 1 : 0,
    t: now,
    s: connected ? 24 : 2,  // 24 and 2 are values from telemetry
    sid: now
  };

  if (!lastStatus) {

    console.log(data);

    emitter.emit('data', data);

  } else if (lastStatus && lastStatus.s !== data.s) {

    console.log(data);

    emitter.emit('data', data);
  }

  lastStatus = data;
}

lsClient.addListener({

  onStatusChange: function (status) {

    // setup a timeout to notify clients if data is not streaming
    clearTimeout(time00001Timeout);
    time00001Timeout = setTimeout(function () { statusUpdate(false); }, 15000);
  }
});

lsClient.subscribe(timeSub);
lsClient.connect();

var unsubTimeout = null;

timeSub.addListener({

  onUnsubscription: function () {

    lsClient.unsubscribe(telemetrySub);
  },

  onItemUpdate: function (update) {

    var status = update.getValue('Status.Class'),
    subscribed = telemetrySub.isSubscribed();

    if (status === '24' && unsubTimeout) {

      clearTimeout(unsubTimeout);
      unsubTimeout = null;
    }

    if (status === '24' && !subscribed) {

      lsClient.subscribe(telemetrySub);

    } else if (status !== '24' && subscribed) {

      // give 20 seconds to collect any outstanding data from lightstreamer
      unsubTimeout = setTimeout(function () {

        lsClient.unsubscribe(telemetrySub);

      }, 10000);
    }
  }
});

telemetrySub.addListener({

  onSubscription: function () {

    telemetrySessionId = utils.getTimeBasedId();

    // setup a timeout to notify clients if data is not streaming
    clearTimeout(time00001Timeout);
    time00001Timeout = setTimeout(function () { statusUpdate(false); }, 10000);
  },

  onItemUpdate: function (update) {

    var fValue = 0,

    fTimeStamp = 0,

    iStatus = 0,

    idx = dd.hash[update.getItemName()];

    try {

      fValue = parseFloat(update.getValue('Value'));
      fTimeStamp = parseFloat(update.getValue('TimeStamp'));
      iStatus = parseInt(update.getValue('Status.Class'), 10);

    } catch (ex) {

      console.error(ex);
    }

    if (fTimeStamp) {
      var now = new Date();
      var year = new Date(Date.UTC(now.getUTCFullYear(), 0)); // This year, jan 1, 00:00:00, utc
      // THE TELEMETRY TIME SEEMS TO ADD 24 HOURS TO NUMBER
      // OF HOURS IN THE YEAR SO FAR.  STRANGE.  TODO
      // so we subtract 24 from fTimeStamp, convert to seconds
      // add to number of seconds as of THIS_YEAR-01-01T00:00:00 UTC
      // truncate the decimal places for a result in seconds, aka unixtime
      fTimeStamp = (((fTimeStamp - 24) * 3600) + (year.getTime() / 1000)) | 0;
    }

    // handle TIME_000001
    if (idx === 296) {
      // in this case utilize the timestamp for the value
      fValue = fTimeStamp;

      // data is streaming, notify clients
      statusUpdate(true);
      // setup a timeout to notify clients if stops streaming
      clearTimeout(time00001Timeout);
      time00001Timeout = setTimeout(function () { statusUpdate(false); }, 10000);
    }

    var data = {
      k: idx,
      v: fValue,
      cv: update.getValue('CalibratedData'),
      t: fTimeStamp,
      s: iStatus,
      sid: telemetrySessionId
    };

    emitter.emit('data', data);

    // if(update.getItemName() === 'USLAB000024') {
    //   console.log(update.getItemName());
    //   SCHEMA.forEach(function(key) { console.log(key + ': ' + update.getValue(key)); });
    // }
  }
});
<|endoftext|>


<commit_before>
/*

rest3d-server.js

The MIT License (MIT)

Copyright (c) 2013 Rémi Arnaud - Advanced Micro Devices, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

'use strict';

if (process.env['NODETIME_KEY']) {
	console.log("+=+=+= Starting http://nodetime.com");
	console.log("Key = '"+process.env['NODETIME_KEY']+"'");
	require('nodetime').profile({
    accountKey: process.env['NODETIME_KEY'],
    appName: 'rest3d.fl4re.com node server'
  });
}

var restify = require('restify');
//var connect = require('connect');
var http = require('http');
var utils = require('./src/utils');
var childProcess = require('child_process');
var os= require('os');
require('shelljs/global');

var fs = require('fs');
var path = require('path');
var cache = require('./src/diskcache').Cache;
// fast html scrapping
var request = require('request');
// get content from zip files
var zip = require("zip");

var formidable = require('formidable');

var rmdirSync = require('./src/rmdir');
var copyFileSync = require('./src/cp');

var toJSON = require('./src/tojson');

var FileInfo = require('./src/fileinfo');
var sendFile = require('./src/sendfile');
var handler= require('./src/handler');

var platform = os.type().match(/^Win/) ? 'win' :
				(os.type().match(/^Dar/) ? 'mac' : 'unix');

console.log('host platform=',platform);
var staticPath = path.join(__dirname , '../static');

console.log('static folder=',staticPath);

var httpPort = process.env.OPENSHIFT_NODEJS_PORT ||
                   process.env.HTTP ||
                   8000;
var httpsPort = process.env.HTTPS || 443;
var ip_address = process.env.OPENSHIFT_NODEJS_IP || null;
var listenToPort = httpPort;

// see where collada2gltf is located
var openshift = process.env.OPENSHIFT_DATA_DIR;
var collada2gltf = 'collada2gltf';
if (openshift)
    collada2gltf = openshift + 'bin/collada2gltf-latest';
if (process.env.GLTF_BIN_PATH)
    collada2gltf = process.env.GLTF_BIN_PATH+'/collada2gltf';

// find out if we are running http or https
// if https, create two servers, the http server only does redirect to https

var params = {name: 'rest3d'};

if (fs.existsSync('./server.pem') && fs.existsSync('./server.key')){
	console.log('found https certficates');
	params.key = fs.readFileSync('./server.key');
	params.certificate = fs.readFileSync('./server.pem');
	listenToPort = httpsPort;
};

var server = module.exports.server = restify.createServer(params);

if (params.key) {
  var http_server = restify.createServer();
  http_server.get(/.*/,function(req,res,next) {
    // Assume https port is on the default port
    var redirect = "https://" + req.headers.host.replace (/(.*):.*/, '$1') +  req.url;
  	res.writeHead(302, {'Location': redirect});

    //console.log('**** https redirect to '+redirect)
    res.end();
    next();
	});
	http_server.listen( httpPort, ip_address);
}

rmdirSync('tmp');
rmdirSync('cache');
rmdirSync('upload');

fs.mkdirSync('tmp');
fs.mkdirSync('upload');
fs.mkdirSync('cache');

fs.chmodSync('tmp', '777');
fs.chmodSync('upload', '777');
fs.chmodSync('cache', '777');

//fs.mkdirSync('upload/thumbnail');

server.use(restify.acceptParser(server.acceptable));
//server.use(restify.authorizationParser());
server.use(restify.dateParser());
server.use(restify.queryParser());
//server.use(restify.bodyParser()); -> use formidable instead
server.use(restify.gzipResponse());
restify.defaultResponseHeaders = false;

var session=require('./src/session')();
server.sessionManager = session;
server.use(session.sessionManager);

// include routes
require('./src/warehouse')(server);
require('./src/3dvia')(server);
require('./src/upload')(server);

require('./src/basex')(server);

// create diskcache (no mem caching, no gzip)
server.diskcache = new cache('cache',true,false,false);

function unknownMethodHandler(req, res) {
	console.log('unkownMethodHandler method='+req.method.toLowerCase());
  if (req.method.toLowerCase() === 'options') {
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version'];

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
    res.header('Access-Control-Allow-Methods', res.methods.join(', '));
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);
/*
server.use(restify.throttle({
  burst: 100,
  rate: 50,
  ip: true,
  overrides: {
    '192.168.1.1': {
      rate: 0,        // unlimited
      burst: 0
    }
  }
}));
*/
//server.use(restify.conditionalRequest());

// rest3d API

// convert

server.post(/^\/rest3d\/convert.*/,function(req,res,next){
	 console.log('post -> convert');

	 var form = new formidable.IncomingForm(),
         url = '',
         params = {};

   var h = new handler(req,res, next);

     form.on('field', function (name, data) {
     	params[name] = data;
     }).on('error', function (e) {
     	h.handleError(e);
     }).on('end', function(){//
     	console.log('now converting collada');
     	console.log(params);
     	 	console.log(params.uri);
     	// if (!params.name && !params.uri || !params.name.toLowerCase().endsWith('dae')) {
     	// 	h.handleError({error: 'invalid file '+params.name+' in convert'});
     	// 	return;
     	// }
     	if(params.hasOwnProperty("path")){
     		var output_dir = params.path.split('/')[1]+'_gltf';
     		console.log(output_dir);
	     	var output_file = params.path.split('/').pop().replace('.dae','.json');
	     	console.log(output_file);
	     	fs.mkdirSync('upload/'+output_dir);
	     	var cmd = collada2gltf+" -p -f \"upload" + params.uri+"\" -o \""+'upload/'+output_dir+'/'+output_file+"\"";
	     	console.log(collada2gltf+" -p -f \"upload" + params.uri+"\" -o \""+'upload/'+output_dir+'/'+output_file+"\"");
     	}
     	else{
	     	var output_dir = params.name.split('\.')[0]+'_gltf';
	     	var output_file = params.name.replace('.dae','.json');
	     	fs.mkdirSync('upload/'+output_dir);

	     	var cmd = collada2gltf+" -p -f \"upload/" + params.name+"\" -o \""+'upload/'+output_dir+'/'+output_file+"\"";
     }
     	console.log('exec '+cmd);
     	// todo -> manage progress !!!
		var outputC2J;
     	var codeC2J;
     	// todo -> manage progress !!!
		var ls = childProcess.exec(cmd, function (error, stdout, stderr) {
		   if (error) {
		     console.log(error.stack);
		     //console.log('Error code: '+error.code);
		     //console.log('Signal received: '+error.signal);

			 h.handleError({"code":error.code, "message": stderr});

		   }
		   console.log('Child Process STDOUT: '+stdout);
		   console.log('Child Process STDERR: '+stderr);
		 });

		 ls.on('exit', function (code, output) {
		  console.log('Child process exited with exit code '+code);
		  if (code !== 0) {
				h.handleError({errorCode:code, message:'Child process exited with exit code '});
				return;
			}
			codeC2J= code;
			outputC2J = output;
			console.log('Exit code:', code);
	  		console.log('Program output:', output);

			// hack, copy all images in the output_dir, so the viewer will work
		    fs.readdir('upload/', function (err, list) {
                list.forEach(function (name) {
                	if (name.endsWith('.png'))
                	{
                		copyFileSync('upload/'+name,'upload/'+output_dir+'/'+name);
                		console.log('upload/'+name+'  TO  upload/'+output_dir+'/'+name);
                	}
		        });
		    });
		    // end hack

			var files = [];
			fs.readdir('upload/'+output_dir, function (err, list) {
                list.forEach(function (name) {
		            var stats = fs.statSync('upload/'+output_dir + '/' + name),
		                fileInfo;
		            if (stats.isFile() && name[0] !== '.') {
		                fileInfo = new FileInfo({
		                    name: output_dir+'/'+name,
		                    size: stats.size
		                });
		                //fileInfo.initUrls(req);
		                files.push(fileInfo);
		            }
		        });
		        var timeout = function() {
                    	rmdirSync('upload/'+output_dir);
                    	console.log('timeout !! upload/'+output_dir+'/ was deleted');
                    }
                    setTimeout(function() { timeout()},5 * 60 * 1000);
		        h.handleResult({files: files, code:codeC2J, output:outputC2J});
		    });
	     });
	     });

    form.parse(req);

});

// static server
server.get(/^\/.*/, function (req, res, next) {

	// parse out parameters from url
	var filename = req.url.split('\?')[0];
	var p=path.resolve(staticPath + filename);

	console.log('http get path='+filename);

	sendFile(req,res,p);
	return next();
});

// clean exit
function sigterm_handler() {
    console.warn('Kaboom Baby!');
    process.exit(0);
}

process.on('SIGTERM', sigterm_handler);

// run server
server.listen( listenToPort, ip_address);
console.log ('rest3d server running on port '+listenToPort);

<commit_msg>Touch<commit_after>
/*

rest3d-server.js

The MIT License (MIT)

Copyright (c) 2013 Rémi Arnaud - Advanced Micro Devices, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

'use strict';

if (process.env['NODETIME_KEY']) {
	console.log("+=+=+= Starting http://nodetime.com");
	console.log("Key = '"+process.env['NODETIME_KEY']+"'");
	require('nodetime').profile({
    accountKey: process.env['NODETIME_KEY'],
    appName: 'rest3d.fl4re.com node server'
  });
}

var restify = require('restify');
//var connect = require('connect');
var http = require('http');
var utils = require('./src/utils');
var childProcess = require('child_process');
var os= require('os');
require('shelljs/global');

var fs = require('fs');
var path = require('path');
var cache = require('./src/diskcache').Cache;
// fast html scrapping
var request = require('request');
// get content from zip files
var zip = require("zip");

var formidable = require('formidable');

var rmdirSync = require('./src/rmdir');
var copyFileSync = require('./src/cp');

var toJSON = require('./src/tojson');

var FileInfo = require('./src/fileinfo');
var sendFile = require('./src/sendfile');
var handler= require('./src/handler');

var platform = os.type().match(/^Win/) ? 'win' :
				(os.type().match(/^Dar/) ? 'mac' : 'unix');

console.log('host platform=',platform);
var staticPath = path.join(__dirname , '../static');

console.log('static folder=',staticPath);

var httpPort = process.env.OPENSHIFT_NODEJS_PORT ||
                   process.env.HTTP ||
                   8000;
var httpsPort = process.env.HTTPS || 443;
var ip_address = process.env.OPENSHIFT_NODEJS_IP || null;
var listenToPort = httpPort;

// see where collada2gltf is located
var openshift = process.env.OPENSHIFT_DATA_DIR;
var collada2gltf = 'collada2gltf';
if (openshift)
    collada2gltf = openshift + 'bin/collada2gltf-latest';
if (process.env.GLTF_BIN_PATH)
    collada2gltf = process.env.GLTF_BIN_PATH+'/collada2gltf';

// find out if we are running http or https
// if https, create two servers, the http server only does redirect to https

var params = {name: 'rest3d'};

if (fs.existsSync('./server.pem') && fs.existsSync('./server.key')){
	console.log('found https certficates');
	params.key = fs.readFileSync('./server.key');
	params.certificate = fs.readFileSync('./server.pem');
	listenToPort = httpsPort;
};

var server = module.exports.server = restify.createServer(params);

if (params.key) {
  var http_server = restify.createServer();
  http_server.get(/.*/,function(req,res,next) {
    // Assume https port is on the default port
    var redirect = "https://" + req.headers.host.replace (/(.*):.*/, '$1') +  req.url;
  	res.writeHead(302, {'Location': redirect});

    //console.log('**** https redirect to '+redirect)
    res.end();
    next();
	});
	http_server.listen( httpPort, ip_address);
}

rmdirSync('tmp');
rmdirSync('cache');
rmdirSync('upload');

fs.mkdirSync('tmp');
fs.mkdirSync('upload');
fs.mkdirSync('cache');

fs.chmodSync('tmp', '777');
fs.chmodSync('upload', '777');
fs.chmodSync('cache', '777');

//fs.mkdirSync('upload/thumbnail');

server.use(restify.acceptParser(server.acceptable));
//server.use(restify.authorizationParser());
server.use(restify.dateParser());
server.use(restify.queryParser());
//server.use(restify.bodyParser()); -> use formidable instead
server.use(restify.gzipResponse());
restify.defaultResponseHeaders = false;

var session=require('./src/session')();
server.sessionManager = session;
server.use(session.sessionManager);

// include routes
require('./src/warehouse')(server);
require('./src/3dvia')(server);
require('./src/upload')(server);

require('./src/basex')(server);

// create diskcache (no mem caching, no gzip)
server.diskcache = new cache('cache',true,false,false);

function unknownMethodHandler(req, res) {
	console.log('unkownMethodHandler method='+req.method.toLowerCase());
  if (req.method.toLowerCase() === 'options') {
    var allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version'];

    if (res.methods.indexOf('OPTIONS') === -1) res.methods.push('OPTIONS');

    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
    res.header('Access-Control-Allow-Methods', res.methods.join(', '));
    res.header('Access-Control-Allow-Origin', req.headers.origin);

    return res.send(204);
  }
  else
    return res.send(new restify.MethodNotAllowedError());
}

server.on('MethodNotAllowed', unknownMethodHandler);
/*
server.use(restify.throttle({
  burst: 100,
  rate: 50,
  ip: true,
  overrides: {
    '192.168.1.1': {
      rate: 0,        // unlimited
      burst: 0
    }
  }
}));
*/
//server.use(restify.conditionalRequest());

// rest3d API

// convert

server.post(/^\/rest3d\/convert.*/,function(req,res,next){
	 console.log('post -> convert');

	 var form = new formidable.IncomingForm(),
         url = '',
         params = {};

   var h = new handler(req,res, next);

     form.on('field', function (name, data) {
     	params[name] = data;
     }).on('error', function (e) {
     	h.handleError(e);
     }).on('end', function(){//
     	console.log('now converting collada');
     	console.log(params);
     	 	console.log(params.uri);
     	// if (!params.name && !params.uri || !params.name.toLowerCase().endsWith('dae')) {
     	// 	h.handleError({error: 'invalid file '+params.name+' in convert'});
     	// 	return;
     	// }
     	if(params.hasOwnProperty("uri")){
     		var output_dir = params.uri.path.split('/')[1]+'_gltf';
     		console.log(output_dir);
	     	var output_file = params.uri.path.split('/').pop().replace('.dae','.json');
	     	console.log(output_file);
	     	fs.mkdirSync('upload/'+output_dir);
	     	var cmd = collada2gltf+" -p -f \"upload" + params.uri.path+"\" -o \""+'upload/'+output_dir+'/'+output_file+"\"";
	     	console.log(collada2gltf+" -p -f \"upload" + params.uri.path+"\" -o \""+'upload/'+output_dir+'/'+output_file+"\"");
     	}
     	else{
	     	var output_dir = params.name.split('\.')[0]+'_gltf';
	     	var output_file = params.name.replace('.dae','.json');
	     	fs.mkdirSync('upload/'+output_dir);

	     	var cmd = collada2gltf+" -p -f \"upload/" + params.name+"\" -o \""+'upload/'+output_dir+'/'+output_file+"\"";
     }
     	console.log('exec '+cmd);
     	// todo -> manage progress !!!
		var outputC2J;
     	var codeC2J;
     	// todo -> manage progress !!!
		var ls = childProcess.exec(cmd, function (error, stdout, stderr) {
		   if (error) {
		     console.log(error.stack);
		     //console.log('Error code: '+error.code);
		     //console.log('Signal received: '+error.signal);

			 h.handleError({"code":error.code, "message": stderr});

		   }
		   console.log('Child Process STDOUT: '+stdout);
		   console.log('Child Process STDERR: '+stderr);
		 });

		 ls.on('exit', function (code, output) {
		  console.log('Child process exited with exit code '+code);
		  if (code !== 0) {
				h.handleError({errorCode:code, message:'Child process exited with exit code '});
				return;
			}
			codeC2J= code;
			outputC2J = output;
			console.log('Exit code:', code);
	  		console.log('Program output:', output);

			// hack, copy all images in the output_dir, so the viewer will work
		    fs.readdir('upload/', function (err, list) {
                list.forEach(function (name) {
                	if (name.endsWith('.png'))
                	{
                		copyFileSync('upload/'+name,'upload/'+output_dir+'/'+name);
                		console.log('upload/'+name+'  TO  upload/'+output_dir+'/'+name);
                	}
		        });
		    });
		    // end hack

			var files = [];
			fs.readdir('upload/'+output_dir, function (err, list) {
                list.forEach(function (name) {
		            var stats = fs.statSync('upload/'+output_dir + '/' + name),
		                fileInfo;
		            if (stats.isFile() && name[0] !== '.') {
		                fileInfo = new FileInfo({
		                    name: output_dir+'/'+name,
		                    size: stats.size
		                });
		                //fileInfo.initUrls(req);
		                files.push(fileInfo);
		            }
		        });
		        var timeout = function() {
                    	rmdirSync('upload/'+output_dir);
                    	console.log('timeout !! upload/'+output_dir+'/ was deleted');
                    }
                    setTimeout(function() { timeout()},5 * 60 * 1000);
		        h.handleResult({files: files, code:codeC2J, output:outputC2J});
		    });
	     });
	     });

    form.parse(req);

});

// static server
server.get(/^\/.*/, function (req, res, next) {

	// parse out parameters from url
	var filename = req.url.split('\?')[0];
	var p=path.resolve(staticPath + filename);

	console.log('http get path='+filename);

	sendFile(req,res,p);
	return next();
});

// clean exit
function sigterm_handler() {
    console.warn('Kaboom Baby!');
    process.exit(0);
}

process.on('SIGTERM', sigterm_handler);

// run server
server.listen( listenToPort, ip_address);
console.log ('rest3d server running on port '+listenToPort);

<|endoftext|>