<commit_before>include('binary');
include('io');
include('ringo/buffer');
include('./util');
include('./mime');
require('core/date');

export('Response',
       'skinResponse',
       'jsonResponse',
       'xmlResponse',
       'staticResponse',
       'redirectResponse',
       'notFoundResponse',
       'errorResponse');

function Response() {

    // missing new security belt
    if (!(this instanceof Response)) {
        var response = new Response();
        response.write.apply(response, arguments);
        return response;
    }

    var config = require('ringo/webapp/env').config;
    var status = 200;
    var charset = config && config.charset || 'utf-8';
    var contentType = config && config.contentType || 'text/html';
    var headers = new Headers();
    var buffer = new Buffer();

    this.write = function write() {
        var length = arguments.length;
        for (var i = 0; i < length; i++) {
            buffer.write(String(arguments[i]));
            if (i < length - 1)
                buffer.write(' ');
        }
        return this;
    };

    this.write.apply(this, arguments);

    this.writeln = function writeln() {
        this.write.apply(this, arguments);
        buffer.write('\r\n');
        return this;
    };

    /**
     * Render a skin to the response's buffer
     * @param skin path to skin resource
     * @param context context object
     */
    this.render = function render(skin, context) {
        var render = require('ringo/skin').render;
        buffer.write(render(skin, context));
    };

    /**
     * Print a debug message to the rendered page.
     */
    this.debug =  function debug() {
        var buffer = this.debugBuffer || new Buffer();
        buffer.write("
");
        var length = arguments.length;
        for (var i = 0; i < length; i++) {
            buffer.write(arguments[i]);
            if (i < length - 1) {
                buffer.write(" ");
            }
        }
        buffer.writeln("
");
        this.debugBuffer = buffer;
        return null;
    };

    /**
     * Write the debug buffer to the response's main buffer.
     */
    this.flushDebug = function() {
        if (this.debugBuffer != null) {
            this.write(this.debugBuffer);
            this.debugBuffer.reset();
        }
        return null;
    };

    this.redirect = function(location) {
        status = 303;
        headers.set('Location', String(location));
    };

    Object.defineProperty(this, 'charset', {
        get: function() {
            return charset;
        },
        set: function(c) {
            charset = c;
        }
    });

    Object.defineProperty(this, 'contentType', {
        get: function() {
            return contentType;
        },
        set: function(c) {
            contentType = c;
        }
    });

    Object.defineProperty(this, 'status', {
        get: function() {
            return status;
        },
        set: function(s) {
            status = s;
        }
    });

    this.getHeader = function(key) {
        headers.get(String(key));
    };

    /**
     * Set a header to be sent to the client. If a header with this name was previously
     * set it will be replaced.
     * @param {String} key the header name
     * @param {String} value the header value
     * @returns {Response} this response for chainability
     */
    this.setHeader = function(key, value) {
        key = String(key);
        if (key.toLowerCase() == "content-type") {
            contentType = String(value);
            charset = getMimeParameter(contentType, "charset") || charset;
        }
        headers.set(key, String(value));
        return this;
    };

    /**
     * Add a header to be sent to the client. If a header with this name was previously
     * set it will not be replaced.
     * @param {String} key the header name
     * @param {String} value the header value
     * @returns {Response} this response for chainability
     */
    this.addHeader = function(key, value) {
        headers.add(String(key), String(value));
        return this;
    };

    /**
     * Sets a cookie to be sent to the client.
     * All arguments except for key and value are optional.
     * The days argument specifies the number of days until the cookie expires.
     * To delete a cookie immediately, set the days argument to 0. If days is
     * undefined or negative, the cookie is set for the current browser session.
     *
     * @example
res.setCookie("username", "michi");
     * res.setCookie("password", "strenggeheim", 10,
     *               {path: "/mypath", domain: ".mydomain.org"});

     *
     * @param {String} key the cookie name
     * @param {String} value the cookie value
     * @param {Number} days optional the number of days to keep the cookie.
     *     If this is undefined or -1, the cookie is set for the current session.
     *     If this is 0, the cookie will be deleted immediately.
     * @param {Object} options optional options argument which may contain the following properties:
     *

path - the path on which to set the cookie (defaults to /)

     *
domain -  the domain on which to set the cookie (defaults to current domain)

     *
secure - to only use this cookie for secure connections

     *
httpOnly - to make the cookie inaccessible to client side scripts

     * @since 0.5
     * @return {Response} this response object for chainability;
     */
    this.setCookie = function(key, value, days, options) {
        if (value) {
            // remove newline chars to prevent response splitting attack as value may be user-provided
            value = value.replace(/[\r\n]/g, "");
        }
        var buffer = new Buffer(key, "=", value);
        if (typeof days == "number" && days > -1) {
            var expires = days == 0 ?
                new Date(0) : new Date(Date.now() + days * 1000 * 60 * 60 * 24);
            var cookieDateFormat = "EEE, dd-MMM-yyyy HH:mm:ss zzz";
            buffer.write("; expires=");
            buffer.write(expires.format(cookieDateFormat, "en", "GMT"));
        }
        options = options || {};
        var path = options.path || "/";
        buffer.write("; path=", encodeURI(path));
        if (options.domain) {
            buffer.write("; domain=", options.domain.toLowerCase());
        }
        if (options.secure) {
            buffer.write("; secure");
        }
        if (options.httpOnly) {
            buffer.write("; HttpOnly");
        }
        this.addHeader("Set-Cookie", buffer.toString());
        return this;
    };

    /**
     * Close and convert this response into a JSGI response object.
     * @returns a JSGI 0.2 response object
     */
    this.close = function() {
        this.flushDebug();
        if (contentType && !headers.contains('content-type')) {
            if (charset) {
                contentType += "; charset=" + charset;
            }
            headers.set("Content-Type", contentType);
        }
        return {
            status: status,
            headers: headers,
            body: buffer
        };
    };

}

/**
 * A response object rendered from a skin.
 * @param {Resource|String} skin the skin resource or path.
 * @param {Object} context the skin context object
 */
function skinResponse(skin, context) {
    if (!(skin instanceof org.ringojs.repository.Resource)) {
        skin = getResource(skin);
    }
    var render = require('ringo/skin').render;
    return new Response(render(skin, context));
}

/**
 * Create a response object containing the JSON representation of an object.
 * @param {Object} object the object whose JSON representation to return
 */
function jsonResponse(object) {
    var res = new Response(JSON.stringify(object));
    res.contentType = 'application/json';
    return res;
}

/**
 * Create a response containing the given XML document
 * @param {XML|String} xml an XML document
 */
function xmlResponse(xml) {
    var res = new Response(typeof xml === 'xml' ? xml.toXMLString() : xml);
    res.contentType = 'application/xml';
    return res;
}

/**
 * A response representing a static resource.
 * @param {String|Resource} resource the resource to serve
 * @param {String} contentType optional MIME type. If not defined,
 *         the MIME type is detected from the file name extension.
 */
function staticResponse(resource, contentType) {
    if (typeof resource == 'string') {
        resource = getResource(resource);
    }
    if (!(resource instanceof org.ringojs.repository.Resource)) {
        throw Error("Wrong argument for staticResponse: " + typeof(resource));
    }
    if (!resource.exists()) {
        return notFoundResponse(String(resource));
    }
    var input;
    return {
        status: 200,
        headers: {
            'Content-Type': contentType || mimeType(resource.name)
        },
        body: {
            digest: function() {
                return resource.lastModified().toString(36)
                    + resource.length.toString(36);
            },
            forEach: function(fn) {
                var read, bufsize = 8192;
                var buffer = new ByteArray(bufsize);
                input = new Stream(resource.getInputStream());
                while ((read = input.readInto(buffer)) > -1) {
                    buffer.length = read;
                    fn(buffer);
                    buffer.length = bufsize;
                }
            },
            close: function() {
                if (input) {
                    input.close();
                }
            }
        }
    };
}

/**
 * Create a response that redirects the client to a different URL.
 * @param {String} location the new location
 */
function redirectResponse(location) {
    return {
        status: 303,
        headers: {Location: location},
        body: ["See other: " + location]
    };
}

/**
 * Create a 404 not-found response.
 * @param {String} location the location that couldn't be found
 */
function notFoundResponse(location) {
    var msg = 'Not Found';
    return {
        status: 404,
        headers: {
            'Content-Type': 'text/html'
        },
        body: [ '<title>', msg, '</title>',
                '
', msg, '
',
                '
The requested URL ', String(location), ' was not found on the server.
',
                '']
    };
}

/**
 * Create a 500 error response.
 * @param {String} msg the message of response body
 */
function errorResponse(msg) {
    return {
        status: 500,
        headers: {'Content-Type': 'text/plain'},
        body: [typeof msg === 'undefined' ? 'Something went wrong.' :
                String(msg)]
    };
}
<commit_msg>Try to locate skin resource both globally and relative to this-module in skinResponse()<commit_after>include('binary');
include('io');
include('ringo/buffer');
include('./util');
include('./mime');
require('core/date');

export('Response',
       'skinResponse',
       'jsonResponse',
       'xmlResponse',
       'staticResponse',
       'redirectResponse',
       'notFoundResponse',
       'errorResponse');

function Response() {

    // missing new security belt
    if (!(this instanceof Response)) {
        var response = new Response();
        response.write.apply(response, arguments);
        return response;
    }

    var config = require('ringo/webapp/env').config;
    var status = 200;
    var charset = config && config.charset || 'utf-8';
    var contentType = config && config.contentType || 'text/html';
    var headers = new Headers();
    var buffer = new Buffer();

    this.write = function write() {
        var length = arguments.length;
        for (var i = 0; i < length; i++) {
            buffer.write(String(arguments[i]));
            if (i < length - 1)
                buffer.write(' ');
        }
        return this;
    };

    this.write.apply(this, arguments);

    this.writeln = function writeln() {
        this.write.apply(this, arguments);
        buffer.write('\r\n');
        return this;
    };

    /**
     * Render a skin to the response's buffer
     * @param skin path to skin resource
     * @param context context object
     */
    this.render = function render(skin, context) {
        var render = require('ringo/skin').render;
        buffer.write(render(skin, context));
    };

    /**
     * Print a debug message to the rendered page.
     */
    this.debug =  function debug() {
        var buffer = this.debugBuffer || new Buffer();
        buffer.write("
");
        var length = arguments.length;
        for (var i = 0; i < length; i++) {
            buffer.write(arguments[i]);
            if (i < length - 1) {
                buffer.write(" ");
            }
        }
        buffer.writeln("
");
        this.debugBuffer = buffer;
        return null;
    };

    /**
     * Write the debug buffer to the response's main buffer.
     */
    this.flushDebug = function() {
        if (this.debugBuffer != null) {
            this.write(this.debugBuffer);
            this.debugBuffer.reset();
        }
        return null;
    };

    this.redirect = function(location) {
        status = 303;
        headers.set('Location', String(location));
    };

    Object.defineProperty(this, 'charset', {
        get: function() {
            return charset;
        },
        set: function(c) {
            charset = c;
        }
    });

    Object.defineProperty(this, 'contentType', {
        get: function() {
            return contentType;
        },
        set: function(c) {
            contentType = c;
        }
    });

    Object.defineProperty(this, 'status', {
        get: function() {
            return status;
        },
        set: function(s) {
            status = s;
        }
    });

    this.getHeader = function(key) {
        headers.get(String(key));
    };

    /**
     * Set a header to be sent to the client. If a header with this name was previously
     * set it will be replaced.
     * @param {String} key the header name
     * @param {String} value the header value
     * @returns {Response} this response for chainability
     */
    this.setHeader = function(key, value) {
        key = String(key);
        if (key.toLowerCase() == "content-type") {
            contentType = String(value);
            charset = getMimeParameter(contentType, "charset") || charset;
        }
        headers.set(key, String(value));
        return this;
    };

    /**
     * Add a header to be sent to the client. If a header with this name was previously
     * set it will not be replaced.
     * @param {String} key the header name
     * @param {String} value the header value
     * @returns {Response} this response for chainability
     */
    this.addHeader = function(key, value) {
        headers.add(String(key), String(value));
        return this;
    };

    /**
     * Sets a cookie to be sent to the client.
     * All arguments except for key and value are optional.
     * The days argument specifies the number of days until the cookie expires.
     * To delete a cookie immediately, set the days argument to 0. If days is
     * undefined or negative, the cookie is set for the current browser session.
     *
     * @example
res.setCookie("username", "michi");
     * res.setCookie("password", "strenggeheim", 10,
     *               {path: "/mypath", domain: ".mydomain.org"});

     *
     * @param {String} key the cookie name
     * @param {String} value the cookie value
     * @param {Number} days optional the number of days to keep the cookie.
     *     If this is undefined or -1, the cookie is set for the current session.
     *     If this is 0, the cookie will be deleted immediately.
     * @param {Object} options optional options argument which may contain the following properties:
     *

path - the path on which to set the cookie (defaults to /)

     *
domain -  the domain on which to set the cookie (defaults to current domain)

     *
secure - to only use this cookie for secure connections

     *
httpOnly - to make the cookie inaccessible to client side scripts

     * @since 0.5
     * @return {Response} this response object for chainability;
     */
    this.setCookie = function(key, value, days, options) {
        if (value) {
            // remove newline chars to prevent response splitting attack as value may be user-provided
            value = value.replace(/[\r\n]/g, "");
        }
        var buffer = new Buffer(key, "=", value);
        if (typeof days == "number" && days > -1) {
            var expires = days == 0 ?
                new Date(0) : new Date(Date.now() + days * 1000 * 60 * 60 * 24);
            var cookieDateFormat = "EEE, dd-MMM-yyyy HH:mm:ss zzz";
            buffer.write("; expires=");
            buffer.write(expires.format(cookieDateFormat, "en", "GMT"));
        }
        options = options || {};
        var path = options.path || "/";
        buffer.write("; path=", encodeURI(path));
        if (options.domain) {
            buffer.write("; domain=", options.domain.toLowerCase());
        }
        if (options.secure) {
            buffer.write("; secure");
        }
        if (options.httpOnly) {
            buffer.write("; HttpOnly");
        }
        this.addHeader("Set-Cookie", buffer.toString());
        return this;
    };

    /**
     * Close and convert this response into a JSGI response object.
     * @returns a JSGI 0.2 response object
     */
    this.close = function() {
        this.flushDebug();
        if (contentType && !headers.contains('content-type')) {
            if (charset) {
                contentType += "; charset=" + charset;
            }
            headers.set("Content-Type", contentType);
        }
        return {
            status: status,
            headers: headers,
            body: buffer
        };
    };

}

/**
 * A response object rendered from a skin.
 * @param {Resource|String} skin the skin resource or path.
 * @param {Object} context the skin context object
 */
function skinResponse(skin, context) {
    if (!(skin instanceof org.ringojs.repository.Resource)) {
        var s = getResource(skin);
        if (!s || !s.exists()) {
            // try locating resource relative to implicit this
            // which may be the calling module
            s = this.getResource(skin);
        }
        skin = s;
    }
    var render = require('ringo/skin').render;
    return new Response(render(skin, context));
}

/**
 * Create a response object containing the JSON representation of an object.
 * @param {Object} object the object whose JSON representation to return
 */
function jsonResponse(object) {
    var res = new Response(JSON.stringify(object));
    res.contentType = 'application/json';
    return res;
}

/**
 * Create a response containing the given XML document
 * @param {XML|String} xml an XML document
 */
function xmlResponse(xml) {
    var res = new Response(typeof xml === 'xml' ? xml.toXMLString() : xml);
    res.contentType = 'application/xml';
    return res;
}

/**
 * A response representing a static resource.
 * @param {String|Resource} resource the resource to serve
 * @param {String} contentType optional MIME type. If not defined,
 *         the MIME type is detected from the file name extension.
 */
function staticResponse(resource, contentType) {
    if (typeof resource == 'string') {
        resource = getResource(resource);
    }
    if (!(resource instanceof org.ringojs.repository.Resource)) {
        throw Error("Wrong argument for staticResponse: " + typeof(resource));
    }
    if (!resource.exists()) {
        return notFoundResponse(String(resource));
    }
    var input;
    return {
        status: 200,
        headers: {
            'Content-Type': contentType || mimeType(resource.name)
        },
        body: {
            digest: function() {
                return resource.lastModified().toString(36)
                    + resource.length.toString(36);
            },
            forEach: function(fn) {
                var read, bufsize = 8192;
                var buffer = new ByteArray(bufsize);
                input = new Stream(resource.getInputStream());
                while ((read = input.readInto(buffer)) > -1) {
                    buffer.length = read;
                    fn(buffer);
                    buffer.length = bufsize;
                }
            },
            close: function() {
                if (input) {
                    input.close();
                }
            }
        }
    };
}

/**
 * Create a response that redirects the client to a different URL.
 * @param {String} location the new location
 */
function redirectResponse(location) {
    return {
        status: 303,
        headers: {Location: location},
        body: ["See other: " + location]
    };
}

/**
 * Create a 404 not-found response.
 * @param {String} location the location that couldn't be found
 */
function notFoundResponse(location) {
    var msg = 'Not Found';
    return {
        status: 404,
        headers: {
            'Content-Type': 'text/html'
        },
        body: [ '<title>', msg, '</title>',
                '
', msg, '
',
                '
The requested URL ', String(location), ' was not found on the server.
',
                '']
    };
}

/**
 * Create a 500 error response.
 * @param {String} msg the message of response body
 */
function errorResponse(msg) {
    return {
        status: 500,
        headers: {'Content-Type': 'text/plain'},
        body: [typeof msg === 'undefined' ? 'Something went wrong.' :
                String(msg)]
    };
}
<|endoftext|>


<commit_before>var output_div = document.getElementById('stores_div');

// Build tables
function display_tables(store_array) {
  output_div.innerHTML = '';
  for (var i = 0; i < store_array.length; i++) {
    var current_store = store_array[i];

    // build h2 with store name
    var store_header = document.createElement('h3');
    store_header.appendChild(document.createTextNode(current_store.name));

    //start building table with header row
    var table_row = document.createElement('tr');
    var headers = ['Hour', 'Total Pizzas Made', 'Deliveries Made', 'Recommended Drivers'];
    for (var j = 0; j < headers.length; j++) {
      var th_col = document.createElement('th');
      th_col.appendChild(document.createTextNode(headers[j]));
      table_row.appendChild(th_col);
    }

    // build and assemble the table header
    var header_row = document.createElement('thead');
    header_row.appendChild(table_row);

    // now build tbody
    var tbody = document.createElement('tbody');
    for (var j = 0; j < current_store.estimates.length; j++) {
      // Iterate over each hour and make that data into a table row
      var table_row = document.createElement('tr');
      var cells = [current_store.estimates[j].time,
                   current_store.estimates[j].pizzas + ' (' + current_store.daily_projections[Math.floor(j / 3)][0] + ',' + current_store.daily_projections[Math.floor(j / 3)][1] + ')',
                   current_store.estimates[j].deliveries + ' (' + current_store.daily_projections[Math.floor(j / 3)][2] + ',' + current_store.daily_projections[Math.floor(j / 3)][3] + ')',
                   current_store.estimates[j].drivers];
      for (var k = 0; k < cells.length; k++) {
        var th_col = document.createElement('td');
        th_col.appendChild(document.createTextNode(cells[k]));
        if (k == 0) {
          th_col.setAttribute('class', 'no-wrap');
        }
        table_row.appendChild(th_col);
      }
      tbody.appendChild(table_row);
    }

    // and lastly build the table footer
    var tfoot = document.createElement('tfoot');
    var table_row = document.createElement('tr');
    var th_col = document.createElement('td');
    th_col.appendChild(document.createTextNode('Totals'));
    table_row.appendChild(th_col);
    th_col = document.createElement('td');
    th_col.appendChild(document.createTextNode(current_store.daily_total_pizzas));
    table_row.appendChild(th_col);
    th_col = document.createElement('td');
    th_col.appendChild(document.createTextNode(current_store.daily_total_deliveries));
    table_row.appendChild(th_col);
    tfoot.appendChild(table_row);

    // create and assemble the table element
    var table = document.createElement('table');
    table.appendChild(header_row);
    table.appendChild(tbody);
    table.appendChild(tfoot);

    // output the table and store name within a div per store
    var store_div = document.createElement('div');
    store_div.setAttribute('class', 'individual_store');
    store_div.setAttribute('id', current_store.name + '_div');
    store_div.appendChild(store_header);
    store_div.appendChild(table);
    output_div.appendChild(store_div);
  }
}

function display_hourly_totals(hourly_totals) {
  // build h3 for totals heading
  var store_header = document.createElement('h3');
  store_header.appendChild(document.createTextNode('Totals by Hour'));

  //start building table with header row
  var table_row = document.createElement('tr');
  var headers = ['Hour', 'Total Pizzas Made', 'Deliveries Made'];
  for (var j = 0; j < headers.length; j++) {
    var th_col = document.createElement('th');
    th_col.appendChild(document.createTextNode(headers[j]));
    table_row.appendChild(th_col);
  }

  // build and assemble the table header
  var header_row = document.createElement('thead');
  header_row.appendChild(table_row);

  // now build tbody
  var tbody = document.createElement('tbody');
  var pizza_totals = 0;
  var delivery_totals = 0;
  for (var key in hourly_totals) {
    var table_row = document.createElement('tr');
    pizza_totals += hourly_totals[key][0];
    delivery_totals += hourly_totals[key][1];
    var cells = [key,
                 hourly_totals[key][0],
                 hourly_totals[key][1]];
    for (var k = 0; k < cells.length; k++) {
      var th_col = document.createElement('td');
      th_col.appendChild(document.createTextNode(cells[k]));
      table_row.appendChild(th_col);
    }
    tbody.appendChild(table_row);
  }

  // and lastly build the table footer
  var tfoot = document.createElement('tfoot');
  var table_row = document.createElement('tr');
  var th_col = document.createElement('td');
  th_col.appendChild(document.createTextNode('Totals'));
  table_row.appendChild(th_col);
  th_col = document.createElement('td');
  th_col.appendChild(document.createTextNode(pizza_totals));
  table_row.appendChild(th_col);
  th_col = document.createElement('td');
  th_col.appendChild(document.createTextNode(delivery_totals));
  table_row.appendChild(th_col);
  tfoot.appendChild(table_row);

  // create and assemble the table element
  var table = document.createElement('table');
  table.appendChild(header_row);
  table.appendChild(tbody);
  table.appendChild(tfoot);

  // output the table and store name within a div per store
  var store_div = document.createElement('div');
  store_div.setAttribute('class', 'totals');
  store_div.appendChild(store_header);
  store_div.appendChild(table);
  output_div.appendChild(store_div);
}

function display_weekly_totals(stores) {
  // build h3 for section heading
  var store_header = document.createElement('h3');
  store_header.appendChild(document.createTextNode('Weekly Totals by Store'));

  var store_div = document.createElement('div');
  store_div.setAttribute('class', 'totals');
  store_div.appendChild(store_header);
  var total_of_totals = 0;
  // var h4_header;

  var table = document.createElement('table');
  var tr, td;
  for (var i = 0; i < stores.length; i++) {
    total_of_totals += stores[i].weekly_total_sales;

    tr = document.createElement('tr');
    td = document.createElement('td');
    td.appendChild(document.createTextNode(stores[i].name));
    tr.appendChild(td);
    td = document.createElement('td');
    td.appendChild(document.createTextNode(stores[i].weekly_total_sales));
    tr.appendChild(td);
    table.appendChild(tr);
  }

  tr = document.createElement('tr');
  td = document.createElement('td');
  td.appendChild(document.createTextNode('Grand Total'));
  tr.appendChild(td);
  td = document.createElement('td');
  td.appendChild(document.createTextNode(total_of_totals));
  tr.appendChild(td);
  table.appendChild(tr);
  table.setAttribute('class', 'grande');

  store_div.appendChild(table);
  store_div.setAttribute('class','totals');

  // output resulting div
  output_div.appendChild(store_div);
}

function render_add_store_form() {
  // create heading
  var add_store_heading = document.createElement('h3');
  add_store_heading.appendChild(document.createTextNode('Add New Location'));

  // create form
  var add_store_form = document.createElement('form');
  var add_store_fieldset = document.createElement('fieldset');
  var paragraph = document.createElement('p');
  var label = document.createElement('label');
  label.setAttribute('for', 'store_name_field');
  label.appendChild(document.createTextNode('Store name: '));
  var input = document.createElement('input');
  input.setAttribute('name', 'store_name_field');
  input.setAttribute('id', 'store_name_field');
  input.setAttribute('autocomplete', 'off');
  input.setAttribute('placeholder', 'Location or Name');
  input.setAttribute('required', 'required');
  paragraph.appendChild(label);
  paragraph.appendChild(input);
  add_store_fieldset.appendChild(paragraph);

  // create labels and data fields
  paragraph = document.createElement('p');
  label = document.createElement('label');
  label.setAttribute('for', 'opening_time_field');
  label.appendChild(document.createTextNode('Opening time: '));

  // create the spinner for opening hour, which can be from midnight to 11pm
  select = document.createElement('select');
  select.setAttribute('name', 'opening_time_field');
  select.setAttribute('id', 'opening_time_field');
  var option;
  for (var hour = 0; hour < 24; hour ++) {
    var time = new Date();
    time.setHours(hour);
    option = document.createElement('option');
    option.setAttribute('value', hour);
    if (hour == 8) {
      option.setAttribute('selected', 'selected');
    }
    select.appendChild(option);
    option.appendChild(document.createTextNode(format_time(time)));
  }
  paragraph.appendChild(label);
  paragraph.appendChild(select);
  add_store_fieldset.appendChild(paragraph);

  paragraph = document.createElement('p');
  label = document.createElement('label');
  label.setAttribute('for', 'hours_open_field');
  label.appendChild(document.createTextNode('Hours open per day: '));
  select = document.createElement('select');
  select.setAttribute('name', 'hours_open_field');
  select.setAttribute('id', 'hours_open_field');
  var option;
  for (var hour = 1; hour <= 24; hour ++) {
    option = document.createElement('option');
    option.setAttribute('value', hour);
    if (hour == 18) {
      option.setAttribute('selected', 'selected');
    }
    select.appendChild(option);
    option.appendChild(document.createTextNode(hour));
  }
  paragraph.appendChild(label);
  paragraph.appendChild(select);
  add_store_fieldset.appendChild(paragraph);
  // TODO: select.addEventListener('change', render_projections_table);

  // create table for new store projected sales
  var projections_table = document.createElement('table');
  projections_table.setAttribute('id', 'projections_table');
  //thead
  var projections_thead = document.createElement('thead');
  //row
  var projections_tr = document.createElement('tr');
  //th's
  var projections_th;
  var headers = ['Shift', 'Pizza Min', 'Pizza Max', 'Delivery Min', 'Delivery Max'];
  for (var i = 0; i < headers.length; i++) {
    projections_th = document.createElement('th');
    projections_th.appendChild(document.createTextNode(headers[i]));
    projections_tr.appendChild(projections_th);
  }
  projections_thead.appendChild(projections_tr);
  projections_table.appendChild(projections_thead);

  //tbody
  var projections_tbody = document.createElement('tbody');
  var projections_td;
  var projections_input;
  // visible rows will be projections[0].length
  for (var row = 0; row < 8; row++) {
    projections_tr = document.createElement('tr');
    projections_td = document.createElement('td');
    projections_td.appendChild(document.createTextNode('Shift ' + (row + 1)));
    projections_tr.appendChild(projections_td);
    projections_tr.setAttribute('id','projection_row_' + row);
    var temp_projections;
    if (row >= projections[0].length) {
      temp_projections = [0,0,0,0];
    } else {
      temp_projections = projections[0][row];
    }
    for (var col = 0; col < temp_projections.length; col++) {
      projections_td = document.createElement('td');
      projections_input = document.createElement('input');
      projections_input.setAttribute('type', 'number');
      projections_input.setAttribute('name', 'input_' + row + '_' + col);
      projections_input.setAttribute('autocomplete', 'off');
      projections_input.setAttribute('min', '0');
      projections_input.setAttribute('max', '999');
      projections_input.setAttribute('value', temp_projections[col]);
      projections_td.appendChild(projections_input);
      projections_tr.appendChild(projections_td);
    }
    projections_tbody.appendChild(projections_tr);
  }
  projections_table.appendChild(projections_tbody);
  add_store_fieldset.appendChild(projections_table);

  // create the button
  paragraph = document.createElement('p');
  var button = document.createElement('button');
  button.setAttribute('class','add_button');
  button.appendChild(document.createTextNode('Create Store'));
  paragraph.appendChild(button);
  add_store_fieldset.appendChild(paragraph);

  // complete the form
  add_store_form.appendChild(add_store_fieldset);
  add_store_form.addEventListener('submit', add_store);

  // append form to div
  var add_store_div = document.createElement('div');
  add_store_div.setAttribute('class', 'add_store_div modal-content');
  add_store_div.appendChild(add_store_heading);
  add_store_div.appendChild(add_store_form);

  // modal div
  var modal_div = document.createElement('div');
  modal_div.setAttribute('class', 'modal');
  modal_div.setAttribute('id', 'add_store_modal');
  modal_div.appendChild(add_store_div);

  // append div to output_div
  output_div.appendChild(modal_div);
}

function set_up_modal() {
  // Get the modal
  var modal = document.getElementById('add_store_modal');

  // Get the button that opens the modal
  var btn = document.getElementById('new_store_button');
  btn.style.display = 'block';

  // Get the <span> element that closes the modal
  var span = document.getElementsByClassName('close')[0];

  // When the user clicks the button, open the modal
  btn.addEventListener('click', display_modal, false);

  function display_modal() {
    modal.style.display = 'block';
    btn.style.display = 'none';
    document.getElementById('store_name_field').focus();
  };

  // When the user clicks anywhere outside of the modal, close it
  window.addEventListener('click', hide_modal, false);

  function hide_modal(event) {
    if (event.target == modal) {
      modal.style.display = 'none';
      btn.style.display = 'block';
    }
  };
}
<commit_msg>reactive shift entry rows finished<commit_after>var output_div = document.getElementById('stores_div');

// Build tables
function display_tables(store_array) {
  output_div.innerHTML = '';
  for (var i = 0; i < store_array.length; i++) {
    var current_store = store_array[i];

    // build h2 with store name
    var store_header = document.createElement('h3');
    store_header.appendChild(document.createTextNode(current_store.name));

    //start building table with header row
    var table_row = document.createElement('tr');
    var headers = ['Hour', 'Total Pizzas Made', 'Deliveries Made', 'Recommended Drivers'];
    for (var j = 0; j < headers.length; j++) {
      var th_col = document.createElement('th');
      th_col.appendChild(document.createTextNode(headers[j]));
      table_row.appendChild(th_col);
    }

    // build and assemble the table header
    var header_row = document.createElement('thead');
    header_row.appendChild(table_row);

    // now build tbody
    var tbody = document.createElement('tbody');
    for (var j = 0; j < current_store.estimates.length; j++) {
      // Iterate over each hour and make that data into a table row
      var table_row = document.createElement('tr');
      var cells = [current_store.estimates[j].time,
                   current_store.estimates[j].pizzas + ' (' + current_store.daily_projections[Math.floor(j / 3)][0] + ',' + current_store.daily_projections[Math.floor(j / 3)][1] + ')',
                   current_store.estimates[j].deliveries + ' (' + current_store.daily_projections[Math.floor(j / 3)][2] + ',' + current_store.daily_projections[Math.floor(j / 3)][3] + ')',
                   current_store.estimates[j].drivers];
      for (var k = 0; k < cells.length; k++) {
        var th_col = document.createElement('td');
        th_col.appendChild(document.createTextNode(cells[k]));
        if (k == 0) {
          th_col.setAttribute('class', 'no-wrap');
        }
        table_row.appendChild(th_col);
      }
      tbody.appendChild(table_row);
    }

    // and lastly build the table footer
    var tfoot = document.createElement('tfoot');
    var table_row = document.createElement('tr');
    var th_col = document.createElement('td');
    th_col.appendChild(document.createTextNode('Totals'));
    table_row.appendChild(th_col);
    th_col = document.createElement('td');
    th_col.appendChild(document.createTextNode(current_store.daily_total_pizzas));
    table_row.appendChild(th_col);
    th_col = document.createElement('td');
    th_col.appendChild(document.createTextNode(current_store.daily_total_deliveries));
    table_row.appendChild(th_col);
    tfoot.appendChild(table_row);

    // create and assemble the table element
    var table = document.createElement('table');
    table.appendChild(header_row);
    table.appendChild(tbody);
    table.appendChild(tfoot);

    // output the table and store name within a div per store
    var store_div = document.createElement('div');
    store_div.setAttribute('class', 'individual_store');
    store_div.setAttribute('id', current_store.name + '_div');
    store_div.appendChild(store_header);
    store_div.appendChild(table);
    output_div.appendChild(store_div);
  }
}

function display_hourly_totals(hourly_totals) {
  // build h3 for totals heading
  var store_header = document.createElement('h3');
  store_header.appendChild(document.createTextNode('Totals by Hour'));

  //start building table with header row
  var table_row = document.createElement('tr');
  var headers = ['Hour', 'Total Pizzas Made', 'Deliveries Made'];
  for (var j = 0; j < headers.length; j++) {
    var th_col = document.createElement('th');
    th_col.appendChild(document.createTextNode(headers[j]));
    table_row.appendChild(th_col);
  }

  // build and assemble the table header
  var header_row = document.createElement('thead');
  header_row.appendChild(table_row);

  // now build tbody
  var tbody = document.createElement('tbody');
  var pizza_totals = 0;
  var delivery_totals = 0;
  for (var key in hourly_totals) {
    var table_row = document.createElement('tr');
    pizza_totals += hourly_totals[key][0];
    delivery_totals += hourly_totals[key][1];
    var cells = [key,
                 hourly_totals[key][0],
                 hourly_totals[key][1]];
    for (var k = 0; k < cells.length; k++) {
      var th_col = document.createElement('td');
      th_col.appendChild(document.createTextNode(cells[k]));
      table_row.appendChild(th_col);
    }
    tbody.appendChild(table_row);
  }

  // and lastly build the table footer
  var tfoot = document.createElement('tfoot');
  var table_row = document.createElement('tr');
  var th_col = document.createElement('td');
  th_col.appendChild(document.createTextNode('Totals'));
  table_row.appendChild(th_col);
  th_col = document.createElement('td');
  th_col.appendChild(document.createTextNode(pizza_totals));
  table_row.appendChild(th_col);
  th_col = document.createElement('td');
  th_col.appendChild(document.createTextNode(delivery_totals));
  table_row.appendChild(th_col);
  tfoot.appendChild(table_row);

  // create and assemble the table element
  var table = document.createElement('table');
  table.appendChild(header_row);
  table.appendChild(tbody);
  table.appendChild(tfoot);

  // output the table and store name within a div per store
  var store_div = document.createElement('div');
  store_div.setAttribute('class', 'totals');
  store_div.appendChild(store_header);
  store_div.appendChild(table);
  output_div.appendChild(store_div);
}

function display_weekly_totals(stores) {
  // build h3 for section heading
  var store_header = document.createElement('h3');
  store_header.appendChild(document.createTextNode('Weekly Totals by Store'));

  var store_div = document.createElement('div');
  store_div.setAttribute('class', 'totals');
  store_div.appendChild(store_header);
  var total_of_totals = 0;
  // var h4_header;

  var table = document.createElement('table');
  var tr, td;
  for (var i = 0; i < stores.length; i++) {
    total_of_totals += stores[i].weekly_total_sales;

    tr = document.createElement('tr');
    td = document.createElement('td');
    td.appendChild(document.createTextNode(stores[i].name));
    tr.appendChild(td);
    td = document.createElement('td');
    td.appendChild(document.createTextNode(stores[i].weekly_total_sales));
    tr.appendChild(td);
    table.appendChild(tr);
  }

  tr = document.createElement('tr');
  td = document.createElement('td');
  td.appendChild(document.createTextNode('Grand Total'));
  tr.appendChild(td);
  td = document.createElement('td');
  td.appendChild(document.createTextNode(total_of_totals));
  tr.appendChild(td);
  table.appendChild(tr);
  table.setAttribute('class', 'grande');

  store_div.appendChild(table);
  store_div.setAttribute('class','totals');

  // output resulting div
  output_div.appendChild(store_div);
}

function render_add_store_form() {
  // create heading
  var add_store_heading = document.createElement('h3');
  add_store_heading.appendChild(document.createTextNode('Add New Location'));

  // create form
  var add_store_form = document.createElement('form');
  var add_store_fieldset = document.createElement('fieldset');
  var paragraph = document.createElement('p');
  var label = document.createElement('label');
  label.setAttribute('for', 'store_name_field');
  label.appendChild(document.createTextNode('Store name: '));
  var input = document.createElement('input');
  input.setAttribute('name', 'store_name_field');
  input.setAttribute('id', 'store_name_field');
  input.setAttribute('autocomplete', 'off');
  input.setAttribute('placeholder', 'Location or Name');
  input.setAttribute('required', 'required');
  paragraph.appendChild(label);
  paragraph.appendChild(input);
  add_store_fieldset.appendChild(paragraph);

  // create labels and data fields
  paragraph = document.createElement('p');
  label = document.createElement('label');
  label.setAttribute('for', 'opening_time_field');
  label.appendChild(document.createTextNode('Opening time: '));

  // create the spinner for opening hour, which can be from midnight to 11pm
  select = document.createElement('select');
  select.setAttribute('name', 'opening_time_field');
  select.setAttribute('id', 'opening_time_field');
  var option;
  for (var hour = 0; hour < 24; hour ++) {
    var time = new Date();
    time.setHours(hour);
    option = document.createElement('option');
    option.setAttribute('value', hour);
    if (hour == 8) {
      option.setAttribute('selected', 'selected');
    }
    select.appendChild(option);
    option.appendChild(document.createTextNode(format_time(time)));
  }
  paragraph.appendChild(label);
  paragraph.appendChild(select);
  add_store_fieldset.appendChild(paragraph);

  paragraph = document.createElement('p');
  label = document.createElement('label');
  label.setAttribute('for', 'hours_open_field');
  label.appendChild(document.createTextNode('Hours open per day: '));
  select = document.createElement('select');
  select.setAttribute('name', 'hours_open_field');
  select.setAttribute('id', 'hours_open_field');
  var option;
  for (var hour = 1; hour <= 24; hour ++) {
    option = document.createElement('option');
    option.setAttribute('value', hour);
    if (hour == 18) {
      option.setAttribute('selected', 'selected');
    }
    select.appendChild(option);
    option.appendChild(document.createTextNode(hour));
  }
  select.addEventListener('change', adjust_shift_visibility, false);
  paragraph.appendChild(label);
  paragraph.appendChild(select);
  add_store_fieldset.appendChild(paragraph);
  // TODO: select.addEventListener('change', render_projections_table);

  // create table for new store projected sales
  var projections_table = document.createElement('table');
  projections_table.setAttribute('id', 'projections_table');
  //thead
  var projections_thead = document.createElement('thead');
  //row
  var projections_tr = document.createElement('tr');
  //th's
  var projections_th;
  var headers = ['Shift', 'Pizza Min', 'Pizza Max', 'Delivery Min', 'Delivery Max'];
  for (var i = 0; i < headers.length; i++) {
    projections_th = document.createElement('th');
    projections_th.appendChild(document.createTextNode(headers[i]));
    projections_tr.appendChild(projections_th);
  }
  projections_thead.appendChild(projections_tr);
  projections_table.appendChild(projections_thead);

  //tbody
  var projections_tbody = document.createElement('tbody');
  var projections_td;
  var projections_input;
  // visible rows will be projections[0].length
  for (var row = 0; row < 8; row++) {
    projections_tr = document.createElement('tr');
    projections_td = document.createElement('td');
    projections_td.appendChild(document.createTextNode('Shift ' + (row + 1)));
    projections_tr.appendChild(projections_td);
    projections_tr.setAttribute('id','projection_row_' + row);
    var temp_projections;
    if (row >= projections[0].length) {
      temp_projections = [0,0,0,0];
    } else {
      temp_projections = projections[0][row];
    }
    for (var col = 0; col < temp_projections.length; col++) {
      projections_td = document.createElement('td');
      projections_input = document.createElement('input');
      projections_input.setAttribute('type', 'number');
      projections_input.setAttribute('name', 'input_' + row + '_' + col);
      projections_input.setAttribute('autocomplete', 'off');
      projections_input.setAttribute('min', '0');
      projections_input.setAttribute('max', '999');
      projections_input.setAttribute('value', temp_projections[col]);
      projections_td.appendChild(projections_input);
      projections_tr.appendChild(projections_td);
    }
    projections_tbody.appendChild(projections_tr);
  }
  projections_table.appendChild(projections_tbody);
  add_store_fieldset.appendChild(projections_table);

  // create the button
  paragraph = document.createElement('p');
  var button = document.createElement('button');
  button.setAttribute('class','add_button');
  button.appendChild(document.createTextNode('Create Store'));
  paragraph.appendChild(button);
  add_store_fieldset.appendChild(paragraph);

  // complete the form
  add_store_form.appendChild(add_store_fieldset);
  add_store_form.addEventListener('submit', add_store);

  // append form to div
  var add_store_div = document.createElement('div');
  add_store_div.setAttribute('class', 'add_store_div modal-content');
  add_store_div.appendChild(add_store_heading);
  add_store_div.appendChild(add_store_form);

  // modal div
  var modal_div = document.createElement('div');
  modal_div.setAttribute('class', 'modal');
  modal_div.setAttribute('id', 'add_store_modal');
  modal_div.appendChild(add_store_div);

  // append div to output_div
  output_div.appendChild(modal_div);
}

function set_up_modal() {
  // Get the modal
  var modal = document.getElementById('add_store_modal');

  // Get the button that opens the modal
  var btn = document.getElementById('new_store_button');
  btn.style.display = 'block';

  // Get the <span> element that closes the modal
  var span = document.getElementsByClassName('close')[0];

  // When the user clicks the button, open the modal
  btn.addEventListener('click', display_modal, false);

  function display_modal() {
    modal.style.display = 'block';
    btn.style.display = 'none';
    document.getElementById('store_name_field').focus();
  };

  // When the user clicks anywhere outside of the modal, close it
  window.addEventListener('click', hide_modal, false);

  function hide_modal(event) {
    if (event.target == modal) {
      modal.style.display = 'none';
      btn.style.display = 'block';
    }
  };
}

function adjust_shift_visibility() {
  var hours_open = document.getElementById('hours_open_field').value;
  var shifts_to_display = Math.ceil(hours_open / 3);
  for (var i = 0; i < shifts_to_display; i++) {
    document.getElementById('projection_row_' + i).removeAttribute('hidden');
  }
  for (var i = shifts_to_display; i < 8; i++) {
    document.getElementById('projection_row_' + i).setAttribute('hidden','hidden');
  }
}
<|endoftext|>


<commit_before>var NumWWs = 0;
var MaxWWs = 10;
const WH_TIME = 0;

var Admins = ["Dino.", "α|CraftSpider|Ω", "HiddenStorys"];

var Commands = {
	"seen": function(user) {
	    postMessage("Sorry, this command doesn't work yet.");
// 		searchMessages("{V:" + user[0] + "}");
	},
	"wordWar": function(length) {
		if (length[0] > 60 || length[0] <= 0) {
			postMessage("Choose a number between 1 and 60.");
		} else if (NumWWs >= MaxWWs) {
		    postMessage("Too many word wars, I can't keep up! Wait for one to finish first.");
		} else {
		    NumWWs++;
			postMessage("I'm starting a " + length[0] + " minute word war." + (length[1]? " Keyword: " + length[1]  + "." : "") + " Go!");
			setTimeout(function() {
			    postMessage("Word War " + (length[1]? "'" + length[1] + "' " : "") + "ends. How did you do?");
			    NumWWs--;
			}, length[0] * 60000);
		}
	},
	"help": function (args) {
	    if (!args[0]) {
		    var helpList = "Greetings. I'm Talos, chat helper. My commands are:\n";
		    for (var C in Commands) {
		    	helpList += "^" + C + "\n";
		    }
		    helpList += "\nMy Admin Commands are:\n";
		    for (var C in AdminCommands) {
		    	helpList += "^" + C + "\n";
		    }
		    postMessage(helpList);
	    } else {
	        switch (args[0]) {
	            case "help":
	                postMessage("Use: ^help [Command Name]\nDescription: Help command, by default gives general information about Talos and a list of available commands. Adding the name of another command as an argument will give a more detailed description of that command. Though you probably figured that out, you're here after all :P");

	                break;
	            case "seen":
	                postMessage("Use: ^seen <Username>\nDescription:");

	                break;
	            case "toggleLock":
	                postMessage("Use: ^toggleLock [time]\nDescription:");

	                break;
	            case "wordWar":
	                postMessage("Use: ^wordWar <time> [keyword]\nDescription:");

	                break;
	            default:
	        }
	    }
	}
};

var AdminCommands = {
    "toggleLock": function(time) {
		toggleChatLock();
		if (time[0]) {
		    setTimeout( function() {
		        toggleChatLock();
		    }, time[0] * 60000);
		}
	},
};

function postMessage(message) {
    // X92.value = message;
    // X342();
    X279(message);
}

function privateMessage(name, message) {
	postMessage("/pm \"" + name + "\" " + message);
}

//Note, only sends the message to online users.
function globalMessage(message) {
	var users = X330.split("\n");
	for (var i = 1; i <= users[0]; i++) {
		user = users[i].split("	");
		privateMessage(user[0], message);	//Replace the 0 with other numbers to grab different values. 2 is last leave/exit, 4 is status, 5 is location.
	}
}

function searchMessages(term) {
	postMessage("/find " + term);

}

///requires re-init of JSBot. Automate that?
function changeName(name) {
	X292('X387');

	setTimeout(function() {
		X481.value = name;
		X544.onsubmit();
	}, 1000);
}

function closeChat() {
	X279("/close");
}

function openChat() {
	X279("/open");
}

function toggleChatLock() {
	if(X105.X398) {
		X279("/open");
	} else {
		X279("/close");
	}
}

var WHActive = false;
var WHAlertOne = false;
var WHAlertTwo = false;

function writingHour() {
    d = new Date();

    if (d.getUTCHours() == WH_TIME && d.getUTCMinutes() == 0 && !WHActive) {
        postMessage("[b]Writing Hour has started.[/b] Have fun, and use it productively!");
        WHActive = true;
        setTimeout(function() {closeChat();}, 500);
        setTimeout(function() {
            openChat();
            setTimeout(function() {postMessage("[b]Writing Hour is over.[/b] How did you do?");}, 500);
            WHActive = false;
            WHAlertTwo = false;
            WHAlertOne = false;
        }, 60 * 60000);

    } else if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1)  && d.getUTCMinutes() == 50 && !WHAlertOne) {
        postMessage("[b][Alert][/b] Writing Hour starts in 10 minutes!");
        WHAlertOne = true;

    } else if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1) && d.getUTCMinutes() == 55 && !WHAlertTwo) {
        postMessage("[b][Alert][/b] Writing Hour starts in 5 minutes!");
        WHAlertTwo = true;
    }
}

function readChat() {
	var Messages = X17("X138").innerHTML.split("\n");
	for (var i = 1; i < Messages.length; i++) {
		var Message = Messages[i];
		if (Message.match(/(.*)<\/b>: \^(\w+)(?:\s(.+))?/)) { //Instead of matching a set list of commands, match the word then check it against a dict?
		    var User = RegExp.$1;
			var Command = RegExp.$2;
			var Args = RegExp.$3.split(/[\s]| <span/);
		    var isAdmin = false;
			for (var U in Admins) {
			    if (User == Admins[U]) {
			        isAdmin = true;
			        break;
			    }
			}
			if (window["AdminCommands"][Command] && isAdmin) {
			    window["AdminCommands"][Command](Args);
			} else if (window["AdminCommands"][Command] && !isAdmin) {
			    postMessage("Sorry, that command is Admin only, and I don't recognize you!");
			} else if (window["Commands"][Command]) {
				window["Commands"][Command](Args);
			} else {
			    postMessage("Sorry, I don't understand that. May I suggest ^help?");
			}
		}
	}

	X17("X138").innerHTML = '
Previous messages parsed (press ESC to re-parse page)
\n';
	X783 = false;
}

function mainLoop() {
    readChat();
    writingHour();

}

setInterval(function() {mainLoop();}, 1000);
X17("X138").innerHTML = '
Previous messages hidden. (press ESC to re-parse page)
\n';
X783 = false;
<commit_msg>Changed admin spelling<commit_after>var NumWWs = 0;
var MaxWWs = 10;
const WH_TIME = 0;

var Admins = ["Dino", "α|CraftSpider|Ω", "HiddenStorys"];

var Commands = {
	"seen": function(user) {
	    postMessage("Sorry, this command doesn't work yet.");
// 		searchMessages("{V:" + user[0] + "}");
	},
	"wordWar": function(length) {
		if (length[0] > 60 || length[0] <= 0) {
			postMessage("Choose a number between 1 and 60.");
		} else if (NumWWs >= MaxWWs) {
		    postMessage("Too many word wars, I can't keep up! Wait for one to finish first.");
		} else {
		    NumWWs++;
			postMessage("I'm starting a " + length[0] + " minute word war." + (length[1]? " Keyword: " + length[1]  + "." : "") + " Go!");
			setTimeout(function() {
			    postMessage("Word War " + (length[1]? "'" + length[1] + "' " : "") + "ends. How did you do?");
			    NumWWs--;
			}, length[0] * 60000);
		}
	},
	"help": function (args) {
	    if (!args[0]) {
		    var helpList = "Greetings. I'm Talos, chat helper. My commands are:\n";
		    for (var C in Commands) {
		    	helpList += "^" + C + "\n";
		    }
		    helpList += "\nMy Admin Commands are:\n";
		    for (var C in AdminCommands) {
		    	helpList += "^" + C + "\n";
		    }
		    postMessage(helpList);
	    } else {
	        switch (args[0]) {
	            case "help":
	                postMessage("Use: ^help [Command Name]\nDescription: Help command, by default gives general information about Talos and a list of available commands. Adding the name of another command as an argument will give a more detailed description of that command. Though you probably figured that out, you're here after all :P");

	                break;
	            case "seen":
	                postMessage("Use: ^seen <Username>\nDescription:");

	                break;
	            case "toggleLock":
	                postMessage("Use: ^toggleLock [time]\nDescription:");

	                break;
	            case "wordWar":
	                postMessage("Use: ^wordWar <time> [keyword]\nDescription:");

	                break;
	            default:
	        }
	    }
	}
};

var AdminCommands = {
    "toggleLock": function(time) {
		toggleChatLock();
		if (time[0]) {
		    setTimeout( function() {
		        toggleChatLock();
		    }, time[0] * 60000);
		}
	},
};

function postMessage(message) {
    // X92.value = message;
    // X342();
    X279(message);
}

function privateMessage(name, message) {
	postMessage("/pm \"" + name + "\" " + message);
}

//Note, only sends the message to online users.
function globalMessage(message) {
	var users = X330.split("\n");
	for (var i = 1; i <= users[0]; i++) {
		user = users[i].split("	");
		privateMessage(user[0], message);	//Replace the 0 with other numbers to grab different values. 2 is last leave/exit, 4 is status, 5 is location.
	}
}

function searchMessages(term) {
	postMessage("/find " + term);

}

///requires re-init of JSBot. Automate that?
function changeName(name) {
	X292('X387');

	setTimeout(function() {
		X481.value = name;
		X544.onsubmit();
	}, 1000);
}

function closeChat() {
	X279("/close");
}

function openChat() {
	X279("/open");
}

function toggleChatLock() {
	if(X105.X398) {
		X279("/open");
	} else {
		X279("/close");
	}
}

var WHActive = false;
var WHAlertOne = false;
var WHAlertTwo = false;

function writingHour() {
    d = new Date();

    if (d.getUTCHours() == WH_TIME && d.getUTCMinutes() == 0 && !WHActive) {
        postMessage("[b]Writing Hour has started.[/b] Have fun, and use it productively!");
        WHActive = true;
        setTimeout(function() {closeChat();}, 500);
        setTimeout(function() {
            openChat();
            setTimeout(function() {postMessage("[b]Writing Hour is over.[/b] How did you do?");}, 500);
            WHActive = false;
            WHAlertTwo = false;
            WHAlertOne = false;
        }, 60 * 60000);

    } else if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1)  && d.getUTCMinutes() == 50 && !WHAlertOne) {
        postMessage("[b][Alert][/b] Writing Hour starts in 10 minutes!");
        WHAlertOne = true;

    } else if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1) && d.getUTCMinutes() == 55 && !WHAlertTwo) {
        postMessage("[b][Alert][/b] Writing Hour starts in 5 minutes!");
        WHAlertTwo = true;
    }
}

function readChat() {
	var Messages = X17("X138").innerHTML.split("\n");
	for (var i = 1; i < Messages.length; i++) {
		var Message = Messages[i];
		if (Message.match(/(.*)<\/b>: \^(\w+)(?:\s(.+))?/)) { //Instead of matching a set list of commands, match the word then check it against a dict?
		    var User = RegExp.$1;
			var Command = RegExp.$2;
			var Args = RegExp.$3.split(/[\s]| <span/);
		    var isAdmin = false;
			for (var U in Admins) {
			    if (User == Admins[U]) {
			        isAdmin = true;
			        break;
			    }
			}
			if (window["AdminCommands"][Command] && isAdmin) {
			    window["AdminCommands"][Command](Args);
			} else if (window["AdminCommands"][Command] && !isAdmin) {
			    postMessage("Sorry, that command is Admin only, and I don't recognize you!");
			} else if (window["Commands"][Command]) {
				window["Commands"][Command](Args);
			} else {
			    postMessage("Sorry, I don't understand that. May I suggest ^help?");
			}
		}
	}

	X17("X138").innerHTML = '
Previous messages parsed (press ESC to re-parse page)
\n';
	X783 = false;
}

function mainLoop() {
    readChat();
    writingHour();

}

setInterval(function() {mainLoop();}, 1000);
X17("X138").innerHTML = '
Previous messages hidden. (press ESC to re-parse page)
\n';
X783 = false;
<|endoftext|>


<commit_before>var q = require('q');

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

var INPUTS_DATA_SRC = 'analog_inputs/inputs.json';
var RANGES_DATA_SRC = 'analog_inputs/ranges.json';
var RANGES_TEMPLATE_SRC = 'analog_inputs/range_options.html';
var INPUTS_TEMPLATE_SRC = 'analog_inputs/input_config.html';

var CONTROLS_MATRIX_SELECTOR = '#controls-matrix';
var RANGE_LISTS_SELECTOR = '.range-list';
var RANGE_LOADING_INDICATOR_SELECTOR = '#loading-ranges-display';

function loadRangeOptions()
{
    var deferred = q.defer();
    var templateLocation = fs_facade.getExternalURI(RANGES_TEMPLATE_SRC);
    var rangesSrc = fs_facade.getExternalURI(RANGES_DATA_SRC);

    fs_facade.getJSON(rangesSrc, genericErrorHandler, function(rangeInfo){

        fs_facade.renderTemplate(
            templateLocation,
            {'ranges': rangeInfo},
            genericErrorHandler,
            function(renderedHTML)
            {
                $(RANGE_LISTS_SELECTOR).html(renderedHTML);
                $(RANGE_LOADING_INDICATOR_SELECTOR).fadeOut();

                deferred.resolve();
            }
        );

    });

    return deferred.promise;
}

function loadInputs()
{
    var deferred = q.defer();
    var templateLocation = fs_facade.getExternalURI(INPUTS_TEMPLATE_SRC);
    var inputsSrc = fs_facade.getExternalURI(INPUTS_DATA_SRC);

    fs_facade.getJSON(inputsSrc, genericErrorHandler, function(inputsInfo){
        fs_facade.renderTemplate(
            templateLocation,
            {'inputs': inputsInfo},
            genericErrorHandler,
            function(renderedHTML)
            {
                $(CONTROLS_MATRIX_SELECTOR).fadeOut(function(){
                    $(CONTROLS_MATRIX_SELECTOR).html(renderedHTML);
                    $(CONTROLS_MATRIX_SELECTOR).fadeIn();

                    deferred.resolve();
                });
            }
        );
    });

    return deferred.promise;
}

$('#analog-inputs-configuration').ready(function(){
    loadInputs().then(loadRangeOptions).done();
});<commit_msg>Reduced fade effects in analog inputs config UI.<commit_after>var q = require('q');

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

var INPUTS_DATA_SRC = 'analog_inputs/inputs.json';
var RANGES_DATA_SRC = 'analog_inputs/ranges.json';
var RANGES_TEMPLATE_SRC = 'analog_inputs/range_options.html';
var INPUTS_TEMPLATE_SRC = 'analog_inputs/input_config.html';

var CONTROLS_MATRIX_SELECTOR = '#controls-matrix';
var RANGE_LISTS_SELECTOR = '.range-list';
var RANGE_LOADING_INDICATOR_SELECTOR = '#loading-ranges-display';

function loadRangeOptions()
{
    var deferred = q.defer();
    var templateLocation = fs_facade.getExternalURI(RANGES_TEMPLATE_SRC);
    var rangesSrc = fs_facade.getExternalURI(RANGES_DATA_SRC);

    fs_facade.getJSON(rangesSrc, genericErrorHandler, function(rangeInfo){

        fs_facade.renderTemplate(
            templateLocation,
            {'ranges': rangeInfo},
            genericErrorHandler,
            function(renderedHTML)
            {
                $(RANGE_LISTS_SELECTOR).html(renderedHTML);
                $(RANGE_LOADING_INDICATOR_SELECTOR).fadeOut();

                deferred.resolve();
            }
        );

    });

    return deferred.promise;
}

function loadInputs()
{
    var deferred = q.defer();
    var templateLocation = fs_facade.getExternalURI(INPUTS_TEMPLATE_SRC);
    var inputsSrc = fs_facade.getExternalURI(INPUTS_DATA_SRC);

    fs_facade.getJSON(inputsSrc, genericErrorHandler, function(inputsInfo){
        fs_facade.renderTemplate(
            templateLocation,
            {'inputs': inputsInfo},
            genericErrorHandler,
            function(renderedHTML)
            {
                $(CONTROLS_MATRIX_SELECTOR).hide(function(){
                    $(CONTROLS_MATRIX_SELECTOR).html(renderedHTML);
                    $(CONTROLS_MATRIX_SELECTOR).fadeIn();

                    deferred.resolve();
                });
            }
        );
    });

    return deferred.promise;
}

$('#analog-inputs-configuration').ready(function(){
    loadInputs().then(loadRangeOptions).done();
});<|endoftext|>


<commit_before>var rest = require('./../rest');

module.exports = function(pool, router, table, path) {
    path = path || '/' + table;

    var query = 'SELECT ' +
        'expertise.id, ' +
        'expertise.name, ' +
        'expertise.description, ' +
        'expertise.hidden, ' +
        'expertise.expertisetype_id, ' +
        'expertisetype.name AS expertisetype_name, ' +
        'expertisetype.maximum, ' +
        'expertisetype.skill_attribute_required, ' +
        'expertisetype.skill_attribute_increment, ' +
        'expertisetype.startsat, ' +
        'expertise.species_id, ' +
        'species.name AS species_name, ' +
        'expertise.manifestation_id, ' +
        'manifestation.name AS manifestation_name, ' +
        'expertise.skill_attribute_id, ' +
        'a1.name AS skill_attribute_name, ' +
        'expertise.give_attribute_id, ' +
        'a2.name AS give_attribute_name, ' +
        'icon.path AS icon_path ' +
        'FROM world_has_expertise ' +
        'LEFT JOIN expertise ON expertise.id = world_has_expertise.expertise_id ' +
        'LEFT JOIN expertisetype ON expertisetype.id = expertise.expertisetype_id ' +
        'LEFT JOIN species ON species.id = expertise.species_id ' +
        'LEFT JOIN manifestation ON manifestation.id = expertise.manifestation_id ' +
        'LEFT JOIN attribute a1 ON a1.id = expertise.skill_attribute_id ' +
        'LEFT JOIN attribute a2 ON a2.id = expertise.give_attribute_id ' +
        'LEFT JOIN icon ON icon.id = a1.icon_id';

    require('../default-has')(pool, router, table, path, ["world_id","expertise_id"]);

    router.get(path + '/id/:id', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id]);
    });

    router.get(path + '/id/:id1/type/:id2', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2]);
    });

    router.get(path + '/id/:id1/type/:id2/skill/:id3/species/:id4', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            'expertise.manifestation_id IS NULL AND ' +
            '(expertise.species_id = ? OR expertise.species_id IS NULL) AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3, req.params.id4]);
    });

    router.get(path + '/id/:id1/type/:id2/skill/:id3/species/:id4/manifestation/:id5', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            '(expertise.species_id = ? OR expertise.species_id IS NULL) AND ' +
            '(expertise.manifestation_id = ? OR expertise.manifestation_id IS NULL) AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3, req.params.id4, req.params.id5]);
    });

    router.get(path + '/id/:id1/skill/:id2', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2]);
    });

    router.get(path + '/id/:id1/skill/:id2/species/:id3', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            'expertise.manifestation_id IS NULL AND ' +
            '(expertise.species_id = ? OR expertise.species_id IS NULL) AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3]);
    });

    router.get(path + '/id/:id1/skill/:id2/species/:id3/manifestation/:id4', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            '(expertise.species_id = ? OR expertise.species_id IS NULL) AND ' +
            '(expertise.manifestation_id = ? OR expertise.manifestation_id IS NULL) AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3, req.params.id4]);
    });
};<commit_msg>expertise<commit_after>var rest = require('./../rest');

module.exports = function(pool, router, table, path) {
    path = path || '/' + table;

    var query = 'SELECT ' +
        'expertise.id, ' +
        'expertise.name, ' +
        'expertise.description, ' +
        'expertise.hidden, ' +
        'expertise.expertisetype_id, ' +
        'expertisetype.name AS expertisetype_name, ' +
        'expertisetype.maximum, ' +
        'expertisetype.skill_attribute_required, ' +
        'expertisetype.skill_attribute_increment, ' +
        'expertisetype.startsat, ' +
        'expertise.species_id, ' +
        'species.name AS species_name, ' +
        'expertise.manifestation_id, ' +
        'manifestation.name AS manifestation_name, ' +
        'expertise.skill_attribute_id, ' +
        'a1.name AS skill_attribute_name, ' +
        'expertise.give_attribute_id, ' +
        'a2.name AS give_attribute_name, ' +
        'icon.path AS icon_path ' +
        'FROM world_has_expertise ' +
        'LEFT JOIN expertise ON expertise.id = world_has_expertise.expertise_id ' +
        'LEFT JOIN expertisetype ON expertisetype.id = expertise.expertisetype_id ' +
        'LEFT JOIN species ON species.id = expertise.species_id ' +
        'LEFT JOIN manifestation ON manifestation.id = expertise.manifestation_id ' +
        'LEFT JOIN attribute a1 ON a1.id = expertise.skill_attribute_id ' +
        'LEFT JOIN attribute a2 ON a2.id = expertise.give_attribute_id ' +
        'LEFT JOIN icon ON icon.id = a1.icon_id';

    require('../default-has')(pool, router, table, path, ["world_id","expertise_id"]);

    router.get(path + '/id/:id', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id]);
    });

    router.get(path + '/id/:id1/type/:id2', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2]);
    });

    router.get(path + '/id/:id1/type/:id2/skill/:id3', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3]);
    });

    router.get(path + '/id/:id1/type/:id2/skill/:id3/species/:id4', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            'expertise.manifestation_id IS NULL AND ' +
            '(expertise.species_id = ? OR expertise.species_id IS NULL) AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3, req.params.id4]);
    });

    router.get(path + '/id/:id1/type/:id2/skill/:id3/species/:id4/manifestation/:id5', function(req, res) {
        var call = query + ' WHERE ' +
            'world_has_expertise.world_id = ? AND ' +
            'expertise.expertisetype_id = ? AND ' +
            'expertise.skill_attribute_id = ? AND ' +
            '(expertise.species_id = ? OR expertise.species_id IS NULL) AND ' +
            '(expertise.manifestation_id = ? OR expertise.manifestation_id IS NULL) AND ' +
            'expertise.hidden = \'0\' AND ' +
            'expertise.deleted IS NULL';

        rest.QUERY(pool, req, res, call, [req.params.id1, req.params.id2, req.params.id3, req.params.id4, req.params.id5]);
    });
};<|endoftext|>


<commit_before>/**
 * Competence class
 */
function Competence(viewmodel, id, code, name, weight, locked, subcompetences) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        weight: ko.observable(weight),
        locked: false,
        subcompetences: ko.observableArray(subcompetences),

        addSubCompetence: function() {
            this.subcompetences.push(new SubCompetence(this));
            automatedWeightCalculation(this.subcompetences());
            /*var total = 100;
            alert(total);
            console.log(this.subcompetences);
            for(var sub in this.subcompetences){
                alert(sub);
                sub.calculateWeight(100);
                total -= sub.weight;
                alert(total);
            }*/
        },

        removeThis: function() {
            viewmodel.removeCompetence(this);
        },

        toggleLock: function(data, event){
            if(this.locked == true)
            {
                $(event.target).addClass("icon-unlock").removeClass("icon-lock");
                this.locked = false;
            }
            else
            {
                $(event.target).addClass("icon-lock").removeClass("icon-unlock");
                this.locked = true;
            }
        },

        removeSubCompetence: function(subCompetence) {
            this.subcompetences.remove(subCompetence);
            automatedWeightCalculation(this.subcompetences());
        }
    };

}

/**
 * SubCompetence class
 */
function SubCompetence(parent, id, code, name, weight, locked, indicators) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        weight: ko.observable(weight),
        locked: false,
        indicators: ko.observableArray(indicators),

        addIndicator: function() {
            this.indicators.push(new Indicator(this));
            automatedWeightCalculation(this.indicators());
        },

        /*calculateWeight: function(total){
            this.weight = total;
        },*/

        removeThis: function() {
            parent.removeSubCompetence(this);

        },

        toggleLock: function(data, event){
            if(this.locked == true)
            {
                $(event.target).addClass("icon-unlock").removeClass("icon-lock");
                this.locked = false;
            }
            else
            {
                $(event.target).addClass("icon-lock").removeClass("icon-unlock");
                this.locked = true;
            }
        },

        removeIndicator: function(indicator) {
            this.indicators.remove(indicator);
            automatedWeightCalculation(this.indicators());
        }

    };
}

/**
 * Indicator class
 */
function Indicator(parent, id, name, weight, locked, description) {
    return {
        id: ko.observable(id),
        name: ko.observable(name),
        weight: ko.observable(weight),
        locked: false,
        description : ko.observable(description),

        removeThis: function() {
            parent.removeIndicator(this);
        },

        toggleLock: function(data, event){
            if(this.locked == true)
            {
                $(event.target).addClass("icon-unlock").removeClass("icon-lock");
                this.locked = false;
            }
            else
            {
                $(event.target).addClass("icon-lock").removeClass("icon-unlock");
                this.locked = true;
            }
        }
    };
}

// View model for the courses page
function pageViewModel(gvm) {
    // projecttitle
    gvm.projecttitle = ko.observable("");
    //gvm.competences = 0;
    gvm.subcomp = 0;

    // Page specific i18n bindings
    gvm.title = ko.computed(function (){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("ProjectTitle") + ": " + gvm.projecttitle();}, gvm);
    gvm.pageHeader = ko.observable("Project");
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.addCompetenceBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddCompetence");}, gvm);
    gvm.savePage = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SaveBtn");}, gvm);

    gvm.competences = ko.observableArray([]);

    gvm.addCompetence = function() {
        gvm.competences.push(new Competence(this));
        automatedWeightCalculation(this.competences());

        // Update automated weight calculation
        ko.utils.arrayForEach(gvm.competences, function(competence){
            console.log(competence.weight);
            competence.weight(percent);
        });
    };

    gvm.removeCompetence = function(competence) {
        gvm.competences.remove(competence);
        automatedWeightCalculation(this.competences());
    }

    gvm.updateCompetence = function(id, code, description, max, weight) {
        var comp = new Competence(this, id, code, description, weight);
        gvm.competences.push(comp);
        return comp;
    }

    gvm.clearStructure = function() {
        gvm.competences.destroyAll();
    }
}

/**
 * Push the current project state to the database
 * @returns {undefined}
 */
function saveProjectStructure() {
    $.ajax({
       type: "POST",
       url: "/api/projectstructure/" + projectid,
       data: ko.toJSON(viewModel.competences),
       success: function(){
           // TODO make multilangual and with modals
           alert("Saved projectstructure to server");

           fetchProjectStructure();
       }
    });
}

function fetchProjectStructure() {
    viewModel.clearStructure();

    $.getJSON("/api/projectstructure/" + projectid, function(data){
        $.each(data, function(i, item){
            var competence = viewModel.updateCompetence(item.id, item.code, item.description, item.max, item.weight);

            $.each(item.subcompetences, function(i, subcomp){
               var subcompetence = new SubCompetence(competence, subcomp.id, subcomp.code, subcomp.description, subcomp.weight);
               competence.subcompetences.push(subcompetence);

               $.each(subcomp.indicators, function(i, indic){
                  subcompetence.indicators.push(new Indicator(subcompetence, indic.id, indic.name, indic.description));
               });
            });
        })
    });
}

function initPage() {
    fetchProjectStructure();

    $(".addCompetenceBtn").click(function() {
        viewModel.addCompetence();
    });

    $(".savePageBtn").click(function(){
        if(totalPercentCheck()) {
            saveProjectStructure();
            console.log("Saved");
        }
        else
        {
            console.log("Not saved");
        }
    });
}

function totalPercentCheck()
{
    var totalPercentCompetences = 0;
    var totalPercentSubcompetences = 0;
    var totalPercentIndicators = 0;

    var nrOfSubcompetences = 0;
    var nrOfIndicators = 0;

    for(var indexCompetences =0; indexCompetences < viewModel.competences().length; indexCompetences++)
    {
        totalPercentCompetences = totalPercentCompetences + parseInt(viewModel.competences()[indexCompetences].weight());
        for(var indexSubCompetences = 0; indexSubCompetences < viewModel.competences()[indexCompetences].subcompetences().length; indexSubCompetences++)
        {
            totalPercentSubcompetences = totalPercentSubcompetences[indexCompetences] + parseInt(viewModel.competences()[indexCompetences].subcompetences()[indexSubCompetences].weight());
            nrOfSubcompetences++;
            for(var indexIndicators = 0; indexIndicators < viewModel.competences()[indexCompetences].subcompetences()[indexSubCompetences].indicators().length; indexIndicators++)
            {
                totalPercentIndicators = totalPercentIndicators + parseInt(viewModel.competences()[indexCompetences].subcompetences()[indexSubCompetences].indicators()[indexIndicators].weight());
                nrOfIndicators++;
            }
        }
    }

    totalPercentSubcompetences = totalPercentSubcompetences / nrOfSubcompetences;
    totalPercentIndicators = totalPercentIndicators / nrOfIndicators;

    console.log(totalPercentSubcompetences + " and " + totalPercentIndicators);

    if(totalPercentCompetences == 100 && totalPercentSubcompetences == 100 && totalPercentIndicators == 100 )
    {
        return true;
    }
    else
    {
        return false;
    }
}

function automatedWeightCalculation(data)
{
    var lockedPercent = 0;
    var nrOfUnlocked = 0;

    for(var index = 0; index < data.length; index++)
    {
        if(data[index].locked == true)
        {
            lockedPercent = lockedPercent + parseInt(data[index].weight());
        }
        else
        {
            nrOfUnlocked++;
        }
    }

    var remainingPercent = 100 - lockedPercent;

    var percentPerCompetence = remainingPercent / nrOfUnlocked;

    percentPerCompetence = percentPerCompetence.toFixed(2);

    for(var index = 0; index < data.length; index++)
    {
        if(data[index].locked == false)
        {
            data[index].weight(percentPerCompetence);
        }
    }
}
<commit_msg>total percent check<commit_after>/**
 * Competence class
 */
function Competence(viewmodel, id, code, name, weight, locked, subcompetences) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        weight: ko.observable(weight),
        locked: false,
        subcompetences: ko.observableArray(subcompetences),

        addSubCompetence: function() {
            this.subcompetences.push(new SubCompetence(this));
            automatedWeightCalculation(this.subcompetences());
            /*var total = 100;
            alert(total);
            console.log(this.subcompetences);
            for(var sub in this.subcompetences){
                alert(sub);
                sub.calculateWeight(100);
                total -= sub.weight;
                alert(total);
            }*/
        },

        removeThis: function() {
            viewmodel.removeCompetence(this);
        },

        toggleLock: function(data, event){
            if(this.locked == true)
            {
                $(event.target).addClass("icon-unlock").removeClass("icon-lock");
                this.locked = false;
            }
            else
            {
                $(event.target).addClass("icon-lock").removeClass("icon-unlock");
                this.locked = true;
            }
        },

        removeSubCompetence: function(subCompetence) {
            this.subcompetences.remove(subCompetence);
            automatedWeightCalculation(this.subcompetences());
        }
    };

}

/**
 * SubCompetence class
 */
function SubCompetence(parent, id, code, name, weight, locked, indicators) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        weight: ko.observable(weight),
        locked: false,
        indicators: ko.observableArray(indicators),

        addIndicator: function() {
            this.indicators.push(new Indicator(this));
            automatedWeightCalculation(this.indicators());
        },

        /*calculateWeight: function(total){
            this.weight = total;
        },*/

        removeThis: function() {
            parent.removeSubCompetence(this);

        },

        toggleLock: function(data, event){
            if(this.locked == true)
            {
                $(event.target).addClass("icon-unlock").removeClass("icon-lock");
                this.locked = false;
            }
            else
            {
                $(event.target).addClass("icon-lock").removeClass("icon-unlock");
                this.locked = true;
            }
        },

        removeIndicator: function(indicator) {
            this.indicators.remove(indicator);
            automatedWeightCalculation(this.indicators());
        }

    };
}

/**
 * Indicator class
 */
function Indicator(parent, id, name, weight, locked, description) {
    return {
        id: ko.observable(id),
        name: ko.observable(name),
        weight: ko.observable(weight),
        locked: false,
        description : ko.observable(description),

        removeThis: function() {
            parent.removeIndicator(this);
        },

        toggleLock: function(data, event){
            if(this.locked == true)
            {
                $(event.target).addClass("icon-unlock").removeClass("icon-lock");
                this.locked = false;
            }
            else
            {
                $(event.target).addClass("icon-lock").removeClass("icon-unlock");
                this.locked = true;
            }
        }
    };
}

// View model for the courses page
function pageViewModel(gvm) {
    // projecttitle
    gvm.projecttitle = ko.observable("");
    //gvm.competences = 0;
    gvm.subcomp = 0;

    // Page specific i18n bindings
    gvm.title = ko.computed(function (){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("ProjectTitle") + ": " + gvm.projecttitle();}, gvm);
    gvm.pageHeader = ko.observable("Project");
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.addCompetenceBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddCompetence");}, gvm);
    gvm.savePage = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SaveBtn");}, gvm);

    gvm.competences = ko.observableArray([]);

    gvm.addCompetence = function() {
        gvm.competences.push(new Competence(this));
        automatedWeightCalculation(this.competences());

        // Update automated weight calculation
        ko.utils.arrayForEach(gvm.competences, function(competence){
            console.log(competence.weight);
            competence.weight(percent);
        });
    };

    gvm.removeCompetence = function(competence) {
        gvm.competences.remove(competence);
        automatedWeightCalculation(this.competences());
    }

    gvm.updateCompetence = function(id, code, description, max, weight) {
        var comp = new Competence(this, id, code, description, weight);
        gvm.competences.push(comp);
        return comp;
    }

    gvm.clearStructure = function() {
        gvm.competences.destroyAll();
    }
}

/**
 * Push the current project state to the database
 * @returns {undefined}
 */
function saveProjectStructure() {
    $.ajax({
       type: "POST",
       url: "/api/projectstructure/" + projectid,
       data: ko.toJSON(viewModel.competences),
       success: function(){
           // TODO make multilangual and with modals
           alert("Saved projectstructure to server");

           fetchProjectStructure();
       }
    });
}

function fetchProjectStructure() {
    viewModel.clearStructure();

    $.getJSON("/api/projectstructure/" + projectid, function(data){
        $.each(data, function(i, item){
            var competence = viewModel.updateCompetence(item.id, item.code, item.description, item.max, item.weight);

            $.each(item.subcompetences, function(i, subcomp){
               var subcompetence = new SubCompetence(competence, subcomp.id, subcomp.code, subcomp.description, subcomp.weight);
               competence.subcompetences.push(subcompetence);

               $.each(subcomp.indicators, function(i, indic){
                  subcompetence.indicators.push(new Indicator(subcompetence, indic.id, indic.name, indic.description));
               });
            });
        })
    });
}

function initPage() {
    fetchProjectStructure();

    $(".addCompetenceBtn").click(function() {
        viewModel.addCompetence();
    });

    $(".savePageBtn").click(function(){
        if(totalPercentCheck()) {
            saveProjectStructure();
            console.log("Saved");
        }
        else
        {
            console.log("Not saved");
        }
    });
}

function totalPercentCheck()
{
    var totalPercentCompetences = 0;
    var totalPercentSubcompetences = 0;
    var totalPercentIndicators = 0;

    var nrOfSubcompetences = 0;
    var nrOfIndicators = 0;

    for(var indexCompetences =0; indexCompetences < viewModel.competences().length; indexCompetences++)
    {
        totalPercentCompetences = totalPercentCompetences + parseInt(viewModel.competences()[indexCompetences].weight());
        for(var indexSubCompetences = 0; indexSubCompetences < viewModel.competences()[indexCompetences].subcompetences().length; indexSubCompetences++)
        {
            totalPercentSubcompetences = totalPercentSubcompetences + parseInt(viewModel.competences()[indexCompetences].subcompetences()[indexSubCompetences].weight());
            nrOfSubcompetences++;
            for(var indexIndicators = 0; indexIndicators < viewModel.competences()[indexCompetences].subcompetences()[indexSubCompetences].indicators().length; indexIndicators++)
            {
                totalPercentIndicators = totalPercentIndicators + parseInt(viewModel.competences()[indexCompetences].subcompetences()[indexSubCompetences].indicators()[indexIndicators].weight());
                nrOfIndicators++;
            }
        }
    }

    console.log(totalPercentSubcompetences + " and " + totalPercentIndicators);

    totalPercentSubcompetences = totalPercentSubcompetences / nrOfSubcompetences;
    totalPercentIndicators = totalPercentIndicators / nrOfIndicators;

    console.log(totalPercentSubcompetences + " and " + totalPercentIndicators);

    if(totalPercentCompetences == 100 && totalPercentSubcompetences == 100 && totalPercentIndicators == 100 )
    {
        return true;
    }
    else
    {
        return false;
    }
}

function automatedWeightCalculation(data)
{
    var lockedPercent = 0;
    var nrOfUnlocked = 0;

    for(var index = 0; index < data.length; index++)
    {
        if(data[index].locked == true)
        {
            lockedPercent = lockedPercent + parseInt(data[index].weight());
        }
        else
        {
            nrOfUnlocked++;
        }
    }

    var remainingPercent = 100 - lockedPercent;

    var percentPerCompetence = remainingPercent / nrOfUnlocked;

    percentPerCompetence = percentPerCompetence.toFixed(2);

    for(var index = 0; index < data.length; index++)
    {
        if(data[index].locked == false)
        {
            data[index].weight(percentPerCompetence);
        }
    }
}
<|endoftext|>