<commit_before>/*
 * Copyright (c) 2016, Natacha Porté
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

var cfg_endpoint = null;
var cfg_data_field = null;

Pebble.addEventListener("ready", function() {
   console.log("Health Export PebbleKit JS ready!");
   Pebble.sendAppMessage({ "modalMessage": "Not configured" });
});

Pebble.addEventListener("appmessage", function(e) {
   console.log('Received message: ' + JSON.stringify(e.payload));
   if (e.payload.dataKey) {
      Pebble.sendAppMessage({ "lastSent": e.payload.dataKey });
   }
});

Pebble.addEventListener("showConfiguration", function() {
   var settings = "?v=1.0";

   if (cfg_endpoint) {
      settings += "&url=" + encodeURIComponent(cfg_endpoint);
   }
   if (cfg_data_field) {
      settings += "&data_field=" + encodeURIComponent(cfg_data_field);
   }

   Pebble.openURL("https://cdn.rawgit.com/faelys/pebble-health-export/v1.0/config.html" + settings);
});

Pebble.addEventListener("webviewclosed", function(e) {
   var configData = JSON.parse(decodeURIComponent(e.response));
   var wasConfigured = (cfg_endpoint && cfg_data_field);

   if (configData.url) {
      cfg_endpoint = configData.url;
   }

   if (configData.dataField) {
      cfg_data_field = configData.dataField;
   }

   if (!wasConfigured && cfg_endpoint && cfg_data_field) {
      Pebble.sendAppMessage({ "lastSent": 0 });
   }
});
<commit_msg>Send data received from the watch to the configured URL<commit_after>/*
 * Copyright (c) 2016, Natacha Porté
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

var cfg_endpoint = null;
var cfg_data_field = null;

var to_send = [];
var sender = new XMLHttpRequest();

function sendHead() {
   if (to_send.length < 1) return;
   var line = to_send.shift();
   var data = new FormData();
   data.append(cfg_data_field, line);
   sender.open("POST", cfg_endpoint, true);
   sender.send(data);
}

function enqueue(key, line) {
   to_send.push(line);
   if (to_send.length === 1) sendHead();
}

function uploadError() { console.log(this.statusText); }

sender.addEventListener("load", sendHead);
sender.addEventListener("error", uploadError);

Pebble.addEventListener("ready", function() {
   console.log("Health Export PebbleKit JS ready!");
   Pebble.sendAppMessage({ "modalMessage": "Not configured" });
});

Pebble.addEventListener("appmessage", function(e) {
   console.log('Received message: ' + JSON.stringify(e.payload));
   if (e.payload.dataKey && e.payload.dataLine) {
      enqueue(e.payload.dataKey, e.payload.dataLine);
      Pebble.sendAppMessage({ "lastSent": e.payload.dataKey });
   }
});

Pebble.addEventListener("showConfiguration", function() {
   var settings = "?v=1.0";

   if (cfg_endpoint) {
      settings += "&url=" + encodeURIComponent(cfg_endpoint);
   }
   if (cfg_data_field) {
      settings += "&data_field=" + encodeURIComponent(cfg_data_field);
   }

   Pebble.openURL("https://cdn.rawgit.com/faelys/pebble-health-export/v1.0/config.html" + settings);
});

Pebble.addEventListener("webviewclosed", function(e) {
   var configData = JSON.parse(decodeURIComponent(e.response));
   var wasConfigured = (cfg_endpoint && cfg_data_field);

   if (configData.url) {
      cfg_endpoint = configData.url;
   }

   if (configData.dataField) {
      cfg_data_field = configData.dataField;
   }

   if (!wasConfigured && cfg_endpoint && cfg_data_field) {
      Pebble.sendAppMessage({ "lastSent": 0 });
   }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import Events from '@storybook/core-events';

import initProviderApi from './init-provider-api';
import initKeyHandler from './init-key-handler';

import getInitialState from './initial-state';

import initAddons from './addons';
import initChannel from './channel';
import initNotifications from './notifications';
import initStories from './stories';
import initLayout from './layout';
import initURL from './url';
import initVersions from './versions';

const Context = React.createContext({ api: undefined, state: getInitialState({}) });

const { STORY_CHANGED, SET_STORIES, SELECT_STORY, APPLY_SHORTCUT } = Events;

export class Provider extends Component {
  static propTypes = {
    navigate: PropTypes.func.isRequired,
    provider: PropTypes.shape({}).isRequired,
    location: PropTypes.shape({}).isRequired,
    path: PropTypes.string,
    viewMode: PropTypes.oneOf(['components', 'info']),
    storyId: PropTypes.string,
    children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
  };

  static defaultProps = {
    viewMode: undefined,
    storyId: undefined,
    path: undefined,
  };

  constructor(props) {
    super(props);
    const { provider, location, path, viewMode, storyId, navigate } = props;

    const store = {
      getState: () => this.state,
      setState: (a, b) => this.setState(a, b),
    };

    const apiData = {
      navigate,
      store,
      provider,
      location,
      path,
      viewMode,
      storyId,
    };

    const modules = [
      initChannel,
      initAddons,
      initLayout,
      initNotifications,
      initStories,
      initURL,
      initVersions,
    ].map(initModule => initModule(apiData));

    // Create our initial state by combining the initial state of all modules
    const state = getInitialState(...modules.map(m => m.state));

    // Get our API by combining the APIs exported by each module
    const combo = Object.assign({ navigate }, ...modules.map(m => m.api));

    const eventHandler = initKeyHandler({ store, api: combo });
    const api = initProviderApi({ provider, store, api: combo, eventHandler });

    api.on(STORY_CHANGED, id => {
      const options = api.getParameters(id, 'options');

      api.setOptions(options);
    });

    console.log(SET_STORIES);
    api.on(SET_STORIES, data => {
      api.setStories(data.stories);
    });
    api.on(SELECT_STORY, ({ kind, story, ...rest }) => {
      api.selectStory(kind, story, rest);
    });
    api.on(APPLY_SHORTCUT, data => {
      api.handleShortcut(data.event);
    });

    // Now every module has had a chance to set its API, call init on each module which gives it
    // a chance to do things that call other modules' APIs.
    modules.forEach(({ init }) => {
      if (init) {
        init({
          ...apiData,
          api,
        });
      }
    });

    this.state = state;
    this.api = api;
    this.eventHandler = eventHandler;
  }

  componentDidMount() {
    this.eventHandler.bind();
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { state: prevState, props: prevProps } = this;

    if (prevState !== nextState) {
      return true;
    }
    if (prevProps.path !== nextProps.path) {
      return true;
    }
    return false;
  }

  static getDerivedStateFromProps = (props, state) => {
    if (state.path !== props.path) {
      return {
        ...state,
        location: props.location,
        path: props.path,
        viewMode: props.viewMode,
        storyId: props.storyId,
      };
    }
    return null;
  };

  render() {
    const { children } = this.props;
    const value = {
      state: this.state,
      api: this.api,
    };

    return (
      <Context.Provider value={value}>
        {typeof children === 'function' ? children(value) : children}
      </Context.Provider>
    );
  }
}
Provider.displayName = 'Manager';

export const { Consumer } = Context;
<commit_msg>REMOVE unnecessary log<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import Events from '@storybook/core-events';

import initProviderApi from './init-provider-api';
import initKeyHandler from './init-key-handler';

import getInitialState from './initial-state';

import initAddons from './addons';
import initChannel from './channel';
import initNotifications from './notifications';
import initStories from './stories';
import initLayout from './layout';
import initURL from './url';
import initVersions from './versions';

const Context = React.createContext({ api: undefined, state: getInitialState({}) });

const { STORY_CHANGED, SET_STORIES, SELECT_STORY, APPLY_SHORTCUT } = Events;

export class Provider extends Component {
  static propTypes = {
    navigate: PropTypes.func.isRequired,
    provider: PropTypes.shape({}).isRequired,
    location: PropTypes.shape({}).isRequired,
    path: PropTypes.string,
    viewMode: PropTypes.oneOf(['components', 'info']),
    storyId: PropTypes.string,
    children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
  };

  static defaultProps = {
    viewMode: undefined,
    storyId: undefined,
    path: undefined,
  };

  constructor(props) {
    super(props);
    const { provider, location, path, viewMode, storyId, navigate } = props;

    const store = {
      getState: () => this.state,
      setState: (a, b) => this.setState(a, b),
    };

    const apiData = {
      navigate,
      store,
      provider,
      location,
      path,
      viewMode,
      storyId,
    };

    const modules = [
      initChannel,
      initAddons,
      initLayout,
      initNotifications,
      initStories,
      initURL,
      initVersions,
    ].map(initModule => initModule(apiData));

    // Create our initial state by combining the initial state of all modules
    const state = getInitialState(...modules.map(m => m.state));

    // Get our API by combining the APIs exported by each module
    const combo = Object.assign({ navigate }, ...modules.map(m => m.api));

    const eventHandler = initKeyHandler({ store, api: combo });
    const api = initProviderApi({ provider, store, api: combo, eventHandler });

    api.on(STORY_CHANGED, id => {
      const options = api.getParameters(id, 'options');

      api.setOptions(options);
    });

    api.on(SET_STORIES, data => {
      api.setStories(data.stories);
    });
    api.on(SELECT_STORY, ({ kind, story, ...rest }) => {
      api.selectStory(kind, story, rest);
    });
    api.on(APPLY_SHORTCUT, data => {
      api.handleShortcut(data.event);
    });

    // Now every module has had a chance to set its API, call init on each module which gives it
    // a chance to do things that call other modules' APIs.
    modules.forEach(({ init }) => {
      if (init) {
        init({
          ...apiData,
          api,
        });
      }
    });

    this.state = state;
    this.api = api;
    this.eventHandler = eventHandler;
  }

  componentDidMount() {
    this.eventHandler.bind();
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { state: prevState, props: prevProps } = this;

    if (prevState !== nextState) {
      return true;
    }
    if (prevProps.path !== nextProps.path) {
      return true;
    }
    return false;
  }

  static getDerivedStateFromProps = (props, state) => {
    if (state.path !== props.path) {
      return {
        ...state,
        location: props.location,
        path: props.path,
        viewMode: props.viewMode,
        storyId: props.storyId,
      };
    }
    return null;
  };

  render() {
    const { children } = this.props;
    const value = {
      state: this.state,
      api: this.api,
    };

    return (
      <Context.Provider value={value}>
        {typeof children === 'function' ? children(value) : children}
      </Context.Provider>
    );
  }
}
Provider.displayName = 'Manager';

export const { Consumer } = Context;
<|endoftext|>


<commit_before>export { Base };

import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as TwoTensors from "../../util/TwoTensors.js";
import * as ReturnOrClone_Activation from "../ReturnOrClone_Activation.js";
import * as BoundsArraySet from "../BoundsArraySet.js";
import { FiltersArray_BiasesArray } from "./Pointwise_FiltersArray_BiasesArray.js";

/**
 * Handle pointwise convolution (1x1 conv2d), bias and activation.
 *
 *
 * @member {boolean} bExisted
 *   If true, this pointwise convolution exists. The same as this.bPointwise.
 *
 * @member {boolean} bPointwise
 *   If true, this pointwise convolution exists. The same as this.bExisted.
 *
 * @member {boolean} bInitOk
 *   If true, the init() is successful.
 *
 * @member {function} pfnConv
 *   This is a method. It has one parameter inputTensor and return a outputTensor. The inputTensor (tf.tensor3d) represents the image
 * ( height x width x channel ) which will be processed. The outputTensor (tf.tensor3d) represents the result.
 * All intermediate tensors will be disposed. The inputTensor may or may not be disposed. In fact, this method calls one of
 * Base.return_input_directly(), Base.keep_input_return_copy(), Conv_and_destroy(), Conv_and_keep() according to the parameters.
 *
 * @member {function} pfnConvBiasActivation
 *   This is a method. It has one parameter inputTensor and return a outputTensor. The inputTensor (tf.tensor3d) represents the image
 * ( height x width x channel ) which will be processed. The outputTensor (tf.tensor3d) represents the result.
 * All intermediate tensors will be disposed. The inputTensors may or may not be disposed. In fact, this method calls one of
 * Base.return_input_directly(), Base.keep_input_return_copy(), Conv_and_destroy_or_keep(), ConvBias_and_destroy_or_keep(),
 * ConvActivation_and_destroy_or_keep(), ConvBiasActivation_and_destroy_or_keep() according to the parameters.
 *
 * @see FiltersArray_BiasesArray
 */
class Base extends FiltersArray_BiasesArray( TwoTensors.filtersTensor4d_biasesTensor3d( ReturnOrClone_Activation.Base ) ) {

  /**
   */
  constructor(
    inputChannelCount, outputChannelCount, bBias, nActivationId, nPassThroughStyleId,
    nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf, channelShuffler_outputGroupCount ) {

    super(
      inputChannelCount, outputChannelCount, bBias, nActivationId, nPassThroughStyleId,
      nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf, channelShuffler_outputGroupCount );
  }

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpreted as weights.
   *
   * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray
   *   The element value bounds (per channel) of input. Usually, it is The .output of the previous convolution-bias-activation value bounds
   * set of this pointwise convolution. It will be kept (not cloned) directly. So caller should not modify them.
   *
   * @param {Array} arrayTemp_forInterleave_asGrouptTwo
   *   A temporary array for placing the original elements temporarily. Provide this array could reduce memory re-allocation
   * and improve performance when doing Interleave_asGrouptTwo.
   *
   * @return {boolean} Return true, if succeeded.
   */
  init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray, arrayTemp_forInterleave_asGrouptTwo ) {

    // Q1: Why is the inputFloat32Array not a parameter of constructor?
    // A1: The reason is to avoid keeping it as this.inputFloat32Array so that it could be released by memory garbage collector.
    //
    // Q2: Why not keep filtersWeights and biasesWeights in data members of this?
    // A2: Their underlying ArrayBuffer is inputFloat32Array.buffer. If this.filtersWeights and this.biasesWeights are kept,
    //     the inputFloat32Array.buffer could not be released by memory garbage collector.

    this.disposeTensors();

    // 1. Determine operation functions.
    Base.Setup_bPointwise_pfn.call( this );

    let bExtractOk;
    if ( !this.bPointwise ) {
      bExtractOk = true; // 2. no operation at all.

      this.byteOffsetBegin = this.byteOffsetEnd = byteOffsetBegin;
      this.tensorWeightCountExtracted = this.tensorWeightCountTotal = 0;

      this.boundsArraySet = new BoundsArraySet.Pointwise( inputScaleBoundsArray, inputScaleBoundsArray.channelCount );
      this.boundsArraySet.output0.set_all_byScaleBoundsArray( inputScaleBoundsArray ); // Bypass previous to next.

    } else { // 3.

      bExtractOk = super.init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray, arrayTemp_forInterleave_asGrouptTwo );
      if ( bExtractOk ) {
        try {
          if ( this.filtersShape && this.filtersArray ) {
            this.filtersTensor4d = tf.tensor( this.filtersArray, this.filtersShape );
            this.filtersArray = null; // Release for reducing memory usage.
          }

          if ( this.biasesShape && this.biasesArray ) {
            this.biasesTensor3d = tf.tensor( this.biasesArray, this.biasesShape );
            this.biasesArray = null; // Release for reducing memory usage.
          }

        } catch ( e ) {  // If failed (e.g. memory not enough), return false.
          bExtractOk = false;
        }
      }

    }

    this.bInitOk = bExtractOk;
    return this.bInitOk;
  }

  disposeTensors() {
    super.disposeTensors(); // Release filtersTensor4d and biasesTensor3d.

    this.pfnConvBiasActivation = this.pfnConv = this.pfnActivation = null;

    this.bPointwise = false;
    this.byteOffsetEnd = -1;
    this.bKeepInputTensor = false;  // Default will dispose input tensor.
    this.bInitOk = false;
  }

  /**
   * Adjust this.pfnConv (and this.pfnConvBiasActivation if need) so that this.pfnConv() and this.pfnConvBiasActivation() will or will not
   * dispose its inputTensor.
   */
  setKeepInputTensor( bKeepInputTensor ) {
    if ( bKeepInputTensor == this.bKeepInputTensor )
      return;

    this.bKeepInputTensor = bKeepInputTensor;

    if ( this.bExisted ) {
      if ( bKeepInputTensor ) {
        this.pfnConv = Base.Conv_and_keep;
      } else {
        this.pfnConv = Base.Conv_and_destroy;
      }
    } else {
      // Since there is no operation at all, let pfnConvBiasActivation ignore pfnConv completely.
      if ( bKeepInputTensor ) {
        this.pfnConvBiasActivation = this.pfnConv = Base.keep_input_return_copy;
      } else {
        this.pfnConvBiasActivation = this.pfnConv = Base.return_input_directly;
      }
    }
  }

  get bExisted() {
    return this.bPointwise;
  }

  /** Determine this.bPointwise and this.pfnXxx data members.
   *
   * @param {Base} this
   *   The Base object to be determined and modified.
   */
  static Setup_bPointwise_pfn() {

    // Determine whether pointwise operation should exist.
    if ( this.outputChannelCount > 0 ) {
      this.bPointwise = true;

    } else {  // ( outputChannelCount <= 0 )
      if ( this.channelShuffler_outputGroupCount > 0 ) {
        this.bPointwise = true; // all-pass-through-and-channel-shuffling mode. (Otherwise, no way to do channel shuffling.)
        this.bBias = false; // In this case, there is always no biases (no matter how original bBias is).

      } else {
        this.bPointwise = false;
      }
    }

    this.pfnActivation = Base.ActivationFunction_getById( this.nActivationId );

    if ( !this.bPointwise ) {
      // Since there is no operation at all, let pfnConvBiasActivation ignore pfnConv completely.
      this.pfnConvBiasActivation = this.pfnConv = Base.return_input_directly;
      return true;
    }

    this.pfnConv = Base.Conv_and_destroy; // will dispose inputTensor.

    if ( this.bBias ) {
      if ( this.pfnActivation )
        this.pfnConvBiasActivation = Base.ConvBiasActivation_and_destroy_or_keep;
      else
        this.pfnConvBiasActivation = Base.ConvBias_and_destroy_or_keep;
    } else {
      if ( this.pfnActivation )
        this.pfnConvBiasActivation = Base.ConvActivation_and_destroy_or_keep;
       else
        this.pfnConvBiasActivation = Base.Conv_and_destroy_or_keep;
    }
  }

  /** Pointwise Convolution (1x1). (The inputTensor will not be disposed so that it can be used for achieving skip connection.) */
  static Conv_and_keep( inputTensor ) {
    return tf.conv2d( inputTensor, this.filtersTensor4d, 1, "valid" ); // 1x1, Stride = 1
  }

  static Conv_and_destroy( inputTensor ) {
    let t = tf.conv2d( inputTensor, this.filtersTensor4d, 1, "valid" );
    inputTensor.dispose();
    return t;
  }

  /** Pointwise Convolution, Bias and Activation. */
  static Conv_and_destroy_or_keep( inputTensor ) {
    return this.pfnConv( inputTensor );
  }

  static ConvBias_and_destroy_or_keep( inputTensor ) {
    let t0 = this.pfnConv( inputTensor );

    let t1 = tf.add( t0, this.biasesTensor3d );
    t0.dispose();

    return t1;
  }

  static ConvActivation_and_destroy_or_keep( inputTensor ) {
    let t0 = this.pfnConv( inputTensor );

    let t1 = this.pfnActivation( t0 );
    t0.dispose();

    return t1;
  }

  static ConvBiasActivation_and_destroy_or_keep( inputTensor ) {
    let t0 = this.pfnConv( inputTensor );

    let t1 = tf.add( t0, this.biasesTensor3d );
    t0.dispose();

    t0 = this.pfnActivation( t1 );
    t1.dispose();

    return t0;
  }

}
<commit_msg>Update Pointwise_Base.js<commit_after>export { Base };

import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as TwoTensors from "../../util/TwoTensors.js";
import * as ReturnOrClone_Activation from "../ReturnOrClone_Activation.js";
import * as BoundsArraySet from "../BoundsArraySet.js";
import { FiltersArray_BiasesArray } from "./Pointwise_FiltersArray_BiasesArray.js";

/**
 * Handle pointwise convolution (1x1 conv2d), bias and activation.
 *
 *
 * @member {boolean} bExisted
 *   If true, this pointwise convolution exists. The same as this.bPointwise.
 *
 * @member {boolean} bPointwise
 *   If true, this pointwise convolution exists. The same as this.bExisted.
 *
 * @member {boolean} bInitOk
 *   If true, the init() is successful.
 *
 * @member {function} pfnConv
 *   This is a method. It has one parameter inputTensor and return a outputTensor. The inputTensor (tf.tensor3d) represents the image
 * ( height x width x channel ) which will be processed. The outputTensor (tf.tensor3d) represents the result.
 * All intermediate tensors will be disposed. The inputTensor may or may not be disposed. In fact, this method calls one of
 * Base.return_input_directly(), Base.keep_input_return_copy(), Conv_and_destroy(), Conv_and_keep() according to the parameters.
 *
 * @member {function} pfnConvBiasActivation
 *   This is a method. It has one parameter inputTensor and return a outputTensor. The inputTensor (tf.tensor3d) represents the image
 * ( height x width x channel ) which will be processed. The outputTensor (tf.tensor3d) represents the result.
 * All intermediate tensors will be disposed. The inputTensors may or may not be disposed. In fact, this method calls one of
 * Base.return_input_directly(), Base.keep_input_return_copy(), Conv_and_destroy_or_keep(), ConvBias_and_destroy_or_keep(),
 * ConvActivation_and_destroy_or_keep(), ConvBiasActivation_and_destroy_or_keep() according to the parameters.
 *
 * @see FiltersArray_BiasesArray
 */
class Base extends FiltersArray_BiasesArray( TwoTensors.filtersTensor4d_biasesTensor3d( ReturnOrClone_Activation.Base ) ) {

  /**
   */
  constructor(
    inputChannelCount, outputChannelCount, bBias, nActivationId, nPassThroughStyleId,
    nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf, channelShuffler_outputGroupCount ) {

    super(
      inputChannelCount, outputChannelCount, bBias, nActivationId, nPassThroughStyleId,
      nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf, channelShuffler_outputGroupCount );
  }

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpreted as weights.
   *
   * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray
   *   The element value bounds (per channel) of input. Usually, it is The .output of the previous convolution-bias-activation value bounds
   * set of this pointwise convolution. It will be kept (not cloned) directly. So caller should not modify them.
   *
   * @param {Array} arrayTemp_forInterleave_asGrouptTwo
   *   A temporary array for placing the original elements temporarily. Provide this array could reduce memory re-allocation
   * and improve performance when doing Interleave_asGrouptTwo.
   *
   * @return {boolean} Return true, if succeeded.
   */
  init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray, arrayTemp_forInterleave_asGrouptTwo ) {

    // Q1: Why is the inputFloat32Array not a parameter of constructor?
    // A1: The reason is to avoid keeping it as this.inputFloat32Array so that it could be released by memory garbage collector.
    //
    // Q2: Why not keep filtersWeights and biasesWeights in data members of this?
    // A2: Their underlying ArrayBuffer is inputFloat32Array.buffer. If this.filtersWeights and this.biasesWeights are kept,
    //     the inputFloat32Array.buffer could not be released by memory garbage collector.

    this.disposeTensors();

    // 1. Determine operation functions.
    Base.Setup_bPointwise_pfn.call( this );

    let bExtractOk;
    if ( !this.bPointwise ) {
      bExtractOk = true; // 2. no operation at all.

      this.byteOffsetBegin = this.byteOffsetEnd = byteOffsetBegin;
      this.tensorWeightCountExtracted = this.tensorWeightCountTotal = 0;

      this.boundsArraySet = new BoundsArraySet.Pointwise( inputScaleBoundsArray, inputScaleBoundsArray.channelCount );
      this.boundsArraySet.output0.set_all_byScaleBoundsArray( inputScaleBoundsArray ); // Bypass previous to next.

    } else { // 3.

      bExtractOk = super.init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray, arrayTemp_forInterleave_asGrouptTwo );
      if ( bExtractOk ) {
        try {
          if ( this.filtersShape && this.filtersArray ) {
            this.filtersTensor4d = tf.tensor( this.filtersArray, this.filtersShape );
            this.filtersArray = null; // Release for reducing memory usage.
          }

          if ( this.biasesShape && this.biasesArray ) {
            this.biasesTensor3d = tf.tensor( this.biasesArray, this.biasesShape );
            this.biasesArray = null; // Release for reducing memory usage.
          }

        } catch ( e ) {  // If failed (e.g. memory not enough), return false.
          bExtractOk = false;
        }
      }

    }

    this.bInitOk = bExtractOk;
    return this.bInitOk;
  }

  disposeTensors() {
    super.disposeTensors(); // Release filtersTensor4d and biasesTensor3d.

    this.pfnConvBiasActivation = this.pfnConv = this.pfnActivation = null;

    this.bPointwise = false;
    this.byteOffsetBegin = this.byteOffsetEnd = -1;
    this.bKeepInputTensor = false;  // Default will dispose input tensor.
    this.bInitOk = false;
  }

  /**
   * Adjust this.pfnConv (and this.pfnConvBiasActivation if need) so that this.pfnConv() and this.pfnConvBiasActivation() will or will not
   * dispose its inputTensor.
   */
  setKeepInputTensor( bKeepInputTensor ) {
    if ( bKeepInputTensor == this.bKeepInputTensor )
      return;

    this.bKeepInputTensor = bKeepInputTensor;

    if ( this.bExisted ) {
      if ( bKeepInputTensor ) {
        this.pfnConv = Base.Conv_and_keep;
      } else {
        this.pfnConv = Base.Conv_and_destroy;
      }
    } else {
      // Since there is no operation at all, let pfnConvBiasActivation ignore pfnConv completely.
      if ( bKeepInputTensor ) {
        this.pfnConvBiasActivation = this.pfnConv = Base.keep_input_return_copy;
      } else {
        this.pfnConvBiasActivation = this.pfnConv = Base.return_input_directly;
      }
    }
  }

  get bExisted() {
    return this.bPointwise;
  }

  /** Determine this.bPointwise and this.pfnXxx data members.
   *
   * @param {Base} this
   *   The Base object to be determined and modified.
   */
  static Setup_bPointwise_pfn() {

    // Determine whether pointwise operation should exist.
    if ( this.outputChannelCount > 0 ) {
      this.bPointwise = true;

    } else {  // ( outputChannelCount <= 0 )
      if ( this.channelShuffler_outputGroupCount > 0 ) {
        this.bPointwise = true; // all-pass-through-and-channel-shuffling mode. (Otherwise, no way to do channel shuffling.)
        this.bBias = false; // In this case, there is always no biases (no matter how original bBias is).

      } else {
        this.bPointwise = false;
      }
    }

    this.pfnActivation = Base.ActivationFunction_getById( this.nActivationId );

    if ( !this.bPointwise ) {
      // Since there is no operation at all, let pfnConvBiasActivation ignore pfnConv completely.
      this.pfnConvBiasActivation = this.pfnConv = Base.return_input_directly;
      return true;
    }

    this.pfnConv = Base.Conv_and_destroy; // will dispose inputTensor.

    if ( this.bBias ) {
      if ( this.pfnActivation )
        this.pfnConvBiasActivation = Base.ConvBiasActivation_and_destroy_or_keep;
      else
        this.pfnConvBiasActivation = Base.ConvBias_and_destroy_or_keep;
    } else {
      if ( this.pfnActivation )
        this.pfnConvBiasActivation = Base.ConvActivation_and_destroy_or_keep;
       else
        this.pfnConvBiasActivation = Base.Conv_and_destroy_or_keep;
    }
  }

  /** Pointwise Convolution (1x1). (The inputTensor will not be disposed so that it can be used for achieving skip connection.) */
  static Conv_and_keep( inputTensor ) {
    return tf.conv2d( inputTensor, this.filtersTensor4d, 1, "valid" ); // 1x1, Stride = 1
  }

  static Conv_and_destroy( inputTensor ) {
    let t = tf.conv2d( inputTensor, this.filtersTensor4d, 1, "valid" );
    inputTensor.dispose();
    return t;
  }

  /** Pointwise Convolution, Bias and Activation. */
  static Conv_and_destroy_or_keep( inputTensor ) {
    return this.pfnConv( inputTensor );
  }

  static ConvBias_and_destroy_or_keep( inputTensor ) {
    let t0 = this.pfnConv( inputTensor );

    let t1 = tf.add( t0, this.biasesTensor3d );
    t0.dispose();

    return t1;
  }

  static ConvActivation_and_destroy_or_keep( inputTensor ) {
    let t0 = this.pfnConv( inputTensor );

    let t1 = this.pfnActivation( t0 );
    t0.dispose();

    return t1;
  }

  static ConvBiasActivation_and_destroy_or_keep( inputTensor ) {
    let t0 = this.pfnConv( inputTensor );

    let t1 = tf.add( t0, this.biasesTensor3d );
    t0.dispose();

    t0 = this.pfnActivation( t1 );
    t1.dispose();

    return t0;
  }

}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Cirrus66
// @namespace    https://github.com/tsdorsey/cirrus66
// @version      0.2.0
// @description  Organize the dashboard to be a bit more compact.
// @author       Trevor Dorsey
// @match        https://app.cloud66.com/dashboard
// @grant        none
// @require      https://code.jquery.com/jquery-2.1.4.js
// @require      https://code.jquery.com/ui/1.11.4/jquery-ui.js
// @run-at       document-idle
// ==/UserScript==

var MutationObserver    = window.MutationObserver || window.WebKitMutationObserver;

function waitForListLoad() {
  if($('#js_search_list').length > 0) {
    start();
  } else {
    setTimeout(waitForListLoad, 250);
  }
}
waitForListLoad();

function start() {
  var items = $('#js_search_list > li');
  var list = items.toArray();

  var envOrder = ['c66_develop', 'staging', 'production'];
  var stackOrder = ['Accounts', 'Dashboard', 'Greenhouse', 'API', 'Sites', 'CloverSites.com'];

  list.forEach(makeSingleColumn);
  bindUpdate(list);
  sortByEnvironment(list, envOrder, stackOrder, '40px');
}

function bindUpdate(itemList) {
  // create an observer instance
  var observer = new MutationObserver (mutationHandler);
  var config = { childList: true, subtree: true };

  itemList.forEach(function(item) {
    observer.observe(item, config);
    updateStack(item);
  });
}

function mutationHandler(mutationRecords) {
  mutationRecords.forEach(function(record) {
    updateStack(record.target);
  });
}

function updateStack(item) {
  $item = $(item);

  if($item.hasClass('cirrus--update')) { return; }

  $item.addClass('cirrus--update');
  compressSpace(item);
  hideFooter(item);
  environmentFirst(item);
  $item.removeClass('cirrus--update');
}

function makeSingleColumn(listItem) {
  $item = $(listItem);
  $item.removeClass('desk--one-half');
}

function compressSpace(listItem) {
  $item = $(listItem);
  $item.find('.Module-header').css( { 'padding-top': '4px', 'padding-bottom': '4px' } );
  $item.find('.Module-headerTools').css( { 'top': '2px' } );
  $item.find('.Module-body').css( { 'height': 'auto', 'padding-top': '0', 'padding-bottom': '3px' } );
  $item.find('.Module--cardList').css( { 'display': 'inline-block', 'margin-right': '50px' } );
  $item.find('.Module--cardListSub > li').css( { 'display': 'inline', 'margin-right': '20px' } );
  $item.find('.state-label').css( { 'position': 'relative', 'top': '7px' } );
  $item.find('.Module--cardScore').css( { 'position': 'relative', 'top': '7px' } );
}

function hideFooter(listItem) {
  $item = $(listItem);
  $item.find('footer.Module-footer').css( { 'display': 'none' } );
}

function environmentFirst(listItem) {
  $item = $(listItem);
  $link = $item.find('.Module-titleLink');
  $env = $link.find('.Module-titleSub');
  $env.detach();
  $link.prepend($env);
}

function sortByEnvironment(list, envOrder, stackOrder, endingPad) {
  list.sort(function(a, b) {
    Da = envAndName(a);
    Db = envAndName(b);

    envOrderResult = order(Da.env, Db.env, envOrder);
    if(envOrderResult != 0) { return envOrderResult; }

    return order(Da.name, Db.name, stackOrder);
  });

  // Put them in the new order by detaching them and appending them in order.
  list.forEach(function(listItem) {
    $item = $(listItem);
    $item.detach();
  });

  parentContainer = $('#js_search_list');
  parentContainer.empty();

  last = envAndName(list[0]);
  list.forEach(function(listItem) {
    $item = $(listItem);
    parentContainer.append($item);
    parentContainer.append("<!--\n-->");

    now = envAndName($item);
    if(now.env != last.env) {
      $item.css( { 'margin-top': endingPad } );
    }

    last = now;
  });
}

function order(a, b, list) {
  A = list.indexOf(a);
  B = list.indexOf(b);

  if(A == B) {
    if(A == -1) {
      // If they are both missing from the list just compare the input values.
      if(a < b) { return -1; }
      if(a > b) { return 1; }
      if(a == b) { return 0; }
    } else {
      // Otherwise consider them equal.
      return 0;
    }
  }

  // Items not in the list sort later than items found in the list.
  if(A == -1) { return 1; }
  if(B == -1) { return -1; }

  if(A < B) { return -1; }
  if(A > B) { return 1; }
}

function envAndName(item) {
  $link = $(item).find('.Module-titleLink');
  $env = $link.find('.Module-titleSub');
  $stack = $link.find('.js-stack-name');
  return { 'name': $stack.html().trim(), 'env': $env.html().trim() };
}
<commit_msg>Locally scope variables and bump the version<commit_after>// ==UserScript==
// @name         Cirrus66
// @namespace    https://github.com/tsdorsey/cirrus66
// @version      0.2.1
// @description  Organize the dashboard to be a bit more compact.
// @author       Trevor Dorsey
// @match        https://app.cloud66.com/dashboard
// @grant        none
// @require      https://code.jquery.com/jquery-2.1.4.js
// @require      https://code.jquery.com/ui/1.11.4/jquery-ui.js
// @run-at       document-idle
// ==/UserScript==

var MutationObserver    = window.MutationObserver || window.WebKitMutationObserver;

function waitForListLoad() {
  if($('#js_search_list').length > 0) {
    start();
  } else {
    setTimeout(waitForListLoad, 250);
  }
}
waitForListLoad();

function start() {
  var items = $('#js_search_list > li');
  var list = items.toArray();

  var envOrder = ['c66_develop', 'staging', 'production'];
  var stackOrder = ['Accounts', 'Dashboard', 'Greenhouse', 'API', 'Sites', 'CloverSites.com'];

  list.forEach(makeSingleColumn);
  bindUpdate(list);
  sortByEnvironment(list, envOrder, stackOrder, '40px');
}

function bindUpdate(itemList) {
  // create an observer instance
  var observer = new MutationObserver (mutationHandler);
  var config = { childList: true, subtree: true };

  itemList.forEach(function(item) {
    observer.observe(item, config);
    updateStack(item);
  });
}

function mutationHandler(mutationRecords) {
  mutationRecords.forEach(function(record) {
    updateStack(record.target);
  });
}

function updateStack(item) {
  var $item = $(item);

  if($item.hasClass('cirrus--update')) { return; }

  $item.addClass('cirrus--update');
  compressSpace(item);
  hideFooter(item);
  environmentFirst(item);
  $item.removeClass('cirrus--update');
}

function makeSingleColumn(listItem) {
  var $item = $(listItem);
  $item.removeClass('desk--one-half');
}

function compressSpace(listItem) {
  var $item = $(listItem);
  $item.find('.Module-header').css( { 'padding-top': '4px', 'padding-bottom': '4px' } );
  $item.find('.Module-headerTools').css( { 'top': '2px' } );
  $item.find('.Module-body').css( { 'height': 'auto', 'padding-top': '0', 'padding-bottom': '3px' } );
  $item.find('.Module--cardList').css( { 'display': 'inline-block', 'margin-right': '50px' } );
  $item.find('.Module--cardListSub > li').css( { 'display': 'inline', 'margin-right': '20px' } );
  $item.find('.state-label').css( { 'position': 'relative', 'top': '7px' } );
  $item.find('.Module--cardScore').css( { 'position': 'relative', 'top': '7px' } );
}

function hideFooter(listItem) {
  var $item = $(listItem);
  $item.find('footer.Module-footer').css( { 'display': 'none' } );
}

function environmentFirst(listItem) {
  var $item = $(listItem);
  var $link = $item.find('.Module-titleLink');
  var $env = $link.find('.Module-titleSub');
  $env.detach();
  $link.prepend($env);
}

function sortByEnvironment(list, envOrder, stackOrder, endingPad) {
  list.sort(function(a, b) {
    var Da = envAndName(a);
    var Db = envAndName(b);

    var envOrderResult = order(Da.env, Db.env, envOrder);
    if(envOrderResult != 0) { return envOrderResult; }

    return order(Da.name, Db.name, stackOrder);
  });

  // Put them in the new order by detaching them and appending them in order.
  list.forEach(function(listItem) {
    var $item = $(listItem);
    $item.detach();
  });

  var parentContainer = $('#js_search_list');
  parentContainer.empty();

  var last = envAndName(list[0]);
  list.forEach(function(listItem) {
    var $item = $(listItem);
    parentContainer.append($item);
    parentContainer.append("<!--\n-->");

    var now = envAndName($item);
    if(now.env != last.env) {
      $item.css( { 'margin-top': endingPad } );
    }

    last = now;
  });
}

function order(a, b, list) {
  var A = list.indexOf(a);
  var B = list.indexOf(b);

  if(A == B) {
    if(A == -1) {
      // If they are both missing from the list just compare the input values.
      if(a < b) { return -1; }
      if(a > b) { return 1; }
      if(a == b) { return 0; }
    } else {
      // Otherwise consider them equal.
      return 0;
    }
  }

  // Items not in the list sort later than items found in the list.
  if(A == -1) { return 1; }
  if(B == -1) { return -1; }

  // Compare their position in the list.
  if(A < B) { return -1; }
  if(A > B) { return 1; }
}

function envAndName(item) {
  var $link = $(item).find('.Module-titleLink');
  var $env = $link.find('.Module-titleSub');
  var $stack = $link.find('.js-stack-name');
  return { 'name': $stack.html().trim(), 'env': $env.html().trim() };
}
<|endoftext|>


<commit_before>function unpack_data (data, out) {
    var teams = {};
    var players = {};
    data.team.forEach(function (team) {
        teams[team.team_id] = team;
        var playerList = team.player || team.squad;
        playerList.forEach(function (player) {
            players[player.player_id] = player;
        });
    });

    var match_status = data.match.match_status;
    if (!match_status || data.match.result !== "0")
        match_status = "complete";

    if (match_status === "current" && !data.live.innings.batting_team_id) {
        match_status = "dormant";
    }

    // XXX fact
    if (data.live["break"]) {
        out.fact = data.live["break"];
    }

    console.log("match status: "+match_status);

    switch (match_status) {
        case "dormant":
            out.score = data.match.team1_abbreviation.toUpperCase()+" v "+data.match.team2_abbreviation.toUpperCase();
            out.lead = "Match starts in "+data.match.match_clock;

            if (data.match.toss_decision && data.match.toss_decision !== "" && data.match.toss_decision !== "0") {
                out.striker_name = teams[data.match.toss_winner_team_id].team_short_name+" won toss,";
                out.nonstriker_name = "will "+data.match.toss_decision_name;
            }
            break;

        case "complete": {
            out.score = data.match.team1_abbreviation.toUpperCase()+" v "+data.match.team2_abbreviation.toUpperCase();

            if (data.match.winner_team_id == "0") {
                out.striker_name = "Match drawn";
            }
            else {
                out.striker_name = teams[data.match.winner_team_id].team_short_name+" won by";
                if (data.match.amount_name === "innings") {
                    out.nonstriker_name = "innings and "+data.match.amount+" runs";
                }
                else {
                    out.nonstriker_name = data.match.amount+" "+data.match.amount_name;
                }
            }
            break;
        }

        case "current": {
            var innings = data.live.innings;

            out.score = [
                teams[innings.batting_team_id].team_abbreviation.toUpperCase() + " " + innings.runs,
                (innings.wickets < 10) ? "/"+innings.wickets : "",
                ((innings.event && innings.event == "declared") ? "d" : "")
            ].join('');

            out.overs = innings.overs;

            if (+data.match.scheduled_overs > 0) {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "Run rate: "+innings.run_rate;
                        break;
                    default:
                        out.lead =
                            "Need "+(1-innings.lead)+" from "+
                            (innings.remaining_overs <= 10.0 ? innings.remaining_balls : innings.remaining_overs+" ov");
                        break;
                }
            }
            else {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "First innings";
                        break;
                    case 4:
                        out.lead = "Target "+(innings.target);
                        break;
                    default:
                        out.lead =
                            innings.lead < 0 ? "Trail by "+(-innings.lead) :
                            innings.lead > 0 ? "Lead by "+innings.lead :
                                            "Scores level";
                }
            }

            var striker = data.live.batting.filter(function (player) { return player.live_current_name == "striker"; })[0];
            var nonstriker = data.live.batting.filter(function (player) { return player.live_current_name == "non-striker"; })[0];

            if (!striker) {
                striker = nonstriker;
                nonstriker = null;
            }

            var shorten = function (n) {
                var bits = n.split(' ');
                for (var i = 0; i < bits.length-1; i++)
                    bits[i] = bits[i].substr(0,1);
                return bits.join('.');
            };

            if (striker) {
                var striker_name = players[striker.player_id].card_short;
                if (striker_name.length > 10 && players[striker.player_id].popular_name.length > 0)
                    striker_name = players[striker.player_id].popular_name;
                if (striker_name.length > 10)
                    striker_name = shorten(striker_name);
                out.striker_name = striker_name + (nonstriker ? "*" : "");
                out.striker_stats = striker.runs+" ("+striker.balls_faced+")";
            }

            if (nonstriker) {
                var nonstriker_name = players[nonstriker.player_id].card_short;
                if (nonstriker_name.length > 10 && players[nonstriker.player_id].popular_name.length > 0)
                    nonstriker_name = players[nonstriker.player_id].popular_name;
                if (nonstriker_name.length > 10)
                    nonstriker_name = shorten(nonstriker_name);
                out.nonstriker_name = nonstriker_name;
                out.nonstriker_stats = nonstriker.runs+" ("+nonstriker.balls_faced+")";
            }

            var bowler = data.live.bowling.filter(function (player) { return player.live_current_name == "current bowler"; })[0];
            if (bowler) {
                var bowler_name = players[bowler.player_id].card_short;
                if (bowler_name.length > 10) bowler_name = players[bowler.player_id].popular_name;
                out.bowler_name = bowler_name;
                out.bowler_stats = bowler.overs+"-"+bowler.maidens+"-"+bowler.conceded+"-"+bowler.wickets;
            }

            break;
        }
    }
}

function new_out () {
    var out = {
        "score":"",
        "overs":"",
        "lead":"",
        "striker_name":"",
        "striker_stats":"",
        "nonstriker_name":"",
        "nonstriker_stats":"",
        "bowler_name":"",
        "bowler_stats":"",
        "fact":""
    };
    return out;
}

function update () {
    var out = new_out();
    var matchId = localStorage.getItem("matchId");
    if (!matchId) {
        out.striker_name = "No match selected";
        out.nonstriker_name = "in config.";
        Pebble.sendAppMessage(out);
        return;
    }
    var req = new XMLHttpRequest();
    req.open('GET', "http://www.espncricinfo.com/ci/engine/match/"+matchId+".json");
    req.onload = function(e) {
        if (req.readyState == 4) {
            if(req.status == 200) {
                console.log("got new data, updating");

                var data = JSON.parse(req.responseText);
                if (data) {
                    unpack_data(data, out);
                    console.log(JSON.stringify(out));
                    Pebble.sendAppMessage(out);
                }

            } else {
                console.log("Error");
            }
        }
    };
    req.send(null);
}

Pebble.addEventListener("ready", function (e) {
    console.log("connected, doing first update");
    update();
});

Pebble.addEventListener("appmessage", function (e) {
    console.log("tick, doing update");
    update();
});

Pebble.addEventListener("showConfiguration", function (e) {
    console.log("config requested");
    Pebble.openURL("http://eatenbyagrue.org/a/sixfour.psgi");
});

Pebble.addEventListener("webviewclosed", function (e) {
    console.log("config closed, response: "+e.response);
    if (e.response !== "CANCELLED") {
        localStorage.setItem("matchId", e.response);
        update();
    }
});
<commit_msg>move break/fact text up for dormant matches<commit_after>function unpack_data (data, out) {
    var teams = {};
    var players = {};
    data.team.forEach(function (team) {
        teams[team.team_id] = team;
        var playerList = team.player || team.squad;
        playerList.forEach(function (player) {
            players[player.player_id] = player;
        });
    });

    var match_status = data.match.match_status;
    if (!match_status || data.match.result !== "0")
        match_status = "complete";

    if (match_status === "current" && !data.live.innings.batting_team_id) {
        match_status = "dormant";
    }

    // XXX fact
    if (data.live["break"]) {
        out.fact = data.live["break"];
    }

    console.log("match status: "+match_status);

    switch (match_status) {
        case "dormant":
            out.score = data.match.team1_abbreviation.toUpperCase()+" v "+data.match.team2_abbreviation.toUpperCase();

            if (data.match.match_clock && data.match.match_clock !== "") {
                out.lead = "Match starts in "+data.match.match_clock;
            }
            // XXX fact
            else if (out.fact !== "") {
                out.lead = out.fact;
                out.fact = "";
            }

            if (data.match.toss_decision && data.match.toss_decision !== "" && data.match.toss_decision !== "0") {
                out.striker_name = teams[data.match.toss_winner_team_id].team_short_name+" won toss,";
                out.nonstriker_name = "will "+data.match.toss_decision_name;
            }
            break;

        case "complete": {
            out.score = data.match.team1_abbreviation.toUpperCase()+" v "+data.match.team2_abbreviation.toUpperCase();

            if (data.match.winner_team_id == "0") {
                out.striker_name = "Match drawn";
            }
            else {
                out.striker_name = teams[data.match.winner_team_id].team_short_name+" won by";
                if (data.match.amount_name === "innings") {
                    out.nonstriker_name = "innings and "+data.match.amount+" runs";
                }
                else {
                    out.nonstriker_name = data.match.amount+" "+data.match.amount_name;
                }
            }
            break;
        }

        case "current": {
            var innings = data.live.innings;

            out.score = [
                teams[innings.batting_team_id].team_abbreviation.toUpperCase() + " " + innings.runs,
                (innings.wickets < 10) ? "/"+innings.wickets : "",
                ((innings.event && innings.event == "declared") ? "d" : "")
            ].join('');

            out.overs = innings.overs;

            if (+data.match.scheduled_overs > 0) {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "Run rate: "+innings.run_rate;
                        break;
                    default:
                        out.lead =
                            "Need "+(1-innings.lead)+" from "+
                            (innings.remaining_overs <= 10.0 ? innings.remaining_balls : innings.remaining_overs+" ov");
                        break;
                }
            }
            else {
                switch (+innings.innings_number) {
                    case 1:
                        out.lead = "First innings";
                        break;
                    case 4:
                        out.lead = "Target "+(innings.target);
                        break;
                    default:
                        out.lead =
                            innings.lead < 0 ? "Trail by "+(-innings.lead) :
                            innings.lead > 0 ? "Lead by "+innings.lead :
                                            "Scores level";
                }
            }

            var striker = data.live.batting.filter(function (player) { return player.live_current_name == "striker"; })[0];
            var nonstriker = data.live.batting.filter(function (player) { return player.live_current_name == "non-striker"; })[0];

            if (!striker) {
                striker = nonstriker;
                nonstriker = null;
            }

            var shorten = function (n) {
                var bits = n.split(' ');
                for (var i = 0; i < bits.length-1; i++)
                    bits[i] = bits[i].substr(0,1);
                return bits.join('.');
            };

            if (striker) {
                var striker_name = players[striker.player_id].card_short;
                if (striker_name.length > 10 && players[striker.player_id].popular_name.length > 0)
                    striker_name = players[striker.player_id].popular_name;
                if (striker_name.length > 10)
                    striker_name = shorten(striker_name);
                out.striker_name = striker_name + (nonstriker ? "*" : "");
                out.striker_stats = striker.runs+" ("+striker.balls_faced+")";
            }

            if (nonstriker) {
                var nonstriker_name = players[nonstriker.player_id].card_short;
                if (nonstriker_name.length > 10 && players[nonstriker.player_id].popular_name.length > 0)
                    nonstriker_name = players[nonstriker.player_id].popular_name;
                if (nonstriker_name.length > 10)
                    nonstriker_name = shorten(nonstriker_name);
                out.nonstriker_name = nonstriker_name;
                out.nonstriker_stats = nonstriker.runs+" ("+nonstriker.balls_faced+")";
            }

            var bowler = data.live.bowling.filter(function (player) { return player.live_current_name == "current bowler"; })[0];
            if (bowler) {
                var bowler_name = players[bowler.player_id].card_short;
                if (bowler_name.length > 10) bowler_name = players[bowler.player_id].popular_name;
                out.bowler_name = bowler_name;
                out.bowler_stats = bowler.overs+"-"+bowler.maidens+"-"+bowler.conceded+"-"+bowler.wickets;
            }

            break;
        }
    }
}

function new_out () {
    var out = {
        "score":"",
        "overs":"",
        "lead":"",
        "striker_name":"",
        "striker_stats":"",
        "nonstriker_name":"",
        "nonstriker_stats":"",
        "bowler_name":"",
        "bowler_stats":"",
        "fact":""
    };
    return out;
}

function update () {
    var out = new_out();
    var matchId = localStorage.getItem("matchId");
    if (!matchId) {
        out.striker_name = "No match selected";
        out.nonstriker_name = "in config.";
        Pebble.sendAppMessage(out);
        return;
    }
    var req = new XMLHttpRequest();
    req.open('GET', "http://www.espncricinfo.com/ci/engine/match/"+matchId+".json");
    req.onload = function(e) {
        if (req.readyState == 4) {
            if(req.status == 200) {
                console.log("got new data, updating");

                var data = JSON.parse(req.responseText);
                if (data) {
                    unpack_data(data, out);
                    console.log(JSON.stringify(out));
                    Pebble.sendAppMessage(out);
                }

            } else {
                console.log("Error");
            }
        }
    };
    req.send(null);
}

Pebble.addEventListener("ready", function (e) {
    console.log("connected, doing first update");
    update();
});

Pebble.addEventListener("appmessage", function (e) {
    console.log("tick, doing update");
    update();
});

Pebble.addEventListener("showConfiguration", function (e) {
    console.log("config requested");
    Pebble.openURL("http://eatenbyagrue.org/a/sixfour.psgi");
});

Pebble.addEventListener("webviewclosed", function (e) {
    console.log("config closed, response: "+e.response);
    if (e.response !== "CANCELLED") {
        localStorage.setItem("matchId", e.response);
        update();
    }
});
<|endoftext|>


<commit_before>"use strict";

const SHELL = require('shelljs');
const PATH = require('path');
const FS = require('fs');

const GLOB = require('glob');

// const COMBINATORICS = require('js-combinatorics');

// const PACKAGE_VERSION = require('../../package.json').version;
// const HOSTNAME = require('os').hostname();
// const NUMBER_OF_ITERATIONS = 1
// const BROWSER = "firefox"

// let connections = [];
// connections.push("cable");
// connections.push("3g");

// let names = [];
// names.push("0-0_starting-point")
// names.push("1-1_gzip")
// names.push("1-2_image-optimization")
// names.push("1-3_asset-minification")
// names.push("2-1_icon-inlining")
// names.push("2-2_asset-bundling")
// names.push("2-3_asset-bundling-shaking")
// names.push("3-1_js-deferring")
// names.push("3-2_critical-css-inlining")

// let http_versions = [];
// // http_versions.push("1.1");
// http_versions.push("2.0");

// let combinations = COMBINATORICS.cartesianProduct(names, connections, http_versions).toArray()

// combinations.forEach(combination => {

//     let name = combination[0]
//     let connection = combination[1]
//     let http_version = combination[2]

//     console.log("measuring ", name, connection, http_version);

//     let url = "";

//     if (http_version === "1.1")
//         url = "https://pagespeed-benchmark-http-1.4pi.eu/best-practices/" + name + ".html"
//     else
//         url = "https://pagespeed-benchmark.4pi.eu/best-practices/" + name + ".html"

//     let dockerRunCommand =
//         'docker run --privileged --shm-size=1g --rm -v "$(pwd)":/browsertime-results sitespeedio/browsertime -n ' + NUMBER_OF_ITERATIONS + ' --speedIndex --viewPort 1024x800 -b ' + BROWSER + ' -c ' + connection + ' ' + url;

//     let resultPath = PATH.join(__dirname, '/../../_measurements/', PACKAGE_VERSION, HOSTNAME, connection, BROWSER);

//     console.log("cd to ", resultPath)

//     SHELL.mkdir('-p', resultPath)
//     SHELL.cd(resultPath)

//     if (SHELL.exec(dockerRunCommand).code !== 0) {
//         SHELL.echo('Error: docker Command failed');
//         SHELL.exit(1);
//     } else {

//         SHELL.echo('Succes: ' + dockerRunCommand);
//     }
// })

const jpgs = GLOB.sync("_measurements/**/*.jpg")

jpgs.forEach(f => {

    console.log(f)

    FS.unlinkSync(f)
})

const videoDirs = GLOB.sync("_measurements/**/video")
var exec = require('child_process').exec;

videoDirs.forEach(f => {

    console.log(f)

    exec('rm -r ' + f, function (err, stdout, stderr) {
        // your callback goes here
    });

})

const hars = GLOB.sync("_measurements/**/*.har")

hars.forEach(f => {

    console.log(f)

    FS.unlinkSync(f)
})

<commit_msg>Removes comments<commit_after>"use strict";

const SHELL = require('shelljs');
const PATH = require('path');
const FS = require('fs');

const GLOB = require('glob');

const COMBINATORICS = require('js-combinatorics');

const PACKAGE_VERSION = require('../../package.json').version;
const HOSTNAME = require('os').hostname();
const NUMBER_OF_ITERATIONS = 1
const BROWSER = "firefox"

let connections = [];
connections.push("cable");
connections.push("3g");

let names = [];
names.push("0-0_starting-point")
names.push("1-1_gzip")
names.push("1-2_image-optimization")
names.push("1-3_asset-minification")
names.push("2-1_icon-inlining")
names.push("2-2_asset-bundling")
names.push("2-3_asset-bundling-shaking")
names.push("3-1_js-deferring")
names.push("3-2_critical-css-inlining")

let http_versions = [];
// http_versions.push("1.1");
http_versions.push("2.0");

let combinations = COMBINATORICS.cartesianProduct(names, connections, http_versions).toArray()

combinations.forEach(combination => {

    let name = combination[0]
    let connection = combination[1]
    let http_version = combination[2]

    console.log("measuring ", name, connection, http_version);

    let url = "";

    if (http_version === "1.1")
        url = "https://pagespeed-benchmark-http-1.4pi.eu/best-practices/" + name + ".html"
    else
        url = "https://pagespeed-benchmark.4pi.eu/best-practices/" + name + ".html"

    let dockerRunCommand =
        'docker run --privileged --shm-size=1g --rm -v "$(pwd)":/browsertime-results sitespeedio/browsertime -n ' + NUMBER_OF_ITERATIONS + ' --speedIndex --viewPort 1024x800 -b ' + BROWSER + ' -c ' + connection + ' ' + url;

    let resultPath = PATH.join(__dirname, '/../../_measurements/', PACKAGE_VERSION, HOSTNAME, connection, BROWSER);

    console.log("cd to ", resultPath)

    SHELL.mkdir('-p', resultPath)
    SHELL.cd(resultPath)

    if (SHELL.exec(dockerRunCommand).code !== 0) {
        SHELL.echo('Error: docker Command failed');
        SHELL.exit(1);
    } else {

        SHELL.echo('Succes: ' + dockerRunCommand);
    }
})

const jpgs = GLOB.sync("_measurements/**/*.jpg")

jpgs.forEach(f => {

    console.log(f)

    FS.unlinkSync(f)
})

const videoDirs = GLOB.sync("_measurements/**/video")
var exec = require('child_process').exec;

videoDirs.forEach(f => {

    console.log(f)

    exec('rm -r ' + f, function (err, stdout, stderr) {
        // your callback goes here
    });

})

const hars = GLOB.sync("_measurements/**/*.har")

hars.forEach(f => {

    console.log(f)

    FS.unlinkSync(f)
})

<|endoftext|>


<commit_before>export { Base, To };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";
import * as FloatValue from "../FloatValue.js";

/**
 * A base class for extracting and keeping weights. It composes of a Float32Array and a shape. It can
 * be used as CNN (depthwise, pointwise and bias) filter weights.
 *
 * @member {number} elementOffsetBegin
 *   The beginning position (i.e. array index) to extract from inputWeightsArray. If this value is negative, the extraction will
 * fail (i.e. ( bInitOk == false ) ).
 *
 * @member {number} elementOffsetEnd
 *   The ending position (i.e. array index) after extracting from inputWeightsArray. It is not inclusive and can be used as the
 * beginning position of next (another) extraction. It is meaningful only if ( bInitOk == true ).
 *
 * @member {number} elementExtractedCount
 *   How many weights (i.e. elements) will be extracted from inputWeightsArray. It should be a non-negative integer value.
 *
 *     - If too many elements need to be extracted (exceeds the inputWeightsArray.length) or elementExtractedCount is NaN or
 *         elementExtractedCount is negative, the extraction will fail (i.e. ( bInitOk == false ) ).
 *
 * @member {boolean} bInitOk
 *   If .init() success, it will be true.
 */
class Base extends Recyclable.Root {

  /**
   * Used as default Weights.Base provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "Weights.Base.Pool", Base, Base.setAsConstructor );

  /**
   * Just record the begin and length without checking them. Please call extract() to finish extracting.
   */
  constructor( elementOffsetBegin, elementExtractedCount ) {
    super();
    Base.setAsConstructor_self.call( this, elementOffsetBegin, elementExtractedCount );
  }

  /** @override */
  static setAsConstructor( elementOffsetBegin, elementExtractedCount ) {
    super.setAsConstructor();
    Base.setAsConstructor_self.call( this, elementOffsetBegin, elementExtractedCount );
    return this;
  }

  /** @override */
  static setAsConstructor_self( elementOffsetBegin, elementExtractedCount ) {
    this.elementOffsetBegin = elementOffsetBegin;
    this.elementExtractedCount = elementExtractedCount;
  }

  /** @override */
  disposeResources() {
    this.bInitOk = undefined;
    this.elementOffsetEnd = undefined;
    this.elementExtractedCount = undefined;
    this.elementOffsetBegin = undefined;
    super.disposeResources();
  }

  /**
   * Determine .elementOffsetEnd according to the inputWeightArray.lnegth, .elementOffsetBegin and .elementExtractedCount.
   *
   * @param {number[]|Float32Array} inputWeightArray
   *   The underlying weights source array to be extracted from. It will not be kept by this object.
   *
   * @return {boolean} Return false, if extraction failed.
   */
  init( inputWeightArray ) {
    this.bInitOk = false;

    if ( Number.isNaN( this.elementExtractedCount ) )
      return false;  // Failed, if NaN.

    if ( this.elementExtractedCount < 0 )
      return false;  // Failed, if negative.

    this.elementOffsetEnd = this.elementOffsetBegin + this.elementExtractedCount;
    if ( this.elementOffsetEnd > inputWeightArray.length )
      return false;  // Failed, if out of array index range.

    this.bInitOk = true;
    return true;     // Success.
  }

//!!! (2021/12/98 Remarked) Using bounds [ -2^24, +2^24 ] seems enough.
//   /**
//    * Confirm:
//    *   - Every element is not NaN. (If it is, become 0.)
//    *   - The smallest non-zero Math.abs( element ) is 2^(-24). (i.e. If ( -2^(-24) < element < +2^(-24) ), become 0.)
//    *   - The largest Math.abs( element ) is 2^(+24).
//    *
//    * This is mainly for ensuring PointDepthPoint's output is legal float32:
//    *   - PointDepthPoint is composed of 3 convolutions: pointwise1-depthwise-pointwise2.
//    *   - Suppose every convolution has 4096 (= 2^12) input channels. (The bias is viewed as the last (i.e. 4095th) channels.)
//    *   - Suppose depthwise uses 4x4 (= 2^4) filter for every channel.
//    *   - Suppose every convolution does not have activation function (so that its result is unbounded).
//    *   - If every Math.abs( pointwise1Input ) is restected to 0 or between [ 2^(-24), 2^24 ].
//    *   - If every Math.abs( weight ) of pointwise1, depthwise, pointwise2 is restected to 0 or between [ 2^(-24), 2^24 ].
//    *   - The Math.abs( pointwise1Result ) will be restriced to 0 or between [ 2^(-(24+24)), 2^(24+24+12) ] = [ 2^(-48), 2^60 ].
//    *   - The Math.abs( depthwiseResult  ) will be restriced to 0 or between [ 2^(-(48+24)), 2^(60+24+4)  ] = [ 2^(-72), 2^88 ].
//    *   - The Math.abs( pointwise2Result ) will be restriced to 0 or between [ 2^(-(72+24)), 2^(88+24+12) ] = [ 2^(-96), 2^124 ].
//    *   - So the result is still legal float32 because Math.abs( float32 ) could be either 0 or between [ 2^(-126), 2^126 ].
//    *
//    * The 2^24 as input element should be enough for most situation:
//    *   - Color image: The R, G, B, A channels are 8 bits (2^8) individually.
//    *   - Sound track: 8 bits (2^8), or 16 bits (2^16), or 20 bits (2^20), or 24 bits (2^24). But not 32 bits (2^32)
//    *   - Unicode character code point: 21 bits (2^21).
//    *
//    *
//    *

//    *              -2^(+24)       -2^(-24)                      +2^(-24)       +2^(+24)
//    *            NEGATIVE_MIN   NEGATIVE_MAX        0         POSITIVE_MIN   POSITIVE_MAX
//    *   --------------|--------------|--------------|--------------|--------------|--------------
//    *
//    * Restricted to:
//    *                 |--------------|00000000000000000000000000000|--------------|
//    *

//    *
//    *
//    * @param {Float32Array} source
//    *   The source Float32Array.
//    *
//    * @return {Float32Array}
//    *   Return a copy of source. Every element (float32):
//    *     - If ( Number.isNaN( element ) == true ), let it become 0.
//    *     - If ( element != 0 ), Math.abs( element ) will be restricted between [ 2^(-24), 2^24 ].
//    *     - ( Math.sign( element ) * Math.abs( element ) ) will be restricted between [ -2^(24), 2^24 ].
//    */
//   static Float32Array_CloneLegal( sourceArray ) {
//     const POSITIVE_MIN = Math.pow( 2, -24 );
//     const POSITIVE_MAX = Math.pow( 2, +24 );
//     const NEGATIVE_MIN = - POSITIVE_MAX; // - Math.pow( 2, +24 )
//     const NEGATIVE_MAX = - POSITIVE_MIN; // - Math.pow( 2, -24 )
//
//     let resultArray = new Float32Array( sourceArray.length );
//     for ( let i = 0; i < sourceArray.length; ++i ) {
//       let element = sourceArray[ i ];
//
//       let restricted;
//       if ( Number.isNaN( element ) ) {
//         restricted = 0;
//
//       } else if ( element >= POSITIVE_MIN ) {
//         if ( element > POSITIVE_MAX )
//           restricted = POSITIVE_MAX;
//         else
//           restricted = element;
//
//       } else if ( element <= NEGATIVE_MAX ) {
//         if ( element < NEGATIVE_MIN )
//           restricted = NEGATIVE_MIN;
//         else
//           restricted = element;
//
//       } else { // ( NEGATIVE_MAX < element < POSITIVE_MIN ) (Note: Zero is inside.)
//         restricted = 0;
//       }
//
//       resultArray[ i ] = restricted;
//     }
//     return resultArray;
//   }

}

//!!! ...unfinished... (2022/01/10)
/*
 * When ( x < 0.0000001 ), the tf.tanh( x ) will be 0.
 * That is, the precision of tf.tanh() may be 0.0000001 (= 1e-7 ).
 *
 * Consider the ActivationEscaping inputDomainLinear of tanh() is [ -0.005, +0.005 ] simultaneously. The value bounds of result
 * after filter-bias (no matter pointwise or depthwise) should be compatible with [ -0.005, +0.005 ] with precision 0.0000001 (= 1e-7 ).
 *
 * For example,
 *   - [ -0.005, +0.005 ] with precision 0.0000001 (= 1e-7 ).
 *   - [ -0.5, +0.5 ] with precision 0.00001 (= 1e-5 ).
 *   - [ -5, +5 ] with precision 0.0001 (= 1e-4 ).
 *   - [ -50, +50 ] with precision 0.001 (= 1e-3 ).
 *   - [ -500, +500 ] with precision 0.01 (= 1e-2 ).
 *   - [ -5000, +5000 ] with precision 0.1 (= 1e-1 ).
 *   - [ -50000, +50000 ] with precision 1 (= 1e+0 ).
 *   - [ -5e+4, +5e+4 ] with precision 1 (= 1e+0 ).
 *   - [ 0, +100000 ] with precision 1 (= 1e+0 ).
 *   - [ 0, +1e+5 ] with precision 1 (= 1e+0 ).
 *
 *
 *
 *
 *
 * For this reason, the Weights.Base.ValueBounds may be more less than [ -( 2 ** 24 ), +( 2 ** 24 ) ].
 * Perhaps, [ -1, +1 ] is better.?
 *
 */

/**
 * This is mainly for ensuring Block's output is legal float32:
 *   - Block is composed of 3 convolutions: pointwise1-depthwise-pointwise2.
 *   - Suppose every convolution has 4096 (= 2^12) input channels. (The bias is viewed as the last (i.e. 4095th) channels.)
 *   - Suppose depthwise uses 4x4 (= 2^4) filter for every channel.
 *   - Suppose every convolution does not have activation function (so that its result is unbounded).
 *   - If every element of pointwise1Input is bounds to [ -2^24, +2^24 ].
 *   - If every element of weights of pointwise1, depthwise, pointwise2 is bounds to [ -2^24, +2^24 ].
 *   - Every element of pointwise1Result will be bounds to [ -2^(24+24+12), +2^(24+24+12) ] = [ -2^60,  +2^60  ].
 *   - Every element of depthwiseResult  will be bounds to [ -2^(60+24+4),  +2^(60+24+4)  ] = [ -2^88,  +2^88  ].
 *   - Every element of pointwise2Result will be bounds to [ -2^(88+24+12), +2^(88+24+12) ] = [ -2^124, +2^124 ].
 *   - So the result is still legal float32 (which could represent floating-point value between [ -2^126, +2^126 ]).
 *
 * The 2^24 as input element should be enough for most situation:
 *   - Color image: The R, G, B, A channels are 8 bits (2^8) individually.
 *   - Sound track: 8 bits (2^8), or 16 bits (2^16), or 20 bits (2^20), or 24 bits (2^24). But not 32 bits (2^32)
 *   - Unicode character code point: 21 bits (2^21).
 */
Base.ValueBounds = new FloatValue.Bounds( -( 2 ** 24 ), +( 2 ** 24 ) );

/**
 * Provides static methods for converting weight to parameter.
 */
class To {

  /** @return {number} Return the absolute value of the trucated value (i.e. integer). */
  static IntegerZeroPositive( v ) {
    return Math.abs( Math.trunc( v ) );
  }

  /**
   * @param {any[]} lookUpArray
   *   The value will be converted into an integer between [ 0, lookUpArray.length ). Use it as array index.
   * Return lookUpArray[ index ].
   *
   * @return {any}
   *   Convert number value into an integer between [ 0, lookUpArray.length ). Use it as array index. Return
   * the looked up element value.
   */
  static ArrayElement( value, lookUpArray ) {
    let i = To.IntegerZeroPositive( value ) % lookUpArray.length;
    return lookUpArray[ i ];
  }

}

<commit_msg>Update Weights_Base.js<commit_after>export { Base, To };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";
import * as FloatValue from "../FloatValue.js";

/**
 * A base class for extracting and keeping weights. It composes of a Float32Array and a shape. It can
 * be used as CNN (depthwise, pointwise and bias) filter weights.
 *
 * @member {number} elementOffsetBegin
 *   The beginning position (i.e. array index) to extract from inputWeightsArray. If this value is negative, the extraction will
 * fail (i.e. ( bInitOk == false ) ).
 *
 * @member {number} elementOffsetEnd
 *   The ending position (i.e. array index) after extracting from inputWeightsArray. It is not inclusive and can be used as the
 * beginning position of next (another) extraction. It is meaningful only if ( bInitOk == true ).
 *
 * @member {number} elementExtractedCount
 *   How many weights (i.e. elements) will be extracted from inputWeightsArray. It should be a non-negative integer value.
 *
 *     - If too many elements need to be extracted (exceeds the inputWeightsArray.length) or elementExtractedCount is NaN or
 *         elementExtractedCount is negative, the extraction will fail (i.e. ( bInitOk == false ) ).
 *
 * @member {boolean} bInitOk
 *   If .init() success, it will be true.
 */
class Base extends Recyclable.Root {

  /**
   * Used as default Weights.Base provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "Weights.Base.Pool", Base, Base.setAsConstructor );

  /**
   * Just record the begin and length without checking them. Please call extract() to finish extracting.
   */
  constructor() {
    super();
    Base.setAsConstructor_self.call( this );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    Base.setAsConstructor_self.call( this );
    return this;
  }

  /** @override */
  static setAsConstructor_self() {
    // Do nothing.
  }

  /** @override */
  disposeResources() {
    this.bInitOk = undefined;
    this.elementOffsetEnd = undefined;
    this.elementExtractedCount = undefined;
    this.elementOffsetBegin = undefined;
    super.disposeResources();
  }

  /**
   * Determine .elementOffsetEnd according to the inputWeightArray.lnegth, .elementOffsetBegin and .elementExtractedCount.
   *
   * @param {number[]|Float32Array} inputWeightArray
   *   The underlying weights source array to be extracted from. It will not be kept by this object.
   *
   * @return {boolean} Return false, if extraction failed.
   */
  init( inputWeightArray, elementOffsetBegin, elementExtractedCount ) {
    this.elementOffsetBegin = elementOffsetBegin;
    this.elementExtractedCount = elementExtractedCount;
    this.bInitOk = false;

    if ( Number.isNaN( this.elementExtractedCount ) )
      return false;  // Failed, if NaN.

    if ( this.elementExtractedCount < 0 )
      return false;  // Failed, if negative.

    this.elementOffsetEnd = this.elementOffsetBegin + this.elementExtractedCount;
    if ( this.elementOffsetEnd > inputWeightArray.length )
      return false;  // Failed, if out of array index range.

    this.bInitOk = true;
    return true;     // Success.
  }

//!!! (2021/12/98 Remarked) Using bounds [ -2^24, +2^24 ] seems enough.
//   /**
//    * Confirm:
//    *   - Every element is not NaN. (If it is, become 0.)
//    *   - The smallest non-zero Math.abs( element ) is 2^(-24). (i.e. If ( -2^(-24) < element < +2^(-24) ), become 0.)
//    *   - The largest Math.abs( element ) is 2^(+24).
//    *
//    * This is mainly for ensuring PointDepthPoint's output is legal float32:
//    *   - PointDepthPoint is composed of 3 convolutions: pointwise1-depthwise-pointwise2.
//    *   - Suppose every convolution has 4096 (= 2^12) input channels. (The bias is viewed as the last (i.e. 4095th) channels.)
//    *   - Suppose depthwise uses 4x4 (= 2^4) filter for every channel.
//    *   - Suppose every convolution does not have activation function (so that its result is unbounded).
//    *   - If every Math.abs( pointwise1Input ) is restected to 0 or between [ 2^(-24), 2^24 ].
//    *   - If every Math.abs( weight ) of pointwise1, depthwise, pointwise2 is restected to 0 or between [ 2^(-24), 2^24 ].
//    *   - The Math.abs( pointwise1Result ) will be restriced to 0 or between [ 2^(-(24+24)), 2^(24+24+12) ] = [ 2^(-48), 2^60 ].
//    *   - The Math.abs( depthwiseResult  ) will be restriced to 0 or between [ 2^(-(48+24)), 2^(60+24+4)  ] = [ 2^(-72), 2^88 ].
//    *   - The Math.abs( pointwise2Result ) will be restriced to 0 or between [ 2^(-(72+24)), 2^(88+24+12) ] = [ 2^(-96), 2^124 ].
//    *   - So the result is still legal float32 because Math.abs( float32 ) could be either 0 or between [ 2^(-126), 2^126 ].
//    *
//    * The 2^24 as input element should be enough for most situation:
//    *   - Color image: The R, G, B, A channels are 8 bits (2^8) individually.
//    *   - Sound track: 8 bits (2^8), or 16 bits (2^16), or 20 bits (2^20), or 24 bits (2^24). But not 32 bits (2^32)
//    *   - Unicode character code point: 21 bits (2^21).
//    *
//    *
//    *

//    *              -2^(+24)       -2^(-24)                      +2^(-24)       +2^(+24)
//    *            NEGATIVE_MIN   NEGATIVE_MAX        0         POSITIVE_MIN   POSITIVE_MAX
//    *   --------------|--------------|--------------|--------------|--------------|--------------
//    *
//    * Restricted to:
//    *                 |--------------|00000000000000000000000000000|--------------|
//    *

//    *
//    *
//    * @param {Float32Array} source
//    *   The source Float32Array.
//    *
//    * @return {Float32Array}
//    *   Return a copy of source. Every element (float32):
//    *     - If ( Number.isNaN( element ) == true ), let it become 0.
//    *     - If ( element != 0 ), Math.abs( element ) will be restricted between [ 2^(-24), 2^24 ].
//    *     - ( Math.sign( element ) * Math.abs( element ) ) will be restricted between [ -2^(24), 2^24 ].
//    */
//   static Float32Array_CloneLegal( sourceArray ) {
//     const POSITIVE_MIN = Math.pow( 2, -24 );
//     const POSITIVE_MAX = Math.pow( 2, +24 );
//     const NEGATIVE_MIN = - POSITIVE_MAX; // - Math.pow( 2, +24 )
//     const NEGATIVE_MAX = - POSITIVE_MIN; // - Math.pow( 2, -24 )
//
//     let resultArray = new Float32Array( sourceArray.length );
//     for ( let i = 0; i < sourceArray.length; ++i ) {
//       let element = sourceArray[ i ];
//
//       let restricted;
//       if ( Number.isNaN( element ) ) {
//         restricted = 0;
//
//       } else if ( element >= POSITIVE_MIN ) {
//         if ( element > POSITIVE_MAX )
//           restricted = POSITIVE_MAX;
//         else
//           restricted = element;
//
//       } else if ( element <= NEGATIVE_MAX ) {
//         if ( element < NEGATIVE_MIN )
//           restricted = NEGATIVE_MIN;
//         else
//           restricted = element;
//
//       } else { // ( NEGATIVE_MAX < element < POSITIVE_MIN ) (Note: Zero is inside.)
//         restricted = 0;
//       }
//
//       resultArray[ i ] = restricted;
//     }
//     return resultArray;
//   }

}

//!!! ...unfinished... (2022/01/10)
/*
 * When ( x < 0.0000001 ), the tf.tanh( x ) will be 0.
 * That is, the precision of tf.tanh() may be 0.0000001 (= 1e-7 ).
 *
 * Consider the ActivationEscaping inputDomainLinear of tanh() is [ -0.005, +0.005 ] simultaneously. The value bounds of result
 * after filter-bias (no matter pointwise or depthwise) should be compatible with [ -0.005, +0.005 ] with precision 0.0000001 (= 1e-7 ).
 *
 * For example,
 *   - [ -0.005, +0.005 ] with precision 0.0000001 (= 1e-7 ).
 *   - [ -0.5, +0.5 ] with precision 0.00001 (= 1e-5 ).
 *   - [ -5, +5 ] with precision 0.0001 (= 1e-4 ).
 *   - [ -50, +50 ] with precision 0.001 (= 1e-3 ).
 *   - [ -500, +500 ] with precision 0.01 (= 1e-2 ).
 *   - [ -5000, +5000 ] with precision 0.1 (= 1e-1 ).
 *   - [ -50000, +50000 ] with precision 1 (= 1e+0 ).
 *   - [ -5e+4, +5e+4 ] with precision 1 (= 1e+0 ).
 *   - [ 0, +100000 ] with precision 1 (= 1e+0 ).
 *   - [ 0, +1e+5 ] with precision 1 (= 1e+0 ).
 *
 *
 *
 *
 *
 * For this reason, the Weights.Base.ValueBounds may be more less than [ -( 2 ** 24 ), +( 2 ** 24 ) ].
 * Perhaps, [ -1, +1 ] is better.?
 *
 */

/**
 * This is mainly for ensuring Block's output is legal float32:
 *   - Block is composed of 3 convolutions: pointwise1-depthwise-pointwise2.
 *   - Suppose every convolution has 4096 (= 2^12) input channels. (The bias is viewed as the last (i.e. 4095th) channels.)
 *   - Suppose depthwise uses 4x4 (= 2^4) filter for every channel.
 *   - Suppose every convolution does not have activation function (so that its result is unbounded).
 *   - If every element of pointwise1Input is bounds to [ -2^24, +2^24 ].
 *   - If every element of weights of pointwise1, depthwise, pointwise2 is bounds to [ -2^24, +2^24 ].
 *   - Every element of pointwise1Result will be bounds to [ -2^(24+24+12), +2^(24+24+12) ] = [ -2^60,  +2^60  ].
 *   - Every element of depthwiseResult  will be bounds to [ -2^(60+24+4),  +2^(60+24+4)  ] = [ -2^88,  +2^88  ].
 *   - Every element of pointwise2Result will be bounds to [ -2^(88+24+12), +2^(88+24+12) ] = [ -2^124, +2^124 ].
 *   - So the result is still legal float32 (which could represent floating-point value between [ -2^126, +2^126 ]).
 *
 * The 2^24 as input element should be enough for most situation:
 *   - Color image: The R, G, B, A channels are 8 bits (2^8) individually.
 *   - Sound track: 8 bits (2^8), or 16 bits (2^16), or 20 bits (2^20), or 24 bits (2^24). But not 32 bits (2^32)
 *   - Unicode character code point: 21 bits (2^21).
 */
Base.ValueBounds = new FloatValue.Bounds( -( 2 ** 24 ), +( 2 ** 24 ) );

/**
 * Provides static methods for converting weight to parameter.
 */
class To {

  /** @return {number} Return the absolute value of the trucated value (i.e. integer). */
  static IntegerZeroPositive( v ) {
    return Math.abs( Math.trunc( v ) );
  }

  /**
   * @param {any[]} lookUpArray
   *   The value will be converted into an integer between [ 0, lookUpArray.length ). Use it as array index.
   * Return lookUpArray[ index ].
   *
   * @return {any}
   *   Convert number value into an integer between [ 0, lookUpArray.length ). Use it as array index. Return
   * the looked up element value.
   */
  static ArrayElement( value, lookUpArray ) {
    let i = To.IntegerZeroPositive( value ) % lookUpArray.length;
    return lookUpArray[ i ];
  }

}

<|endoftext|>


<commit_before>import electron from 'electron'
import { Application } from 'spectron'

const beforeEach = function () {
  this.app = new Application({
    path: electron,
    args: ['.']
  })
  return this.app.start()
}

const afterEach = function () {
  if (this.app && this.app.isRunning()) {
    return this.app.stop()
  }
}

const asyncTimeout = ms => new Promise(resolve => setTimeout(resolve, ms))

export default {
  beforeEach,
  afterEach,
  asyncTimeout
}
<commit_msg>Trying to fix circleci test<commit_after>import electron from 'electron'
import { Application } from 'spectron'

const beforeEach = function (done) {
  this.app = new Application({
    path: electron,
    args: ['.']
  })
  this.app.start()
    then(done)
}

const afterEach = function (done) {
  if (this.app && this.app.isRunning()) {
    this.app.stop()
      then(done)
  } else {
    done()
  }
}

const asyncTimeout = ms => new Promise(resolve => setTimeout(resolve, ms))

export default {
  beforeEach,
  afterEach,
  asyncTimeout
}
<|endoftext|>


<commit_before>!function () {

    function main () {
        var canvas = document.getElementById("canvas")
          , context = canvas.getContext("2d")

        playGame(context, new Player(50, 350), new Player(650, 350), new Ball())
    }

    function Player (x, y, vx, vy, score) {
        this.x = x || 50,
        this.y = y || 350,
        this.vx = vx || 0,
        this.vy = vy || 0,
        this.score = score || 0
    }

    function Ball (x, y, vx, vy) {
        this.x = x || 350,
        this.y = y || 50,
        this.vx = vx || 4,
        this.vy = vy || 2
    }

    function playGame(ctx, p1, p2, ball) {
        registerKeyListeners(p1, p2)
        startGameLoop(ctx, p1, p2, ball)
    }

    function registerKeyListeners(p1, p2) {
        var dv = 5.0
        document.addEventListener("keydown", function (e) {
            function movePlayer(p, l, u, r) {
                if (e.keyCode == l) {
                    p.x += p.vx
                    p.vx -= dv
                } else if (e.keyCode == u) {
                    if (p.y >= 350) {
                        p.vy -= 5 * dv
                        p.y += p.vy
                    } else {
                        p.x += p.vx
                        p.y += p.vy
                    }
                } else if (e.keyCode == r) {
                    p.x += p.vx
                    p.vx += dv
                }
            }
            movePlayer(p1, 65, 87, 68)
            movePlayer(p2, 37, 38, 39)
        })
    }

    function startGameLoop (ctx, p1, p2, ball) {
        !function loop(ctx, p1, p2, ball) {
            drawBackground(ctx)
            move(p1, p2, ball)
            collide(p1, p2, ball)
            score(p1, p2, ball)
            drawGame(ctx, p1, p2, ball)
            setTimeout(function () {
                loop(ctx, p1, p2, ball)
            }, 17)
        }(ctx, p1, p2, ball)
    }

    function move (p1, p2, ball) {
        function lowerBound(p) {
            if (p.y > 350) p.y = 350
            p.vy += 0.5
        }
        function tick(p) {
            p.x += p.vx
            p.y += p.vy
            p.vx *= 0.9
            p.vy *= 0.9
        }
        lowerBound(p1)
        lowerBound(p2)
        tick(p1)
        tick(p2)
        ball.x += ball.vx
        ball.y += ball.vy
        ball.vy += 0.25
    }

    function collide(p1, p2, ball) {
        collideWithWalls(p1, 25)
        collideWithWalls(p2, 25)
        collideWithWalls(ball, 10)
    }

    function collideWithWalls (x, r) {
        if(x.x < r || x.x > (700 - r) || r > 10 && Math.abs(x.x-375) < r) {
            x.vx *= -1
            x.x += x.vx
        }
    }

    function score(p1, p2, ball) {
        if(ball.y > 360) {
            if(ball.x < 375) p2.score += 1
            else p1.score += 1
            ball.x = 350
            ball.y = 50
            ball.vx = 4
            ball.vy = 2
        }
    }

    function drawGame(ctx, p1, p2, ball) {
        ctx.font = "40pt Helvetica"
        ctx.fillText(p1.score, 25, 50)
        ctx.fillText(p2.score, 650, 50)
        ctx.fillStyle = "#FF0000"
        ctx.beginPath()
        ctx.arc(p1.x, p1.y, 25, 0, 2*Math.PI, false)
        ctx.fill()
        ctx.stroke()
        ctx.fillStyle = "#0000FF"
        ctx.beginPath()
        ctx.arc(p2.x, p2.y, 25, 0, 2*Math.PI, false)
        ctx.fill()
        ctx.stroke()
        ctx.fillStyle = "#00FF00"
        ctx.beginPath()
        ctx.arc(ball.x, ball.y, 10, 0, 2*Math.PI, false)
        ctx.fill()
        ctx.stroke()
    }

    function drawBackground(ctx) {
        ctx.fillStyle = "#999"
        ctx.fillRect(0, 350, 750, 400)
        ctx.fillStyle = "#FFF"
        ctx.fillRect(0, 0, 750, 350)
        ctx.fillStyle = "#3F3"
        ctx.fillRect(375, 320, 1, 60)
    }

    main()
} ()<commit_msg>proper collision detection, feature parity as far as I can tell<commit_after>!function () {

    function main () {
        var canvas = document.getElementById("canvas")
          , context = canvas.getContext("2d")

        playGame(context, new Player(50, 350), new Player(650, 350), new Ball())
    }

    function Player (x, y, vx, vy, score) {
        this.x = x || 50,
        this.y = y || 350,
        this.vx = vx || 0,
        this.vy = vy || 0,
        this.score = score || 0
    }

    function Ball (x, y, vx, vy) {
        this.x = x || 350,
        this.y = y || 50,
        this.vx = vx || 4,
        this.vy = vy || 2
    }

    function playGame(ctx, p1, p2, ball) {
        registerKeyListeners(p1, p2)
        startGameLoop(ctx, p1, p2, ball)
    }

    function registerKeyListeners(p1, p2) {
        var dv = 5.0
        document.addEventListener("keydown", function (e) {
            function movePlayer(p, l, u, r) {
                if (e.keyCode == l) {
                    p.x += p.vx
                    p.vx -= dv
                } else if (e.keyCode == u) {
                    if (p.y >= 350) {
                        p.vy -= 5 * dv
                        p.y += p.vy
                    } else {
                        p.x += p.vx
                        p.y += p.vy
                    }
                } else if (e.keyCode == r) {
                    p.x += p.vx
                    p.vx += dv
                }
            }
            movePlayer(p1, 65, 87, 68)
            movePlayer(p2, 37, 38, 39)
        })
    }

    function startGameLoop (ctx, p1, p2, ball) {
        !function loop(ctx, p1, p2, ball) {
            drawBackground(ctx)
            move(p1, p2, ball)
            collide(p1, p2, ball)
            score(p1, p2, ball)
            drawGame(ctx, p1, p2, ball)
            setTimeout(function () {
                loop(ctx, p1, p2, ball)
            }, 17)
        }(ctx, p1, p2, ball)
    }

    function move (p1, p2, ball) {
        function lowerBound(p) {
            if (p.y > 350) p.y = 350
            p.vy += 0.5
        }
        function tick(p) {
            p.x += p.vx
            p.y += p.vy
            p.vx *= 0.9
            p.vy *= 0.9
        }
        lowerBound(p1)
        lowerBound(p2)
        tick(p1)
        tick(p2)
        ball.x += ball.vx
        ball.y += ball.vy
        ball.vy += 0.25
    }

    function collide(p1, p2, ball) {
        collideWithWalls(p1, 25)
        collideWithWalls(p2, 25)
        collideWithWalls(ball, 10)
        collideWithBall(p1, ball)
        collideWithBall(p2, ball)
    }

    function collideWithWalls (x, r) {
        if(x.x < r || x.x > (700 - r) || r > 10 && Math.abs(x.x-375) < r) {
            x.vx *= -1
            x.x += x.vx
        }
    }

    function collideWithBall (p, b) {
        if( ((p.x - b.x) * (p.x - b.x)) + ((p.y - b.y) * (p.y - b.y)) < (25 * 25)) {
            var n = normalisedVectorBetween(p, b)
            var a1 = dot({x:b.vx, y:b.vy}, n)
            var a2 = dot({x:p.vx, y:p.vy}, n)
            var op = (2*(a2-a1))/(1+2)
            var v = prod(-0.99, diff({x:b.vx, y:b.vy}, prod(op, prod(2, n))))
            b.x += 2*v.x
            b.y += 2*v.y
            b.vx += v.x
            b.vy += v.y
        }
    }

    function prod(scalar, vector) {
        return {x: scalar*vector.x, y: scalar*vector.y }
    }

    function diff(a, b) {
        return {x: a.x - b.x, y: a.y - b.y}
    }

    function dot (p, n) {
        return p.x * n.x + p.y * n.y
    }

    function normalisedVectorBetween(p, b) {
        var dx = p.x - b.x, dy = p.y - b.y
        var d = Math.sqrt(dx*dx + dy*dy)
        return { x:dx/d, y: dy/d }
    }

    function score(p1, p2, ball) {
        if(ball.y > 360) {
            if(ball.x < 375) p2.score += 1
            else p1.score += 1
            ball.x = 350
            ball.y = 50
            ball.vx = 4
            ball.vy = 2
        }
    }

    function drawGame(ctx, p1, p2, ball) {
        ctx.font = "40pt Helvetica"
        ctx.fillText(p1.score, 25, 50)
        ctx.fillText(p2.score, 650, 50)
        ctx.fillStyle = "#FF0000"
        ctx.beginPath()
        ctx.arc(p1.x, p1.y, 25, 0, 2*Math.PI, false)
        ctx.fill()
        ctx.stroke()
        ctx.fillStyle = "#0000FF"
        ctx.beginPath()
        ctx.arc(p2.x, p2.y, 25, 0, 2*Math.PI, false)
        ctx.fill()
        ctx.stroke()
        ctx.fillStyle = "#00FF00"
        ctx.beginPath()
        ctx.arc(ball.x, ball.y, 10, 0, 2*Math.PI, false)
        ctx.fill()
        ctx.stroke()
    }

    function drawBackground(ctx) {
        ctx.fillStyle = "#999"
        ctx.fillRect(0, 350, 750, 400)
        ctx.fillStyle = "#FFF"
        ctx.fillRect(0, 0, 750, 350)
        ctx.fillStyle = "#3F3"
        ctx.fillRect(375, 320, 1, 60)
    }

    main()
} ()<|endoftext|>