<commit_before>'use strict';

(function() {
  const DEFAULT_FETCH_INTERVAL_SEC = 600;
  const NOTIE_DISPLAY_SEC = 1.5;
  const COLOR_ICON_FILENAME_64 = 'redmine_icon_color_64.png';

  var remote = window.require('remote');
  var shell = remote.require('shell');
  var fs = require('fs');
  var notie = require('notie');
  var notifier = require('node-notifier');

  var FETCH_MODE = Object.freeze({ TIME: 'TIME', DATE: 'DATE' });

  /**
   * Initialize the RedmineNotifier object.
   * @constructor
   */
  function RedmineNotifier() {
    this._lastExecutionTime = null;
    this._settings = null;
    this._fetchTimer = null;
    this._fetchMode = null;
  }

  /**
   * Initialize the event listeners.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.initEventListener = function() {
    var _this = this;

    document.getElementById('save-button').addEventListener('click', function() {
      _this.readScreenSettings();

      if (_this.validateSettings()) {
        _this.initFetch()
          .updateSettings();
      } else {
        _this.readStoredSettings();
      }

      notie.alert(1, 'Settings have been saved.', NOTIE_DISPLAY_SEC);
    });

    document.getElementById('close-button').addEventListener('click', function() {
      _this.readStoredSettings()
        .displaySettings();
      remote.getCurrentWindow().hide();
    });

    document.getElementById('test-connection-button').addEventListener('click', function() {
      _this.testConnection(FETCH_MODE.TIME);
    });

    return this;
  };

  /**
   * Display the default settings on the screen.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.displayDefaultSettings = function() {
    document.getElementById('default-fetch-interval-sec').innerHTML = DEFAULT_FETCH_INTERVAL_SEC;
    return this;
  };

  /**
   * Display the settings on the screen.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.displaySettings = function() {
    document.getElementById('url').value = this._settings.url;
    document.getElementById('api-key').value = this._settings.apiKey;
    document.getElementById('project-id').value = this._settings.projectId;
    document.getElementById('fetch-interval-sec').value = this._settings.fetchIntervalSec;
    return this;
  };

  /**
   * Get the settings from the screen.
   * @return {Object} Settings.
   */
  RedmineNotifier.prototype.getPageSettings = function() {
    return {
      url: document.getElementById('url').value,
      apiKey: document.getElementById('api-key').value,
      projectId: document.getElementById('project-id').value,
      fetchIntervalSec: document.getElementById('fetch-interval-sec').value
    };
  };

  /**
   * Read the settings from the screen.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.readScreenSettings = function() {
    this._settings = this.getPageSettings();
    return this;
  };

  /**
   * Read the settings from the localStorage.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.readStoredSettings = function() {
    this._settings = {
      url: localStorage.getItem('url'),
      apiKey: localStorage.getItem('apiKey'),
      projectId: localStorage.getItem('projectId'),
      fetchIntervalSec: localStorage.getItem('fetchIntervalSec')
    };

    return this;
  };

  /**
   * Update the stored last execution time.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.updateLastExecutionTime = function() {
    this._lastExecutionTime = (new Date()).toISOString().replace(/\.\d+Z$/, 'Z');
    localStorage.setItem('lastExecutionTime', this._lastExecutionTime);
    return this;
  };

  /**
   * Update the stored settings.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.updateSettings = function() {
    localStorage.setItem('url', this._settings.url);
    localStorage.setItem('apiKey', this._settings.apiKey);
    localStorage.setItem('projectId', this._settings.projectId);
    localStorage.setItem('fetchIntervalSec', this._settings.fetchIntervalSec);
    return this;
  };

  /**
   * Validate the settings.
   * @return {boolean} true if valid.
   */
  RedmineNotifier.prototype.validateSettings = function() {
    if (this._settings.url && this._settings.apiKey) {
      return true;
    } else {
      notie.alert(3, 'Please enter required fields.', NOTIE_DISPLAY_SEC);
      return false;
    }
  };

  /**
   * Initialize the fetch function.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.initFetch = function() {
    var _this = this;
    var intervalMsec = 1000 * (this._settings.fetchIntervalSec || DEFAULT_FETCH_INTERVAL_SEC);

    clearInterval(this._fetchTimer);

    this._fetchTimer = setInterval(function() {
      _this.fetch(_this._fetchMode || FETCH_MODE.TIME);
    }, intervalMsec);

    return this;
  };

  /**
   * Fetch updated issues by using Redmine REST API.
   * @param {string} mode - Time or date.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.fetch = function(mode) {
    var _this = this;
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        _this.handleResponseFetch(mode, xhr.status, xhr.responseText);
      }
    };

    xhr.open('GET', this._settings.url + '/issues.json' + this.getRequestParams(mode, this._settings.projectId));
    xhr.setRequestHeader('X-Redmine-API-Key', this._settings.apiKey);
    xhr.send();

    return this;
  };

  /**
   * Handle the response for the fetch.
   * @param {string} mode - Time or date.
   * @param {number} status - Response status.
   * @param {string} responseText - Response text.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.handleResponseFetch = function(mode, status, responseText) {
    if (mode === FETCH_MODE.TIME) {
      if (status === 200) {
        this.notify(JSON.parse(responseText).issues)
          .updateLastExecutionTime();
      } else if (status === 422) {
        // Retry with date mode if Redmine API doesn't accept time format
        this._fetchMode = FETCH_MODE.DATE;
        this.fetch(FETCH_MODE.DATE);
      }
    } else {
      if (status === 200) {
        this.notify(this.pickIssues(JSON.parse(responseText).issues));
      }

      this.updateLastExecutionTime();
    }

    return this;
  };

  /**
   * Get issues which were updated after last execution time.
   * @param {string} responseIssues - Response issues.
   * @return {Object[]} Processed issues.
   */
  RedmineNotifier.prototype.pickIssues = function(responseIssues) {
    var responseIssueCount = responseIssues.length;
    var lastExecutionTime = new Date(this._lastExecutionTime).getTime();
    var issues = [];
    var i;
    var updatedTime;

    for (i = 0; i < responseIssueCount; i++) {
      updatedTime = new Date(responseIssues[i].updated_on).getTime();

      if (updatedTime >= lastExecutionTime) {
        issues.push(responseIssues[i]);
      }
    }

    return issues;
  };

  /**
   * Test the connection to the Redmine.
   * @param {string} mode - Time or date.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.testConnection = function(mode) {
    var _this = this;
    var xhr = new XMLHttpRequest();
    var pageSettings = this.getPageSettings();

    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        _this.handleResponseTestConnection(mode, xhr.status);
      }
    };

    xhr.open('GET', pageSettings.url + '/issues.json' + this.getRequestParams(mode, pageSettings.projectId));
    xhr.setRequestHeader('X-Redmine-API-Key', pageSettings.apiKey);
    xhr.send();

    return this;
  };

  /**
   * Handle the response for the test connection.
   * @param {string} mode - Time or date.
   * @param {number} status - Response status.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.handleResponseTestConnection = function(mode, status) {
    if (status === 200) {
      notie.alert(1, 'Connection succeeded.', NOTIE_DISPLAY_SEC);
      return this;
    }

    // Retry with date mode if Redmine API doesn't accept time format
    if (mode === FETCH_MODE.TIME && status === 422) {
      this.testConnection(FETCH_MODE.DATE);
      return this;
    }

    notie.alert(3, 'Connection failed.', NOTIE_DISPLAY_SEC);

    return this;
  };

  /**
   * Get the request parameters.
   * @param {string} mode - Time or date.
   * @param {string} projectId - Project ID (a numeric value, not a project identifier).
   * @return {string} Request parameters.
   */
  RedmineNotifier.prototype.getRequestParams = function(mode, projectId) {
    var params = [
      'updated_on=%3E%3D' + this.getLastExecutionTime(mode),
      'sort=updated_on:desc'
    ];

    if (typeof projectId === 'string' && projectId !== '') {
      params.unshift('project_id=' + projectId);
    }

    return '?' + params.join('&');
  };

  /**
   * Get last execution time by mode.
   * @param {string} mode - Time or date.
   * @return {string} Last execution time.
   */
  RedmineNotifier.prototype.getLastExecutionTime = function(mode) {
    if (mode === FETCH_MODE.TIME) {
      return this._lastExecutionTime;
    } else {
      return this._lastExecutionTime.replace(/T.*/, ''); // Date
    }
  };

  /**
   * Send the desktop notification.
   * @param {Object} issues - All of updated issues.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.notify = function(issues) {
    var _this = this;
    var issueCount = issues.length;

    if (issueCount === 0) return this;

    var appDir = __dirname + '.unpacked'; // Production
    try {
      fs.statSync(appDir);
    } catch(e) {
      appDir = __dirname; // Development
    }

    // Display the latest issue's subject only
    notifier.notify({
      title: '(' + issueCount + ') Redmine Notifier',
      message: issues[0].subject,
      icon: appDir + '/images/' + COLOR_ICON_FILENAME_64,
      wait: true
    });

    notifier.removeAllListeners();

    notifier.once('click', function() {
      shell.openExternal(_this._settings.url + '/issues/' + issues[0].id);
      notifier.removeAllListeners();
    });

    notifier.once('timeout', function() {
      notifier.removeAllListeners();
    });

    return this;
  };

  window.addEventListener('load', function() {
    var redmineNotifier = new RedmineNotifier();
    redmineNotifier.initEventListener()
      .displayDefaultSettings()
      .updateLastExecutionTime()
      .readStoredSettings()
      .displaySettings();

    if (redmineNotifier.validateSettings()) {
      redmineNotifier.initFetch();
    }
  });
}());

<commit_msg>Do not flash previous page style, like `background-color` of a button<commit_after>'use strict';

(function() {
  const DEFAULT_FETCH_INTERVAL_SEC = 600;
  const NOTIE_DISPLAY_SEC = 1.5;
  const COLOR_ICON_FILENAME_64 = 'redmine_icon_color_64.png';

  var remote = window.require('remote');
  var shell = remote.require('shell');
  var fs = require('fs');
  var notie = require('notie');
  var notifier = require('node-notifier');

  var FETCH_MODE = Object.freeze({ TIME: 'TIME', DATE: 'DATE' });

  /**
   * Initialize the RedmineNotifier object.
   * @constructor
   */
  function RedmineNotifier() {
    this._lastExecutionTime = null;
    this._settings = null;
    this._fetchTimer = null;
    this._fetchMode = null;
  }

  /**
   * Initialize the event listeners.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.initEventListener = function() {
    var _this = this;

    document.getElementById('save-button').addEventListener('click', function() {
      _this.readScreenSettings();

      if (_this.validateSettings()) {
        _this.initFetch()
          .updateSettings();
      } else {
        _this.readStoredSettings();
      }

      notie.alert(1, 'Settings have been saved.', NOTIE_DISPLAY_SEC);
    });

    document.getElementById('close-button').addEventListener('click', function() {
      _this.readStoredSettings()
        .displaySettings();
      remote.getCurrentWindow().hide();
      remote.getCurrentWindow().reload();
    });

    document.getElementById('test-connection-button').addEventListener('click', function() {
      _this.testConnection(FETCH_MODE.TIME);
    });

    return this;
  };

  /**
   * Display the default settings on the screen.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.displayDefaultSettings = function() {
    document.getElementById('default-fetch-interval-sec').innerHTML = DEFAULT_FETCH_INTERVAL_SEC;
    return this;
  };

  /**
   * Display the settings on the screen.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.displaySettings = function() {
    document.getElementById('url').value = this._settings.url;
    document.getElementById('api-key').value = this._settings.apiKey;
    document.getElementById('project-id').value = this._settings.projectId;
    document.getElementById('fetch-interval-sec').value = this._settings.fetchIntervalSec;
    return this;
  };

  /**
   * Get the settings from the screen.
   * @return {Object} Settings.
   */
  RedmineNotifier.prototype.getPageSettings = function() {
    return {
      url: document.getElementById('url').value,
      apiKey: document.getElementById('api-key').value,
      projectId: document.getElementById('project-id').value,
      fetchIntervalSec: document.getElementById('fetch-interval-sec').value
    };
  };

  /**
   * Read the settings from the screen.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.readScreenSettings = function() {
    this._settings = this.getPageSettings();
    return this;
  };

  /**
   * Read the settings from the localStorage.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.readStoredSettings = function() {
    this._settings = {
      url: localStorage.getItem('url'),
      apiKey: localStorage.getItem('apiKey'),
      projectId: localStorage.getItem('projectId'),
      fetchIntervalSec: localStorage.getItem('fetchIntervalSec')
    };

    return this;
  };

  /**
   * Update the stored last execution time.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.updateLastExecutionTime = function() {
    this._lastExecutionTime = (new Date()).toISOString().replace(/\.\d+Z$/, 'Z');
    localStorage.setItem('lastExecutionTime', this._lastExecutionTime);
    return this;
  };

  /**
   * Update the stored settings.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.updateSettings = function() {
    localStorage.setItem('url', this._settings.url);
    localStorage.setItem('apiKey', this._settings.apiKey);
    localStorage.setItem('projectId', this._settings.projectId);
    localStorage.setItem('fetchIntervalSec', this._settings.fetchIntervalSec);
    return this;
  };

  /**
   * Validate the settings.
   * @return {boolean} true if valid.
   */
  RedmineNotifier.prototype.validateSettings = function() {
    if (this._settings.url && this._settings.apiKey) {
      return true;
    } else {
      notie.alert(3, 'Please enter required fields.', NOTIE_DISPLAY_SEC);
      return false;
    }
  };

  /**
   * Initialize the fetch function.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.initFetch = function() {
    var _this = this;
    var intervalMsec = 1000 * (this._settings.fetchIntervalSec || DEFAULT_FETCH_INTERVAL_SEC);

    clearInterval(this._fetchTimer);

    this._fetchTimer = setInterval(function() {
      _this.fetch(_this._fetchMode || FETCH_MODE.TIME);
    }, intervalMsec);

    return this;
  };

  /**
   * Fetch updated issues by using Redmine REST API.
   * @param {string} mode - Time or date.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.fetch = function(mode) {
    var _this = this;
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        _this.handleResponseFetch(mode, xhr.status, xhr.responseText);
      }
    };

    xhr.open('GET', this._settings.url + '/issues.json' + this.getRequestParams(mode, this._settings.projectId));
    xhr.setRequestHeader('X-Redmine-API-Key', this._settings.apiKey);
    xhr.send();

    return this;
  };

  /**
   * Handle the response for the fetch.
   * @param {string} mode - Time or date.
   * @param {number} status - Response status.
   * @param {string} responseText - Response text.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.handleResponseFetch = function(mode, status, responseText) {
    if (mode === FETCH_MODE.TIME) {
      if (status === 200) {
        this.notify(JSON.parse(responseText).issues)
          .updateLastExecutionTime();
      } else if (status === 422) {
        // Retry with date mode if Redmine API doesn't accept time format
        this._fetchMode = FETCH_MODE.DATE;
        this.fetch(FETCH_MODE.DATE);
      }
    } else {
      if (status === 200) {
        this.notify(this.pickIssues(JSON.parse(responseText).issues));
      }

      this.updateLastExecutionTime();
    }

    return this;
  };

  /**
   * Get issues which were updated after last execution time.
   * @param {string} responseIssues - Response issues.
   * @return {Object[]} Processed issues.
   */
  RedmineNotifier.prototype.pickIssues = function(responseIssues) {
    var responseIssueCount = responseIssues.length;
    var lastExecutionTime = new Date(this._lastExecutionTime).getTime();
    var issues = [];
    var i;
    var updatedTime;

    for (i = 0; i < responseIssueCount; i++) {
      updatedTime = new Date(responseIssues[i].updated_on).getTime();

      if (updatedTime >= lastExecutionTime) {
        issues.push(responseIssues[i]);
      }
    }

    return issues;
  };

  /**
   * Test the connection to the Redmine.
   * @param {string} mode - Time or date.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.testConnection = function(mode) {
    var _this = this;
    var xhr = new XMLHttpRequest();
    var pageSettings = this.getPageSettings();

    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        _this.handleResponseTestConnection(mode, xhr.status);
      }
    };

    xhr.open('GET', pageSettings.url + '/issues.json' + this.getRequestParams(mode, pageSettings.projectId));
    xhr.setRequestHeader('X-Redmine-API-Key', pageSettings.apiKey);
    xhr.send();

    return this;
  };

  /**
   * Handle the response for the test connection.
   * @param {string} mode - Time or date.
   * @param {number} status - Response status.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.handleResponseTestConnection = function(mode, status) {
    if (status === 200) {
      notie.alert(1, 'Connection succeeded.', NOTIE_DISPLAY_SEC);
      return this;
    }

    // Retry with date mode if Redmine API doesn't accept time format
    if (mode === FETCH_MODE.TIME && status === 422) {
      this.testConnection(FETCH_MODE.DATE);
      return this;
    }

    notie.alert(3, 'Connection failed.', NOTIE_DISPLAY_SEC);

    return this;
  };

  /**
   * Get the request parameters.
   * @param {string} mode - Time or date.
   * @param {string} projectId - Project ID (a numeric value, not a project identifier).
   * @return {string} Request parameters.
   */
  RedmineNotifier.prototype.getRequestParams = function(mode, projectId) {
    var params = [
      'updated_on=%3E%3D' + this.getLastExecutionTime(mode),
      'sort=updated_on:desc'
    ];

    if (typeof projectId === 'string' && projectId !== '') {
      params.unshift('project_id=' + projectId);
    }

    return '?' + params.join('&');
  };

  /**
   * Get last execution time by mode.
   * @param {string} mode - Time or date.
   * @return {string} Last execution time.
   */
  RedmineNotifier.prototype.getLastExecutionTime = function(mode) {
    if (mode === FETCH_MODE.TIME) {
      return this._lastExecutionTime;
    } else {
      return this._lastExecutionTime.replace(/T.*/, ''); // Date
    }
  };

  /**
   * Send the desktop notification.
   * @param {Object} issues - All of updated issues.
   * @return {Object} Current object.
   */
  RedmineNotifier.prototype.notify = function(issues) {
    var _this = this;
    var issueCount = issues.length;

    if (issueCount === 0) return this;

    var appDir = __dirname + '.unpacked'; // Production
    try {
      fs.statSync(appDir);
    } catch(e) {
      appDir = __dirname; // Development
    }

    // Display the latest issue's subject only
    notifier.notify({
      title: '(' + issueCount + ') Redmine Notifier',
      message: issues[0].subject,
      icon: appDir + '/images/' + COLOR_ICON_FILENAME_64,
      wait: true
    });

    notifier.removeAllListeners();

    notifier.once('click', function() {
      shell.openExternal(_this._settings.url + '/issues/' + issues[0].id);
      notifier.removeAllListeners();
    });

    notifier.once('timeout', function() {
      notifier.removeAllListeners();
    });

    return this;
  };

  window.addEventListener('load', function() {
    var redmineNotifier = new RedmineNotifier();
    redmineNotifier.initEventListener()
      .displayDefaultSettings()
      .updateLastExecutionTime()
      .readStoredSettings()
      .displaySettings();

    if (redmineNotifier.validateSettings()) {
      redmineNotifier.initFetch();
    }
  });
}());

<|endoftext|>


<commit_before>/**
 * Contentful Management API Client. Contains methods which allow access to
 * any operations that can be performed with a management token.
 * @namespace ContentfulClientAPI
 */

/**
 * Types for meta information found across the different entities in Contentful
 * @namespace Meta
 */

/**
 * System metadata. See Common Resource Attributes for more details.
 * @memberof Meta
 * @typedef Sys
 * @prop {string} type
 * @prop {string} id
 * @prop {Meta.Link} space
 * @prop {string} createdAt
 * @prop {string} updatedAt
 * @prop {number} revision
 */

/**
 * Link to another entity. See Links for more details.
 * @memberof Meta
 * @typedef Link
 * @prop {string} type - type of this entity. Always link.
 * @prop {string} id
 * @prop {string} linkType - type of this link. If defined, either Entry or Asset
 */

/**
 * @memberof ContentfulClientAPI
 * @typedef {Object} ClientAPI
 * @prop {function} getSpace
 * @prop {function} getSpaces
 * @prop {function} createSpace
 * @prop {function} createPersonalAccessToken
 * @prop {function} getCurrentUser
 * @prop {function} getPersonalAccessTokens
 * @prop {function} getPersonalAccessToken
 * @prop {function} getOrganizations
 * @prop {function} rawRequest
 */

import { createRequestConfig } from 'contentful-sdk-core'
import errorHandler from './error-handler'
import entities from './entities'
/**
 * Creates API object with methods to access functionality from Contentful's
 * Management API
 * @private
 * @param {Object} params - API initialization params
 * @prop {Object} http - HTTP client instance
 * @prop {Function} shouldLinksResolve - Link resolver preconfigured with global setting
 * @return {ClientAPI}
 */
export default function createClientApi ({ http }) {
  const {wrapSpace, wrapSpaceCollection} = entities.space
  const {wrapUser} = entities.user
  const {wrapPersonalAccessToken, wrapPersonalAccessTokenCollection} = entities.personalAccessToken
  const {wrapOrganizationCollection} = entities.organization

  /**
   * Gets all spaces
   * @memberof ContentfulClientAPI
   * @return {Promise<Space.SpaceCollection>} Promise for a collection of Spaces
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getSpaces()
   * .then((response) => console.log(response.items))
   * .catch(console.error)
   */
  function getSpaces (query = {}) {
    return http.get('', createRequestConfig({query: query}))
      .then((response) => wrapSpaceCollection(http, response.data), errorHandler)
  }

  /**
   * Gets a space
   * @memberof ContentfulClientAPI
   * @param {string} id - Space ID
   * @return {Promise<Space.Space>} Promise for a Space
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getSpace('<space_id>')
   * .then((space) => console.log(space))
   * .catch(console.error)
   */
  function getSpace (id) {
    return http.get(id)
      .then((response) => wrapSpace(http, response.data), errorHandler)
  }

  /**
   * Creates a space
   * @memberof ContentfulClientAPI
   * @see {Space.Space}
   * @param {object} data - Object representation of the Space to be created
   * @param {string=} organizationId - Organization ID, if the associated token can manage more than one organization.
   * @return {Promise<Space.Space>} Promise for the newly created Space
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.createSpace({
   *   name: 'Name of new space'
   * })
   * .then((space) => console.log(space))
   * .catch(console.error)
   */
  function createSpace (data, organizationId) {
    return http.post('', data, {
      headers: organizationId ? {'X-Contentful-Organization': organizationId} : {}
    })
      .then((response) => wrapSpace(http, response.data), errorHandler)
  }

  /**
   * Gets a collection of Organizations
   * @memberof ClientAPI
   * @return {Promise<OrganizationCollection>} Promise for a collection of Organizations
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getOrganizations()
   * .then(result => console.log(result.items))
   * .catch(console.error)
   */
  function getOrganizations () {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/organizations/')
    return http.get('', {
      baseURL
    })
      .then((response) => wrapOrganizationCollection(http, response.data), errorHandler)
  }

  /**
   * Gets the authenticated user
   * @return {Promise<User>} Promise for a User
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getCurrentUser()
   * .then(user => console.log(user.firstName))
   * .catch(console.error)
   */
  function getCurrentUser () {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/')
    return http.get('', {
      baseURL
    })
      .then((response) => wrapUser(http, response.data), errorHandler)
  }

  /**
   * Creates a personal access token
   * @param {Object} data - personal access token config
   * @return {Promise<User>} Promise for a Token
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.createPersonalAccessToken(
   *  {
   *    "name": "My Token",
   *    "scope": [
   *      "content_management_manage"
   *    ]
   *  }
   * )
   * .then(personalAccessToken => console.log(personalAccessToken.token))
   * .catch(console.error)
   */
  function createPersonalAccessToken (data) {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/access_tokens')
    return http.post('', data, {
      baseURL
    })
      .then((response) => wrapPersonalAccessToken(http, response.data), errorHandler)
  }

  /**
   * Gets a personal access token
   * @param {Object} data - personal access token config
   * @return {Promise<User>} Promise for a Token
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getPersonalAccessToken(tokenId)
   * .then(token => console.log(token.token))
   * .catch(console.error)
   */
  function getPersonalAccessToken (tokenId) {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/access_tokens')
    return http.post(tokenId, {
      baseURL
    })
      .then((response) => wrapPersonalAccessToken(http, response.data), errorHandler)
  }

  /**
   * Gets all personal access tokens
   * @return {Promise<User>} Promise for a Token
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getPersonalAccessTokens()
   * .then(response => console.log(reponse.items))
   * .catch(console.error)
   */
  function getPersonalAccessTokens () {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/access_tokens')
    return http.get('', {
      baseURL
    })
      .then((response) => wrapPersonalAccessTokenCollection(http, response.data), errorHandler)
  }

  /**
   * Make a custom request to the Contentful management API's /spaces endpoint
   * @memberof ContentfulClientAPI
   * @param {Object} opts - axios request options (https://github.com/mzabriskie/axios)
   * @return {Promise<Object>} Promise for the response data
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.rawRequest({
   *   method: 'GET',
   *   url: '/custom/path'
   * })
   * .then((responseData) => console.log(responseData))
   * .catch(console.error)
   */
  function rawRequest (opts) {
    return http(opts).then((response) => response.data, errorHandler)
  }

  return {
    getSpaces: getSpaces,
    getSpace: getSpace,
    createSpace: createSpace,
    getOrganizations: getOrganizations,
    getCurrentUser: getCurrentUser,
    createPersonalAccessToken: createPersonalAccessToken,
    getPersonalAccessToken: getPersonalAccessToken,
    getPersonalAccessTokens: getPersonalAccessTokens,
    rawRequest: rawRequest
  }
}
<commit_msg>docs(client): add correct membership to functions<commit_after>/**
 * Contentful Management API Client. Contains methods which allow access to
 * any operations that can be performed with a management token.
 * @namespace ContentfulClientAPI
 */

/**
 * Types for meta information found across the different entities in Contentful
 * @namespace Meta
 */

/**
 * System metadata. See Common Resource Attributes for more details.
 * @memberof Meta
 * @typedef Sys
 * @prop {string} type
 * @prop {string} id
 * @prop {Meta.Link} space
 * @prop {string} createdAt
 * @prop {string} updatedAt
 * @prop {number} revision
 */

/**
 * Link to another entity. See Links for more details.
 * @memberof Meta
 * @typedef Link
 * @prop {string} type - type of this entity. Always link.
 * @prop {string} id
 * @prop {string} linkType - type of this link. If defined, either Entry or Asset
 */

/**
 * @memberof ContentfulClientAPI
 * @typedef {Object} ClientAPI
 * @prop {function} getSpace
 * @prop {function} getSpaces
 * @prop {function} createSpace
 * @prop {function} createPersonalAccessToken
 * @prop {function} getCurrentUser
 * @prop {function} getPersonalAccessTokens
 * @prop {function} getPersonalAccessToken
 * @prop {function} getOrganizations
 * @prop {function} rawRequest
 */

import { createRequestConfig } from 'contentful-sdk-core'
import errorHandler from './error-handler'
import entities from './entities'
/**
 * Creates API object with methods to access functionality from Contentful's
 * Management API
 * @private
 * @param {Object} params - API initialization params
 * @prop {Object} http - HTTP client instance
 * @prop {Function} shouldLinksResolve - Link resolver preconfigured with global setting
 * @return {ClientAPI}
 */
export default function createClientApi ({ http }) {
  const {wrapSpace, wrapSpaceCollection} = entities.space
  const {wrapUser} = entities.user
  const {wrapPersonalAccessToken, wrapPersonalAccessTokenCollection} = entities.personalAccessToken
  const {wrapOrganizationCollection} = entities.organization

  /**
   * Gets all spaces
   * @memberof ContentfulClientAPI
   * @return {Promise<Space.SpaceCollection>} Promise for a collection of Spaces
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getSpaces()
   * .then((response) => console.log(response.items))
   * .catch(console.error)
   */
  function getSpaces (query = {}) {
    return http.get('', createRequestConfig({query: query}))
      .then((response) => wrapSpaceCollection(http, response.data), errorHandler)
  }

  /**
   * Gets a space
   * @memberof ContentfulClientAPI
   * @param {string} id - Space ID
   * @return {Promise<Space.Space>} Promise for a Space
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getSpace('<space_id>')
   * .then((space) => console.log(space))
   * .catch(console.error)
   */
  function getSpace (id) {
    return http.get(id)
      .then((response) => wrapSpace(http, response.data), errorHandler)
  }

  /**
   * Creates a space
   * @memberof ContentfulClientAPI
   * @see {Space.Space}
   * @param {object} data - Object representation of the Space to be created
   * @param {string=} organizationId - Organization ID, if the associated token can manage more than one organization.
   * @return {Promise<Space.Space>} Promise for the newly created Space
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.createSpace({
   *   name: 'Name of new space'
   * })
   * .then((space) => console.log(space))
   * .catch(console.error)
   */
  function createSpace (data, organizationId) {
    return http.post('', data, {
      headers: organizationId ? {'X-Contentful-Organization': organizationId} : {}
    })
      .then((response) => wrapSpace(http, response.data), errorHandler)
  }

  /**
   * Gets a collection of Organizations
   * @memberof ClientAPI
   * @return {Promise<OrganizationCollection>} Promise for a collection of Organizations
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getOrganizations()
   * .then(result => console.log(result.items))
   * .catch(console.error)
   */
  function getOrganizations () {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/organizations/')
    return http.get('', {
      baseURL
    })
      .then((response) => wrapOrganizationCollection(http, response.data), errorHandler)
  }

  /**
   * Gets the authenticated user
   * @memberof ContentfulClientAPI
   * @return {Promise<User>} Promise for a User
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getCurrentUser()
   * .then(user => console.log(user.firstName))
   * .catch(console.error)
   */
  function getCurrentUser () {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/')
    return http.get('', {
      baseURL
    })
      .then((response) => wrapUser(http, response.data), errorHandler)
  }

  /**
   * Creates a personal access token
   * @memberof ContentfulClientAPI
   * @param {Object} data - personal access token config
   * @return {Promise<User>} Promise for a Token
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.createPersonalAccessToken(
   *  {
   *    "name": "My Token",
   *    "scope": [
   *      "content_management_manage"
   *    ]
   *  }
   * )
   * .then(personalAccessToken => console.log(personalAccessToken.token))
   * .catch(console.error)
   */
  function createPersonalAccessToken (data) {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/access_tokens')
    return http.post('', data, {
      baseURL
    })
      .then((response) => wrapPersonalAccessToken(http, response.data), errorHandler)
  }

  /**
   * Gets a personal access token
   * @memberof ContentfulClientAPI
   * @param {Object} data - personal access token config
   * @return {Promise<User>} Promise for a Token
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getPersonalAccessToken(tokenId)
   * .then(token => console.log(token.token))
   * .catch(console.error)
   */
  function getPersonalAccessToken (tokenId) {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/access_tokens')
    return http.post(tokenId, {
      baseURL
    })
      .then((response) => wrapPersonalAccessToken(http, response.data), errorHandler)
  }

  /**
   * Gets all personal access tokens
   * @memberof ContentfulClientAPI
   * @return {Promise<User>} Promise for a Token
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.getPersonalAccessTokens()
   * .then(response => console.log(reponse.items))
   * .catch(console.error)
   */
  function getPersonalAccessTokens () {
    const baseURL = http.defaults.baseURL.replace('/spaces/', '/users/me/access_tokens')
    return http.get('', {
      baseURL
    })
      .then((response) => wrapPersonalAccessTokenCollection(http, response.data), errorHandler)
  }

  /**
   * Make a custom request to the Contentful management API's /spaces endpoint
   * @memberof ContentfulClientAPI
   * @param {Object} opts - axios request options (https://github.com/mzabriskie/axios)
   * @return {Promise<Object>} Promise for the response data
   * @example
   * const contentful = require('contentful-management')
   *
   * const client = contentful.createClient({
   *   accessToken: '<content_management_api_key>'
   * })
   *
   * client.rawRequest({
   *   method: 'GET',
   *   url: '/custom/path'
   * })
   * .then((responseData) => console.log(responseData))
   * .catch(console.error)
   */
  function rawRequest (opts) {
    return http(opts).then((response) => response.data, errorHandler)
  }

  return {
    getSpaces: getSpaces,
    getSpace: getSpace,
    createSpace: createSpace,
    getOrganizations: getOrganizations,
    getCurrentUser: getCurrentUser,
    createPersonalAccessToken: createPersonalAccessToken,
    getPersonalAccessToken: getPersonalAccessToken,
    getPersonalAccessTokens: getPersonalAccessTokens,
    rawRequest: rawRequest
  }
}
<|endoftext|>


<commit_before>
/*
load forcast of current location on load. Then upon submit/enter return forecast for searched city.
Use Autocomplete API for search results. This will return a Json. list the city names from the Json,
and attach the link associated with each city so it will load the forecast from that city. Populate new
forecast into cards.
*/

"use strict";

angular.module('myapp')
  .controller("WeatherController", function($scope, $http){
    $scope.forecastDay = [];
    $scope.forecastNight = [];
    if (navigator.geolocation) navigator.geolocation.getCurrentPosition(onPositionUpdate);

    function onPositionUpdate(position) {
      var lati = position.coords.latitude;
      var longi = position.coords.longitude;
      var url = 'https://api.wunderground.com/api/4a82154c39d11213/forecast/q/' + lati + ',' + longi + '.json';

      $http.get(url)
        .then(function(info) {
          //console.log(info);
          for(var i = 0; i < 8; i++){
            var item = {
              title: info.data.forecast.txt_forecast.forecastday[i].title,
              icon: info.data.forecast.txt_forecast.forecastday[i].icon_url,
              conditionsI: info.data.forecast.txt_forecast.forecastday[i].fcttext,
              conditionsM: info.data.forecast.txt_forecast.forecastday[i].fcttext_metric,
            };

            if(i%2 === 0){
              $scope.forecastDay.push(item);
            }else{
              $scope.forecastNight.push(item);
            }

            }
            console.log($scope.forecastDay);
            console.log($scope.forecastNight);

        });
      //$scope.search = function(e){
        //e.preventDefault();

      //};

   }

  });
<commit_msg>Update controller1.js<commit_after>
/*
load forcast of current location on load. Then upon submit/enter return forecast for searched city.
Use Autocomplete API for search results. This will return a Json. list the city names from the Json,
and attach the link associated with each city so it will load the forecast from that city. Populate new
forecast into cards.
*/

"use strict";

angular.module('myapp')
  .controller("WeatherController", function($scope, $http){
    //$scope.forecastDay = [];
    //$scope.forecastNight = [];
    $scope.forecast = [];
    if (navigator.geolocation) navigator.geolocation.getCurrentPosition(onPositionUpdate);

    function onPositionUpdate(position) {
      var lati = position.coords.latitude;
      var longi = position.coords.longitude;
      var url = 'https://api.wunderground.com/api/4a82154c39d11213/forecast/q/' + lati + ',' + longi + '.json';

      $http.get(url)
        .then(function(info) {
          //console.log(info);
          for(var i = 0; i < 8; i++){
            var item = {
              title: info.data.forecast.txt_forecast.forecastday[i].title,
              icon: info.data.forecast.txt_forecast.forecastday[i].icon_url,
              conditionsI: info.data.forecast.txt_forecast.forecastday[i].fcttext,
              conditionsM: info.data.forecast.txt_forecast.forecastday[i].fcttext_metric,
            };
            $scope.forecast.push(item);

            //if(i%2 === 0){
            //  $scope.forecastDay.push(item);
            //}else{
            //  $scope.forecastNight.push(item);
            //}

            }
            //console.log($scope.forecastDay);
            //console.log($scope.forecastNight);
            console.log($scope.forecast);

        });
      //$scope.search = function(e){
        //e.preventDefault();

      //};

   }

  });
<|endoftext|>


<commit_before>var dgram = require('dgram')

function Node (id, address, port, generateProposalId) { // :: Int -> Int -> (Int) -> Node
  this.socket = dgram.createSocket('udp4')
  this.id = id
  this.address = address
  this.port = port
  this.acceptors = {} // ID -> [[port, address], last proposal]
  this.proposal = null
  this.value = null
  this.stateLog = {}
  this.roles = []
  this.quorum = null
  this.generateProposalId = generateProposalId
}

function Cluster (nodes) { // :: [Node] -> Cluster
  this.learners = {}
  this.acceptors = {}
  this.proposers = {}
  if (nodes) {
    nodes.ForEach(function (node, _, __) {
      this.addNode(node)
    }, this)
  }

  this.setQuorum = function () {
    if (this.acceptors.length % 2 == 0) {
      this.quorum = this.acceptors.length / 2 + 1
    } else {
      this.quorum = Math.ceil(Object.keys(this.acceptors).length / 2)
    }
    nodes.ForEach(function (node, _, _) {
      node.quorum = this.quorum
    }, this)()
  }

  this.addNode = function (node) {
    if (node.roles.indexOf('Learner') > -1) {
     this.learners[node.id] = [node.port, node.address]
    }
    if (node.roles.indexOf('Acceptor') > -1) {
     this.acceptors[node.id] = [node.port, node.address]
    }
    if (node.roles.indexOf('Proposer') > -1) {
     this.proposers[node.id] = [node.port, node.address]
    }
    for (var id in cluster.acceptors) {
      node.acceptors[id] = [cluster.acceptors[id], null]
    }
  }
}

function initializeProposer (node, cluster) { // :: Node -> Cluster -> a ->
  node.roles.push('Proposer')
  node.proposalId = null
  node.lastId = null
  node.promises = []
  node.nextProposalNum = 1

  node.socket.bind(node.port, node.address)
  node.socket.on("message", function (message, rinfo) {
    message = JSON.parse(message.toString())
    if (message.type == "promise") {
      node.receivePromise(message.id, message.proposalId, message.lastAcceptedId, message.lastValue)
    } else if (message.type == "proposal") {
      node.setProposal(message.proposal, message.proposalId)
    } else if (message.type == "NAK") {
      node.prepare()
    } else if (message.type == "accepted") {
    }
  })

  node.setProposal = function (proposal, proposalId) {
    if ((node.proposal == null) || (proposalId !== node.proposalId)) {
      node.proposal = proposal
      node.proposalId = proposalId
    }
  }

  node.prepare = function () {
    node.promises = []
    node.nextProposalNum += 1
  }

  node.receivePromise = function (from, proposalId, lastAcceptedId, lastValue) { // :: Int -> Int -> Int -> a ->
    if (proposalId != node.proposalId || (node.promises.indexOf(from) < 0)) {
      return
    }

    if (node.acceptors[from] == null) {
      // we don't know this acceptor
      // TODO: query known acceptors
      return
    }

    if (node.promises.indexOf(from) < 0) {
      node.promises.push(from)
    } else { return }

    if (lastAcceptedId > node.lastId) {
      node.lastId = last_acceptedId
      if (lastValue) { node.proposal = lastValue }
    }

    if (node.promises.length == node.quorom) {
      if (node.proposal) {
        acceptReq = new Buffer(JSON.stringify({
          type: "accept",
          proposalId: node.proposalId,
          proposal: node.proposal,
        }))
        for (var acceptor in node.acceptors) {
          node.socket.send(acceptReq, 0, node.acceptors[acceptor][0][0], node.acceptors[acceptor][0][1])
        }
      }
    }
  }

  cluster.addNode(node)
  cluster.setQuorum()
}

function initializeAcceptor (node, cluster) { // :: Node -> Cluster ->
  node.roles.push('Acceptor')
  // Sync stateLog with acceptors in cluster
  node.promisedId = null
  node.acceptedId = null

  node.receivePrepare = function (from, proposalId) {
    if (proposalID == node.promisedId) {
    } else if (proposalId > node.promisedId) {
      node.promisedId = proposalId
      // send prepare
    }
  }

  node.receiveAcceptRequest = function (from, proposalId, proposal) { // :: Int -> Int -> a ->
    if (proposalId == node.promisedId) {
      node.promisedId = proposalId
      node.acceptedId = proposalId
      node.value = proposal
      // alert other nodes that a value is accepted
    }
  }

  node.sendPromise = function () {} // TODO

  cluster.addNode(node)
  cluster.setQuorum()
}

function initializeLearner (node, cluster) { // :: Node -> Cluster ->
  node.roles.push('Learner')
  node.finalValue = null
  node.finalProposalId = null

  node.proposals = {} // proposal ID -> [accept count, retain count, value]

  node.receiveAccept = function (from, proposalId, acceptedValue) { // :: Int -> Int -> a ->
    if (node.finalValue != null) {
      return
    }

    var last = node.acceptors[from][1]
    if (last) {
      if (last > proposalId) { return }
      node.acceptors[from][1] = proposalId

      oldProposal = node.proposals[last]
      oldProposal[1] -= 1
      if (oldProposal[1] == 0) { delete node.proposals[last] }
    }

    if (node.proposals[proposalId] == null) {
      node.proposals[proposalId] = [1, 1, acceptedValue]
    }

    if (node.proposals[proposalId][0] == node.quorum) { // round over
      node.finalValue = acceptedValue
      node.finalProposalId = proposalId
    }
  }
  cluster.addNode(node)
  cluster.setQuorum()
}
<commit_msg>Comments and cleanup.<commit_after>var dgram = require('dgram')

function Node (id, address, port, generateProposalId) { // :: Int -> Int -> (Int) -> Node
  this.socket = dgram.createSocket('udp4')
  this.id = id
  this.address = address
  this.port = port
  this.acceptors = {} // ID -> [[port, address], last proposal]
  this.proposal = null
  this.value = null
  this.stateLog = {}
  this.roles = []
  this.quorum = null
  this.generateProposalId = generateProposalId
}

function Cluster (nodes) { // :: [Node] -> Cluster
  this.learners = {}
  this.acceptors = {}
  this.proposers = {}
  if (nodes) {
    nodes.ForEach(function (node, _, __) {
      this.addNode(node)
    }, this)
  }

  this.setQuorum = function () {
    if (this.acceptors.length % 2 == 0) {
      this.quorum = this.acceptors.length / 2 + 1
    } else {
      this.quorum = Math.ceil(Object.keys(this.acceptors).length / 2)
    }
    nodes.ForEach(function (node, _, _) {
      node.quorum = this.quorum
    }, this)()
  }

  this.addNode = function (node) {
    if (node.roles.indexOf('Learner') > -1) {
     this.learners[node.id] = [node.port, node.address]
    }
    if (node.roles.indexOf('Acceptor') > -1) {
     this.acceptors[node.id] = [node.port, node.address]
    }
    if (node.roles.indexOf('Proposer') > -1) {
     this.proposers[node.id] = [node.port, node.address]
    }
    for (var id in cluster.acceptors) {
      node.acceptors[id] = [cluster.acceptors[id], null]
    }
  }
}

function initializeProposer (node, cluster) { // :: Node -> Cluster -> a ->
  node.roles.push('Proposer')
  node.proposalId = null
  node.lastId = null
  node.promises = []
  node.nextProposalNum = 1

  node.socket.bind(node.port, node.address)
  node.socket.on("message", function (message, rinfo) {
    message = JSON.parse(message.toString())
    if (message.type == "promise") {
      node.receivePromise(message.id, message.proposalId, message.lastAcceptedId, message.lastValue)
    } else if (message.type == "proposal") {
      node.setProposal(message.proposal)
    } else if (message.type == "NAK") {
      node.prepare()
    } else if (message.type == "accepted") {
      node.recieveAccept()
    }
  })

  node.setProposal = function (proposal, proposalId) {
    node.proposal = proposal
    node.proposalId = node.generateProposalId()
  }

  node.propose = function () {
    // TODO: create and send proposal to all acceptors
  }

  node.prepare = function () {
    node.promises = []
    node.nextProposalNum += 1
  }

  node.receivePromise = function (from, proposalId, lastAcceptedId, lastValue) { // :: Int -> Int -> Int -> a ->
    if (proposalId != node.proposalId || (node.promises.indexOf(from) < 0)) {
      return
    }

    if (node.acceptors[from] == null) {
      // we don't know this acceptor
      // TODO: query known acceptors
      return
    }

    if (node.promises.indexOf(from) < 0) {
      node.promises.push(from)
    } else { return } // we have already received a promise. Something is probably wrong.

    if (lastAcceptedId > node.lastId) {
      node.lastId = last_acceptedId
      if (lastValue) { node.proposal = lastValue }
    }

    if (node.promises.length == node.quorom) {
      if (node.proposal) {
        acceptReq = new Buffer(JSON.stringify({
          type: "accept",
          proposalId: node.proposalId,
          proposal: node.proposal,
        }))
        for (var acceptor in node.acceptors) {
          node.socket.send(acceptReq, 0, node.acceptors[acceptor][0][0], node.acceptors[acceptor][0][1])
        }
      }
    }
  }

  node.receiveAccept = function () {} //TODO

  cluster.addNode(node)
  cluster.setQuorum()
}

function initializeAcceptor (node, cluster) { // :: Node -> Cluster ->
  node.roles.push('Acceptor')
  // Sync stateLog with acceptors in cluster
  node.promisedId = null
  node.acceptedId = null

  node.receivePrepare = function (from, proposalId) {
    if (proposalID == node.promisedId) {
    } else if (proposalId > node.promisedId) {
      node.promisedId = proposalId
      // send prepare
    }
  }

  node.receiveAcceptRequest = function (from, proposalId, proposal) { // :: Int -> Int -> a ->
    if (proposalId == node.promisedId) {
      node.promisedId = proposalId
      node.acceptedId = proposalId
      node.value = proposal
      // alert other nodes that a value is accepted
    }
  }

  node.sendPromise = function () {} // TODO

  cluster.addNode(node)
  cluster.setQuorum()
}

function initializeLearner (node, cluster) { // :: Node -> Cluster ->
  node.roles.push('Learner')
  node.finalValue = null
  node.finalProposalId = null

  node.proposals = {} // proposal ID -> [accept count, retain count, value]

  node.receiveAccept = function (from, proposalId, acceptedValue) { // :: Int -> Int -> a ->
    if (node.finalValue != null) {
      return
    }

    var last = node.acceptors[from][1]
    if (last) {
      if (last > proposalId) { return }
      node.acceptors[from][1] = proposalId

      oldProposal = node.proposals[last]
      oldProposal[1] -= 1
      if (oldProposal[1] == 0) { delete node.proposals[last] }
    }

    if (node.proposals[proposalId] == null) {
      node.proposals[proposalId] = [1, 1, acceptedValue]
    }

    if (node.proposals[proposalId][0] == node.quorum) { // round over
      node.finalValue = acceptedValue
      node.finalProposalId = proposalId
    }
  }
  cluster.addNode(node)
  cluster.setQuorum()
}
<|endoftext|>


<commit_before>(function() {
    const electron = require('electron');
    const fs = require('fs')
    const moment = require('moment')
    const app = electron.app;
    const BrowserWindow = electron.BrowserWindow;
    const globalShortcut = electron.globalShortcut;
    const ipc = electron.ipcMain
    const shell = electron.shell
    const { dialog } = require('electron')
    let mainWindow;
    const remote = require('electron').remote;
    const appPath = process.env.NODE_ENV === 'production' ? remote.app.getAppPath() : __dirname;

    const _isProduction = false;

    function createWindow() {
        mainWindow = new BrowserWindow({
            maximizable: true,
            minimizable: true,
            closable: true,
            movable: true,
            title: "ESRG - Estabilidade de Solo Reforçado com Geossintéticos",
            show: true,
            autoHideMenuBar: true,
            titleBarStyle: 'hidden-inset'
        })

        mainWindow.loadURL(`file://${__dirname}/source/index.html`);

        if (!_isProduction) {
            mainWindow.webContents.openDevTools();
        }

        mainWindow.on('closed', function() {
            mainWindow = null;
        })
        mainWindow.maximize()
    }

    app.on('ready', createWindow);

    app.on('window-all-closed', function() {
        if (process.platform !== 'darwin') {
            app.quit();
        }
    })

    app.on('activate', function() {
        if (mainWindow === null) {
            createWindow();
        }
    })

    ipc.on('print-to-pdf', function(event) {
        var d = new Date();
        var timeStamp = moment().format('YYYYMMDD-HHmm');
        const fileName = "relatorio" + timeStamp + '.pdf';
        let pdfPath = appPath + '/dist/relatorio.pdf';

        const win = BrowserWindow.fromWebContents(event.sender)

        win.webContents.printToPDF({
            marginsType: 0,
            printBackground: false,
            printSelectionOnly: false,
            landscape: false
        }, (error, data) => {
            fs.writeFile(pdfPath, data, (error) => {
                var savePath = dialog.showSaveDialog(win, {
                    title: fileName,
                    defaultPath: fileName
                }, function(result) {
                    if (!result) {
                        return;
                    }
                    let readStream = fs.createReadStream(pdfPath);
                    readStream.once('error', (err) => {
                        console.error(err);
                    });
                    readStream.once('end', () => {});
                    readStream.pipe(fs.createWriteStream(result));
                });
            })
        })
    })

})();<commit_msg>Remove console<commit_after>(function() {
    const electron = require('electron');
    const fs = require('fs')
    const moment = require('moment')
    const app = electron.app;
    const BrowserWindow = electron.BrowserWindow;
    const globalShortcut = electron.globalShortcut;
    const ipc = electron.ipcMain
    const shell = electron.shell
    const { dialog } = require('electron')
    let mainWindow;
    const remote = require('electron').remote;
    const appPath = process.env.NODE_ENV === 'production' ? remote.app.getAppPath() : __dirname;

    function createWindow() {
        mainWindow = new BrowserWindow({
            maximizable: true,
            minimizable: true,
            closable: true,
            movable: true,
            title: "ESRG - Estabilidade de Solo Reforçado com Geossintéticos",
            show: true,
            autoHideMenuBar: true,
            titleBarStyle: 'hidden-inset'
        })

        mainWindow.loadURL(`file://${__dirname}/source/index.html`);

        // mainWindow.webContents.openDevTools();

        mainWindow.on('closed', function() {
            mainWindow = null;
        })
        mainWindow.maximize()
    }

    app.on('ready', createWindow);

    app.on('window-all-closed', function() {
        if (process.platform !== 'darwin') {
            app.quit();
        }
    })

    app.on('activate', function() {
        if (mainWindow === null) {
            createWindow();
        }
    })

    ipc.on('print-to-pdf', function(event) {
        var d = new Date();
        var timeStamp = moment().format('YYYYMMDD-HHmm');
        const fileName = "relatorio" + timeStamp + '.pdf';
        let pdfPath = appPath + '/dist/relatorio.pdf';

        const win = BrowserWindow.fromWebContents(event.sender)

        win.webContents.printToPDF({
            marginsType: 0,
            printBackground: false,
            printSelectionOnly: false,
            landscape: false
        }, (error, data) => {
            fs.writeFile(pdfPath, data, (error) => {
                var savePath = dialog.showSaveDialog(win, {
                    title: fileName,
                    defaultPath: fileName
                }, function(result) {
                    if (!result) {
                        return;
                    }
                    let readStream = fs.createReadStream(pdfPath);
                    readStream.once('error', (err) => {
                        console.error(err);
                    });
                    readStream.once('end', () => {});
                    readStream.pipe(fs.createWriteStream(result));
                });
            })
        })
    })

})();<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. 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.
 */

CLASS({
  package: 'foam.ui',
  name: 'MultiChoiceView',

  extends: 'foam.ui.View',

  documentation: 'A View for selecting a set of keys from an array of choices or from a DAO.',

  properties: [
    {
      name: 'prop',
      hidden: true
    },
    {
      name:  'choices',
      documentation: 'Array of [value, text] choices.  Simple String values will be upgraded to [value, value]. Can also be a map, in which case this becomes a [key, value] map in enumeration order.',
      factory: function() { return []; },
      preSet: function(_, a) {
        // If a is a map, instead of an array, we make [key, value] pairs.
        if ( typeof a === 'object' && ! Array.isArray(a) ) {
          var out = [];
          for ( var key in a ) {
            if ( a.hasOwnProperty(key) )
              out.push([key, a[key]]);
          }
          return out;
        }

        a = a.clone();
        // Upgrade single values to [value, value]
        for ( var i = 0 ; i < a.length ; i++ )
          if ( ! Array.isArray(a[i]) )
            a[i] = [a[i], a[i]];
        return a;
      },

      postSet: function(_, choices) {
        var set = this.data;
        var newSet = {};

        for ( var i = 0 ; i < choices.length ; i++ ) {
          var key = choices[i][0];

          if ( set[key] ) newSet[key] = set[key];
        }

        if ( Object.keys(set).toString() !== Object.keys(newSet).toString() ) this.data = newSet;

        this.updateHTML();
      }
    },
    {
      type: 'Function',
      name: 'objToChoice',
      help: 'A Function which adapts an object from the DAO to a [key, value, ...] choice.'
    },
    {
      model_: 'foam.core.types.DAOProperty',
      name: 'dao',
      onDAOUpdate: 'onDAOUpdate'
    },
    {
      name: 'name',
      type: 'String',
      defaultValue: 'field'
    },
    {
      name: 'helpText',
      type: 'String',
      defaultValue: undefined
    },
    {
      name: 'size',
      type: 'Int',
      defaultValue: 1
    }
  ],

  listeners: [
    {
      name: 'onValueChange',
      code: function(select) {
        var set = {};
        for ( var i = 0 ; i < this.choices.length ; i++ ) {
          if ( this.getTarget(select)[i].selected ) set[this.choices[i][0]] = true;
        }
        this.data = set;
      }
    },
    {
      name: 'onDAOUpdate',
      isMerged: 100,
      code: function() {
        if ( ! this.dao ) return;
        this.dao.select(MAP(this.objToChoice))(function(map) {
          // console.log('***** Update Choices ', map.arg2, this.choices);
          this.choices = map.arg2;
        }.bind(this));
      }
    }
  ],

  templates: [
    function CSS() {/*
      .multi-choice-view {
        overflow: auto;
        margin-right: 6px;
      }
    */},
    function toHTML() {/*
<select class="multi-choice-view" id="%%id" name="%%name" size="%%size" multiple><% this.toInnerHTML(out); %></select>*/},
    function toInnerHTML() {/*
<% if ( this.helpText ) { %>
<option disabled="disabled"><%= escapeHTML(this.helpText) %></option>
<% } %>
<% this.choices.forEach(function(choice) {
  var id = self.nextID();
  self.data$.addListener(function() { if ( ! self.X.$(id) ) return; self.X.$(id).selected = self.data[choice[0]]; });
 %>
 <option id="<%= id %>" <% if ( self.data[choice[0]] ) { %> selected="selected"<% } %>><%= escapeHTML(choice[1].toString()) %></option>
<% }); %>
*/}
  ],

  methods: [
    function initHTML() {
      this.SUPER();
      this.onDAOUpdate();
      this.$.addEventListener('change', this.onValueChange);
    },
    function shouldDestroy(old) { return false; },
    function getTarget(e) {
      var t = e.target || e.srcElement;
      if ( t.nodeType == 3 ) t = t.parentNode; // Opera fix
      return t;
    }
  ]
});
<commit_msg>Make the size property of the MultiChoiceView respected if the view has already been rendered.<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. 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.
 */

CLASS({
  package: 'foam.ui',
  name: 'MultiChoiceView',

  extends: 'foam.ui.View',

  documentation: 'A View for selecting a set of keys from an array of choices or from a DAO.',

  properties: [
    {
      name: 'prop',
      hidden: true
    },
    {
      name:  'choices',
      documentation: 'Array of [value, text] choices.  Simple String values will be upgraded to [value, value]. Can also be a map, in which case this becomes a [key, value] map in enumeration order.',
      factory: function() { return []; },
      preSet: function(_, a) {
        // If a is a map, instead of an array, we make [key, value] pairs.
        if ( typeof a === 'object' && ! Array.isArray(a) ) {
          var out = [];
          for ( var key in a ) {
            if ( a.hasOwnProperty(key) )
              out.push([key, a[key]]);
          }
          return out;
        }

        a = a.clone();
        // Upgrade single values to [value, value]
        for ( var i = 0 ; i < a.length ; i++ )
          if ( ! Array.isArray(a[i]) )
            a[i] = [a[i], a[i]];
        return a;
      },

      postSet: function(_, choices) {
        var set = this.data;
        var newSet = {};

        for ( var i = 0 ; i < choices.length ; i++ ) {
          var key = choices[i][0];

          if ( set[key] ) newSet[key] = set[key];
        }

        if ( Object.keys(set).toString() !== Object.keys(newSet).toString() ) this.data = newSet;

        this.updateHTML();
      }
    },
    {
      type: 'Function',
      name: 'objToChoice',
      help: 'A Function which adapts an object from the DAO to a [key, value, ...] choice.'
    },
    {
      model_: 'foam.core.types.DAOProperty',
      name: 'dao',
      onDAOUpdate: 'onDAOUpdate'
    },
    {
      name: 'name',
      type: 'String',
      defaultValue: 'field'
    },
    {
      name: 'helpText',
      type: 'String',
      defaultValue: undefined
    },
    {
      name: 'size',
      type: 'Int',
      defaultValue: 1,
      postSet: function(_, n) { if (this.$) this.$.size = n; },
    }
  ],

  listeners: [
    {
      name: 'onValueChange',
      code: function(select) {
        var set = {};
        for ( var i = 0 ; i < this.choices.length ; i++ ) {
          if ( this.getTarget(select)[i].selected ) set[this.choices[i][0]] = true;
        }
        this.data = set;
      }
    },
    {
      name: 'onDAOUpdate',
      isMerged: 100,
      code: function() {
        if ( ! this.dao ) return;
        this.dao.select(MAP(this.objToChoice))(function(map) {
          // console.log('***** Update Choices ', map.arg2, this.choices);
          this.choices = map.arg2;
        }.bind(this));
      }
    }
  ],

  templates: [
    function CSS() {/*
      .multi-choice-view {
        overflow: auto;
        margin-right: 6px;
      }
    */},
    function toHTML() {/*
<select class="multi-choice-view" id="%%id" name="%%name" size="%%size" multiple><% this.toInnerHTML(out); %></select>*/},
    function toInnerHTML() {/*
<% if ( this.helpText ) { %>
<option disabled="disabled"><%= escapeHTML(this.helpText) %></option>
<% } %>
<% this.choices.forEach(function(choice) {
  var id = self.nextID();
  self.data$.addListener(function() { if ( ! self.X.$(id) ) return; self.X.$(id).selected = self.data[choice[0]]; });
 %>
 <option id="<%= id %>" <% if ( self.data[choice[0]] ) { %> selected="selected"<% } %>><%= escapeHTML(choice[1].toString()) %></option>
<% }); %>
*/}
  ],

  methods: [
    function initHTML() {
      this.SUPER();
      this.onDAOUpdate();
      this.$.addEventListener('change', this.onValueChange);
    },
    function shouldDestroy(old) { return false; },
    function getTarget(e) {
      var t = e.target || e.srcElement;
      if ( t.nodeType == 3 ) t = t.parentNode; // Opera fix
      return t;
    }
  ]
});
<|endoftext|>


<commit_before>(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global.DeepDiff = factory());
}(this, (function () { 'use strict';

var $scope;
var conflict;
var conflictResolution = [];
if (typeof global === 'object' && global) {
  $scope = global;
} else if (typeof window !== 'undefined') {
  $scope = window;
} else {
  $scope = {};
}
conflict = $scope.DeepDiff;
if (conflict) {
  conflictResolution.push(
    function() {
      if ('undefined' !== typeof conflict && $scope.DeepDiff === accumulateDiff) {
        $scope.DeepDiff = conflict;
        conflict = undefined;
      }
    });
}

// nodejs compatible on server side and in the browser.
function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
}

function Diff(kind, path) {
  Object.defineProperty(this, 'kind', {
    value: kind,
    enumerable: true
  });
  if (path && path.length) {
    Object.defineProperty(this, 'path', {
      value: path,
      enumerable: true
    });
  }
}

function DiffEdit(path, origin, value) {
  DiffEdit.super_.call(this, 'E', path);
  Object.defineProperty(this, 'lhs', {
    value: origin,
    enumerable: true
  });
  Object.defineProperty(this, 'rhs', {
    value: value,
    enumerable: true
  });
}
inherits(DiffEdit, Diff);

function DiffNew(path, value) {
  DiffNew.super_.call(this, 'N', path);
  Object.defineProperty(this, 'rhs', {
    value: value,
    enumerable: true
  });
}
inherits(DiffNew, Diff);

function DiffDeleted(path, value) {
  DiffDeleted.super_.call(this, 'D', path);
  Object.defineProperty(this, 'lhs', {
    value: value,
    enumerable: true
  });
}
inherits(DiffDeleted, Diff);

function DiffArray(path, index, item) {
  DiffArray.super_.call(this, 'A', path);
  Object.defineProperty(this, 'index', {
    value: index,
    enumerable: true
  });
  Object.defineProperty(this, 'item', {
    value: item,
    enumerable: true
  });
}
inherits(DiffArray, Diff);

function arrayRemove(arr, from, to) {
  var rest = arr.slice((to || from) + 1 || arr.length);
  arr.length = from < 0 ? arr.length + from : from;
  arr.push.apply(arr, rest);
  return arr;
}

function realTypeOf(subject) {
  var type = typeof subject;
  if (type !== 'object') {
    return type;
  }

  if (subject === Math) {
    return 'math';
  } else if (subject === null) {
    return 'null';
  } else if (Array.isArray(subject)) {
    return 'array';
  } else if (Object.prototype.toString.call(subject) === '[object Date]') {
    return 'date';
  } else if (typeof subject.toString === 'function' && /^\/.*\//.test(subject.toString())) {
    return 'regexp';
  }
  return 'object';
}

function deepDiff(lhs, rhs, changes, prefilter, path, key, stack, orderIndependent) {
  path = path || [];
  var currentPath = path.slice(0);
  if (typeof key !== 'undefined') {
    if (prefilter) {
      if (typeof(prefilter) === 'function' && prefilter(currentPath, key)) { return; }
      else if (typeof(prefilter) === 'object') {
        if (prefilter.prefilter && prefilter.prefilter(currentPath, key)) { return; }
        if (prefilter.normalize) {
          var alt = prefilter.normalize(currentPath, key, lhs, rhs);
          if (alt) {
            lhs = alt[0];
            rhs = alt[1];
          }
        }
      }
    }
    currentPath.push(key);
  }

  // Use string comparison for regexes
  if (realTypeOf(lhs) === 'regexp' && realTypeOf(rhs) === 'regexp') {
    lhs = lhs.toString();
    rhs = rhs.toString();
  }

  var ltype = typeof lhs;
  var rtype = typeof rhs;
  var ldefined = ltype !== 'undefined' || (stack && stack[stack.length - 1].lhs && stack[stack.length - 1].lhs.hasOwnProperty(key));
  var rdefined = rtype !== 'undefined' || (stack && stack[stack.length - 1].rhs && stack[stack.length - 1].rhs.hasOwnProperty(key));

  if (!ldefined && rdefined) {
    changes(new DiffNew(currentPath, rhs));
  } else if (!rdefined && ldefined) {
    changes(new DiffDeleted(currentPath, lhs));
  } else if (realTypeOf(lhs) !== realTypeOf(rhs)) {
    changes(new DiffEdit(currentPath, lhs, rhs));
  } else if (realTypeOf(lhs) === 'date' && (lhs - rhs) !== 0) {
    changes(new DiffEdit(currentPath, lhs, rhs));
  } else if (ltype === 'object' && lhs !== null && rhs !== null) {
    if (!stack.filter(function(x) {
        return x.lhs === lhs; }).length) {
      stack.push({ lhs: lhs, rhs: rhs });
      if (Array.isArray(lhs)) {
        // If order doesn't matter, we need to sort our arrays
        if (orderIndependent) {
          lhs.sort(function(a, b) {
            return getOrderIndependentHash(a) - getOrderIndependentHash(b);
          });

          rhs.sort(function(a, b) {
            return getOrderIndependentHash(a) - getOrderIndependentHash(b);
          });
        }
        var i, len = lhs.length;
        for (i = 0; i < lhs.length; i++) {
          if (i >= rhs.length) {
            changes(new DiffArray(currentPath, i, new DiffDeleted(undefined, lhs[i])));
          } else {
            deepDiff(lhs[i], rhs[i], changes, prefilter, currentPath, i, stack, orderIndependent);
          }
        }
        while (i < rhs.length) {
          changes(new DiffArray(currentPath, i, new DiffNew(undefined, rhs[i++])));
        }
      } else {
        var akeys = Object.keys(lhs);
        var pkeys = Object.keys(rhs);
        akeys.forEach(function(k, i) {
          var other = pkeys.indexOf(k);
          if (other >= 0) {
            deepDiff(lhs[k], rhs[k], changes, prefilter, currentPath, k, stack, orderIndependent);
            pkeys = arrayRemove(pkeys, other);
          } else {
            deepDiff(lhs[k], undefined, changes, prefilter, currentPath, k, stack, orderIndependent);
          }
        });
        pkeys.forEach(function(k) {
          deepDiff(undefined, rhs[k], changes, prefilter, currentPath, k, stack, orderIndependent);
        });
      }
      stack.length = stack.length - 1;
    } else if (lhs !== rhs) {
      // lhs is contains a cycle at this element and it differs from rhs
      changes(new DiffEdit(currentPath, lhs, rhs));
    }
  } else if (lhs !== rhs) {
    if (!(ltype === 'number' && isNaN(lhs) && isNaN(rhs))) {
      changes(new DiffEdit(currentPath, lhs, rhs));
    }
  }
}

function orderIndependentDeepDiff(lhs, rhs, changes, prefilter, path, key, stack) {
  return deepDiff(lhs, rhs, changes, prefilter, path, key, stack, true);
}

function accumulateDiff(lhs, rhs, prefilter, accum) {
  accum = accum || [];
  deepDiff(lhs, rhs,
    function(diff) {
      if (diff) {
        accum.push(diff);
      }
    },
    prefilter);
  return (accum.length) ? accum : undefined;
}

function accumulateOrderIndependentDiff(lhs, rhs, prefilter, accum) {
  accum = accum || [];
  deepDiff(lhs, rhs,
    function(diff) {
      if (diff) {
        accum.push(diff);
      }
    },
    prefilter, null, null, null, true);
  return (accum.length) ? accum : undefined;
}

// Gets a hash of the given object in an array order-independent fashion
// also object key order independent (easier since they can be alphabetized)
function getOrderIndependentHash(object) {
  var accum = 0;
  var type = realTypeOf(object);

  if (type === 'array') {
    object.forEach(function(item) {
      // Addition is commutative so this is order indep
      accum += getOrderIndependentHash(item);
    });

    var arrayString = '[type: array, hash: ' + accum + ']';
    return accum + hashThisString(arrayString);
  }

  if (type === 'object') {
    for (var key in object) {
      if (object.hasOwnProperty(key)) {
        var keyValueString = '[ type: object, key: ' + key + ', value hash: ' + getOrderIndependentHash(object[key]) + ']';
        accum += hashThisString(keyValueString);
      }
    }

    return accum;
  }

  // Non object, non array...should be good?
  var stringToHash = '[ type: ' + type + ' ; value: ' + object + ']';
  return accum + hashThisString(stringToHash);
}

// http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
function hashThisString(string) {
  var hash = 0;
  if (string.length === 0) return hash;
  for (var i = 0; i < string.length; i++) {
    var char = string.charCodeAt(i);
    hash = ((hash<<5)-hash)+char;
    hash = hash & hash; // Convert to 32bit integer
  }

  return hash;
}

function applyArrayChange(arr, index, change) {
  if (change.path && change.path.length) {
    var it = arr[index],
        i, u = change.path.length - 1;
    for (i = 0; i < u; i++) {
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        applyArrayChange(it[change.path[i]], change.index, change.item);
        break;
      case 'D':
        delete it[change.path[i]];
        break;
      case 'E':
      case 'N':
        it[change.path[i]] = change.rhs;
        break;
    }
  } else {
    switch (change.kind) {
      case 'A':
        applyArrayChange(arr[index], change.index, change.item);
        break;
      case 'D':
        arr = arrayRemove(arr, index);
        break;
      case 'E':
      case 'N':
        arr[index] = change.rhs;
        break;
    }
  }
  return arr;
}

function applyChange(target, source, change) {
  if (target && source && change && change.kind) {
    var it = target,
        i = -1,
        last = change.path ? change.path.length - 1 : 0;
    while (++i < last) {
      if (typeof it[change.path[i]] === 'undefined') {
        it[change.path[i]] = (typeof change.path[i] === 'number') ? [] : {};
      }
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        applyArrayChange(change.path ? it[change.path[i]] : it, change.index, change.item);
        break;
      case 'D':
        delete it[change.path[i]];
        break;
      case 'E':
      case 'N':
        it[change.path[i]] = change.rhs;
        break;
    }
  }
}

function revertArrayChange(arr, index, change) {
  if (change.path && change.path.length) {
    // the structure of the object at the index has changed...
    var it = arr[index],
        i, u = change.path.length - 1;
    for (i = 0; i < u; i++) {
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        revertArrayChange(it[change.path[i]], change.index, change.item);
        break;
      case 'D':
        it[change.path[i]] = change.lhs;
        break;
      case 'E':
        it[change.path[i]] = change.lhs;
        break;
      case 'N':
        delete it[change.path[i]];
        break;
    }
  } else {
    // the array item is different...
    switch (change.kind) {
      case 'A':
        revertArrayChange(arr[index], change.index, change.item);
        break;
      case 'D':
        arr[index] = change.lhs;
        break;
      case 'E':
        arr[index] = change.lhs;
        break;
      case 'N':
        arr = arrayRemove(arr, index);
        break;
    }
  }
  return arr;
}

function revertChange(target, source, change) {
  if (target && source && change && change.kind) {
    var it = target,
        i, u;
    u = change.path.length - 1;
    for (i = 0; i < u; i++) {
      if (typeof it[change.path[i]] === 'undefined') {
        it[change.path[i]] = {};
      }
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        // Array was modified...
        // it will be an array...
        revertArrayChange(it[change.path[i]], change.index, change.item);
        break;
      case 'D':
        // Item was deleted...
        it[change.path[i]] = change.lhs;
        break;
      case 'E':
        // Item was edited...
        it[change.path[i]] = change.lhs;
        break;
      case 'N':
        // Item is new...
        delete it[change.path[i]];
        break;
    }
  }
}

function applyDiff(target, source, filter) {
  if (target && source) {
    var onChange = function(change) {
      if (!filter || filter(target, source, change)) {
        applyChange(target, source, change);
      }
    };
    deepDiff(target, source, onChange);
  }
}

Object.defineProperties(accumulateDiff, {

  diff: {
    value: accumulateDiff,
    enumerable: true
  },
  orderIndependentDiff: {
    value: accumulateOrderIndependentDiff,
    enumerable: true
  },
  observableDiff: {
    value: deepDiff,
    enumerable: true
  },
  orderIndependentObservableDiff: {
    value:orderIndependentDeepDiff,
    enumerable: true
  },
  orderIndepHash: {
    value:getOrderIndependentHash,
    enumerable: true
  },
  applyDiff: {
    value: applyDiff,
    enumerable: true
  },
  applyChange: {
    value: applyChange,
    enumerable: true
  },
  revertChange: {
    value: revertChange,
    enumerable: true
  },
  isConflict: {
    value: function() {
      return 'undefined' !== typeof conflict;
    },
    enumerable: true
  },
  noConflict: {
    value: function() {
      if (conflictResolution) {
        conflictResolution.forEach(function(it) {
          it();
        });
        conflictResolution = null;
      }
      return accumulateDiff;
    },
    enumerable: true
  }
});

return accumulateDiff;

})));
<commit_msg>Fix conflict<commit_after>(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global.DeepDiff = factory());
}(this, (function () { 'use strict';

var $scope;
var conflict;
var conflictResolution = [];
if (typeof global === 'object' && global) {
  $scope = global;
} else if (typeof window !== 'undefined') {
  $scope = window;
} else {
  $scope = {};
}
conflict = $scope.DeepDiff;
if (conflict) {
  conflictResolution.push(
    function() {
      if ('undefined' !== typeof conflict && $scope.DeepDiff === accumulateDiff) {
        $scope.DeepDiff = conflict;
        conflict = undefined;
      }
    });
}

// nodejs compatible on server side and in the browser.
function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
}

function Diff(kind, path) {
  Object.defineProperty(this, 'kind', {
    value: kind,
    enumerable: true
  });
  if (path && path.length) {
    Object.defineProperty(this, 'path', {
      value: path,
      enumerable: true
    });
  }
}

function DiffEdit(path, origin, value) {
  DiffEdit.super_.call(this, 'E', path);
  Object.defineProperty(this, 'lhs', {
    value: origin,
    enumerable: true
  });
  Object.defineProperty(this, 'rhs', {
    value: value,
    enumerable: true
  });
}
inherits(DiffEdit, Diff);

function DiffNew(path, value) {
  DiffNew.super_.call(this, 'N', path);
  Object.defineProperty(this, 'rhs', {
    value: value,
    enumerable: true
  });
}
inherits(DiffNew, Diff);

function DiffDeleted(path, value) {
  DiffDeleted.super_.call(this, 'D', path);
  Object.defineProperty(this, 'lhs', {
    value: value,
    enumerable: true
  });
}
inherits(DiffDeleted, Diff);

function DiffArray(path, index, item) {
  DiffArray.super_.call(this, 'A', path);
  Object.defineProperty(this, 'index', {
    value: index,
    enumerable: true
  });
  Object.defineProperty(this, 'item', {
    value: item,
    enumerable: true
  });
}
inherits(DiffArray, Diff);

function arrayRemove(arr, from, to) {
  var rest = arr.slice((to || from) + 1 || arr.length);
  arr.length = from < 0 ? arr.length + from : from;
  arr.push.apply(arr, rest);
  return arr;
}

function realTypeOf(subject) {
  var type = typeof subject;
  if (type !== 'object') {
    return type;
  }

  if (subject === Math) {
    return 'math';
  } else if (subject === null) {
    return 'null';
  } else if (Array.isArray(subject)) {
    return 'array';
  } else if (Object.prototype.toString.call(subject) === '[object Date]') {
    return 'date';
  } else if (typeof subject.toString === 'function' && /^\/.*\//.test(subject.toString())) {
    return 'regexp';
  }
  return 'object';
}

function deepDiff(lhs, rhs, changes, prefilter, path, key, stack, orderIndependent) {
  path = path || [];
  var currentPath = path.slice(0);
  if (typeof key !== 'undefined') {
    if (prefilter) {
      if (typeof(prefilter) === 'function' && prefilter(currentPath, key)) { return; }
      else if (typeof(prefilter) === 'object') {
        if (prefilter.prefilter && prefilter.prefilter(currentPath, key)) { return; }
        if (prefilter.normalize) {
          var alt = prefilter.normalize(currentPath, key, lhs, rhs);
          if (alt) {
            lhs = alt[0];
            rhs = alt[1];
          }
        }
      }
    }
    currentPath.push(key);
  }

  // Use string comparison for regexes
  if (realTypeOf(lhs) === 'regexp' && realTypeOf(rhs) === 'regexp') {
    lhs = lhs.toString();
    rhs = rhs.toString();
  }

  var ltype = typeof lhs;
  var rtype = typeof rhs;

  var ldefined = ltype !== 'undefined' || (stack && stack[stack.length - 1].lhs && stack[stack.length - 1].lhs.hasOwnProperty(key));
  var rdefined = rtype !== 'undefined' || (stack && stack[stack.length - 1].rhs && stack[stack.length - 1].rhs.hasOwnProperty(key));

  if (!ldefined && rdefined) {
    changes(new DiffNew(currentPath, rhs));
  } else if (!rdefined && ldefined) {
    changes(new DiffDeleted(currentPath, lhs));
  } else if (realTypeOf(lhs) !== realTypeOf(rhs)) {
    changes(new DiffEdit(currentPath, lhs, rhs));
  } else if (realTypeOf(lhs) === 'date' && (lhs - rhs) !== 0) {
    changes(new DiffEdit(currentPath, lhs, rhs));
  } else if (ltype === 'object' && lhs !== null && rhs !== null) {
    if (!stack.filter(function(x) {
        return x.lhs === lhs; }).length) {
      stack.push({ lhs: lhs, rhs: rhs });
      if (Array.isArray(lhs)) {
        // If order doesn't matter, we need to sort our arrays
        if (orderIndependent) {
          lhs.sort(function(a, b) {
            return getOrderIndependentHash(a) - getOrderIndependentHash(b);
          });

          rhs.sort(function(a, b) {
            return getOrderIndependentHash(a) - getOrderIndependentHash(b);
          });
        }
        var i, len = lhs.length;
        for (i = 0; i < lhs.length; i++) {
          if (i >= rhs.length) {
            changes(new DiffArray(currentPath, i, new DiffDeleted(undefined, lhs[i])));
          } else {
            deepDiff(lhs[i], rhs[i], changes, prefilter, currentPath, i, stack, orderIndependent);
          }
        }
        while (i < rhs.length) {
          changes(new DiffArray(currentPath, i, new DiffNew(undefined, rhs[i++])));
        }
      } else {
        var akeys = Object.keys(lhs);
        var pkeys = Object.keys(rhs);
        akeys.forEach(function(k, i) {
          var other = pkeys.indexOf(k);
          if (other >= 0) {
            deepDiff(lhs[k], rhs[k], changes, prefilter, currentPath, k, stack, orderIndependent);
            pkeys = arrayRemove(pkeys, other);
          } else {
            deepDiff(lhs[k], undefined, changes, prefilter, currentPath, k, stack, orderIndependent);
          }
        });
        pkeys.forEach(function(k) {
          deepDiff(undefined, rhs[k], changes, prefilter, currentPath, k, stack, orderIndependent);
        });
      }
      stack.length = stack.length - 1;
    } else if (lhs !== rhs) {
      // lhs is contains a cycle at this element and it differs from rhs
      changes(new DiffEdit(currentPath, lhs, rhs));
    }
  } else if (lhs !== rhs) {
    if (!(ltype === 'number' && isNaN(lhs) && isNaN(rhs))) {
      changes(new DiffEdit(currentPath, lhs, rhs));
    }
  }
}

function orderIndependentDeepDiff(lhs, rhs, changes, prefilter, path, key, stack) {
  return deepDiff(lhs, rhs, changes, prefilter, path, key, stack, true);
}

function accumulateDiff(lhs, rhs, prefilter, accum) {
  accum = accum || [];
  deepDiff(lhs, rhs,
    function(diff) {
      if (diff) {
        accum.push(diff);
      }
    },
    prefilter);
  return (accum.length) ? accum : undefined;
}

function accumulateOrderIndependentDiff(lhs, rhs, prefilter, accum) {
  accum = accum || [];
  deepDiff(lhs, rhs,
    function(diff) {
      if (diff) {
        accum.push(diff);
      }
    },
    prefilter, null, null, null, true);
  return (accum.length) ? accum : undefined;
}

// Gets a hash of the given object in an array order-independent fashion
// also object key order independent (easier since they can be alphabetized)
function getOrderIndependentHash(object) {
  var accum = 0;
  var type = realTypeOf(object);

  if (type === 'array') {
    object.forEach(function(item) {
      // Addition is commutative so this is order indep
      accum += getOrderIndependentHash(item);
    });

    var arrayString = '[type: array, hash: ' + accum + ']';
    return accum + hashThisString(arrayString);
  }

  if (type === 'object') {
    for (var key in object) {
      if (object.hasOwnProperty(key)) {
        var keyValueString = '[ type: object, key: ' + key + ', value hash: ' + getOrderIndependentHash(object[key]) + ']';
        accum += hashThisString(keyValueString);
      }
    }

    return accum;
  }

  // Non object, non array...should be good?
  var stringToHash = '[ type: ' + type + ' ; value: ' + object + ']';
  return accum + hashThisString(stringToHash);
}

// http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
function hashThisString(string) {
  var hash = 0;
  if (string.length === 0) return hash;
  for (var i = 0; i < string.length; i++) {
    var char = string.charCodeAt(i);
    hash = ((hash<<5)-hash)+char;
    hash = hash & hash; // Convert to 32bit integer
  }

  return hash;
}

function applyArrayChange(arr, index, change) {
  if (change.path && change.path.length) {
    var it = arr[index],
        i, u = change.path.length - 1;
    for (i = 0; i < u; i++) {
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        applyArrayChange(it[change.path[i]], change.index, change.item);
        break;
      case 'D':
        delete it[change.path[i]];
        break;
      case 'E':
      case 'N':
        it[change.path[i]] = change.rhs;
        break;
    }
  } else {
    switch (change.kind) {
      case 'A':
        applyArrayChange(arr[index], change.index, change.item);
        break;
      case 'D':
        arr = arrayRemove(arr, index);
        break;
      case 'E':
      case 'N':
        arr[index] = change.rhs;
        break;
    }
  }
  return arr;
}

function applyChange(target, source, change) {
  if (target && source && change && change.kind) {
    var it = target,
        i = -1,
        last = change.path ? change.path.length - 1 : 0;
    while (++i < last) {
      if (typeof it[change.path[i]] === 'undefined') {
        it[change.path[i]] = (typeof change.path[i] === 'number') ? [] : {};
      }
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        applyArrayChange(change.path ? it[change.path[i]] : it, change.index, change.item);
        break;
      case 'D':
        delete it[change.path[i]];
        break;
      case 'E':
      case 'N':
        it[change.path[i]] = change.rhs;
        break;
    }
  }
}

function revertArrayChange(arr, index, change) {
  if (change.path && change.path.length) {
    // the structure of the object at the index has changed...
    var it = arr[index],
        i, u = change.path.length - 1;
    for (i = 0; i < u; i++) {
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        revertArrayChange(it[change.path[i]], change.index, change.item);
        break;
      case 'D':
        it[change.path[i]] = change.lhs;
        break;
      case 'E':
        it[change.path[i]] = change.lhs;
        break;
      case 'N':
        delete it[change.path[i]];
        break;
    }
  } else {
    // the array item is different...
    switch (change.kind) {
      case 'A':
        revertArrayChange(arr[index], change.index, change.item);
        break;
      case 'D':
        arr[index] = change.lhs;
        break;
      case 'E':
        arr[index] = change.lhs;
        break;
      case 'N':
        arr = arrayRemove(arr, index);
        break;
    }
  }
  return arr;
}

function revertChange(target, source, change) {
  if (target && source && change && change.kind) {
    var it = target,
        i, u;
    u = change.path.length - 1;
    for (i = 0; i < u; i++) {
      if (typeof it[change.path[i]] === 'undefined') {
        it[change.path[i]] = {};
      }
      it = it[change.path[i]];
    }
    switch (change.kind) {
      case 'A':
        // Array was modified...
        // it will be an array...
        revertArrayChange(it[change.path[i]], change.index, change.item);
        break;
      case 'D':
        // Item was deleted...
        it[change.path[i]] = change.lhs;
        break;
      case 'E':
        // Item was edited...
        it[change.path[i]] = change.lhs;
        break;
      case 'N':
        // Item is new...
        delete it[change.path[i]];
        break;
    }
  }
}

function applyDiff(target, source, filter) {
  if (target && source) {
    var onChange = function(change) {
      if (!filter || filter(target, source, change)) {
        applyChange(target, source, change);
      }
    };
    deepDiff(target, source, onChange);
  }
}

Object.defineProperties(accumulateDiff, {

  diff: {
    value: accumulateDiff,
    enumerable: true
  },
  orderIndependentDiff: {
    value: accumulateOrderIndependentDiff,
    enumerable: true
  },
  observableDiff: {
    value: deepDiff,
    enumerable: true
  },
  orderIndependentObservableDiff: {
    value:orderIndependentDeepDiff,
    enumerable: true
  },
  orderIndepHash: {
    value:getOrderIndependentHash,
    enumerable: true
  },
  applyDiff: {
    value: applyDiff,
    enumerable: true
  },
  applyChange: {
    value: applyChange,
    enumerable: true
  },
  revertChange: {
    value: revertChange,
    enumerable: true
  },
  isConflict: {
    value: function() {
      return 'undefined' !== typeof conflict;
    },
    enumerable: true
  },
  noConflict: {
    value: function() {
      if (conflictResolution) {
        conflictResolution.forEach(function(it) {
          it();
        });
        conflictResolution = null;
      }
      return accumulateDiff;
    },
    enumerable: true
  }
});

return accumulateDiff;

})));
<|endoftext|>