<commit_before>const EventEmitter = require('events');
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const log = require('electron-log');

const { bridge } = require('../spring_api');

class Compiler extends EventEmitter {
  constructor(bridge) {
    super();

    this.progressPattern = new RegExp('[0-9]+/\\s*[0-9]+');
    this.bridge = bridge;

    let executableBin;
    if (process.platform === 'win32') {
      executableBin = 'springMapConvNG.exe';
    } else if (process.platform === 'linux') {
      executableBin = 'springMapConvNG';
    } else {
      const errMsg = `Unsupported platform: ${process.platform}, cannot compile`;
      log.error(errMsg);
      this.bridge.send("CompileMapError", {
        "code": errMsg,
      });
      return;
    }

    this.executablePath = path.resolve(`${__dirname}/../../bin/${executableBin}`);
    if (!fs.existsSync(this.executablePath)) {
      this.executablePath = path.resolve(`${process.resourcesPath}/../bin/${executableBin}`);
    }
  }

  compile(opts) {
    this.bridge.send("CompileMapStarted");
    // do async
    this.compileMap_SpringMapConvNG(opts);
  }

  compileMap_SpringMapConvNG(opts) {
    var callParams = [
        "-t", opts["diffusePath"],
        "-h", opts["heightPath"],
        "-ct", "1", // TODO: allow customization?
        "-o", opts["outputPath"]
    ]
    const extraParams = {
      "metalPath" : "-m",
      "typePath"  : "-z",
      "maxh" : "-maxh",
      "minh" : "-minh",
      "minimap" : "-minimap",

      // disable some potential footguns
      // "-ccount [compare_tilecount]",
      // "-th [compression_level]",
      // "-features [featurefile]"
    }

    for (var k in extraParams) {
      if (k in opts) {
        callParams.push(extraParams[k], opts[k]);
      }
    }

    // proc = Popen(callParams, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    // for line in iter(proc.stdout.readline, ""):
    //     try:
    //         line = line.split("Compressing")[1]
    //         est, total = line.split("/")[0], line.split("/")[1]
    //         est = int(est.strip())
    //         total = int(total.strip().split()[0].strip())
    //     except Exception:
    //         pass
    //     else:
    //         self.sc.send({
    //             "name" : "UpdateCompiling",
    //             "command" : {
    //                 "est" : est,
    //                 "total" : total,
    //             }
    //         })
    //         #yield stdout_line
    // proc.stdout.close()
    // return_code = proc.wait()
    // stderr = proc.stderr.read()

    // const compilerPath = "./src/exts/springMapConvNG";
    // process = spawn('ls');

    log.info(callParams);
    process = spawn(this.executablePath, callParams);

    process.stdout.on('data', (data) => {
      const line = data.toString();
      console.log(line);
      if (line.includes("Compressing")) {
        const matched = line.match(this.progressPattern);
        if (!matched || matched.length == 0) {
          return;
        }
        var progressStr = matched[0];
        var [current, total] = progressStr.split("/");
        var current = parseInt(current);
        var total = parseInt(total);
        this.bridge.send("CompileMapProgress", {
          current: current,
          total: total
        });
      }
    });

    process.stderr.on('data', (data) => {
      console.log("stderr: ", data.toString());
    });

    process.on('exit', (code) => {
      console.log(`Exited: ${code}`);
      if (code == 0) {
        this.bridge.send("CompileMapFinished");
      } else {
        this.bridge.send("CompileMapError", {
            "code": code,
        });
      }
    });

    console.log("finished");
  }
}

const compiler = new Compiler(bridge);

bridge.on("CompileMap", (command) => {
  compiler.compile(command);
});
<commit_msg>try to improve the map compiler error message quality<commit_after>const EventEmitter = require('events');
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const log = require('electron-log');

const { bridge } = require('../spring_api');

class Compiler extends EventEmitter {
  constructor(bridge) {
    super();

    this.progressPattern = new RegExp('[0-9]+/\\s*[0-9]+');
    this.bridge = bridge;

    let executableBin;
    if (process.platform === 'win32') {
      executableBin = 'springMapConvNG.exe';
    } else if (process.platform === 'linux') {
      executableBin = 'springMapConvNG';
    } else {
      const errMsg = `Unsupported platform: ${process.platform}, cannot compile`;
      log.error(errMsg);
      this.bridge.send("CompileMapError", {
        "code": errMsg,
      });
      return;
    }

    this.executablePath = path.resolve(`${__dirname}/../../bin/${executableBin}`);
    if (!fs.existsSync(this.executablePath)) {
      this.executablePath = path.resolve(`${process.resourcesPath}/../bin/${executableBin}`);
    }
  }

  compile(opts) {
    this.bridge.send("CompileMapStarted");
    // do async
    this.compileMap_SpringMapConvNG(opts);
  }

  compileMap_SpringMapConvNG(opts) {
    var callParams = [
        "-t", opts["diffusePath"],
        "-h", opts["heightPath"],
        "-ct", "1", // TODO: allow customization?
        "-o", opts["outputPath"]
    ]
    const extraParams = {
      "metalPath" : "-m",
      "typePath"  : "-z",
      "maxh" : "-maxh",
      "minh" : "-minh",
      "minimap" : "-minimap",

      // disable some potential footguns
      // "-ccount [compare_tilecount]",
      // "-th [compression_level]",
      // "-features [featurefile]"
    }

    for (var k in extraParams) {
      if (k in opts) {
        callParams.push(extraParams[k], opts[k]);
      }
    }

    // proc = Popen(callParams, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    // for line in iter(proc.stdout.readline, ""):
    //     try:
    //         line = line.split("Compressing")[1]
    //         est, total = line.split("/")[0], line.split("/")[1]
    //         est = int(est.strip())
    //         total = int(total.strip().split()[0].strip())
    //     except Exception:
    //         pass
    //     else:
    //         self.sc.send({
    //             "name" : "UpdateCompiling",
    //             "command" : {
    //                 "est" : est,
    //                 "total" : total,
    //             }
    //         })
    //         #yield stdout_line
    // proc.stdout.close()
    // return_code = proc.wait()
    // stderr = proc.stderr.read()

    // const compilerPath = "./src/exts/springMapConvNG";
    // process = spawn('ls');

    log.info(callParams);
    process = spawn(this.executablePath, callParams);

    process.stdout.on('data', (data) => {
      const line = data.toString();
      console.log(line);
      if (line.includes("Compressing")) {
        const matched = line.match(this.progressPattern);
        if (!matched || matched.length == 0) {
          return;
        }
        var progressStr = matched[0];
        var [current, total] = progressStr.split("/");
        var current = parseInt(current);
        var total = parseInt(total);
        this.bridge.send("CompileMapProgress", {
          current: current,
          total: total
        });
      }
    });

    var errorMsg = "";
    process.stderr.on('data', (data) => {
      console.log("stderr: ", data.toString());
      errorMsg += data.toString() + "\n";
    });

    process.on('exit', (code) => {
      console.log(`Exited: ${code}`);
      if (code == 0) {
        this.bridge.send("CompileMapFinished");
      } else {
        this.bridge.send("CompileMapError", {
            "code": code,
            "msg": errorMsg
        });
      }
    });

    console.log("finished");
  }
}

const compiler = new Compiler(bridge);

bridge.on("CompileMap", (command) => {
  compiler.compile(command);
});
<|endoftext|>


<commit_before>export { ScaleTranslateSet };

import * as FloatValue from "../Unpacker/FloatValue.js";
import * as ConvBiasActivation from "./ConvBiasActivation.js";

/**
 * Several scale-translate for escaping a value bounds from being activated (i.e. being non-linearized) by activation function.
 *
 *
 * @member {FloatValue.ScaleTranslateArray} doWithoutPreviousUndo
 *   The scale-translate for moving current value bounds into the linear domain of the activation function. That is, for letting
 * ConvBiasActivation.ValueBoundsSet.beforeActivation escape from activation function's non-linear domain into linear domain.
 *
 * @member {FloatValue.ScaleTranslateArray} do
 *   The result of combining this.doWithoutPreviousUndo with previous ActivationEscape.ScaleTranslateSet.undo. It both undo the
 * previous escaping scale-translate and do itself escaping scale-translate.
 *
 * @member {FloatValue.ScaleTranslateArray} undo
 *   If apply this.undo (important: scale first, translate second), it will have the effect of undoing the this.do.
 */
class ScaleTranslateSet {

  constructor() {
    this.doWithoutPreviousUndo = new FloatValue.ScaleTranslateArray();
    this.do = new FloatValue.ScaleTranslateArray();
    this.undo = new FloatValue.ScaleTranslateArray();
  }

  clone() {
    let result = new ScaleTranslateSet();
    result.set_byScaleTranslateSet( this );
    return result;
  }

  /**
   * @param {ScaleTranslateSet} aScaleTranslateSet
   *   The ScaleTranslateSet to be copied.
   */
  set_byScaleTranslateSet( aScaleTranslateSet ) {
    this.doWithoutPreviousUndo.set_ScaleTranslateArray( aScaleTranslateSet.doWithoutPreviousUndo );
    this.do.set_ScaleTranslateArray( aScaleTranslateSet.do );
    this.undo.set_ScaleTranslateArray( aScaleTranslateSet.undo );
  }

  /** Reset all scale-translate values. Default is ( scale = 1, translate = 0 ) (i.e. no scale and no translate). */
  reset( scale = 1, translate = 0 ) {
    this.doWithoutPreviousUndo.set_all_by_scale_translate( scale , translate );
    this.do.set_all_by_scale_translate( scale , translate );
    this.undo.set_all_by_scale_translate( scale , translate );
  }

//!!! ...unfinished... (2021/12/26)
/**
 * - For depthwise with ( pad == same ), it seems that the activation escaping can not be undone completely, because pad is always 0
 *   (can not scale-translate). Unless, pad can be non-zero?
 *
 *   - Fortunately, this is not a problem for pass-through channels. Because the pass-through filter value is also 0 in the padded
 *       position, the result is not affected. (But its a big problem for non-pass-through channels.)
 *
 *   - Perhaps, force use ( pad == valid ) so that the activation escaping always can be undone completely.
 *
 *     - In original ShuffleNetV2, using ( pad == same ) is necessary for concatenating ( depthwise1, input1 ).
 *
 *     - In our combined-depthwise1-with-higher-half-pass-through (i.e. ONE_INPUT_HALF_THROUGH_XXX), the ( depthwise1, input1 )
 *         already combined together. There is no concatenation issue. So using ( pad == valid ) is possible.
 *
 *     - However, this is not so good for pass-through channels. Because the pass-through filter value is 0 at the right-bottom
 *         corner, the image value will be destroyed.
 *
 * - If previous convolution does not have activation escaping do (i.e. is a normal convolution without pass-through)，this
 *     this convolution's .do should be different.
 *
 * - Perhaps, there should be value-bounds and activation-escaping scale-translate for every single channel (i.e. lower-array,
 *     upper-array, scale-array and translate-array). Even if channels are shuffled, they could be still tracked correctly.
 *
 * - When extractFilters() and extractBiases(), pre-apply the per channel undoing scale and translate to filter-value, bias-value,
 *     and their bounds. (The .do and .undo should also affect the value bounds.)
 *
 * - When across Block (i.e. at ShuffleNetV2_ByMobileNetV1's head), the higher-half-copy-lower-half channels's value bounds
 *     does not come from previous corresponding channels. They comes from the lower-half channels which they copied from.
 *
 */

  /**
   * Set the following properties:
   *   - this.doWithoutPreviousUndo
   *   - this.do
   *   - this.undo
   *
   * @param {ConvBiasActivation.ValueBoundsSet} current_ConvBiasActivation_ValueBoundsSet
   *   The ValueBoundsSet of current convolution-bias-activation for calculating this.doWithoutPreviousUndo.
   *
   * @param {ScaleTranslateSet} previous_ActivationEscaping_ScaleTranslateSet
   *   The ActivationEscaping.ScaleTranslateSet of previous convolution-bias-activation for calculating this.do.
   */
  set_by_currentValueBoundsSet_previousActivationEscaping(
    current_ConvBiasActivation_ValueBoundsSet, previous_ActivationEscaping_ScaleTranslateSet ) {

    // Calculate the scale-translate for escaping from activation function's non-linear domain into linear domain.
    //
    // Note: This does not work for avg/max pooling.
    this.doWithoutPreviousUndo.set_all_by_fromBoundsArray_ToBoundsArray(
      current_ConvBiasActivation_ValueBoundsSet.beforeActivation, current_ConvBiasActivation_ValueBoundsSet.output );

    // Combine undoing previous activation escaping scale-translate and doing current activation escaping scale-translate.
    this.do.set_all_byScaleTranslateArray( previous_ActivationEscaping_ScaleTranslateSet.undo );
    this.do.scaleTranslate_all_byScaleTranslateArray( this.doWithoutPreviousUndo );

    // Prepare the undoing scale-translate for the next convolution-bias-activation.
    this.undo.set_byUndo_ScaleTranslate( this.do );
  }

}

<commit_msg>Update ActivationEscapeing.js<commit_after>export { ScaleTranslateSet };

import * as FloatValue from "../Unpacker/FloatValue.js";
import * as ConvBiasActivation from "./ConvBiasActivation.js";

/**
 * Several scale-translate for escaping a value bounds from being activated (i.e. being non-linearized) by activation function.
 *
 *
 * @member {FloatValue.ScaleTranslateArray} doWithoutPreviousUndo
 *   The scale-translate for moving current value bounds into the linear domain of the activation function. That is, for letting
 * ConvBiasActivation.ValueBoundsSet.beforeActivation escape from activation function's non-linear domain into linear domain.
 *
 * @member {FloatValue.ScaleTranslateArray} do
 *   The result of combining this.doWithoutPreviousUndo with previous ActivationEscape.ScaleTranslateSet.undo. It both undo the
 * previous escaping scale-translate and do itself escaping scale-translate.
 *
 * @member {FloatValue.ScaleTranslateArray} undo
 *   If apply this.undo (important: scale first, translate second), it will have the effect of undoing the this.do.
 */
class ScaleTranslateSet {

  constructor() {
    this.doWithoutPreviousUndo = new FloatValue.ScaleTranslateArray();
    this.do = new FloatValue.ScaleTranslateArray();
    this.undo = new FloatValue.ScaleTranslateArray();
  }

  clone() {
    let result = new ScaleTranslateSet();
    result.set_byScaleTranslateSet( this );
    return result;
  }

  /**
   * @param {ScaleTranslateSet} aScaleTranslateSet
   *   The ScaleTranslateSet to be copied.
   */
  set_byScaleTranslateSet( aScaleTranslateSet ) {
    this.doWithoutPreviousUndo.set_ScaleTranslateArray( aScaleTranslateSet.doWithoutPreviousUndo );
    this.do.set_ScaleTranslateArray( aScaleTranslateSet.do );
    this.undo.set_ScaleTranslateArray( aScaleTranslateSet.undo );
  }

  /** Reset all scale-translate values. Default is ( scale = 1, translate = 0 ) (i.e. no scale and no translate). */
  reset_by_scale_translate( scale = 1, translate = 0 ) {
    this.doWithoutPreviousUndo.set_all_by_scale_translate( scale , translate );
    this.do.set_all_by_scale_translate( scale , translate );
    this.undo.set_all_by_scale_translate( scale , translate );
  }

//!!! ...unfinished... (2021/12/26)
/**
 * - For depthwise with ( pad == same ), it seems that the activation escaping can not be undone completely, because pad is always 0
 *   (can not scale-translate). Unless, pad can be non-zero?
 *
 *   - Fortunately, this is not a problem for pass-through channels. Because the pass-through filter value is also 0 in the padded
 *       position, the result is not affected. (But its a big problem for non-pass-through channels.)
 *
 *   - Perhaps, force use ( pad == valid ) so that the activation escaping always can be undone completely.
 *
 *     - In original ShuffleNetV2, using ( pad == same ) is necessary for concatenating ( depthwise1, input1 ).
 *
 *     - In our combined-depthwise1-with-higher-half-pass-through (i.e. ONE_INPUT_HALF_THROUGH_XXX), the ( depthwise1, input1 )
 *         already combined together. There is no concatenation issue. So using ( pad == valid ) is possible.
 *
 *     - However, this is not so good for pass-through channels. Because the pass-through filter value is 0 at the right-bottom
 *         corner, the image value will be destroyed.
 *
 * - If previous convolution does not have activation escaping do (i.e. is a normal convolution without pass-through)，this
 *     this convolution's .do should be different.
 *
 * - Perhaps, there should be value-bounds and activation-escaping scale-translate for every single channel (i.e. lower-array,
 *     upper-array, scale-array and translate-array). Even if channels are shuffled, they could be still tracked correctly.
 *
 * - When extractFilters() and extractBiases(), pre-apply the per channel undoing scale and translate to filter-value, bias-value,
 *     and their bounds. (The .do and .undo should also affect the value bounds.)
 *
 * - When across Block (i.e. at ShuffleNetV2_ByMobileNetV1's head), the higher-half-copy-lower-half channels's value bounds
 *     does not come from previous corresponding channels. They comes from the lower-half channels which they copied from.
 *
 */

  /**
   * Set the following properties:
   *   - this.doWithoutPreviousUndo
   *   - this.do
   *   - this.undo
   *
   * @param {ConvBiasActivation.ValueBoundsSet} current_ConvBiasActivation_ValueBoundsSet
   *   The ValueBoundsSet of current convolution-bias-activation for calculating this.doWithoutPreviousUndo.
   *
   * @param {ScaleTranslateSet} previous_ActivationEscaping_ScaleTranslateSet
   *   The ActivationEscaping.ScaleTranslateSet of previous convolution-bias-activation for calculating this.do.
   */
  set_by_currentValueBoundsSet_previousActivationEscaping(
    current_ConvBiasActivation_ValueBoundsSet, previous_ActivationEscaping_ScaleTranslateSet ) {

    // Calculate the scale-translate for escaping from activation function's non-linear domain into linear domain.
    //
    // Note: This does not work for avg/max pooling.
    this.doWithoutPreviousUndo.set_all_by_fromBoundsArray_ToBoundsArray(
      current_ConvBiasActivation_ValueBoundsSet.beforeActivation, current_ConvBiasActivation_ValueBoundsSet.output );

    // Combine undoing previous activation escaping scale-translate and doing current activation escaping scale-translate.
    this.do.set_all_byScaleTranslateArray( previous_ActivationEscaping_ScaleTranslateSet.undo );
    this.do.scaleTranslate_all_byScaleTranslateArray( this.doWithoutPreviousUndo );

    // Prepare the undoing scale-translate for the next convolution-bias-activation.
    this.undo.set_byUndo_ScaleTranslate( this.do );
  }

}

<|endoftext|>


<commit_before>export { assert_Pool_issuedCount };
export { assert_Pool_issuedCount_same_after_as_before };
export { assert_Pool_issuedCount_zero };

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

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
// /**
//  * @param {Pool.Base} pool
//  *   The pool object to be asserted.
//  */
// function assert_Pool_issuedCount( prefixMsg, pool, issuedCount_shouldBe ) {
//   if ( pool.issuedCount != issuedCount_shouldBe )
//     throw Error( `${prefixMsg}: memory leak: `
//       + `pool ( ${pool.poolName} )'s issuedCount ( ${pool.issuedCount} ) should be ( ${issuedCount_shouldBe} ).` );
// }

/**
 */
function assert_PoolAll_issuedCount( prefixMsg, issuedCount_shouldBe ) {
  if ( Pool.All.issuedCount != issuedCount_shouldBe )
    throw Error( `${prefixMsg}: memory leak: `
      + `Pool.All.issuedCount ( ${Pool.All.issuedCount} ) should be ( ${issuedCount_shouldBe} ).` );
}

/**
 * Assert all pool's .issuedCount before and after calling pfn() are the same.
 *
 * @param (Function} pfn
 *   The function to be called.
 *
 * @param (Object} thisArg
 *   The "this" value when function pfn is called.
 *
 * @param (Object[]} restArgs
 *   All arguments when function pfn is called.
 */
function assert_Pool_issuedCount_same_after_as_before( prefixMsg, pfn, thisArg, ...restArgs ) {

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//  let issuedCount_array_before;
  try {

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//     issuedCount_array_before = Recyclable.Array.Pool.get_or_create_by( Pool.All.registeredPoolArray.length );
//     for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
//       let pool = Pool.All.registeredPoolArray[ i ];
//       issuedCount_array_before[ i ] = pool.issuedCount;
//     }

    let issuedCount_before = Pool.All.issuedCount;

    pfn.apply( thisArg, restArgs );

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//     for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
//       let pool = Pool.All.registeredPoolArray[ i ];
//       assert_Pool_issuedCount( prefixMsg, pool, issuedCount_array_before[ i ] );
//     }

    assert_PoolAll_issuedCount( prefixMsg, issuedCount_before );

  } catch ( e ) {
    throw e;

  } finally {
//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//     if ( issuedCount_array_before ) {
//       issuedCount_array_before.disposeResources_and_recycleToPool();
//       issuedCount_array_before = null;
//     }
  }
}

/**
 *
 */
function assert_PoolAll_issuedCount_zero( prefixMsg ) {

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//   for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
//     let pool = Pool.All.registeredPoolArray[ i ];
//     assert_Pool_issuedCount( prefixMsg, pool, 0 );
//   }

  assert_PoolAll_issuedCount( prefixMsg, 0 );
}
<commit_msg>Update Pool_Asserter.js<commit_after>export { assert_Pool_issuedCount };
export { assert_Pool_issuedCount_same_after_as_before };
export { assert_Pool_issuedCount_zero };

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

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
// /**
//  * @param {Pool.Base} pool
//  *   The pool object to be asserted.
//  */
// function assert_Pool_issuedCount( prefixMsg, pool, issuedCount_shouldBe ) {
//   if ( pool.issuedCount != issuedCount_shouldBe )
//     throw Error( `${prefixMsg}: memory leak: `
//       + `pool ( ${pool.poolName} )'s issuedCount ( ${pool.issuedCount} ) should be ( ${issuedCount_shouldBe} ).` );
// }

/**
 */
function assert_Pool_issuedCount( prefixMsg, issuedCount_shouldBe ) {
  if ( Pool.All.issuedCount != issuedCount_shouldBe )
    throw Error( `${prefixMsg}: memory leak: `
      + `Pool.All.issuedCount ( ${Pool.All.issuedCount} ) should be ( ${issuedCount_shouldBe} ).` );
}

/**
 * Assert all pool's .issuedCount before and after calling pfn() are the same.
 *
 * @param (Function} pfn
 *   The function to be called.
 *
 * @param (Object} thisArg
 *   The "this" value when function pfn is called.
 *
 * @param (Object[]} restArgs
 *   All arguments when function pfn is called.
 */
function assert_Pool_issuedCount_same_after_as_before( prefixMsg, pfn, thisArg, ...restArgs ) {

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//  let issuedCount_array_before;
  try {

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//     issuedCount_array_before = Recyclable.Array.Pool.get_or_create_by( Pool.All.registeredPoolArray.length );
//     for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
//       let pool = Pool.All.registeredPoolArray[ i ];
//       issuedCount_array_before[ i ] = pool.issuedCount;
//     }

    let issuedCount_before = Pool.All.issuedCount;

    pfn.apply( thisArg, restArgs );

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//     for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
//       let pool = Pool.All.registeredPoolArray[ i ];
//       assert_Pool_issuedCount( prefixMsg, pool, issuedCount_array_before[ i ] );
//     }

    assert_Pool_issuedCount( prefixMsg, issuedCount_before );

  } catch ( e ) {
    throw e;

  } finally {
//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//     if ( issuedCount_array_before ) {
//       issuedCount_array_before.disposeResources_and_recycleToPool();
//       issuedCount_array_before = null;
//     }
  }
}

/**
 *
 */
function assert_Pool_issuedCount_zero( prefixMsg ) {

//!!! (2022/06/30 Remarked) Now, no issuedCount for individual pool
//   for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
//     let pool = Pool.All.registeredPoolArray[ i ];
//     assert_Pool_issuedCount( prefixMsg, pool, 0 );
//   }

  assert_Pool_issuedCount( prefixMsg, 0 );
}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import SideNav from '../common/Sidebar'
import * as actions from '../../actions/user'
import { Segment, Container, List, Button, Icon } from 'semantic-ui-react'
const styles = {
    container: {
        marginTop: '4%'
    },
}
class UserList extends Component {

    componentWillMount() {
        if (this.props.auth && !this.props.auth.authenticated) {
            this.props.history.push("/");
        }
        this.props.getAllUser();
        document.title = "User List";
    }
    componentWillReceiveProps(nextProps) {
       if (nextProps.auth && !nextProps.auth.authenticated) {
            this.props.history.push("/");
        }
    }

    handleDelete(key) {
        this.props.deleteUser(key, (err,msg) => {
            if(!err){
                this.props.getAllUser();
            }else{
                alert(msg);
            }
        })
    }
    renderUserList() {
        return this.props.user.list.userList.map((item, index) => {
            return (
                //

                //

                //
{item.key}

                //         <button onClick={() => this.handleDelete(item.key)}>Delete</button>
                //

                //

                ( item.username !== 'root' ? <List.Item key={index}>
                { this.props.auth.user.permissions.search(/DELETE_USERS|ALL/) >= 0 ? <List.Content floated='right'>
                    <Button animated color='red' onClick={() => this.handleDelete(item.username)} >
                        <Button.Content visible> Delete</Button.Content>
                        <Button.Content hidden>
                            <Icon name='trash' />
                        </Button.Content>
                    </Button>
                </List.Content> :  null}
                { this.props.auth.user.permissions.search(/EDIT_USER|ALL/) >= 0 ? <List.Content floated='right'>
                    <Button animated color='blue' as={Link} to={'/users/edit/' + item.username + '/' + item.permission}>
                        <Button.Content visible>Edit Permission</Button.Content>
                        <Button.Content hidden>
                            <Icon name='edit' />
                        </Button.Content>
                    </Button>
                </List.Content> : null}
                <List.Content>
                    <List.Header>{item.username}</List.Header>
                </List.Content>
            </List.Item> : null)
            )
        })
    }

    render() {
      if (typeof this.props.auth.user !== `undefined` && (this.props.auth.user.permissions.search(/VIEW_USERS|ALL/) >= 0)) {
        return (
            <SideNav>
                <Container style={styles.container}>
                    <Segment raised >

                            <List animated divided verticalAlign='middle' size={'big'}>
                                {this.props.user.list && this.renderUserList()}

                            </List>

                        { this.props.auth.user.permissions.search(/ADD_USERS|ALL/) >= 0 ? <Container textAlign='center' style={{ marginTop: '10px' }}>
                            <Button as={Link} to={'/create/user'} animated color='teal'>
                                <Button.Content visible>Add User</Button.Content>
                                <Button.Content hidden>
                                    <Icon name='add user' />
                                </Button.Content>
                            </Button>
                        </Container> : null }

                    </Segment>
                </Container>
                {/* UserList
                {this.props.user.list && this.renderUserList()}
                <Link to={"/create/user"}>Add User</Link> */}
            </SideNav>
        )
    } else {
      this.props.history.push("/");
      return (null);
    }
  }
}

function mapStateToProps({ user, auth }) {
    return { user, auth }
}

export default connect(mapStateToProps, actions)(UserList);
<commit_msg>Add User Management heading and also add deletion success message upon deleting an user. Fixes issues #154 and #159<commit_after>import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import SideNav from '../common/Sidebar'
import * as actions from '../../actions/user'
import { Segment, Container, List, Button, Icon, Header } from 'semantic-ui-react'
const styles = {
    container: {
        marginTop: '4%'
    },
}
class UserList extends Component {

    componentWillMount() {
        if (this.props.auth && !this.props.auth.authenticated) {
            this.props.history.push("/");
        }
        this.props.getAllUser();
        document.title = "User List";
    }
    componentWillReceiveProps(nextProps) {
       if (nextProps.auth && !nextProps.auth.authenticated) {
            this.props.history.push("/");
        }
    }

    handleDelete(key) {
        this.props.deleteUser(key, (err,msg) => {
            if(!err){
                alert("Deletion Success");
                this.props.getAllUser();
            }else{
                alert(msg);
            }
        })
    }
    renderUserList() {
        return this.props.user.list.userList.map((item, index) => {
            return (
                //

                //

                //
{item.key}

                //         <button onClick={() => this.handleDelete(item.key)}>Delete</button>
                //

                //

                ( item.username !== 'root' ? <List.Item key={index}>
                { this.props.auth.user.permissions.search(/DELETE_USERS|ALL/) >= 0 ? <List.Content floated='right'>
                    <Button animated color='red' onClick={() => this.handleDelete(item.username)} >
                        <Button.Content visible> Delete</Button.Content>
                        <Button.Content hidden>
                            <Icon name='trash' />
                        </Button.Content>
                    </Button>
                </List.Content> :  null}
                { this.props.auth.user.permissions.search(/EDIT_USER|ALL/) >= 0 ? <List.Content floated='right'>
                    <Button animated color='blue' as={Link} to={'/users/edit/' + item.username + '/' + item.permission}>
                        <Button.Content visible>Edit Permission</Button.Content>
                        <Button.Content hidden>
                            <Icon name='edit' />
                        </Button.Content>
                    </Button>
                </List.Content> : null}
                <List.Content>
                    <List.Header>{item.username}</List.Header>
                </List.Content>
            </List.Item> : null)
            )
        })
    }

    render() {
      if (typeof this.props.auth.user !== `undefined` && (this.props.auth.user.permissions.search(/VIEW_USERS|ALL/) >= 0)) {
        return (
            <SideNav>
                <Container style={styles.container}>
                    User Management
                    <Segment raised >

                            <List animated divided verticalAlign='middle' size={'big'}>
                                {this.props.user.list && this.renderUserList()}
                            </List>

                        { this.props.auth.user.permissions.search(/ADD_USERS|ALL/) >= 0 ? <Container textAlign='center' style={{ marginTop: '10px' }}>
                            <Button as={Link} to={'/create/user'} animated color='teal'>
                                <Button.Content visible>Add User</Button.Content>
                                <Button.Content hidden>
                                    <Icon name='add user' />
                                </Button.Content>
                            </Button>
                        </Container> : null }

                    </Segment>
                </Container>
                {/* UserList
                {this.props.user.list && this.renderUserList()}
                <Link to={"/create/user"}>Add User</Link> */}
            </SideNav>
        )
    } else {
      this.props.history.push("/");
      return (null);
    }
  }
}

function mapStateToProps({ user, auth }) {
    return { user, auth }
}

export default connect(mapStateToProps, actions)(UserList);
<|endoftext|>


<commit_before>'use strict'

const pull = require('pull-stream')
const promisify = require('promisify-es6')
const getFolderSize = promisify(require('get-folder-size'))
const byteman = require('byteman')
const mh = require('multihashes')
const multibase = require('multibase')
const toPull = require('stream-to-pull-stream')
const { createProgressBar } = require('../utils')
const { cidToString } = require('../../utils/cid')
const globSource = require('../../utils/files/glob-source')

async function getTotalBytes (paths, cb) {
  const sizes = await Promise.all(paths.map(p => getFolderSize(p)))
  return sizes.reduce((total, size) => total + size, 0)
}

function addPipeline (source, addStream, options) {
  return new Promise((resolve, reject) => {
    pull(
      source,
      addStream,
      pull.collect((err, added) => {
        if (err) {
          // Tweak the error message and add more relevant infor for the CLI
          if (err.code === 'ERR_DIR_NON_RECURSIVE') {
            err.message = `'${err.path}' is a directory, use the '-r' flag to specify directories`
          }
          return reject(err)
        }

        if (options.silent) return resolve()

        if (options.quieter) {
          options.print(added.pop().hash)
          return resolve()
        }

        added
          .sort((a, b) => {
            if (a.path > b.path) {
              return 1
            }
            if (a.path < b.path) {
              return -1
            }
            return 0
          })
          .reverse()
          .map((file) => {
            const log = options.quiet ? [] : ['added']
            log.push(cidToString(file.hash, { base: options.cidBase }))
            if (!options.quiet && file.path.length > 0) log.push(file.path)
            return log.join(' ')
          })
          .forEach((msg) => options.print(msg))

        resolve()
      })
    )
  })
}

module.exports = {
  command: 'add [file...]',

  describe: 'Add a file to IPFS using the UnixFS data format',

  builder: {
    progress: {
      alias: 'p',
      type: 'boolean',
      default: true,
      describe: 'Stream progress data'
    },
    recursive: {
      alias: 'r',
      type: 'boolean',
      default: false
    },
    trickle: {
      alias: 't',
      type: 'boolean',
      default: false,
      describe: 'Use the trickle DAG builder'
    },
    'wrap-with-directory': {
      alias: 'w',
      type: 'boolean',
      default: false
    },
    'only-hash': {
      alias: 'n',
      type: 'boolean',
      default: false,
      describe: 'Only chunk and hash, do not write'
    },
    chunker: {
      default: 'size-262144',
      describe: 'Chunking algorithm to use, formatted like [size-{size}, rabin, rabin-{avg}, rabin-{min}-{avg}-{max}]'
    },
    'enable-sharding-experiment': {
      type: 'boolean',
      default: false
    },
    'shard-split-threshold': {
      type: 'integer',
      default: 1000
    },
    'raw-leaves': {
      type: 'boolean',
      describe: 'Use raw blocks for leaf nodes. (experimental)'
    },
    'cid-version': {
      type: 'integer',
      describe: 'CID version. Defaults to 0 unless an option that depends on CIDv1 is passed. (experimental)',
      default: 0
    },
    'cid-base': {
      describe: 'Number base to display CIDs in.',
      type: 'string',
      choices: multibase.names
    },
    hash: {
      type: 'string',
      choices: Object.keys(mh.names),
      describe: 'Hash function to use. Will set CID version to 1 if used. (experimental)'
    },
    quiet: {
      alias: 'q',
      type: 'boolean',
      default: false,
      describe: 'Write minimal output'
    },
    quieter: {
      alias: 'Q',
      type: 'boolean',
      default: false,
      describe: 'Write only final hash'
    },
    silent: {
      type: 'boolean',
      default: false,
      describe: 'Write no output'
    },
    pin: {
      type: 'boolean',
      default: true,
      describe: 'Pin this object when adding'
    }
  },

  handler (argv) {
    argv.resolve((async () => {
      const ipfs = await argv.getIpfs()
      const options = {
        strategy: argv.trickle ? 'trickle' : 'balanced',
        shardSplitThreshold: argv.enableShardingExperiment
          ? argv.shardSplitThreshold
          : Infinity,
        cidVersion: argv.cidVersion,
        rawLeaves: argv.rawLeaves,
        onlyHash: argv.onlyHash,
        hashAlg: argv.hash,
        wrapWithDirectory: argv.wrapWithDirectory,
        pin: argv.pin,
        chunker: argv.chunker
      }

      if (options.enableShardingExperiment && argv.isDaemonOn()) {
        throw new Error('Error: Enabling the sharding experiment should be done on the daemon')
      }

      const source = argv.file
        ? globSource(...argv.file, { recursive: argv.recursive })
        : toPull.source(process.stdin) // Pipe directly to ipfs.add

      const adder = ipfs.addPullStream(options)

      // No progress or piping directly to ipfs.add: no need to getTotalBytes
      if (!argv.progress || !argv.file) {
        return addPipeline(source, adder, argv)
      }

      const totalBytes = await getTotalBytes(argv.file)
      const bar = createProgressBar(totalBytes)

      options.progress = byteLength => {
        bar.update(byteLength / totalBytes, { progress: byteman(byteLength, 2, 'MB') })
      }

      return addPipeline(source, adder, argv)
    })())
  }
}
<commit_msg>docs: add description for CLI add wrap option (#2127)<commit_after>'use strict'

const pull = require('pull-stream')
const promisify = require('promisify-es6')
const getFolderSize = promisify(require('get-folder-size'))
const byteman = require('byteman')
const mh = require('multihashes')
const multibase = require('multibase')
const toPull = require('stream-to-pull-stream')
const { createProgressBar } = require('../utils')
const { cidToString } = require('../../utils/cid')
const globSource = require('../../utils/files/glob-source')

async function getTotalBytes (paths, cb) {
  const sizes = await Promise.all(paths.map(p => getFolderSize(p)))
  return sizes.reduce((total, size) => total + size, 0)
}

function addPipeline (source, addStream, options) {
  return new Promise((resolve, reject) => {
    pull(
      source,
      addStream,
      pull.collect((err, added) => {
        if (err) {
          // Tweak the error message and add more relevant infor for the CLI
          if (err.code === 'ERR_DIR_NON_RECURSIVE') {
            err.message = `'${err.path}' is a directory, use the '-r' flag to specify directories`
          }
          return reject(err)
        }

        if (options.silent) return resolve()

        if (options.quieter) {
          options.print(added.pop().hash)
          return resolve()
        }

        added
          .sort((a, b) => {
            if (a.path > b.path) {
              return 1
            }
            if (a.path < b.path) {
              return -1
            }
            return 0
          })
          .reverse()
          .map((file) => {
            const log = options.quiet ? [] : ['added']
            log.push(cidToString(file.hash, { base: options.cidBase }))
            if (!options.quiet && file.path.length > 0) log.push(file.path)
            return log.join(' ')
          })
          .forEach((msg) => options.print(msg))

        resolve()
      })
    )
  })
}

module.exports = {
  command: 'add [file...]',

  describe: 'Add a file to IPFS using the UnixFS data format',

  builder: {
    progress: {
      alias: 'p',
      type: 'boolean',
      default: true,
      describe: 'Stream progress data'
    },
    recursive: {
      alias: 'r',
      type: 'boolean',
      default: false
    },
    trickle: {
      alias: 't',
      type: 'boolean',
      default: false,
      describe: 'Use the trickle DAG builder'
    },
    'wrap-with-directory': {
      alias: 'w',
      type: 'boolean',
      default: false,
      describe: 'Add a wrapping node'
    },
    'only-hash': {
      alias: 'n',
      type: 'boolean',
      default: false,
      describe: 'Only chunk and hash, do not write'
    },
    chunker: {
      default: 'size-262144',
      describe: 'Chunking algorithm to use, formatted like [size-{size}, rabin, rabin-{avg}, rabin-{min}-{avg}-{max}]'
    },
    'enable-sharding-experiment': {
      type: 'boolean',
      default: false
    },
    'shard-split-threshold': {
      type: 'integer',
      default: 1000
    },
    'raw-leaves': {
      type: 'boolean',
      describe: 'Use raw blocks for leaf nodes. (experimental)'
    },
    'cid-version': {
      type: 'integer',
      describe: 'CID version. Defaults to 0 unless an option that depends on CIDv1 is passed. (experimental)',
      default: 0
    },
    'cid-base': {
      describe: 'Number base to display CIDs in.',
      type: 'string',
      choices: multibase.names
    },
    hash: {
      type: 'string',
      choices: Object.keys(mh.names),
      describe: 'Hash function to use. Will set CID version to 1 if used. (experimental)'
    },
    quiet: {
      alias: 'q',
      type: 'boolean',
      default: false,
      describe: 'Write minimal output'
    },
    quieter: {
      alias: 'Q',
      type: 'boolean',
      default: false,
      describe: 'Write only final hash'
    },
    silent: {
      type: 'boolean',
      default: false,
      describe: 'Write no output'
    },
    pin: {
      type: 'boolean',
      default: true,
      describe: 'Pin this object when adding'
    }
  },

  handler (argv) {
    argv.resolve((async () => {
      const ipfs = await argv.getIpfs()
      const options = {
        strategy: argv.trickle ? 'trickle' : 'balanced',
        shardSplitThreshold: argv.enableShardingExperiment
          ? argv.shardSplitThreshold
          : Infinity,
        cidVersion: argv.cidVersion,
        rawLeaves: argv.rawLeaves,
        onlyHash: argv.onlyHash,
        hashAlg: argv.hash,
        wrapWithDirectory: argv.wrapWithDirectory,
        pin: argv.pin,
        chunker: argv.chunker
      }

      if (options.enableShardingExperiment && argv.isDaemonOn()) {
        throw new Error('Error: Enabling the sharding experiment should be done on the daemon')
      }

      const source = argv.file
        ? globSource(...argv.file, { recursive: argv.recursive })
        : toPull.source(process.stdin) // Pipe directly to ipfs.add

      const adder = ipfs.addPullStream(options)

      // No progress or piping directly to ipfs.add: no need to getTotalBytes
      if (!argv.progress || !argv.file) {
        return addPipeline(source, adder, argv)
      }

      const totalBytes = await getTotalBytes(argv.file)
      const bar = createProgressBar(totalBytes)

      options.progress = byteLength => {
        bar.update(byteLength / totalBytes, { progress: byteman(byteLength, 2, 'MB') })
      }

      return addPipeline(source, adder, argv)
    })())
  }
}
<|endoftext|>


<commit_before>var calendarEvents = [];

var currentOptions = {};

var selectedCameras = null;

var calendarChannelOptions = {
	bookings: true,
	staffAbsences: true
};

function setupCalendar(selector, onSelect, viewOptions) {
	var cal = selector.show().fullCalendar({
		// basic appearance
		header: {
			left: 'prev,next today',
			center: 'title',
			right: ''
		},
		defaultView: 'agendaWeek',
		selectable: true,
		selectHelper: true,
		allDaySlot: false,
		timeFormat: 'HH:mm',
		weekends: true,
		slotMinutes: 15,

		// set data source
		events: calendarEvents,

		// TODO
		minTime: "08:00:00",
		maxTime: "19:00:00",

		// what to display?
		viewDisplay: function (e) {
			// clear bookings
			calendarEvents.length = 0;

			// reload for new date range
			updateCalendar(selector, e.start, e.end, viewOptions);

			// resize
			var v = this;
			e.setHeight($(window).height() - $(v).position().top - 60);
			setTimeout(function () {
				e.setHeight($(window).height() - $(v).position().top - 60);
			}, 500);
		},

		// on-select function
		select: onSelect,

		// pop-up with details
		eventRender: function (event, element) {
			element.addClass(event.type);

			element.popover({
				title: event.title,
				placement: 'auto',
				html: true,
				trigger: 'hover',
				animation: 'true',
				content: event.msg,
				container: 'body'
			});

			// click listener to hide
			$('body').on('click', function (e) {
				if (!element.is(e.target) && element.has(e.target).length === 0
					&& $('.popover').has(e.target).length === 0)
					element.popover('hide');
			});
		},

		eventClick: function (calEvent, jsEvent, view) {
			if (calEvent.url && viewOptions['linkEvents']) {
				window.location.href = calEvent.url;
			}
			return false;
		},

		windowResize: function (calView) {
			calView.setHeight($(window).height() - $(this).position().top - 60);
		}
	});

	// add loading icon and toggle buttons
	cal.find('.fc-header-right').html('' +
	'' +
	'' +
	'    ' +
	'' +
	'' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="staffAbsences"> Absences</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="genericEvents"> Events</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-cameras"> Camera Use</button>' +
	'');

	// perform action for toggle buttons
	$('.calendar-channel-toggle').click(function (e) {
		e.preventDefault();

		// get target
		var target = $(this).data('target');

		// switch button classes
		if (calendarChannelOptions[target]) {
			$(this).find('i').removeClass('fa-check-square-o').addClass('fa-square-o');
		} else {
			$(this).find('i').removeClass('fa-square-o').addClass('fa-check-square-o');
		}

		// change option
		calendarChannelOptions[target] = !calendarChannelOptions[target];

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// drop focus
		$(this).blur();
	});

	// perform action for camera selection buttons
	$('.calendar-channel-cameras').click(function (e) {
		e.preventDefault();
		openCameraSelectModal();
	});

	return cal;
}

function updateCalendar(selector, startDate, endDate, options) {
	// store current options
	currentOptions['selector'] = selector;
	currentOptions['startDate'] = startDate;
	currentOptions['endDate'] = endDate;
	currentOptions['options'] = options;

	// show loading message
	$('.calendar-loading-msg').show();

	// adjust end date backwards by one
	endDate = new Date(((endDate.getTime()) - 86400000));

	// get start/end strings to pass to calendar data route
	var startDateString = startDate.getFullYear()
		+ '-'
		+ (startDate.getMonth() < 10 ? '0' : '') + (startDate.getMonth() + 1)
		+ '-'
		+ ((startDate.getDate()) < 10 ? '0' : '') + (startDate.getDate());
	var endDateString = endDate.getFullYear()
		+ '-'
		+ (endDate.getMonth() < 10 ? '0' : '') + (endDate.getMonth() + 1)
		+ '-'
		+ ((endDate.getDate()) < 10 ? '0' : '') + (endDate.getDate());

	// build URL
	var url = '/calendar-data?start=' + startDateString + '&end=' + endDateString;
	for (var key in options) url += '&' + key + '=' + (options[key] === true ? '1' : options[key]);
	for (key in calendarChannelOptions) url += '&' + key + '=' + (calendarChannelOptions[key] === true ? '1' : calendarChannelOptions[key]);
	url += '&cameras=';
	if (selectedCameras == null) {
		// default to all
		url += 'all';
	} else {
		url += selectedCameras.join(',');
	}

	// send AJAX call
	$.get(url)
		.done(function (result) {
			var rawJson = result.toString();
			var parsedJson = JSON.parse(rawJson);

			// loop through bookings
			if (calendarChannelOptions['bookings'] && typeof(parsedJson.bookings) != "undefined") {
				var bookingTitle, bookingCameraType, bookingStart, bookingEnd;
				for (var i = 0; i < parsedJson.bookings.length; ++i) {
					for (var j = 0; j < parsedJson.bookings[i].bookingSections.length; ++j) {
						// build title
						bookingTitle = parsedJson.bookings[i].therapyName + ":\n" + parsedJson.bookings[i].patientName;

						// build camera type
						bookingCameraType = parsedJson.bookings[i].cameraName;

						// start and end time
						bookingStart = parsedJson.bookings[i].bookingSections[j].startTime + ":00";
						bookingStart = bookingStart.replace(" ", "T");
						bookingEnd = parsedJson.bookings[i].bookingSections[j].endTime + ":00";
						bookingEnd = bookingEnd.replace(" ", "T");

						// add event
						calendarEvents.push({
							title: bookingTitle,
							start: bookingStart,
							end: bookingEnd,
							msg: "" +
							"Start time: " + parsedJson.bookings[i].bookingSections[j].startTime.substring(10, 16) + ""
							+ "
" +
							"End time: " + parsedJson.bookings[i].bookingSections[j].endTime.substring(10, 16) + ""
							+ "
" + bookingCameraType,
							allDay: false,
							url: '/booking-details/' + parsedJson.bookings[i].id,
							type: 'booking booking-' + parsedJson.bookings[i].colourNumber
						});
					}
				}
			}

			// loop through absences
			if (calendarChannelOptions['staffAbsences'] && typeof(parsedJson.staffAbsences) != "undefined") {
				var absenceTitle, absenceStart, absenceEnd;
				for (i = 0; i < parsedJson.staffAbsences.length; ++i) {
					// build title
					absenceTitle = "Absent: " + parsedJson.staffAbsences[i].staffName;

					// start and end time
					absenceStart = parsedJson.staffAbsences[i].from + ":00";
					absenceStart = absenceStart.replace(" ", "T");
					absenceEnd = parsedJson.staffAbsences[i].to + ":00";
					absenceEnd = absenceEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: absenceTitle,
						start: absenceStart,
						end: absenceEnd,
						msg: "" +
						"Start time: " + parsedJson.staffAbsences[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.staffAbsences[i].to.substring(10, 16) + "",
						allDay: false,
						type: 'absence'
					});
				}
			}

			// update events
			selector.fullCalendar('refetchEvents');

			// hide loading message
			$('.calendar-loading-msg').hide();
			$('.calendar-channel-filters').removeClass('hide').show();
		})
		.fail(function (xhr, textStatus, errorThrown) {
			toastr.error("Failed to load calendar data.")
			$('.calendar-loading-msg').hide();
		}
	);
}

function openCameraSelectModal() {
	var modal = $('.camera-select-modal');

	modal.removeClass('hide').modal({
		backdrop: 'static',
		keyboard: false
	});

	$('.btn-update').unbind('click').click(function (e) {
		// get selected
		selectedCameras = $('.selected-cameras:checked').map(function () {
			return this.value;
		}).get();

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// close modal
		modal.modal('hide');
	});

	$('.btn-cancel').unbind('click').click(function (e) {
		modal.modal('hide');
	});
}<commit_msg>Fade on calendar loading<commit_after>var calendarEvents = [];

var currentOptions = {};

var selectedCameras = null;

var calendarChannelOptions = {
	bookings: true,
	staffAbsences: true
};

function setupCalendar(selector, onSelect, viewOptions) {
	var cal = selector.show().fullCalendar({
		// basic appearance
		header: {
			left: 'prev,next today',
			center: 'title',
			right: ''
		},
		defaultView: 'agendaWeek',
		selectable: true,
		selectHelper: true,
		allDaySlot: false,
		timeFormat: 'HH:mm',
		weekends: true,
		slotMinutes: 15,

		// set data source
		events: calendarEvents,

		// TODO
		minTime: "08:00:00",
		maxTime: "19:00:00",

		// what to display?
		viewDisplay: function (e) {
			// clear bookings
			calendarEvents.length = 0;

			// reload for new date range
			updateCalendar(selector, e.start, e.end, viewOptions);

			// resize
			var v = this;
			e.setHeight($(window).height() - $(v).position().top - 60);
			setTimeout(function () {
				e.setHeight($(window).height() - $(v).position().top - 60);
			}, 500);
		},

		// on-select function
		select: onSelect,

		// pop-up with details
		eventRender: function (event, element) {
			element.addClass(event.type);

			element.popover({
				title: event.title,
				placement: 'auto',
				html: true,
				trigger: 'hover',
				animation: 'true',
				content: event.msg,
				container: 'body'
			});

			// click listener to hide
			$('body').on('click', function (e) {
				if (!element.is(e.target) && element.has(e.target).length === 0
					&& $('.popover').has(e.target).length === 0)
					element.popover('hide');
			});
		},

		eventClick: function (calEvent, jsEvent, view) {
			if (calEvent.url && viewOptions['linkEvents']) {
				window.location.href = calEvent.url;
			}
			return false;
		},

		windowResize: function (calView) {
			calView.setHeight($(window).height() - $(this).position().top - 60);
		}
	});

	// add loading icon and toggle buttons
	cal.find('.fc-header-right').html('' +
	'' +
	'' +
	'    ' +
	'' +
	'' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="staffAbsences"> Absences</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="genericEvents"> Events</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-cameras"> Camera Use</button>' +
	'');

	// perform action for toggle buttons
	$('.calendar-channel-toggle').click(function (e) {
		e.preventDefault();

		// get target
		var target = $(this).data('target');

		// switch button classes
		if (calendarChannelOptions[target]) {
			$(this).find('i').removeClass('fa-check-square-o').addClass('fa-square-o');
		} else {
			$(this).find('i').removeClass('fa-square-o').addClass('fa-check-square-o');
		}

		// change option
		calendarChannelOptions[target] = !calendarChannelOptions[target];

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// drop focus
		$(this).blur();
	});

	// perform action for camera selection buttons
	$('.calendar-channel-cameras').click(function (e) {
		e.preventDefault();
		openCameraSelectModal();
	});

	return cal;
}

function updateCalendar(selector, startDate, endDate, options) {
	// store current options
	currentOptions['selector'] = selector;
	currentOptions['startDate'] = startDate;
	currentOptions['endDate'] = endDate;
	currentOptions['options'] = options;

	// show loading message
	setLoading(true, selector);

	// adjust end date backwards by one
	endDate = new Date(((endDate.getTime()) - 86400000));

	// get start/end strings to pass to calendar data route
	var startDateString = startDate.getFullYear()
		+ '-'
		+ (startDate.getMonth() < 10 ? '0' : '') + (startDate.getMonth() + 1)
		+ '-'
		+ ((startDate.getDate()) < 10 ? '0' : '') + (startDate.getDate());
	var endDateString = endDate.getFullYear()
		+ '-'
		+ (endDate.getMonth() < 10 ? '0' : '') + (endDate.getMonth() + 1)
		+ '-'
		+ ((endDate.getDate()) < 10 ? '0' : '') + (endDate.getDate());

	// build URL
	var url = '/calendar-data?start=' + startDateString + '&end=' + endDateString;
	for (var key in options) url += '&' + key + '=' + (options[key] === true ? '1' : options[key]);
	for (key in calendarChannelOptions) url += '&' + key + '=' + (calendarChannelOptions[key] === true ? '1' : calendarChannelOptions[key]);
	url += '&cameras=';
	if (selectedCameras == null) {
		// default to all
		url += 'all';
	} else {
		url += selectedCameras.join(',');
	}

	// send AJAX call
	$.get(url)
		.done(function (result) {
			var rawJson = result.toString();
			var parsedJson = JSON.parse(rawJson);

			// loop through bookings
			if (calendarChannelOptions['bookings'] && typeof(parsedJson.bookings) != "undefined") {
				var bookingTitle, bookingCameraType, bookingStart, bookingEnd;
				for (var i = 0; i < parsedJson.bookings.length; ++i) {
					for (var j = 0; j < parsedJson.bookings[i].bookingSections.length; ++j) {
						// build title
						bookingTitle = parsedJson.bookings[i].therapyName + ":\n" + parsedJson.bookings[i].patientName;

						// build camera type
						bookingCameraType = parsedJson.bookings[i].cameraName;

						// start and end time
						bookingStart = parsedJson.bookings[i].bookingSections[j].startTime + ":00";
						bookingStart = bookingStart.replace(" ", "T");
						bookingEnd = parsedJson.bookings[i].bookingSections[j].endTime + ":00";
						bookingEnd = bookingEnd.replace(" ", "T");

						// add event
						calendarEvents.push({
							title: bookingTitle,
							start: bookingStart,
							end: bookingEnd,
							msg: "" +
							"Start time: " + parsedJson.bookings[i].bookingSections[j].startTime.substring(10, 16) + ""
							+ "
" +
							"End time: " + parsedJson.bookings[i].bookingSections[j].endTime.substring(10, 16) + ""
							+ "
" + bookingCameraType,
							allDay: false,
							url: '/booking-details/' + parsedJson.bookings[i].id,
							type: 'booking booking-' + parsedJson.bookings[i].colourNumber
						});
					}
				}
			}

			// loop through absences
			if (calendarChannelOptions['staffAbsences'] && typeof(parsedJson.staffAbsences) != "undefined") {
				var absenceTitle, absenceStart, absenceEnd;
				for (i = 0; i < parsedJson.staffAbsences.length; ++i) {
					// build title
					absenceTitle = "Absent: " + parsedJson.staffAbsences[i].staffName;

					// start and end time
					absenceStart = parsedJson.staffAbsences[i].from + ":00";
					absenceStart = absenceStart.replace(" ", "T");
					absenceEnd = parsedJson.staffAbsences[i].to + ":00";
					absenceEnd = absenceEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: absenceTitle,
						start: absenceStart,
						end: absenceEnd,
						msg: "" +
						"Start time: " + parsedJson.staffAbsences[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.staffAbsences[i].to.substring(10, 16) + "",
						allDay: false,
						type: 'absence'
					});
				}
			}

			// update events
			selector.fullCalendar('refetchEvents');

			// hide loading message
			setLoading(false, selector);
		})
		.fail(function (xhr, textStatus, errorThrown) {
			toastr.error("Failed to load calendar data.");
			$('.calendar-loading-msg').hide();
		}
	);
}

function openCameraSelectModal() {
	var modal = $('.camera-select-modal');

	modal.removeClass('hide').modal({
		backdrop: 'static',
		keyboard: false
	});

	$('.btn-update').unbind('click').click(function (e) {
		// get selected
		selectedCameras = $('.selected-cameras:checked').map(function () {
			return this.value;
		}).get();

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// close modal
		modal.modal('hide');
	});

	$('.btn-cancel').unbind('click').click(function (e) {
		modal.modal('hide');
	});
}

function setLoading(loading, calendar) {
	if (loading) {
		$('.calendar-loading-msg').show();
		calendar.fadeTo(300, 0.4);
	} else {
		$('.calendar-loading-msg').hide();
		$('.calendar-channel-filters').removeClass('hide').show();
		calendar.fadeTo(300, 1.0);
	}
}<|endoftext|>


<commit_before>// This is the core script of the SkyX engine. It will be served by the extension's main server.
// This architecture will allow us not only to update extensions, but to update the SkyX core remotely.
// Its purposes:
//
// 1. Load all extensions and run them.
// 2. Check for plugin updates from their servers
// 3. Prodive a GeoFS API for adding UI elements and modifying base GeoFS methods.
// 4. Add a UI to manage extensions (add, remove, update, etc.)
//
// (Add if I missed something, Ron)
//

(function() {
	var CORE_VERSION = "0.1.0";
	SkyXDebug.log("Core has been loaded");
});

// Adding some lines to trigger WebHook<commit_msg>Webhook deleted?<commit_after>// This is the core script of the SkyX engine. It will be served by the extension's main server.
// This architecture will allow us not only to update extensions, but to update the SkyX core remotely.
// Its purposes:
//
// 1. Load all extensions and run them.
// 2. Check for plugin updates from their servers
// 3. Prodive a GeoFS API for adding UI elements and modifying base GeoFS methods.
// 4. Add a UI to manage extensions (add, remove, update, etc.)
//
// (Add if I missed something, Ron)
//

(function() {
	var CORE_VERSION = "0.1.0";
	SkyXDebug.log("Core has been loaded");
});

// Adding some lines to trigger WebHook . !<|endoftext|>


<commit_before>import ContractAddress from "../fixtures/contractAddress.js";
import ContractStructure from "../fixtures/contractStructure.js";

if (typeof web3 === 'undefined') {
    var web3 = require('ethereum.js');
    window.web3 = web3;
}

web3.setProvider(new web3.providers.HttpProvider());

class EthClient {
    constructor() {
        let WorkerDispatcher = web3.eth.contract(ContractStructure.WorkerDispatcher);
        this.contract = new WorkerDispatcher(ContractAddress);
        this.identity = web3.shh.newIdentity();
    }

    getCoinbase(success) {
        success(web3.eth.coinbase);
    }

    getChain(success) {
        function createContent() {
            return {
                items: [
                    {label: "Coinbase", value: web3.eth.coinbase},
                    {label: "Accounts", value: web3.eth.accounts},
                    {label: "Balance", value: web3.toDecimal(web3.eth.getBalance(web3.eth.coinbase))}
                ]
            }
        }

        success(createContent());
        web3.eth.filter('chain').watch(function() {
            success(createContent());
        });
    }

    getPending(success) {
        let contract = this.contract;
        function createContent() {
            let workers = contract.numWorkers();
            let latestBlock = web3.eth.blockNumber;
            return {
                items: [
                    {label: "Latest block", value: latestBlock},
                    {label: "Latest block hash", value: web3.eth.getBlock(latestBlock).hash},
                    {label: "Latest block timestamp", value: web3.eth.getBlock(latestBlock).timestamp},
                    {label: "Contract address", value: ContractAddress},
                    {label: "Number of workers", value: workers.toString()}
                ]
            }
        }
        success(createContent());
        web3.eth.filter('pending').watch(function() {
            success(createContent());
        });
    }

    unregisterChain() {
        web3.eth.filter('chain').stopWatching();
    }

    unregisterPending() {
        web3.eth.filter('pending').stopWatching();
    }

    registerWorker(maxLength, price, name) {
        this.contract.registerWorker(maxLength, price, name);
    }

    changeWorkerPrice(newPrice) {
        this.contract.changeWorkerPrice(newPrice);
    }

    bigNumberToInt(bigNumber) {
        return bigNumber.c[0];
    }

    findWorkers(length, price, success) {
        let numWorkers = this.bigNumberToInt(this.contract.numWorkers());
        let workers = [];
        for (let i = 0; i < numWorkers; i++) {
            let address = this.contract.workerList(i);
            let info = this.contract.workersInfo(address);
            let workerLength = this.bigNumberToInt(info[1]);
            let workerPrice = this.bigNumberToInt(info[2]);
            if (length <= workerLength && price >= workerPrice) {
                workers[workers.length] = {pubkey: address, name: info[0], length: workerLength, price: workerPrice};
            }
        }

        success(workers);
    }

    setJsonRpc(url) {
        web3.setProvider(new web3.providers.HttpProvider(url));
    }

    sendMsg(to, data) {
        web3.shh.post({
            "from": this.identity,
            "to": to,
            "payload": [ web3.fromAscii(data) ],
        });
    }

    askWorker(workerAddress, contractAddress) {
        web3.shh.post({
            "from": this.identity,
            "topic": workerAddress,
            "payload": [ contractAddress ],
        });
    }
}

let ethclient = new EthClient();

export default ethclient;
<commit_msg>Made the support for external eth clients better<commit_after>import ContractAddress from "../fixtures/contractAddress.js";
import ContractStructure from "../fixtures/contractStructure.js";

if (typeof web3 === 'undefined') {
    var web3 = require('ethereum.js');
    window.web3 = web3;
}

web3.setProvider(new web3.providers.HttpProvider());

class EthClient {
    constructor() {
        try {
            var m = web3.eth.getStorageAt(ContractAddress, "0x1");
            let WorkerDispatcher = web3.eth.contract(ContractStructure.WorkerDispatcher);
            this.contract = new WorkerDispatcher(ContractAddress);
            this.identity = web3.shh.newIdentity();
        }
        catch(e) {
            console.log("Could not contact localhost:8080");
        }
    }

    getCoinbase(success) {
        success(web3.eth.coinbase);
    }

    getChain(success) {
        function createContent() {
            return {
                items: [
                    {label: "Coinbase", value: web3.eth.coinbase},
                    {label: "Accounts", value: web3.eth.accounts},
                    {label: "Balance", value: web3.toDecimal(web3.eth.getBalance(web3.eth.coinbase))}
                ]
            }
        }

        success(createContent());
        web3.eth.filter('chain').watch(function() {
            success(createContent());
        });
    }

    getPending(success) {
        let contract = this.contract;
        function createContent() {
            let workers = contract.numWorkers();
            let latestBlock = web3.eth.blockNumber;
            return {
                items: [
                    {label: "Latest block", value: latestBlock},
                    {label: "Latest block hash", value: web3.eth.getBlock(latestBlock).hash},
                    {label: "Latest block timestamp", value: web3.eth.getBlock(latestBlock).timestamp},
                    {label: "Contract address", value: ContractAddress},
                    {label: "Number of workers", value: workers.toString()}
                ]
            }
        }
        success(createContent());
        web3.eth.filter('pending').watch(function() {
            success(createContent());
        });
    }

    unregisterChain() {
        web3.eth.filter('chain').stopWatching();
    }

    unregisterPending() {
        web3.eth.filter('pending').stopWatching();
    }

    registerWorker(maxLength, price, name) {
        this.contract.registerWorker(maxLength, price, name);
    }

    changeWorkerPrice(newPrice) {
        this.contract.changeWorkerPrice(newPrice);
    }

    bigNumberToInt(bigNumber) {
        return bigNumber.c[0];
    }

    findWorkers(length, price, success) {
        let numWorkers = this.bigNumberToInt(this.contract.numWorkers());
        let workers = [];
        for (let i = 0; i < numWorkers; i++) {
            let address = this.contract.workerList(i);
            let info = this.contract.workersInfo(address);
            let workerLength = this.bigNumberToInt(info[1]);
            let workerPrice = this.bigNumberToInt(info[2]);
            if (length <= workerLength && price >= workerPrice) {
                workers[workers.length] = {pubkey: address, name: info[0], length: workerLength, price: workerPrice};
            }
        }

        success(workers);
    }

    setJsonRpc(url) {
        web3.setProvider(new web3.providers.HttpProvider(url));
    }

    sendMsg(to, data) {
        web3.shh.post({
            "from": this.identity,
            "to": to,
            "payload": [ web3.fromAscii(data) ],
        });
    }

    askWorker(workerAddress, contractAddress) {
        web3.shh.post({
            "from": this.identity,
            "topic": workerAddress,
            "payload": [ contractAddress ],
        });
    }
}

let ethclient = new EthClient();

export default ethclient;
<|endoftext|>


<commit_before>module.exports = {
    directory: __dirname,
    prefix: 'eric',
    fields: {
        creator_e: {
            type: 'edge',
            unidirected: false,
            label: 'Creator'
        },
        wrote: {
            type: 'inverseedge',
            edge: 'creator_e'
        },
        title: {
            type: 'text',
            label: 'Title',
            css: 'font-weight: bold; font-size: 120%;'
        },
        source: {
            type: 'text',
            label: 'Source',
            css: 'font-style: italic;'
        },
        citation: {
            type: 'text',
            label: 'Citation'
        },
        description: {
            type: 'text',
            label: 'Description'
        },
        publisher: {
            type: 'text',
            label: 'Publisher'
        },
        uri: {
            type: 'property',
            datatype: 'String',
            unique: false,
            multivalue: true,
            label: 'URI'
        },
        subject_e: {
            type: 'edge',
            label: 'Subject'
        },
        source_e: {
            type: 'edge',
            label: 'Source (edge)'
        }
    },
    facets: {
        creator_e: {
            outlabel: 'By',
            inlabel: 'Wrote',
            facetlabel: 'Author'
        },
        subject_e: {
            outlabel: 'About',
            inlabel: 'Topic of',
            facetlabel: 'Subject'
        },
        source_e: {
            outlabel: 'In',
            inlabel: 'Contains',
            facetlabel: 'Source'
        }
    },
    static_relevance_bumps: {
        recordclass: {
            biblio: 2,
            term: 0.5,
            synonym: -0.5
        }
    },
    templates: [
        'eric'
    ]
};

<commit_msg>Correct eric boosts<commit_after>module.exports = {
    directory: __dirname,
    prefix: 'eric',
    fields: {
        creator_e: {
            type: 'edge',
            unidirected: false,
            label: 'Creator'
        },
        wrote: {
            type: 'inverseedge',
            edge: 'creator_e'
        },
        title: {
            type: 'text',
            label: 'Title',
            css: 'font-weight: bold; font-size: 120%;'
        },
        source: {
            type: 'text',
            label: 'Source',
            css: 'font-style: italic;'
        },
        citation: {
            type: 'text',
            label: 'Citation'
        },
        description: {
            type: 'text',
            label: 'Description'
        },
        publisher: {
            type: 'text',
            label: 'Publisher'
        },
        uri: {
            type: 'property',
            datatype: 'String',
            unique: false,
            multivalue: true,
            label: 'URI'
        },
        subject_e: {
            type: 'edge',
            label: 'Subject'
        },
        source_e: {
            type: 'edge',
            label: 'Source (edge)'
        }
    },
    facets: {
        creator_e: {
            outlabel: 'By',
            inlabel: 'Wrote',
            facetlabel: 'Author'
        },
        subject_e: {
            outlabel: 'About',
            inlabel: 'Topic of',
            facetlabel: 'Subject'
        },
        source_e: {
            outlabel: 'In',
            inlabel: 'Contains',
            facetlabel: 'Source'
        }
    },
    static_relevance_bumps: {
        recordclass: {
            biblio: 2,
            term: 0.5,
            synonym: 0.2
        }
    },
    templates: [
        'eric'
    ]
};

<|endoftext|>