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

goog.provide('shaka.test.TestScheme');

/**
 * A plugin that handles fake network requests.  This will serve both segments
 * and manifests that will point to a fake manifest generator.
 *
 * @param {string} uri
 * @param {shakaExtern.Request} request
 * @return {!Promise.<shakaExtern.Response>}
 */
shaka.test.TestScheme = function(uri, request) {
  var manifestParts = /^test:([^\/]+)$/.exec(uri);
  if (manifestParts) {
    /** @type {shakaExtern.Response} */
    var response = {
      uri: uri,
      data: new ArrayBuffer(0),
      headers: {'content-type': 'application/x-test-manifest'}
    };
    return Promise.resolve(response);
  }

  var re = /^test:([^\/]+)\/(video|audio)\/(init|[0-9]+)$/;
  var segmentParts = re.exec(uri);
  if (!segmentParts) {
    // Use expect so the URI is printed on errors.
    expect(uri).toMatch(re);
    return Promise.reject();
  }

  var name = segmentParts[1];
  var type = segmentParts[2];
  var generators = shaka.test.TestScheme.GENERATORS[name];
  expect(generators).toBeTruthy();
  if (!generators) return Promise.reject();

  var generator = generators[type];
  expect(generator).toBeTruthy();
  if (!generator) return Promise.reject();

  var responseData;
  if (segmentParts[3] === 'init') {
    responseData = generator.getInitSegment(0);
  } else {
    var index = Number(segmentParts[3]);
    responseData = generator.getSegment(index + 1, 0, 0);
  }

  var ret = {uri: uri, data: responseData, headers: {}};
  // Cannot use |Promise.resolve(ret)| because of a compiler bug.
  // https://goo.gl/4TdteC
  return Promise.resolve().then(function() { return ret; });
};

/** @const {!Object.<string, shakaExtern.Manifest>} */
shaka.test.TestScheme.MANIFESTS = {};

/** @const {!Object.<string, !Object.<string, !shaka.test.IStreamGenerator>>} */
shaka.test.TestScheme.GENERATORS = {};

/** @const */
shaka.test.TestScheme.DATA = {
  'sintel': {
    video: {
      initSegmentUri: '/base/test/test/assets/sintel-video-init.mp4',
      mvhdOffset: 0x24,
      segmentUri: '/base/test/test/assets/sintel-video-segment.mp4',
      tfdtOffset: 0x38,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codec: 'avc1.42c01e'
    },
    audio: {
      initSegmentUri: '/base/test/test/assets/sintel-audio-init.mp4',
      mvhdOffset: 0x20,
      segmentUri: '/base/test/test/assets/sintel-audio-segment.mp4',
      tfdtOffset: 0x3c,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codec: 'mp4a.40.2'
    },
    text: {
      uri: '/base/test/test/assets/text-clip.vtt',
      mimeType: 'text/vtt'
    },
    // TODO: Allow changing the duration so StreamingEngine test can use this.
    duration: 30
  },
  'sintel-enc': {
    video: {
      initSegmentUri: '/base/test/test/assets/encrypted-sintel-video-init.mp4',
      mvhdOffset: 0x24,
      segmentUri: '/base/test/test/assets/encrypted-sintel-video-segment.mp4',
      tfdtOffset: 0x38,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codec: 'avc1.42c01e',
      initData:
          'AAAAc3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFMIARIQaKzMBtasU1iYiGwe' +
          'MeC/ORIQPgfUgWF6UGqdIm5yx/XJtxIQRC1g0g+tXe6lxz4ABfHDnhoNd2lkZXZp' +
          'bmVfdGVzdCIIzsW/9dxA3ckyAA=='
    },
    audio: {
      initSegmentUri: '/base/test/test/assets/encrypted-sintel-audio-init.mp4',
      mvhdOffset: 0x20,
      segmentUri: '/base/test/test/assets/encrypted-sintel-audio-segment.mp4',
      tfdtOffset: 0x3c,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codec: 'mp4a.40.2',
      initData:
          'AAAAc3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFMIARIQaKzMBtasU1iYiGwe' +
          'MeC/ORIQPgfUgWF6UGqdIm5yx/XJtxIQRC1g0g+tXe6lxz4ABfHDnhoNd2lkZXZp' +
          'bmVfdGVzdCIIzsW/9dxA3ckyAA=='
    },
    text: {
      uri: '/base/test/test/assets/text-clip.vtt',
      mimeType: 'text/vtt'
    },
    licenseServers: {
      'com.widevine.alpha': '//widevine-proxy.appspot.com/proxy'
    },
    duration: 30
  },
  'multidrm': {
    video: {
      initSegmentUri: '/base/test/test/assets/multidrm-video-init.mp4',
      mvhdOffset: 0x72,
      segmentUri: '/base/test/test/assets/multidrm-video-segment.mp4',
      tfdtOffset: 0x78,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codec: 'avc1.64001e',
      initData:
          'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQblodJidXR9eARuq' +
          'l0dNLWg=='
    },
    audio: {
      initSegmentUri: '/base/test/test/assets/multidrm-audio-init.mp4',
      mvhdOffset: 0x72,
      segmentUri: '/base/test/test/assets/multidrm-audio-segment.mp4',
      tfdtOffset: 0x7c,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codec: 'mp4a.40.2',
      initData:
          'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQblodJidXR9eARuq' +
          'l0dNLWg=='
    },
    text: {
      uri: '/base/test/test/assets/text-clip.vtt',
      mimeType: 'text/vtt'
    },
    licenseServers: {
      'com.widevine.alpha':
          '//drm-widevine-licensing.axtest.net/AcquireLicense',
      'com.microsoft.playready':
          '//drm-playready-licensing.axtest.net/AcquireLicense'
    },
    licenseRequestHeaders: {
      'X-AxDRM-Message':
          'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5' +
          'X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc' +
          '2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIj' +
          'oiNmU1YTFkMjYtMjc1Ny00N2Q3LTgwNDYtZWFhNWQxZDM0YjVhIn1dfX0.yF7PflO' +
          'Pv9qHnu3ZWJNZ12jgkqTabmwXbDWk_47tLNE'
    },
    duration: 30
  }
};

/**
 * Sets up the networking callbacks required to play the given asset.
 *
 * @param {!shaka.Player} player
 * @param {string} name
 */
shaka.test.TestScheme.setupPlayer = function(player, name) {
  var asset = shaka.test.TestScheme.DATA[name];
  goog.asserts.assert(asset, 'Unknown asset');
  if (!asset) return;
  if (asset.licenseRequestHeaders) {
    player.getNetworkingEngine().registerRequestFilter(
        function(type, request) {
          if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) return;

          for (var header in asset.licenseRequestHeaders) {
            request.headers[header] = asset.licenseRequestHeaders[header];
          }
        });
  }
  if (asset.licenseServers) {
    var config = /** @type {shakaExtern.PlayerConfiguration} */ (
        {drm: {servers: asset.licenseServers}});
    player.configure(config);
  }
};

/**
 * Creates the manifests and generators.
 * @param {*} shaka
 * @param {string} suffix
 * @return {!Promise}
 */
shaka.test.TestScheme.createManifests = function(shaka, suffix) {
  function createStreamGenerator(metadata, duration) {
    return new window.shaka.test.DashVodStreamGenerator(
        metadata.initSegmentUri, metadata.mvhdOffset, metadata.segmentUri,
        metadata.tfdtOffset, metadata.segmentDuration,
        metadata.presentationTimeOffset, duration);
  }

  var async = [];
  var DATA = window.shaka.test.TestScheme.DATA;
  var GENERATORS = window.shaka.test.TestScheme.GENERATORS;
  var MANIFESTS = window.shaka.test.TestScheme.MANIFESTS;
  for (var name in DATA) {
    GENERATORS[name + suffix] = GENERATORS[name + suffix] || {};
    var data = DATA[name];
    ['video', 'audio'].forEach(function(type) {
      var streamGen = createStreamGenerator(data[type], data.duration);
      GENERATORS[name + suffix][type] = streamGen;
      async.push(streamGen.init());
    });

    var gen = new window.shaka.test.ManifestGenerator(shaka)
        .setPresentationDuration(data.duration)
        .addPeriod(0);
    ['audio', 'video'].forEach(function(type, i) {
      gen.addStreamSet(type)
          .addStream(i)
            .presentationTimeOffset(data[type].presentationTimeOffset)
            .mime(data[type].mimeType, data[type].codec)
            .initSegmentReference(
                  ['test:' + name + '/' + type + '/init'], 0, null)
            .useSegmentTemplate('test:' + name + '/' + type + '/%d',
                                data[type].segmentDuration);

      if (data.licenseServers) {
        for (var keySystem in data.licenseServers) {
          gen.addDrmInfo(keySystem)
              .licenseServerUri(data.licenseServers[keySystem]);
          if (data[type].initData) {
            gen.addCencInitData(data[type].initData);
          }
        }
      }
    });
    gen.addStreamSet('text')
        .addStream(2)
          .mime(data.text.mimeType, data.text.codec)
          .textStream(data.text.uri);

    MANIFESTS[name + suffix] = gen.build();
  }

  return Promise.all(async);
};

beforeAll(function(done) {
  shaka.test.TestScheme.createManifests(shaka, '').catch(fail).then(done);
});

/**
 * @constructor
 * @struct
 * @implements {shakaExtern.ManifestParser}
 */
shaka.test.TestScheme.ManifestParser = function() {};

/** @override */
shaka.test.TestScheme.ManifestParser.prototype.configure = function(config) {};

/** @override */
shaka.test.TestScheme.ManifestParser.prototype.start = function(uri) {
  var re = /^test:([^\/]+)$/;
  var manifestParts = re.exec(uri);
  if (!manifestParts) {
    // Use expect so the URI is printed on errors.
    expect(uri).toMatch(re);
    return Promise.reject();
  }

  var manifest = shaka.test.TestScheme.MANIFESTS[manifestParts[1]];
  expect(manifest).toBeTruthy();
  if (!manifest) return Promise.reject();

  return Promise.resolve(manifest);
};

/** @override */
shaka.test.TestScheme.ManifestParser.prototype.stop = function() {
  return Promise.resolve();
};

shaka.net.NetworkingEngine.registerScheme('test', shaka.test.TestScheme);
shaka.media.ManifestParser.registerParserByMime(
    'application/x-test-manifest', shaka.test.TestScheme.ManifestParser);

<commit_msg>Fix failure to load test vtt stream on Safari<commit_after>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * 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.
 */

goog.provide('shaka.test.TestScheme');

/**
 * A plugin that handles fake network requests.  This will serve both segments
 * and manifests that will point to a fake manifest generator.
 *
 * @param {string} uri
 * @param {shakaExtern.Request} request
 * @return {!Promise.<shakaExtern.Response>}
 */
shaka.test.TestScheme = function(uri, request) {
  var manifestParts = /^test:([^\/]+)$/.exec(uri);
  if (manifestParts) {
    /** @type {shakaExtern.Response} */
    var response = {
      uri: uri,
      data: new ArrayBuffer(0),
      headers: {'content-type': 'application/x-test-manifest'}
    };
    return Promise.resolve(response);
  }

  var re = /^test:([^\/]+)\/(video|audio)\/(init|[0-9]+)$/;
  var segmentParts = re.exec(uri);
  if (!segmentParts) {
    // Use expect so the URI is printed on errors.
    expect(uri).toMatch(re);
    return Promise.reject();
  }

  var name = segmentParts[1];
  var type = segmentParts[2];
  var generators = shaka.test.TestScheme.GENERATORS[name];
  expect(generators).toBeTruthy();
  if (!generators) return Promise.reject();

  var generator = generators[type];
  expect(generator).toBeTruthy();
  if (!generator) return Promise.reject();

  var responseData;
  if (segmentParts[3] === 'init') {
    responseData = generator.getInitSegment(0);
  } else {
    var index = Number(segmentParts[3]);
    responseData = generator.getSegment(index + 1, 0, 0);
  }

  var ret = {uri: uri, data: responseData, headers: {}};
  // Cannot use |Promise.resolve(ret)| because of a compiler bug.
  // https://goo.gl/4TdteC
  return Promise.resolve().then(function() { return ret; });
};

/** @const {!Object.<string, shakaExtern.Manifest>} */
shaka.test.TestScheme.MANIFESTS = {};

/** @const {!Object.<string, !Object.<string, !shaka.test.IStreamGenerator>>} */
shaka.test.TestScheme.GENERATORS = {};

/** @const */
shaka.test.TestScheme.DATA = {
  'sintel': {
    video: {
      initSegmentUri: '/base/test/test/assets/sintel-video-init.mp4',
      mvhdOffset: 0x24,
      segmentUri: '/base/test/test/assets/sintel-video-segment.mp4',
      tfdtOffset: 0x38,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codec: 'avc1.42c01e'
    },
    audio: {
      initSegmentUri: '/base/test/test/assets/sintel-audio-init.mp4',
      mvhdOffset: 0x20,
      segmentUri: '/base/test/test/assets/sintel-audio-segment.mp4',
      tfdtOffset: 0x3c,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codec: 'mp4a.40.2'
    },
    text: {
      uri: '/base/test/test/assets/text-clip.vtt',
      mimeType: 'text/vtt'
    },
    // TODO: Allow changing the duration so StreamingEngine test can use this.
    duration: 30
  },
  'sintel-enc': {
    video: {
      initSegmentUri: '/base/test/test/assets/encrypted-sintel-video-init.mp4',
      mvhdOffset: 0x24,
      segmentUri: '/base/test/test/assets/encrypted-sintel-video-segment.mp4',
      tfdtOffset: 0x38,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codec: 'avc1.42c01e',
      initData:
          'AAAAc3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFMIARIQaKzMBtasU1iYiGwe' +
          'MeC/ORIQPgfUgWF6UGqdIm5yx/XJtxIQRC1g0g+tXe6lxz4ABfHDnhoNd2lkZXZp' +
          'bmVfdGVzdCIIzsW/9dxA3ckyAA=='
    },
    audio: {
      initSegmentUri: '/base/test/test/assets/encrypted-sintel-audio-init.mp4',
      mvhdOffset: 0x20,
      segmentUri: '/base/test/test/assets/encrypted-sintel-audio-segment.mp4',
      tfdtOffset: 0x3c,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codec: 'mp4a.40.2',
      initData:
          'AAAAc3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFMIARIQaKzMBtasU1iYiGwe' +
          'MeC/ORIQPgfUgWF6UGqdIm5yx/XJtxIQRC1g0g+tXe6lxz4ABfHDnhoNd2lkZXZp' +
          'bmVfdGVzdCIIzsW/9dxA3ckyAA=='
    },
    text: {
      uri: '/base/test/test/assets/text-clip.vtt',
      mimeType: 'text/vtt'
    },
    licenseServers: {
      'com.widevine.alpha': '//widevine-proxy.appspot.com/proxy'
    },
    duration: 30
  },
  'multidrm': {
    video: {
      initSegmentUri: '/base/test/test/assets/multidrm-video-init.mp4',
      mvhdOffset: 0x72,
      segmentUri: '/base/test/test/assets/multidrm-video-segment.mp4',
      tfdtOffset: 0x78,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'video/mp4',
      codec: 'avc1.64001e',
      initData:
          'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQblodJidXR9eARuq' +
          'l0dNLWg=='
    },
    audio: {
      initSegmentUri: '/base/test/test/assets/multidrm-audio-init.mp4',
      mvhdOffset: 0x72,
      segmentUri: '/base/test/test/assets/multidrm-audio-segment.mp4',
      tfdtOffset: 0x7c,
      segmentDuration: 10,
      presentationTimeOffset: 0,
      mimeType: 'audio/mp4',
      codec: 'mp4a.40.2',
      initData:
          'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQblodJidXR9eARuq' +
          'l0dNLWg=='
    },
    text: {
      uri: '/base/test/test/assets/text-clip.vtt',
      mimeType: 'text/vtt'
    },
    licenseServers: {
      'com.widevine.alpha':
          '//drm-widevine-licensing.axtest.net/AcquireLicense',
      'com.microsoft.playready':
          '//drm-playready-licensing.axtest.net/AcquireLicense'
    },
    licenseRequestHeaders: {
      'X-AxDRM-Message':
          'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5' +
          'X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc' +
          '2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIj' +
          'oiNmU1YTFkMjYtMjc1Ny00N2Q3LTgwNDYtZWFhNWQxZDM0YjVhIn1dfX0.yF7PflO' +
          'Pv9qHnu3ZWJNZ12jgkqTabmwXbDWk_47tLNE'
    },
    duration: 30
  }
};

/**
 * Sets up the networking callbacks required to play the given asset.
 *
 * @param {!shaka.Player} player
 * @param {string} name
 */
shaka.test.TestScheme.setupPlayer = function(player, name) {
  var asset = shaka.test.TestScheme.DATA[name];
  goog.asserts.assert(asset, 'Unknown asset');
  if (!asset) return;
  if (asset.licenseRequestHeaders) {
    player.getNetworkingEngine().registerRequestFilter(
        function(type, request) {
          if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) return;

          for (var header in asset.licenseRequestHeaders) {
            request.headers[header] = asset.licenseRequestHeaders[header];
          }
        });
  }
  if (asset.licenseServers) {
    var config = /** @type {shakaExtern.PlayerConfiguration} */ (
        {drm: {servers: asset.licenseServers}});
    player.configure(config);
  }
};

/**
 * Creates the manifests and generators.
 * @param {*} shaka
 * @param {string} suffix
 * @return {!Promise}
 */
shaka.test.TestScheme.createManifests = function(shaka, suffix) {
  function createStreamGenerator(metadata, duration) {
    return new window.shaka.test.DashVodStreamGenerator(
        metadata.initSegmentUri, metadata.mvhdOffset, metadata.segmentUri,
        metadata.tfdtOffset, metadata.segmentDuration,
        metadata.presentationTimeOffset, duration);
  }

  var async = [];
  var DATA = window.shaka.test.TestScheme.DATA;
  var GENERATORS = window.shaka.test.TestScheme.GENERATORS;
  var MANIFESTS = window.shaka.test.TestScheme.MANIFESTS;
  for (var name in DATA) {
    GENERATORS[name + suffix] = GENERATORS[name + suffix] || {};
    var data = DATA[name];
    ['video', 'audio'].forEach(function(type) {
      var streamGen = createStreamGenerator(data[type], data.duration);
      GENERATORS[name + suffix][type] = streamGen;
      async.push(streamGen.init());
    });

    var gen = new window.shaka.test.ManifestGenerator(shaka)
        .setPresentationDuration(data.duration)
        .addPeriod(0);
    ['audio', 'video'].forEach(function(type, i) {
      gen.addStreamSet(type)
          .addStream(i)
            .presentationTimeOffset(data[type].presentationTimeOffset)
            .mime(data[type].mimeType, data[type].codec)
            .initSegmentReference(
                  ['test:' + name + '/' + type + '/init'], 0, null)
            .useSegmentTemplate('test:' + name + '/' + type + '/%d',
                                data[type].segmentDuration);

      if (data.licenseServers) {
        for (var keySystem in data.licenseServers) {
          gen.addDrmInfo(keySystem)
              .licenseServerUri(data.licenseServers[keySystem]);
          if (data[type].initData) {
            gen.addCencInitData(data[type].initData);
          }
        }
      }
    });

    // This seems to be necessary.  Otherwise, we end up with a URL like
    // "http:/base/..." which then fails to load on Safari for some reason.
    var locationUri = new goog.Uri(location.href);
    var partialUri = new goog.Uri(data.text.uri);
    var absoluteUri = locationUri.resolve(partialUri);

    gen.addStreamSet('text')
        .addStream(2)
          .mime(data.text.mimeType, data.text.codec)
          .textStream(absoluteUri.toString());

    MANIFESTS[name + suffix] = gen.build();
  }

  return Promise.all(async);
};

beforeAll(function(done) {
  shaka.test.TestScheme.createManifests(shaka, '').catch(fail).then(done);
});

/**
 * @constructor
 * @struct
 * @implements {shakaExtern.ManifestParser}
 */
shaka.test.TestScheme.ManifestParser = function() {};

/** @override */
shaka.test.TestScheme.ManifestParser.prototype.configure = function(config) {};

/** @override */
shaka.test.TestScheme.ManifestParser.prototype.start = function(uri) {
  var re = /^test:([^\/]+)$/;
  var manifestParts = re.exec(uri);
  if (!manifestParts) {
    // Use expect so the URI is printed on errors.
    expect(uri).toMatch(re);
    return Promise.reject();
  }

  var manifest = shaka.test.TestScheme.MANIFESTS[manifestParts[1]];
  expect(manifest).toBeTruthy();
  if (!manifest) return Promise.reject();

  return Promise.resolve(manifest);
};

/** @override */
shaka.test.TestScheme.ManifestParser.prototype.stop = function() {
  return Promise.resolve();
};

shaka.net.NetworkingEngine.registerScheme('test', shaka.test.TestScheme);
shaka.media.ManifestParser.registerParserByMime(
    'application/x-test-manifest', shaka.test.TestScheme.ManifestParser);

<|endoftext|>


<commit_before>'use strict';

var io = require('socket.io-client');
var fs = require('fs');
var CHUNK_SIZE = 1024*1024; //1Mb
var MAX_CONS = 10; //This must be configurable

class ClientP2P {

    constructor(onCompleteDownloadFilePeer, onErrorConnection, onConnectFilePeer, onCompleteDownload) {
        this._file = {
            id: null,
            name: null,
            hash: null,
            size: null,
            downloading: false
        };
        this._peers = [];
        this._state = {
            buffers: []
        };
        this._chunks = [];
        this._connections = 0;
        this._onCompleteDownloadFilePeerEvent = onCompleteDownloadFilePeer;
        this._onErrorConnectionEvent = onErrorConnection;
        this._onConnectFilePeerEvent = onConnectFilePeer;
        this._onCompleteDownloadEvent = onCompleteDownload;
    }

    /* :::::::::::::::::::::::::::::::
       :::::::  MÉTODOS PÚBLICOS :::::
       :::::::::::::::::::::::::::::::  */

    /* Agrega un nuevo servidor-par */
    addPeer(ip, port, size, offset) {
        this._peers.push({
            id: this._peers.length,
            ip: ip,
            port: port,
            size: size,
            offset: offset,
            state: 0
        });

        this._downloadChunks();
    }

    /* Modifica un servidor-par */
    setPeer(id, ip, port, size, offset) {
        this._peers[id] = {
            ip: ip,
            port: port,
            size: size,
            offset: offset,
            state: 0
        };
    }

    /* Obtiene un servidor-par */
    getPeer(id) {
        return this._peers[id];
    }

    /* Obtiene un servidor-par diferente al id */
    getPeerDistinct(id) {
      $.each(this._peers, function(i, peer) {
        if (i != id) {
          return peer
        }
      });
    }

    /* Establece el nombre del archivo a solicitar */
    setFile(id, name, hash, size) {
        this._file.id = id;
        this._file.name = name;
        this._file.hash = hash;
        this._file.size = size;

        var i;
        for(i=0;i < Math.floor(size/CHUNK_SIZE); i++) {
            this._chunks[i] = {offset: i*CHUNK_SIZE, size: CHUNK_SIZE, state: false};
        }

        if(size%CHUNK_SIZE != 0)
            this._chunks[i] = {offset: i*CHUNK_SIZE, size: size%CHUNK_SIZE, state: false};

	//Here is possible shuffle chunks to avoid download contiguous chunks every time
    }

    /* Devuelve el nombre del archivo a solicitar */
    getFile() {
        return this._file.name;
    }

    /* Inicia la descarga del archivo */
    downloadFile() {
        this._file.downloading = true;
        this._downloadChunks();
    }

    /* :::::::::::::::::::::::::::::::
       :::::::  MÉTODOS PRIVADOS :::::
       :::::::::::::::::::::::::::::::  */
    _fileComplete() {
        this._chunks.forEach((chunk, i) => {
            if(chunk.state == false) return false;
        });

        return true;
    }

    _getPeerFree() {
        var peerFreeId = null;
        this._peers.forEach((peer, i) => {
            if(peer.state == 0){
                peerFreeId = i;
            }
        });
        return peerFreeId
    }

    _downloadChunks() {
        if(this._file.downloading == false) return false;

        this._chunks.forEach((chunk, i) => {
            if(this._connections < MAX_CONS) {
                if(chunk.state == false) {

                    var peer_id = this._getPeerFree();
                    var peer = this._peers[peer_id];
                    this._downloadFilePeer(peer_id, peer.ip, peer.port, this._file.name, chunk.size, chunk.offset);
                }
            } else {
                return true;
            }
        });
    }

    /* Inicia la descarga de los servidores-pares que no hayan descargado su fragmento  */
    _downloadFilePeers() {
        this._peers.forEach((peer, i) => {
            if (peer.state == 0) {
              this._downloadFilePeer(i, peer.ip, peer.port, this._file.name, peer.size, peer.offset);
            }
        });
    }

    /* Inicia la descarga de un servidor-par */
    _downloadFilePeer(id, ip, port, file_name, file_size, file_offset, callback) {

            var socket = io.connect('http://' + ip + ':' + port, { 'reconnect': false });

            // Detecta la conexión
            socket.on('connect', function() {
                this._onConnectFilePeerEvent(this.getPeer(id), this._file.hash);
                console.log('Conectado a ' + ip + ':' + port);
                this._peers[id].state = 1;
                this._connections++;
            }.bind(this));

            // Detecta la desconexión
            socket.on('disconnect', function() {
                this._connections--;
                this._peers[id].state = 0;
                this._onErrorConnectionEvent(this.getPeer(id), this._file.id);
                this._downloadChunks();
            }.bind(this));

            socket.emit('getfile', {
                file: file_name,
                size: file_size,
                offset: file_offset
            });

            console.log('Se solicitó ' + file_name);

            socket.on("sendfile", function(info) {
                socket.disconnect();
                this._connections--;
                this._onCompleteDownloadFilePeer(id, info);
            }.bind(this));
    }

    /* Método que se ejecuta cuando se finaliza la descarga de uno de los pares */
    _onCompleteDownloadFilePeer(id, info) {
        this._peers[id].state = 0;
        //this._state.buffers[id] = buffer;
        //this._concatFile();
        this._writeChunk(info);

        this._onCompleteDownloadFilePeerEvent(this.getPeer(id), this._file.hash);
        this._downloadChunks();
    }

    _chunkDownloaded(downloadedChunk) {
        this._chunks.forEach((chunk, i) => {
            if(chunk.offset == downloadedChunk.offset)
                this._chunks[i].state = true;
        });
    }

    _writeChunk(info, chunk_id) {
        fs.open('./downloads/' + this._file.name, 'w', function(err, fd) {
            if (err) throw err;

            fs.write(fd, info.buffer, 0, info.size, info.offset, function(err, written, buff) {
                fs.close(fd, function() {
                    this._chunkDownloaded(info);
                    console.log('chunk[' + info.offset + ':' + (info.offset + info.size) + '] Guardado con éxito.');
                    if(this._fileComplete()) {
                        this._onCompleteDownloadEvent(this._file.id, this._file.name);
                        console.log(this._file.name + ' Guardado con éxito.');
                    }
                }.bind(this));
            }.bind(this))
        }.bind(this));
    }

    /* Permite concatenar los buffers y guarda el archivo */
    _concatFile() {

        var flag = true;

        // Verificamos que todos los servidores-pares hayan enviado la infomración
        for (var i in this._peers) {
            if (this._peers[i].state == 0) {
                flag = false;
            }
        }

        if (flag) {

            fs.open('./downloads/' + this._file.name, 'a', function(err, fd) {
                if (err) throw err;

                var my_buffer = Buffer.concat(this._state.buffers);

                fs.write(fd, my_buffer, 0, my_buffer.length, null, function(err, written, buff) {
                    fs.close(fd, function() {
                        this._onCompleteDownloadEvent(this._file.id, this._file.name);
                        console.log(this._file.name + ' Guardado con éxito.');
                    }.bind(this));
                }.bind(this))
            }.bind(this));
        }
    }
}

module.exports = ClientP2P;
<commit_msg>asdasd<commit_after>'use strict';

var io = require('socket.io-client');
var fs = require('fs');
var CHUNK_SIZE = 1024*1024; //1Mb
var MAX_CONS = 10; //This must be configurable

class ClientP2P {

    constructor(onCompleteDownloadFilePeer, onErrorConnection, onConnectFilePeer, onCompleteDownload) {
        this._file = {
            id: null,
            name: null,
            hash: null,
            size: null,
            downloading: false
        };
        this._peers = [];
        this._state = {
            buffers: []
        };
        this._chunks = [];
        this._connections = 0;
        this._onCompleteDownloadFilePeerEvent = onCompleteDownloadFilePeer;
        this._onErrorConnectionEvent = onErrorConnection;
        this._onConnectFilePeerEvent = onConnectFilePeer;
        this._onCompleteDownloadEvent = onCompleteDownload;
    }

    /* :::::::::::::::::::::::::::::::
       :::::::  MÉTODOS PÚBLICOS :::::
       :::::::::::::::::::::::::::::::  */

    /* Agrega un nuevo servidor-par */
    addPeer(ip, port, size, offset) {
        this._peers.push({
            id: this._peers.length,
            ip: ip,
            port: port,
            size: size,
            offset: offset,
            state: 0
        });

        this._downloadChunks();
    }

    /* Modifica un servidor-par */
    setPeer(id, ip, port, size, offset) {
        this._peers[id] = {
            ip: ip,
            port: port,
            size: size,
            offset: offset,
            state: 0
        };
    }

    /* Obtiene un servidor-par */
    getPeer(id) {
        return this._peers[id];
    }

    /* Obtiene un servidor-par diferente al id */
    getPeerDistinct(id) {
      $.each(this._peers, function(i, peer) {
        if (i != id) {
          return peer
        }
      });
    }

    /* Establece el nombre del archivo a solicitar */
    setFile(id, name, hash, size) {
        this._file.id = id;
        this._file.name = name;
        this._file.hash = hash;
        this._file.size = size;

        var i;
        for(i=0;i < Math.floor(size/CHUNK_SIZE); i++) {
            this._chunks[i] = {offset: i*CHUNK_SIZE, size: CHUNK_SIZE, state: false};
        }

        if(size%CHUNK_SIZE != 0)
            this._chunks[i] = {offset: i*CHUNK_SIZE, size: size%CHUNK_SIZE, state: false};

	//Here is possible shuffle chunks to avoid download contiguous chunks every time
    }

    /* Devuelve el nombre del archivo a solicitar */
    getFile() {
        return this._file.name;
    }

    /* Inicia la descarga del archivo */
    downloadFile() {
        this._file.downloading = true;
        this._downloadChunks();
    }

    /* :::::::::::::::::::::::::::::::
       :::::::  MÉTODOS PRIVADOS :::::
       :::::::::::::::::::::::::::::::  */
    _fileComplete() {
        this._chunks.forEach((chunk, i) => {
            if(chunk.state == false) return false;
        });

        return true;
    }

    _getPeerFree() {
        var peerFreeId = null;
        this._peers.forEach((peer, i) => {
            if(peer.state == 0){
                peerFreeId = i;
            }
        });
        return peerFreeId
    }

    _downloadChunks() {
        if(this._file.downloading == false) return false;

        this._chunks.forEach((chunk, i) => {
            if(this._connections < MAX_CONS) {
                if(chunk.state == false) {

                    var peer_id = this._getPeerFree();
                    var peer = this._peers[peer_id];
                    this._downloadFilePeer(peer_id, peer.ip, peer.port, this._file.name, chunk.size, chunk.offset);
                }
            } else {
                return true;
            }
        });
    }

    /* Inicia la descarga de los servidores-pares que no hayan descargado su fragmento  */
    _downloadFilePeers() {
        this._peers.forEach((peer, i) => {
            if (peer.state == 0) {
              this._downloadFilePeer(i, peer.ip, peer.port, this._file.name, peer.size, peer.offset);
            }
        });
    }

    /* Inicia la descarga de un servidor-par */
    _downloadFilePeer(id, ip, port, file_name, file_size, file_offset, callback) {

            var socket = io.connect('http://' + ip + ':' + port, { 'reconnect': false });

            this._peers[id].state = 1;

            // Detecta la conexión
            socket.on('connect', function() {
                this._onConnectFilePeerEvent(this.getPeer(id), this._file.hash);
                console.log('Conectado a ' + ip + ':' + port);
                this._connections++;
            }.bind(this));

            // Detecta la desconexión
            socket.on('disconnect', function() {
                this._connections--;
                this._peers[id].state = 0;
                this._onErrorConnectionEvent(this.getPeer(id), this._file.id);
                this._downloadChunks();
            }.bind(this));

            socket.emit('getfile', {
                file: file_name,
                size: file_size,
                offset: file_offset
            });

            console.log('Se solicitó ' + file_name);

            socket.on("sendfile", function(info) {
                socket.disconnect();
                this._connections--;
                this._onCompleteDownloadFilePeer(id, info);
            }.bind(this));
    }

    /* Método que se ejecuta cuando se finaliza la descarga de uno de los pares */
    _onCompleteDownloadFilePeer(id, info) {
        this._peers[id].state = 0;
        //this._state.buffers[id] = buffer;
        //this._concatFile();
        this._writeChunk(info);

        this._onCompleteDownloadFilePeerEvent(this.getPeer(id), this._file.hash);
        this._downloadChunks();
    }

    _chunkDownloaded(downloadedChunk) {
        this._chunks.forEach((chunk, i) => {
            if(chunk.offset == downloadedChunk.offset)
                this._chunks[i].state = true;
        });
    }

    _writeChunk(info, chunk_id) {
        fs.open('./downloads/' + this._file.name, 'w', function(err, fd) {
            if (err) throw err;

            fs.write(fd, info.buffer, 0, info.size, info.offset, function(err, written, buff) {
                fs.close(fd, function() {
                    this._chunkDownloaded(info);
                    console.log('chunk[' + info.offset + ':' + (info.offset + info.size) + '] Guardado con éxito.');
                    if(this._fileComplete()) {
                        this._onCompleteDownloadEvent(this._file.id, this._file.name);
                        console.log(this._file.name + ' Guardado con éxito.');
                    }
                }.bind(this));
            }.bind(this))
        }.bind(this));
    }

    /* Permite concatenar los buffers y guarda el archivo */
    _concatFile() {

        var flag = true;

        // Verificamos que todos los servidores-pares hayan enviado la infomración
        for (var i in this._peers) {
            if (this._peers[i].state == 0) {
                flag = false;
            }
        }

        if (flag) {

            fs.open('./downloads/' + this._file.name, 'a', function(err, fd) {
                if (err) throw err;

                var my_buffer = Buffer.concat(this._state.buffers);

                fs.write(fd, my_buffer, 0, my_buffer.length, null, function(err, written, buff) {
                    fs.close(fd, function() {
                        this._onCompleteDownloadEvent(this._file.id, this._file.name);
                        console.log(this._file.name + ' Guardado con éxito.');
                    }.bind(this));
                }.bind(this))
            }.bind(this));
        }
    }
}

module.exports = ClientP2P;
<|endoftext|>


<commit_before>///////////////////////////////////////
//get requests
///////////////////////////////////////

app.get('/HV', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/HV.jade');
});

app.get('/GRIFFIN', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('detectors/GRIFFIN.jade');
});

app.get('/DAQ', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/DAQ.jade');
});

app.get('/PPG', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/PPG.jade');
});

app.get('/Clocks', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/Clock.jade');
});

app.get('/Filter', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/Filter.jade');
});

///////////////////////////////////////
//post routes
///////////////////////////////////////

app.post('/postHV', function(req, res){

	spawn('odbedit', ['-c', "set /Equipment/HV-"+req.body.crateIndex+"/Variables/Demand["+req.body.chIndex+"] " + req.body.demandVoltage]);
	spawn('odbedit', ['-c', "set '/Equipment/HV-"+req.body.crateIndex+"/Settings/Ramp Up Speed["+req.body.chIndex+"]' " + req.body.voltageUp]);
	spawn('odbedit', ['-c', "set '/Equipment/HV-"+req.body.crateIndex+"/Settings/Ramp Down Speed["+req.body.chIndex+"]' " + req.body.voltageDown]);

	if(req.body.powerSwitch == 'off')
		spawn('odbedit', ['-c', "set /Equipment/HV-"+req.body.crateIndex+"/Settings/ChState["+req.body.chIndex+"] 0"]);
	else
		spawn('odbedit', ['-c', "set /Equipment/HV-"+req.body.crateIndex+"/Settings/ChState["+req.body.chIndex+"] 1"]);

	return res.redirect('/HV?crate=0&channel='+req.body.chName);
});

app.post('/registerCycle', function(req, res){
	var cycle = (req.body.cycleString) ? JSON.parse(req.body.cycleString) : null,
		i,
		steps = [],
		durations = [];

	//just load an existing cycle
	if(req.body.loadTarget != 'null'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.loadTarget]);
		return res.redirect('/PPG');
	}

	//delete an existing cycle
	if(req.body.deleteTarget != 'null'){
		spawn('odbedit', ['-c', "rm /PPG/Cycles/" + req.body.deleteTarget]);
		return res.redirect('/PPG');
	}

	//register a new cycle
	for(i=0; i<cycle.length; i++){
		steps[i] = parseInt(cycle[i].PPGcode, 10);
		durations[i] = parseInt(cycle[i].duration, 10);
	}

	spawn('odbedit', ['-c', "rm /PPG/Cycles/" + req.body.cycleName]);

	spawn('odbedit', ['-c', "mkdir /PPG/Cycles/" + req.body.cycleName]);

	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/PPGcodes[" + steps.length + "]"]);
	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/durations[" + steps.length + "]"]);
	for(i=0; i<cycle.length; i++){
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/PPGcodes["+ i +"]  " + Math.round(steps[i]) ]);
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/durations["+ i +"]  " + Math.round(durations[i]) ]);
	}

	if(req.body.applyCycle == 'on'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.cycleName]);
	}

	return res.redirect('/PPG');
});

app.post('/registerFilter', function(req, res){
	var filter = (req.body.filterString) ? JSON.parse(req.body.filterString) : null,
		i, j,
		steps = [],
		durations = [];

/*
	//just load an existing cycle
	if(req.body.loadTarget != 'null'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.loadTarget]);
		return res.redirect('/PPG');
	}

	//delete an existing cycle
	if(req.body.deleteTarget != 'null'){
		spawn('odbedit', ['-c', "rm /PPG/Cycles/" + req.body.deleteTarget]);
		return res.redirect('/PPG');
	}
*/
	//register a new filter
	/*
	for(i=0; i<cycle.length; i++){
		steps[i] = parseInt(cycle[i].PPGcode, 10);
		durations[i] = parseInt(cycle[i].duration, 10);
	}
	*/

	/*
	spawn('odbedit', ['-c', "rm /Filter/Filters/" + req.body.filterName]);
	spawn('odbedit', ['-c', "mkdir /Filter/Filters/" + req.body.filterName]);

	for(i=0; i<filter.length; i++){
		spawn('odbedit', ['-c', "create string /Filter/Filters/" + req.body.filterName + "/orCondition"+i+"[" + filter[i].length + "]" ]);
		for(j=0; j<filter[i].length; j++){
			spawn('odbedit', ['-c', "set /Filter/Filters/" + req.body.filterName + "/orCondition"+i + '['+j+'] ' + filter[i][j] ]);
		}
	}
	*/

	exec('odbedit -c rm /Filter/Filters/' + req.body.filterName);
	exec('odbedit -c mkdir /Filter/Filters/' + req.body.filterName);

	for(i=0; i<filter.length; i++){
		exec('odbedit -c create string /Filter/Filters/' + req.body.filterName + '/orCondition'+i+'[' + filter[i].length + "]");
		for(j=0; j<filter[i].length; j++){
			exec('odbedit -c set /Filter/Filters/' + req.body.filterName + '/orCondition'+i + '['+j+'] ' + filter[i][j] );
		}
	}

	/*
	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/PPGcodes[" + steps.length + "]"]);
	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/durations[" + steps.length + "]"]);
	for(i=0; i<cycle.length; i++){
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/PPGcodes["+ i +"]  " + Math.round(steps[i]) ]);
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/durations["+ i +"]  " + Math.round(durations[i]) ]);
	}

	if(req.body.applyCycle == 'on'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.cycleName]);
	}
*/
	return res.redirect('/Filter');

});

app.post('/updateClock', function(req, res){
	var ClockEnB = 0,
		powerOn,
		stepdown = parseInt(req.body.freqStepdown,10);

	//channel on / off
	for(i=0; i<6; i++){
		powerOn = req.body['eSATAtoggle' + i] == 1
		ClockEnB = ClockEnB | ((powerOn) ? (0xF << 4*i) : 0);
	}
	spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[0] " + ClockEnB]);

	//freq. stepdown
	if(stepdown && req.body.isMaster=='1'){
		for(i=0; i<8; i++){
			spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[" + (11+4*i) + "] " + stepdown]);
			spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[" + (12+4*i) + "] " + stepdown]);
		}
	}

	return res.redirect('/Clocks');
});

app.post('/toggleClock', function(req, res){
	spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[1] " + req.body['radio'+req.body.clockIndex] ]);

	return res.redirect('/Clocks');
})

<commit_msg>fighting with weird ODB writing problems - try exec?<commit_after>///////////////////////////////////////
//get requests
///////////////////////////////////////

app.get('/HV', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/HV.jade');
});

app.get('/GRIFFIN', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('detectors/GRIFFIN.jade');
});

app.get('/DAQ', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/DAQ.jade');
});

app.get('/PPG', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/PPG.jade');
});

app.get('/Clocks', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/Clock.jade');
});

app.get('/Filter', function(req, res){
	if(!req.cookies.midas_pwd) res.redirect(MIDAS)

	res.render('widgets/Filter.jade');
});

///////////////////////////////////////
//post routes
///////////////////////////////////////

app.post('/postHV', function(req, res){

	spawn('odbedit', ['-c', "set /Equipment/HV-"+req.body.crateIndex+"/Variables/Demand["+req.body.chIndex+"] " + req.body.demandVoltage]);
	spawn('odbedit', ['-c', "set '/Equipment/HV-"+req.body.crateIndex+"/Settings/Ramp Up Speed["+req.body.chIndex+"]' " + req.body.voltageUp]);
	spawn('odbedit', ['-c', "set '/Equipment/HV-"+req.body.crateIndex+"/Settings/Ramp Down Speed["+req.body.chIndex+"]' " + req.body.voltageDown]);

	if(req.body.powerSwitch == 'off')
		spawn('odbedit', ['-c', "set /Equipment/HV-"+req.body.crateIndex+"/Settings/ChState["+req.body.chIndex+"] 0"]);
	else
		spawn('odbedit', ['-c', "set /Equipment/HV-"+req.body.crateIndex+"/Settings/ChState["+req.body.chIndex+"] 1"]);

	return res.redirect('/HV?crate=0&channel='+req.body.chName);
});

app.post('/registerCycle', function(req, res){
	var cycle = (req.body.cycleString) ? JSON.parse(req.body.cycleString) : null,
		i,
		steps = [],
		durations = [];

	//just load an existing cycle
	if(req.body.loadTarget != 'null'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.loadTarget]);
		return res.redirect('/PPG');
	}

	//delete an existing cycle
	if(req.body.deleteTarget != 'null'){
		spawn('odbedit', ['-c', "rm /PPG/Cycles/" + req.body.deleteTarget]);
		return res.redirect('/PPG');
	}

	//register a new cycle
	for(i=0; i<cycle.length; i++){
		steps[i] = parseInt(cycle[i].PPGcode, 10);
		durations[i] = parseInt(cycle[i].duration, 10);
	}

	spawn('odbedit', ['-c', "rm /PPG/Cycles/" + req.body.cycleName]);

	spawn('odbedit', ['-c', "mkdir /PPG/Cycles/" + req.body.cycleName]);

	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/PPGcodes[" + steps.length + "]"]);
	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/durations[" + steps.length + "]"]);
	for(i=0; i<cycle.length; i++){
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/PPGcodes["+ i +"]  " + Math.round(steps[i]) ]);
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/durations["+ i +"]  " + Math.round(durations[i]) ]);
	}

	if(req.body.applyCycle == 'on'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.cycleName]);
	}

	return res.redirect('/PPG');
});

app.post('/registerFilter', function(req, res){
	var filter = (req.body.filterString) ? JSON.parse(req.body.filterString) : null,
		i, j,
		steps = [],
		durations = [];

/*
	//just load an existing cycle
	if(req.body.loadTarget != 'null'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.loadTarget]);
		return res.redirect('/PPG');
	}

	//delete an existing cycle
	if(req.body.deleteTarget != 'null'){
		spawn('odbedit', ['-c', "rm /PPG/Cycles/" + req.body.deleteTarget]);
		return res.redirect('/PPG');
	}
*/
	//register a new filter
	/*
	for(i=0; i<cycle.length; i++){
		steps[i] = parseInt(cycle[i].PPGcode, 10);
		durations[i] = parseInt(cycle[i].duration, 10);
	}
	*/

	/*
	spawn('odbedit', ['-c', "rm /Filter/Filters/" + req.body.filterName]);
	spawn('odbedit', ['-c', "mkdir /Filter/Filters/" + req.body.filterName]);

	for(i=0; i<filter.length; i++){
		spawn('odbedit', ['-c', "create string /Filter/Filters/" + req.body.filterName + "/orCondition"+i+"[" + filter[i].length + "]" ]);
		for(j=0; j<filter[i].length; j++){
			spawn('odbedit', ['-c', "set /Filter/Filters/" + req.body.filterName + "/orCondition"+i + '['+j+'] ' + filter[i][j] ]);
		}
	}
	*/

	exec('odbedit -c rm /Filter/Filters/' + req.body.filterName, function(){});
	exec('odbedit -c mkdir /Filter/Filters/' + req.body.filterName, function(){});

	for(i=0; i<filter.length; i++){
		exec('odbedit -c create string /Filter/Filters/' + req.body.filterName + '/orCondition'+i+'[' + filter[i].length + "]", function(){});
		for(j=0; j<filter[i].length; j++){
			exec('odbedit -c set /Filter/Filters/' + req.body.filterName + '/orCondition'+i + '['+j+'] ' + filter[i][j], function(){} );
		}
	}

	/*
	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/PPGcodes[" + steps.length + "]"]);
	spawn('odbedit', ['-c', "create int /PPG/Cycles/" + req.body.cycleName + "/durations[" + steps.length + "]"]);
	for(i=0; i<cycle.length; i++){
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/PPGcodes["+ i +"]  " + Math.round(steps[i]) ]);
		spawn('odbedit', ['-c', "set /PPG/Cycles/" + req.body.cycleName + "/durations["+ i +"]  " + Math.round(durations[i]) ]);
	}

	if(req.body.applyCycle == 'on'){
		spawn('odbedit', ['-c', "set /PPG/Current " + req.body.cycleName]);
	}
*/
	return res.redirect('/Filter');

});

app.post('/updateClock', function(req, res){
	var ClockEnB = 0,
		powerOn,
		stepdown = parseInt(req.body.freqStepdown,10);

	//channel on / off
	for(i=0; i<6; i++){
		powerOn = req.body['eSATAtoggle' + i] == 1
		ClockEnB = ClockEnB | ((powerOn) ? (0xF << 4*i) : 0);
	}
	spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[0] " + ClockEnB]);

	//freq. stepdown
	if(stepdown && req.body.isMaster=='1'){
		for(i=0; i<8; i++){
			spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[" + (11+4*i) + "] " + stepdown]);
			spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[" + (12+4*i) + "] " + stepdown]);
		}
	}

	return res.redirect('/Clocks');
});

app.post('/toggleClock', function(req, res){
	spawn('odbedit', ['-c', "set /Equipment/GRIF-Clk" + req.body.clockIndex + "/Variables/Output[1] " + req.body['radio'+req.body.clockIndex] ]);

	return res.redirect('/Clocks');
})

<|endoftext|>


<commit_before>'use strict';

//noinspection JSUnresolvedVariable,JSUnresolvedFunction,JSHint
define([  'jquery',
  'knockout',
  '../../../assets/js/views/smartDetailsViewmodel.js',
  '../../../assets/js/views/style.js',
  '../../../assets/js/support/settings.js',
  '../../../assets/js/biz/diskHelper.js'
], function ($, ko, SmartDetailsViewModel, Style, Settings, DiskHelper) {

  //noinspection JSHint,JSUnresolvedFunction,JSUnusedGlobalSymbols
  return {
    refreshing: ko.observable(false),

    refreshFrequency: ko.observable('?'),

    refreshIntervalId: 0,

    disks: ko.observableArray([]),

    // Called from timer
    fetch: function (DiskListViewModel) {

      DiskListViewModel.refreshing(true);

      //Requests disk list
      //noinspection JSUnresolvedFunction
      $.getJSON(Settings.get().webServicesUrl + 'esxi/disks.json', function (diskListData) {
        DiskListViewModel.refreshing(false);

        //noinspection JSUnresolvedFunction
        DiskListViewModel.disks.removeAll();

        //Builds disk list for SMART request
        var diskIds = '';
        for (var id = 1; id <= diskListData.disks.length; id++) {

          diskIds = diskIds.concat(id.toString());

          if (id < diskListData.disks.length) {
            diskIds = diskIds.concat(',');
          }
        }

        //Requests SMART data for these disks
        //noinspection JSUnresolvedFunction
        $.getJSON(Settings.get().webServicesUrl + 'esxi/disks/' + diskIds + '/smart.json', function (diskSmartData) {
          //noinspection JSHint,JSUnresolvedFunction
          /** @namespace diskSmartData.disks_smart */
          $.each(diskSmartData.disks_smart, function (index, smartData) {
            var disk = diskListData.disks[index];
            disk.smart = smartData.smart;

            //Updates model with disk list
            DiskListViewModel.disks.push(disk);
          });
        });
      });
    },

    bindSubView: function () {
      var smartPopup = $('#smartPopup');
      //noinspection JSUnresolvedFunction
      ko.applyBindings(SmartDetailsViewModel, smartPopup[0]);
    },

    // Called from binding: click on row
    showSmartDetails: function (disk) {
      //noinspection JSUnresolvedVariable,JSUnresolvedFunction
      var smartPopup = $('#smartPopup');

      //noinspection JSUnresolvedFunction
      SmartDetailsViewModel.items.removeAll();

      SmartDetailsViewModel.get(disk);

      //noinspection JSUnresolvedFunction
      smartPopup.modal('show');
    },

		// Called from binding: computed
		temperature: function (diskId) {
			//noinspection JSUnresolvedFunction,JSUnresolvedVariable
			return ko.computed({
				read: function () {
					var temperatureCelsius = DiskHelper.getTemperatureCelsius(this, diskId);

					if (temperatureCelsius !== DiskHelper.NOT_AVAILABLE_VALUE) {
						var temperatureFahrenheit = DiskHelper.getTemperatureFahrenheit(this, diskId);
						return Math.floor(temperatureCelsius) + '°C / ' + Math.floor(temperatureFahrenheit) + '°F';
					}

					return DiskHelper.NOT_AVAILABLE_VALUE;
				}
			}, this);
		},

    // Called from binding: computed
    brand: function (driveModel) {
      //noinspection JSUnresolvedFunction,JSUnresolvedVariable
      return ko.computed({
        read: function () {
          return DiskHelper.extractBrand(driveModel);
        }
      }, this);
    },

    // Called from binding: computed
    global_status: function (diskId) {
      //noinspection JSUnresolvedFunction,JSUnresolvedVariable
      return ko.computed({
        read: function () //noinspection JSHint
        {
          var disk = this.disks()[diskId - 1];
          // To handle case of empty disk list in model (when refreshing).
          if (!disk) {
            return '';
          }

          /** @namespace disk.smart.i_status */
          return disk.smart.i_status;
        }
      }, this);
    },

    // Called from binding: computed
    tempStatus: function (diskId) {
      //noinspection JSUnresolvedFunction,JSUnresolvedVariable
      return ko.computed({
        read: function () {
          var disk = this.disks()[diskId - 1];
          // To handle case of empty disk list in model (when refreshing).
          if (!disk) {
            return '';
          }

          return disk.smart.items[8].status;
        }
      }, this);
    },

    // Called from binding: computed
    statusCssClass: function (status) {
      return Style.getStatusLabelCssClass(status);
    }
  };
});<commit_msg>[12] ensure view model is cleared only when valid service response.<commit_after>'use strict';

//noinspection JSUnresolvedVariable,JSUnresolvedFunction,JSHint
define([  'jquery',
  'knockout',
  '../../../assets/js/views/smartDetailsViewmodel.js',
  '../../../assets/js/views/style.js',
  '../../../assets/js/support/settings.js',
  '../../../assets/js/biz/diskHelper.js'
], function ($, ko, SmartDetailsViewModel, Style, Settings, DiskHelper) {

  //noinspection JSHint,JSUnresolvedFunction,JSUnusedGlobalSymbols
  return {
    refreshing: ko.observable(false),

    refreshFrequency: ko.observable('?'),

    refreshIntervalId: 0,

    disks: ko.observableArray([]),

    // Called from timer
    fetch: function (DiskListViewModel) {

      DiskListViewModel.refreshing(true);

      //Requests disk list
      //noinspection JSUnresolvedFunction
      $.getJSON(Settings.get().webServicesUrl + 'esxi/disks.json', function (diskListData) {

        //Builds disk list for SMART request
        var diskIds = '';

				diskListData.disks.forEach(function (disk, i, disks) {

					var diskId = i + 1;

					diskIds = diskIds.concat(diskId);

					if (diskId < disks.length) {
						diskIds = diskIds.concat(',');
					}

				});

				if (diskIds !== '') {
					//Requests SMART data for these disks
					//noinspection JSUnresolvedFunction
					$.getJSON(Settings.get().webServicesUrl + 'esxi/disks/' + diskIds + '/smart.json', function (diskSmartData) {

						//noinspection JSUnresolvedFunction
						DiskListViewModel.disks.removeAll();

						//noinspection JSHint,JSUnresolvedFunction
						/** @namespace diskSmartData.disks_smart */
						diskSmartData.disks_smart.forEach(function (smartData, i) {
							var disk = diskListData.disks[i];
							disk.smart = smartData.smart;

							//Updates model with disk list
							DiskListViewModel.disks.push(disk);
						});
					});
				}

				DiskListViewModel.refreshing(false);
      });
    },

    bindSubView: function () {
      var smartPopup = $('#smartPopup');
      //noinspection JSUnresolvedFunction
      ko.applyBindings(SmartDetailsViewModel, smartPopup[0]);
    },

    // Called from binding: click on row
    showSmartDetails: function (disk) {
      //noinspection JSUnresolvedVariable,JSUnresolvedFunction
      var smartPopup = $('#smartPopup');

      //noinspection JSUnresolvedFunction
      SmartDetailsViewModel.items.removeAll();

      SmartDetailsViewModel.get(disk);

      //noinspection JSUnresolvedFunction
      smartPopup.modal('show');
    },

		// Called from binding: computed
		temperature: function (diskId) {
			//noinspection JSUnresolvedFunction,JSUnresolvedVariable
			return ko.computed({
				read: function () {
					var temperatureCelsius = DiskHelper.getTemperatureCelsius(this, diskId);

					if (temperatureCelsius !== DiskHelper.NOT_AVAILABLE_VALUE) {
						var temperatureFahrenheit = DiskHelper.getTemperatureFahrenheit(this, diskId);
						return Math.floor(temperatureCelsius) + '°C / ' + Math.floor(temperatureFahrenheit) + '°F';
					}

					return DiskHelper.NOT_AVAILABLE_VALUE;
				}
			}, this);
		},

    // Called from binding: computed
    brand: function (driveModel) {
      //noinspection JSUnresolvedFunction,JSUnresolvedVariable
      return ko.computed({
        read: function () {
          return DiskHelper.extractBrand(driveModel);
        }
      }, this);
    },

    // Called from binding: computed
    global_status: function (diskId) {
      //noinspection JSUnresolvedFunction,JSUnresolvedVariable
      return ko.computed({
        read: function () //noinspection JSHint
        {
          var disk = this.disks()[diskId - 1];
          // To handle case of empty disk list in model (when refreshing).
          if (!disk) {
            return '';
          }

          /** @namespace disk.smart.i_status */
          return disk.smart.i_status;
        }
      }, this);
    },

    // Called from binding: computed
    tempStatus: function (diskId) {
      //noinspection JSUnresolvedFunction,JSUnresolvedVariable
      return ko.computed({
        read: function () {
          var disk = this.disks()[diskId - 1];
          // To handle case of empty disk list in model (when refreshing).
          if (!disk) {
            return '';
          }

					/** @namespace disk.smart.items[].status */
          return disk.smart.items[8].status;
        }
      }, this);
    },

    // Called from binding: computed
    statusCssClass: function (status) {
      return Style.getStatusLabelCssClass(status);
    }
  };
});<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import Plotly from 'plotly.js';

const VALID_EVENT_KEYS = ['x', 'y', 'z', 'text', 'labels', 'values', 'pointNumber',
                          'curveNumber'];

const filterEventData = (eventData) => {
    // Create a new object
    return {
        // `Array.prototype.map` creates a new array of points.
        points: eventData.points.map((pointData) =>
            VALID_EVENT_KEYS.reduce((result, currentKey) => {
                const currentVal = pointData[currentKey];
                return Object.assign(result, {[currentKey]: currentVal});
            }, {})
        )
    };
};

export default class PlotlyGraph extends Component {
    constructor(props) {
        super(props);
        this.bindEvents = this.bindEvents.bind(this);
    }

    plot(props) {
        const {id, figure} = props;
        return Plotly.newPlot(id, figure);
    }

    bindEvents(props) {
        const {id, fireEvent, valueChanged} = props;

        // Get DOM node to call jQuery-provided `on` event binder.
        const gd = document.getElementById(id);

        gd.on('plotly_click', (eventData) => {
            const clickData = filterEventData(eventData);
            if (valueChanged) {
                valueChanged({clickData});
            }
            if (fireEvent) fireEvent({event: 'click'});
        });
        gd.on('plotly_hover', (eventData) => {
            const hoverData = filterEventData(eventData);
            if (valueChanged) valueChanged({hoverData});
            if (fireEvent) fireEvent({event: 'hover'})
        });
        gd.on('plotly_selected', (eventData) => {
            const selectedData = filterEventData(eventData);
            if (valueChanged) valueChanged({selectedData});
            if (fireEvent) fireEvent({event: 'selected'});
        });
        // TODO - Is there a zoom event?
    }

    componentDidMount() {
        this.plot(this.props).then(() => {
            this.bindEvents(this.props);
            window.addEventListener('resize', () => {
                Plotly.Plots.resize(document.getElementById(this.props.id));
            });
        });
    }

    componentWillUnmount() {
        if (this.eventEmitter) {
            this.eventEmitter.removeAllListeners();
        }
    }

    shouldComponentUpdate() {
        // Never re-render after initialization, let Plotly.js own the DOM node.
        return false;
    }

    componentWillReceiveProps(nextProps) {
        // TODO optimize this check
        const figureChanged = JSON.stringify(this.props.figure) !== JSON.stringify(nextProps.figure)

        /*
         * Rebind events in case fireEvent or valueChanged
         * wasn't defined on initial render
         * TODO - Is it safe to rebind events?
         */
        const shouldBindEvents = (
            (!this.props.valueChanged && nextProps.valueChanged) ||
            (!this.props.fireEvent && nextProps.fireEvent)
        );
        if (figureChanged) {
            this.plot(nextProps).then(() => {
                if(shouldBindEvents) this.bindEvents(nextProps);
            });
        } else if (shouldBindEvents) {
            this.bindEvents(nextProps);
        }
    }

    render(){
        const {style, id} = this.props

        return (
            <div
                id={id}
                style={style}
            />
        );
    }
}

PlotlyGraph.propTypes = {
    /**
     * Data from latest click event
     */
    clickData: PropTypes.object,

    /**
     * Data from latest hover event
     */
    hoverData: PropTypes.object,

    /**
     * Data from latest select event
     */
    selectedData: PropTypes.object,

    /**
     * Data from latest zoom event
     */
    zoomData: PropTypes.object,

    /**
     * Plotly `figure` object. See schema:
     * https://plot.ly/javascript/reference
     */
    figure: PropTypes.object,

    /**
     * Generic style overrides on the plot div
     */
    style: PropTypes.object,

    /**
     * Function that updates the state tree.
     */
    valueChanged: PropTypes.func,

    /**
     * Function that fires events
     */
    fireEvent: PropTypes.func
}

PlotlyGraph.defaultProps = {
    clickData: null,
    hoverData: null,
    selectedData: null,
    zoomData: null,
    figure: {data: [], layout: {}},
    layout: {}
};
<commit_msg>rebind events after every newPlot<commit_after>import React, {Component, PropTypes} from 'react';
import Plotly from 'plotly.js';

const VALID_EVENT_KEYS = ['x', 'y', 'z', 'text', 'labels', 'values', 'pointNumber',
                          'curveNumber'];

const filterEventData = (eventData) => {
    // Create a new object
    return {
        // `Array.prototype.map` creates a new array of points.
        points: eventData.points.map((pointData) =>
            VALID_EVENT_KEYS.reduce((result, currentKey) => {
                const currentVal = pointData[currentKey];
                return Object.assign(result, {[currentKey]: currentVal});
            }, {})
        )
    };
};

export default class PlotlyGraph extends Component {
    constructor(props) {
        super(props);
        this.bindEvents = this.bindEvents.bind(this);
    }

    plot(props) {
        const {id, figure} = props;
        return Plotly.newPlot(id, figure).then(() => {
            this.bindEvents(props);
        });
    }

    bindEvents(props) {
        const {id, fireEvent, valueChanged} = props;

        // Get DOM node to call jQuery-provided `on` event binder.
        const gd = document.getElementById(id);

        gd.on('plotly_click', (eventData) => {
            const clickData = filterEventData(eventData);
            if (valueChanged) {
                valueChanged({clickData});
            }
            if (fireEvent) fireEvent({event: 'click'});
        });
        gd.on('plotly_hover', (eventData) => {
            const hoverData = filterEventData(eventData);
            if (valueChanged) valueChanged({hoverData});
            if (fireEvent) fireEvent({event: 'hover'})
        });
        gd.on('plotly_selected', (eventData) => {
            const selectedData = filterEventData(eventData);
            if (valueChanged) valueChanged({selectedData});
            if (fireEvent) fireEvent({event: 'selected'});
        });
        // TODO - Is there a zoom event?
    }

    componentDidMount() {
        this.plot(this.props).then(() => {
            window.addEventListener('resize', () => {
                Plotly.Plots.resize(document.getElementById(this.props.id));
            });
        });
    }

    componentWillUnmount() {
        if (this.eventEmitter) {
            this.eventEmitter.removeAllListeners();
        }
    }

    shouldComponentUpdate() {
        // Never re-render after initialization, let Plotly.js own the DOM node.
        return false;
    }

    componentWillReceiveProps(nextProps) {
        // TODO optimize this check
        const figureChanged = JSON.stringify(this.props.figure) !== JSON.stringify(nextProps.figure)

        /*
         * Rebind events in case fireEvent or valueChanged
         * wasn't defined on initial render
         * TODO - Is it safe to rebind events?
         */
        const shouldBindEvents = (
            (!this.props.valueChanged && nextProps.valueChanged) ||
            (!this.props.fireEvent && nextProps.fireEvent)
        );
        if (figureChanged) {
            this.plot(nextProps);
        } else if (shouldBindEvents) {
            this.bindEvents(nextProps);
        }
    }

    render(){
        const {style, id} = this.props

        return (
            <div
                id={id}
                style={style}
            />
        );
    }
}

PlotlyGraph.propTypes = {
    /**
     * Data from latest click event
     */
    clickData: PropTypes.object,

    /**
     * Data from latest hover event
     */
    hoverData: PropTypes.object,

    /**
     * Data from latest select event
     */
    selectedData: PropTypes.object,

    /**
     * Data from latest zoom event
     */
    zoomData: PropTypes.object,

    /**
     * Plotly `figure` object. See schema:
     * https://plot.ly/javascript/reference
     */
    figure: PropTypes.object,

    /**
     * Generic style overrides on the plot div
     */
    style: PropTypes.object,

    /**
     * Function that updates the state tree.
     */
    valueChanged: PropTypes.func,

    /**
     * Function that fires events
     */
    fireEvent: PropTypes.func
}

PlotlyGraph.defaultProps = {
    clickData: null,
    hoverData: null,
    selectedData: null,
    zoomData: null,
    figure: {data: [], layout: {}},
    layout: {}
};
<|endoftext|>


<commit_before>Router.map(function() {

    this.route('home', {
        path: '/',
        layoutTemplate: ''
    });
    this.route('customers', {
        path: '/customers',
        layoutTemplate: 'mainLayout'
    });
    this.route('archives', {
        path: '/archives',
        layoutTemplate: 'mainLayout'
    });
    this.route('roles', {
        path: '/roles',
        layoutTemplate: 'mainLayout'
    });

    this.route('dashboard', {
        path: '/dashboard',
        loginRequired: 'entrySignIn',
        waitOn: function() {
            return Meteor.subscribe("projects");
        },
        data: {
            projects: Projects.find({})
        },
        onAfterAction: function() {
            SEO.set({
                title: 'Dashboard | ' + SEO.settings.title
            });
        }
    });

    this.route('profile', {
        path: '/profile',
        data: function() {
            return Meteor.user();
        }
    });

    this.route('notFound', {
        path: '*',
        where: 'server',
        action: function() {
            this.response.statusCode = 404;
            this.response.end(Handlebars.templates['404']());
        }
    });

});
<commit_msg>ProjectView route with subscriptions<commit_after>Router.map(function() {

    this.route('home', {
        path: '/',
        layoutTemplate: ''
    });
    this.route('customers', {
        path: '/customers',
        layoutTemplate: 'mainLayout'
    });
    this.route('archives', {
        path: '/archives',
        layoutTemplate: 'mainLayout'
    });
    this.route('roles', {
        path: '/roles',
        layoutTemplate: 'mainLayout'
    });

    this.route('dashboard', {
        path: '/dashboard',
        loginRequired: 'entrySignIn',
        waitOn: function() {
            return Meteor.subscribe("projects");
        },
        data: {
            projects: Projects.find({})
        },
        onAfterAction: function() {
            SEO.set({
                title: 'Dashboard | ' + SEO.settings.title
            });
        }
    });

    this.route('profile', {
        path: '/profile',
        data: function() {
            return Meteor.user();
        }
    });

    this.route('projectView', {
        path: '/projects/:_id',
        layoutTemplate: 'mainLayout',
        loginRequired: 'entrySignIn',
        waitOn: function () {
            Meteor.subscribe('customers');
            Meteor.subscribe('conversations', this.params._id);
            Meteor.subscribe('todos', this.params._id);
            Meteor.subscribe('calevents', this.params._id);
            Meteor.subscribe('uploads', this.params._id);
            return Meteor.subscribe('projects');
        },
        data: function () {
            return Projects.findOne(this.params._id);
        },
        onAfterAction: function () {
            SEO.set({
                title: 'Project View | ' + SEO.settings.title
            })
        }
    });

    this.route('notFound', {
        path: '*',
        where: 'server',
        action: function() {
            this.response.statusCode = 404;
            this.response.end(Handlebars.templates['404']());
        }
    });

});
<|endoftext|>


<commit_before>import React from 'react';

import FileTransferButtons from './FileTransferButtons';

const RESIZE_RATIO = 0.5;
const ALLOW_FILE_TYPES = ['image/png', 'image/jpeg'];

const autoDownload = (url, fileName) => {
  const elem = document.createElement('a');
  elem.href = url;
  elem.download = fileName;
  elem.click();
};

const isAllowedFileType = (uploadedFileType, allowList) => {
  const result = allowList.filter(allowFile => allowFile === uploadedFileType);
  return !!(result.length > 0);
};

const resizeImage = (imageDataUrl, mime, ratio) =>
  new Promise(resolve => {
    const image = new Image();
    image.onload = () => {
      const deformedWidth = image.width * ratio;
      const deformedHeight = image.height * ratio;
      const canvas = document.createElement('canvas');
      canvas.width = deformedWidth;
      canvas.height = deformedHeight;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(image, 0, 0, deformedWidth, deformedHeight);
      resolve(canvas.toDataURL(mime));
    };
    image.src = imageDataUrl;
  });

export default class ImageEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      previewImageDataUrl: null,
      downloadImageFileName: null,
      errorMessage: null,
    };
    this.onImageSelected = this.onImageSelected.bind(this);
    this.onImageLoad = this.onImageLoad.bind(this);
  }

  onImageLoad(imageDataUrl, originalFileName, originalFileMime) {
    resizeImage(imageDataUrl, originalFileMime, RESIZE_RATIO).then(res => {
      this.setState({
        previewImageDataUrl: res,
        /* prettier-ignore */
        downloadImageFileName: originalFileName,
        errorMessage: null,
      });
      autoDownload(
        this.state.previewImageDataUrl,
        this.state.downloadImageFileName
      );
    });
  }

  onImageSelected(e) {
    const file = e.target.files[0];
    if (!isAllowedFileType(file.type, ALLOW_FILE_TYPES)) {
      this.setState({errorMessage: '対応しているファイル形式はjpegとpngのみです。'});
      return;
    }
    const fileReader = new FileReader();
    fileReader.onload = () => {
      this.onImageLoad(fileReader.result, file.name, file.type);
    };
    fileReader.readAsDataURL(file);
  }

  render() {
    const {
      previewImageDataUrl,
      downloadImageFileName,
      errorMessage,
    } = this.state;
    return (

        <FileTransferButtons
          onImageSelected={this.onImageSelected}
          previewImageDataUrl={previewImageDataUrl}
          downloadImageFileName={downloadImageFileName}
        />
        {errorMessage &&
{errorMessage}
}

    );
  }
}
<commit_msg>自動ダウンロードの機能をオンオフできるようにした。<commit_after>import React from 'react';

import FileTransferButtons from './FileTransferButtons';

const RESIZE_RATIO = 0.5;
const ALLOW_FILE_TYPES = ['image/png', 'image/jpeg'];

const autoDownload = (url, fileName) => {
  const elem = document.createElement('a');
  elem.href = url;
  elem.download = fileName;
  elem.click();
};

const isAllowedFileType = (uploadedFileType, allowList) => {
  const result = allowList.filter(allowFile => allowFile === uploadedFileType);
  return !!(result.length > 0);
};

const resizeImage = (imageDataUrl, mime, ratio) =>
  new Promise(resolve => {
    const image = new Image();
    image.onload = () => {
      const deformedWidth = image.width * ratio;
      const deformedHeight = image.height * ratio;
      const canvas = document.createElement('canvas');
      canvas.width = deformedWidth;
      canvas.height = deformedHeight;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(image, 0, 0, deformedWidth, deformedHeight);
      resolve(canvas.toDataURL(mime));
    };
    image.src = imageDataUrl;
  });

export default class ImageEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      previewImageDataUrl: null,
      downloadImageFileName: null,
      allowAutoDownload: true,
      errorMessage: null,
    };
    this.onImageSelected = this.onImageSelected.bind(this);
    this.onImageLoad = this.onImageLoad.bind(this);
  }

  onImageLoad(imageDataUrl, originalFileName, originalFileMime) {
    resizeImage(imageDataUrl, originalFileMime, RESIZE_RATIO).then(res => {
      this.setState({
        previewImageDataUrl: res,
        /* prettier-ignore */
        downloadImageFileName: originalFileName,
        errorMessage: null,
      });
      if (!this.state.allowAutoDownload) return;
      autoDownload(
        this.state.previewImageDataUrl,
        this.state.downloadImageFileName
      );
    });
  }

  onImageSelected(e) {
    const file = e.target.files[0];
    if (!isAllowedFileType(file.type, ALLOW_FILE_TYPES)) {
      this.setState({errorMessage: '対応しているファイル形式はjpegとpngのみです。'});
      return;
    }
    const fileReader = new FileReader();
    fileReader.onload = () => {
      this.onImageLoad(fileReader.result, file.name, file.type);
    };
    fileReader.readAsDataURL(file);
  }

  render() {
    const {
      previewImageDataUrl,
      downloadImageFileName,
      allowAutoDownload,
      errorMessage,
    } = this.state;
    return (

        <FileTransferButtons
          onImageSelected={this.onImageSelected}
          previewImageDataUrl={previewImageDataUrl}
          downloadImageFileName={downloadImageFileName}
        />
        <form>

            <input
              id="optionSetting"
              type="checkbox"
              checked={allowAutoDownload}
              onChange={e => {
                this.setState({allowAutoDownload: e.target.checked});
              }}
            />
            リサイズした画像を自動的にダウンロードする

        </form>
        {errorMessage &&
{errorMessage}
}

    );
  }
}
<|endoftext|>


<commit_before>var checkin = require('./checkin.js'),
    getDetails = require('./getDetails.js'),
    offer = require('./offersPromise.js'),
    register = require('./register.js'),
    del = require('./del.js'),
    groups = require('./groups.js'),
    update = require('./update.js');

exports.getRoutes = function(server){
    var users = "/users",
        business = "/business",
        offers = '/offers',
        group = '/groups';

   // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.get({
        path: users + "/test"
    }, function(req, res,next) {
        res.send('works')
        res.end();
    });
    // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.put({
        path: users + "/checkin"
    }, function(req, res, next) {
        checkin.checkin(req, res, next);
    });
    // Get details for user
    server.get({
        path: users + "/get/:username"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'users');
    });
    // Get details for business
    server.get({
        path: business + "/get/:businessname"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'business');
    });
    //Register user
    server.post({
        path: users
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'users');
        }
    });
    // Register business.
    server.post({
        path: business
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'business');
        }
    });
    //Update User
    server.put({
        path: users + "/:username"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update.updateUser(req, res, next);
        }
    });
    //Update Business
    server.put({
        path: business + "/:businessname"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update.updateBusiness(req, res, next);
        }
    });
    // Delete user
    server.del({
        path: users + "/:username"
    }, function(req, res, next) {
        del.del.deleteUser(req, res, next);
    });
    // Delete business
    server.del({
        path: business + "/:businessname"
    }, function(req, res, next) {
        del.del.deletebusiness(req, res, next);
    });
    server.post({
        path: group
    }, function(req, res, next) {
        groups.groups.createGroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.get({
        path: group +"/:groupname"
    }, function(req, res, next) {
        groups.showgroup(req, res, next);
    });
    //?username=username&competition=freshers
    server.get({
        path: group
    }, function(req, res, next) {

        groups.showcompetitiongroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.put({
        path: users + "/joingroup"
    }, function(req, res, next) {
        groups.joinGroup(req, res, next);
    });
    //Create Offer
    server.post({
        path: business + offers
    }, function(req, res, next) {
        offer.offers.addOffer(req, res, next);
    });
    //Get all Offers
    server.get({
        path: business + offers + '/:businessname'
    }, function(req, res, next) {
        offer.offers.getAllOffers(req, res, next);
    });
    //Redeem Offer
    server.put({
        path: business + offers + '/redeem'
    }, function(req, res, next) {
        offer.offers.redeemOffer(req, res, next);
    });
 }
<commit_msg>changed routing error<commit_after>var checkin = require('./checkin.js'),
    getDetails = require('./getDetails.js'),
    offer = require('./offersPromise.js'),
    register = require('./register.js'),
    del = require('./del.js'),
    groups = require('./groups.js'),
    update = require('./update.js');

exports.getRoutes = function(server){
    var users = "/users",
        business = "/business",
        offers = '/offers',
        group = '/groups';

   // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.get({
        path: users + "/test"
    }, function(req, res,next) {
        res.send('works')
        res.end();
    });
    // The way this works by sending a parameter of "business" and looks up how many points to add from couchDB
    server.put({
        path: users + "/checkin"
    }, function(req, res, next) {
        checkin.checkin(req, res, next);
    });
    // Get details for user
    server.get({
        path: users + "/get/:username"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'users');
    });
    // Get details for business
    server.get({
        path: business + "/get/:businessname"
    }, function(req, res, next) {
        getDetails.getDetails(req, res, next, 'business');
    });
    //Register user
    server.post({
        path: users
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'users');
        }
    });
    // Register business.
    server.post({
        path: business
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            register.register(req, res, next, 'business');
        }
    });
    //Update User
    server.put({
        path: users + "/:username"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update.updateUser(req, res, next);
        }
    });
    //Update Business
    server.put({
        path: business + "/:businessname"
    }, function(req, res, next) {
        if(req.authorization.scheme !== 'Basic') {
            return next(new restify.UnauthorizedError('Basic HTTP auth required'));
            failed = true;
        } else {
            update.update.updateBusiness(req, res, next);
        }
    });
    // Delete user
    server.del({
        path: users + "/:username"
    }, function(req, res, next) {
        del.del.deleteUser(req, res, next);
    });
    // Delete business
    server.del({
        path: business + "/:businessname"
    }, function(req, res, next) {
        del.del.deleteBusiness(req, res, next);
    });
    server.post({
        path: group
    }, function(req, res, next) {
        groups.groups.createGroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.get({
        path: group +"/:groupname"
    }, function(req, res, next) {
        groups.showgroup(req, res, next);
    });
    //?username=username&competition=freshers
    server.get({
        path: group
    }, function(req, res, next) {

        groups.showcompetitiongroup(req, res, next);
    });
    //?username=username&groupname=test21
    server.put({
        path: users + "/joingroup"
    }, function(req, res, next) {
        groups.joinGroup(req, res, next);
    });
    //Create Offer
    server.post({
        path: business + offers
    }, function(req, res, next) {
        offer.offers.addOffer(req, res, next);
    });
    //Get all Offers
    server.get({
        path: business + offers + '/:businessname'
    }, function(req, res, next) {
        offer.offers.getAllOffers(req, res, next);
    });
    //Redeem Offer
    server.put({
        path: business + offers + '/redeem'
    }, function(req, res, next) {
        offer.offers.redeemOffer(req, res, next);
    });
 }
<|endoftext|>