<commit_before>import Ember from 'ember';

import flightFromData from '../utils/flight-from-data';
import slFlightCollection from '../utils/flight-collection';
import Fix from '../utils/fix';

/**
 * List of colors for flight path display
 * @type {Array<String>}
 */
const COLORS = [
  '#004bbd',
  '#bf0099',
  '#cf7c00',
  '#ff0000',
  '#00c994',
  '#ffff00',
];

export default Ember.Service.extend({
  flights: [],

  /*
   * Global time, can be:
   * null -> no time is set, don't show barogram crosshair/plane position
   * -1 -> always show the latest time/fix for each flight
   * >= 0 -> show the associated time in the barogram and on the map
   * @type {!Number}
   */
  time: null,

  /**
   * Default time - the time to set when no time is set
   * @type {!Number}
   */
  defaultTime: null,

  timer: null,

  isRunning: Ember.computed.bool('timer'),

  startTimes: Ember.computed.mapBy('flights', 'startTime'),
  minStartTime: Ember.computed.min('startTimes'),

  endTimes: Ember.computed.mapBy('flights', 'endTime'),
  maxEndTime: Ember.computed.max('endTimes'),

  fixes: Ember.computed.map('flights', function(flight) {
    return Fix.create({ flight, fixCalc: this });
  }),

  init() {
    this._super(...arguments);
    window.fixCalcService = this;

    this.set('flights', slFlightCollection.create());
  },

  startPlayback() {
    let time = this.get('time');

    if (time === null || time === -1) {
      this.set('time', this.get('minStartTime'));
    }

    this.set('timer', Ember.run.later(this, 'onTick', 50));
  },

  stopPlayback() {
    let timer = this.get('timer');
    if (timer) {
      Ember.run.cancel(timer);
      this.set('timer', null);
    }
  },

  onTick() {
    let time = this.get('time') + 1;

    if (time > this.get('maxEndTime')) {
      this.stopPlayback();
    }

    this.set('time', time);
    this.set('timer', Ember.run.later(this, 'onTick', 50));
  },

  resetTime() {
    this.set('time', this.get('defaultTime'));
  },

  /**
   * Add a flight to the map and barogram.
   *
   * @param {Object} data The data received from the JSON request.
   */
  addFlight(data) {
    let flights = this.get('flights');

    let flight = flightFromData(data);

    if (data.additional && data.additional.color) {
      flight.set('color', data.additional.color);
    } else {
      flight.set('color', COLORS[flights.get('length') % COLORS.length]);
    }

    flights.pushObject(flight);
  },

  /**
   * Perform a JSON request to get a flight.
   *
   * @param {String} url URL to fetch.
   */
  addFlightFromJSON(url) {
    let flights = this.get('flights');

    Ember.$.ajax(url, {
      success: data => {
        if (flights.findBy('id', data.sfid))
          return;

        this.addFlight(data);
      },
    });
  },
});
<commit_msg>services/fix-calc: Use "ajax" service<commit_after>import Ember from 'ember';

import flightFromData from '../utils/flight-from-data';
import slFlightCollection from '../utils/flight-collection';
import Fix from '../utils/fix';

/**
 * List of colors for flight path display
 * @type {Array<String>}
 */
const COLORS = [
  '#004bbd',
  '#bf0099',
  '#cf7c00',
  '#ff0000',
  '#00c994',
  '#ffff00',
];

export default Ember.Service.extend({
  ajax: Ember.inject.service(),

  flights: [],

  /*
   * Global time, can be:
   * null -> no time is set, don't show barogram crosshair/plane position
   * -1 -> always show the latest time/fix for each flight
   * >= 0 -> show the associated time in the barogram and on the map
   * @type {!Number}
   */
  time: null,

  /**
   * Default time - the time to set when no time is set
   * @type {!Number}
   */
  defaultTime: null,

  timer: null,

  isRunning: Ember.computed.bool('timer'),

  startTimes: Ember.computed.mapBy('flights', 'startTime'),
  minStartTime: Ember.computed.min('startTimes'),

  endTimes: Ember.computed.mapBy('flights', 'endTime'),
  maxEndTime: Ember.computed.max('endTimes'),

  fixes: Ember.computed.map('flights', function(flight) {
    return Fix.create({ flight, fixCalc: this });
  }),

  init() {
    this._super(...arguments);
    window.fixCalcService = this;

    this.set('flights', slFlightCollection.create());
  },

  startPlayback() {
    let time = this.get('time');

    if (time === null || time === -1) {
      this.set('time', this.get('minStartTime'));
    }

    this.set('timer', Ember.run.later(this, 'onTick', 50));
  },

  stopPlayback() {
    let timer = this.get('timer');
    if (timer) {
      Ember.run.cancel(timer);
      this.set('timer', null);
    }
  },

  onTick() {
    let time = this.get('time') + 1;

    if (time > this.get('maxEndTime')) {
      this.stopPlayback();
    }

    this.set('time', time);
    this.set('timer', Ember.run.later(this, 'onTick', 50));
  },

  resetTime() {
    this.set('time', this.get('defaultTime'));
  },

  /**
   * Add a flight to the map and barogram.
   *
   * @param {Object} data The data received from the JSON request.
   */
  addFlight(data) {
    let flights = this.get('flights');

    let flight = flightFromData(data);

    if (data.additional && data.additional.color) {
      flight.set('color', data.additional.color);
    } else {
      flight.set('color', COLORS[flights.get('length') % COLORS.length]);
    }

    flights.pushObject(flight);
  },

  /**
   * Perform a JSON request to get a flight.
   *
   * @param {String} url URL to fetch.
   */
  addFlightFromJSON(url) {
    let flights = this.get('flights');

    return this.get('ajax').request(url).then(data => {
      if (flights.findBy('id', data.sfid))
        return;

      this.addFlight(data);
    });
  },
});
<|endoftext|>


<commit_before>import Ember from 'ember';
const { inject: { service }, isEmpty } = Ember;
import NodeJsonWebToken from 'npm:jsonwebtoken';
import ENV from 'bracco/config/environment';

export default Ember.Service.extend({
  session: service(),
  store: service(),
  flashMessages: service(),
  features: service(),

  uid: null,
  jwt: null,
  name: null,
  email: null,
  role_id: null,
  roleName: null,
  provider_id: null,
  client_id: null,
  home: null,
  settings: null,
  isAdmin: false,
  isProvider: false,
  isClient: false,

  load() {
    let jwt = this.get('session.data.authenticated.access_token');
    if (!isEmpty(jwt)) {
      // RSA public key
      let cert = ENV.JWT_PUBLIC_KEY ? ENV.JWT_PUBLIC_KEY.replace(/\\n/g, '\n') : null;

      // verify asymmetric token, using RSA with SHA-256 hash algorithm
      let self = this;
      NodeJsonWebToken.verify(jwt, cert, { algorithms: ['RS256'] }, function (error, payload) {
        if (payload) {
          self.set('jwt', jwt);
          self.initUser(payload);
        } else if (error.message !== "jwt must be provided") {
          Ember.Logger.assert(false, error);
        }
      });
    }
    return Ember.RSVP.resolve();
  },

  initUser(payload) {
    if (!isEmpty(payload) && !isEmpty(payload.uid)) {
      this.set('uid', payload.uid);
      this.set('name', payload.name);
      this.set('email', payload.email);
      this.set('provider_id', payload.provider_id);
      this.set('client_id', payload.client_id);
      this.set('role_id', payload.role_id);
      this.set('roleName', payload.role_id.split('_')[0].capitalize());

      if (payload.role_id === 'staff_admin') {
        this.set('isAdmin', true);
        this.set('home', { route: 'index' });
        this.set('settings', { route: 'settings' });
      } else if (payload.role_id === 'provider_admin') {
        this.set('isProvider', true);
        this.set('home', { route: 'providers.show', id: this.get('uid') });
        this.set('settings', { route: 'providers.show.settings', id: this.get('uid') });
      } else if (payload.role_id === 'client_admin') {
        this.set('isClient', true);
        this.set('home', { route: 'clients.show', id: this.get('uid') });
        this.set('settings', { route: 'clients.show.settings', id: this.get('uid') });
      } else if (payload.role_id === 'user') {
        this.set('home', 'password');
      }

      if (payload.role_id !== 'user') {
        this.get('flashMessages').info('Welcome ' + this.get('name') + ' to the DOI Fabrica administration area.');
      }

      // setup features for ember-feature-flags
      // this.get('features').setup(payload.features);
    }
  }
});
<commit_msg>handle expired password reset links. Closes datacite/datacite#339<commit_after>import Ember from 'ember';
const { inject: { service }, isEmpty } = Ember;
import NodeJsonWebToken from 'npm:jsonwebtoken';
import ENV from 'bracco/config/environment';

export default Ember.Service.extend({
  session: service(),
  store: service(),
  flashMessages: service(),
  features: service(),

  uid: null,
  jwt: null,
  name: null,
  email: null,
  role_id: null,
  roleName: null,
  provider_id: null,
  client_id: null,
  home: null,
  settings: null,
  isAdmin: false,
  isProvider: false,
  isClient: false,

  load() {
    let jwt = this.get('session.data.authenticated.access_token');
    if (!isEmpty(jwt)) {
      // RSA public key
      let cert = ENV.JWT_PUBLIC_KEY ? ENV.JWT_PUBLIC_KEY.replace(/\\n/g, '\n') : null;

      // verify asymmetric token, using RSA with SHA-256 hash algorithm
      let self = this;
      NodeJsonWebToken.verify(jwt, cert, { algorithms: ['RS256'] }, function (error, payload) {
        if (payload) {
          self.set('jwt', jwt);
          self.initUser(payload);
        } else if (error.message !== "jwt must be provided") {
          self.get('flashMessages').danger('Unable to authenticate because the token was wrong or has expired.');
          self.set('router', Ember.getOwner(self).lookup('router:main'));
          self.get('router').transitionTo('/');
        }
      });
    }
    return Ember.RSVP.resolve();
  },

  initUser(payload) {
    if (!isEmpty(payload) && !isEmpty(payload.uid)) {
      this.set('uid', payload.uid);
      this.set('name', payload.name);
      this.set('email', payload.email);
      this.set('provider_id', payload.provider_id);
      this.set('client_id', payload.client_id);
      this.set('role_id', payload.role_id);
      this.set('roleName', payload.role_id.split('_')[0].capitalize());

      if (payload.role_id === 'staff_admin') {
        this.set('isAdmin', true);
        this.set('home', { route: 'index' });
        this.set('settings', { route: 'settings' });
      } else if (payload.role_id === 'provider_admin') {
        this.set('isProvider', true);
        this.set('home', { route: 'providers.show', id: this.get('uid') });
        this.set('settings', { route: 'providers.show.settings', id: this.get('uid') });
      } else if (payload.role_id === 'client_admin') {
        this.set('isClient', true);
        this.set('home', { route: 'clients.show', id: this.get('uid') });
        this.set('settings', { route: 'clients.show.settings', id: this.get('uid') });
      } else if (payload.role_id === 'user') {
        this.set('home', 'password');
      }

      if (payload.role_id !== 'user') {
        this.get('flashMessages').info('Welcome ' + this.get('name') + ' to the DOI Fabrica administration area.');
      }

      // setup features for ember-feature-flags
      // this.get('features').setup(payload.features);
    }
  }
});
<|endoftext|>


<commit_before>/* jshint globalstrict:false, strict:false, maxlen: 5000 */
/* global describe, beforeEach, afterEach, it, global, before,  */
'use strict';

// //////////////////////////////////////////////////////////////////////////////
// / DISCLAIMER
// /
// / Copyright 2020 ArangoDB GmbH, Cologne, Germany
// /
// / 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.
// /
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
// /
// / @author Michael Hackstein
// //////////////////////////////////////////////////////////////////////////////

const {expect} = require('chai');
const request = require("@arangodb/request");
const db = require("internal").db;

const expectOneBucketChanged = (actual, old) => {
  let foundOne = false;
  for (const [key, value] of Object.entries(actual)) {
    if (old[key] < value) {
      foundOne = true;
    }
    expect(old[key]).to.be.most(value);

  }
  expect(foundOne).to.equal(true);
};

const MetricNames = {
  QUERY_TIME: "arangodb_aql_total_query_time_msec",
  PHASE_1_BUCKET: "arangodb_maintenance_phase1_runtime_msec_bucket",
  PHASE_1_COUNT: "arangodb_maintenance_phase1_runtime_msec_count",
  PHASE_2_BUCKET: "arangodb_maintenance_phase2_runtime_msec_bucket",
  PHASE_2_COUNT: "arangodb_maintenance_phase2_runtime_msec_count",
  SHARD_COUNT: "arangodb_shards_total_count",
  SHARD_LEADER_COUNT: "arangodb_shards_leader_count",
  HEARTBEAT_BUCKET: "arangodb_heartbeat_send_time_msec_bucket",
  HEARTBEAT_COUNT: "arangodb_heartbeat_send_time_msec_count",
  SUPERVISION_BUCKET: "arangodb_agency_supervision_runtime_msec_bucket",
  SUPERVISION_COUNT: "arangodb_agency_supervision_runtime_msec_count"
};

class Watcher {
  beforeCoordinator(metrics) {};
  afterCoordinator(metrics) {};
  beforeDBServer(metrics) {};
  afterDBServer(metrics) {};
  beforeAgent(metrics) {};
  afterAgent(metrics) {};
}

class CoordinatorValueWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeCoordinator(metrics) {
    this._before = metrics[this._metric];
  };

  afterCoordinator(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before);
  };
}

class CoordinatorBucketWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeCoordinator(metrics) {
    this._before = metrics[this._metric];
  };

  afterCoordinator(metrics) {
    const after =  metrics[this._metric];
    expectOneBucketChanged(after, this._before);
  };
}

class DBServerValueWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeDBServer(metrics) {
    this._before = metrics[this._metric];
  };

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before);
  };
}

class DBServerBucketWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeDBServer(metrics) {
    this._before = metrics[this._metric];
  };

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expectOneBucketChanged(after, this._before);
  };
}

class AgentValueWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeAgent(metrics) {
    this._before = metrics[this._metric];
  };

  afterAgent(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before);
  };
}

class AgentBucketWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeAgent(metrics) {
    this._before = metrics[this._metric];
  };

  afterAgent(metrics) {
    const after =  metrics[this._metric];
    expectOneBucketChanged(after, this._before);
  };
}

class QueryTimeWatcher extends CoordinatorValueWatcher {
  constructor(minChange) {
    super(MetricNames.QUERY_TIME);
    this._minChange = minChange;
  }

  afterCoordinator(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before + this._minChange);
  };
}

class ShardCountWatcher extends DBServerValueWatcher {
  constructor(change) {
    super(MetricNames.SHARD_COUNT);
    this._change = change;
  }

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.equal(this._before + this._change);
  };
}

class ShardLeaderCountWatcher extends DBServerValueWatcher {
  constructor(change) {
    super(MetricNames.SHARD_LEADER_COUNT);
    this._change = change;
  }

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.equal(this._before + this._change);
  };
}

class MaintenanceWatcher extends Watcher {
  constructor() {
    super();
    this._p1ValueWatcher = new DBServerValueWatcher(MetricNames.PHASE_1_COUNT);
    this._p2ValueWatcher = new DBServerValueWatcher(MetricNames.PHASE_2_COUNT);
    this._p1BucketWatcher = new DBServerBucketWatcher(MetricNames.PHASE_1_BUCKET);
    this._p2BucketWatcher = new DBServerBucketWatcher(MetricNames.PHASE_2_BUCKET);
  }

  beforeDBServer(metrics) {
    this._p1ValueWatcher.beforeDBServer(metrics);
    this._p2ValueWatcher.beforeDBServer(metrics);
    this._p1BucketWatcher.beforeDBServer(metrics);
    this._p2BucketWatcher.beforeDBServer(metrics);
  };

  afterDBServer(metrics) {
    this._p1ValueWatcher.afterDBServer(metrics);
    this._p2ValueWatcher.afterDBServer(metrics);
    this._p1BucketWatcher.afterDBServer(metrics);
    this._p2BucketWatcher.afterDBServer(metrics);
  };
}

class HeartBeatWatcher extends Watcher {
  constructor() {
    super();
    this._dbhbValueWatcher = new DBServerValueWatcher(MetricNames.HEARTBEAT_COUNT);
    this._dbhbBucketWatcher = new DBServerBucketWatcher(MetricNames.HEARTBEAT_BUCKET);
    this._coordhbValueWatcher = new CoordinatorValueWatcher(MetricNames.HEARTBEAT_COUNT);
    this._coordhbBucketWatcher = new CoordinatorBucketWatcher(MetricNames.HEARTBEAT_BUCKET);
  }

  beforeDBServer(metrics) {
    this._dbhbValueWatcher.beforeDBServer(metrics);
    this._dbhbBucketWatcher.beforeDBServer(metrics);
  };

  afterDBServer(metrics) {
    this._dbhbValueWatcher.afterDBServer(metrics);
    this._dbhbBucketWatcher.afterDBServer(metrics);
  };

  beforeCoordinator(metrics) {
    this._coordhbValueWatcher.beforeCoordinator(metrics);
    this._coordhbBucketWatcher.beforeCoordinator(metrics);
  };

  afterCoordinator(metrics) {
    this._coordhbValueWatcher.afterCoordinator(metrics);
    this._coordhbBucketWatcher.afterCoordinator(metrics);
  };
}

class SupervisionWatcher extends Watcher {
  constructor() {
    super();
    this._svValueWatcher = new AgentValueWatcher(MetricNames.SUPERVISION_COUNT);
    this._svBucketWatcher = new AgentBucketWatcher(MetricNames.SUPERVISION_BUCKET);
  }

  beforeAgent(metrics) {
    this._svValueWatcher.beforeAgent(metrics);
    this._svBucketWatcher.beforeAgent(metrics);
  };

  afterAgent(metrics) {
    this._svValueWatcher.afterAgent(metrics);
    this._svBucketWatcher.afterAgent(metrics);
  };
};

describe('_admin/metrics', () => {

  const getServers = () => {
    const endpointToURL = (endpoint) => {
      if (endpoint.substr(0, 6) === 'ssl://') {
        return 'https://' + endpoint.substr(6);
      }
      var pos = endpoint.indexOf('://');
      if (pos === -1) {
        return 'http://' + endpoint;
      }
      return 'http' + endpoint.substr(pos);
    };
    const {instanceInfo} = global;
    const list = new Map();
    list.set("coordinator", []);
    list.set("dbserver", []);
    list.set("agent", []);
    for (const d of instanceInfo.arangods) {
      const {role, endpoint} = d;
      list.get(role).push(endpointToURL(endpoint));
    }
    return list;
  };

  let servers;

  before(() => {
    servers = getServers();
  });

  const extractKeyAndLabel = (key) => {
    const start = key.indexOf('{');
    const labels = new Map();
    if (start === -1) {
      return [key, labels];
    }
    const labelPart = key.substring(start + 1, key.length - 1);
    for (const l of labelPart.split(",")) {
      const [lab, val] = l.split("=");
      labels.set(lab,val);
    }
    return [
      key.substring(0, start),
      labels
    ];
  };

    const prometheusToJson = (prometheus) => {
      const lines = prometheus.split('\n').filter((s) => !s.startsWith('#') && s !== '');
      const res = {};
      for (const l of lines) {
        const [keypart, count] = l.split(' ');
        const [key, labels] = extractKeyAndLabel(keypart);
        if (labels.has("le")) {
          // Bucket case
          // We only check for:
          // identifier{le="range"}
          // For all other bucket-types this code will fail
          res[key] = res[key] || {};
          res[key][labels.get("le")] = parseFloat(count);
        } else {
          // evertyhing else
          // We ignore other labels for now.
          res[key] = parseFloat(count);
        }

      }
      return res;
    };

    const loadMetrics = (role, idx) =>  {
      const url = `${servers.get(role)[idx]}/_admin/metrics`;

      const res = request({
        json: true,
        method: 'GET',
        url
      });
      expect(res.statusCode).to.equal(200);
      return prometheusToJson(res.body);
    };

    const joinMetrics = (lhs, rhs) => {
      if (Object.entries(lhs).length === 0) {
        return rhs;
      }
      for (const [key, value] of Object.entries(rhs)) {
        if (value instanceof Object) {
          for (const [bucket, content] of Object.entries(value)) {
            lhs[key][bucket] += content;
          }
        } else {
          lhs[key] += rhs[key];
        }
      }
      return lhs;
    };

    const loadAllMetrics = (role) => {
      return servers.get(role).map((_, i) => loadMetrics(role, i)).reduce(joinMetrics, {});
     };

    const runTest = (action, watchers) => {
      const coordBefore = loadAllMetrics("coordinator");
      watchers.forEach(w => {w.beforeCoordinator(coordBefore);});

      const dbBefore = loadAllMetrics("dbserver");
      watchers.forEach(w => {w.beforeDBServer(dbBefore);});

      const agentsBefore = loadAllMetrics("agent");
      watchers.forEach(w => {w.beforeAgent(agentsBefore);});

      action();
      const coordAfter = loadAllMetrics("coordinator");
      watchers.forEach(w => {w.afterCoordinator(coordAfter);});

      const dbAfter = loadAllMetrics("dbserver");
      watchers.forEach(w => {w.afterDBServer(dbAfter);});

      const agentsAfter = loadAllMetrics("agent");
      watchers.forEach(w => {w.afterAgent(agentsAfter);});
    };

    it('aql query time', () => {
      runTest(() => {
        const query = `return sleep(1)`;
        db._query(query);
      }, [new QueryTimeWatcher(1000)]);
    });

    it('collection and index', () => {
      try {
        runTest(() => {
          db._create("UnitTestCollection", {numberOfShards: 9, replicationFactor: 2});
        },
        [new MaintenanceWatcher(), new ShardCountWatcher(18), new ShardLeaderCountWatcher(9)]
        );
        runTest(() => {
          db["UnitTestCollection"].ensureHashIndex("temp");
        },
        [new MaintenanceWatcher()]
        );
      } finally {
        db._drop("UnitTestCollection");
      }
    });

    it('at least 1 heartbeat and supervision per second', () => {
      runTest(() => {
        require("internal").wait(1.0);
      }, [new HeartBeatWatcher(), new SupervisionWatcher()]);
    });
});
<commit_msg>Fix QueryTimeWatcher to check >=, not > (#11413)<commit_after>/* jshint globalstrict:false, strict:false, maxlen: 5000 */
/* global describe, beforeEach, afterEach, it, global, before,  */
'use strict';

// //////////////////////////////////////////////////////////////////////////////
// / DISCLAIMER
// /
// / Copyright 2020 ArangoDB GmbH, Cologne, Germany
// /
// / 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.
// /
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
// /
// / @author Michael Hackstein
// //////////////////////////////////////////////////////////////////////////////

const {expect} = require('chai');
const request = require("@arangodb/request");
const db = require("internal").db;

const expectOneBucketChanged = (actual, old) => {
  let foundOne = false;
  for (const [key, value] of Object.entries(actual)) {
    if (old[key] < value) {
      foundOne = true;
    }
    expect(old[key]).to.be.most(value);

  }
  expect(foundOne).to.equal(true);
};

const MetricNames = {
  QUERY_TIME: "arangodb_aql_total_query_time_msec",
  PHASE_1_BUCKET: "arangodb_maintenance_phase1_runtime_msec_bucket",
  PHASE_1_COUNT: "arangodb_maintenance_phase1_runtime_msec_count",
  PHASE_2_BUCKET: "arangodb_maintenance_phase2_runtime_msec_bucket",
  PHASE_2_COUNT: "arangodb_maintenance_phase2_runtime_msec_count",
  SHARD_COUNT: "arangodb_shards_total_count",
  SHARD_LEADER_COUNT: "arangodb_shards_leader_count",
  HEARTBEAT_BUCKET: "arangodb_heartbeat_send_time_msec_bucket",
  HEARTBEAT_COUNT: "arangodb_heartbeat_send_time_msec_count",
  SUPERVISION_BUCKET: "arangodb_agency_supervision_runtime_msec_bucket",
  SUPERVISION_COUNT: "arangodb_agency_supervision_runtime_msec_count"
};

class Watcher {
  beforeCoordinator(metrics) {};
  afterCoordinator(metrics) {};
  beforeDBServer(metrics) {};
  afterDBServer(metrics) {};
  beforeAgent(metrics) {};
  afterAgent(metrics) {};
}

class CoordinatorValueWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeCoordinator(metrics) {
    this._before = metrics[this._metric];
  };

  afterCoordinator(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before);
  };
}

class CoordinatorBucketWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeCoordinator(metrics) {
    this._before = metrics[this._metric];
  };

  afterCoordinator(metrics) {
    const after =  metrics[this._metric];
    expectOneBucketChanged(after, this._before);
  };
}

class DBServerValueWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeDBServer(metrics) {
    this._before = metrics[this._metric];
  };

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before);
  };
}

class DBServerBucketWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeDBServer(metrics) {
    this._before = metrics[this._metric];
  };

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expectOneBucketChanged(after, this._before);
  };
}

class AgentValueWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeAgent(metrics) {
    this._before = metrics[this._metric];
  };

  afterAgent(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.greaterThan(this._before);
  };
}

class AgentBucketWatcher extends Watcher {
  constructor(metric) {
    super();
    this._metric = metric;
    this._before = null;
  }

  beforeAgent(metrics) {
    this._before = metrics[this._metric];
  };

  afterAgent(metrics) {
    const after =  metrics[this._metric];
    expectOneBucketChanged(after, this._before);
  };
}

class QueryTimeWatcher extends CoordinatorValueWatcher {
  constructor(minChange) {
    super(MetricNames.QUERY_TIME);
    this._minChange = minChange;
  }

  afterCoordinator(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.at.least(this._before + this._minChange);
  };
}

class ShardCountWatcher extends DBServerValueWatcher {
  constructor(change) {
    super(MetricNames.SHARD_COUNT);
    this._change = change;
  }

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.equal(this._before + this._change);
  };
}

class ShardLeaderCountWatcher extends DBServerValueWatcher {
  constructor(change) {
    super(MetricNames.SHARD_LEADER_COUNT);
    this._change = change;
  }

  afterDBServer(metrics) {
    const after =  metrics[this._metric];
    expect(after).to.be.equal(this._before + this._change);
  };
}

class MaintenanceWatcher extends Watcher {
  constructor() {
    super();
    this._p1ValueWatcher = new DBServerValueWatcher(MetricNames.PHASE_1_COUNT);
    this._p2ValueWatcher = new DBServerValueWatcher(MetricNames.PHASE_2_COUNT);
    this._p1BucketWatcher = new DBServerBucketWatcher(MetricNames.PHASE_1_BUCKET);
    this._p2BucketWatcher = new DBServerBucketWatcher(MetricNames.PHASE_2_BUCKET);
  }

  beforeDBServer(metrics) {
    this._p1ValueWatcher.beforeDBServer(metrics);
    this._p2ValueWatcher.beforeDBServer(metrics);
    this._p1BucketWatcher.beforeDBServer(metrics);
    this._p2BucketWatcher.beforeDBServer(metrics);
  };

  afterDBServer(metrics) {
    this._p1ValueWatcher.afterDBServer(metrics);
    this._p2ValueWatcher.afterDBServer(metrics);
    this._p1BucketWatcher.afterDBServer(metrics);
    this._p2BucketWatcher.afterDBServer(metrics);
  };
}

class HeartBeatWatcher extends Watcher {
  constructor() {
    super();
    this._dbhbValueWatcher = new DBServerValueWatcher(MetricNames.HEARTBEAT_COUNT);
    this._dbhbBucketWatcher = new DBServerBucketWatcher(MetricNames.HEARTBEAT_BUCKET);
    this._coordhbValueWatcher = new CoordinatorValueWatcher(MetricNames.HEARTBEAT_COUNT);
    this._coordhbBucketWatcher = new CoordinatorBucketWatcher(MetricNames.HEARTBEAT_BUCKET);
  }

  beforeDBServer(metrics) {
    this._dbhbValueWatcher.beforeDBServer(metrics);
    this._dbhbBucketWatcher.beforeDBServer(metrics);
  };

  afterDBServer(metrics) {
    this._dbhbValueWatcher.afterDBServer(metrics);
    this._dbhbBucketWatcher.afterDBServer(metrics);
  };

  beforeCoordinator(metrics) {
    this._coordhbValueWatcher.beforeCoordinator(metrics);
    this._coordhbBucketWatcher.beforeCoordinator(metrics);
  };

  afterCoordinator(metrics) {
    this._coordhbValueWatcher.afterCoordinator(metrics);
    this._coordhbBucketWatcher.afterCoordinator(metrics);
  };
}

class SupervisionWatcher extends Watcher {
  constructor() {
    super();
    this._svValueWatcher = new AgentValueWatcher(MetricNames.SUPERVISION_COUNT);
    this._svBucketWatcher = new AgentBucketWatcher(MetricNames.SUPERVISION_BUCKET);
  }

  beforeAgent(metrics) {
    this._svValueWatcher.beforeAgent(metrics);
    this._svBucketWatcher.beforeAgent(metrics);
  };

  afterAgent(metrics) {
    this._svValueWatcher.afterAgent(metrics);
    this._svBucketWatcher.afterAgent(metrics);
  };
};

describe('_admin/metrics', () => {

  const getServers = () => {
    const endpointToURL = (endpoint) => {
      if (endpoint.substr(0, 6) === 'ssl://') {
        return 'https://' + endpoint.substr(6);
      }
      var pos = endpoint.indexOf('://');
      if (pos === -1) {
        return 'http://' + endpoint;
      }
      return 'http' + endpoint.substr(pos);
    };
    const {instanceInfo} = global;
    const list = new Map();
    list.set("coordinator", []);
    list.set("dbserver", []);
    list.set("agent", []);
    for (const d of instanceInfo.arangods) {
      const {role, endpoint} = d;
      list.get(role).push(endpointToURL(endpoint));
    }
    return list;
  };

  let servers;

  before(() => {
    servers = getServers();
  });

  const extractKeyAndLabel = (key) => {
    const start = key.indexOf('{');
    const labels = new Map();
    if (start === -1) {
      return [key, labels];
    }
    const labelPart = key.substring(start + 1, key.length - 1);
    for (const l of labelPart.split(",")) {
      const [lab, val] = l.split("=");
      labels.set(lab,val);
    }
    return [
      key.substring(0, start),
      labels
    ];
  };

    const prometheusToJson = (prometheus) => {
      const lines = prometheus.split('\n').filter((s) => !s.startsWith('#') && s !== '');
      const res = {};
      for (const l of lines) {
        const [keypart, count] = l.split(' ');
        const [key, labels] = extractKeyAndLabel(keypart);
        if (labels.has("le")) {
          // Bucket case
          // We only check for:
          // identifier{le="range"}
          // For all other bucket-types this code will fail
          res[key] = res[key] || {};
          res[key][labels.get("le")] = parseFloat(count);
        } else {
          // evertyhing else
          // We ignore other labels for now.
          res[key] = parseFloat(count);
        }

      }
      return res;
    };

    const loadMetrics = (role, idx) =>  {
      const url = `${servers.get(role)[idx]}/_admin/metrics`;

      const res = request({
        json: true,
        method: 'GET',
        url
      });
      expect(res.statusCode).to.equal(200);
      return prometheusToJson(res.body);
    };

    const joinMetrics = (lhs, rhs) => {
      if (Object.entries(lhs).length === 0) {
        return rhs;
      }
      for (const [key, value] of Object.entries(rhs)) {
        if (value instanceof Object) {
          for (const [bucket, content] of Object.entries(value)) {
            lhs[key][bucket] += content;
          }
        } else {
          lhs[key] += rhs[key];
        }
      }
      return lhs;
    };

    const loadAllMetrics = (role) => {
      return servers.get(role).map((_, i) => loadMetrics(role, i)).reduce(joinMetrics, {});
     };

    const runTest = (action, watchers) => {
      const coordBefore = loadAllMetrics("coordinator");
      watchers.forEach(w => {w.beforeCoordinator(coordBefore);});

      const dbBefore = loadAllMetrics("dbserver");
      watchers.forEach(w => {w.beforeDBServer(dbBefore);});

      const agentsBefore = loadAllMetrics("agent");
      watchers.forEach(w => {w.beforeAgent(agentsBefore);});

      action();
      const coordAfter = loadAllMetrics("coordinator");
      watchers.forEach(w => {w.afterCoordinator(coordAfter);});

      const dbAfter = loadAllMetrics("dbserver");
      watchers.forEach(w => {w.afterDBServer(dbAfter);});

      const agentsAfter = loadAllMetrics("agent");
      watchers.forEach(w => {w.afterAgent(agentsAfter);});
    };

    it('aql query time', () => {
      runTest(() => {
        const query = `return sleep(1)`;
        db._query(query);
      }, [new QueryTimeWatcher(1000)]);
    });

    it('collection and index', () => {
      try {
        runTest(() => {
          db._create("UnitTestCollection", {numberOfShards: 9, replicationFactor: 2});
        },
        [new MaintenanceWatcher(), new ShardCountWatcher(18), new ShardLeaderCountWatcher(9)]
        );
        runTest(() => {
          db["UnitTestCollection"].ensureHashIndex("temp");
        },
        [new MaintenanceWatcher()]
        );
      } finally {
        db._drop("UnitTestCollection");
      }
    });

    it('at least 1 heartbeat and supervision per second', () => {
      runTest(() => {
        require("internal").wait(1.0);
      }, [new HeartBeatWatcher(), new SupervisionWatcher()]);
    });
});
<|endoftext|>


<commit_before>var regExCache = {
    array: new RegExp(/(.*?)\[(.*?)\]/), //looks for [<contents>],
    cond: new RegExp(/([^<>=]+)([<>=][=]*)([^<>=]+)/), //looks for a>b , a<b, a=b, a>=b, a<=b patterns
    math: new RegExp(/([^\+-]+)([\+-])([^\+-]+)/), //looks for a+b, a-b
    exp: new RegExp(/(.*?)\((.*?)\)/) //look for (<contents>)
};

let prop = (name => (obj => obj[name]));
let genProp = (fn => (obj => obj[fn(obj)]));

function pick(arr) {

    if (!arr.length) {
        return (() => false);
    }
    let obj = {};
    arr.forEach(entry => obj[entry] = true);
    return ((entry, idx) => idx in obj) ;
}

function filter(fn) {
    return function doFilter(arr) {
        let result = [];
        if(typeof arr !== 'object') {
            return result;
        }

        Object.keys(arr).forEach(function(i) {
            let current = fn(arr[i], i);
            if (current) {
                result[result.length] = arr[i];
            }
        });
        return result;
    };
}

function pickRange(start, end, step) {
    var fn;

    if (step) {
        fn = filter((entry, idx) => ((idx === start || ((idx - start) % step) === 0) && idx < end));
    }
    return (arr => (fn && fn(arr)) || (end !== undefined ? arr.slice(start, end): arr.slice(start)));
}

function mapAndFilter(fn) {
    return function doMapFilter(arr) {
        let result = [];
        if (typeof arr !== 'object') {
            return result;
        }

        let current;
        for (let i in arr) {
            if (arr.hasOwnProperty(i)) {
                current = fn(arr[i], i);
                if (current !== undefined) {
                    result[result.length] = current;
                }
            }
        }
        return result;
    };
}

function spread(fn) {
    return function doSpread(arr) {
        let result = [];
        let current;
        arr.forEach(entry => result = (current = fn(entry)) ? result.concat(current): result);
        return result;
    };
}

function keys() {
    return function getValues(obj) {
        let result = [];

        if (typeof obj !== 'object') {
            return result;
        }

        let keys = Object.keys(obj);
        keys.forEach((item, i) => result[i] = obj[keys[i]]);
        return result;
    };
}

function findKey(name) {
    return function find(obj) {
        let result = [];

        Object.keys(obj).forEach(function(key) {
            let value = obj[key];
            if (name === key || name === '*') {
                result[result.length] = value;
            }

            if (typeof value === 'object') {
                result = result.concat(find(value));
            }
        });
        return result;
    };
}

function processVal(val) {
    let isProp = (val.indexOf && val.indexOf('@') !== -1);

    if (isProp) {
        val = val.replace('@.', '');
    } else {
        try {
            val = val.replace(/'/g, '');
        } catch (e) {}
    }
    return {
        isProp,
        val
    };
}

function conditional(lhs, op, rhs) {
    lhs = processVal(lhs);
    rhs = processVal(rhs);
    return function doCheck(entry) {
        var lvalue = (lhs.isProp) ? entry[lhs.val] : lhs.val,
            rvalue = (rhs.isProp) ? entry[rhs.val] : rhs.val;

        if (typeof(lvalue) === 'object' || typeof(rvalue) === 'object') {
            return false;
        }

        switch (op) {
            case '>':
                return lvalue > rvalue;

            case '>=':
                return lvalue >= rvalue;

            case '<':
                return lvalue < rvalue;

            case '<=':
                return lvalue <= rvalue;

            case '=':
                return lvalue == rvalue; // jshint ignore:line

            default:
                return false;
        }
    };
}

function math(lhs, op, rhs) {
    lhs = processVal(lhs);
    rhs = processVal(rhs);

    return function doMath(entry) {
        var lvalue = (lhs.isProp) ? entry[lhs.val] : lhs.val,
            rvalue = (rhs.isProp) ? entry[rhs.val] : rhs.val;

        if (typeof lvalue === 'object' || typeof rvalue === 'object') {
            return NaN;
        }
        switch (op) {
            case '+':
                return lvalue + rvalue;

            case '-':
                return lvalue - rvalue;

            case '*':
                return lvalue * rvalue;

            case '/':
                return lvalue / rvalue;

            default:
                return NaN;
        }
    };
}

function handleArrArg (loc, processors) {
    let exp = regExCache.cond.exec(loc);
    if (exp) {
        processors.push(spread(filter(conditional(exp[1], exp[2], exp[3]))));
    } else {
        exp = regExCache.math.exec(loc);
        if (exp) {
            processors.push(mapAndFilter(genProp(math(exp[1], exp[2], exp[3]))));
        } else {
            processors.push(spread(filter(prop(loc.replace('@.', '')))));
        }
    }
}

function handleArr({locator, processors, idx}, doSpread) {

    let exp = regExCache.array.exec(locator.replace(/\s/g, ''));
    if(!exp) {
        throw new Error('Invalid JSONPath');
    }

    if(doSpread) {
        processors.push(spread(findKey(exp[1])));
    } else {
        //could be a pattern like $[<content>]
        if (exp[1] !== '$') {
            processors.push(mapAndFilter(prop(exp[1])));
        }
    }

    let tmp;
    if(locator.indexOf('@') !== -1) {
        tmp = regExCache.exp.exec(exp[2]);
        if (!tmp) {
            throw new Error('Invalid JSONPath');
        }
        handleArrArg(tmp[2].replace(/\s/g, ''), processors);

    } else {
        if(exp[2] === '*') {
            //[*]
            processors.push(spread(keys()));
        } else if((idx = exp[2].indexOf(':') )!== -1) {
            tmp = exp[2].split(':');
            if(tmp.length < 3) {
                //n: or :n pattern
                processors.push(spread((idx === 0) ? pickRange(0, parseInt(tmp[1])): pickRange(parseInt(tmp[0]))));
            } else {
                //start:end:step
                processors.push(spread(pickRange(parseInt(tmp[0]), parseInt(tmp[1]), parseInt(tmp[2]))));
            }
        } else {
            //[n], [1,2,...,n]
            processors.push(spread(filter(pick(exp[2].split(',')))));
        }
    }
}

function stitchLocator (locators, currIdx) {
    let loc = locators[currIdx];
    let idx = currIdx + 1;

    do {
        loc += '.' + locators[idx];
    } while (locators[idx++].indexOf(']') === -1 && idx < locators.length);

    return {
        loc,
        idx
    };
}

function process(pattern) {

    var locators = pattern.replace('$.', '').split('.'),
        processors = [],
        idx = 0, loc, idx1, idx2, tmp;

    while (idx < locators.length) {

        loc = locators[idx];
        if (loc === '*') {
            // .* operator
            processors.push(spread(keys()));
        } else if(loc.length === 0) {
            // .. operator
            tmp = locators[++idx];
            idx1 = tmp.indexOf('[');
            idx2 = tmp.indexOf(']');
            if(idx1 !== -1) {
                if (idx2 === -1) {
                    tmp = stitchLocator(locators, idx);
                    idx = tmp.idx;
                    loc = tmp.loc;
                }
                handleArr({locator: tmp.loc || tmp, processors, idx}, true);
            } else {
                processors.push(spread(findKey(tmp)));
            }
        }
        else if (loc.indexOf('[') !== -1) {
            if (loc.indexOf(']') === -1) {
                //has  [<pattern>]
                tmp = stitchLocator(locators, idx);
                idx = tmp.idx;
                loc = tmp.loc;
            }
            handleArr({locator: loc, idx, processors});
        } else {
            //simple .prop ref
            processors.push(mapAndFilter(prop(loc)));
        }
        idx++;
    }
    return processors;
}

export default function fastpath(pattern) {
    return {
        pattern,
        evaluate: (obj => process(pattern).reduce((prev, current) => current(prev), [obj]))
    };
};
<commit_msg>more es6 usage<commit_after>var regExCache = {
    array: new RegExp(/(.*?)\[(.*?)\]/), //looks for [<contents>],
    cond: new RegExp(/([^<>=]+)([<>=][=]*)([^<>=]+)/), //looks for a>b , a<b, a=b, a>=b, a<=b patterns
    math: new RegExp(/([^\+-]+)([\+-])([^\+-]+)/), //looks for a+b, a-b
    exp: new RegExp(/(.*?)\((.*?)\)/) //look for (<contents>)
};

let prop = (name => (obj => obj[name]));
let genProp = (fn => (obj => obj[fn(obj)]));

function pick(arr) {

    if (!arr.length) {
        return (() => false);
    }
    let obj = {};
    arr.forEach(entry => obj[entry] = true);
    return ((entry, idx) => idx in obj) ;
}

function filter(fn) {
    return function doFilter(arr) {
        let result = [];
        if(typeof arr !== 'object') {
            return result;
        }

        let current;
        Object.keys(arr).forEach(i => (current = fn(arr[i], i)) ? result[result.length] = arr[i] : undefined);
        return result;
    };
}

function pickRange(start, end, step) {
    var fn;

    if (step) {
        fn = filter((entry, idx) => ((idx === start || ((idx - start) % step) === 0) && idx < end));
    }
    return (arr => (fn && fn(arr)) || (end !== undefined ? arr.slice(start, end): arr.slice(start)));
}

function mapAndFilter(fn) {
    return function doMapFilter(arr) {
        let result = [];
        if (typeof arr !== 'object') {
            return result;
        }

        let current;
        for (let i in arr) {
            if (arr.hasOwnProperty(i)) {
                current = fn(arr[i], i);
                if (current !== undefined) {
                    result[result.length] = current;
                }
            }
        }
        return result;
    };
}

function spread(fn) {
    return function doSpread(arr) {
        let result = [];
        let current;
        arr.forEach(entry => result = (current = fn(entry)) ? result.concat(current): result);
        return result;
    };
}

function keys() {
    return function getValues(obj) {
        let result = [];

        if (typeof obj !== 'object') {
            return result;
        }

        let keys = Object.keys(obj);
        keys.forEach((item, i) => result[i] = obj[keys[i]]);
        return result;
    };
}

function findKey(name) {
    return function find(obj) {
        let result = [];

        Object.keys(obj).forEach(function(key) {
            let value = obj[key];
            if (name === key || name === '*') {
                result[result.length] = value;
            }

            if (typeof value === 'object') {
                result = result.concat(find(value));
            }
        });
        return result;
    };
}

function processVal(val) {
    let isProp = (val.indexOf && val.indexOf('@') !== -1);

    if (isProp) {
        val = val.replace('@.', '');
    } else {
        try {
            val = val.replace(/'/g, '');
        } catch (e) {}
    }
    return {
        isProp,
        val
    };
}

function conditional(lhs, op, rhs) {
    lhs = processVal(lhs);
    rhs = processVal(rhs);
    return function doCheck(entry) {
        var lvalue = (lhs.isProp) ? entry[lhs.val] : lhs.val,
            rvalue = (rhs.isProp) ? entry[rhs.val] : rhs.val;

        if (typeof(lvalue) === 'object' || typeof(rvalue) === 'object') {
            return false;
        }

        switch (op) {
            case '>':
                return lvalue > rvalue;

            case '>=':
                return lvalue >= rvalue;

            case '<':
                return lvalue < rvalue;

            case '<=':
                return lvalue <= rvalue;

            case '=':
                return lvalue == rvalue; // jshint ignore:line

            default:
                return false;
        }
    };
}

function math(lhs, op, rhs) {
    lhs = processVal(lhs);
    rhs = processVal(rhs);

    return function doMath(entry) {
        var lvalue = (lhs.isProp) ? entry[lhs.val] : lhs.val,
            rvalue = (rhs.isProp) ? entry[rhs.val] : rhs.val;

        if (typeof lvalue === 'object' || typeof rvalue === 'object') {
            return NaN;
        }
        switch (op) {
            case '+':
                return lvalue + rvalue;

            case '-':
                return lvalue - rvalue;

            case '*':
                return lvalue * rvalue;

            case '/':
                return lvalue / rvalue;

            default:
                return NaN;
        }
    };
}

function handleArrArg (loc, processors) {
    let exp = regExCache.cond.exec(loc);
    if (exp) {
        processors.push(spread(filter(conditional(exp[1], exp[2], exp[3]))));
    } else {
        exp = regExCache.math.exec(loc);
        if (exp) {
            processors.push(mapAndFilter(genProp(math(exp[1], exp[2], exp[3]))));
        } else {
            processors.push(spread(filter(prop(loc.replace('@.', '')))));
        }
    }
}

function handleArr({locator, processors, idx}, doSpread) {

    let exp = regExCache.array.exec(locator.replace(/\s/g, ''));
    if(!exp) {
        throw new Error('Invalid JSONPath');
    }

    if(doSpread) {
        processors.push(spread(findKey(exp[1])));
    } else {
        //could be a pattern like $[<content>]
        if (exp[1] !== '$') {
            processors.push(mapAndFilter(prop(exp[1])));
        }
    }

    let tmp;
    if(locator.indexOf('@') !== -1) {
        tmp = regExCache.exp.exec(exp[2]);
        if (!tmp) {
            throw new Error('Invalid JSONPath');
        }
        handleArrArg(tmp[2].replace(/\s/g, ''), processors);

    } else {
        if(exp[2] === '*') {
            //[*]
            processors.push(spread(keys()));
        } else if((idx = exp[2].indexOf(':') )!== -1) {
            tmp = exp[2].split(':');
            if(tmp.length < 3) {
                //n: or :n pattern
                processors.push(spread((idx === 0) ? pickRange(0, parseInt(tmp[1])): pickRange(parseInt(tmp[0]))));
            } else {
                //start:end:step
                processors.push(spread(pickRange(parseInt(tmp[0]), parseInt(tmp[1]), parseInt(tmp[2]))));
            }
        } else {
            //[n], [1,2,...,n]
            processors.push(spread(filter(pick(exp[2].split(',')))));
        }
    }
}

function stitchLocator (locators, currIdx) {
    let loc = locators[currIdx];
    let idx = currIdx + 1;

    do {
        loc += '.' + locators[idx];
    } while (locators[idx++].indexOf(']') === -1 && idx < locators.length);

    return {
        loc,
        idx
    };
}

function process(pattern) {

    var locators = pattern.replace('$.', '').split('.'),
        processors = [],
        idx = 0, loc, idx1, idx2, tmp;

    while (idx < locators.length) {

        loc = locators[idx];
        if (loc === '*') {
            // .* operator
            processors.push(spread(keys()));
        } else if(loc.length === 0) {
            // .. operator
            tmp = locators[++idx];
            idx1 = tmp.indexOf('[');
            idx2 = tmp.indexOf(']');
            if(idx1 !== -1) {
                if (idx2 === -1) {
                    tmp = stitchLocator(locators, idx);
                    idx = tmp.idx;
                    loc = tmp.loc;
                }
                handleArr({locator: tmp.loc || tmp, processors, idx}, true);
            } else {
                processors.push(spread(findKey(tmp)));
            }
        }
        else if (loc.indexOf('[') !== -1) {
            if (loc.indexOf(']') === -1) {
                //has  [<pattern>]
                tmp = stitchLocator(locators, idx);
                idx = tmp.idx;
                loc = tmp.loc;
            }
            handleArr({locator: loc, idx, processors});
        } else {
            //simple .prop ref
            processors.push(mapAndFilter(prop(loc)));
        }
        idx++;
    }
    return processors;
}

export default function fastpath(pattern) {
    return {
        pattern,
        evaluate: (obj => process(pattern).reduce((prev, current) => current(prev), [obj]))
    };
};
<|endoftext|>


<commit_before>// Generated by Creer at 10:54PM on October 16, 2015 UTC, git hash: '98604e3773d1933864742cb78acbf6ea0b4ecd7b'

var Class = require(__basedir + "/utilities/class");
var serializer = require(__basedir + "/gameplay/serializer");
var log = require(__basedir + "/gameplay/log");
var Building = require("./building");

//<<-- Creer-Merge: requires -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

// any additional requires you want can be required here safely between cree runs
//<<-- /Creer-Merge: requires -->>

// @class Warehouse: A typical abandoned warehouse... that anarchists hang out in and can be bribed to burn down Buildings.
var Warehouse = Class(Building, {
    /**
     * Initializes Warehouses.
     *
     * @param {Object} a simple mapping passsed in to the constructor with whatever you sent with it.
     */
    init: function(data) {
        Building.init.apply(this, arguments);

        /**
         * How exposed the anarchists in this warehouse are to PoliceStations. Raises when bribed to ignite buildings, and drops each turn if not bribed.
         *
         * @type {number}
         */
        this._addProperty("exposure", serializer.defaultInteger(data.exposure));

        /**
         * The amount of fire added to buildings when bribed to ignite a building. Headquarters add more fire than normal Warehouses.
         *
         * @type {number}
         */
        this._addProperty("fireAdded", serializer.defaultInteger(data.fireAdded));

        //<<-- Creer-Merge: init -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

        // put any initialization logic here. the base variables should be set from 'data' above
        // NOTE: no players are connected (nor created) at this point. For that logic use 'begin()'

        //<<-- /Creer-Merge: init -->>
    },

    gameObjectName: "Warehouse",

    /**
     * Bribes the Warehouse to light a Building on fire. This adds this building's fireAdded to their fire, and then this building's exposure is increased based on the Manhatten distance between the two buildings.
     *
     * @param {Player} player - the player that called this.
     * @param {Building} building - The Building you want to light on fire.
     * @param {function} asyncReturn - if you nest orders in this function you must return that value via this function in the order's callback.
     * @returns {number} The exposure added to this Building's exposure. -1 is returned if there was an error.
     */
    ignite: function(player, building, asyncReturn) {
        // <<-- Creer-Merge: ignite -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

        if(player.bribesRemaining <= 0){
            return game.logicError(-1, "Player has no bribes remaining.");
        }

        if(this.health <= 0){
            return game.logicError(-1, "Warehouse has no hp.");
        }

        if(this.bribed){
            return game.logicError(-1, "Warehouse has already been bribed.");
        }

        if(this.owner !== player){
            return game.logicError(-1, "You do not control this Warehouse.");
        }

        var newFire = building.fire + this.fireAdded;
        var exposure = Math.abs(this.x - building.x) + Math.abs(this.y - building.y);

        this.exposure += exposure; //Do we want a cap on this?
        this.bribed = true;
        building.fire = Math.min(newFire, this.game.maxFire);
        player.bribesRemaining--;
        return exposure;

        // <<-- /Creer-Merge: ignite -->>
    },

    //<<-- Creer-Merge: added-functions -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

    // You can add additional functions here. These functions will not be directly callable by client AIs

    //<<-- /Creer-Merge: added-functions -->>

});

module.exports = Warehouse;
<commit_msg>Refactoring warehouse.ignite in b7e4eb700f23c8d2f4969bcf79d79da6e9b33cf3<commit_after>// Generated by Creer at 10:54PM on October 16, 2015 UTC, git hash: '98604e3773d1933864742cb78acbf6ea0b4ecd7b'

var Class = require(__basedir + "/utilities/class");
var serializer = require(__basedir + "/gameplay/serializer");
var log = require(__basedir + "/gameplay/log");
var Building = require("./building");

//<<-- Creer-Merge: requires -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

// any additional requires you want can be required here safely between cree runs
//<<-- /Creer-Merge: requires -->>

// @class Warehouse: A typical abandoned warehouse... that anarchists hang out in and can be bribed to burn down Buildings.
var Warehouse = Class(Building, {
    /**
     * Initializes Warehouses.
     *
     * @param {Object} a simple mapping passsed in to the constructor with whatever you sent with it.
     */
    init: function(data) {
        Building.init.apply(this, arguments);

        /**
         * How exposed the anarchists in this warehouse are to PoliceStations. Raises when bribed to ignite buildings, and drops each turn if not bribed.
         *
         * @type {number}
         */
        this._addProperty("exposure", serializer.defaultInteger(data.exposure));

        /**
         * The amount of fire added to buildings when bribed to ignite a building. Headquarters add more fire than normal Warehouses.
         *
         * @type {number}
         */
        this._addProperty("fireAdded", serializer.defaultInteger(data.fireAdded));

        //<<-- Creer-Merge: init -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

        // put any initialization logic here. the base variables should be set from 'data' above
        // NOTE: no players are connected (nor created) at this point. For that logic use 'begin()'

        //<<-- /Creer-Merge: init -->>
    },

    gameObjectName: "Warehouse",

    /**
     * Bribes the Warehouse to light a Building on fire. This adds this building's fireAdded to their fire, and then this building's exposure is increased based on the Manhatten distance between the two buildings.
     *
     * @param {Player} player - the player that called this.
     * @param {Building} building - The Building you want to light on fire.
     * @param {function} asyncReturn - if you nest orders in this function you must return that value via this function in the order's callback.
     * @returns {number} The exposure added to this Building's exposure. -1 is returned if there was an error.
     */
    ignite: function(player, building, asyncReturn) {
        // <<-- Creer-Merge: ignite -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

        if(player.bribesRemaining <= 0) {
            return game.logicError(-1, "Player has no bribes remaining.");
        }

        if(this.health <= 0) {
            return game.logicError(-1, "Warehouse has no hp.");
        }

        if(this.bribed) {
            return game.logicError(-1, "Warehouse has already been bribed.");
        }

        if(this.owner !== player) {
            return game.logicError(-1, "You do not control this Warehouse.");
        }

        var newFire = building.fire + this.fireAdded;
        var exposure = Math.abs(this.x - building.x) + Math.abs(this.y - building.y);

        this.exposure += exposure; //Do we want a cap on this?
        this.bribed = true;
        building.fire = Math.min(newFire, this.game.maxFire);
        player.bribesRemaining--;
        return exposure;

        // <<-- /Creer-Merge: ignite -->>
    },

    //<<-- Creer-Merge: added-functions -->> - Code you add between this comment and the end comment will be preserved between Creer re-runs.

    // You can add additional functions here. These functions will not be directly callable by client AIs

    //<<-- /Creer-Merge: added-functions -->>

});

module.exports = Warehouse;
<|endoftext|>


<commit_before>// Build include and exclude filesets for _Plato_ and _JSHint_ based on a
// common fileset format. Paths ending with a `/` are assumed to be a directory,
// all other paths are assumed to be a file. Individual files will be included
// or excluded as is. Directories will include or exclude all javascript files
// contained in them.

var util = require('util');
var async = require('async');
var chalk = require('chalk');

// By default we want to include everything and exclude nothing.

var includeFileset = [ './' ];
var excludeFileset = [ ];

// Directories are identified in filesets by virtue of having a trailing `/`.

function isDirectory(filename) {
    return filename.slice(-1) === '/';
}

// Filesets are validated by ensuring the fileset is an array and each item is a
// string. Valid filesets are applied, invalid ones are ignored.

function validateFileset(fileset, setter) {
    if (Array.isArray(fileset)) {
        async.each(fileset, function(path, callback) {
            if (typeof path === 'string') {
                callback();
            } else {
                callback(util.format('Invalid path: %s', path));
            }
        }, function(err) {
            if (err) {
                console.log(chalk.red(err));
            } else {
                setter(fileset);
            }
        });
    } else {
        console.log(chalk.red('Fileset is not an array: %j', fileset));
    }
}

function setIncludeFileset(fileset) {
    includeFileset = fileset;
}

function setExcludeFileset(fileset) {
    excludeFileset = fileset;
}

// The default filesets can be overridden using the `include` and `exclude`
// functions. If the fileset is invalid (i.e. not an array of strings) then an
// error is logged and the fileset will not be set.

function include(fileset) {

    validateFileset(fileset, setIncludeFileset);
}

function exclude(fileset) {
    validateFileset(fileset, setExcludeFileset);
}

// The plato include set is in the same format as our include set.

function platoIncludes() {
    return includeFileset;
}

// Plato uses a regular expression to exclude files so turn the list of exclude
// files into a properly formatted, pipe delimited list of files.

function platoExcludes() {
    var excludes = '';
    excludeFileset.forEach(function (file) {
        if (isDirectory(file)) {
            excludes += file.replace(/\//g, '\/');
        } else {
            excludes += file;
        }
        excludes += '|';
    });

    return new RegExp(excludes.slice(0, -1));
}

// JS Hint uses a globbing format for both include and exclude filesets. Files
// are added as is, directories are added using `**/*.js` which includes all
// Javascript files in all subdirectories.

function jshintFileset(fileset) {
    var files = [];
    fileset.forEach(function (file) {
        if (isDirectory(file)) {
            files.push(file + '**/*.js');
        } else {
            files.push(file);
        }
    });

    return files;
}

function jshintIncludes() {
    return jshintFileset(includeFileset);
}

function jshintExcludes() {
    return jshintFileset(excludeFileset);
}

module.exports.include = include;
module.exports.exclude = exclude;
module.exports.platoIncludes = platoIncludes;
module.exports.platoExcludes = platoExcludes;
module.exports.jshintIncludes = jshintIncludes;
module.exports.jshintExcludes = jshintExcludes;<commit_msg>Alter default filesets to something more sensible<commit_after>// Build include and exclude filesets for _Plato_ and _JSHint_ based on a
// common fileset format. Paths ending with a `/` are assumed to be a directory,
// all other paths are assumed to be a file. Individual files will be included
// or excluded as is. Directories will include or exclude all javascript files
// contained in them.

var util = require('util');
var async = require('async');
var chalk = require('chalk');

// By default include `lib`, `index.js` and `app.js`. Exclude `node_modules` and
// `reports`.

var includeFileset = [ './lib/' ];
var excludeFileset = [ './node_modules/', './reports/' ];

// Directories are identified in filesets by virtue of having a trailing `/`.

function isDirectory(filename) {
    return filename.slice(-1) === '/'
}

// Filesets are validated by ensuring the fileset is an array and each item is a
// string. Valid filesets are applied, invalid ones are ignored.

function validateFileset(fileset, setter) {
    if (Array.isArray(fileset)) {
        async.each(fileset, function(path, callback) {
            if (typeof path === 'string') {
                callback();
            } else {
                callback(util.format('Invalid path: %s', path));
            }
        }, function(err) {
            if (err) {
                console.log(chalk.red(err));
            } else {
                setter(fileset);
            }
        });
    } else {
        console.log(chalk.red('Fileset is not an array: %j', fileset));
    }
}

function setIncludeFileset(fileset) {
    includeFileset = fileset;
}

function setExcludeFileset(fileset) {
    excludeFileset = fileset;
}

// The default filesets can be overridden using the `include` and `exclude`
// functions. If the fileset is invalid (i.e. not an array of strings) then an
// error is logged and the fileset will not be set.

function include(fileset) {

    validateFileset(fileset, setIncludeFileset);
}

function exclude(fileset) {
    validateFileset(fileset, setExcludeFileset);
}

// The plato include set is in the same format as our include set.

function platoIncludes() {
    return includeFileset;
}

// Plato uses a regular expression to exclude files so turn the list of exclude
// files into a properly formatted, pipe delimited list of files.

function platoExcludes() {
    var excludes = '';
    excludeFileset.forEach(function (file) {
        if (isDirectory(file)) {
            excludes += file.replace(/\//g, '\/');
        } else {
            excludes += file;
        }
        excludes += '|';
    });

    return new RegExp(excludes.slice(0, -1));
}

// JS Hint uses a globbing format for both include and exclude filesets. Files
// are added as is, directories are added using `**/*.js` which includes all
// Javascript files in all subdirectories.

function jshintFileset(fileset) {
    var files = [];
    fileset.forEach(function (file) {
        if (isDirectory(file)) {
            files.push(file + '**/*.js');
        } else {
            files.push(file);
        }
    });

    return files;
}

function jshintIncludes() {
    return jshintFileset(includeFileset);
}

function jshintExcludes() {
    return jshintFileset(excludeFileset);
}

module.exports.include = include;
module.exports.exclude = exclude;
module.exports.platoIncludes = platoIncludes;
module.exports.platoExcludes = platoExcludes;
module.exports.jshintIncludes = jshintIncludes;
module.exports.jshintExcludes = jshintExcludes;<|endoftext|>


<commit_before>/**
 * Created by oleksiy.rudenko on 02/04/2016.
 */
(function(){

    angular
        .module('app')
        .controller('AppController', AppController);

    AppController.$inject=[ // 'appService',
        '$scope', 'userService', '$mdSidenav',
        '$mdBottomSheet', '$log', '$q',
        '$mdDialog', '$mdMedia',
    ];

    /**
     * Main Controller for the TaxRet App
     * @param $scope
     * @param userService
     * @param $mdSidenav
     * @param $mdBottomSheet
     * @param $log
     * @param $q
     * @param $mdDialog
     * @param $mdMedia
     * @constructor
     */
    function AppController( // appService,
                            $scope,
                            userService, $mdSidenav, $mdBottomSheet, $log, $q,
                            $mdDialog, $mdMedia) {
        /* jshint validthis: true */
        var vm = this;
        vm.userService = userService; // ?
        $scope.selectedTab = 0; // to use in tabbed context -- switch to initial tab, where selected item expected to be

        vm.states     = [
            {
                sref    :   'payroll',
                icon    :   '',
                title   :   'Доходи ФО',
            },
            {
                sref    :   'transport',
                icon    :   '',
                title   :   'Транспортні засоби',
            },
            {
                sref    :   'realestate',
                icon    :   '',
                title   :   'Нерухомість',
            },
            {
                sref    :   'funds',
                icon    :   '',
                title   :   'Фондові активи',
            },
            {
                sref    :   'foreignfee',
                icon    :   '',
                title   :   'Зарубіжні доходи',
            },
            {
                sref    :   'entrepreneur',
                icon    :   '',
                title   :   'Доходи ФОП',
            },
            {
                sref    :   'expenseexempt',
                icon    :   '',
                title   :   'Пільгові витрати',
                hr      :   true,
            },
            {
                sref    :   'docUserManual',
                icon    :   '',
                title   :   'Керівництво користувача',
            },
            {
                sref    :   'docAbout',
                icon    :   '',
                title   :   'Про проект',
                hr      :   true,
            },
            {
                sref    :   'docDev',
                icon    :   '',
                title   :   'Розробникам',
            }
        ];

        vm.currDeclarant    = vm.userService.getDeclarantCurrent(); // null
        vm.users            = [ ];
        vm.selectUser       = selectUser;
        vm.toggleSideNav    = toggleSideNav;
        vm.makeContact      = makeContact;

        // Load all registered users

        vm.userService
            .loadAllUsers()
            .then( function( users ) {
                vm.users    = [].concat(users);
                // vm.currDeclarant = userService.getDeclarantCurrent();
            });

        // *********************************
        // Internal methods
        // *********************************

        /**
         * Hide or Show the 'left' sideNav area
         */
        function toggleSideNav() {
            $mdSidenav('left').toggle();
        }

        /**
         * Select the current avatars
         * @param user
         */
        function selectUser ( user ) {
            user = angular.isNumber(user) ? $scope.users[user] : user;
            vm.currDeclarant = user;
            userService.setDeclarantCurrent(user);
            $scope.selectedTab = 0;
        }

        // ================= Pop-up dialog fn set
        $scope.status = '  ';
        $scope.customFullscreen = $mdMedia('xs') || $mdMedia('sm');
        $scope.ChooseAvatarDialog = function(ev,avatarid) {

          var useFullScreen = ($mdMedia('sm') || $mdMedia('xs'))  && $scope.customFullscreen;
          // alert("Asked for me?");
          $mdDialog.show({
              controller: DialogController,
              templateUrl: 'src/users/view/dialog.app.ChooseAvatar.html',
              parent: angular.element(document.body),
              targetEvent: ev,
              clickOutsideToClose:false,
              fullscreen: useFullScreen
            })
            .then(function(answer) {
              $scope.status = 'You said the information was "' + answer + '".';
            }, function() {
              $scope.status = 'You cancelled the dialog.';
            });
          $scope.$watch(function() {
            return $mdMedia('xs') || $mdMedia('sm');
          }, function(wantsFullScreen) {
            $scope.customFullscreen = (wantsFullScreen === true);
          });
        };

        function DialogController($scope, $mdDialog) {
          // $scope.UserAvaGridController = UserAvaGridController;
          $scope.hide = function() {
            $mdDialog.hide();
          };
          $scope.cancel = function() {
            $mdDialog.cancel();
          };
          $scope.answer = function(answer) {
            $mdDialog.hide(answer);
          };
        }

        // ================== AvaGrid

        /**
         * Show the Contact view in the bottom sheet
         */
        function makeContact(selectedUser) {

            $mdBottomSheet.show({
                controllerAs  : "cp",
                templateUrl   : './src/users/view/contactSheet.html',
                controller    : [ '$mdBottomSheet', ContactSheetController],
                parent        : angular.element(document.getElementById('content'))
            }).then(function(clickedItem) {
                $log.debug( clickedItem.name + ' clicked!');
            });

            /**
             * User ContactSheet controller
             */
            function ContactSheetController( $mdBottomSheet ) {
                this.user = selectedUser;
                this.actions = [
                    { name: 'Phone'       , icon: 'phone'       , icon_url: 'assets/svg/phone.svg'},
                    { name: 'Twitter'     , icon: 'twitter'     , icon_url: 'assets/svg/twitter.svg'},
                    { name: 'Google+'     , icon: 'google_plus' , icon_url: 'assets/svg/google_plus.svg'},
                    { name: 'Hangout'     , icon: 'hangouts'    , icon_url: 'assets/svg/hangouts.svg'}
                ];
                this.contactUser = function(action) {
                    // The actually contact process has not been implemented...
                    // so just hide the bottomSheet

                    $mdBottomSheet.hide(action);
                };
            }
        }

    }

})();<commit_msg>Make anonymous function named<commit_after>/**
 * Created by oleksiy.rudenko on 02/04/2016.
 */
(function(){

    angular
        .module('app')
        .controller('AppController', AppController);

    AppController.$inject=[ // 'appService',
        '$scope', 'userService', '$mdSidenav',
        '$mdBottomSheet', '$log', '$q',
        '$mdDialog', '$mdMedia',
    ];

    /**
     * Main Controller for the TaxRet App
     * @param $scope
     * @param userService
     * @param $mdSidenav
     * @param $mdBottomSheet
     * @param $log
     * @param $q
     * @param $mdDialog
     * @param $mdMedia
     * @constructor
     */
    function AppController( // appService,
                            $scope,
                            userService, $mdSidenav, $mdBottomSheet, $log, $q,
                            $mdDialog, $mdMedia) {
        /* jshint validthis: true */
        var vm = this;
        vm.userService = userService; // ?
        $scope.selectedTab = 0; // to use in tabbed context -- switch to initial tab, where selected item expected to be

        vm.states     = [
            {
                sref    :   'payroll',
                icon    :   '',
                title   :   'Доходи ФО',
            },
            {
                sref    :   'transport',
                icon    :   '',
                title   :   'Транспортні засоби',
            },
            {
                sref    :   'realestate',
                icon    :   '',
                title   :   'Нерухомість',
            },
            {
                sref    :   'funds',
                icon    :   '',
                title   :   'Фондові активи',
            },
            {
                sref    :   'foreignfee',
                icon    :   '',
                title   :   'Зарубіжні доходи',
            },
            {
                sref    :   'entrepreneur',
                icon    :   '',
                title   :   'Доходи ФОП',
            },
            {
                sref    :   'expenseexempt',
                icon    :   '',
                title   :   'Пільгові витрати',
                hr      :   true,
            },
            {
                sref    :   'docUserManual',
                icon    :   '',
                title   :   'Керівництво користувача',
            },
            {
                sref    :   'docAbout',
                icon    :   '',
                title   :   'Про проект',
                hr      :   true,
            },
            {
                sref    :   'docDev',
                icon    :   '',
                title   :   'Розробникам',
            }
        ];

        vm.currDeclarant    = vm.userService.getDeclarantCurrent(); // null
        vm.users            = [ ];
        vm.selectUser       = selectUser;
        vm.toggleSideNav    = toggleSideNav;
        vm.makeContact      = makeContact;

        // Load all registered users

        vm.userService
            .loadAllUsers()
            .then( function( users ) {
                vm.users    = [].concat(users);
                // vm.currDeclarant = userService.getDeclarantCurrent();
            });

        // *********************************
        // Internal methods
        // *********************************

        /**
         * Hide or Show the 'left' sideNav area
         */
        function toggleSideNav() {
            $mdSidenav('left').toggle();
        }

        /**
         * Select the current avatars
         * @param user
         */
        function selectUser ( user ) {
            user = angular.isNumber(user) ? $scope.users[user] : user;
            vm.currDeclarant = user;
            userService.setDeclarantCurrent(user);
            $scope.selectedTab = 0;
        }

        // ================= Pop-up dialog fn set
        $scope.status = '  ';
        $scope.customFullscreen = $mdMedia('xs') || $mdMedia('sm');
        $scope.ChooseAvatarDialog =   ChooseAvatarDialog;

        function ChooseAvatarDialog(ev,avatarid) {
          var useFullScreen = ($mdMedia('sm') || $mdMedia('xs'))  && $scope.customFullscreen;
          // alert("Asked for me?");
          $mdDialog.show({
              controller: DialogController,
              templateUrl: 'src/users/view/dialog.app.ChooseAvatar.html',
              parent: angular.element(document.body),
              targetEvent: ev,
              clickOutsideToClose:false,
              fullscreen: useFullScreen
            })
            .then(function(answer) {
              $scope.status = 'You said the information was "' + answer + '".';
            }, function() {
              $scope.status = 'You cancelled the dialog.';
            });
          $scope.$watch(function() {
            return $mdMedia('xs') || $mdMedia('sm');
          }, function(wantsFullScreen) {
            $scope.customFullscreen = (wantsFullScreen === true);
          });
        };

        function DialogController($scope, $mdDialog) {
          // $scope.UserAvaGridController = UserAvaGridController;
          $scope.hide = function() {
            $mdDialog.hide();
          };
          $scope.cancel = function() {
            $mdDialog.cancel();
          };
          $scope.answer = function(answer) {
            $mdDialog.hide(answer);
          };
        }

        // ================== AvaGrid

        /**
         * Show the Contact view in the bottom sheet
         */
        function makeContact(selectedUser) {

            $mdBottomSheet.show({
                controllerAs  : "cp",
                templateUrl   : './src/users/view/contactSheet.html',
                controller    : [ '$mdBottomSheet', ContactSheetController],
                parent        : angular.element(document.getElementById('content'))
            }).then(function(clickedItem) {
                $log.debug( clickedItem.name + ' clicked!');
            });

            /**
             * User ContactSheet controller
             */
            function ContactSheetController( $mdBottomSheet ) {
                this.user = selectedUser;
                this.actions = [
                    { name: 'Phone'       , icon: 'phone'       , icon_url: 'assets/svg/phone.svg'},
                    { name: 'Twitter'     , icon: 'twitter'     , icon_url: 'assets/svg/twitter.svg'},
                    { name: 'Google+'     , icon: 'google_plus' , icon_url: 'assets/svg/google_plus.svg'},
                    { name: 'Hangout'     , icon: 'hangouts'    , icon_url: 'assets/svg/hangouts.svg'}
                ];
                this.contactUser = function(action) {
                    // The actually contact process has not been implemented...
                    // so just hide the bottomSheet

                    $mdBottomSheet.hide(action);
                };
            }
        }

    }

})();<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var process = require('process');
process.title = 'nodejs-benchmarks-bench_server';

var parseArgs = require('minimist');
var assert = require('assert');
var Statsd = require('uber-statsd-client');

var Reporter = require('../tcollector/reporter.js');
var TChannel = require('../channel');
var RandomSample = require('./random_sample.js');

var argv = parseArgs(process.argv.slice(2), {
    boolean: ['trace'],
    default: {
        pingOverhead: 'none',
        setOverhead: 'none',
        getOverhead: 'none'
    }
});

assert(argv.port, 'port needed');
assert(argv.instances, 'instances needed');

var overhead = {};
overhead.ping = parseOverhead(argv.pingOverhead);
overhead.set = parseOverhead(argv.setOverhead);
overhead.get = parseOverhead(argv.getOverhead);

assert('trace' in argv, 'trace option needed');
if (argv.trace) {
    assert(argv.traceRelayHostPort, 'traceRelayHostPort needed');
}

var INSTANCES = parseInt(argv.instances, 10);

function BenchServer(port) {
    if (!(this instanceof BenchServer)) {
        return new BenchServer(port);
    }

    var self = this;

    self.port = port;
    self.server = TChannel({
        statTags: {
            app: 'my-server'
        },
        trace: true,
        emitConnectionMetrics: false,
        statsd: new Statsd({
            host: '127.0.0.1',
            port: 7036
        })
    });

    if (argv.trace) {
        self.setupReporter();
    }

    self.serverChan = self.server.makeSubChannel({
        serviceName: 'benchmark'
    });

    self.keys = {};

    self.registerEndpoints();
}

BenchServer.prototype.setupReporter = function setupReporter() {
    var self = this;

    var reporter = Reporter({
        channel: self.server.makeSubChannel({
            serviceName: 'tcollector',
            peers: [argv.traceRelayHostPort]
        }),
        logger: self.server.logger,
        callerName: 'my-server'
    });

    self.server.tracer.reporter = function report(span) {
        reporter.report(span, {
            timeout: 10 * 1000
        });
    };
};

BenchServer.prototype.registerEndpoints = function registerEndpoints() {
    var self = this;

    if (overhead.ping) {
        onPing = withDelay(onPing, overhead.ping);
    }
    if (overhead.set) {
        onSet = withDelay(onSet, overhead.set);
    }
    if (overhead.get) {
        onGet = withDelay(onGet, overhead.get);
    }

    self.serverChan.register('ping', onPing);
    self.serverChan.register('set', onSet);
    self.serverChan.register('get', onGet);
    self.serverChan.register('bad', onBad);

    function onPing(req, res) {
        res.headers.as = 'raw';
        res.sendOk('pong', null);
    }

    function onSet(req, res, arg2, arg3) {
        var key = arg2.toString('utf8');
        var val = arg3.toString('utf8');
        self.keys[key] = val;
        res.headers.as = 'raw';
        res.sendOk('ok', 'really ok');
    }

    function onGet(req, res, arg2, arg3) {
        var key = arg2.toString('utf8');
        res.headers.as = 'raw';
        if (self.keys[key] !== undefined) {
            var val = self.keys[key];
            res.sendOk(val.length.toString(10), val);
        } else {
            res.sendNotOk('key not found', key);
        }
    }

    function onBad(req, res, arg2, arg3) {
        res.headers.as = 'raw';
        res.sendError('BadRequest', 'parse error');
    }
};

BenchServer.prototype.listen = function listen() {
    var self = this;

    self.server.listen(self.port, '127.0.0.1');
};

for (var i = 0; i < INSTANCES; i++) {
    var port = parseInt(argv.port, 10) + i;

    var benchServer = BenchServer(port);
    benchServer.listen();
}

function parseOverhead(str) {
    if (str === 'none') {
        return null;
    } else {
        return RandomSample.fromString(str);
    }
}

function withDelay(handler, delay) {
    return delayedHandler;

    function delayedHandler(req, res, arg2, arg3) {
        var t = delay();
        setTimeout(runHandler, t);
        function runHandler() {
            handler(req, res, arg2, arg3);
        }
    }
}

// setInterval(function () {
//  Object.keys(keys).forEach(function (key) {
//      console.log(key + '=' + keys[key].length + ' bytes');
//  });
// }, 1000);
<commit_msg>benchmarks: bad_set and bad_get<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var process = require('process');
process.title = 'nodejs-benchmarks-bench_server';

var parseArgs = require('minimist');
var assert = require('assert');
var Statsd = require('uber-statsd-client');

var Reporter = require('../tcollector/reporter.js');
var TChannel = require('../channel');
var RandomSample = require('./random_sample.js');

var argv = parseArgs(process.argv.slice(2), {
    boolean: ['trace'],
    default: {
        pingOverhead: 'none',
        setOverhead: 'none',
        getOverhead: 'none'
    }
});

assert(argv.port, 'port needed');
assert(argv.instances, 'instances needed');

var overhead = {};
overhead.ping = parseOverhead(argv.pingOverhead);
overhead.set = parseOverhead(argv.setOverhead);
overhead.get = parseOverhead(argv.getOverhead);

assert('trace' in argv, 'trace option needed');
if (argv.trace) {
    assert(argv.traceRelayHostPort, 'traceRelayHostPort needed');
}

var INSTANCES = parseInt(argv.instances, 10);

function BenchServer(port) {
    if (!(this instanceof BenchServer)) {
        return new BenchServer(port);
    }

    var self = this;

    self.port = port;
    self.server = TChannel({
        statTags: {
            app: 'my-server'
        },
        trace: true,
        emitConnectionMetrics: false,
        statsd: new Statsd({
            host: '127.0.0.1',
            port: 7036
        })
    });

    if (argv.trace) {
        self.setupReporter();
    }

    self.serverChan = self.server.makeSubChannel({
        serviceName: 'benchmark'
    });

    self.keys = {};

    self.registerEndpoints();
}

BenchServer.prototype.setupReporter = function setupReporter() {
    var self = this;

    var reporter = Reporter({
        channel: self.server.makeSubChannel({
            serviceName: 'tcollector',
            peers: [argv.traceRelayHostPort]
        }),
        logger: self.server.logger,
        callerName: 'my-server'
    });

    self.server.tracer.reporter = function report(span) {
        reporter.report(span, {
            timeout: 10 * 1000
        });
    };
};

BenchServer.prototype.registerEndpoints = function registerEndpoints() {
    var self = this;

    if (overhead.ping) {
        onPing = withDelay(onPing, overhead.ping);
    }
    if (overhead.set) {
        onSet = withDelay(onSet, overhead.set);
    }
    if (overhead.get) {
        onGet = withDelay(onGet, overhead.get);
    }

    self.serverChan.register('ping', onPing);
    self.serverChan.register('set', onSet);
    self.serverChan.register('get', onGet);

    self.serverChan.register('bad_set', onBad);
    self.serverChan.register('bad_get', onBad);

    function onPing(req, res) {
        res.headers.as = 'raw';
        res.sendOk('pong', null);
    }

    function onSet(req, res, arg2, arg3) {
        var key = arg2.toString('utf8');
        var val = arg3.toString('utf8');
        self.keys[key] = val;
        res.headers.as = 'raw';
        res.sendOk('ok', 'really ok');
    }

    function onGet(req, res, arg2, arg3) {
        var key = arg2.toString('utf8');
        res.headers.as = 'raw';
        if (self.keys[key] !== undefined) {
            var val = self.keys[key];
            res.sendOk(val.length.toString(10), val);
        } else {
            res.sendNotOk('key not found', key);
        }
    }

    function onBad(req, res, arg2, arg3) {
        res.headers.as = 'raw';
        res.sendError('BadRequest', 'parse error');
    }
};

BenchServer.prototype.listen = function listen() {
    var self = this;

    self.server.listen(self.port, '127.0.0.1');
};

for (var i = 0; i < INSTANCES; i++) {
    var port = parseInt(argv.port, 10) + i;

    var benchServer = BenchServer(port);
    benchServer.listen();
}

function parseOverhead(str) {
    if (str === 'none') {
        return null;
    } else {
        return RandomSample.fromString(str);
    }
}

function withDelay(handler, delay) {
    return delayedHandler;

    function delayedHandler(req, res, arg2, arg3) {
        var t = delay();
        setTimeout(runHandler, t);
        function runHandler() {
            handler(req, res, arg2, arg3);
        }
    }
}

// setInterval(function () {
//  Object.keys(keys).forEach(function (key) {
//      console.log(key + '=' + keys[key].length + ' bytes');
//  });
// }, 1000);
<|endoftext|>