<commit_before>/****************************************************************************
 * Copyright (C) 2009-2010 GGA Software Services LLC
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU Affero General Public License version 3 as published by the Free
 * Software Foundation and appearing in the file LICENSE.GPL included in
 * the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

if (!window.chem || !window.rnd || !rnd.MolData)
	throw new Error("Include MolData.js first");

rnd.MolData.prototype.calcConn = function (aid)
{
	var conn = 0;
	var atom = this.atoms.get(aid);
	for (var i = 0; i < atom.neighbors.length; ++i) {
		var hb = this.halfBonds.get(atom.neighbors[i]);
		var bond = this.bonds.get(hb.bid);
		switch (bond.b.type) {
			case chem.Molecule.BOND.TYPE.SINGLE:
				conn += 1;
				break;
			case chem.Molecule.BOND.TYPE.DOUBLE:
				conn += 2;
				break;
			case chem.Molecule.BOND.TYPE.TRIPLE:
				conn += 3;
				break;
			case chem.Molecule.BOND.TYPE.AROMATIC:
				conn += 1.5;
				break;
			default:
				return -1;
		}
	}
	return conn;
}

rnd.AtomData.prototype.calcValence = function (conn)
{
	var atom = this.a;
	var charge = atom.charge;
	var label = atom.label;
	if (atom.isQuery()) {
		this.valence = -1;
		this.a.implicitH = -1;
		return true;
	}
	var elem = chem.Element.getElementByLabel(label);
	if (elem == null) {
		return true;
	}

	var groupno = chem.Element.elements.get(elem).group;
	var rad = chem.Molecule.radicalElectrons(atom.radical);

	var valence = conn;
	var hyd = 0;
	var absCharge = Math.abs(charge);

	if (groupno == 1)
	{
		if (label == 'H' ||
			label == 'Li' || label == 'Na' || label == 'K' ||
			label == 'Rb' || label == 'Cs' || label == 'Fr')
			{
			valence = 1;
			hyd = 1 - rad - conn - absCharge;
		}
	}
	else if (groupno == 3)
	{
		if (label == 'B' || label == 'Al' || label == 'Ga' || label == 'In')
		{
			if (charge == -1)
			{
				valence = 4;
				hyd = 4 - rad - conn;
			}
			else
			{
				valence = 3;
				hyd = 3 - rad - conn - absCharge;
			}
		}
		else if (label == 'Tl')
		{
			if (charge == -1)
			{
				if (rad + conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else
				{
					valence = 4;
					hyd = 4 - rad - conn;
				}
			}
			else if (charge == -2)
			{
				if (rad + conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn;
				}
			}
			else
			{
				if (rad + conn + absCharge <= 1)
				{
					valence = 1;
					hyd = 1 - rad - conn - absCharge;
				}
				else
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
			}
		}
	}
	else if (groupno == 4)
	{
		if (label == 'C' || label == 'Si' || label == 'Ge')
		{
			valence = 4;
			hyd = 4 - rad - conn - absCharge;
		}
		else if (label == 'Sn' || label == 'Pb')
		{
			if (conn + rad + absCharge <= 2)
			{
				valence = 2;
				hyd = 2 - rad - conn - absCharge;
			}
			else
			{
				valence = 4;
				hyd = 4 - rad - conn - absCharge;
			}
		}
	}
	else if (groupno == 5)
	{
		if (label == 'N' || label == 'P')
		{
			if (charge == 1)
			{
				valence = 4;
				hyd = 4 - rad - conn;
			}
			else if (charge == 2)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				if (label == 'N' || rad + conn + absCharge <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
				else // ELEM_P && rad + conn + absCharge > 3
				{
					valence = 5;
					hyd = 5 - rad - conn - absCharge;
				}
			}
		}
		else if (label == 'Bi' || label == 'Sb' || label == 'As')
		{
			if (charge == 1)
			{
				if (rad + conn <= 2 && elem != ELEM_As)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else
				{
					valence = 4;
					hyd = 4 - rad - conn;
				}
			}
			else if (charge == 2)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				if (rad + conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn - absCharge;
				}
			}
		}
	}
	else if (groupno == 6)
	{
		if (label == 'O')
		{
			if (charge >= 1)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				valence = 2;
				hyd = 2 - rad - conn - absCharge;
			}
		}
		else if (label == 'S' || label == 'Se' || label == 'Po')
		{
			if (charge == 1)
			{
				if (conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn;
				}
			}
			else
			{
				if (conn + rad + absCharge <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
				else if (conn + rad + absCharge <= 4)
				// See examples in PubChem
				// [S] : CID 16684216
				// [Se]: CID 5242252
				// [Po]: no example, just following ISIS/Draw logic here
				{
					valence = 4;
					hyd = 4 - rad - conn - absCharge;
				}
				else
				// See examples in PubChem
				// [S] : CID 46937044
				// [Se]: CID 59786
				// [Po]: no example, just following ISIS/Draw logic here
				{
					valence = 6;
					hyd = 6 - rad - conn - absCharge;
				}
			}
		}
		else if (label == 'Te')
		{
			if (charge == -1)
			{
				if (conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
			}
			else if (charge == 0 || charge == 2)
			{
				if (conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
				else if (conn <= 4)
				{
					valence = 4;
					hyd = 4 - rad - conn - absCharge;
				}
				else if (charge == 0 && conn <= 6)
				{
					valence = 6;
					hyd = 6 - rad - conn - absCharge;
				}
				else
					hyd = -1;
			}
		}
	}
	else if (groupno == 7)
	{
		if (label == 'F')
		{
			valence = 1;
			hyd = 1 - rad - conn - absCharge;
		}
		else if (label == 'Cl' || label == 'Br' ||
			label == 'I'  || label == 'At')
			{
			if (charge == 1)
			{
				if (conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else if (conn == 3 || conn == 5 || conn >= 7)
					hyd = -1;
			}
			else if (charge == 0)
			{
				if (conn <= 1)
				{
					valence = 1;
					hyd = 1 - rad - conn;
				}
				// While the halogens can have valence 3, they can not have
				// hydrogens in that case.
				else if (conn == 2 || conn == 4 || conn == 6)
				{
					if (rad == 1)
					{
						valence = conn;
						hyd = 0;
					}
					else
						hyd = -1; // will throw an error in the end
				}
				else if (conn > 7)
					hyd = -1; // will throw an error in the end
			}
		}
	}

	this.valence = valence;
	this.a.implicitH = hyd;
	if (this.a.implicitH < 0)
	{
		this.valence = conn;
		this.a.implicitH = 0;
		this.badConn = true;
		return false;
	}
	return true;
}

rnd.AtomData.prototype.calcValenceMinusHyd = function (conn)
{
	var atom = this.a;
	var charge = atom.charge;
	var label = atom.label;
	var elem = chem.Element.getElementByLabel(label);
	if (elem == null)
		throw new Error("Element " + elem + " unknown");
	if (elem < 0) { // query atom, skip
		this.valence = -1;
		this.a.implicitH = -1;
		return null;
	}

	var groupno = chem.Element.elements.get(elem).group;
	var rad = chem.Molecule.radicalElectrons(atom.radical);

	if (groupno == 3)
	{
		if (label == 'B' || label == 'Al' || label == 'Ga' || label == 'In')
		{
			if (charge == -1)
				if (rad + conn <= 4)
					return rad + conn;
		}
	}
	else if (groupno == 5)
	{
		if (label == 'N' || label == 'P')
		{
			if (charge == 1)
				return rad + conn;
			if (charge == 2)
				return rad + conn;
		}
		else if (label == 'Sb' || label == 'Bi' || label == 'As')
		{
			if (charge == 1)
				return rad + conn;
			else if (charge == 2)
				return rad + conn;
		}
	}
	else if (groupno == 6)
	{
		if (label == 'O')
		{
			if (charge >= 1)
				return rad + conn;
		}
		else if (label == 'S'  || label == 'Se' || label == 'Po')
		{
			if (charge == 1)
				return rad + conn;
		}
	}
	else if (groupno == 7)
	{
		if (label == 'Cl' || label == 'Br' ||
			label == 'I'  || label == 'At')
			{
			if (charge == 1)
				return rad + conn;
		}
	}

	return rad + conn + Math.abs(charge);
}

rnd.MolData.prototype.calcImplicitHydrogen = function (aid)
{
	var conn = this.calcConn(aid);
	var atom = this.atoms.get(aid);
	if (conn < 0) {
		atom.a.implicitH = -1;
		return;
	}
	if (atom.a.explicitValence) {
		atom.a.implicitH = atom.a.valence - atom.calcValenceMinusHyd(conn);
		if (atom.a.implicitH < 0) {
			atom.a.implicitH = -1;
			atom.badConn = true;
		}
	} else {
		atom.badConn = false;
		atom.calcValence(conn);
	}
}<commit_msg>fix pseudoatom implicit hydrogen calculation<commit_after>/****************************************************************************
 * Copyright (C) 2009-2010 GGA Software Services LLC
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU Affero General Public License version 3 as published by the Free
 * Software Foundation and appearing in the file LICENSE.GPL included in
 * the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

if (!window.chem || !window.rnd || !rnd.MolData)
	throw new Error("Include MolData.js first");

rnd.MolData.prototype.calcConn = function (aid)
{
	var conn = 0;
	var atom = this.atoms.get(aid);
	for (var i = 0; i < atom.neighbors.length; ++i) {
		var hb = this.halfBonds.get(atom.neighbors[i]);
		var bond = this.bonds.get(hb.bid);
		switch (bond.b.type) {
			case chem.Molecule.BOND.TYPE.SINGLE:
				conn += 1;
				break;
			case chem.Molecule.BOND.TYPE.DOUBLE:
				conn += 2;
				break;
			case chem.Molecule.BOND.TYPE.TRIPLE:
				conn += 3;
				break;
			case chem.Molecule.BOND.TYPE.AROMATIC:
				conn += 1.5;
				break;
			default:
				return -1;
		}
	}
	return conn;
}

rnd.AtomData.prototype.calcValence = function (conn)
{
	var atom = this.a;
	var charge = atom.charge;
	var label = atom.label;
	if (atom.isQuery()) {
		this.valence = -1;
		this.a.implicitH = -1;
		return true;
	}
	var elem = chem.Element.getElementByLabel(label);
	if (elem == null) {
		this.valence = -1;
		this.a.implicitH = 0;
		return true;
	}

	var groupno = chem.Element.elements.get(elem).group;
	var rad = chem.Molecule.radicalElectrons(atom.radical);

	var valence = conn;
	var hyd = 0;
	var absCharge = Math.abs(charge);

	if (groupno == 1)
	{
		if (label == 'H' ||
			label == 'Li' || label == 'Na' || label == 'K' ||
			label == 'Rb' || label == 'Cs' || label == 'Fr')
			{
			valence = 1;
			hyd = 1 - rad - conn - absCharge;
		}
	}
	else if (groupno == 3)
	{
		if (label == 'B' || label == 'Al' || label == 'Ga' || label == 'In')
		{
			if (charge == -1)
			{
				valence = 4;
				hyd = 4 - rad - conn;
			}
			else
			{
				valence = 3;
				hyd = 3 - rad - conn - absCharge;
			}
		}
		else if (label == 'Tl')
		{
			if (charge == -1)
			{
				if (rad + conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else
				{
					valence = 4;
					hyd = 4 - rad - conn;
				}
			}
			else if (charge == -2)
			{
				if (rad + conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn;
				}
			}
			else
			{
				if (rad + conn + absCharge <= 1)
				{
					valence = 1;
					hyd = 1 - rad - conn - absCharge;
				}
				else
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
			}
		}
	}
	else if (groupno == 4)
	{
		if (label == 'C' || label == 'Si' || label == 'Ge')
		{
			valence = 4;
			hyd = 4 - rad - conn - absCharge;
		}
		else if (label == 'Sn' || label == 'Pb')
		{
			if (conn + rad + absCharge <= 2)
			{
				valence = 2;
				hyd = 2 - rad - conn - absCharge;
			}
			else
			{
				valence = 4;
				hyd = 4 - rad - conn - absCharge;
			}
		}
	}
	else if (groupno == 5)
	{
		if (label == 'N' || label == 'P')
		{
			if (charge == 1)
			{
				valence = 4;
				hyd = 4 - rad - conn;
			}
			else if (charge == 2)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				if (label == 'N' || rad + conn + absCharge <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
				else // ELEM_P && rad + conn + absCharge > 3
				{
					valence = 5;
					hyd = 5 - rad - conn - absCharge;
				}
			}
		}
		else if (label == 'Bi' || label == 'Sb' || label == 'As')
		{
			if (charge == 1)
			{
				if (rad + conn <= 2 && elem != ELEM_As)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else
				{
					valence = 4;
					hyd = 4 - rad - conn;
				}
			}
			else if (charge == 2)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				if (rad + conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn - absCharge;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn - absCharge;
				}
			}
		}
	}
	else if (groupno == 6)
	{
		if (label == 'O')
		{
			if (charge >= 1)
			{
				valence = 3;
				hyd = 3 - rad - conn;
			}
			else
			{
				valence = 2;
				hyd = 2 - rad - conn - absCharge;
			}
		}
		else if (label == 'S' || label == 'Se' || label == 'Po')
		{
			if (charge == 1)
			{
				if (conn <= 3)
				{
					valence = 3;
					hyd = 3 - rad - conn;
				}
				else
				{
					valence = 5;
					hyd = 5 - rad - conn;
				}
			}
			else
			{
				if (conn + rad + absCharge <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
				else if (conn + rad + absCharge <= 4)
				// See examples in PubChem
				// [S] : CID 16684216
				// [Se]: CID 5242252
				// [Po]: no example, just following ISIS/Draw logic here
				{
					valence = 4;
					hyd = 4 - rad - conn - absCharge;
				}
				else
				// See examples in PubChem
				// [S] : CID 46937044
				// [Se]: CID 59786
				// [Po]: no example, just following ISIS/Draw logic here
				{
					valence = 6;
					hyd = 6 - rad - conn - absCharge;
				}
			}
		}
		else if (label == 'Te')
		{
			if (charge == -1)
			{
				if (conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
			}
			else if (charge == 0 || charge == 2)
			{
				if (conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn - absCharge;
				}
				else if (conn <= 4)
				{
					valence = 4;
					hyd = 4 - rad - conn - absCharge;
				}
				else if (charge == 0 && conn <= 6)
				{
					valence = 6;
					hyd = 6 - rad - conn - absCharge;
				}
				else
					hyd = -1;
			}
		}
	}
	else if (groupno == 7)
	{
		if (label == 'F')
		{
			valence = 1;
			hyd = 1 - rad - conn - absCharge;
		}
		else if (label == 'Cl' || label == 'Br' ||
			label == 'I'  || label == 'At')
			{
			if (charge == 1)
			{
				if (conn <= 2)
				{
					valence = 2;
					hyd = 2 - rad - conn;
				}
				else if (conn == 3 || conn == 5 || conn >= 7)
					hyd = -1;
			}
			else if (charge == 0)
			{
				if (conn <= 1)
				{
					valence = 1;
					hyd = 1 - rad - conn;
				}
				// While the halogens can have valence 3, they can not have
				// hydrogens in that case.
				else if (conn == 2 || conn == 4 || conn == 6)
				{
					if (rad == 1)
					{
						valence = conn;
						hyd = 0;
					}
					else
						hyd = -1; // will throw an error in the end
				}
				else if (conn > 7)
					hyd = -1; // will throw an error in the end
			}
		}
	}

	this.valence = valence;
	this.a.implicitH = hyd;
	if (this.a.implicitH < 0)
	{
		this.valence = conn;
		this.a.implicitH = 0;
		this.badConn = true;
		return false;
	}
	return true;
}

rnd.AtomData.prototype.calcValenceMinusHyd = function (conn)
{
	var atom = this.a;
	var charge = atom.charge;
	var label = atom.label;
	var elem = chem.Element.getElementByLabel(label);
	if (elem == null)
		throw new Error("Element " + elem + " unknown");
	if (elem < 0) { // query atom, skip
		this.valence = -1;
		this.a.implicitH = -1;
		return null;
	}

	var groupno = chem.Element.elements.get(elem).group;
	var rad = chem.Molecule.radicalElectrons(atom.radical);

	if (groupno == 3)
	{
		if (label == 'B' || label == 'Al' || label == 'Ga' || label == 'In')
		{
			if (charge == -1)
				if (rad + conn <= 4)
					return rad + conn;
		}
	}
	else if (groupno == 5)
	{
		if (label == 'N' || label == 'P')
		{
			if (charge == 1)
				return rad + conn;
			if (charge == 2)
				return rad + conn;
		}
		else if (label == 'Sb' || label == 'Bi' || label == 'As')
		{
			if (charge == 1)
				return rad + conn;
			else if (charge == 2)
				return rad + conn;
		}
	}
	else if (groupno == 6)
	{
		if (label == 'O')
		{
			if (charge >= 1)
				return rad + conn;
		}
		else if (label == 'S'  || label == 'Se' || label == 'Po')
		{
			if (charge == 1)
				return rad + conn;
		}
	}
	else if (groupno == 7)
	{
		if (label == 'Cl' || label == 'Br' ||
			label == 'I'  || label == 'At')
			{
			if (charge == 1)
				return rad + conn;
		}
	}

	return rad + conn + Math.abs(charge);
}

rnd.MolData.prototype.calcImplicitHydrogen = function (aid)
{
	var conn = this.calcConn(aid);
	var atom = this.atoms.get(aid);
	if (conn < 0) {
		atom.a.implicitH = -1;
		return;
	}
	if (atom.a.explicitValence) {
		atom.a.implicitH = atom.a.valence - atom.calcValenceMinusHyd(conn);
		if (atom.a.implicitH < 0) {
			atom.a.implicitH = -1;
			atom.badConn = true;
		}
	} else {
		atom.badConn = false;
		atom.calcValence(conn);
	}
}<|endoftext|>


<commit_before>/*
 * Module for REST API client
 */

import qs from 'qs';
import heartbeat from 'kolibri.heartbeat';
import logger from 'kolibri.lib.logging';
import store from 'kolibri.coreVue.vuex.store';
import errorCodes from '../disconnectionErrorCodes';
import clientFactory from './baseClient';

export const logging = logger.getLogger(__filename);

const baseClient = clientFactory();

// Disconnection handler interceptor
baseClient.interceptors.request.use(function(request) {
  if (!store.getters.connected) {
    // If the vuex state records that we are not currently connected then cancel all
    // outgoing requests.
    request.abort();
    return Promise.reject(request);
  }
  return request;
});

// Login timeout detection interceptor and disconnection monitoring
baseClient.interceptors.response.use(
  response => response,
  function(error) {
    // If we receive a 403 response from the server, it is possible that the user
    // is attempting to access information they are not allowed to see.
    // However, more likely, it is because their login has timed out, but the frontend
    // client code is still trying to access data that they would be allowed to see
    // if they were logged in.
    if (error.response) {
      if (error.response.status === 403) {
        if (!store.state.core.session.id) {
          // Don't have any session information, so assume that this
          // page has just been reopened and the session has expired.
          // Redirect now!
          heartbeat.signOutDueToInactivity();
        } else {
          // In this case, we should check right now if they are still logged in
          heartbeat.pollSessionEndPoint();
        }
      }
      // On every error, check to see if the status code is one of our designated
      // disconnection status codes.
    } else if (errorCodes.includes(error.response.status)) {
      // If so, set our heartbeat module to start monitoring the disconnection state
      heartbeat.monitorDisconnect(error.response.status);
    }
    return Promise.reject(error);
  }
);

const client = options => {
  if (
    options &&
    typeof options === 'object' &&
    !Array.isArray(options) &&
    (!options.method || options.method.toLowerCase() === 'get')
  ) {
    if (!options.params) {
      options.params = {};
    } else {
      options.params = Object.assign({}, options.params);
    }
    // Cache bust by default, but allow it to be turned off
    if (options.cacheBust || typeof options.cacheBust === 'undefined') {
      const cacheBust = new Date().getTime();
      options.params[cacheBust] = cacheBust;
    }
    if (options.path) {
      // Provide backwards compatibility with the previous Rest JS API.
      options.url = options.path;
      delete options.path;
      logging.warn('option path is deprecated, please use url option instead');
    }
  }
  const headers = { ...(options.headers || {}) };
  if (options.multipart) {
    headers['Content-Type'] = 'multipart/form-data';
  }
  return baseClient.request({
    ...options,
    headers,
  });
};

export default client;

export const httpClient = options => {
  return client({
    ...options,
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    data: qs.stringify(options.data),
    url: options.url,
  });
};
<commit_msg>Move disconnection checking into accessible code branch.<commit_after>/*
 * Module for REST API client
 */

import qs from 'qs';
import heartbeat from 'kolibri.heartbeat';
import logger from 'kolibri.lib.logging';
import store from 'kolibri.coreVue.vuex.store';
import errorCodes from '../disconnectionErrorCodes';
import clientFactory from './baseClient';

export const logging = logger.getLogger(__filename);

const baseClient = clientFactory();

// Disconnection handler interceptor
baseClient.interceptors.request.use(function(request) {
  if (!store.getters.connected) {
    // If the vuex state records that we are not currently connected then cancel all
    // outgoing requests.
    request.abort();
    return Promise.reject(request);
  }
  return request;
});

// Login timeout detection interceptor and disconnection monitoring
baseClient.interceptors.response.use(
  response => response,
  function(error) {
    // If we receive a 403 response from the server, it is possible that the user
    // is attempting to access information they are not allowed to see.
    // However, more likely, it is because their login has timed out, but the frontend
    // client code is still trying to access data that they would be allowed to see
    // if they were logged in.
    if (error.response) {
      if (error.response.status === 403) {
        if (!store.state.core.session.id) {
          // Don't have any session information, so assume that this
          // page has just been reopened and the session has expired.
          // Redirect now!
          heartbeat.signOutDueToInactivity();
        } else {
          // In this case, we should check right now if they are still logged in
          heartbeat.pollSessionEndPoint();
        }
      }
      // On every error, check to see if the status code is one of our designated
      // disconnection status codes.
      if (errorCodes.includes(error.response.status)) {
        // If so, set our heartbeat module to start monitoring the disconnection state
        heartbeat.monitorDisconnect(error.response.status);
      }
    }
    return Promise.reject(error);
  }
);

const client = options => {
  if (
    options &&
    typeof options === 'object' &&
    !Array.isArray(options) &&
    (!options.method || options.method.toLowerCase() === 'get')
  ) {
    if (!options.params) {
      options.params = {};
    } else {
      options.params = Object.assign({}, options.params);
    }
    // Cache bust by default, but allow it to be turned off
    if (options.cacheBust || typeof options.cacheBust === 'undefined') {
      const cacheBust = new Date().getTime();
      options.params[cacheBust] = cacheBust;
    }
    if (options.path) {
      // Provide backwards compatibility with the previous Rest JS API.
      options.url = options.path;
      delete options.path;
      logging.warn('option path is deprecated, please use url option instead');
    }
  }
  const headers = { ...(options.headers || {}) };
  if (options.multipart) {
    headers['Content-Type'] = 'multipart/form-data';
  }
  return baseClient.request({
    ...options,
    headers,
  });
};

export default client;

export const httpClient = options => {
  return client({
    ...options,
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    data: qs.stringify(options.data),
    url: options.url,
  });
};
<|endoftext|>


<commit_before>/*
Gradebook from Names and Scores
I worked on this challenge with: Jessica Richardson/Jon Clayton
This challenge took me [#] hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.
/*
var gradebook = {};
gradebook.Joseph = {};
gradebook.Susan = {};
gradebook.William = {};
gradebook.Elizabeth = {};

gradebook.Joseph = {testScores: scores[0]};
gradebook.Susan = {testScores: scores[1]};
gradebook.William = {testScores: scores[2]};
gradebook.Elizabeth = {testScores: scores[3]};

gradebook.addScore = function(name,score){
  gradebook[name].testScores.push(score);
}

gradebook.getAverage = function(name){return average(gradebook[name].testScores)};

function average(array) {
  var sum = array.reduce (function (x, y) {return x + y;}, 0);
  return sum/array.length;
}
*/

//  gradebook[name].testScores.reduce(function(x, y) { return x + y;}, 0);

// __________________________________________
// Refactored Solution

var gradebook = {
  addScore: function(name, score) {this[name].testScores.push(score)},
  getAverage: function(name) {return average(this[name].testScores)}
}

students.forEach(function(student){gradebook[student] = {testScores: scores[students.indexOf(student)]}});

function average(array) {
  return array.reduce( (x, y) => x + y)/array.length;
}

/* __________________________________________
### Reflect
####What did you learn about adding functions to objects?
I saw how to do it externally, and then in the refactor figured out how to do it internally, letting me replace the object name with "this".

####How did you iterate over nested arrays in JavaScript?
In this case I used `#forEach` and then something a bit messy to get an index number to pull from a different array at the same index. I could also have used a for loop with an explicit index number but that seemed even a bit less elegant.

####Were there any new methods you were able to incorporate? If so, what were they and how did they work?
I learned a trick, using `=>` to get rid of the `function`, `return` and {} in the original way I used reduce.  Much shorter syntax!  Thanks Dan Anderson!

// __________________________________________
// Test Code:  Do not alter code below this line.
*/

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<commit_msg>Update gradebook.js<commit_after>/*
Gradebook from Names and Scores
I worked on this challenge with: Jessica Richardson/Jon Clayton
This challenge took me 2 hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.
/*
var gradebook = {};
gradebook.Joseph = {};
gradebook.Susan = {};
gradebook.William = {};
gradebook.Elizabeth = {};

gradebook.Joseph = {testScores: scores[0]};
gradebook.Susan = {testScores: scores[1]};
gradebook.William = {testScores: scores[2]};
gradebook.Elizabeth = {testScores: scores[3]};

gradebook.addScore = function(name,score){
  gradebook[name].testScores.push(score);
}

gradebook.getAverage = function(name){return average(gradebook[name].testScores)};

function average(array) {
  var sum = array.reduce (function (x, y) {return x + y;}, 0);
  return sum/array.length;
}
*/

// __________________________________________
// Refactored Solution

var gradebook = {
  addScore: function(name, score) {this[name].testScores.push(score)},
  getAverage: function(name) {return average(this[name].testScores)}
}

students.forEach(function(student){gradebook[student] = {testScores: scores[students.indexOf(student)]}});

function average(array) {
  return array.reduce( (x, y) => x + y)/array.length;
}

/* __________________________________________
### Reflect
####What did you learn about adding functions to objects?
I saw how to do it externally, and then in the refactor figured out how to do it internally, letting me replace the object name with "this".

####How did you iterate over nested arrays in JavaScript?
In this case I used `#forEach` and then something a bit messy to get an index number to pull from a different array at the same index. I could also have used a for loop with an explicit index number but that seemed even a bit less elegant.

####Were there any new methods you were able to incorporate? If so, what were they and how did they work?
I learned a trick, using `=>` to get rid of the `function`, `return` and {} in the original way I used reduce.  Much shorter syntax!  Thanks Dan Anderson!

// __________________________________________
// Test Code:  Do not alter code below this line.
*/

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)
<|endoftext|>


<commit_before>/*
Gradebook from Names and Scores
I worked on this challenge [with: Chris Lamkin]
This challenge took me [1] hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.

var gradebook = new Object();

gradebook["Joseph"] = {};
gradebook["Susan"] = {};
gradebook["William"] = {};
gradebook["Elizabeth"] = {};

gradebook.Joseph.testScores = scores[0];
gradebook.Susan.testScores = scores[1];
gradebook.William.testScores = scores[2];
gradebook.Elizabeth.testScores = scores[3];

gradebook["addScore"] =
function(name, score){
  gradebook[name]["testScores"].push(score);
}

gradebook.getAverage = function(name){
  return average(gradebook[name]["testScores"]);
};

function average(arrayIntegers){
  var sum = 0;
 for (var i = 0; i < arrayIntegers.length; i++){
   sum += arrayIntegers[i];
 }
  var average = sum / arrayIntegers.length;
  return average;
}

// __________________________________________
// Refactored Solution

var gradebook = {};

for (var i = 0; i < students.length; i++){
  gradebook[students[i]] = {testScores: scores[i]};
}

gradebook["addScore"] =
function(name, score){
  gradebook[name]["testScores"].push(score);
}

gradebook.getAverage = function(name){
  return average(gradebook[name]["testScores"]);
};

function average(arrayIntegers){
  var sum = 0;
 for (var i = 0; i < arrayIntegers.length; i++){
   sum += arrayIntegers[i];
 }
  return (sum / arrayIntegers.length);

}

// __________________________________________
// Reflect

/*
1. What did you learn about adding functions to objects?

I learned that functions can be added to objects in the same way that properties are added to objects. A function can be declared within an object by stating the object, followed by a period, and then the name of the function. After specifying the function parameters, you can insert the block of code within the function. The function can be called in the same a property is called. You simply state the function in either dot or bracket notation.

2. How did you iterate over nested arrays in JavaScript?

We iterated over the arrays in JavaScript by using a for loop. The loop allowed us to move through each element in the array and acquire the values that we needed. In terms of nested arrays, bracket notation allowed us to specify which values we needed from the nested arrays. In this way, we didn't need to create a iteration within an iteration to move through the elements in our nested arrays.

3. Were there any new methods you were able to incorporate? If so, what were they and how did they work?

We didn't incorporate any new methods into our solution. We did use the existing method of push to insert a new score to the end of our testScores. Other than methods, the most useful part of this challenge was learning to differentiate the use of dot notation from bracket notation in JavaScript. It helped me understand how each differed and when to use each one.

*/

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<commit_msg>Complete Challenge 8.2 for Practice<commit_after>/*
Gradebook from Names and Scores
I worked on this challenge [with: Chris Lamkin]
This challenge took me [1] hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.

// Solution 1
var gradebook = new Object();

gradebook["Joseph"] = {};
gradebook["Susan"] = {};
gradebook["William"] = {};
gradebook["Elizabeth"] = {};

gradebook.Joseph.testScores = scores[0];
gradebook.Susan.testScores = scores[1];
gradebook.William.testScores = scores[2];
gradebook.Elizabeth.testScores = scores[3];

gradebook["addScore"] =
function(name, score){
  gradebook[name]["testScores"].push(score);
}

gradebook.getAverage = function(name){
  return average(gradebook[name]["testScores"]);
};

function average(arrayIntegers){
  var sum = 0;
 for (var i = 0; i < arrayIntegers.length; i++){
   sum += arrayIntegers[i];
 }
  var average = sum / arrayIntegers.length;
  return average;
}

// Solution 2
var gradebook = {};

gradebook["Joseph"] = {};
gradebook["Susan"] = {};
gradebook["William"] = {};
gradebook["Elizabeth"] = {};

gradebook["Joseph"].testScores = scores[0];
gradebook["Susan"].testScores = scores[1];
gradebook["William"].testScores = scores[2];
gradebook["Elizabeth"].testScores = scores[3];

gradebook.addScore = function(name, score){
  gradebook[name].testScores.push(score);
};

gradebook.getAverage = function(name) {
  return average(gradebook[name].testScores)
};

var average = function(array_of_integers){
  sum = 0;
  for(var i = 0; i < array_of_integers.length; i++) {
    sum += array_of_integers[i];
  }
  return sum/array_of_integers.length
};

// __________________________________________
// Refactored Solution

var gradebook = {};

for (var i = 0; i < students.length; i++){
  gradebook[students[i]] = {testScores: scores[i]};
}

gradebook["addScore"] =
function(name, score){
  gradebook[name]["testScores"].push(score);
}

gradebook.getAverage = function(name){
  return average(gradebook[name]["testScores"]);
};

function average(arrayIntegers){
  var sum = 0;
 for (var i = 0; i < arrayIntegers.length; i++){
   sum += arrayIntegers[i];
 }
  return (sum / arrayIntegers.length);

}

// __________________________________________
// Reflect

/**
1. What did you learn about adding functions to objects?

I learned that functions can be added to objects in the same way that properties are added to objects. A function can be declared within an object by stating the object, followed by a period, and then the name of the function. After specifying the function parameters, you can insert the block of code within the function. The function can be called in the same a property is called. You simply state the function in either dot or bracket notation.

2. How did you iterate over nested arrays in JavaScript?

We iterated over the arrays in JavaScript by using a for loop. The loop allowed us to move through each element in the array and acquire the values that we needed. In terms of nested arrays, bracket notation allowed us to specify which values we needed from the nested arrays. In this way, we didn't need to create a iteration within an iteration to move through the elements in our nested arrays.

3. Were there any new methods you were able to incorporate? If so, what were they and how did they work?

We didn't incorporate any new methods into our solution. We did use the existing method of push to insert a new score to the end of our testScores. Other than methods, the most useful part of this challenge was learning to differentiate the use of dot notation from bracket notation in JavaScript. It helped me understand how each differed and when to use each one.
**/

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<|endoftext|>


<commit_before>/*
Gradebook from Names and Scores
I worked on this challenge [by myself, with:]
This challenge took me [#] hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.

// var gradebook = {}

// gradebook["Joseph"] = {testScores: scores[0]};
// gradebook["Susan"] = {testScores: scores[1]};
// gradebook["William"] = {testScores: scores[2]};
// gradebook["Elizabeth"] = {testScores: scores[3]};

// gradebook["addScore"] = function addScore (name, score) {
//   gradebook[name].testScores.push(score);
// }

// gradebook["getAverage"] = function getAverage (name) {
//   var scores = gradebook[name]["testScores"];
//   return scores.reduce(function(a,b){return a + b}) / scores.length

// }
// function average(testArray) {
//   var sum = 0;
//   for (var i = 0; i < testArray.length; i++) {
//     sum += testArray[i];
//   }
//   return sum/testArray.length;
// };

// getAverage: function(name) {
//   var scores = gradebook[name]["testScores"];
//   return scores.reduce(function(a,b){return a + b}) / scores.length
//   }
// };

// gradebook.addScore("Susan", 80);

// __________________________________________
// Refactored Solution

var gradebook = {}

function populate() {
  for(var i = 0; i < students.length; i++) {
  gradebook[students[i]] = {testScores:scores[i]};
  }
}
populate();

gradebook["addScore"] = function addScore (name, score) {
  gradebook[name].testScores.push(score);
}

gradebook["getAverage"] = function getAverage (name) {
  var scores = gradebook[name]["testScores"];
  return scores.reduce(function(a,b){return a + b}) / scores.length
}

function average (testArray) {
  var sum = 0;
  for (var i = 0; i < testArray.length; i++) {
    sum += testArray[i];
  }
  return sum/testArray.length;
};

// average(gradebook["Joseph"].testScores);
// getAverage: function(name) {
//   var scores = gradebook[name]["testScores"];
//   return scores.reduce(function(a,b){return a + b}) / scores.length
//   }
// };

// gradebook.addScore("Susan", 80);

// __________________________________________
// Reflect

// What did you learn about adding functions to objects?

// How did you iterate over nested arrays in JavaScript?

// Were there any new methods you were able to incorporate? If so, what were they and how did they work?

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<commit_msg>Add final commit for 8.2 JavaScript Gradebook<commit_after>/*
Gradebook from Names and Scores
I worked on this challenge with Emmett Garber
This challenge took me 2 hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.

// var gradebook = {}

// gradebook["Joseph"] = {testScores: scores[0]};
// gradebook["Susan"] = {testScores: scores[1]};
// gradebook["William"] = {testScores: scores[2]};
// gradebook["Elizabeth"] = {testScores: scores[3]};

// gradebook["addScore"] = function addScore (name, score) {
//   gradebook[name].testScores.push(score);
// }

// gradebook["getAverage"] = function getAverage (name) {
//   var scores = gradebook[name]["testScores"];
//   return scores.reduce(function(a,b){return a + b}) / scores.length

// }
// function average(testArray) {
//   var sum = 0;
//   for (var i = 0; i < testArray.length; i++) {
//     sum += testArray[i];
//   }
//   return sum/testArray.length;
// };

// getAverage: function(name) {
//   var scores = gradebook[name]["testScores"];
//   return scores.reduce(function(a,b){return a + b}) / scores.length
//   }
// };

// gradebook.addScore("Susan", 80);

// __________________________________________
// Refactored Solution

var gradebook = {}

function populate() {
  for(var i = 0; i < students.length; i++) {
  gradebook[students[i]] = {testScores:scores[i]};
  }
}
populate();

gradebook["addScore"] = function addScore (name, score) {
  gradebook[name].testScores.push(score);
}

gradebook["getAverage"] = function getAverage (name) {
  var scores = gradebook[name]["testScores"];
  return scores.reduce(function(a,b){return a + b}) / scores.length
}

function average (testArray) {
  var sum = 0;
  for (var i = 0; i < testArray.length; i++) {
    sum += testArray[i];
  }
  return sum/testArray.length;
};

// average(gradebook["Joseph"].testScores);
// getAverage: function(name) {
//   var scores = gradebook[name]["testScores"];
//   return scores.reduce(function(a,b){return a + b}) / scores.length
//   }
// };

// gradebook.addScore("Susan", 80);

// __________________________________________
// Reflect

// What did you learn about adding functions to objects?
// Here is the standard way to create an object prototype is to use an object constructor function:
// function person(first, last, age, eyecolor) {
//     this.firstName = first;
//     this.lastName = last;
//     this.age = age;
//     this.eyeColor = eyecolor;
// }

// With a constructor function, you can use the new keyword to create new objects from the same prototype:
// var myFather = new person("John", "Doe", 50, "blue");
// var myMother = new person("Sally", "Rally", 48, "green");

// Adding a new property to an existing object is easy:
// myFather.nationality = "English";

// How did you iterate over nested arrays in JavaScript?
// The for loop is very helpful for iterating over nested arrays in JS.  Using .length we can go through each object in the array.

// Were there any new methods you were able to incorporate? If so, what were they and how did they work?

// The reduce method is good for any sort of situation where we want to take an array and boil it down into a new value in steps that have access to one or two of the array elements at a time.  Unlike map and sort, which produce new arrays, reduce can boil an array down to a new value of any type.

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<|endoftext|>


<commit_before>// DOM Manipulation Challenge

// I worked on this challenge [by myself, with: ].

// Add your JavaScript calls to this page:

// Release 0:

// Release 1:
var root = document.getElementsByTagName( 'div' )[0]; // '0' to assign the first (and only `div` tag)

root.setAttribute( 'class', 'done' );

// Release 2:
document.getElementById("release-1").style.display = "none";

// Release 3:

document.getElementById("tag").innerHTML = "I completed release 2."

// Release 4:
document.getElementById("release-3").style.color = "#955251";

// Release 5:
document.getElementById("release-3").style.textSize = "2em";

// Release 6:
var tmpl = document.getElementById ('hidden');
document.body.appendChild (tmpl.content.cloneNode (true))<commit_msg>Add reflection to js file instead of html<commit_after>// DOM Manipulation Challenge

// I worked on this challenge [by myself, with: ].

// Add your JavaScript calls to this page:

// Release 0:

// Release 1:
var root = document.getElementsByTagName( 'div' )[0]; // '0' to assign the first (and only `div` tag)

root.setAttribute( 'class', 'done' );

// Release 2:
document.getElementById("release-1").style.display = "none";

// Release 3:

document.getElementById("tag").innerHTML = "I completed release 2."

// Release 4:
document.getElementById("release-3").style.color = "#955251";

// Release 5:
document.getElementById("release-3").style.textSize = "2em";

// Release 6:
var tmpl = document.getElementById ('hidden');
document.body.appendChild (tmpl.content.cloneNode (true))

/* Reflection
What did you learn about the DOM?
I learned that it will give me errors on the JavaScript. The formating
can be hard to get used to because I don't really understand JS very well.

What are some useful methods to use to manipulate the DOM?
.appendchild, .innerHTML, .getElementById these were all brand new but
they seemed to work well. I will need to do more practice with this.

*/<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

define([
    "firebug/lib/trace",
],
function(FBTrace) {

// ********************************************************************************************* //
// Constants

function pauseGrip(context, args)
{
    var actor = args[0];
    var type = args[1];

    var context = Firebug.currentContext;
    if (!context)
        return "No current context";

    var client = context.debuggerClient;
    if (!client)
        return "Debugger client not available";

    var thread = client.activeThread;
    if (!thread)
        return "The debugger must be paused";

    if (!actor)
        return "No actor specified";

    var grip = thread.pauseGrip({actor: actor});
    grip.getPrototypeAndProperties(function(response)
    {
        Firebug.Console.log(response);
    });

    return Firebug.Console.getDefaultReturnValue(context.window);
}

// ********************************************************************************************* //
// Registration

Firebug.registerCommand("pauseGrip", {
    handler: pauseGrip.bind(this),
    description: "Helper command for accessing server side Grips. For debugging purposes only."
})

return {};

// ********************************************************************************************* //
});
<commit_msg>Extend the pauseGrip() command line command (just for debugging)<commit_after>/* See license.txt for terms of usage */

define([
    "firebug/lib/trace",
],
function(FBTrace) {

// ********************************************************************************************* //
// Constants

function pauseGrip(context, args)
{
    var actor = args[0];
    var type = args[1];

    var context = Firebug.currentContext;
    if (!context)
        return "No current context";

    var client = context.debuggerClient;
    if (!client)
        return "Debugger client not available";

    var thread = client.activeThread;
    if (!thread)
        return "The debugger must be paused";

    if (!actor)
        return "No actor specified";

    var grip = thread.pauseGrip({actor: actor});
    var handler = grip.getPrototypeAndProperties;
    switch (type)
    {
        case "object":
            handler = grip.getPrototypeAndProperties;
            break;

        case "function":
            handler = grip.getSignature;
            break;

        case "decompile":
            handler = grip.getSource;
            break;
    }

    handler.call(grip, function(response)
    {
        Firebug.Console.log(response);
    });

    return Firebug.Console.getDefaultReturnValue(context.window);
}

// ********************************************************************************************* //
// Registration

Firebug.registerCommand("pauseGrip", {
    handler: pauseGrip.bind(this),
    description: "Helper command for accessing server side Grips. For debugging purposes only."
})

return {};

// ********************************************************************************************* //
});
<|endoftext|>


<commit_before>/**
 * Copyright 2021 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import * as Preact from '../../../../src/preact';

/**
 * @param {*} props
 * @param {*} props.id
 * @param {*} props.children
 * @return {*}
 */
export const VideoElementWithActions = ({
  id,
  children,
  actions = ['play', 'pause', 'mute', 'unmute', 'fullscreen'],
}) => (

      {actions.map((action) => (
        <button style={{flex: 1, margin: '0 4px'}} on={`tap:${id}.${action}`}>
          {action}
        </button>
      ))}

    {children}

);
<commit_msg>🐛 Fix bad type (#34254)<commit_after>/**
 * Copyright 2021 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import * as Preact from '../../../../src/preact';

/**
 * @param {*} props
 * @return {*}
 */
export const VideoElementWithActions = ({
  id,
  children,
  actions = ['play', 'pause', 'mute', 'unmute', 'fullscreen'],
}) => (

      {actions.map((action) => (
        <button style={{flex: 1, margin: '0 4px'}} on={`tap:${id}.${action}`}>
          {action}
        </button>
      ))}

    {children}

);
<|endoftext|>


<commit_before>$('body').fadein(1400);

var slinkyRosDisplay = new ROSLIB.Ros({
  url: 'wss://42-b:9090'
});

var displaySwitchTopic = new ROSLIB.Topic({
  ros: slinkyRosDisplay,
  name: '/display/switch',
  messageType: 'std_msgs/String',
});

displaySwitchTopic.subscribe(function(msg){
  var url = msg.data;
  $('body').fadeOut(2000, function() { document.location = url } );
});
<commit_msg>Fixes...<commit_after>$(document).ready(function(){$("body").hide().fadeIn(1000);});

var slinkyRosDisplay = new ROSLIB.Ros({
  url: 'wss://42-b:9090'
});

var displaySwitchTopic = new ROSLIB.Topic({
  ros: slinkyRosDisplay,
  name: '/display/switch',
  messageType: 'std_msgs/String',
});

displaySwitchTopic.subscribe(function(msg){
  var url = msg.data;
  $('body').fadeOut(2000, function() { document.location = url } );
});
<|endoftext|>


<commit_before>"use strict";

var status = require('http-status-codes');
var addSocketResponse = require('./socket/response');
var addSocketKeys = require('./socket/keys');

class WebsocketRest {
	constructor(){
		/**
		 * Websocket server instance.
		 * @type {null}
		 */
		this.socket = null;

		/**
		 * Verzion of your app. This data will exist in all responses to clients.
		 * @type {null}
		 */
		this.apiVersion = null;

		/**
		 * All registered modules.
		 * @type {{}}
		 */
		this.modules = {};

		/**
		 * All on connect to url events.
		 * @type {{}}
		 */
		this.onUrlConnect = {};

		/**
		 * All on close from url events.
		 * @type {{}}
		 */
		this.onUrlClose = {};

		/**
		 * All connected clients.
		 * @type {{}}
		 * @private
		 */
		this._connectedClients = {};

		/**
		 * Winston logger instance
		 * @type {null}
		 */
		this._log = null;
	}

	/**
	 * Init function where you set socket server and apiVersion for responses.
	 *
	 * @param socket
	 * @param apiVersion
	 */
    init(socket, apiVersion) {
        this.socket = socket;
        this.apiVersion = apiVersion;
    }

	/**
	 * Logger must have next methods.
	 *
	 * @param logger
	 */
	logger(logger){
		this._log = logger;
	}

	/**
	 * Get connected socket with key.
	 *
	 * @param key
	 * @returns {*}
	 */
	getConnectedClient(key){
		if(key in this._connectedClients){
			return this._connectedClients[key];
		}
	}

	/**
	 * Get all connected socket clients.
	 *
	 * @returns {{}|*}
	 */
	getConnectedClients(){
		return this._connectedClients;
	}

	/**
	 * Adding new module to this.module if not exists.
	 *
	 * @param moduleName
	 * @param module
	 */
    registerModule(moduleName, module) {
        if (moduleName in this.modules) {
            throw new Error(moduleName + ' is allready in registered modules!');
        } else {
            this.modules[moduleName] = module;
        }
    }

	/**
	 * Register fun. that will execute on connection event when
	 * client want to connect to specific server url.
	 * When callback function is called, the client is added to connected clients.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnConnectUrl(url,fun){
		var self = this;
		if(url in this.onUrlConnect){
			let error = `${url} is allready in onUrlConnect!`;
			self._log.fatal('websocket-rest (registerOnConnectUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlConnect[url] = function(socket){
				try {
					fun(socket,function(){
						self._connectedClients[socket.key] = socket;
					});
				} catch (err) {
					self._log.err(`websocket-rest (registerOnConnectUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * Register fun. that will execute on connection close request from client
	 * or from server action. This will remove client from connected clients
	 * and execute on close function for appropriate socket.urlPath.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnCloseUrl(url, fun) {
		var self = this;
		if (url in this.onUrlClose) {
			let error = `${url} is allready in onUrlClose !`;
			self._log.fatal('websocket-rest (registerOnCloseUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlClose[url] = function(socket){
				try {
					fun(socket);
				} catch (err) {
					self._log.err(`websocket-rest (registerOnCloseUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * On client connect this method will execute
	 * registered function for socket client url.
	 * If url not found it will close connection end report the error
	 *
	 * @param socket
	 * @private
	 */
	_onConnection(socket){
		let urlPath = socket.urlPath;

		if(urlPath in this.onUrlConnect){
			this.onUrlConnect[urlPath](socket);
		} else {
			var err = `UrlPath: ${socket.urlPath}] not found !`;
			socket.error(status.getStatusText(status.NOT_FOUND), [err], status.NOT_FOUND);
		}
	}

	/**
	 * This will add listeners and handlers when socket client will connect to registered url
	 * 1. It will add socket response methods [ data, info, error ].
	 * 2. It will add socket properties...
	 * 3. It will execute on connect function for client url.
	 * 4. It will register on close event which will remove client from connected clients and after
	 * that execute registered on close function.
	 * 5. It will register on message event which will parse client message to json,
	 * check for module and method key in message,
	 * check if client want to call private method,
	 * form request structure,
	 * and call requested method in module.
	 */
    initServer() {
        var self = this;
        this.socket.on('connection', function (socket) {

	        addSocketResponse(socket,self.apiVersion,self._log);
	        addSocketKeys(socket);

	        self._onConnection(socket);

			socket.on('close',function(){
				//Remove connected clients is here because self scopping.
				delete self._connectedClients[socket.key];
				if (socket.urlPath in self.onUrlClose) {
					self.onUrlClose[socket.urlPath](socket);
				}
			});

            socket.on('message', function (msg) {
                var req = JSON.parse(msg || "{}");

				//check req
                var reqKeys = ['module', 'method'];
                var keyError = [];
                for (var i in reqKeys) {
                    if (!(reqKeys[i] in req)) keyError.push(reqKeys[i]);
                }
                if (keyError.length != 0) {
                    var err = `Keys: [${keyError}] not in request!`;
                    socket.error(status.getStatusText(status.BAD_REQUEST),[err],status.BAD_REQUEST);

                } else if(0 == req.method.indexOf("private")){
					var err = `Method: [${req.method}] is private!`;
					socket.error(status.getStatusText(status.METHOD_NOT_ALLOWED),[err],status.METHOD_NOT_ALLOWED);
				} else {
					socket.REST.module = req['module'];
					socket.REST.method = req['method'];

	                //For standardization with express...
	                if (req.hasOwnProperty('data')) {
		                req['body'] = req['data'];
		                delete req['data'];
	                }

	                try{
		                self.modules[req['module']][req['method']](req, socket);
	                } catch (err){
		                self._log.fatal('websocket-rest (on.message)',{
			                message : 'Found new undiscowered error!',
			                stack : err.stack
		                })
	                }
                }
            });
        });
    }
}

/**
 * Module will export instance of WebsocketRest class.
 *
 * @type {WebsocketRest}
 */
module.exports = new WebsocketRest();
<commit_msg>Adding logging on connect and disconnect<commit_after>"use strict";

var status = require('http-status-codes');
var addSocketResponse = require('./socket/response');
var addSocketKeys = require('./socket/keys');

class WebsocketRest {
	constructor(){
		/**
		 * Websocket server instance.
		 * @type {null}
		 */
		this.socket = null;

		/**
		 * Verzion of your app. This data will exist in all responses to clients.
		 * @type {null}
		 */
		this.apiVersion = null;

		/**
		 * All registered modules.
		 * @type {{}}
		 */
		this.modules = {};

		/**
		 * All on connect to url events.
		 * @type {{}}
		 */
		this.onUrlConnect = {};

		/**
		 * All on close from url events.
		 * @type {{}}
		 */
		this.onUrlClose = {};

		/**
		 * All connected clients.
		 * @type {{}}
		 * @private
		 */
		this._connectedClients = {};

		/**
		 * Winston logger instance
		 * @type {null}
		 */
		this._log = null;
	}

	/**
	 * Init function where you set socket server and apiVersion for responses.
	 *
	 * @param socket
	 * @param apiVersion
	 */
    init(socket, apiVersion) {
        this.socket = socket;
        this.apiVersion = apiVersion;
    }

	/**
	 * Logger must have next methods.
	 *
	 * @param logger
	 */
	logger(logger){
		this._log = logger;
	}

	/**
	 * Get connected socket with key.
	 *
	 * @param key
	 * @returns {*}
	 */
	getConnectedClient(key){
		if(key in this._connectedClients){
			return this._connectedClients[key];
		}
	}

	/**
	 * Get all connected socket clients.
	 *
	 * @returns {{}|*}
	 */
	getConnectedClients(){
		return this._connectedClients;
	}

	/**
	 * Adding new module to this.module if not exists.
	 *
	 * @param moduleName
	 * @param module
	 */
    registerModule(moduleName, module) {
        if (moduleName in this.modules) {
            throw new Error(moduleName + ' is allready in registered modules!');
        } else {
            this.modules[moduleName] = module;
        }
    }

	/**
	 * Register fun. that will execute on connection event when
	 * client want to connect to specific server url.
	 * When callback function is called, the client is added to connected clients.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnConnectUrl(url,fun){
		var self = this;
		if(url in this.onUrlConnect){
			let error = `${url} is allready in onUrlConnect!`;
			self._log.fatal('websocket-rest (registerOnConnectUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlConnect[url] = function(socket){
				try {
					fun(socket,function(){
						self._connectedClients[socket.key] = socket;
						self._log.info('websocket-rest (socket.connection)',{
							message: 'Client has connected',
							socket: {
								address: socket.address,
								query: socket.query,
								urlPath: socket.urlPath,
								headers: socket.headers,
								key: socket.key,
								connectedAt: socket.connectedAt
							}
						});
					});
				} catch (err) {
					self._log.err(`websocket-rest (registerOnConnectUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * Register fun. that will execute on connection close request from client
	 * or from server action. This will remove client from connected clients
	 * and execute on close function for appropriate socket.urlPath.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnCloseUrl(url, fun) {
		var self = this;
		if (url in this.onUrlClose) {
			let error = `${url} is allready in onUrlClose !`;
			self._log.fatal('websocket-rest (registerOnCloseUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlClose[url] = function(socket){
				try {
					self._log.info('websocket-rest (socket.close)', {
						message: 'Client has disconnected',
						socket: {
							address: socket.address,
							query: socket.query,
							urlPath: socket.urlPath,
							headers: socket.headers,
							key: socket.key,
							connectedAt: socket.connectedAt
						}
					});
					fun(socket);
				} catch (err) {
					self._log.err(`websocket-rest (registerOnCloseUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * On client connect this method will execute
	 * registered function for socket client url.
	 * If url not found it will close connection end report the error
	 *
	 * @param socket
	 * @private
	 */
	_onConnection(socket){
		let urlPath = socket.urlPath;

		if(urlPath in this.onUrlConnect){
			this.onUrlConnect[urlPath](socket);
		} else {
			var err = `UrlPath: ${socket.urlPath}] not found !`;
			socket.error(status.getStatusText(status.NOT_FOUND), [err], status.NOT_FOUND);
		}
	}

	/**
	 * This will add listeners and handlers when socket client will connect to registered url
	 * 1. It will add socket response methods [ data, info, error ].
	 * 2. It will add socket properties...
	 * 3. It will execute on connect function for client url.
	 * 4. It will register on close event which will remove client from connected clients and after
	 * that execute registered on close function.
	 * 5. It will register on message event which will parse client message to json,
	 * check for module and method key in message,
	 * check if client want to call private method,
	 * form request structure,
	 * and call requested method in module.
	 */
    initServer() {
        var self = this;
        this.socket.on('connection', function (socket) {

	        addSocketResponse(socket,self.apiVersion,self._log);
	        addSocketKeys(socket);

	        self._onConnection(socket);

			socket.on('close',function(){
				//Remove connected clients is here because self scopping.
				delete self._connectedClients[socket.key];
				if (socket.urlPath in self.onUrlClose) {
					self.onUrlClose[socket.urlPath](socket);
				}
			});

            socket.on('message', function (msg) {
                var req = JSON.parse(msg || "{}");

				//check req
                var reqKeys = ['module', 'method'];
                var keyError = [];
                for (var i in reqKeys) {
                    if (!(reqKeys[i] in req)) keyError.push(reqKeys[i]);
                }
                if (keyError.length != 0) {
                    var err = `Keys: [${keyError}] not in request!`;
                    socket.error(status.getStatusText(status.BAD_REQUEST),[err],status.BAD_REQUEST);

                } else if(0 == req.method.indexOf("private")){
					var err = `Method: [${req.method}] is private!`;
					socket.error(status.getStatusText(status.METHOD_NOT_ALLOWED),[err],status.METHOD_NOT_ALLOWED);
				} else {
					socket.REST.module = req['module'];
					socket.REST.method = req['method'];

	                //For standardization with express...
	                if (req.hasOwnProperty('data')) {
		                req['body'] = req['data'];
		                delete req['data'];
	                }

	                try{
		                self.modules[req['module']][req['method']](req, socket);
	                } catch (err){
		                self._log.fatal('websocket-rest (on.message)',{
			                message : 'Found new undiscowered error!',
			                stack : err.stack
		                })
	                }
                }
            });
        });
    }
}

/**
 * Module will export instance of WebsocketRest class.
 *
 * @type {WebsocketRest}
 */
module.exports = new WebsocketRest();
<|endoftext|>


<commit_before>"use strict";

var status = require('http-status-codes');
var addSocketResponse = require('./socket/response');
var addSocketKeys = require('./socket/keys');

class WebsocketRest {
	constructor(){
		/**
		 * Websocket server instance.
		 * @type {null}
		 */
		this.socket = null;

		/**
		 * Verzion of your app. This data will exist in all responses to clients.
		 * @type {null}
		 */
		this.apiVersion = null;

		/**
		 * All registered modules.
		 * @type {{}}
		 */
		this.modules = {};

		/**
		 * All on connect to url events.
		 * @type {{}}
		 */
		this.onUrlConnect = {};

		/**
		 * All on close from url events.
		 * @type {{}}
		 */
		this.onUrlClose = {};

		/**
		 * All connected clients.
		 * @type {{}}
		 * @private
		 */
		this._connectedClients = {};

		/**
		 * Winston logger instance
		 * @type {null}
		 */
		this._log = null;
	}

	/**
	 * Init function where you set socket server and apiVersion for responses.
	 *
	 * @param socket
	 * @param apiVersion
	 */
    init(socket, apiVersion) {
        this.socket = socket;
        this.apiVersion = apiVersion;
    }

	/**
	 * Logger must have next methods.
	 *
	 * @param logger
	 */
	logger(logger){
		this._log = logger;
	}

	/**
	 * Get connected socket with key.
	 *
	 * @param key
	 * @returns {*}
	 */
	getConnectedClient(key){
		if(key in this._connectedClients){
			return this._connectedClients[key];
		}
	}

	/**
	 * Get all connected socket clients.
	 *
	 * @returns {{}|*}
	 */
	getConnectedClients(){
		return this._connectedClients;
	}

	/**
	 * Adding new module to this.module if not exists.
	 *
	 * @param moduleName
	 * @param module
	 */
    registerModule(moduleName, module) {
        if (moduleName in this.modules) {
            throw new Error(moduleName + ' is allready in registered modules!');
        } else {
            this.modules[moduleName] = module;
        }
    }

	/**
	 * Register fun. that will execute on connection event when
	 * client want to connect to specific server url.
	 * When callback function is called, the client is added to connected clients.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnConnectUrl(url,fun){
		var self = this;
		if(url in this.onUrlConnect){
			let error = `${url} is allready in onUrlConnect!`;
			self._log.fatal('websocket-rest (registerOnConnectUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlConnect[url] = function(socket){
				try {
					fun(socket,function(){
						self._connectedClients[socket.key] = socket;
					});
				} catch (err) {
					self._log.err(`websocket-rest (registerOnConnectUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * Register fun. that will execute on connection close request from client
	 * or from server action. This will remove client from connected clients
	 * and execute on close function for appropriate socket.urlPath.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnCloseUrl(url, fun) {
		var self = this;
		if (url in this.onUrlClose) {
			let error = `${url} is allready in onUrlClose !`;
			self._log.fatal('websocket-rest (registerOnCloseUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlClose[url] = function(socket){
				try {
					fun(socket);
				} catch (err) {
					self._log.err(`websocket-rest (registerOnCloseUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * On client connect this method will execute
	 * registered function for socket client url.
	 * If url not found it will close connection end report the error
	 *
	 * @param socket
	 * @private
	 */
	_onConnection(socket){
		let urlPath = socket.urlPath;

		if(urlPath in this.onUrlConnect){
			this.onUrlConnect[urlPath](socket);
		} else {
			var err = `UrlPath: ${socket.urlPath}] not found !`;
			socket.error(status.getStatusText(status.NOT_FOUND), [err], status.NOT_FOUND);
		}
	}

	/**
	 * This will add listeners and handlers when socket client will connect to registered url
	 * 1. It will add socket response methods [ data, info, error ].
	 * 2. It will add socket properties...
	 * 3. It will execute on connect function for client url.
	 * 4. It will register on close event which will remove client from connected clients and after
	 * that execute registered on close function.
	 * 5. It will register on message event which will parse client message to json,
	 * check for module and method key in message,
	 * check if client want to call private method,
	 * form request structure,
	 * and call requested method in module.
	 */
    initServer() {
        var self = this;
        this.socket.on('connection', function (socket) {

	        addSocketResponse(socket,self.apiVersion,self._log);
	        addSocketKeys(socket);

	        self._onConnection(socket);

			socket.on('close',function(){
				//Remove connected clients is here because self scopping.
				delete self._connectedClients[socket.key];
				if (socket.urlPath in self.onUrlClose) {
					self.onUrlClose[socket.urlPath](socket);
				}
			});

            socket.on('message', function (msg) {
                var req = JSON.parse(msg || "{}");

				//check req
                var reqKeys = ['module', 'method'];
                var keyError = [];
                for (var i in reqKeys) {
                    if (!(reqKeys[i] in req)) keyError.push(reqKeys[i]);
                }
                if (keyError.length != 0) {
                    var err = `Keys: [${keyError}] not in request!`;
                    socket.error(status.getStatusText(status.BAD_REQUEST),[err],status.BAD_REQUEST);

                } else if(0 == req.method.indexOf("private")){
					var err = `Method: [${req.method}] is private!`;
					socket.error(status.getStatusText(status.METHOD_NOT_ALLOWED),[err],status.METHOD_NOT_ALLOWED);
				} else {
					socket.REST.module = req['module'];
					socket.REST.method = req['method'];

	                //For standardization with express...
	                if (req.hasOwnProperty('data')) {
		                req['body'] = req['data'];
		                delete req['data'];
	                }

	                try{
		                self.modules[req['module']][req['method']](req, socket);
	                } catch (err){
		                self._log.fatal('websocket-rest (on.message)',{
			                message : 'Found new undiscowered error!',
			                stack : err.stack
		                })
	                }
                }
            });
        });
    }
}

/**
 * Module will export instance of WebsocketRest class.
 *
 * @type {WebsocketRest}
 */
module.exports = new WebsocketRest();
<commit_msg>Fixing req. standardization<commit_after>"use strict";

var status = require('http-status-codes');
var addSocketResponse = require('./socket/response');
var addSocketKeys = require('./socket/keys');

class WebsocketRest {
	constructor(){
		/**
		 * Websocket server instance.
		 * @type {null}
		 */
		this.socket = null;

		/**
		 * Verzion of your app. This data will exist in all responses to clients.
		 * @type {null}
		 */
		this.apiVersion = null;

		/**
		 * All registered modules.
		 * @type {{}}
		 */
		this.modules = {};

		/**
		 * All on connect to url events.
		 * @type {{}}
		 */
		this.onUrlConnect = {};

		/**
		 * All on close from url events.
		 * @type {{}}
		 */
		this.onUrlClose = {};

		/**
		 * All connected clients.
		 * @type {{}}
		 * @private
		 */
		this._connectedClients = {};

		/**
		 * Winston logger instance
		 * @type {null}
		 */
		this._log = null;
	}

	/**
	 * Init function where you set socket server and apiVersion for responses.
	 *
	 * @param socket
	 * @param apiVersion
	 */
    init(socket, apiVersion) {
        this.socket = socket;
        this.apiVersion = apiVersion;
    }

	/**
	 * Logger must have next methods.
	 *
	 * @param logger
	 */
	logger(logger){
		this._log = logger;
	}

	/**
	 * Get connected socket with key.
	 *
	 * @param key
	 * @returns {*}
	 */
	getConnectedClient(key){
		if(key in this._connectedClients){
			return this._connectedClients[key];
		}
	}

	/**
	 * Get all connected socket clients.
	 *
	 * @returns {{}|*}
	 */
	getConnectedClients(){
		return this._connectedClients;
	}

	/**
	 * Adding new module to this.module if not exists.
	 *
	 * @param moduleName
	 * @param module
	 */
    registerModule(moduleName, module) {
        if (moduleName in this.modules) {
            throw new Error(moduleName + ' is allready in registered modules!');
        } else {
            this.modules[moduleName] = module;
        }
    }

	/**
	 * Register fun. that will execute on connection event when
	 * client want to connect to specific server url.
	 * When callback function is called, the client is added to connected clients.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnConnectUrl(url,fun){
		var self = this;
		if(url in this.onUrlConnect){
			let error = `${url} is allready in onUrlConnect!`;
			self._log.fatal('websocket-rest (registerOnConnectUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlConnect[url] = function(socket){
				try {
					fun(socket,function(){
						self._connectedClients[socket.key] = socket;
					});
				} catch (err) {
					self._log.err(`websocket-rest (registerOnConnectUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * Register fun. that will execute on connection close request from client
	 * or from server action. This will remove client from connected clients
	 * and execute on close function for appropriate socket.urlPath.
	 *
	 * @param url
	 * @param fun
	 */
	registerOnCloseUrl(url, fun) {
		var self = this;
		if (url in this.onUrlClose) {
			let error = `${url} is allready in onUrlClose !`;
			self._log.fatal('websocket-rest (registerOnCloseUrl)',{
				message : error,
				url : url
			});
			throw new Error(error);
		} else {
			this.onUrlClose[url] = function(socket){
				try {
					fun(socket);
				} catch (err) {
					self._log.err(`websocket-rest (registerOnCloseUrl)`,{
						message : 'this.onUrlConnect[url]',
						url : url,
						stack : err.stack
					});
				}
			};
		}
	}

	/**
	 * On client connect this method will execute
	 * registered function for socket client url.
	 * If url not found it will close connection end report the error
	 *
	 * @param socket
	 * @private
	 */
	_onConnection(socket){
		let urlPath = socket.urlPath;

		if(urlPath in this.onUrlConnect){
			this.onUrlConnect[urlPath](socket);
		} else {
			var err = `UrlPath: ${socket.urlPath}] not found !`;
			socket.error(status.getStatusText(status.NOT_FOUND), [err], status.NOT_FOUND);
		}
	}

	/**
	 * This will add listeners and handlers when socket client will connect to registered url
	 * 1. It will add socket response methods [ data, info, error ].
	 * 2. It will add socket properties...
	 * 3. It will execute on connect function for client url.
	 * 4. It will register on close event which will remove client from connected clients and after
	 * that execute registered on close function.
	 * 5. It will register on message event which will parse client message to json,
	 * check for module and method key in message,
	 * check if client want to call private method,
	 * form request structure,
	 * and call requested method in module.
	 */
    initServer() {
        var self = this;
        this.socket.on('connection', function (socket) {

	        addSocketResponse(socket,self.apiVersion,self._log);
	        addSocketKeys(socket);

	        self._onConnection(socket);

			socket.on('close',function(){
				//Remove connected clients is here because self scopping.
				delete self._connectedClients[socket.key];
				if (socket.urlPath in self.onUrlClose) {
					self.onUrlClose[socket.urlPath](socket);
				}
			});

            socket.on('message', function (msg) {
                var req = JSON.parse(msg || "{}");

				//check req
                var reqKeys = ['module', 'method'];
                var keyError = [];
                for (var i in reqKeys) {
                    if (!(reqKeys[i] in req)) keyError.push(reqKeys[i]);
                }
                if (keyError.length != 0) {
                    var err = `Keys: [${keyError}] not in request!`;
                    socket.error(status.getStatusText(status.BAD_REQUEST),[err],status.BAD_REQUEST);

                } else if(0 == req.method.indexOf("private")){
					var err = `Method: [${req.method}] is private!`;
					socket.error(status.getStatusText(status.METHOD_NOT_ALLOWED),[err],status.METHOD_NOT_ALLOWED);
				} else {
					socket.REST.module = req['module'];
					socket.REST.method = req['method'];

	                //For standardization with express...
	                if(!req.data){
		                req.body = {};
	                } else {
		                req.body = req.data;
		                delete req.data;
	                }

	                try{
		                self.modules[req['module']][req['method']](req, socket);
	                } catch (err){
		                self._log.fatal('websocket-rest (on.message)',{
			                message : 'Found new undiscowered error!',
			                stack : err.stack
		                })
	                }
                }
            });
        });
    }
}

/**
 * Module will export instance of WebsocketRest class.
 *
 * @type {WebsocketRest}
 */
module.exports = new WebsocketRest();
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var hue = require('node-hue-api');
var q = require('q');
var HueApi = hue.HueApi;
var lightState = hue.lightState;

var hostname = '192.168.117.28';
var username = '';
var api = new HueApi(hostname, username);

router.get('/bridges', function(req, res) {
    hue.nupnpSearch(function(err, result) {
        if (err) throw err;
        res.send(result);
    });
});

router.get('/lights', function(req, res) {
    api.lights(function(err, lights) {
        if (err) throw err;
        res.send(lights);
    });
});

router.get('/lights/details', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            promises.push(api.lightStatus(light.id));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/lights/:id', function(req, res) {
    api.lightStatus(req.params.id)
        .then(function(result) {
            res.send(result);
        })
        .done();
});

router.get('/lights/:id/on', function(req, res) {
    api.setLightState(req.params.id, {'on': true})
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/lights/:id/off', function(req, res) {
    api.setLightState(req.params.id, {'on': false})
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/lights/:id/random', function(req, res) {
    api.setLightState(req.params.id, {
        'xy': [
            Math.random(),
            Math.random()
        ],
    })
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/groups', function(req, res) {
    api.groups()
        .then(function(result) {
            res.send(result);
        })
        .done();
});
/*
router.get('/register', function(req, res) {
    api = new HueApi();
    api.createUser(hostname, null, null, function(err, user) {
        if (err) throw err;
        res.send(user);
    });
});
*/

router.get('/on', function(req, res) {
    api.setGroupLightState(0, {'on': true}) // provide a value of false to turn off
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/brightness/inc', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            var state = lightState.create(light);
            promises.push(api.setLightState(light.id, state.bri_inc(50)));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/brightness/dec', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            var state = lightState.create(light);
            promises.push(api.setLightState(light.id, state.bri_inc(-50)));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/off', function(req, res) {
    api.setGroupLightState(0, {'on': false}) // provide a value of false to turn off
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/randomcolor', function(req, res) {
    api.setGroupLightState(0, {
        'xy': [
            Math.random(),
            Math.random()
        ]
    })
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/randomcolors', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            promises.push(api.setLightState(light.id, {
                'xy': [
                    Math.random(),
                    Math.random()
                ]
            }));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

module.exports = router;
<commit_msg>feat(lights): set rgb value and colorloop<commit_after>var express = require('express');
var router = express.Router();
var hue = require('node-hue-api');
var q = require('q');
var HueApi = hue.HueApi;
var lightState = hue.lightState;

var hostname = '192.168.117.28';
var username = '120e0f4639d30f441d7b6b923e8a073f';
var api = new HueApi(hostname, username);

router.get('/bridges', function(req, res) {
    hue.nupnpSearch(function(err, result) {
        if (err) throw err;
        res.send(result);
    });
});

router.get('/lights', function(req, res) {
    api.lights(function(err, lights) {
        if (err) throw err;
        res.send(lights);
    });
});

router.get('/lights/details', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            promises.push(api.lightStatus(light.id));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/lights/:id', function(req, res) {
    api.lightStatus(req.params.id)
        .then(function(result) {
            res.send(result);
        })
        .done();
});

router.get('/lights/:id/on', function(req, res) {
    api.setLightState(req.params.id, {'on': true})
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/lights/:id/off', function(req, res) {
    api.setLightState(req.params.id, {'on': false})
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/lights/:id/random', function(req, res) {
    api.setLightState(req.params.id, {
        'xy': [
            Math.random(),
            Math.random()
        ],
    })
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/lights/:id/set', function(req, res) {
    api.lightStatus(req.params.id)
        .then(function(result) {
            var state = lightState.create(result);
            state.rgb([
                req.query.r,
                req.query.g,
                req.query.b
            ])
            return api.setLightState(req.params.id, state);
        })
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/groups', function(req, res) {
    api.groups()
        .then(function(result) {
            res.send(result);
        })
        .done();
});
/*
router.get('/register', function(req, res) {
    api = new HueApi();
    api.createUser(hostname, null, null, function(err, user) {
        if (err) throw err;
        res.send(user);
    });
});
*/

router.get('/on', function(req, res) {
    api.setGroupLightState(0, {'on': true}) // provide a value of false to turn off
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/brightness/inc', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            var state = lightState.create(light);
            promises.push(api.setLightState(light.id, state.bri_inc(50)));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/brightness/dec', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            var state = lightState.create(light);
            promises.push(api.setLightState(light.id, state.bri_inc(-50)));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/off', function(req, res) {
    api.setGroupLightState(0, {'on': false}) // provide a value of false to turn off
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/randomcolor', function(req, res) {
    api.setGroupLightState(0, {
        'xy': [
            Math.random(),
            Math.random()
        ]
    })
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});

router.get('/randomcolors', function(req, res) {
    api.lights(function(err, result) {
        if (err) throw err;
        var promises = [];
        result.lights.forEach(function(light) {
            promises.push(api.setLightState(light.id, {
                'xy': [
                    Math.random(),
                    Math.random()
                ]
            }));
        });
        q.all(promises)
        .then(function(result) {
            var data = [];
            res.send(result);
        },
        function() {
            res.sendStatus(500);
        });
    });
});

router.get('/colorloop', function(req, res) {
    var state = lightState.create().colorLoop();
    api.setGroupLightState(0, state)
        .then(function(result) {
            res.send(result);
        })
        .fail(function(error) {
            res.send(error);
        })
        .done();
});
module.exports = router;
<|endoftext|>