<commit_before>/**
 * module.js - The core of module loader
 */

var cachedModules = seajs.cache = {}

var STATUS = {
  'LOADING': 1,   // The module file is loading
  'SAVED': 2,     // The module data has been saved to cachedModules
  'LOADED': 3,    // The module and all its dependencies are ready to compile
  'COMPILING': 4, // The module is being compiled
  'COMPILED': 5   // The module is compiled and `module.exports` is available
}

function Module(uri, status) {
  this.uri = uri
  this.status = status || STATUS.LOADING
  this.dependencies = []
  this.waitings = []
}

Module.prototype.load = function(ids, callback) {
  var uris = resolve(isArray(ids) ? ids : [ids], this.uri)

  load(uris, function() {
    var exports = []

    forEach(uris, function(uri, i) {
      exports[i] = compile(cachedModules[uri])
    })

    if (callback) {
      callback.apply(global, exports)
    }
  })
}

function resolve(ids, refUri) {
  if (isArray(ids)) {
    // Use `for` loop instead of `forEach` or `map` function for performance
    var ret = []
    for (var i = 0, len = ids.length; i < len; i++) {
      ret[i] = resolve(ids[i], refUri)
    }
    return ret
  }

  return id2Uri(ids, refUri)
}

function load(uris, callback, options) {
  options = options || {}
  var unloadedUris = options.filtered ? uris : getUnloadedUris(uris)

  if (unloadedUris.length === 0) {
    callback()
    return
  }

  // Emit load event for plugins such as combo plugin
  emit('load', unloadedUris)

  var len = unloadedUris.length
  var remain = len

  for (var i = 0; i < len; i++) {
    (function(uri) {

      var mod = cachedModules[uri]
      mod.status < STATUS.SAVED ? fetch(uri, onFetched) : onFetched()

      function onFetched() {
        // Maybe failed to fetch successfully, such as 404 error
        // In these cases, just call `cb` function directly
        if (mod.status < STATUS.SAVED) {
          done()
          return
        }

        // Break circular waiting callbacks
        if (isCircularWaiting(mod)) {
          printCircularLog(circularStack)
          circularStack.length = 0
          done(mod)
          return
        }

        // Load all unloaded dependencies
        var waitings = mod.waitings = getUnloadedUris(mod.dependencies)
        if (waitings.length === 0) {
          done(mod)
          return
        }

        load(waitings, function() {
          done(mod)
        }, { filtered: true })
      }

    })(unloadedUris[i])
  }

  function done(mod) {
    if (mod && mod.status < STATUS.LOADED) {
      mod.status = STATUS.LOADED
    }

    if (--remain === 0) {
      callback()
    }
  }
}

var fetchingList = {}
var fetchedList = {}
var callbackList = {}
var anonymousModuleMeta = null

function fetch(uri, callback) {
  // Emit `fetch` event. Plugins could use this event to
  // modify uri or do other magic things
  var requestUri = emitData('fetch',
      { uri: uri, fetchedList: fetchedList },
      'uri')

  if (fetchedList[requestUri]) {
    callback()
    return
  }

  if (fetchingList[requestUri]) {
    callbackList[requestUri].push(callback)
    return
  }

  fetchingList[requestUri] = true
  callbackList[requestUri] = [callback]

  // Send request
  var charset = config.charset
  var requested = emitData('request',
      { uri: requestUri, callback: onRequested, charset: charset },
      'requested')

  if (!requested) {
    request(requestUri, onRequested, charset)
  }

  function onRequested() {
    delete fetchingList[requestUri]
    fetchedList[requestUri] = true

    // Save meta data of anonymous module
    if (anonymousModuleMeta) {
      save(uri, anonymousModuleMeta)
      anonymousModuleMeta = null
    }

    // Call callbacks
    var fn, fns = callbackList[requestUri]
    delete callbackList[requestUri]
    while ((fn = fns.shift())) fn()
  }
}

function define(id, deps, factory) {
  var argsLen = arguments.length

  // HANDLE: define(factory)
  if (argsLen === 1) {
    factory = id
    id = undefined
  }
  // HANDLE: define(id || deps, factory)
  else if (argsLen === 2) {
    factory = deps
    deps = undefined

    // HANDLE: define(deps, factory)
    if (isArray(id)) {
      deps = id
      id = undefined
    }
  }

  // Parse dependencies according to the module factory code
  if (!isArray(deps) && isFunction(factory)) {
    deps = parseDependencies(factory.toString())
  }

  var meta = { id: id, dependencies: deps, factory: factory }
  var derivedUri

  // Try to derive uri in IE6-9 for anonymous modules
  if (!id && doc.attachEvent) {
    var script = getCurrentScript()

    if (script && script.src) {
      derivedUri = getScriptAbsoluteSrc(script)
      derivedUri = emitData('derived', { uri: derivedUri })
    }
    else {
      log('Failed to derive URI from interactive script for:',
          factory.toString(), 'warn')

      // NOTE: If the id-deriving methods above is failed, then falls back
      // to use onload event to get the uri
    }
  }

  var resolvedUri = id ? resolve(id) : derivedUri

  if (resolvedUri) {
    save(resolvedUri, meta)
  }
  else {
    // Save information for "memoizing" work in the script onload event
    anonymousModuleMeta = meta
  }

}

function save(uri, meta) {
  var mod = getModule(uri)

  // Do NOT override already saved modules
  if (mod.status < STATUS.SAVED) {
    mod.id = meta.id || uri // Let anonymous module id equal to its uri
    mod.dependencies = resolve(meta.dependencies || [], uri)
    mod.factory = meta.factory

    mod.status = STATUS.SAVED
  }
}

function compile(mod) {
  // When module is compiled, DO NOT compile it again. When module
  // is being compiled, just return `module.exports` too, for avoiding
  // circularly calling
  if (mod.status >= STATUS.COMPILING) {
    return mod.exports
  }

  emit('compile', mod)

  // Just return `null` when:
  //  1. the module file is 404
  //  2. the module file is not written with valid module format
  //  3. other error cases
  if (mod.status < STATUS.LOADED && mod.exports === undefined) {
    return null
  }

  mod.status = STATUS.COMPILING

  function require(id) {
    var child = cachedModules[require.resolve(id)]

    // Return `null` when `uri` is invalid
    if (child === undefined) {
      return null
    }

    child.parent = mod
    return compile(child)
  }

  require.async = function(ids, callback) {
    mod.load(ids, callback)
  }

  require.resolve = function(id) {
    return resolve(id, mod.uri)
  }

  require.cache = cachedModules

  var factory = mod.factory
  var exports = factory === undefined ? mod.exports : factory

  if (isFunction(factory)) {
    exports = factory(mod.require, mod.exports, mod)
  }

  mod.exports = exports === undefined ? {} : exports
  mod.status = STATUS.COMPILED

  emit('compiled', mod)

  delete mod.factory
  delete mod.waitings

  return mod.exports
}

// Helpers

function getModule(uri, status) {
  return cachedModules[uri] ||
      (cachedModules[uri] = new Module(uri, status))
}

function getUnloadedUris(uris) {
  var ret = []

  forEach(uris, function(uri) {
    if (getModule(uri).status < STATUS.LOADED) {
      ret.push(uri)
    }
  })
  return ret
}

var circularStack = []

function isCircularWaiting(mod) {
  var waitings = mod.waitings
  if (waitings.length === 0) {
    return false
  }

  circularStack.push(mod.uri)
  if (isOverlap(waitings, circularStack)) {
    return true
  }

  for (var i = 0; i < waitings.length; i++) {
    if (isCircularWaiting(cachedModules[waitings[i]])) {
      return true
    }
  }

  circularStack.pop()
  return false
}

function printCircularLog(stack) {
  stack.push(stack[0])
  log('Found circular dependencies:', stack.join(' --> '))
}

function isOverlap(arrA, arrB) {
  var arrC = arrA.concat(arrB)
  return  unique(arrC).length < arrC.length
}

// Public API

var globalModule = new Module(pageUri, STATUS.COMPILED)

function preload(callback) {
  var preloadModules = config.preload
  var len = preloadModules.length

  len ? globalModule.load(preloadModules.splice(0, len), callback) :
      callback()
}

seajs.use = function(ids, callback) {
  // Load preload modules before all other modules
  preload(function() {
    globalModule.load(ids, callback)
  })
  return seajs
}

global.define = define

<commit_msg>Improve compile function<commit_after>/**
 * module.js - The core of module loader
 */

var cachedModules = seajs.cache = {}

var STATUS = {
  'LOADING': 1,   // The module file is loading
  'SAVED': 2,     // The module data has been saved to cachedModules
  'LOADED': 3,    // The module and all its dependencies are ready to compile
  'COMPILING': 4, // The module is being compiled
  'COMPILED': 5   // The module is compiled and `module.exports` is available
}

function Module(uri, status) {
  this.uri = uri
  this.status = status || STATUS.LOADING
  this.dependencies = []
  this.waitings = []
}

Module.prototype.load = function(ids, callback) {
  var uris = resolve(isArray(ids) ? ids : [ids], this.uri)

  load(uris, function() {
    var exports = []

    forEach(uris, function(uri, i) {
      exports[i] = compile(cachedModules[uri])
    })

    if (callback) {
      callback.apply(global, exports)
    }
  })
}

function resolve(ids, refUri) {
  if (isArray(ids)) {
    // Use `for` loop instead of `forEach` or `map` function for performance
    var ret = []
    for (var i = 0, len = ids.length; i < len; i++) {
      ret[i] = resolve(ids[i], refUri)
    }
    return ret
  }

  return id2Uri(ids, refUri)
}

function load(uris, callback, options) {
  options = options || {}
  var unloadedUris = options.filtered ? uris : getUnloadedUris(uris)

  if (unloadedUris.length === 0) {
    callback()
    return
  }

  // Emit load event for plugins such as combo plugin
  emit('load', unloadedUris)

  var len = unloadedUris.length
  var remain = len

  for (var i = 0; i < len; i++) {
    (function(uri) {

      var mod = cachedModules[uri]
      mod.status < STATUS.SAVED ? fetch(uri, onFetched) : onFetched()

      function onFetched() {
        // Maybe failed to fetch successfully, such as 404 error
        // In these cases, just call `cb` function directly
        if (mod.status < STATUS.SAVED) {
          done()
          return
        }

        // Break circular waiting callbacks
        if (isCircularWaiting(mod)) {
          printCircularLog(circularStack)
          circularStack.length = 0
          done(mod)
          return
        }

        // Load all unloaded dependencies
        var waitings = mod.waitings = getUnloadedUris(mod.dependencies)
        if (waitings.length === 0) {
          done(mod)
          return
        }

        load(waitings, function() {
          done(mod)
        }, { filtered: true })
      }

    })(unloadedUris[i])
  }

  function done(mod) {
    if (mod && mod.status < STATUS.LOADED) {
      mod.status = STATUS.LOADED
    }

    if (--remain === 0) {
      callback()
    }
  }
}

var fetchingList = {}
var fetchedList = {}
var callbackList = {}
var anonymousModuleMeta = null

function fetch(uri, callback) {
  // Emit `fetch` event. Plugins could use this event to
  // modify uri or do other magic things
  var requestUri = emitData('fetch',
      { uri: uri, fetchedList: fetchedList },
      'uri')

  if (fetchedList[requestUri]) {
    callback()
    return
  }

  if (fetchingList[requestUri]) {
    callbackList[requestUri].push(callback)
    return
  }

  fetchingList[requestUri] = true
  callbackList[requestUri] = [callback]

  // Send request
  var charset = config.charset
  var requested = emitData('request',
      { uri: requestUri, callback: onRequested, charset: charset },
      'requested')

  if (!requested) {
    request(requestUri, onRequested, charset)
  }

  function onRequested() {
    delete fetchingList[requestUri]
    fetchedList[requestUri] = true

    // Save meta data of anonymous module
    if (anonymousModuleMeta) {
      save(uri, anonymousModuleMeta)
      anonymousModuleMeta = null
    }

    // Call callbacks
    var fn, fns = callbackList[requestUri]
    delete callbackList[requestUri]
    while ((fn = fns.shift())) fn()
  }
}

function define(id, deps, factory) {
  var argsLen = arguments.length

  // HANDLE: define(factory)
  if (argsLen === 1) {
    factory = id
    id = undefined
  }
  // HANDLE: define(id || deps, factory)
  else if (argsLen === 2) {
    factory = deps
    deps = undefined

    // HANDLE: define(deps, factory)
    if (isArray(id)) {
      deps = id
      id = undefined
    }
  }

  // Parse dependencies according to the module factory code
  if (!isArray(deps) && isFunction(factory)) {
    deps = parseDependencies(factory.toString())
  }

  var meta = { id: id, dependencies: deps, factory: factory }
  var derivedUri

  // Try to derive uri in IE6-9 for anonymous modules
  if (!id && doc.attachEvent) {
    var script = getCurrentScript()

    if (script && script.src) {
      derivedUri = getScriptAbsoluteSrc(script)
      derivedUri = emitData('derived', { uri: derivedUri })
    }
    else {
      log('Failed to derive URI from interactive script for:',
          factory.toString(), 'warn')

      // NOTE: If the id-deriving methods above is failed, then falls back
      // to use onload event to get the uri
    }
  }

  var resolvedUri = id ? resolve(id) : derivedUri

  if (resolvedUri) {
    save(resolvedUri, meta)
  }
  else {
    // Save information for "memoizing" work in the script onload event
    anonymousModuleMeta = meta
  }

}

function save(uri, meta) {
  var mod = getModule(uri)

  // Do NOT override already saved modules
  if (mod.status < STATUS.SAVED) {
    mod.id = meta.id || uri // Let anonymous module id equal to its uri
    mod.dependencies = resolve(meta.dependencies || [], uri)
    mod.factory = meta.factory

    mod.status = STATUS.SAVED
  }
}

function compile(mod) {
  // When module is compiled, DO NOT compile it again. When module
  // is being compiled, just return `module.exports` too, for avoiding
  // circularly calling
  if (mod.status >= STATUS.COMPILING) {
    return mod.exports
  }

  emit('compile', mod)

  // Just return `null` when:
  //  1. the module file is 404
  //  2. the module file is not written with valid module format
  //  3. other error cases
  if (mod.status < STATUS.LOADED && mod.exports === undefined) {
    return null
  }

  mod.status = STATUS.COMPILING

  function require(id) {
    var child = cachedModules[require.resolve(id)]

    // Return `null` when `uri` is invalid
    if (child === undefined) {
      return null
    }

    child.parent = mod
    return compile(child)
  }

  require.async = function(ids, callback) {
    mod.load(ids, callback)
  }

  require.resolve = function(id) {
    return resolve(id, mod.uri)
  }

  require.cache = cachedModules

  var factory = mod.factory
  var exports = factory === undefined ? mod.exports : factory

  if (isFunction(factory)) {
    exports = factory(mod.require, mod.exports, mod)
  }

  mod.exports = exports === undefined ? {} : exports
  mod.status = STATUS.COMPILED

  emit('compiled', mod)
  return mod.exports
}

// Helpers

function getModule(uri, status) {
  return cachedModules[uri] ||
      (cachedModules[uri] = new Module(uri, status))
}

function getUnloadedUris(uris) {
  var ret = []

  forEach(uris, function(uri) {
    if (getModule(uri).status < STATUS.LOADED) {
      ret.push(uri)
    }
  })
  return ret
}

var circularStack = []

function isCircularWaiting(mod) {
  var waitings = mod.waitings
  if (waitings.length === 0) {
    return false
  }

  circularStack.push(mod.uri)
  if (isOverlap(waitings, circularStack)) {
    return true
  }

  for (var i = 0; i < waitings.length; i++) {
    if (isCircularWaiting(cachedModules[waitings[i]])) {
      return true
    }
  }

  circularStack.pop()
  return false
}

function printCircularLog(stack) {
  stack.push(stack[0])
  log('Found circular dependencies:', stack.join(' --> '))
}

function isOverlap(arrA, arrB) {
  var arrC = arrA.concat(arrB)
  return  unique(arrC).length < arrC.length
}

// Public API

var globalModule = new Module(pageUri, STATUS.COMPILED)

function preload(callback) {
  var preloadModules = config.preload
  var len = preloadModules.length

  len ? globalModule.load(preloadModules.splice(0, len), callback) :
      callback()
}

seajs.use = function(ids, callback) {
  // Load preload modules before all other modules
  preload(function() {
    globalModule.load(ids, callback)
  })
  return seajs
}

global.define = define

<|endoftext|>


<commit_before>/* global kuromoji */
import d3 from "d3"
import "kuromoji"

if(1){
  document.write("JavaScriptはONです。");
}

var i,j,k,l,m,n,bunsuu;  //mは段落

var width = 1320,
    height = 660;

var color = d3.scale.category20c();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(120)
    .size([width, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

document.getElementById('load-button').addEventListener('click', function () {
        var file = document.getElementById('file-input').files[0];
        var reader = new FileReader();
        reader.onload = function(event) {
            var data = JSON.parse(event.target.result);
            console.log(data);

            kuromoji.builder({dicPath: 'dict/'}).build((err, tokenizer) => {
              const path = tokenizer.tokenize(data[0].a); //1集計単位ごとにこの関数を用いよう
              console.log(path);

              var keitaisokaiseki = new Array; //このlengthは段落数
              var reasonMatrix = new Array;

              var buntou;
              var tegakari;
              var toutencount;
              var toutenbasho=0;
              n=0; //nは全データ内で何文字目か
              bunsuu=0; //全段落内で何分目か
              m=0; //何個目の発言か
              var karabasho;
              var reason;
              var kara="から"
              while(n<path.length){//発言ごとのループ
                keitaisokaiseki[m] = new Array; //一発言
                i=0; //段落内の何文目か。
                while(n<path.length){//文ごとのループ
                  keitaisokaiseki[m][i] = new Array; //文
                  keitaisokaiseki[m][i].length = 0;
                  reasonMatrix[i] = new Array;
                  k=0; //集計単位内で何単語目か
                  while(n<path.length){//単語ごとのループ
                      if(path[n].basic_form=="。"||path[n].basic_form=="？"||path[n].basic_form=="?"||path[n].word_id=="2613630"){
                        bunsuu++;
                        toutencount=0;
                        break;//3区間終了
                      }
                      keitaisokaiseki[m][i][k] = path[n].basic_form;
                      reasonMatrix[i][k] = reason;
                      n++;
                      k++;
                  }
                  if(n==path.length){//確認
                    break;
                  }
                  if(path[n].word_id=="2613630"){
                    n++;
                    break;
                  }//1段落作成完了
                  n++;
                  i++;//段落内の何文目か
                }
                m++;
              }

            //以下、想定していた形態素解析後の結果から、共起ネットワークのノード・エッジ作成へ

            console.log(keitaisokaiseki);

            var tangoset = new Set();

            var tmp=new Array;

            for(m=0;m
              <keitaisokaiseki.length;++m){
              for(i=0;i<keitaisokaiseki[m].length;++i){
                tmp = keitaisokaiseki[m][i];
                console.log("m=%d,i=%d",m,i);
                console.log(tmp);
                if(keitaisokaiseki[m][i] ==false||keitaisokaiseki[m][i]==new Array){
                  keitaisokaiseki[m][i].length=0;
                  continue;
                }
                for(j=0;j<tmp.length;++j){
                  tangoset.add({name:keitaisokaiseki[m][i][j],
                                group:reasonMatrix[i][j]

                              });

                  }
                }
            }

          var tangosett = new Array;;

          tangosett = Array.from(tangoset).map(function(t) {
            return {t};
            // body...
          });

            var miserables={"nodes":new Array,"links":new Array};

            for(i=0;i<tangosett.length;i++){
              miserables.nodes[i]=tangosett[i].t;
            }

            console.log(miserables.nodes);
            console.log(miserables.nodes.length);

            /*あとはlinksの作成だけ
            まずはlistをつくる*/
            var list = new Array(keitaisokaiseki.length);
            //list作成

            var RGBlist  = new Array(keitaisokaiseki.length);

            //keitaisokaisekiとnodesを照らしあわせる
            for(m=0;m<keitaisokaiseki.length;++m){
              list[m] = new Array(keitaisokaiseki[m].length);
              for(i=0;i<keitaisokaiseki[m].length;++i){
                list[m][i] = new Array(miserables.nodes.length);
                for(j=0;j<keitaisokaiseki[m][i].length;++j){
                  for(k=0;k<miserables.nodes.length;++k){
                    if(keitaisokaiseki[m][i][j]==miserables.nodes[k].name){
                      list[m][i][k]=1;
                      if(keitaisokaiseki[m][i][j]=="母"){
                        console.log("%d発言目の%d文目の%d語目に「母」が出ています",m,i,j);
                      }

                    }
                  }
                }
              }
            }

            console.log(list);
            //listはi*k

            //listからmiserables.linksとlist3をつくる

            var x,y,z;

            var edge=-1;

                for(k=0;k<miserables.nodes.length;++k){

                  for(l=k+1;l<miserables.nodes.length;++l){//別の単語を見る
                    //現在単語2個の組み合わせを選択中

                    //ここから段落を指定して縦になめる

                    for(m=0;i<keitaisokaiseki.length;++m){
                      for(i=0;i<keitaisokaiseki[m].length;++i){
                        x=list[m][i][k];
                        y=list[m][i][l];

                        if(x==1 && y==1){

                          miserables.links.push({source:l,target:k,value:0});
                          edge++;//最初のedgeが0
                          break;
                        }
                      }
                    }
                      //とりあえずエッジつくってbreak
                      //こっからvalueを与える
                    for(m=0;i<keitaisokaiseki.length;++m){
                      for(i=0;i<keitaisokaiseki[m].length;++i){
                        x=list[m][i][k];
                        y=list[m][i][l];
                        if(x==1 && y==1){
                          z = miserables.links[edge].value;
                          z++;
                          miserables.links[edge].value = z;
                        }
                      }
                    }

                    }

                  }

                console.log(miserables.links);

            //以上計算中

            var graph = miserables;

//共起マップ
/*
                force
                    .nodes(graph.nodes)
                    .links(graph.links)
                    .start();

*/
/*
                var link = svg.selectAll(".link")
                    .data(graph.links)
                  .enter().append("line")
                    .attr("class", "link")
                    .style("stroke-width", function(d) { return Math.sqrt(d.value); });
*/
/*              var node = svg.selectAll(".node")
                  .data(graph.nodes)
                .enter().append("text")
                  .attr("class", "node")
                  .style("fill", function(d) {
                    if(d.group==1){
                      return "red";
                    } else{
                      return "blue";
                    }

                  })
                  .call(force.drag)
                  .text(function(d) { return d.name; });
*/

/*
                force.on("tick", function() {
                  link.attr("x1", function(d) { return d.source.x; })
                      .attr("y1", function(d) { return d.source.y; })
                      .attr("x2", function(d) { return d.target.x; })
                      .attr("y2", function(d) { return d.target.y; });

                  node.attr("x", function(d) { return d.x; })
                      .attr("y", function(d) { return d.y; });
                });

*/

                });
        };
        reader.readAsText(file);

        /*clustering*/

  });

  var cluster = require('hierarchical-clustering');
  var colors = [
  [20, 20, 80],
  [22, 22, 90],
  [250, 255, 253],
  [100, 54, 255]
  ];

  // Euclidean distance
  function distance(a, b) {
  var d = 0;
  for (var i = 0; i < a.length; i++) {
  d += Math.pow(a[i] - b[i], 2);
  }
  return Math.sqrt(d);
  }

  // Single-linkage clustering
  function linkage(distances) {
  return Math.min.apply(null, distances);
  }

  var levels = cluster({
  input: colors,
  distance: distance,
  linkage: linkage,
  minClusters: 2, // only want two clusters
  });

  var clusters = levels[levels.length - 1].clusters;
  console.log(clusters);
  // => [ [ 2 ], [ 3, 1, 0 ] ]
  clusters = clusters.map(function (cluster) {
  return cluster.map(function (index) {
  return colors[index];
  });
  });
  console.log(clusters);
  // => [ [ [ 250, 255, 253 ] ],
  // => [ [ 100, 54, 255 ], [ 22, 22, 90 ], [ 20, 20, 80 ] ] ]

//ドットで区切る
//単語グループ分け -> 形態素解析時点で。

//クライアントの各文の得点換算
//stackdataArr完成

          var stackdataArr = [
              [{x:1,y:3},{x:2,y:5},{x:3,y:7},{x:4,y:3},{x:5,y:5},{x:6,y:7}],
              [{x:1,y:2},{x:2,y:4},{x:3,y:9},{x:4,y:7},{x:5,y:6},{x:6,y:4}],
              [{x:1,y:1},{x:2,y:8},{x:3,y:5},{x:4,y:3},{x:5,y:5},{x:6,y:7}],
              [{x:1,y:18},{x:2,y:7},{x:3,y:3},{x:4,y:11},{x:5,y:8},{x:6,y:6}]
          ];
          var stack = d3.layout.stack()
              .x(function(d){return 1;})
              .y(function(d){return d.y;})
              .values(function(d){return d;});
          var stackdata = stack(stackdataArr);
          var max = d3.max(stackdata[stackdata.length - 1], function(d){return d.y + d.y0;});
          var scaleX = d3.scale.linear().domain([0,6]).range([0,width/2]);
          var scaleY = d3.scale.linear().domain([0,max]).range([0,200]);
          var colors = ["lightgray","#77ff77","#ff7777","#7777ff","yellow","#0f0","green"];
          var colors2 = ["gray","#d4d","#d4d","gray","#d4d","#d4d","gray"];
          var area = d3.svg.area()
              .x(function(d,i){return i * width/10})
              .y0(function(d){return 200})
              .y1(function(d){return 200 - scaleY(d.y+d.y0)});
          svg.selectAll("path")
              .data(stackdata.reverse())
              .enter()
              .append("path")
              .attr("d", area)
              .attr("fill",function(d,i){return colors[i]});

              //grid line
              //引数はstart,stop,stepの順
              //[190,170,150,130,110,90,70,50,30,10]と同等
            var range = d3.range((width/2)-(width/20),4,-width/10);
            svg.selectAll("line.v")
              .data(range).enter().append("line")
              .attr("x1", function(d,i){return d;}).attr("y1", 0)
              .attr("x2", function(d,i){return d;}).attr("y2", 200);
            svg.selectAll("line")
              .attr("stroke", function(d,i){return colors2[i]})
              .attr("stroke-width", 10)

//チェックボックス

              function boxCheck(){

                //チェックされた項目を記録する変数
                var str="";

                //for文でチェックボックスを１つずつ確認
                for( i=0; i<6; i++ )
                {
                  //チェックされているか確認する
                  if( document.chbox.elements[i].checked )
                  {
                    //変数strが空でない時、区切りのコンマを入れる
                    if( str != "" ) str=str+",";

                    //チェックボックスのvalue値を変数strに入れる
                    str=str+document.chbox.elements[i].value;
                  }
                }

                //strが空の時、警告を出す
                if( str=="" ){
                   alert( "どれか選択してください。" );
                }else{
                  alert( str + "が選択されました。" );
                }
              }
<commit_msg>countable!<commit_after>/* global kuromoji */
import d3 from "d3"
import "kuromoji"

if(1){
  document.write("JavaScriptはONです。");
}

var i,j,k,l,m,n,bunsuu;  //mは段落

var width = 1320,
    height = 660;

var color = d3.scale.category20c();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(120)
    .size([width, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

document.getElementById('load-button').addEventListener('click', function () {
        var file = document.getElementById('file-input').files[0];
        var reader = new FileReader();
        reader.onload = function(event) {
            var data = JSON.parse(event.target.result);
            console.log(data);

            kuromoji.builder({dicPath: 'dict/'}).build((err, tokenizer) => {
              const path = tokenizer.tokenize(data[0].a); //1集計単位ごとにこの関数を用いよう
              console.log(path);

              var keitaisokaiseki = new Array; //このlengthは段落数
              var reasonMatrix = new Array;

              var buntou;
              var tegakari;
              var toutencount;
              var toutenbasho=0;
              n=0; //nは全データ内で何文字目か
              bunsuu=0; //全段落内で何分目か
              m=0; //何個目の発言か
              var karabasho;
              var reason;
              var kara="から"
              while(n<path.length){//発言ごとのループ
                keitaisokaiseki[m] = new Array; //一発言
                i=0; //段落内の何文目か。
                while(n<path.length){//文ごとのループ
                  keitaisokaiseki[m][i] = new Array; //文
                  keitaisokaiseki[m][i].length = 0;
                  reasonMatrix[i] = new Array;
                  k=0; //集計単位内で何単語目か
                  while(n<path.length){//単語ごとのループ
                      if(path[n].basic_form=="。"||path[n].basic_form=="？"||path[n].basic_form=="?"||path[n].word_id=="2613630"){
                        bunsuu++;
                        toutencount=0;
                        break;//3区間終了
                      }
                      keitaisokaiseki[m][i][k] = path[n].basic_form;
                      reasonMatrix[i][k] = reason;
                      n++;
                      k++;
                  }
                  if(n==path.length){//確認
                    break;
                  }
                  if(path[n].word_id=="2613630"){
                    n++;
                    break;
                  }//1段落作成完了
                  n++;
                  i++;//段落内の何文目か
                }
                m++;
              }

            //以下、想定していた形態素解析後の結果から、共起ネットワークのノード・エッジ作成へ

            console.log(keitaisokaiseki);

            var tangoset = new Set();

            var tmp=new Array;

            for(m=0;m
              <keitaisokaiseki.length;++m){
              for(i=0;i<keitaisokaiseki[m].length;++i){
                tmp = keitaisokaiseki[m][i];
                console.log("m=%d,i=%d",m,i);
                console.log(tmp);
                if(keitaisokaiseki[m][i] ==false||keitaisokaiseki[m][i]==new Array){
                  keitaisokaiseki[m][i].length=0;
                  continue;
                }
                for(j=0;j<tmp.length;++j){
                  tangoset.add({name:keitaisokaiseki[m][i][j],
                                group:reasonMatrix[i][j]

                              });

                  }
                }
            }

          var tangosett = new Array;;

          tangosett = Array.from(tangoset).map(function(t) {
            return {t};
            // body...
          });

            var miserables={"nodes":new Array,"links":new Array};

            for(i=0;i<tangosett.length;i++){
              miserables.nodes[i]=tangosett[i].t;
            }

            console.log(miserables.nodes);
            console.log(miserables.nodes.length);

            /*あとはlinksの作成だけ
            まずはlistをつくる*/
            var list = new Array(keitaisokaiseki.length);
            //list作成

            var RGBlist  = new Array(keitaisokaiseki.length);

            //keitaisokaisekiとnodesを照らしあわせる
            for(m=0;m<keitaisokaiseki.length;++m){
              list[m] = new Array(keitaisokaiseki[m].length);
              RGBlist[m] = new Array(keitaisokaiseki[m].length);
              for(i=0;i<keitaisokaiseki[m].length;++i){
                list[m][i] = new Array(miserables.nodes.length);
                RGBlist[m][i] = new Array(3);
                RGBlist[m][i][0]=0;
                RGBlist[m][i][1]=0;
                RGBlist[m][i][2]=0;
                for(j=0;j<keitaisokaiseki[m][i].length;++j){
                  for(k=0;k<miserables.nodes.length;++k){
                    if(keitaisokaiseki[m][i][j]==miserables.nodes[k].name){
                      list[m][i][k]=1;
                      if(keitaisokaiseki[m][i][j]=="母"){

                        RGBlist[m][i][0]=RGBlist[m][i][0]+1;
                      }
                      if(keitaisokaiseki[m][i][j]=="仕事")
                        RGBlist[m][i][2]=RGBlist[m][i][2]+1;
                      }
                      if(keitaisokaiseki[m][i][j]=="友人"){
                        RGBlist[m][i][1]=RGBlist[m][i][1]+1;
                      }

                    }
                  }

                  console.log(RGBlist[m][i]);
                }
              }

            console.log(list);
            //listはi*k

            //listからmiserables.linksとlist3をつくる

            var x,y,z;

            var edge=-1;

                for(k=0;k<miserables.nodes.length;++k){

                  for(l=k+1;l<miserables.nodes.length;++l){//別の単語を見る
                    //現在単語2個の組み合わせを選択中

                    //ここから段落を指定して縦になめる

                    for(m=0;m<keitaisokaiseki.length;++m){
                      for(i=0;i<keitaisokaiseki[m].length;++i){
                        x=list[m][i][k];
                        y=list[m][i][l];

                        if(x==1 && y==1){

                          miserables.links.push({source:l,target:k,value:0});
                          edge++;//最初のedgeが0
                          break;
                        }
                      }
                    }
                      //とりあえずエッジつくってbreak
                      //こっからvalueを与える
                    for(m=0;m<keitaisokaiseki.length;++m){
                      for(i=0;i<keitaisokaiseki[m].length;++i){
                        x=list[m][i][k];
                        y=list[m][i][l];
                        if(x==1 && y==1){
                          z = miserables.links[edge].value;
                          z++;
                          miserables.links[edge].value = z;
                        }
                      }
                    }

                    }

                  }

                console.log(miserables.links);

            //以上計算中

            var graph = miserables;

//共起マップ
/*
                force
                    .nodes(graph.nodes)
                    .links(graph.links)
                    .start();

*/
/*
                var link = svg.selectAll(".link")
                    .data(graph.links)
                  .enter().append("line")
                    .attr("class", "link")
                    .style("stroke-width", function(d) { return Math.sqrt(d.value); });
*/
/*              var node = svg.selectAll(".node")
                  .data(graph.nodes)
                .enter().append("text")
                  .attr("class", "node")
                  .style("fill", function(d) {
                    if(d.group==1){
                      return "red";
                    } else{
                      return "blue";
                    }

                  })
                  .call(force.drag)
                  .text(function(d) { return d.name; });
*/

/*
                force.on("tick", function() {
                  link.attr("x1", function(d) { return d.source.x; })
                      .attr("y1", function(d) { return d.source.y; })
                      .attr("x2", function(d) { return d.target.x; })
                      .attr("y2", function(d) { return d.target.y; });

                  node.attr("x", function(d) { return d.x; })
                      .attr("y", function(d) { return d.y; });
                });

*/

                });
        };
        reader.readAsText(file);

        /*clustering*/

  });

  var cluster = require('hierarchical-clustering');
  var colors = [
  [20, 20, 80],
  [22, 22, 90],
  [250, 255, 253],
  [100, 54, 255]
  ];

  // Euclidean distance
  function distance(a, b) {
  var d = 0;
  for (var i = 0; i < a.length; i++) {
  d += Math.pow(a[i] - b[i], 2);
  }
  return Math.sqrt(d);
  }

  // Single-linkage clustering
  function linkage(distances) {
  return Math.min.apply(null, distances);
  }

  var levels = cluster({
  input: colors,
  distance: distance,
  linkage: linkage,
  minClusters: 2, // only want two clusters
  });

  var clusters = levels[levels.length - 1].clusters;
  console.log(clusters);
  // => [ [ 2 ], [ 3, 1, 0 ] ]
  clusters = clusters.map(function (cluster) {
  return cluster.map(function (index) {
  return colors[index];
  });
  });
  console.log(clusters);
  // => [ [ [ 250, 255, 253 ] ],
  // => [ [ 100, 54, 255 ], [ 22, 22, 90 ], [ 20, 20, 80 ] ] ]

//ドットで区切る
//単語グループ分け -> 形態素解析時点で。

//クライアントの各文の得点換算
//stackdataArr完成

          var stackdataArr = [
              [{x:1,y:3},{x:2,y:5},{x:3,y:7},{x:4,y:3},{x:5,y:5},{x:6,y:7}],
              [{x:1,y:2},{x:2,y:4},{x:3,y:9},{x:4,y:7},{x:5,y:6},{x:6,y:4}],
              [{x:1,y:1},{x:2,y:8},{x:3,y:5},{x:4,y:3},{x:5,y:5},{x:6,y:7}],
              [{x:1,y:18},{x:2,y:7},{x:3,y:3},{x:4,y:11},{x:5,y:8},{x:6,y:6}]
          ];
          var stack = d3.layout.stack()
              .x(function(d){return 1;})
              .y(function(d){return d.y;})
              .values(function(d){return d;});
          var stackdata = stack(stackdataArr);
          var max = d3.max(stackdata[stackdata.length - 1], function(d){return d.y + d.y0;});
          var scaleX = d3.scale.linear().domain([0,6]).range([0,width/2]);
          var scaleY = d3.scale.linear().domain([0,max]).range([0,200]);
          var colors = ["lightgray","#77ff77","#ff7777","#7777ff","yellow","#0f0","green"];
          var colors2 = ["gray","#d4d","#d4d","gray","#d4d","#d4d","gray"];
          var area = d3.svg.area()
              .x(function(d,i){return i * width/10})
              .y0(function(d){return 200})
              .y1(function(d){return 200 - scaleY(d.y+d.y0)});
          svg.selectAll("path")
              .data(stackdata.reverse())
              .enter()
              .append("path")
              .attr("d", area)
              .attr("fill",function(d,i){return colors[i]});

              //grid line
              //引数はstart,stop,stepの順
              //[190,170,150,130,110,90,70,50,30,10]と同等
            var range = d3.range((width/2)-(width/20),4,-width/10);
            svg.selectAll("line.v")
              .data(range).enter().append("line")
              .attr("x1", function(d,i){return d;}).attr("y1", 0)
              .attr("x2", function(d,i){return d;}).attr("y2", 200);
            svg.selectAll("line")
              .attr("stroke", function(d,i){return colors2[i]})
              .attr("stroke-width", 10)

//チェックボックス

              function boxCheck(){

                //チェックされた項目を記録する変数
                var str="";

                //for文でチェックボックスを１つずつ確認
                for( i=0; i<6; i++ )
                {
                  //チェックされているか確認する
                  if( document.chbox.elements[i].checked )
                  {
                    //変数strが空でない時、区切りのコンマを入れる
                    if( str != "" ) str=str+",";

                    //チェックボックスのvalue値を変数strに入れる
                    str=str+document.chbox.elements[i].value;
                  }
                }

                //strが空の時、警告を出す
                if( str=="" ){
                   alert( "どれか選択してください。" );
                }else{
                  alert( str + "が選択されました。" );
                }
              }
<|endoftext|>


<commit_before>;
(function(mag) {

  "use strict";

  var mod = {
    modules: [],
    promises: [],
    deferreds: [],
    controllers: [],
    elements: []
  }

  mod.getController = function(mod, element, fill) {
    var controller

    // FireFox support only
    if (typeof Proxy !== 'undefined') {
      controller = new Proxy(new mod.controller, {
        get: function(target, prop) {
          if (target[prop] === undefined && ['watchers', 'toJSON', 'called', 'onload', 'onunload'].indexOf(prop) === -1) {
            var a = fill.find(element, prop),
              greedy = prop[0] === '$',
              v, // can be an array, object or string
              // for each
              tmp = []
              a.forEach(function(item, index) {
                if (a[index]) {
                  if (a[index].value && a[index].value.length > 0) {
                    v = a[index].value
                    if (a[index].type && (a[index].type == 'checkbox' || a[index].type == 'radio')) {
                      v = {
                        _text: v,
                        _checked: a[index].checked
                      }
                      tmp.push(v)
                    }
                  } else if (a[index].innerText && a[index].innerText.length > 0) {
                    v = a[index].innerText
                  } else if (a[0].innerHTML && a[index].innerHTML.length > 0) {
                    v = a[index].innerHTML
                  }
                }
              })
              if (tmp.length > 0 && greedy) return tmp
              return v
          }
          return target[prop]
        }
      })
    } else {
      controller = new mod.controller
    }
    return controller
  }

  mod.submodule = function(module, args) {
    var controller = function(args) {
      return (module.controller || function() {}).apply(this, args)
    }.bind({}, args)

    var view = function(ctrl) {
      if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1))
      var template = module.view.apply(module, args ? [ctrl].concat(args) : [ctrl])
      if (args[0] && args[0].key != null) template.attrs.key = args[0].key
      // There's no template return ??
      return template
    }
    controller.$original = module.controller

    var output = {
      controller: controller,
      view: view
    }
    if (args[0] && args[0].key != null) output.attrs = {
      key: args[0].key
    }
    return output
  }

  mod.getArgs = function(i) {
    var args = mod.modules[i].controller && mod.modules[i].controller.$$args ? [mod.controllers[i]].concat(mod.modules[i].controller.$$args) : [mod.controllers[i]]
    return args
  }
  mag.mod = mod

})(window.mag || {})
<commit_msg>Update module.js<commit_after>;
(function(mag) {

  "use strict";

  var mod = {
    modules: [],
    promises:[],
    deferreds:[],
    controllers: [],
    elements: []
  }

  mod.getController = function(mod, element, fill) {
    var controller

    // FireFox support only
    // Removing since we are now native with Object.observe which is only Chrome & Opera
    /*
    if (typeof Proxy !== 'undefined') {
      controller = new Proxy(new mod.controller, {
        get: function(target, prop) {
          if (target[prop] === undefined && ['watchers', 'toJSON', 'called', 'onload', 'onunload'].indexOf(prop) === -1) {
            var a = fill.find(element, prop),
              greedy = prop[0] === '$',
            v, // can be an array, object or string
            // for each
            tmp = []
            a.forEach(function(item, index) {
              if (a[index]) {
                if (a[index].value && a[index].value.length > 0) {
                  v = a[index].value
                  if (a[index].type && (a[index].type == 'checkbox' || a[index].type == 'radio')) {
                    v = {
                      _text: v,
                      _checked: a[index].checked
                    }
                    tmp.push(v)
                  }
                } else if (a[index].innerText && a[index].innerText.length > 0) {
                  v = a[index].innerText
                } else if (a[0].innerHTML && a[index].innerHTML.length > 0) {
                  v = a[index].innerHTML
                }
              }
            })
            if (tmp.length > 0 && greedy) return tmp
            return v
          }
          return target[prop]
        }
      })
    } else {
      controller = new mod.controller
    }
    */
    controller = new mod.controller
    return controller
  }

  mod.submodule = function(module, args) {
    var controller = function(args) {
      return (module.controller || function() {}).apply(this, args)
    }.bind({}, args)

    var view = function(ctrl) {
      if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1))
      var template = module.view.apply(module, args ? [ctrl].concat(args) : [ctrl])
      if (args[0] && args[0].key != null) template.attrs.key = args[0].key
      // There's no template return ??
      return template
    }
    controller.$original = module.controller

    var output = {
      controller: controller,
      view: view
    }
    if (args[0] && args[0].key != null) output.attrs = {
      key: args[0].key
    }
    return output
  }

  mod.getArgs = function(i) {
    var args = mod.modules[i].controller && mod.modules[i].controller.$$args ? [mod.controllers[i]].concat(mod.modules[i].controller.$$args) : [mod.controllers[i]]
    return args
  }
  mag.mod = mod

})(window.mag || {})
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var util = require('util'),
  _ = require('lodash'),
  fs = require('fs'),
  path = require('path');

// Make _.defaults recursive
_.defaults = require('merge-defaults');
_.str = require('underscore.string');

// Fetch stub attribute template on initial load.
var ATTRIBUTE_TEMPLATE = path.resolve(__dirname, '../templates/attribute.template');
ATTRIBUTE_TEMPLATE = fs.readFileSync(ATTRIBUTE_TEMPLATE, 'utf8');

/**
 * This `before` function is run before generating targets.
 * Validate, configure defaults, get extra dependencies, etc.
 *
 * @param  {Object} scope
 * @param  {Function} cb    [callback]
 */

module.exports = function(scope, cb) {

  // scope.args are the raw command line arguments.
  //
  // e.g. if you run:
  // sails generate controlller user find create update
  // then:
  // scope.args = ['user', 'find', 'create', 'update']
  //
  _.defaults(scope, {
    id: _.str.capitalize(scope.args[0]),
    attributes: scope.args.slice(1)
  });

  if (!scope.rootPath) {
    return cb.invalid('Usage: sails generate model <modelname> [attribute|attribute:type ...]');
  }
  if (!scope.id) {
    return cb.invalid('Usage: sails generate model <modelname> [attribute|attribute:type ...]');
  }

  // Validate optional attribute arguments
  var attributes = scope.attributes;
  var invalidAttributes = [];
  attributes = _.map(attributes, function(attribute, i) {

    var parts = attribute.split(':');

    if (parts[1] === undefined) parts[1] = 'string';

    // Handle invalidAttributes
    if (!parts[1] || !parts[0]) {
      invalidAttributes.push(
        'Invalid attribute notation:   "' + attribute + '"');
      return;
    }
    return {
      name: parts[0],
      type: parts[1]
    };

  });

  // Handle invalid action arguments
  // Send back invalidActions
  if (invalidAttributes.length) {
    return cb.invalid(invalidAttributes);
  }

  // Make sure there aren't duplicates
  if ((_.uniq(attributes)).length !== attributes.length) {
    return cb.invalid('Duplicate attributes not allowed!');
  }

  //
  // Determine default values based on the
  // available scope.
  //
  _.defaults(scope, {
    globalID: _.str.capitalize(scope.id),
    ext: (scope.coffee) ? '.coffee' : '.js',
    attributes: []
  });

  // Take another pass to take advantage of
  // the defaults absorbed in previous passes.
  _.defaults(scope, {
    rootPath: scope.rootPath,
    filename: scope.globalID + scope.ext,
    lang: scope.coffee ? 'coffee' : 'js',
    destDir: 'api/models/'
  });

  //
  // Transforms
  //

  // Render some stringified code from the action template
  // and make it available in our scope for use later on.
  scope.attributes = _.map(attributes, function(attribute) {

    return _.str.rtrim(
      _.unescape(
        _.template(ATTRIBUTE_TEMPLATE, {
          name: attribute.name,
          type: attribute.type,
          lang: scope.coffee ? 'coffee' : 'js'
        })
      )
    );
  }).join((scope.coffee) ? '\n' : ',\n');

  // Trigger callback with no error to proceed.
  return cb.success();
};<commit_msg>Update before.js<commit_after>/**
 * Module dependencies
 */

var util = require('util'),
  _ = require('lodash'),
  fs = require('fs'),
  path = require('path');

// Make _.defaults recursive
_.defaults = require('merge-defaults');
_.str = require('underscore.string');

// Fetch stub attribute template on initial load.
var ATTRIBUTE_TEMPLATE = path.resolve(__dirname, '../templates/attribute.template');
ATTRIBUTE_TEMPLATE = fs.readFileSync(ATTRIBUTE_TEMPLATE, 'utf8');

/**
 * This `before` function is run before generating targets.
 * Validate, configure defaults, get extra dependencies, etc.
 *
 * @param  {Object} scope
 * @param  {Function} cb    [callback]
 */

module.exports = function(scope, cb) {

  // scope.args are the raw command line arguments.
  //
  // e.g. if you run:
  // sails generate controlller user find create update
  // then:
  // scope.args = ['user', 'find', 'create', 'update']
  //
  _.defaults(scope, {
    id: _.str.capitalize(scope.args[0]),
    attributes: scope.args.slice(1)
  });

  if (!scope.rootPath) {
    return cb.invalid('Usage: sails generate model <modelname> [attribute|attribute:type ...]');
  }
  if (!scope.id) {
    return cb.invalid('Usage: sails generate model <modelname> [attribute|attribute:type ...]');
  }

  // Validate optional attribute arguments
  var attributes = scope.attributes;
  var invalidAttributes = [];
  attributes = _.map(attributes, function(attribute, i) {

    var parts = attribute.split(':');

    if (parts[1] === undefined) parts[1] = 'string';

    // Handle invalidAttributes
    if (!parts[1] || !parts[0]) {
      invalidAttributes.push(
        'Invalid attribute notation:   "' + attribute + '"');
      return;
    }
    return {
      name: parts[0],
      type: parts[1]
    };

  });

  // Handle invalid action arguments
  // Send back invalidActions
  if (invalidAttributes.length) {
    return cb.invalid(invalidAttributes);
  }

  // Make sure there aren't duplicates
  if (_(attributes).pluck('name').uniq().valueOf().length !== attributes.length) {
    return cb.invalid('Duplicate attributes not allowed!');
  }

  //
  // Determine default values based on the
  // available scope.
  //
  _.defaults(scope, {
    globalID: _.str.capitalize(scope.id),
    ext: (scope.coffee) ? '.coffee' : '.js',
    attributes: []
  });

  // Take another pass to take advantage of
  // the defaults absorbed in previous passes.
  _.defaults(scope, {
    rootPath: scope.rootPath,
    filename: scope.globalID + scope.ext,
    lang: scope.coffee ? 'coffee' : 'js',
    destDir: 'api/models/'
  });

  //
  // Transforms
  //

  // Render some stringified code from the action template
  // and make it available in our scope for use later on.
  scope.attributes = _.map(attributes, function(attribute) {

    return _.str.rtrim(
      _.unescape(
        _.template(ATTRIBUTE_TEMPLATE, {
          name: attribute.name,
          type: attribute.type,
          lang: scope.coffee ? 'coffee' : 'js'
        })
      )
    );
  }).join((scope.coffee) ? '\n' : ',\n');

  // Trigger callback with no error to proceed.
  return cb.success();
};
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import App from './components/App';
import SignIn from './components/SignIn';
import SignUp from './components/SignUp';

ReactDOM.render( <Router path='/' history={browserHistory}>

    </Router> , document.getElementById('root'));<commit_msg>"[GIT AUTO COMMIT]: Mon Jun 26 2017 19:26:52 GMT+0530 (India Standard Time)"<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import App from './components/App';
import SignIn from './components/SignIn';
import SignUp from './components/SignUp';

ReactDOM.render( <Router path='/' history={browserHistory}>
    <Route path='/app' component={App} />
    <Route path='/signin' component={SignIn} />
    <Route path='/signup' component={SignUp} />
    </Router> , document.getElementById('root'));<|endoftext|>


<commit_before>'use strict';

var polyfills = require('famous-polyfills');
var rAF = polyfills.requestAnimationFrame;

var _now;
if (typeof performance !== 'undefined') {
    _now = function() {
        return performance.now();
    };
}
else {
    _now = Date.now;
}

if (typeof document !== 'undefined') {
    var VENDOR_HIDDEN, VENDOR_VISIBILITY_CHANGE;

    if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
        VENDOR_HIDDEN = 'hidden';
        VENDOR_VISIBILITY_CHANGE = 'visibilitychange';
    }
    else if (typeof document.mozHidden !== 'undefined') {
        VENDOR_HIDDEN = 'mozHidden';
        VENDOR_VISIBILITY_CHANGE = 'mozvisibilitychange';
    }
    else if (typeof document.msHidden !== 'undefined') {
        VENDOR_HIDDEN = 'msHidden';
        VENDOR_VISIBILITY_CHANGE = 'msvisibilitychange';
    }
    else if (typeof document.webkitHidden !== 'undefined') {
        VENDOR_HIDDEN = 'webkitHidden';
        VENDOR_VISIBILITY_CHANGE = 'webkitvisibilitychange';
    }
}

function Engine() {
    this._updates = [];
    var _this = this;
    this.looper = function(time) {
        _this.loop(time);
    };
    this._stoppedAt = _now();
    this._sleep = 0;
    this._startOnVisibilityChange = true;
    this.start();
    rAF(this.looper);

    if (typeof document !== 'undefined') {
        var _this = this;
        document.addEventListener(VENDOR_VISIBILITY_CHANGE, function() {
            if (document[VENDOR_HIDDEN]) {
                var startOnVisibilityChange = _this._startOnVisibilityChange;
                _this.stop();
                _this._startOnVisibilityChange = startOnVisibilityChange;
            }
            else {
                if (_this._startOnVisibilityChange) {
                    _this.start();
                }
            }
        });
    }
}

Engine.prototype.start = function start() {
    this._startOnVisibilityChange = true;
    this._running = true;
    this._sleep += _now() - this._stoppedAt;
    return this;
};

Engine.prototype.stop = function stop() {
    this._startOnVisibilityChange = false;
    this._running = false;
    this._stoppedAt = _now();
    return this;
};

Engine.prototype.isRunning = function isRunning() {
    return this._running;
};

Engine.prototype.step = function step (time) {
    for (var i = 0, len = this._updates.length ; i < len ; i++) {
        this._updates[i].update(time);
    }
    return this;
};

Engine.prototype.loop = function loop(time) {
    this.step(time - this._sleep);
    if (this._running) {
        rAF(this.looper);
    }
    return this;
};

Engine.prototype.update = function update(item) {
    if (this._updates.indexOf(item) === -1) this._updates.push(item);
    return this;
};

Engine.prototype.noLongerUpdate = function noLongerUpdate(item) {
    var index = this._updates.indexOf(item);
    if (index > -1) {
        this._updates.splice(index, 1);
    }
    return this;
};

module.exports = Engine;
<commit_msg>docs: Document Engine<commit_after>'use strict';

var polyfills = require('famous-polyfills');
var rAF = polyfills.requestAnimationFrame;

var _now;
if (typeof performance !== 'undefined') {
    _now = function() {
        return performance.now();
    };
}
else {
    _now = Date.now;
}

if (typeof document !== 'undefined') {
    var VENDOR_HIDDEN, VENDOR_VISIBILITY_CHANGE;

    // Opera 12.10 and Firefox 18 and later support
    if (typeof document.hidden !== 'undefined') {
        VENDOR_HIDDEN = 'hidden';
        VENDOR_VISIBILITY_CHANGE = 'visibilitychange';
    }
    else if (typeof document.mozHidden !== 'undefined') {
        VENDOR_HIDDEN = 'mozHidden';
        VENDOR_VISIBILITY_CHANGE = 'mozvisibilitychange';
    }
    else if (typeof document.msHidden !== 'undefined') {
        VENDOR_HIDDEN = 'msHidden';
        VENDOR_VISIBILITY_CHANGE = 'msvisibilitychange';
    }
    else if (typeof document.webkitHidden !== 'undefined') {
        VENDOR_HIDDEN = 'webkitHidden';
        VENDOR_VISIBILITY_CHANGE = 'webkitvisibilitychange';
    }
}

/**
 * Engine class used for updating objects on a frame-by-frame. Synchronizes the
 * `update` method invocations to the refresh rate of the screen. Manages
 * the `requestAnimationFrame`-loop by normalizing the passed in timestamp
 * when switching tabs.
 *
 * @class Engine
 * @constructor
 */
function Engine() {
    this._updates = [];
    var _this = this;
    this.looper = function(time) {
        _this.loop(time);
    };
    this._stoppedAt = _now();
    this._sleep = 0;
    this._startOnVisibilityChange = true;
    this.start();
    rAF(this.looper);

    if (typeof document !== 'undefined') {
        document.addEventListener(VENDOR_VISIBILITY_CHANGE, function() {
            if (document[VENDOR_HIDDEN]) {
                var startOnVisibilityChange = _this._startOnVisibilityChange;
                _this.stop();
                _this._startOnVisibilityChange = startOnVisibilityChange;
            }
            else {
                if (_this._startOnVisibilityChange) {
                    _this.start();
                }
            }
        });
    }
}

/**
 * Starts the Engine.
 *
 * @method start
 * @chainable
 *
 * @return {Engine} this
 */
Engine.prototype.start = function start() {
    this._startOnVisibilityChange = true;
    this._running = true;
    this._sleep += _now() - this._stoppedAt;
    return this;
};

/**
 * Stops the Engine.
 *
 * @method stop
 * @chainable
 *
 * @return {Engine} this
 */
Engine.prototype.stop = function stop() {
    this._startOnVisibilityChange = false;
    this._running = false;
    this._stoppedAt = _now();
    return this;
};

/**
 * Determines whether the Engine is currently running or not.
 *
 * @method isRunning
 *
 * @return {Boolean}    boolean value indicating whether the Engine is
 *                      currently running or not
 */
Engine.prototype.isRunning = function isRunning() {
    return this._running;
};

/**
 * Updates all registered objects.
 *
 * @method step
 * @chainable
 *
 * @param  {Number} time high resolution timstamp used for invoking the
 *                       `update` method on all registered objects
 * @return {Engine}      this
 */
Engine.prototype.step = function step (time) {
    for (var i = 0, len = this._updates.length ; i < len ; i++) {
        this._updates[i].update(time);
    }
    return this;
};

/**
 * Method being called by `requestAnimationFrame` on every paint. Indirectly
 * recursive by scheduling a future invocation of itself on the next paint.
 *
 * @method loop
 * @chainable
 *
 * @param  {Number} time high resolution timstamp used for invoking the
 *                       `update` method on all registered objects
 * @return {Engine}      this
 */
Engine.prototype.loop = function loop(time) {
    this.step(time - this._sleep);
    if (this._running) {
        rAF(this.looper);
    }
    return this;
};

/**
 * Registeres an updateable object which `update` method should be invoked on
 * every paint, starting on the next paint (assuming the Engine is running).
 *
 * @method update
 * @chainable
 *
 * @param  {Object} updateable          object to be updated
 * @param  {Function} updateable.update update function to be called on the
 *                                      registered object
 * @return {Engine}                     this
 */
Engine.prototype.update = function update(updateable) {
    if (this._updates.indexOf(updateable) === -1) {
        this._updates.push(updateable);
    }
    return this;
};

/**
 * Deregisters an updateable object previously registered using `update` to be
 * no longer updated.
 *
 * @method noLongerUpdate
 * @chainable
 *
 * @param  {Object} updateable          updateable object previously
 *                                      registered using `update`
 * @return {Engine}                     this
 */
Engine.prototype.noLongerUpdate = function noLongerUpdate(updateable) {
    var index = this._updates.indexOf(updateable);
    if (index > -1) {
        this._updates.splice(index, 1);
    }
    return this;
};

module.exports = Engine;
<|endoftext|>


<commit_before>'use strict';

const enums = require('./constants');

// const net = require('net');
// const semver = require('semver');
const debug = require('debug')('busy:bridge');

const Message = require('./message.js');
const noop = require('./noop');
const extend = require('gextend');
const Keypath = require('gkeypath');

const utils = require('./utils');

const DEFAULTS = {
    host: '127.0.0.1',
    port: enums.DEFAULT_PORT
};

class Bridge {

    constructor(config = {}, cb = noop) {

        if (utils._isNumber(config)) {
            config = { port: config };
        }

        if (utils._isFunction(config)) {
            cb = config;
            config = {};
        }

        /*
         * In theory, if we have path, port,
         * and host the path should take
         * precedence. Not happening, tho.
         */
        if (!config.path) {
            config = extend({}, {
                host: '127.0.0.1',
                port: enums.DEFAULT_PORT
            }, config);
        }

        this._config = config;

        this._sockets = new Map();

        this._server = require('./transport').createServer(this._onConnection.bind(this));
        this._server.once('error', cb);
        this._server.once('listening', cb);
        this._server.listen(config);
    }

    /**
     * This function will close the connection
     * with a last message.
     * @param  {Array} closeData
     * @return {void}
     */
    close(closeData) {

        const msg = new Message(enums.CLOSE, utils._isArray(closeData) ? closeData : []);

        for (let nodeName in this._sockets.keys()) {
            this._sendToNode(nodeName, msg);
        }

        this._server.close();
    }

    _onConnection(socket) {
        debug('new node (%s:%s)', socket.remoteAddress, socket.remotePort);
        socket.setEncoding('utf8');
        socket.setTimeout(0);
        socket.on('data', this._onData.bind(this, socket));
        socket.on('error', this._cleanUpSocketConnection.bind(this, socket));
    }

    _onData(socket, rawData) {
        const self = this;

        try {
            const events = rawData.split(enums.EOL);
            debug('raw data is: %s. Events: %s', rawData, events.length);

            events.forEach(event => {
                //Char LF, code 10 is a line feed
                if (!event || event.charCodeAt(0) === 10) {
                    return;
                }

                debug('node --> bridge: %s', event);

                const message = Message.fromString(event);

                switch (message.method) {
                    case enums.PING:
                        self._onPingMessage(socket, message);
                        break;
                    case enums.IDENT:
                        self._onIdentityMessage(socket, message);
                        break;
                    case enums.TELL:
                        self._onTellMessage(socket, message);
                        break;
                    case enums.SHOUT:
                        self._onShoutMessage(socket, message);
                        break;
                    case enums.ACK:
                        self._onACKMessage(socket, message);
                        break;
                    case enums.LEAVE:
                        self._onLeaveMessage(socket, message);
                        break;
                    default:
                        debug('received unrecognized command: %s', message.method);
                }
            });
        } catch (e) {
            debug('error: %s', e.message)
            return debug('bridge received invalid data, ignoring...');
        }
    }

    /**********************************************************
     * Command Handlers
     ***********************************************************/

    /**
     * We handle a simple ping/pong pattern
     * between nodes.
     *
     * @param {Socket} socket Node instance to write to
     * @param {Message} message Message to serialzie and wire
     */
    _onPingMessage(socket, message) {
        this._writeToSocket(socket, 'pong');
    }

    /**
     * A new node is registering with the group.
     * It might be that a node is reconnecting but
     * we have not removed it before, in that
     * case we reconnect.
     *
     * @param {Socket} socket Node instance to write to
     * @param {Message} message Message to serialzie and wire
     */
    _onIdentityMessage(socket, message) {
        if (this._sockets.has(message.nodeName)) {
            //TODO: Check if we are reconnecting, and if so then swap.
            debug('duplicate node name: %s', message.nodeName);
            this._writeToSocket(socket, new Message(enums.ACK, [message.id, ['duplicate-node']]));
        } else {
            socket.nodeName = message.nodeName;
            this._sockets.set(message.nodeName, socket);

            //This won't be called sometimes, we need better handling
            socket.on('close', this._cleanUpSocketConnection.bind(this, socket));

            debug('sending ACK (id: %s)', message.id);

            this._sendToNode(message.nodeName, new Message(enums.ACK, [message.id, [null]]));
        }
    }

    /**
     * This acts as a broadcast, we send the message to
     * all nodes in the network.
     *
     * @param {Socket} socket Node instance to write to
     * @param {Message} message Message to serialzie and wire
     */
    _onShoutMessage(socket, message) {
        const msg = new Message(enums.SHOUT, message.data);

        for (let nodeName in this._sockets.keys()) {
            if (nodeName === message.nodeName) {
                continue;
            }
            this._sendToNode(nodeName, msg);
        }
    }

    _onACKMessage(socket, message) {
        const [to, cbid, params] = message.data;
        this._sendToNode(to, new Message(enums.ACK, [cbid, params]));
    }

    _onTellMessage(socket, message) {
        const [nodeName, nodeEvent, params] = message.data;

        if (!this._sockets.has(nodeName)) {
            debug('attempting to "tell" a non-existent node: %s', nodeName);
            this._sendToNode(message.nodeName, new Message(enums.ACK, [message.id, ['unknown-node']]));
        } else {
            this._sendToNode(nodeName, new Message(enums.TELL, [message.nodeName, message.id, nodeEvent, params]));
        }
    }

    _onLeaveMessage(socket, message) {
        this._writeToSocket(socket, new Message(enums.ACK, [message.id, []]));
        this._cleanUpSocketConnection(socket);
    }

    /**********************************************************
     * Write and Socket Management Functions
     ***********************************************************/

    _sendToNode(name, what) {
        if (this._sockets.has(name)) {
            this._writeToSocket(this._sockets.get(name), what);
        } else {
            debug('tried to write to an unregistered socket');
        }
    }

    _writeToSocket(socket, what) {
        try {
            socket.write(what.toString());
        } catch (e) {
            debug('tried to write to dead socket');
            this._cleanUpSocketConnection(socket);
        }
    }

    _cleanUpSocketConnection(socket) {
        const name = this.getSocketName(socket);
        if (name) {
            this._sockets.delete(name);
            debug('Node "%s" has left. Cleaning up...', name);
        }
        socket.removeAllListeners();
    }

    getSocketName(socket) {
        for (let name in this._sockets.keys()) {
            if (socket === this._sockets.get(name)) {
                return name;
            }
        }
        return null;
    }
}

module.exports = Bridge;<commit_msg>update publish methods<commit_after>'use strict';

const enums = require('./constants');

// const net = require('net');
// const semver = require('semver');
const debug = require('debug')('busy:bridge');

const Message = require('./message.js');
const noop = require('./noop');
const extend = require('gextend');
const Keypath = require('gkeypath');

const utils = require('./utils');

const DEFAULTS = {
    host: '127.0.0.1',
    port: enums.DEFAULT_PORT
};

class Bridge {

    constructor(config = {}, cb = noop) {

        if (utils._isNumber(config)) {
            config = { port: config };
        }

        if (utils._isFunction(config)) {
            cb = config;
            config = {};
        }

        /*
         * In theory, if we have path, port,
         * and host the path should take
         * precedence. Not happening, tho.
         */
        if (!config.path) {
            config = extend({}, {
                host: '127.0.0.1',
                port: enums.DEFAULT_PORT
            }, config);
        }

        this._config = config;

        this._sockets = new Map();

        this._server = require('./transport').createServer(this._onConnection.bind(this));
        this._server.once('error', cb);
        this._server.once('listening', cb);
        this._server.listen(config);
    }

    /**
     * This function will close the connection
     * with a last message.
     * @param  {Array} closeData
     * @return {void}
     */
    close(closeData) {

        const msg = new Message(enums.CLOSE, utils._isArray(closeData) ? closeData : []);

        for (let nodeName in this._sockets.keys()) {
            this._sendToNode(nodeName, msg);
        }

        this._server.close();
    }

    _onConnection(socket) {
        debug('new node (%s:%s)', socket.remoteAddress, socket.remotePort);
        socket.setEncoding('utf8');
        socket.setTimeout(0);
        socket.on('data', this._onData.bind(this, socket));
        socket.on('error', this._cleanUpSocketConnection.bind(this, socket));
    }

    _onData(socket, rawData) {
        const self = this;

        try {
            const events = rawData.split(enums.EOL);
            debug('raw data is: %s. Events: %s', rawData, events.length);

            events.forEach(event => {
                //Char LF, code 10 is a line feed
                if (!event || event.charCodeAt(0) === 10) {
                    return;
                }

                debug('node --> bridge: %s', event);

                const message = Message.fromString(event);

                switch (message.method) {
                    case enums.PING:
                        self._onPingMessage(socket, message);
                        break;
                    case enums.IDENT:
                        self._onIdentityMessage(socket, message);
                        break;
                    case enums.TELL:
                        self._onTellMessage(socket, message);
                        break;
                    case enums.SHOUT:
                        self._onShoutMessage(socket, message);
                        break;
                    case enums.ACK:
                        self._onACKMessage(socket, message);
                        break;
                    case enums.LEAVE:
                        self._onLeaveMessage(socket, message);
                        break;
                    default:
                        debug('received unrecognized command: %s', message.method);
                }
            });
        } catch (e) {
            debug('error: %s', e.message)
            return debug('bridge received invalid data, ignoring...');
        }
    }

    /**********************************************************
     * Command Handlers
     ***********************************************************/

    /**
     * We handle a simple ping/pong pattern
     * between nodes.
     *
     * @param {Socket} socket Node instance to write to
     * @param {Message} message Message to serialzie and wire
     */
    _onPingMessage(socket, message) {
        this._writeToSocket(socket, 'pong');
    }

    /**
     * A new node is registering with the group.
     * It might be that a node is reconnecting but
     * we have not removed it before, in that
     * case we reconnect.
     *
     * @param {Socket} socket Node instance to write to
     * @param {Message} message Message to serialzie and wire
     */
    _onIdentityMessage(socket, message) {
        if (this._sockets.has(message.nodeName)) {
            //TODO: Check if we are reconnecting, and if so then swap.
            debug('duplicate node name: %s', message.nodeName);
            this._writeToSocket(socket, new Message(enums.ACK, [message.id, ['duplicate-node']]));
        } else {
            socket.nodeName = message.nodeName;
            this._sockets.set(message.nodeName, socket);

            //This won't be called sometimes, we need better handling
            socket.on('close', this._cleanUpSocketConnection.bind(this, socket));

            debug('sending ACK (id: %s)', message.id);

            this._sendToNode(message.nodeName, new Message(enums.ACK, [message.id, [null]]));
        }
    }

    /**
     * This acts as a broadcast, we send the message to
     * all nodes in the network.
     *
     * @param {Socket} socket Node instance to write to
     * @param {Message} message Message to serialzie and wire
     */
    _onShoutMessage(socket, message) {
        const msg = new Message(enums.SHOUT, message.data);

        for (let nodeName in this._sockets.keys()) {
            if (nodeName === message.nodeName) {
                continue;
            }
            this._sendToNode(nodeName, msg);
        }
    }

    _onACKMessage(socket, message) {
        const [to, cbid, params] = message.data;
        this._sendToNode(to, new Message(enums.ACK, [cbid, params]));
    }

    _onTellMessage(socket, message) {
        const [nodeName, nodeEvent, params] = message.data;

        if (!this._sockets.has(nodeName)) {
            debug('attempting to "publish" a non-existent node: %s', nodeName);
            this._sendToNode(message.nodeName, new Message(enums.ACK, [message.id, ['unknown-node']]));
        } else {
            this._sendToNode(nodeName, new Message(enums.TELL, [message.nodeName, message.id, nodeEvent, params]));
        }
    }

    _onLeaveMessage(socket, message) {
        this._writeToSocket(socket, new Message(enums.ACK, [message.id, []]));
        this._cleanUpSocketConnection(socket);
    }

    /**********************************************************
     * Write and Socket Management Functions
     ***********************************************************/

    _sendToNode(name, what) {
        if (this._sockets.has(name)) {
            this._writeToSocket(this._sockets.get(name), what);
        } else {
            debug('tried to write to an unregistered socket');
        }
    }

    _writeToSocket(socket, what) {
        try {
            socket.write(what.toString());
        } catch (e) {
            debug('tried to write to dead socket');
            this._cleanUpSocketConnection(socket);
        }
    }

    _cleanUpSocketConnection(socket) {
        const name = this.getSocketName(socket);
        if (name) {
            this._sockets.delete(name);
            debug('Node "%s" has left. Cleaning up...', name);
        }
        socket.removeAllListeners();
    }

    getSocketName(socket) {
        for (let name in this._sockets.keys()) {
            if (socket === this._sockets.get(name)) {
                return name;
            }
        }
        return null;
    }
}

module.exports = Bridge;<|endoftext|>


<commit_before>import _ from 'lodash'
import request from 'request-promise'
import fs from 'fs'

const BASE_SENTRY_URL = 'https://sentry.io/api/0/projects'

const DEFAULT_TRANSFORM = (filename) => filename

module.exports = class SentryPlugin {
	constructor(options) {
		this.baseSentryURL = options.baseSentryURL || BASE_SENTRY_URL
		this.organisationSlug = options.organisation
		this.projectSlug = options.project
		this.apiKey = options.apiKey

		this.releaseVersion = options.release;

		this.include = options.include
		this.exclude = options.exclude

		this.filenameTransform = options.filenameTransform || DEFAULT_TRANSFORM
		this.suppressErrors = options.suppressErrors
	}

	apply(compiler) {
		compiler.plugin('after-emit', (compilation, cb) => {
			const errors = this.ensureRequiredOptions()

			if (errors) {
				return this.handleErrors(errors, compilation, cb)
			}

			const files = this.getFiles(compilation)

			if (_.isFunction(this.releaseVersion)) {
				this.releaseVersion(compilation.hash)
			}

			return this.createRelease()
				.then(() => this.uploadFiles(files))
				.then(() => cb())
				.catch((err) => this.handleErrors(err, compilation, cb))
		})
	}

	handleErrors(err, compilation, cb) {
		const errorMsg = `Sentry Plugin: ${err}`
		if (this.suppressErrors) {
			compilation.warnings.push(errorMsg)
		}
		else {
			compilation.errors.push(errorMsg)
		}

		cb()
	}

	ensureRequiredOptions() {
		if (!this.organisationSlug) {
			return new Error('Must provide organisation')
		}
		else if (!this.projectSlug) {
			return new Error(('Must provide project'))
		}
		else if (!this.apiKey) {
			return new Error('Must provide api key')
		}
		else if (!this.releaseVersion) {
			return new Error('Must provide release version')
		}
		else {
			return null
		}
	}

	getFiles(compilation) {
		return _.reduce(compilation.assets, (acc, asset, name) => {
			return this.isIncludeOrExclude(name)
				? acc.concat({ name, path: asset.existsAt })
				: acc
		}, [])
	}

	isIncludeOrExclude(filename) {
		const isIncluded = this.include ? this.include.test(filename) : true
		const isExcluded = this.exclude ? this.exclude.test(filename) : false

		return isIncluded && !isExcluded
	}

	createRelease() {
		return request({
			url: `${this.sentryReleaseUrl()}/`,
			method: 'POST',
			auth: {
				bearer: this.apiKey
			},
			headers: {
				'Content-Type': 'application/json'
			},
			body: JSON.stringify({ version: this.releaseVersion })
		})
	}

	uploadFiles(files) {
		return Promise.all(files.map(this.uploadFile.bind(this)))
	}

	uploadFile({ path, name }) {
		return request({
			url: `${this.sentryReleaseUrl()}/${this.releaseVersion}/files/`,
			method: 'POST',
			auth: {
				bearer: this.apiKey
			},
			formData: {
				file: fs.createReadStream(path),
				name: this.filenameTransform(name)
			}
		})
	}

	sentryReleaseUrl() {
		return `${this.baseSentryURL}/${this.organisationSlug}/${this.projectSlug}/releases`
	}
}
<commit_msg>Fix release version fn not reassinging to version variable<commit_after>import _ from 'lodash'
import request from 'request-promise'
import fs from 'fs'

const BASE_SENTRY_URL = 'https://sentry.io/api/0/projects'

const DEFAULT_TRANSFORM = (filename) => filename

module.exports = class SentryPlugin {
	constructor(options) {
		this.baseSentryURL = options.baseSentryURL || BASE_SENTRY_URL
		this.organisationSlug = options.organisation
		this.projectSlug = options.project
		this.apiKey = options.apiKey

		this.releaseVersion = options.release;

		this.include = options.include
		this.exclude = options.exclude

		this.filenameTransform = options.filenameTransform || DEFAULT_TRANSFORM
		this.suppressErrors = options.suppressErrors
	}

	apply(compiler) {
		compiler.plugin('after-emit', (compilation, cb) => {
			const errors = this.ensureRequiredOptions()

			if (errors) {
				return this.handleErrors(errors, compilation, cb)
			}

			const files = this.getFiles(compilation)

			if (_.isFunction(this.releaseVersion)) {
				this.releaseVersion = this.releaseVersion(compilation.hash)
			}

			return this.createRelease()
				.then(() => this.uploadFiles(files))
				.then(() => cb())
				.catch((err) => this.handleErrors(err, compilation, cb))
		})
	}

	handleErrors(err, compilation, cb) {
		const errorMsg = `Sentry Plugin: ${err}`
		if (this.suppressErrors) {
			compilation.warnings.push(errorMsg)
		}
		else {
			compilation.errors.push(errorMsg)
		}

		cb()
	}

	ensureRequiredOptions() {
		if (!this.organisationSlug) {
			return new Error('Must provide organisation')
		}
		else if (!this.projectSlug) {
			return new Error(('Must provide project'))
		}
		else if (!this.apiKey) {
			return new Error('Must provide api key')
		}
		else if (!this.releaseVersion) {
			return new Error('Must provide release version')
		}
		else {
			return null
		}
	}

	getFiles(compilation) {
		return _.reduce(compilation.assets, (acc, asset, name) => {
			return this.isIncludeOrExclude(name)
				? acc.concat({ name, path: asset.existsAt })
				: acc
		}, [])
	}

	isIncludeOrExclude(filename) {
		const isIncluded = this.include ? this.include.test(filename) : true
		const isExcluded = this.exclude ? this.exclude.test(filename) : false

		return isIncluded && !isExcluded
	}

	createRelease() {
		return request({
			url: `${this.sentryReleaseUrl()}/`,
			method: 'POST',
			auth: {
				bearer: this.apiKey
			},
			headers: {
				'Content-Type': 'application/json'
			},
			body: JSON.stringify({ version: this.releaseVersion })
		})
	}

	uploadFiles(files) {
		return Promise.all(files.map(this.uploadFile.bind(this)))
	}

	uploadFile({ path, name }) {
		return request({
			url: `${this.sentryReleaseUrl()}/${this.releaseVersion}/files/`,
			method: 'POST',
			auth: {
				bearer: this.apiKey
			},
			formData: {
				file: fs.createReadStream(path),
				name: this.filenameTransform(name)
			}
		})
	}

	sentryReleaseUrl() {
		return `${this.baseSentryURL}/${this.organisationSlug}/${this.projectSlug}/releases`
	}
}
<|endoftext|>