<commit_before>/*
* basically just the functions which will be improved when we move to the new server API
*
* Note that a lot of this code is replicated in the nextstrain.org repo
* and it could instead be exposed by "auspice" (and imported by the nextstrain.org repo)
* Note also https://github.com/nextstrain/auspice/issues/687 which proposes
* changing the server-client API
*
*/

const utils = require("../utils");
const queryString = require("query-string");
const path = require("path");
const convertFromV1 = require("./convertJsonSchemas").convertFromV1;
const fs = require("fs");

const handleError = (res, clientMsg, serverMsg="") => {
  res.statusMessage = clientMsg;
  utils.warn(`${clientMsg} -- ${serverMsg}`);
  return res.status(500).end();
};

const splitPrefixIntoParts = (url) => url
  .replace(/^\//, '')
  .replace(/\/$/, '')
  .split("/");

/**
 * Basic interpretation of an auspice request
 * @returns {Object} keys: `dataType`, `parts`
 */
const interpretRequest = (req) => {
  utils.log(`GET DATASET query received: ${req.url.split('?')[1]}`);
  const query = queryString.parse(req.url.split('?')[1]);
  if (!query.prefix) throw new Error("'prefix' not defined in request");
  const datanameParts = splitPrefixIntoParts(query.prefix);
  const info = {parts: datanameParts};
  if (query.type && query.type !== "tree") { // "tree" is deprecated
    info.dataType = query.type;
  } else {
    info.dataType = "dataset";
  }

  return info;
};

/**
 * Given a request, does the dataset exist?
 * In the future, if there is no exact match but a partial one we
 * should extend this. E.g. `["flu"]` -> `["flu", "h3n2", "ha", "3y"]`
 * In that case, we should utilise `res.redirect` as we do in the nextstrain.org server
 * @throws
 */
const extendDataPathsToMatchAvailable = (info, availableDatasets) => {
  const requestStrToMatch = info.parts.join("/"); // TO DO
  /* TODO currently there must be an _exact_ match in the available datasets */
  if (!availableDatasets.map((d) => d.request).includes(requestStrToMatch)) {
    throw new Error(`${requestStrToMatch} not in available datasets`);
  }
  /* what we want to do is modify `info.parts` to match the available dataset, if possible */
};

/**
 * sets info.address.
 * if we need v1 datasets then `info.address` will be an object with `meta`
 * and `tree` keys. Otherwise `info.address` will be a string of the fetch
 * path.
 * @sideEffect sets `info.address` {Object | string}
 * @throws
 */
const makeFetchAddresses = (info, datasetsPath, availableDatasets) => {
  if (info.dataType !== "dataset") {
    info.address = path.join(
      datasetsPath,
      `${info.parts.join("_")}_${info.dataType}.json`
    );
  } else {
    const requestStr = info.parts.join("/"); // TO DO
    const availableInfo = availableDatasets.filter((d) => d.request === requestStr)[0];
    if (availableInfo.v2) {
      info.address = path.join(datasetsPath, `${info.parts.join("_")}.json`);
    } else {
      info.address = {
        meta: path.join(datasetsPath, `${info.parts.join("_")}_meta.json`),
        tree: path.join(datasetsPath, `${info.parts.join("_")}_tree.json`)
      };
    }
  }
};

const sendJson = async (res, info) => {
  if (typeof info.address === "string") {
    /* In general, JSONs are designed such that no server modifications
    are needed by the server. This allows us to read as a stream and
    stream the response */
    const readStream = fs.createReadStream(info.address);
    readStream.on('open', () => {
      readStream.pipe(res);
    });
    readStream.on('error', (err) => {
      utils.warn(`Failed to read ${info.address}`);
      utils.verbose(err);
      res.sendStatus(404);
    });
  } else {
    /* v1 JSONs require modification to the JSON data (i.e. conversion
    into a v2 JSON!). This requires us to read both (v1) JSONs
    into memory */
    const meta = await utils.readFilePromise(info.address.meta);
    const tree = await utils.readFilePromise(info.address.tree);
    const v2Json = convertFromV1({tree, meta});
    return res.json(v2Json);
  }
};

/**
 * Return a subset of `availableDatasetUrls` which we deem to be suitable
 * candidates to make a second tree.
 * The current logic is to include all datasets which
 * (a) contain the same first "part" of the URL -- interpreted here to represent the same pathogen
 * (b) have the same number of "parts" in the URL
 * (c) differ from the `currentDatasetUrl` by only 1 part
 * Note: the "parts" of the URL are formed by splitting it on `"/"`
 */
const findAvailableSecondTreeOptions = (currentDatasetUrl, availableDatasetUrls) => {
  const currentDatasetUrlArr = currentDatasetUrl.split('/');

  const availableTangleTreeOptions = availableDatasetUrls.filter((datasetUrl) => {
    const datasetUrlArr = datasetUrl.split('/');
    // Do not return the same dataset
    if (currentDatasetUrl === datasetUrl) return null;

    // Do not return dataset if the URLs have different number of parameters
    if (currentDatasetUrlArr.length !== datasetUrlArr.length) return null;

    // Do not return dataset if different pathogens
    if (currentDatasetUrlArr[0] !== datasetUrlArr[0]) return null;

    // Find differences between the two dataset URLs
    const urlDifferences = currentDatasetUrlArr.filter((param, index) => {
      if (datasetUrlArr[index] !== param) {
        return param;
      }
      return null;
    });

    // Do not return dataset if more than one parameter is different
    if (urlDifferences.length > 1) return null;

    return datasetUrl;
  });

  return availableTangleTreeOptions;
};

module.exports = {
  interpretRequest,
  extendDataPathsToMatchAvailable,
  makeFetchAddresses,
  handleError,
  sendJson,
  findAvailableSecondTreeOptions
};
<commit_msg>Added application/json content-type to v2 dataset responses<commit_after>/*
* basically just the functions which will be improved when we move to the new server API
*
* Note that a lot of this code is replicated in the nextstrain.org repo
* and it could instead be exposed by "auspice" (and imported by the nextstrain.org repo)
* Note also https://github.com/nextstrain/auspice/issues/687 which proposes
* changing the server-client API
*
*/

const utils = require("../utils");
const queryString = require("query-string");
const path = require("path");
const convertFromV1 = require("./convertJsonSchemas").convertFromV1;
const fs = require("fs");

const handleError = (res, clientMsg, serverMsg="") => {
  res.statusMessage = clientMsg;
  utils.warn(`${clientMsg} -- ${serverMsg}`);
  return res.status(500).end();
};

const splitPrefixIntoParts = (url) => url
  .replace(/^\//, '')
  .replace(/\/$/, '')
  .split("/");

/**
 * Basic interpretation of an auspice request
 * @returns {Object} keys: `dataType`, `parts`
 */
const interpretRequest = (req) => {
  utils.log(`GET DATASET query received: ${req.url.split('?')[1]}`);
  const query = queryString.parse(req.url.split('?')[1]);
  if (!query.prefix) throw new Error("'prefix' not defined in request");
  const datanameParts = splitPrefixIntoParts(query.prefix);
  const info = {parts: datanameParts};
  if (query.type && query.type !== "tree") { // "tree" is deprecated
    info.dataType = query.type;
  } else {
    info.dataType = "dataset";
  }

  return info;
};

/**
 * Given a request, does the dataset exist?
 * In the future, if there is no exact match but a partial one we
 * should extend this. E.g. `["flu"]` -> `["flu", "h3n2", "ha", "3y"]`
 * In that case, we should utilise `res.redirect` as we do in the nextstrain.org server
 * @throws
 */
const extendDataPathsToMatchAvailable = (info, availableDatasets) => {
  const requestStrToMatch = info.parts.join("/"); // TO DO
  /* TODO currently there must be an _exact_ match in the available datasets */
  if (!availableDatasets.map((d) => d.request).includes(requestStrToMatch)) {
    throw new Error(`${requestStrToMatch} not in available datasets`);
  }
  /* what we want to do is modify `info.parts` to match the available dataset, if possible */
};

/**
 * sets info.address.
 * if we need v1 datasets then `info.address` will be an object with `meta`
 * and `tree` keys. Otherwise `info.address` will be a string of the fetch
 * path.
 * @sideEffect sets `info.address` {Object | string}
 * @throws
 */
const makeFetchAddresses = (info, datasetsPath, availableDatasets) => {
  if (info.dataType !== "dataset") {
    info.address = path.join(
      datasetsPath,
      `${info.parts.join("_")}_${info.dataType}.json`
    );
  } else {
    const requestStr = info.parts.join("/"); // TO DO
    const availableInfo = availableDatasets.filter((d) => d.request === requestStr)[0];
    if (availableInfo.v2) {
      info.address = path.join(datasetsPath, `${info.parts.join("_")}.json`);
    } else {
      info.address = {
        meta: path.join(datasetsPath, `${info.parts.join("_")}_meta.json`),
        tree: path.join(datasetsPath, `${info.parts.join("_")}_tree.json`)
      };
    }
  }
};

const sendJson = async (res, info) => {
  if (typeof info.address === "string") {
    /* In general, JSONs are designed such that no server modifications
    are needed by the server. This allows us to read as a stream and
    stream the response */
    const readStream = fs.createReadStream(info.address);
    readStream.on('open', () => {
      res.set('Content-Type', 'application/json');
      readStream.pipe(res);
    });
    readStream.on('error', (err) => {
      utils.warn(`Failed to read ${info.address}`);
      utils.verbose(err);
      res.sendStatus(404);
    });
  } else {
    /* v1 JSONs require modification to the JSON data (i.e. conversion
    into a v2 JSON!). This requires us to read both (v1) JSONs
    into memory */
    const meta = await utils.readFilePromise(info.address.meta);
    const tree = await utils.readFilePromise(info.address.tree);
    const v2Json = convertFromV1({tree, meta});
    return res.json(v2Json);
  }
};

/**
 * Return a subset of `availableDatasetUrls` which we deem to be suitable
 * candidates to make a second tree.
 * The current logic is to include all datasets which
 * (a) contain the same first "part" of the URL -- interpreted here to represent the same pathogen
 * (b) have the same number of "parts" in the URL
 * (c) differ from the `currentDatasetUrl` by only 1 part
 * Note: the "parts" of the URL are formed by splitting it on `"/"`
 */
const findAvailableSecondTreeOptions = (currentDatasetUrl, availableDatasetUrls) => {
  const currentDatasetUrlArr = currentDatasetUrl.split('/');

  const availableTangleTreeOptions = availableDatasetUrls.filter((datasetUrl) => {
    const datasetUrlArr = datasetUrl.split('/');
    // Do not return the same dataset
    if (currentDatasetUrl === datasetUrl) return null;

    // Do not return dataset if the URLs have different number of parameters
    if (currentDatasetUrlArr.length !== datasetUrlArr.length) return null;

    // Do not return dataset if different pathogens
    if (currentDatasetUrlArr[0] !== datasetUrlArr[0]) return null;

    // Find differences between the two dataset URLs
    const urlDifferences = currentDatasetUrlArr.filter((param, index) => {
      if (datasetUrlArr[index] !== param) {
        return param;
      }
      return null;
    });

    // Do not return dataset if more than one parameter is different
    if (urlDifferences.length > 1) return null;

    return datasetUrl;
  });

  return availableTangleTreeOptions;
};

module.exports = {
  interpretRequest,
  extendDataPathsToMatchAvailable,
  makeFetchAddresses,
  handleError,
  sendJson,
  findAvailableSecondTreeOptions
};
<|endoftext|>


<commit_before>var _ = require("lib")._;
var Backbone = require("lib").Backbone;

var utils = require("utils");

var CodeView = Backbone.View.extend({

    initialize: function(options) {
        this.options = options;
        this.domId = "code-editor-{0}".format(utils.getUniqueId());
        var div = $("<div>").attr({
            "id": this.domId,
            "class": "code-editor"
        });
        this.$el.append(div);
    },

    render: function() {
        this.editor = ace.edit(this.domId);
        //this.editor.setTheme("ace/theme/chrome");
        this.editor.getSession().setMode("ace/mode/python");
        this.editor.setValue(this.options.code || "");
        this.editor.setShowPrintMargin(false);
        window.editor = this.editor;

        if(this.options.listenToInputChange) {
            this.listenToInputChange();
        }
        return this;
    },

    listenToInputChange: function() {
        var self = this;
        this.editor.on("input", function() {
            self.trigger("change", self.val());
        });
    },

    val: function() {
        return this.editor.getValue();
    },

    remove: function() {
        this.editor.off();
        Backbone.View.prototype.remove.call(this);
    }
});

module.exports = {
    CodeView: CodeView
};<commit_msg>Code Quiz Ace Editor: Fix warning.<commit_after>var _ = require("lib")._;
var Backbone = require("lib").Backbone;

var utils = require("utils");

var CodeView = Backbone.View.extend({

    initialize: function(options) {
        this.options = options;
        this.domId = "code-editor-{0}".format(utils.getUniqueId());
        var div = $("<div>").attr({
            "id": this.domId,
            "class": "code-editor"
        });
        this.$el.append(div);
    },

    render: function() {
        this.editor = ace.edit(this.domId);
        this.editor.$blockScrolling = Infinity;
        this.editor.getSession().setMode("ace/mode/python");
        this.editor.setValue(this.options.code || "");
        this.editor.setShowPrintMargin(false);

        window.editor = this.editor;

        if(this.options.listenToInputChange) {
            this.listenToInputChange();
        }
        return this;
    },

    listenToInputChange: function() {
        var self = this;
        this.editor.on("input", function() {
            self.trigger("change", self.val());
        });
    },

    val: function() {
        return this.editor.getValue();
    },

    remove: function() {
        this.editor.off();
        Backbone.View.prototype.remove.call(this);
    }
});

module.exports = {
    CodeView: CodeView
};<|endoftext|>


<commit_before>"use strict";

angular.module('swot').directive('ckedit', function ($parse) {
    CKEDITOR.disableAutoInline = true;
    var counter = 0,
    prefix = '__ckd_';

    return {
        restrict: 'A',
        link: function (scope, element, attrs, controller) {
            var getter = $parse(attrs.ckedit),
                setter = getter.assign;

            attrs.$set('contenteditable', true); // inline ckeditor needs this
            if (!attrs.id) {
                attrs.$set('id', prefix + (++counter));
            }

            // CKEditor stuff
            // Override the normal CKEditor save plugin

            CKEDITOR.plugins.registered['save'] =
            {
                init: function (editor) {
                    editor.addCommand('save',
                        {
                            modes: { wysiwyg: 1, source: 1 },
                            exec: function (editor) {
                                if (editor.checkDirty()) {
                                    var ckValue = editor.getData();
                                    scope.$apply(function () {
                                        setter(scope, ckValue);
                                    });
                                    ckValue = null;
                                    editor.resetDirty();
                                }
                            }
                        }
                    );
                    editor.ui.addButton('Save', { label: 'Save', command: 'save', toolbar: 'document' });
                }
            };
            var options = {};
            options.on = {
                blur: function (e) {
                    if (e.editor.checkDirty()) {
                        var ckValue = e.editor.getData();
                        scope.$apply(function () {
                            setter(scope, ckValue);
                        });
                        ckValue = null;
                        e.editor.resetDirty();
                    }
                }
            };
            //options.extraPlugins = 'sourcedialog';
            //options.removePlugins = 'sourcearea';
            var editorangular = CKEDITOR.inline(element[0], options); //invoke

            scope.$watch(attrs.ckedit, function (value) {
                editorangular.setData(value);
            });
        }
    }

});
<commit_msg>Edit Quiz: Remove useless tooltip when hovering over questions<commit_after>"use strict";

angular.module('swot').directive('ckedit', function ($parse) {
    CKEDITOR.disableAutoInline = true;
    var counter = 0,
    prefix = '__ckd_';

    return {
        restrict: 'A',
        link: function (scope, element, attrs, controller) {
            var getter = $parse(attrs.ckedit),
                setter = getter.assign;

            attrs.$set('contenteditable', true); // inline ckeditor needs this
            if (!attrs.id) {
                attrs.$set('id', prefix + (++counter));
            }

            // CKEditor stuff
            // Override the normal CKEditor save plugin

            CKEDITOR.plugins.registered['save'] =
            {
                init: function (editor) {
                    editor.addCommand('save',
                        {
                            modes: { wysiwyg: 1, source: 1 },
                            exec: function (editor) {
                                if (editor.checkDirty()) {
                                    var ckValue = editor.getData();
                                    scope.$apply(function () {
                                        setter(scope, ckValue);
                                    });
                                    ckValue = null;
                                    editor.resetDirty();
                                }
                            }
                        }
                    );
                    editor.ui.addButton('Save', { label: 'Save', command: 'save', toolbar: 'document' });
                }
            };
            var options = {};
            options.on = {
                blur: function (e) {
                    if (e.editor.checkDirty()) {
                        var ckValue = e.editor.getData();
                        scope.$apply(function () {
                            setter(scope, ckValue);
                        });
                        ckValue = null;
                        e.editor.resetDirty();
                    }
                }
            };
            //options.extraPlugins = 'sourcedialog';
            //options.removePlugins = 'sourcearea';
            options.title = false;
            var editorangular = CKEDITOR.inline(element[0], options); //invoke

            scope.$watch(attrs.ckedit, function (value) {
                editorangular.setData(value);
            });
        }
    }

});
<|endoftext|>


<commit_before>var NUMBER_OF_TRIES = 3;
var POINTS = [];

$(document).ready(function (){
	$("#score").hide();
	$("#play").hide();
	// Loads levels data
	POINTS[0] = [30, 370];
	$.ajax({
    	type: "GET",
    	url: "http://127.0.0.1:1234/get_levels",
    	success: function(data) {
    		var output = '';
    		$.each(data.levels, function(index, element){
    			var rgbval = element.r + "," + element.g + "," + element.b;
    			output += "

 Score : " + element.score + "

";
    		});
      		$('#levels').html(output);
    	},
    	error: function(jqXHR, textStatus, errorThrown){
    		alert("An error occured. Please refresh your page.\nMaybe the server is down.")
    		console.log(errorThrown);
    	}
  	});

	$("#playImage").click(function (event){
		pos_x = event.offsetX?(event.offsetX):event.pageX - $("#playImage").offsetLeft;
		pos_y = event.offsetY?(event.offsetY):event.pageY - $("#playImage").offsetTop;

		if(NUMBER_OF_TRIES == 1){
			POINTS[3] = [pos_x, pos_y];
			drawPointer(pos_x, pos_y);
			drawLine(POINTS[2], POINTS[3]);
			POINTS[4] = [570, 30];
			drawLine(POINTS[3], POINTS[4]);
			NUMBER_OF_TRIES--;
			submitPoints();
		}

		if(NUMBER_OF_TRIES == 2){
			POINTS[2] = [pos_x, pos_y];
			drawPointer(pos_x, pos_y);
			drawLine(POINTS[1], POINTS[2]);
			NUMBER_OF_TRIES--;
		}

		if(NUMBER_OF_TRIES == 3){
			POINTS[1] = [pos_x, pos_y];
			drawPointer(pos_x, pos_y);
			drawLine(POINTS[0], POINTS[1]);
			NUMBER_OF_TRIES--;
		}

	});

});

function fadeToHome(){
	$("#tutorial").fadeOut();
}

function chooseLevel(elem){
	$("#score").hide();
	elem = $(elem);
	level_id = elem.attr("id");
	elem.addClass("selected");
	elem.siblings().removeClass("selected");
	var canvas = document.getElementById("playImage");
	var context = canvas.getContext('2d');
	var imageObj = new Image();
	imageObj.src = "http://127.0.0.1:1234/level/" + level_id;
	context.drawImage(imageObj, 0, 0);
	//Image drawn

	context.beginPath();
    context.arc(30, 370, 25, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgb(92, 196, 196)';
    context.fill();
    context.lineWidth = 20;
    context.strokeStyle = '#000000';
    context.stroke();
    context.closePath();

    context.beginPath();
    context.arc(570, 30, 25, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgb(92, 196, 196)';
    context.fill();
    context.lineWidth = 20;
    context.strokeStyle = '#000000';
    context.stroke();
    context.closePath();
	// Stage setup ok

	// ct = new ColorThief();
	// playImage = $("#playImage");
	// var domColor = ct.getColor(playImage);
	// console.log(domColor);
	// Generate color in html format
	var color = $(".selected .levelHigh").css("background-color");
	console.log(color);
	var info = "Stick to

";
	// console.log(info);
	$("#playInfo").html(info);
	$("#play").show();
	NUMBER_OF_TRIES = 3;
	// Color info set
}

function getCoord(event){
	pos_x = event.offsetX?(event.offsetX):event.pageX - $("#playImage").offsetLeft;
	pos_y = event.offsetY?(event.offsetY):event.pageY - $("#playImage").offsetTop;

	console.log("x : " + pos_x);
	console.log("y : " + pos_y);
}

function drawPointer(x, y){
	var canvas = document.getElementById("playImage");
	var context = canvas.getContext('2d');
	context.beginPath();
    context.arc(x, y, 10, 0, 2 * Math.PI, false);
    context.fillStyle = 'black';
    context.fill();
    context.lineWidth = 10;
    context.strokeStyle = '#000000';
    context.stroke();
    context.closePath();
}

function drawLine(a, b){
	var canvas = document.getElementById("playImage");
	var context = canvas.getContext('2d');
	context.beginPath();
	context.moveTo(a[0], a[1]);
	context.lineTo(b[0], b[1]);
	context.lineWidth = 6;
	context.stroke();
	context.closePath();
}

function submitPoints(){

	var level = $(".selected").attr("id");
	var points = POINTS[0][0] + " " + POINTS[0][1] + " " + POINTS[1][0] + " " + POINTS[1][1] + " " + POINTS[2][0] + " " + POINTS[2][1] + " " + POINTS[3][0] + " " + POINTS[3][1] + " " + POINTS[4][0] + " " + POINTS[4][1];
	console.log(points);
	inputs = {
		"level": level,
		"points": points
	};
	console.log(inputs);

	$.ajax({
		type: "POST",
		url: "http://127.0.0.1:1234/submit",
		data: inputs,
		success: function(result){
			console.log(result);
		},
		error: function(jqXHR, textStatus, errorThrown){
			console.log(textStatus);
		}
	});

	$("#score").show();
}<commit_msg>Attach score listener<commit_after>var NUMBER_OF_TRIES = 3;
var POINTS = [];

$(document).ready(function (){
	$("#score").hide();
	$("#play").hide();
	// Loads levels data
	POINTS[0] = [30, 370];
	$.ajax({
    	type: "GET",
    	url: "http://127.0.0.1:1234/get_levels",
    	success: function(data) {
    		var output = '';
    		$.each(data.levels, function(index, element){
    			var rgbval = element.r + "," + element.g + "," + element.b;
    			output += "

 Score : " + element.score + "

";
    		});
      		$('#levels').html(output);
    	},
    	error: function(jqXHR, textStatus, errorThrown){
    		alert("An error occured. Please refresh your page.\nMaybe the server is down.")
    		console.log(errorThrown);
    	}
  	});

	$("#playImage").click(function (event){
		pos_x = event.offsetX?(event.offsetX):event.pageX - $("#playImage").offsetLeft;
		pos_y = event.offsetY?(event.offsetY):event.pageY - $("#playImage").offsetTop;

		if(NUMBER_OF_TRIES == 1){
			POINTS[3] = [pos_x, pos_y];
			drawPointer(pos_x, pos_y);
			drawLine(POINTS[2], POINTS[3]);
			POINTS[4] = [570, 30];
			drawLine(POINTS[3], POINTS[4]);
			NUMBER_OF_TRIES--;
			submitPoints();
		}

		if(NUMBER_OF_TRIES == 2){
			POINTS[2] = [pos_x, pos_y];
			drawPointer(pos_x, pos_y);
			drawLine(POINTS[1], POINTS[2]);
			NUMBER_OF_TRIES--;
		}

		if(NUMBER_OF_TRIES == 3){
			POINTS[1] = [pos_x, pos_y];
			drawPointer(pos_x, pos_y);
			drawLine(POINTS[0], POINTS[1]);
			NUMBER_OF_TRIES--;
		}

	});

});

function fadeToHome(){
	$("#tutorial").fadeOut();
}

function chooseLevel(elem){
	$("#score").hide();
	elem = $(elem);
	level_id = elem.attr("id");
	elem.addClass("selected");
	elem.siblings().removeClass("selected");
	var canvas = document.getElementById("playImage");
	var context = canvas.getContext('2d');
	var imageObj = new Image();
	imageObj.src = "http://127.0.0.1:1234/level/" + level_id;
	context.drawImage(imageObj, 0, 0);
	//Image drawn

	context.beginPath();
    context.arc(30, 370, 25, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgb(92, 196, 196)';
    context.fill();
    context.lineWidth = 20;
    context.strokeStyle = '#000000';
    context.stroke();
    context.closePath();

    context.beginPath();
    context.arc(570, 30, 25, 0, 2 * Math.PI, false);
    context.fillStyle = 'rgb(92, 196, 196)';
    context.fill();
    context.lineWidth = 20;
    context.strokeStyle = '#000000';
    context.stroke();
    context.closePath();
	// Stage setup ok

	// ct = new ColorThief();
	// playImage = $("#playImage");
	// var domColor = ct.getColor(playImage);
	// console.log(domColor);
	// Generate color in html format
	var color = $(".selected .levelHigh").css("background-color");
	console.log(color);
	var info = "Stick to

";
	// console.log(info);
	$("#playInfo").html(info);
	$("#play").show();
	NUMBER_OF_TRIES = 3;
	// Color info set
}

function getCoord(event){
	pos_x = event.offsetX?(event.offsetX):event.pageX - $("#playImage").offsetLeft;
	pos_y = event.offsetY?(event.offsetY):event.pageY - $("#playImage").offsetTop;

	console.log("x : " + pos_x);
	console.log("y : " + pos_y);
}

function drawPointer(x, y){
	var canvas = document.getElementById("playImage");
	var context = canvas.getContext('2d');
	context.beginPath();
    context.arc(x, y, 10, 0, 2 * Math.PI, false);
    context.fillStyle = 'black';
    context.fill();
    context.lineWidth = 10;
    context.strokeStyle = '#000000';
    context.stroke();
    context.closePath();
}

function drawLine(a, b){
	var canvas = document.getElementById("playImage");
	var context = canvas.getContext('2d');
	context.beginPath();
	context.moveTo(a[0], a[1]);
	context.lineTo(b[0], b[1]);
	context.lineWidth = 6;
	context.stroke();
	context.closePath();
}

function submitPoints(){

	var level = $(".selected").attr("id");
	var points = POINTS[0][0] + " " + POINTS[0][1] + " " + POINTS[1][0] + " " + POINTS[1][1] + " " + POINTS[2][0] + " " + POINTS[2][1] + " " + POINTS[3][0] + " " + POINTS[3][1] + " " + POINTS[4][0] + " " + POINTS[4][1];
	console.log(points);
	inputs = {
		"level": level,
		"points": points
	};
	console.log(inputs);

	$.ajax({
		type: "POST",
		url: "http://127.0.0.1:1234/submit",
		data: inputs,
		success: function(result){
			$("#show").html("Score : " + result);
		},
		error: function(jqXHR, textStatus, errorThrown){
			console.log(textStatus);
		}
	});

	$("#score").show();
}<|endoftext|>


<commit_before>'use strict';

let spawn = require( 'child_process' ).spawnSync
const format = require('fmt-obj')  // https://github.com/queckezz/fmt-obj

function prt(cmd, verbose=true) {
  let result = {}

  if (cmd.stderr == null) {
    if (verbose)
      result.stderr = null
  }
  else
      if (cmd.stderr.length == 0) {
        if (verbose)
          result.stderr = cmd.stderr.toString().trim()
      }
      else
        result.stderr = cmd.stderr.toString().trim()

  if (cmd.stdout == null) {
    if (verbose)
      result.stdout = null
  }
  else
      if (cmd.stdout.length == 0) {
        if (verbose)
          result.stdout = cmd.stdout.toString().trim()
      }
      else
        result.stdout = cmd.stdout.toString().trim()

  return result
}

function cmd_was_run(cmd) {
  return (cmd.stderr != null &&
          cmd.stdout != null )
}

class Base {
  constructor(path) {
    this.path = path
    this.result_shell_ls
    this.result_shell_version
    this.result_shell_file_size
    this.version
    this.size
    this.warnings = []
    this.interpret_stderr_as_stdout_for_getting_version_info = false  // subclass to set if needed
    this.report_obj = {}
  }

  get exists() {
    return this.valid(this.result_shell_ls)
  }

  get runs_ok() {
    return this.valid(this.result_shell_version)
  }

  valid(result_shell_obj) {
    if (! cmd_was_run(result_shell_obj))
      return false

    let accept_stderr_msg_as_valid = result_shell_obj.args[1] == "--version" &&
                                     this.interpret_stderr_as_stdout_for_getting_version_info

    if (accept_stderr_msg_as_valid)
      return result_shell_obj.stderr.length > 0
    else
      return result_shell_obj.stderr.length == 0
  }

  analyse_exe_empty() {
    const regex = /^\s+(\d+)\s{1}\//

    let match = regex.exec(this.result_shell_file_size.stdout.toString())  // match things like "     281 /usr/local/bin/pip"
    if (match != null)
      this.size = parseInt(match[1])
  }

  analyse() {
    this.result_shell_ls = spawn('ls', ['-lh', this.path])
    this.result_shell_version = spawn(this.path, ['--version'])
    this.result_shell_file_size = spawn('wc', ['-c', this.path])

    if (this.exists && this.runs_ok) {
      this.analyse_version()  // template pattern - method declared in subclass
      if (this.version == undefined) this.warnings.push(`version could not be determined`)
    }

    if (this.exists && ! this.runs_ok) {
      this.analyse_exe_empty()
      if (this.size == undefined) this.warnings.push(`could not determine file size`)
      if (this.size == 0) this.warnings.push(`executable file exists but is empty?`)
    }

    // if (! this.exists) this.warnings.push(`${this.path} executable doesn't exist`)
    if (this.exists && ! this.runs_ok) this.warnings.push(`${this.path} doesn't run properly`)
  }

  report() {
    this.report_obj = {}
    this.report_obj.path = this.path
    this.report_obj['executable exists'] = this.exists
    if (this.exists) {
      this.report_obj.runs_ok = this.runs_ok
      this.report_obj.version = this.version
    }
    if (this.warnings.length > 0) {
      this.report_obj.warnings = this.warnings
      // if verbose
      this.report_obj['shell results'] = {}
      if (cmd_was_run(this.result_shell_ls))
        this.report_obj['shell results']['ls -l'] = prt(this.result_shell_ls)
      if (cmd_was_run(this.result_shell_version))
        this.report_obj['shell results']['--version'] = prt(this.result_shell_version)
      if (cmd_was_run(this.result_shell_file_size))
        this.report_obj['shell results']['wc -c'] = prt(this.result_shell_file_size)
    }
  }

}

class Python extends Base {
  constructor(path) {
    super(path)
    this.interpret_stderr_as_stdout_for_getting_version_info = true  // cope with python 2 bug which reports python version via stderr rather than stdout
    this.result_shell_site_info
    this.sys_path = []
    this.analyse()
  }

  analyse() {
    super.analyse()
    this.result_shell_site_info = spawn( this.path, [ '-m', 'site' ] )
    this.parse_site_info()
  }

  analyse_version() {
    const regex = /Python (.*)/

    let match = regex.exec(this.result_shell_version.stderr.toString())  // note: python 2 reports python version via stderr rather than stdout
    if (match != null)
      this.version = match[1]
  }

  parse_site_info() {
    if (! this.valid(this.result_shell_site_info))
      return

    let lines = this.result_shell_site_info.stdout.toString().split("\n")
    let scan = false
    let chunk = ''

    for (let line of lines) {
      if (line == 'sys.path = [') {
        chunk = '['
        scan = true
        continue
      }
      if (scan)
        chunk += line
      if (line == ']')
        scan = false
    }

    function eval_local(chunk){
      "use strict"
      let sys_path = eval(`let x = ${chunk} ; x`);
      return sys_path
    }

    this.sys_path = eval_local(chunk)  // idea from http://stackoverflow.com/questions/9781285/specify-scope-for-eval-in-javascript
  }

  report() {
    super.report()
    if (this.runs_ok)
      this.report_obj['sys.path'] = `${this.sys_path.length} entries`
  }
}

class Pip extends Base {
  constructor(path) {
    super(path);
    this.site_package_path
    this.pythons = []
    this.analyse()
  }

  analyse() {
    super.analyse()
  }

  analyse_version() {
    const regex = /pip (.*) from (.*)\/site-packages/
    // const regex2 = /^\/Library\//

    let match = regex.exec(this.result_shell_version.stdout.toString())
    if (match != null) {
      this.version = match[1]
      this.site_package_path = match[2] + '/site-packages'
    }

    // The directory
    //   /Library/Python/2.7/site-packages
    // used to be used by both system python AND python org python
    // but as of python 2.7.13 is only used by mac system python - NOT python org python anymore cos of incompatibilities
    //
    // let match2 = regex2.exec(this.site_package_path)
    // this.site_package_path_is_non_system_python = (match != null) {
  }

  inform_about(python) {
    this.pythons.push(python)
  }

  report() {
    super.report()
    this.report_obj.site = this.site_package_path

    this.report_obj.associations = {}
    for (let python of this.pythons) {
      let pip_and_python_share_a_site = false
      if (! python.exists)
        pip_and_python_share_a_site = 'N/A'
      else
        pip_and_python_share_a_site = python.sys_path.length > 0 && python.sys_path.indexOf(this.site_package_path) >= 0
      this.report_obj.associations[python.path] = pip_and_python_share_a_site
    }
  }
}

let python_usr_bin = new Python('/usr/bin/python')
let python_usr_local_bin = new Python('/usr/local/bin/python')
let pip_usr_local_bin = new Pip('/usr/local/bin/pip')
pip_usr_local_bin.inform_about(python_usr_bin)
pip_usr_local_bin.inform_about(python_usr_local_bin)

python_usr_bin.report()
python_usr_local_bin.report()
pip_usr_local_bin.report()
let report = {
  'Python System Mac': python_usr_bin.report_obj,
  'Python Other': python_usr_local_bin.report_obj,
  'Pip': pip_usr_local_bin.report_obj
}
console.log(format(report))

console.log('DONE ')
<commit_msg>improved analyse_is_exe_empty logic<commit_after>'use strict';

let spawn = require( 'child_process' ).spawnSync
const format = require('fmt-obj')  // https://github.com/queckezz/fmt-obj

function prt(cmd, verbose=true) {
  let result = {}

  if (cmd.stderr == null) {
    if (verbose)
      result.stderr = null
  }
  else
      if (cmd.stderr.length == 0) {
        if (verbose)
          result.stderr = cmd.stderr.toString().trim()
      }
      else
        result.stderr = cmd.stderr.toString().trim()

  if (cmd.stdout == null) {
    if (verbose)
      result.stdout = null
  }
  else
      if (cmd.stdout.length == 0) {
        if (verbose)
          result.stdout = cmd.stdout.toString().trim()
      }
      else
        result.stdout = cmd.stdout.toString().trim()

  return result
}

function cmd_was_run(cmd) {
  return (cmd.stderr != null &&
          cmd.stdout != null )
}

class Base {
  constructor(path) {
    this.path = path
    this.result_shell_ls
    this.result_shell_version
    this.result_shell_file_size
    this.version
    this.size
    this.warnings = []
    this.interpret_stderr_as_stdout_for_getting_version_info = false  // subclass to set if needed
    this.report_obj = {}
  }

  get exists() {
    return this.valid(this.result_shell_ls)
  }

  get runs_ok() {
    return this.valid(this.result_shell_version)
  }

  valid(result_shell_obj) {
    if (! cmd_was_run(result_shell_obj))
      return false

    let accept_stderr_msg_as_valid = result_shell_obj.args[1] == "--version" &&
                                     this.interpret_stderr_as_stdout_for_getting_version_info

    if (accept_stderr_msg_as_valid)
      return result_shell_obj.stderr.length > 0
    else
      return result_shell_obj.stderr.length == 0
  }

  analyse_is_exe_empty() {
    const regex = /^\s+(\d+)\s{1}\//

    let match = regex.exec(this.result_shell_file_size.stdout.toString())  // match things like "     281 /usr/local/bin/pip"
    if (match != null)
      this.size = parseInt(match[1])
  }

  analyse() {
    this.result_shell_ls = spawn('ls', ['-lh', this.path])
    this.result_shell_version = spawn(this.path, ['--version'])
    this.result_shell_file_size = spawn('wc', ['-c', this.path])

    if (this.exists) {
      this.analyse_is_exe_empty()
      this.analyse_version()  // template pattern - method declared in subclass

      if (this.version == undefined) this.warnings.push(`version could not be determined`)
      if (this.size == undefined) this.warnings.push(`could not determine file size`)
      if (this.size == 0) this.warnings.push(`executable file exists but is empty?`)
    }
    if (this.exists && ! this.runs_ok) this.warnings.push(`${this.path} doesn't run properly`)
  }

  report() {
    this.report_obj = {}
    this.report_obj.path = this.path
    this.report_obj['executable exists'] = this.exists
    if (this.exists) {
      this.report_obj.runs_ok = this.runs_ok
      this.report_obj.version = this.version
    }
    if (this.warnings.length > 0) {
      this.report_obj.warnings = this.warnings
      // if verbose
      this.report_obj['shell results'] = {}
      if (cmd_was_run(this.result_shell_ls))
        this.report_obj['shell results']['ls -l'] = prt(this.result_shell_ls)
      if (cmd_was_run(this.result_shell_version))
        this.report_obj['shell results']['--version'] = prt(this.result_shell_version)
      if (cmd_was_run(this.result_shell_file_size))
        this.report_obj['shell results']['wc -c'] = prt(this.result_shell_file_size)
    }
  }

}

class Python extends Base {
  constructor(path) {
    super(path)
    this.interpret_stderr_as_stdout_for_getting_version_info = true  // cope with python 2 bug which reports python version via stderr rather than stdout
    this.result_shell_site_info
    this.sys_path = []
    this.analyse()
  }

  analyse() {
    super.analyse()
    this.result_shell_site_info = spawn( this.path, [ '-m', 'site' ] )
    this.parse_site_info()
  }

  analyse_version() {
    const regex = /Python (.*)/

    let match = regex.exec(this.result_shell_version.stderr.toString())  // note: python 2 reports python version via stderr rather than stdout
    if (match != null)
      this.version = match[1]
  }

  parse_site_info() {
    if (! this.valid(this.result_shell_site_info))
      return

    let lines = this.result_shell_site_info.stdout.toString().split("\n")
    let scan = false
    let chunk = ''

    for (let line of lines) {
      if (line == 'sys.path = [') {
        chunk = '['
        scan = true
        continue
      }
      if (scan)
        chunk += line
      if (line == ']')
        scan = false
    }

    function eval_local(chunk){
      "use strict"
      let sys_path = eval(`let x = ${chunk} ; x`);
      return sys_path
    }

    this.sys_path = eval_local(chunk)  // idea from http://stackoverflow.com/questions/9781285/specify-scope-for-eval-in-javascript
  }

  report() {
    super.report()
    if (this.runs_ok)
      this.report_obj['sys.path'] = `${this.sys_path.length} entries`
  }
}

class Pip extends Base {
  constructor(path) {
    super(path);
    this.site_package_path
    this.pythons = []
    this.analyse()
  }

  analyse() {
    super.analyse()
  }

  analyse_version() {
    const regex = /pip (.*) from (.*)\/site-packages/
    // const regex2 = /^\/Library\//

    let match = regex.exec(this.result_shell_version.stdout.toString())
    if (match != null) {
      this.version = match[1]
      this.site_package_path = match[2] + '/site-packages'
    }

    // The directory
    //   /Library/Python/2.7/site-packages
    // used to be used by both system python AND python org python
    // but as of python 2.7.13 is only used by mac system python - NOT python org python anymore cos of incompatibilities
    //
    // let match2 = regex2.exec(this.site_package_path)
    // this.site_package_path_is_non_system_python = (match != null) {
  }

  inform_about(python) {
    this.pythons.push(python)
  }

  report() {
    super.report()
    this.report_obj.site = this.site_package_path

    this.report_obj.associations = {}
    for (let python of this.pythons) {
      let pip_and_python_share_a_site = false
      if (! python.exists)
        pip_and_python_share_a_site = 'N/A'
      else
        pip_and_python_share_a_site = python.sys_path.length > 0 && python.sys_path.indexOf(this.site_package_path) >= 0
      this.report_obj.associations[python.path] = pip_and_python_share_a_site
    }
  }
}

let python_usr_bin = new Python('/usr/bin/python')
let python_usr_local_bin = new Python('/usr/local/bin/python')
let pip_usr_local_bin = new Pip('/usr/local/bin/pip')
pip_usr_local_bin.inform_about(python_usr_bin)
pip_usr_local_bin.inform_about(python_usr_local_bin)

python_usr_bin.report()
python_usr_local_bin.report()
pip_usr_local_bin.report()
let report = {
  'Python System Mac': python_usr_bin.report_obj,
  'Python Other': python_usr_local_bin.report_obj,
  'Pip': pip_usr_local_bin.report_obj
}
console.log(format(report))

console.log('DONE ')
<|endoftext|>


<commit_before>// Assignment Template

/* Check if an object in arr has value for field. */
function findObjectByField(arr, field, value) {
    for (var i = 0; i < arr.length; i += 1) {
        if (arr[i][field] == value) {
            return i;
        }
    }
    return -1;
}

medianX = function(medianArr) {
    count = medianArr.length;
    median = (count % 2 == 0) ? (medianArr[(medianArr.length / 2) - 1] + medianArr[(medianArr.length / 2)]) / 2 : medianArr[Math.floor(medianArr.length / 2)];
    return median;
}

toggleBands = function(chart) {
    var i = chart.xAxis[0].plotLinesAndBands.length;
    if (i > 0) {
        while (i--) {
            chart.xAxis[0].plotLinesAndBands[i].destroy();
        }
    } else {
        chart.xAxis[0].update({
            plotLines: plotLines,
            plotBands: plotBands
        });
    }
}

average = function(data) {
    var sum = data.reduce(function(sum, value) {
        return sum + value;
    }, 0);
    var avg = sum / data.length;
    return avg;
}

setTimeData = function(ret) {
    var data = Template.instance().readerSubmissionList.get();

    for (gId in data) {
	data[gId] = data[gId].map(function(e) {return e.graded_at ? new Date(e.graded_at) : null;});
    }
    var assignment = Session.get("assignment");
    var created = new Date(assignment.created_at);
    var lastDate = created;
    for (gId in data) {
	for (var k=0; k < data[gId].length; k += 1) {
	    console.log("DAAAAAAAAAAATE");
	    date = data[gId][k];
	    console.log(date);
	    if (date > lastDate) {
		lastDate = date;
	    }
	}
    }
    console.log("LastDate: " + lastDate.toISOString());
    interval = (lastDate-created)/10
    cats = []
    for (var i=0; i < 10; i += 1) {
	cats.push(new Date((i*interval) + (created/1)));
    }
    console.log("CATS");
    console.log(cats);
    duetime = assignment.due_at;
    sers = [];
    for (gId in data) {
	values = [];
	for (var j=0; j < cats.length; j += 1) {
	    date = cats[j];
	    subs = data[gId].filter(function(e) {return e <= date;}).length;
	    values.push(subs/data[gId].length);
	}
	ind = findObjectByField(ret, 'grader_id', gId);
	if (ind != -1) {
	    sers.push({
		name: ret[ind].grader_name,
		data: values
	    });
	}
    }
    Session.set("timeData", {
        title: {
            text: 'Reader Progress',
            x: -20 //center
        },
        xAxis: {
            categories: cats
        },
        yAxis: {
            title: {
                text: 'Percent Complete (%)'
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }]
        },
        tooltip: {
            valueSuffix: '%'
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'middle',
            borderWidth: 0
        },
        series: sers
    });
}

setHistoData = function(ret) {
    var all = $.grep(ret, function(o) {
        return o.grader_id == "All";
    });
    all = all[0];
    var mean = all.mean;
    var scores = all.scores;
    var squareDiffs = scores.map(function(value) {
        var diff = value - mean;
        var sqr = diff * diff;
        return sqr;
    });
    var sd = Math.sqrt(average(squareDiffs));
    Session.set("standardDeviation", sd);
    Session.set("mean", mean);
    Session.set("median", medianX(scores));
    var plotLines = [{
        "value": mean,
        "width": 2,
        "color": "#666",
        "zIndex": 10,
        "dashStyle": "Dash",
        "label": {
            "text": "m",
            "rotation": 0,
            "align": "center",
            "x": 0,
            "y": -5,
            "style": {
                "fontSize": "10px"
            }
        }
    }];
    var sigmas = [-3, -2, -1, 1, 2, 3];
    for (s in sigmas) {
        plotLines.push({
            "value": mean + sd * sigmas[s],
            "width": 1,
            "color": "#999",
            "dashStyle": "Dash",
            "zIndex": 10,
            "label": {
                "text": sigmas[s].toString() + "s",
                "rotation": 0,
                "align": "center",
                "x": 0,
                "y": -5,
                "style": {
                    "fontSize": "10px"
                }
            }
        });
    }
    var plotBands = [{
        "from": -1 * sd + mean,
        "to": 1 * sd + mean,
        "color": "rgba(184,210,236,.1)",
        "zIndex": 0
    }, {
        "from": -2 * sd + mean,
        "to": 2 * sd + mean,
        "color": "rgba(184,210,236,.1)",
        "zIndex": 0
    }, {
        "from": -3 * sd + mean,
        "to": 3 * sd + mean,
        "color": "rgba(184,210,236,.1)",
        "zIndex": 0
    }];
    var maxPoints = Session.get("assignment").points_possible;
    var bucketSize = Math.ceil(maxPoints / 10);
    var bucketMargin = bucketSize / 2;
    var curBucket = bucketMargin;
    var buckets = [];
    var count = 0;
    while (curBucket < maxPoints) {
        count = 0;
        for (var i = 0; i < scores.length; i += 1) {
            if (scores[i] >= curBucket - bucketMargin && scores[i] < curBucket + bucketMargin) {
                count += 1;
            }
        }
        buckets.push([curBucket, count]);
        curBucket += bucketSize;
    }
    count = 0;
    for (var j = 0; j < scores.length; j += 1) {
        if (scores[j] == maxPoints) {
            count += 1;
        }
    }
    buckets[buckets.length - 1][1] += count;
    Session.set("histoData", {
        chart: {
            type: 'column',
            alignTicks: false,
            marginTop: 25,
            showAxes: true
        },
        exporting: {
            enabled: false
        },
        title: {
            text: 'Grade Histogram'
        },
        tooltip: {
            borderWidth: 1,
            pointFormatter: function() {
                lower = this.x - bucketMargin;
                upper = this.x + bucketMargin;
                return 'Range:
 ' + lower + ' - ' + upper + '
' +
                    'Count: ' + this.y;
            }
        },
        plotOptions: {
            series: {
                minPointLength: 1,
                shadow: false,
                marker: {
                    enabled: false
                }
            },
            area: {
                events: {
                    legendItemClick: function(e) {
                        if (this.name == 'Sigma Bands') {
                            toggleBands(this.chart);
                        }
                    }
                }
            }
        },
        xAxis: {
            title: {
                text: 'Point Buckets'
            },
            lineColor: '#999',
            tickColor: '#ccc',
            plotLines: plotLines,
            plotBands: plotBands
        },
        yAxis: {
            title: {
                text: 'Count'
            },
            gridLineColor: '#e9e9e9',
            tickWidth: 1,
            tickLength: 3,
            tickColor: '#ccc',
            lineColor: '#ccc',
            endOnTick: false,
        },
        series: [{
            name: 'Submission Samples',
            data: buckets,
            pointRange: bucketSize,
            borderWidth: .5,
            borderColor: '#666',
            pointPadding: 0,
            groupPadding: 0,
            color: '#e3e3e3',
            tooltip: {
                pointFormatter: function() {
                    lower = this.x - bucketMargin;
                    upper = this.x + bucketMargin;
                    return 'Range:
 ' + lower + ' - ' + upper + '
' + 'Count: ' + this.y;
                }
            }
        }, {
            type: 'area',
            name: 'Sigma Bands',
        }]
    });
}

computeStats = function(values) {
    var ret = [0, 0, 0, 0, 0];
    values.sort(function(a, b) {
        return a - b;
    });
    q1Arr = (values.length % 2 == 0) ? values.slice(0, (values.length / 2) + 1) : values.slice(0, Math.floor(values.length / 2) + 1);
    q2Arr = values;
    q3Arr = (values.length % 2 == 0) ? values.slice((values.length / 2) - 1, values.length) : values.slice(Math.ceil(values.length / 2) - 1, values.length);
    medianX(q1Arr);
    ret[1] = median;
    medianX(q2Arr);
    ret[2] = median;
    medianX(q3Arr);
    ret[3] = median;
    ret[0] = values[0];
    ret[4] = values[values.length - 1];
    return ret;
}

setBoxData = function(ret) {
    Session.set("boxData", {
        chart: {
            type: 'boxplot',
            backgroundColor: 'white' //"#BBBBBB"
        },
        title: {
            text: 'Reader Grade Distributions'
        },
        legend: {
            enabled: false
        },
        xAxis: {
            categories: ret.map(function(x) {
                return x.grader_name;
            }),
            title: {
                text: 'Grader'
            }
        },
        yAxis: {
            title: {
                text: 'Points Awarded'
            }
        },
        series: [{
            name: 'Grade Distribution',
            data: Session.get("ret").map(function(x) {
                return computeStats(x.scores);
            }),
            tooltip: {
                headerFormat: '{point.key} Grades
'
            }
        }, {
            name: 'Mean',
            color: Highcharts.getOptions().colors[0],
            type: 'scatter',
            data: ret.map(function(x) {
                return [ret.indexOf(x), x.scores.reduce(function(a, b) {
                    return a + b
                }, 0) / x.scores.length]
            }),
            marker: {
                fillColor: '#254A6E',
                lineWidth: 1,
                lineColor: Highcharts.getOptions().colors[0]
            },
            tooltip: {
                pointFormat: 'Value: {point.y}'
            }
        }]
    });
}

Template.assignment.created = function() {
    var self = this;
    self.submissionList = new ReactiveVar([]);
    Meteor.call("getSubmissions", Session.get("course").id, Session.get("assignment").id, function(err, value) {
        if (err) {
            console.log(err);
        } else {
            self.submissionList.set(value);
        }
    });

    self.mysubmissionList = new ReactiveVar([]);
    Meteor.call("mySubmissions", Session.get("assignment").id, function(err, value) {
        if (err) {
            console.log(err);
        } else {
            self.mysubmissionList.set(value);
        }
    });
    self.readerSubmissionList = new ReactiveVar([]);
    Meteor.call("assignedSubmissions", Session.get("course").id, Session.get("assignment").id, function(err, value) {
        if (err) {
            console.log(err);
        } else {
            self.readerSubmissionList.set(value);
        }
    });
}

Template.assignment.rendered = function() {
    $("#gradedata-toggle").click(function() {
        if ($("#gradeHistogram").contents().length != 0) {
            $("#gradeHistogram").html("");
        } else {
            $("#gradeHistogram").highcharts(Session.get("histoData"));
        }
    });
    $("#analytics-toggle").click(function() {
        if ($("#readerAverages").contents().length != 0) {
            $("#readerAverages").html("");
        } else {
            $("#readerAverages").highcharts(Session.get("boxData"));
        }
        if ($("#readerTimelines").contents().length != 0) {
            $("#readerTimelines").html("");
        } else {
            $("#readerTimelines").highcharts(Session.get("timeData"));
        }
    });
}

Template.assignment.helpers({
    assignment: function() {
        return Session.get("assignment");
    },
    course: function() {
        return Session.get("course");
    },
    submissions: function() {
        var data = Template.instance().submissionList.get();
        return data;
    },
    mysubmissions: function() {
        var data = Template.instance().mysubmissionList.get();
        return data;
    },
    graderStats: function() {
        var data = Template.instance().submissionList.get();
        var total = 0;
        var count = 0;
        var stats = {};
        var gId = 0;
        for (var i = 0; i < data.length; i += 1) {
            gId = data[i].grader_id;
            total += data[i].score;
            count += 1;
            if (stats[gId]) {
                stats[gId].count += 1;
                stats[gId].total += data[i].score;
                stats[gId].scores.push(data[i].score);
            } else {
                stats[gId] = {
                    count: 1,
                    total: data[i].score,
                    scores: [data[i].score],
                    grader_name: data[i].grader_name
                };
            }
        }
        var ret = [];
        ret.push({
            grader_id: "All",
            mean: total / count,
            total: total,
            count: count,
            scores: data.map(function(x) {
                return x.score;
            }),
            grader_name: "All"
        });
        for (grader in stats) {
            stats[grader].mean = stats[grader].total / stats[grader].count;
            stats[grader].grader_id = grader;
            ret.push(stats[grader]);
        }
        Session.set("classMean", total / count);
        Session.set("ret", ret);
        setBoxData(ret);
        setTimeData(ret);
	setHistoData(ret);
        return ret;
    },
    classMean: function() {
        return Session.get("classMean");
    },
    mean: function() {
        return Session.get("mean");
    },
    standardDeviation: function() {
        return Session.get("standardDeviation");
    },
    median: function() {
        return Session.get("standardDeviation");
    }
});

Template.assignment.events({
    'click .course-link': function(e) {
        Session.set("dashView", "course");
    },
    'click .grade-submission': function(e) {
        if (this.preview_url) {
            Session.set("submissionURL", this.preview_url);
        } else {
            Session.set("submissionURL", this.html_url);
        }
        window.open(Session.get("submissionURL"), "_blank").focus();
    },
    'click #doAssignment': function(e) {
        var assnID = Session.get('assignment').id
        var courseID = Session.get('course').id
        var pctConstraint = $('.pctConstraint').val();
        var numConstraint = $('.numConstraint').val();
        var params = {
            course: courseID,
            assign: assnID,
            pct: parseFloat(pctConstraint),
            num: parseFloat(numConstraint)
        }
        $('.assignconf').html('');
        Meteor.call('doReaderAssign', params, function(err, value) {
            if (err) {
                $('.assignconf').html(err);
            } else {
                $('.assignconf').html('
Success!
');
                Meteor.call("getSubmissions", Session.get("course").id, Session.get("assignment").id, function(err, value) {
                    if (err) {
                        console.log(err);
                    } else {
                        self.submissionList.set(value);
                    }
                });
            }
        });

    }
});
<commit_msg>yesssssssssssssssssssssssssssssssssssssssssss it works<commit_after>// Assignment Template

/* Check if an object in arr has value for field. */
function findObjectByField(arr, field, value) {
    for (var i = 0; i < arr.length; i += 1) {
        if (arr[i][field] == value) {
            return i;
        }
    }
    return -1;
}

medianX = function(medianArr) {
    count = medianArr.length;
    median = (count % 2 == 0) ? (medianArr[(medianArr.length / 2) - 1] + medianArr[(medianArr.length / 2)]) / 2 : medianArr[Math.floor(medianArr.length / 2)];
    return median;
}

toggleBands = function(chart) {
    var i = chart.xAxis[0].plotLinesAndBands.length;
    if (i > 0) {
        while (i--) {
            chart.xAxis[0].plotLinesAndBands[i].destroy();
        }
    } else {
        chart.xAxis[0].update({
            plotLines: plotLines,
            plotBands: plotBands
        });
    }
}

average = function(data) {
    var sum = data.reduce(function(sum, value) {
        return sum + value;
    }, 0);
    var avg = sum / data.length;
    return avg;
}

setTimeData = function(ret) {
    var data = Template.instance().readerSubmissionList.get();

    for (gId in data) {
	data[gId] = data[gId].map(function(e) {return e.graded_at ? new Date(e.graded_at) : null;});
    }
    var assignment = Session.get("assignment");
    var created = new Date(assignment.created_at);
    var lastDate = created;
    for (gId in data) {
	for (var k=0; k < data[gId].length; k += 1) {
	    console.log("DAAAAAAAAAAATE");
	    date = data[gId][k];
	    console.log(date);
	    if (date > lastDate) {
		lastDate = date;
	    }
	}
    }
    console.log("LastDate: " + lastDate.toISOString());
    interval = (lastDate-created)/10
    cats = []
    for (var i=0; i < 11; i += 1) {
	cats.push(new Date((i*interval) + (created/1)));
    }
    console.log("CATS");
    console.log(cats);
    duetime = assignment.due_at;
    sers = [];
    for (gId in data) {
	values = [];
	for (var j=0; j < cats.length; j += 1) {
	    date = cats[j];
	    subs = data[gId].filter(function(e) {return e <= date;}).length;
	    values.push((subs/data[gId].length)*100);
	}
	ind = findObjectByField(ret, 'grader_id', gId);
	if (ind != -1) {
	    sers.push({
		name: ret[ind].grader_name,
		data: values
	    });
	}
    }
    Session.set("timeData", {
        title: {
            text: 'Reader Progress',
            x: -20 //center
        },
        xAxis: {
            categories: cats
        },
        yAxis: {
            title: {
                text: 'Percent Complete (%)'
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }]
        },
        tooltip: {
            valueSuffix: '%'
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'middle',
            borderWidth: 0
        },
        series: sers
    });
}

setHistoData = function(ret) {
    var all = $.grep(ret, function(o) {
        return o.grader_id == "All";
    });
    all = all[0];
    var mean = all.mean;
    var scores = all.scores;
    var squareDiffs = scores.map(function(value) {
        var diff = value - mean;
        var sqr = diff * diff;
        return sqr;
    });
    var sd = Math.sqrt(average(squareDiffs));
    Session.set("standardDeviation", sd);
    Session.set("mean", mean);
    Session.set("median", medianX(scores));
    var plotLines = [{
        "value": mean,
        "width": 2,
        "color": "#666",
        "zIndex": 10,
        "dashStyle": "Dash",
        "label": {
            "text": "m",
            "rotation": 0,
            "align": "center",
            "x": 0,
            "y": -5,
            "style": {
                "fontSize": "10px"
            }
        }
    }];
    var sigmas = [-3, -2, -1, 1, 2, 3];
    for (s in sigmas) {
        plotLines.push({
            "value": mean + sd * sigmas[s],
            "width": 1,
            "color": "#999",
            "dashStyle": "Dash",
            "zIndex": 10,
            "label": {
                "text": sigmas[s].toString() + "s",
                "rotation": 0,
                "align": "center",
                "x": 0,
                "y": -5,
                "style": {
                    "fontSize": "10px"
                }
            }
        });
    }
    var plotBands = [{
        "from": -1 * sd + mean,
        "to": 1 * sd + mean,
        "color": "rgba(184,210,236,.1)",
        "zIndex": 0
    }, {
        "from": -2 * sd + mean,
        "to": 2 * sd + mean,
        "color": "rgba(184,210,236,.1)",
        "zIndex": 0
    }, {
        "from": -3 * sd + mean,
        "to": 3 * sd + mean,
        "color": "rgba(184,210,236,.1)",
        "zIndex": 0
    }];
    var maxPoints = Session.get("assignment").points_possible;
    var bucketSize = Math.ceil(maxPoints / 10);
    var bucketMargin = bucketSize / 2;
    var curBucket = bucketMargin;
    var buckets = [];
    var count = 0;
    while (curBucket < maxPoints) {
        count = 0;
        for (var i = 0; i < scores.length; i += 1) {
            if (scores[i] >= curBucket - bucketMargin && scores[i] < curBucket + bucketMargin) {
                count += 1;
            }
        }
        buckets.push([curBucket, count]);
        curBucket += bucketSize;
    }
    count = 0;
    for (var j = 0; j < scores.length; j += 1) {
        if (scores[j] == maxPoints) {
            count += 1;
        }
    }
    buckets[buckets.length - 1][1] += count;
    Session.set("histoData", {
        chart: {
            type: 'column',
            alignTicks: false,
            marginTop: 25,
            showAxes: true
        },
        exporting: {
            enabled: false
        },
        title: {
            text: 'Grade Histogram'
        },
        tooltip: {
            borderWidth: 1,
            pointFormatter: function() {
                lower = this.x - bucketMargin;
                upper = this.x + bucketMargin;
                return 'Range:
 ' + lower + ' - ' + upper + '
' +
                    'Count: ' + this.y;
            }
        },
        plotOptions: {
            series: {
                minPointLength: 1,
                shadow: false,
                marker: {
                    enabled: false
                }
            },
            area: {
                events: {
                    legendItemClick: function(e) {
                        if (this.name == 'Sigma Bands') {
                            toggleBands(this.chart);
                        }
                    }
                }
            }
        },
        xAxis: {
            title: {
                text: 'Point Buckets'
            },
            lineColor: '#999',
            tickColor: '#ccc',
            plotLines: plotLines,
            plotBands: plotBands
        },
        yAxis: {
            title: {
                text: 'Count'
            },
            gridLineColor: '#e9e9e9',
            tickWidth: 1,
            tickLength: 3,
            tickColor: '#ccc',
            lineColor: '#ccc',
            endOnTick: false,
        },
        series: [{
            name: 'Submission Samples',
            data: buckets,
            pointRange: bucketSize,
            borderWidth: .5,
            borderColor: '#666',
            pointPadding: 0,
            groupPadding: 0,
            color: '#e3e3e3',
            tooltip: {
                pointFormatter: function() {
                    lower = this.x - bucketMargin;
                    upper = this.x + bucketMargin;
                    return 'Range:
 ' + lower + ' - ' + upper + '
' + 'Count: ' + this.y;
                }
            }
        }, {
            type: 'area',
            name: 'Sigma Bands',
        }]
    });
}

computeStats = function(values) {
    var ret = [0, 0, 0, 0, 0];
    values.sort(function(a, b) {
        return a - b;
    });
    q1Arr = (values.length % 2 == 0) ? values.slice(0, (values.length / 2) + 1) : values.slice(0, Math.floor(values.length / 2) + 1);
    q2Arr = values;
    q3Arr = (values.length % 2 == 0) ? values.slice((values.length / 2) - 1, values.length) : values.slice(Math.ceil(values.length / 2) - 1, values.length);
    medianX(q1Arr);
    ret[1] = median;
    medianX(q2Arr);
    ret[2] = median;
    medianX(q3Arr);
    ret[3] = median;
    ret[0] = values[0];
    ret[4] = values[values.length - 1];
    return ret;
}

setBoxData = function(ret) {
    Session.set("boxData", {
        chart: {
            type: 'boxplot',
            backgroundColor: 'white' //"#BBBBBB"
        },
        title: {
            text: 'Reader Grade Distributions'
        },
        legend: {
            enabled: false
        },
        xAxis: {
            categories: ret.map(function(x) {
                return x.grader_name;
            }),
            title: {
                text: 'Grader'
            }
        },
        yAxis: {
            title: {
                text: 'Points Awarded'
            }
        },
        series: [{
            name: 'Grade Distribution',
            data: Session.get("ret").map(function(x) {
                return computeStats(x.scores);
            }),
            tooltip: {
                headerFormat: '{point.key} Grades
'
            }
        }, {
            name: 'Mean',
            color: Highcharts.getOptions().colors[0],
            type: 'scatter',
            data: ret.map(function(x) {
                return [ret.indexOf(x), x.scores.reduce(function(a, b) {
                    return a + b
                }, 0) / x.scores.length]
            }),
            marker: {
                fillColor: '#254A6E',
                lineWidth: 1,
                lineColor: Highcharts.getOptions().colors[0]
            },
            tooltip: {
                pointFormat: 'Value: {point.y}'
            }
        }]
    });
}

Template.assignment.created = function() {
    var self = this;
    self.submissionList = new ReactiveVar([]);
    Meteor.call("getSubmissions", Session.get("course").id, Session.get("assignment").id, function(err, value) {
        if (err) {
            console.log(err);
        } else {
            self.submissionList.set(value);
        }
    });

    self.mysubmissionList = new ReactiveVar([]);
    Meteor.call("mySubmissions", Session.get("assignment").id, function(err, value) {
        if (err) {
            console.log(err);
        } else {
            self.mysubmissionList.set(value);
        }
    });
    self.readerSubmissionList = new ReactiveVar([]);
    Meteor.call("assignedSubmissions", Session.get("course").id, Session.get("assignment").id, function(err, value) {
        if (err) {
            console.log(err);
        } else {
            self.readerSubmissionList.set(value);
        }
    });
}

Template.assignment.rendered = function() {
    $("#gradedata-toggle").click(function() {
        if ($("#gradeHistogram").contents().length != 0) {
            $("#gradeHistogram").html("");
        } else {
            $("#gradeHistogram").highcharts(Session.get("histoData"));
        }
    });
    $("#analytics-toggle").click(function() {
        if ($("#readerAverages").contents().length != 0) {
            $("#readerAverages").html("");
        } else {
            $("#readerAverages").highcharts(Session.get("boxData"));
        }
        if ($("#readerTimelines").contents().length != 0) {
            $("#readerTimelines").html("");
        } else {
            $("#readerTimelines").highcharts(Session.get("timeData"));
        }
    });
}

Template.assignment.helpers({
    assignment: function() {
        return Session.get("assignment");
    },
    course: function() {
        return Session.get("course");
    },
    submissions: function() {
        var data = Template.instance().submissionList.get();
        return data;
    },
    mysubmissions: function() {
        var data = Template.instance().mysubmissionList.get();
        return data;
    },
    graderStats: function() {
        var data = Template.instance().submissionList.get();
        var total = 0;
        var count = 0;
        var stats = {};
        var gId = 0;
        for (var i = 0; i < data.length; i += 1) {
            gId = data[i].grader_id;
            total += data[i].score;
            count += 1;
            if (stats[gId]) {
                stats[gId].count += 1;
                stats[gId].total += data[i].score;
                stats[gId].scores.push(data[i].score);
            } else {
                stats[gId] = {
                    count: 1,
                    total: data[i].score,
                    scores: [data[i].score],
                    grader_name: data[i].grader_name
                };
            }
        }
        var ret = [];
        ret.push({
            grader_id: "All",
            mean: total / count,
            total: total,
            count: count,
            scores: data.map(function(x) {
                return x.score;
            }),
            grader_name: "All"
        });
        for (grader in stats) {
            stats[grader].mean = stats[grader].total / stats[grader].count;
            stats[grader].grader_id = grader;
            ret.push(stats[grader]);
        }
        Session.set("classMean", total / count);
        Session.set("ret", ret);
        setBoxData(ret);
        setTimeData(ret);
	setHistoData(ret);
        return ret;
    },
    classMean: function() {
        return Session.get("classMean");
    },
    mean: function() {
        return Session.get("mean");
    },
    standardDeviation: function() {
        return Session.get("standardDeviation");
    },
    median: function() {
        return Session.get("standardDeviation");
    }
});

Template.assignment.events({
    'click .course-link': function(e) {
        Session.set("dashView", "course");
    },
    'click .grade-submission': function(e) {
        if (this.preview_url) {
            Session.set("submissionURL", this.preview_url);
        } else {
            Session.set("submissionURL", this.html_url);
        }
        window.open(Session.get("submissionURL"), "_blank").focus();
    },
    'click #doAssignment': function(e) {
        var assnID = Session.get('assignment').id
        var courseID = Session.get('course').id
        var pctConstraint = $('.pctConstraint').val();
        var numConstraint = $('.numConstraint').val();
        var params = {
            course: courseID,
            assign: assnID,
            pct: parseFloat(pctConstraint),
            num: parseFloat(numConstraint)
        }
        $('.assignconf').html('');
        Meteor.call('doReaderAssign', params, function(err, value) {
            if (err) {
                $('.assignconf').html(err);
            } else {
                $('.assignconf').html('
Success!
');
                Meteor.call("getSubmissions", Session.get("course").id, Session.get("assignment").id, function(err, value) {
                    if (err) {
                        console.log(err);
                    } else {
                        self.submissionList.set(value);
                    }
                });
            }
        });

    }
});
<|endoftext|>


<commit_before>(function ($) {
    $.fn.shotgunConsole = function () {
        var $this = this,
            client = new shotgun.Client(),
            $display = $('
')
                .appendTo($this);
            $cliContainer = $('
')
                .html('> ')
                .appendTo($this),
            $cli = $('<input>')
                .attr('type', 'text')
                .css({
                    backgroundColor: 'transparent',
                    color: $this.css('color'),
                    fontSize: $this.css('font-size'),
                    width: '75%',
                    border: 'none',
                    outline: 'none'
                })
                .appendTo($cliContainer);

        $cli.keypress(function (e) {
            if (e.which == 13) {
                client.execute($cli.val(), function (result) {
                    if (result.clearDisplay) $display.html('');
                    if (result.exit) {
                        window.open('','_self','');
                        window.close();
                    }
                    for (var count = 0; count < result.lines.length; count++) {
                        var line = result.lines[count];
                        $display.append(line.text.replace(/  /g, '  ') + '
');
                        $this.scrollTop($this[0].scrollHeight);
                    };
                });
                $cli.val('');
            }
        });
    };
})(jQuery);<commit_msg>Added a small margin above cli in jquery adapter.<commit_after>(function ($) {
    $.fn.shotgunConsole = function () {
        var $this = this,
            client = new shotgun.Client(),
            $display = $('
')
                .appendTo($this);
            $cliContainer = $('
')
                .html('> ')
                .appendTo($this),
            $cli = $('<input>')
                .attr('type', 'text')
                .css({
                    backgroundColor: 'transparent',
                    color: $this.css('color'),
                    fontSize: $this.css('font-size'),
                    width: '75%',
                    border: 'none',
                    outline: 'none',
                    marginTop: '5px'
                })
                .appendTo($cliContainer);

        $cli.keypress(function (e) {
            if (e.which == 13) {
                client.execute($cli.val(), function (result) {
                    if (result.clearDisplay) $display.html('');
                    if (result.exit) {
                        window.open('','_self','');
                        window.close();
                    }
                    for (var count = 0; count < result.lines.length; count++) {
                        var line = result.lines[count];
                        $display.append(line.text.replace(/  /g, '  ') + '
');
                        $this.scrollTop($this[0].scrollHeight);
                    };
                });
                $cli.val('');
            }
        });
    };
})(jQuery);<|endoftext|>


<commit_before>import _isEmpty from "lodash/isEmpty"
import * as Models from "models"
import PropTypes from "prop-types"
import React, { Component } from "react"
import { Link } from "react-router-dom"
import utils from "utils"

const MODEL_NAMES = Object.keys(Models).map(key => {
  let camel = utils.camelCase(key)
  if (camel === "location") {
    camel = "anetLocation"
  }
  Models[camel] = Models[key]
  return camel
})

const modelPropTypes = MODEL_NAMES.reduce(
  (map, name) => ({
    ...map,
    [name]: PropTypes.oneOfType([
      PropTypes.instanceOf(Models[name]),
      PropTypes.object,
      PropTypes.string
    ])
  }),
  {}
)

export default class LinkTo extends Component {
  static propTypes = {
    componentClass: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
    className: PropTypes.string,

    showIcon: PropTypes.bool,
    isLink: PropTypes.bool,
    edit: PropTypes.bool,

    // Configures this link to look like a button. Set it to true to make it a button,
    // or pass a string to set a button type
    button: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),

    target: PropTypes.string,
    whenUnspecified: PropTypes.string,
    ...modelPropTypes
  }

  static defaultProps = {
    componentClass: Link,
    showIcon: true,
    isLink: true,
    edit: false,
    button: false,
    whenUnspecified: "Unspecified"
  }

  render() {
    let {
      componentClass,
      children,
      edit,
      button,
      showIcon,
      isLink,
      whenUnspecified,
      className,
      ...componentProps
    } = this.props

    if (button) {
      componentProps.className = [
        className,
        "btn",
        `btn-${button === true ? "default" : button}`
      ].join(" ")
    } else {
      componentProps.className = className
    }
    let modelName = Object.keys(componentProps).find(
      key => MODEL_NAMES.indexOf(key) !== -1
    )
    if (!modelName) {
      console.error("You called LinkTo without passing a Model as a prop")
      return null
    }

    const modelFields = this.props[modelName]
    if (_isEmpty(modelFields)) return {whenUnspecified}

    const modelClass = Models[modelName]
    const isModel = typeof modelFields !== "string"
    const modelInstance = new modelClass(isModel ? modelFields : {})
    showIcon = showIcon && !button
    const modelIcon = showIcon && modelInstance.iconUrl()

    if (!isLink) return {modelInstance.toString()}

    let to = modelFields
    if (!isModel) {
      if (to.indexOf("?")) {
        let components = to.split("?")
        to = { pathname: components[0], search: components[1] }
      }
    } else {
      to = edit
        ? modelClass.pathForEdit(modelInstance)
        : modelClass.pathFor(modelInstance)
    }

    componentProps = Object.without(componentProps, modelName)

    const LinkToComponent = componentClass
    return (
      <LinkToComponent to={to} {...componentProps}>
        <React.Fragment>
          {showIcon && modelIcon && (

          )}
          {children || modelInstance.toString()}
        </React.Fragment>
      </LinkToComponent>
    )
  }
}
<commit_msg>NCI-Agency/anet#1522: Resolve lint warning about constructor name<commit_after>import _isEmpty from "lodash/isEmpty"
import * as Models from "models"
import PropTypes from "prop-types"
import React, { Component } from "react"
import { Link } from "react-router-dom"
import utils from "utils"

const MODEL_NAMES = Object.keys(Models).map(key => {
  let camel = utils.camelCase(key)
  if (camel === "location") {
    camel = "anetLocation"
  }
  Models[camel] = Models[key]
  return camel
})

const modelPropTypes = MODEL_NAMES.reduce(
  (map, name) => ({
    ...map,
    [name]: PropTypes.oneOfType([
      PropTypes.instanceOf(Models[name]),
      PropTypes.object,
      PropTypes.string
    ])
  }),
  {}
)

export default class LinkTo extends Component {
  static propTypes = {
    componentClass: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
    className: PropTypes.string,

    showIcon: PropTypes.bool,
    isLink: PropTypes.bool,
    edit: PropTypes.bool,

    // Configures this link to look like a button. Set it to true to make it a button,
    // or pass a string to set a button type
    button: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),

    target: PropTypes.string,
    whenUnspecified: PropTypes.string,
    ...modelPropTypes
  }

  static defaultProps = {
    componentClass: Link,
    showIcon: true,
    isLink: true,
    edit: false,
    button: false,
    whenUnspecified: "Unspecified"
  }

  render() {
    let {
      componentClass,
      children,
      edit,
      button,
      showIcon,
      isLink,
      whenUnspecified,
      className,
      ...componentProps
    } = this.props

    if (button) {
      componentProps.className = [
        className,
        "btn",
        `btn-${button === true ? "default" : button}`
      ].join(" ")
    } else {
      componentProps.className = className
    }
    let modelName = Object.keys(componentProps).find(
      key => MODEL_NAMES.indexOf(key) !== -1
    )
    if (!modelName) {
      console.error("You called LinkTo without passing a Model as a prop")
      return null
    }

    const modelFields = this.props[modelName]
    if (_isEmpty(modelFields)) return {whenUnspecified}

    const ModelClass = Models[modelName]
    const isModel = typeof modelFields !== "string"
    const modelInstance = new ModelClass(isModel ? modelFields : {})
    showIcon = showIcon && !button
    const modelIcon = showIcon && modelInstance.iconUrl()

    if (!isLink) return {modelInstance.toString()}

    let to = modelFields
    if (!isModel) {
      if (to.indexOf("?")) {
        let components = to.split("?")
        to = { pathname: components[0], search: components[1] }
      }
    } else {
      to = edit
        ? ModelClass.pathForEdit(modelInstance)
        : ModelClass.pathFor(modelInstance)
    }

    componentProps = Object.without(componentProps, modelName)

    const LinkToComponent = componentClass
    return (
      <LinkToComponent to={to} {...componentProps}>
        <React.Fragment>
          {showIcon && modelIcon && (

          )}
          {children || modelInstance.toString()}
        </React.Fragment>
      </LinkToComponent>
    )
  }
}
<|endoftext|>


<commit_before>var http = require('http'),
    _ = require('underscore');

var ourTeamId = 1;

var extractHandFromGame = function (game_state) {
    var hand = [],
        me = game_state.players.filter(function (player) {
            if (player.id == ourTeamId) return player;
        }),
        publicCards = game_state.community_cards;
    _.forEach(me[0].hole_cards, function (card) {
        hand.push(card);
    });
    _.forEach(publicCards, function (card) {
        hand.push(card);
    });

    return hand;
};

var playGame = function (game_state, bet) {
    var myHand = extractHandFromGame(game_state);
    if(myHand.length >= 5) {
        var request = http.get("http://rainman.leanpoker.org/rank?cards=" + JSON.stringify(myHand), function (response) {
            var body = '';
            response.on('data', function (d) {
                body += d;
            });
            response.on('end', function () {
                var data = JSON.parse(body);
                console.log(body);
                placeBet(data.rank, game_state, bet);
            });
        });
        request.on('error', function (err) {
            console.log("an error occured ");
            bet(0);
        });
    } else {
        placeBet(1, game_state, bet);
    }

};

var placeBet = function (handRank, game_state, bet) {
    if (handRank == 0 ) {
        bet(0);
    } else if (handRank >= 1 && handRank <= 5) {
        call(game_state, bet);
    } else {
        raise(game_state, bet);
    }
};

var call = function (game_state, bet) {
    return bet(game_state.current_buy_in - game_state.players[game_state.in_action].bet);
};

var raise = function raise(game_state, bet) {
    return bet(game_state.current_buy_in - game_state.players[game_state.in_action].bet + game_state.minimum_raise + 200);
};

module.exports = {
    VERSION: "V1",

    bet_request: function (game_state, bet) {
        if (game_state)
            console.log(JSON.stringify(game_state));

        playGame(game_state, bet);
    },

    showdown: function (game_state) {

    }
};

<commit_msg>tracing time<commit_after>var http = require('http'),
    _ = require('underscore');

var ourTeamId = 1;

var extractHandFromGame = function (game_state) {
    var hand = [],
        me = game_state.players.filter(function (player) {
            if (player.id == ourTeamId) return player;
        }),
        publicCards = game_state.community_cards;
    _.forEach(me[0].hole_cards, function (card) {
        hand.push(card);
    });
    _.forEach(publicCards, function (card) {
        hand.push(card);
    });

    return hand;
};

var playGame = function (game_state, bet) {
    var myHand = extractHandFromGame(game_state);
    var t0 = new Date().getTime();
    if(myHand.length >= 5) {
        var request = http.get("http://rainman.leanpoker.org/rank?cards=" + JSON.stringify(myHand), function (response) {
            var body = '';
            response.on('data', function (d) {
                body += d;
            });
            response.on('end', function () {
                console.log(new Date().getTime() - t0);
                var data = JSON.parse(body);
                placeBet(data.rank, game_state, bet);
            });
        });
        request.on('error', function (err) {
            console.log("an error occured ");
            bet(0);
        });
    } else {
        placeBet(1, game_state, bet);
    }

};

var placeBet = function (handRank, game_state, bet) {
    if (handRank == 0 ) {
        bet(0);
    } else if (handRank >= 1 && handRank <= 5) {
        call(game_state, bet);
    } else {
        raise(game_state, bet);
    }
};

var call = function (game_state, bet) {
    return bet(game_state.current_buy_in - game_state.players[game_state.in_action].bet);
};

var raise = function raise(game_state, bet) {
    return bet(game_state.current_buy_in - game_state.players[game_state.in_action].bet + game_state.minimum_raise + 200);
};

module.exports = {
    VERSION: "V1",

    bet_request: function (game_state, bet) {
        if (game_state)
            console.log(JSON.stringify(game_state));

        playGame(game_state, bet);
    },

    showdown: function (game_state) {

    }
};

<|endoftext|>


<commit_before>import 'raf/polyfill';

const polyfill = (callback) => {
  // const browserSupported = Boolean(
  //   'Map' in window &&
  //   'Set' in window &&
  //   'fetch' in window &&
  //   'assign' in Object &&
  //   'Intl' in window &&
  //   'includes' in Array.prototype &&
  //   'filter' in Array.prototype
  // );

  // if (browserSupported) {
  //   callback();
  // } else {
  //   /*
  //     Load polyfills for older browsers.

  //     We could load the whole of core-js/shim here (and perhaps we should if we find we
  //     need to come back here and add stuff frequently) but it makes the polyfill bundle
  //     about 40% larger. So let's try this and see if it's "enough".
  //   */

  /* eslint-disable global-require */
  require.ensure([], () => {
    require('core-js/es6/array');
    require('core-js/es6/object');
    require('core-js/es6/number');
    require('core-js/es6/map');
    require('core-js/es6/set');
    require('core-js/modules/es7.object.values');
    require('core-js/modules/es7.array.includes');
    require('intl');
    /* eslint-enable-global-require */

    callback();
  });
  // }
};

export default polyfill;
<commit_msg>IE10 polyfill issues #1525<commit_after>/* eslint-disable global-require */

import 'raf/polyfill';

const polyfill = (callback) => {
  const toBePolyfilled = [];

  if (!(window.Map && window.Set && window.WeakMap && window.WeakSet)) {
    toBePolyfilled.push('core-js/es6/map');
    toBePolyfilled.push('core-js/es6/set');
  }

  if (!(window.Intl)) {
    toBePolyfilled.push('intl');
  }

  if (!(Object.assign && Object.is && Object.setPrototypeOf)) {
    toBePolyfilled.push('core-js/es6/object');
    toBePolyfilled.push('core-js/modules/es7.object.values');
  }

  if (!(Array.prototype &&
    Array.prototype.copyWithin &&
    Array.prototype.fill &&
    Array.prototype.find &&
    Array.prototype.findIndex &&
    Array.prototype.keys &&
    Array.prototype.entries &&
    Array.prototype.values &&
    Array.from &&
    Array.of)
  ) {
    toBePolyfilled.push('core-js/es6/array');
    toBePolyfilled.push('core-js/modules/es7.array.includes');
  }

  if (!(Number.isFinite &&
    Number.isInteger &&
    Number.isSafeInteger &&
    Number.isNaN &&
    Number.parseInt &&
    Number.parseFloat &&
    Number.isInteger(Number.MAX_SAFE_INTEGER) &&
    Number.isInteger(Number.MIN_SAFE_INTEGER) &&
    Number.isFinite(Number.EPSILON))
  ) {
    toBePolyfilled.push('core-js/es6/number');
  }

  if (!toBePolyfilled.length) {
    callback();
  } else {
    require.ensure([], () => {
      toBePolyfilled.forEach(require);
      callback();
    });
  }
};

export default polyfill;
<|endoftext|>


<commit_before>
module.exports = {

  VERSION: "Default JavaScript folding player",

  bet_request: function(game_state) {
    return 0;
  },

  showdown: function(game_state) {

  }
};
<commit_msg>Player name changed<commit_after>
module.exports = {

  VERSION: "Chuck Norris player",

  bet_request: function(game_state) {
    return 0;
  },

  showdown: function(game_state) {

  }
};
<|endoftext|>


<commit_before>module.exports = {

    VERSION: "Desperados",

    bet_request: function (game_state) {
        var ourBet = game_state.players[game_state.in_action].bet;

        var callOrFold = function () {
            var currentCall = call();

            // TBD: nicht fix 50, sondern basierend auf Blindes
            if(currentCall <= 50){
                return call();
            }

            if(currentCall <= ourBet * 1.25){
                return call();
            }

            return fold();
        };
        var call = function () {
            return game_state.current_buy_in - ourBet - game_state.small_blind;
        }
        var fold = function () {
            return 0;
        }
        var minimumRaise = function () {
            return call() + game_state.minimum_raise;
        }
        var rank = function () {
            var cards = game_state.players[game_state.in_action].hole_cards;

            var card0 = cards[0].rank;
            var card1 = cards[1].rank;

            if (card0 === '10') {
                card0 = 'T';
            }
            if (card1 === '10') {
                card1 = 'T';
            }

            var hand = card0 + card1,
                handReverse = card1 + card0;

            var ranks = [
                {
                    "rank": 1,
                    "cards": ['AA', 'KK', 'QQ', 'AK']
                },
                {
                    "rank": 2,
                    "cards": ['JJ', 'TT', '99']
                },
                {
                    "rank": 3,
                    "cards": ['88', '77', 'AQ']
                },
                {
                    "rank": 4,
                    "cards": ['66', '65', '44', '33', '22', 'AJ', 'AT', 'A9', 'A8']
                },
                {
                    "rank": 5,
                    "cards": ['A7', 'A6', 'A5', 'A4', 'A3', 'A2', 'KQ']
                },
                {
                    "rank": 6,
                    "cards": ['QJ', 'JT', 'T9', '98', '87', '76', '75', '65']
                }
            ];

            var rank = 7;
            ranks.every(function (data, index) {
                if (data.cards.indexOf(hand) > 0 || data.cards.indexOf(handReverse) > 0) {
                    rank = data.rank;
                    return false;
                }
                return true;
            });
            return rank;
        }

        var preFlopStrategie = function () {

            switch (rank()) {

            case 1:
                return minimumRaise() * 2;
            case 2:
                return minimumRaise() * 2;
            case 3:
                return minimumRaise() * 1.5;
            case 4:
                return minimumRaise() * 1.5;
            case 5:
                return minimumRaise();
            case 6:
                return callOrFold();
            default:
                return callOrFold();
            }

        };

        var flopStrategie = function () {

        };

        // Rounds
        switch (game_state.community_cards.length) {
        case 0: // Preflop
            console.log("preflop");
            return preFlopStrategie();
        case 3: // Flop
            console.log("flop");
            return preFlopStrategie();
        case 4: // Turn
            console.log("turn");
            return preFlopStrategie();
        case 5: // River
            console.log("river");
            return preFlopStrategie();
        default:
            return preFlopStrategie();
        }
    },

    showdown: function (game_state) {

    }
};
<commit_msg>changed raise for rank 1<commit_after>module.exports = {

    VERSION: "Eichhof",

    bet_request: function (game_state) {
        var ourBet = game_state.players[game_state.in_action].bet;

        var callOrFold = function () {
            var currentCall = call();

            // TBD: nicht fix 50, sondern basierend auf Blindes
            if(currentCall <= 50){
                return call();
            }

            if(currentCall <= ourBet * 1.25){
                return call();
            }

            return fold();
        };
        var call = function () {
            return game_state.current_buy_in - ourBet - game_state.small_blind;
        }
        var fold = function () {
            return 0;
        }
        var minimumRaise = function () {
            return call() + game_state.minimum_raise;
        }
        var rank = function () {
            var cards = game_state.players[game_state.in_action].hole_cards;

            var card0 = cards[0].rank;
            var card1 = cards[1].rank;

            if (card0 === '10') {
                card0 = 'T';
            }
            if (card1 === '10') {
                card1 = 'T';
            }

            var hand = card0 + card1,
                handReverse = card1 + card0;

            var ranks = [
                {
                    "rank": 1,
                    "cards": ['AA', 'KK', 'QQ', 'AK']
                },
                {
                    "rank": 2,
                    "cards": ['JJ', 'TT', '99']
                },
                {
                    "rank": 3,
                    "cards": ['88', '77', 'AQ']
                },
                {
                    "rank": 4,
                    "cards": ['66', '65', '44', '33', '22', 'AJ', 'AT', 'A9', 'A8']
                },
                {
                    "rank": 5,
                    "cards": ['A7', 'A6', 'A5', 'A4', 'A3', 'A2', 'KQ']
                },
                {
                    "rank": 6,
                    "cards": ['QJ', 'JT', 'T9', '98', '87', '76', '75', '65']
                }
            ];

            var rank = 7;
            ranks.every(function (data, index) {
                if (data.cards.indexOf(hand) > 0 || data.cards.indexOf(handReverse) > 0) {
                    rank = data.rank;
                    return false;
                }
                return true;
            });
            return rank;
        }

        var preFlopStrategie = function () {

            switch (rank()) {

            case 1:
                return minimumRaise() * 5;
            case 2:
                return minimumRaise() * 2;
            case 3:
                return minimumRaise() * 1.5;
            case 4:
                return minimumRaise() * 1.5;
            case 5:
                return minimumRaise();
            case 6:
                return callOrFold();
            default:
                return callOrFold();
            }

        };

        var flopStrategie = function () {

        };

        // Rounds
        switch (game_state.community_cards.length) {
        case 0: // Preflop
            console.log("preflop");
            return preFlopStrategie();
        case 3: // Flop
            console.log("flop");
            return preFlopStrategie();
        case 4: // Turn
            console.log("turn");
            return preFlopStrategie();
        case 5: // River
            console.log("river");
            return preFlopStrategie();
        default:
            return preFlopStrategie();
        }
    },

    showdown: function (game_state) {

    }
};
<|endoftext|>