<commit_before>import {Loader} from '../src/index';

describe("the abstract loader", () => {

  it("should throw when calling the create default", () => {
    expect(Loader.createDefaultLoader).toThrow();
  });

  describe("instance", () => {
    var loader;

    beforeEach(() => loader = new Loader());

    describe("abstract method", () => {
      it('loadModule() should throw when called', () => {
        expect(loader.loadModule).toThrow();
      });

      it('loadAllModules() should throw when called', () => {
        expect(loader.loadAllModules).toThrow();
      });

      it('loadTemplate() should throw when called', () => {
        expect(loader.loadTemplate).toThrow();
      });
    });

    describe("implemented method", () => {

      afterEach(() => {
        var link = document.head.querySelector('link[rel="import"]');
        document.head.removeChild(link);
      });

      it("importDocument() should load a document fragment for a url", (done) => {
        loader.importDocument('base/test/fixtures/plainHtml.html')
          .then((imported) => expect(imported).toBeDefined())
          .catch((reason) => expect(false).toBeTruthy(reason))
          .then(done);
      });

      it("importTemplate() should extract a template", (done) => {
        loader.importTemplate('base/test/fixtures/template.html')
        .then((template) => expect(template.innerHTML).toBe("
This is the template
"))
        .catch((error) => expect(false).toBeTruthy(error))
        .then(done);
      });

      it("importTemplate() should fail if there is no template tag", (done) => {
        loader.importTemplate('base/test/fixtures/plainHtml.html')
          .then((template) => expect(false).toBeTruthy("This should have failed"))
          .catch((error) => expect(error).toBeDefined(error))
          .then(done);
      });
    });
  });
});
<commit_msg>test(all): fix broken tests after last design work<commit_after>import {Loader} from '../src/index';

describe("the abstract loader", () => {

  describe("instance", () => {
    var loader;

    beforeEach(() => loader = new Loader());

    describe("abstract method", () => {
      it('loadModule() should throw when called', () => {
        expect(loader.loadModule).toThrow();
      });

      it('loadAllModules() should throw when called', () => {
        expect(loader.loadAllModules).toThrow();
      });

      it('loadTemplate() should throw when called', () => {
        expect(loader.loadTemplate).toThrow();
      });
    });

    describe("implemented method", () => {

      afterEach(() => {
        var link = document.head.querySelector('link[rel="import"]');
        document.head.removeChild(link);
      });

      it("importDocument() should load a document fragment for a url", (done) => {
        loader.importDocument('base/test/fixtures/plainHtml.html')
          .then((imported) => expect(imported).toBeDefined())
          .catch((reason) => expect(false).toBeTruthy(reason))
          .then(done);
      });

      it("importTemplate() should extract a template", (done) => {
        loader.importTemplate('base/test/fixtures/template.html')
        .then((template) => expect(template.innerHTML).toBe("
This is the template
"))
        .catch((error) => expect(false).toBeTruthy(error))
        .then(done);
      });

      it("importTemplate() should fail if there is no template tag", (done) => {
        loader.importTemplate('base/test/fixtures/plainHtml.html')
          .then((template) => expect(false).toBeTruthy("This should have failed"))
          .catch((error) => expect(error).toBeDefined(error))
          .then(done);
      });
    });
  });
});
<|endoftext|>


<commit_before>const path = require('path');
const {
  rule,
  rules,
  multiRule,
  svgRule,
  compile,
  loaderPath,
  fixturesPath,
  extractPlugin,
  extractCSSRule,
  extractHTMLRule,
  compileAndNotReject
} = require('./utils');

const SpritePlugin = require('../lib/plugin');
const loaderDefaults = require('../lib/config').loader;
const Exceptions = require('../lib/exceptions');

const defaultSpriteFilename = loaderDefaults.spriteFilename;

describe('loader and plugin', () => {
  describe('normal mode', () => {
    describe('exceptions', () => {
      it('should emit error if invalid runtime passed', async () => {
        const { errors } = await compileAndNotReject({
          entry: './entry',
          module: rules(
            svgRule({ runtimeGenerator: 'qwe', symbolId: 'qwe' })
          )
        });

        errors.should.be.lengthOf(1);
        errors[0].error.should.be.instanceOf(Exceptions.InvalidRuntimeException);
      });

      it('should warn if several rules applied to module', async () => {
        const { warnings } = await compile({
          entry: './entry',
          module: rules(
            svgRule(),
            rule({ test: /\.svg$/, loader: loaderPath })
          )
        });

        // TODO loader applies 2 times so warning also will me emitted 2 times
        warnings.should.be.lengthOf(2);
        warnings[0].warning.should.be.instanceOf(Exceptions.SeveralRulesAppliedException);
      });
    });

    it('should allow to use custom runtime generator', async () => {
      const customRuntimeGeneratorPath = path.resolve(fixturesPath, 'custom-runtime-generator.js');

      const { assets } = await compile({
        entry: './entry',
        module: rules(
          svgRule({ runtimeGenerator: customRuntimeGeneratorPath })
        )
      });

      assets['main.js'].source().should.contain('olala');
    });
  });

  describe('extract mode', () => {
    describe('exceptions', () => {
      it('should emit error if loader used without plugin in extract mode', async () => {
        const { errors } = await compileAndNotReject({
          entry: './entry',
          module: rules(
            svgRule({ extract: true })
          )
        });

        errors.should.be.lengthOf(1);
        errors[0].error.should.be.instanceOf(Exceptions.ExtractPluginMissingException);
      });

      it('should warn if there is remaining loaders in extract mode', async () => {
        const { warnings } = await compile({
          entry: './entry',
          module: rules(
            multiRule({
              test: /\.svg$/,
              use: [
                'file-loader',
                { loader: loaderPath, options: { extract: true } },
                'svgo-loader'
              ]
            })
          ),
          plugins: [new SpritePlugin()]
        });

        warnings.should.be.lengthOf(1);
        warnings[0].warning.should.be.instanceOf(Exceptions.RemainingLoadersInExtractModeException);
      });
    });

    describe('interoperability', () => {
      describe('extract-text-webpack-plugin', () => {
        it.only('should properly extract sprite from extractable CSS', () => {

        });

        it('should work properly with `allChunks: true` config option', async () => {
          const spriteFilename = 'qwe.svg';
          const extractor = extractPlugin('[name].css', { allChunks: true });

          const { assets } = await compile({
            entry: './styles.css',
            module: rules(
              svgRule({ spriteFilename }),
              extractCSSRule(extractor)
            ),
            plugins: [
              new SpritePlugin(),
              extractor
            ]
          });

          Object.keys(assets).should.be.lengthOf(3);
          assets.should.have.property(spriteFilename);
          assets['main.css'].source().should.includes(spriteFilename);
        });
      });
    });

    it('should automatically detect modules to extract', async () => {
      const { assets } = await compile({
        entry: './entry',
        module: rules(
          svgRule()
        ),
        plugins: [new SpritePlugin()]
      });

      Object.keys(assets).should.be.lengthOf(1);
    });

    it('should allow to specify custom sprite filename', async () => {
      const spriteFilename = 'qwe.svg';

      const { assets } = await compile({
        entry: './styles.css',
        module: rules(
          svgRule({ spriteFilename }),
          extractCSSRule()
        ),
        plugins: [
          CSSExtractor,
          new SpritePlugin()
        ]
      });

      Object.keys(assets).should.be.lengthOf(3);
      assets.should.have.property(spriteFilename);
    });

    it('should emit sprite for each chunk if [chunkname] presented in sprite filename', async () => {
      const { assets } = await compile({
        entry: {
          styles: './styles.css',
          styles2: './styles2.css'
        },
        module: rules(
          multiRule({
            test: /\.svg$/,
            use: [
              { loader: loaderPath, options: { spriteFilename: '[chunkname]-sprite.svg' } },
              'svgo-loader'
            ]
          }),
          extractCSSRule()
        ),
        plugins: [
          CSSExtractor,
          new SpritePlugin()
        ]
      });

      Object.keys(assets).should.be.lengthOf(6);
      assets.should.have.property('styles-sprite.svg');
      assets.should.have.property('styles2-sprite.svg');
    });

    it('should replace with proper publicPath', async () => {
      const publicPath = '/olala/';
      const spriteFilename = defaultSpriteFilename;

      const { assets } = await compile({
        entry: './entry',
        output: { publicPath },
        module: rules(
          svgRule({ extract: true, spriteFilename })
        ),
        plugins: [new SpritePlugin()]
      });

      assets['main.js'].source().should.contain(publicPath + spriteFilename);
    });

    it('should work with html-loader', async () => {
      const spriteFilename = defaultSpriteFilename;

      const { assets } = await compile({
        entry: './page.html',
        module: rules(
          svgRule({ spriteFilename }),
          extractHTMLRule()
        ),
        plugins: [
          new SpritePlugin(),
          HTMLExtractor
        ]
      });

      assets['main.html'].source().should.contain(`img src="${spriteFilename}#`);
    });

    it('should emit only built chunks', () => {
      // TODO test with webpack-recompilation-emulator
    });
  });
});
<commit_msg>test(loader): update extract-text-webpack-plugin interop test<commit_after>const path = require('path');
const {
  rule,
  rules,
  multiRule,
  svgRule,
  compile,
  loaderPath,
  fixturesPath,
  extractPlugin,
  extractCSSRule,
  extractHTMLRule,
  compileAndNotReject
} = require('./utils');

const SpritePlugin = require('../lib/plugin');
const loaderDefaults = require('../lib/config').loader;
const Exceptions = require('../lib/exceptions');

const defaultSpriteFilename = loaderDefaults.spriteFilename;

describe('loader and plugin', () => {
  describe('normal mode', () => {
    describe('exceptions', () => {
      it('should emit error if invalid runtime passed', async () => {
        const { errors } = await compileAndNotReject({
          entry: './entry',
          module: rules(
            svgRule({ runtimeGenerator: 'qwe', symbolId: 'qwe' })
          )
        });

        errors.should.be.lengthOf(1);
        errors[0].error.should.be.instanceOf(Exceptions.InvalidRuntimeException);
      });

      it('should warn if several rules applied to module', async () => {
        const { warnings } = await compile({
          entry: './entry',
          module: rules(
            svgRule(),
            rule({ test: /\.svg$/, loader: loaderPath })
          )
        });

        // TODO loader applies 2 times so warning also will me emitted 2 times
        warnings.should.be.lengthOf(2);
        warnings[0].warning.should.be.instanceOf(Exceptions.SeveralRulesAppliedException);
      });
    });

    it('should allow to use custom runtime generator', async () => {
      const customRuntimeGeneratorPath = path.resolve(fixturesPath, 'custom-runtime-generator.js');

      const { assets } = await compile({
        entry: './entry',
        module: rules(
          svgRule({ runtimeGenerator: customRuntimeGeneratorPath })
        )
      });

      assets['main.js'].source().should.contain('olala');
    });
  });

  describe('extract mode', () => {
    describe('exceptions', () => {
      it('should emit error if loader used without plugin in extract mode', async () => {
        const { errors } = await compileAndNotReject({
          entry: './entry',
          module: rules(
            svgRule({ extract: true })
          )
        });

        errors.should.be.lengthOf(1);
        errors[0].error.should.be.instanceOf(Exceptions.ExtractPluginMissingException);
      });

      it('should warn if there is remaining loaders in extract mode', async () => {
        const { warnings } = await compile({
          entry: './entry',
          module: rules(
            multiRule({
              test: /\.svg$/,
              use: [
                'file-loader',
                { loader: loaderPath, options: { extract: true } },
                'svgo-loader'
              ]
            })
          ),
          plugins: [new SpritePlugin()]
        });

        warnings.should.be.lengthOf(1);
        warnings[0].warning.should.be.instanceOf(Exceptions.RemainingLoadersInExtractModeException);
      });
    });

    describe('interoperability', () => {
      describe('extract-text-webpack-plugin', () => {
        it.only('should properly extract sprite from extractable CSS', () => {

        });

        it('should work properly with `allChunks: true` config option', async () => {
          const spriteFilename = 'qwe.svg';
          const extractor = extractPlugin('[name].css', { allChunks: true });

          const { assets } = await compile({
            entry: {
              styles: './styles.css',
              styles2: './styles2.css'
            },
            module: rules(
              svgRule({ spriteFilename }),
              extractCSSRule(extractor)
            ),
            plugins: [
              new SpritePlugin(),
              extractor
            ]
          });

          Object.keys(assets).should.be.lengthOf(5);
          assets.should.have.property(spriteFilename);
          assets['styles.css'].source().should.includes(spriteFilename);
          assets['styles2.css'].source().should.includes(spriteFilename);
        });
      });
    });

    it('should automatically detect modules to extract', async () => {
      const { assets } = await compile({
        entry: './entry',
        module: rules(
          svgRule()
        ),
        plugins: [new SpritePlugin()]
      });

      Object.keys(assets).should.be.lengthOf(1);
    });

    it('should allow to specify custom sprite filename', async () => {
      const spriteFilename = 'qwe.svg';

      const { assets } = await compile({
        entry: './styles.css',
        module: rules(
          svgRule({ spriteFilename }),
          extractCSSRule()
        ),
        plugins: [
          CSSExtractor,
          new SpritePlugin()
        ]
      });

      Object.keys(assets).should.be.lengthOf(3);
      assets.should.have.property(spriteFilename);
    });

    it('should emit sprite for each chunk if [chunkname] presented in sprite filename', async () => {
      const { assets } = await compile({
        entry: {
          styles: './styles.css',
          styles2: './styles2.css'
        },
        module: rules(
          multiRule({
            test: /\.svg$/,
            use: [
              { loader: loaderPath, options: { spriteFilename: '[chunkname]-sprite.svg' } },
              'svgo-loader'
            ]
          }),
          extractCSSRule()
        ),
        plugins: [
          CSSExtractor,
          new SpritePlugin()
        ]
      });

      Object.keys(assets).should.be.lengthOf(6);
      assets.should.have.property('styles-sprite.svg');
      assets.should.have.property('styles2-sprite.svg');
    });

    it('should replace with proper publicPath', async () => {
      const publicPath = '/olala/';
      const spriteFilename = defaultSpriteFilename;

      const { assets } = await compile({
        entry: './entry',
        output: { publicPath },
        module: rules(
          svgRule({ extract: true, spriteFilename })
        ),
        plugins: [new SpritePlugin()]
      });

      assets['main.js'].source().should.contain(publicPath + spriteFilename);
    });

    it('should work with html-loader', async () => {
      const spriteFilename = defaultSpriteFilename;

      const { assets } = await compile({
        entry: './page.html',
        module: rules(
          svgRule({ spriteFilename }),
          extractHTMLRule()
        ),
        plugins: [
          new SpritePlugin(),
          HTMLExtractor
        ]
      });

      assets['main.html'].source().should.contain(`img src="${spriteFilename}#`);
    });

    it('should emit only built chunks', () => {
      // TODO test with webpack-recompilation-emulator
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Chainable sheeter for js object/values sheets (deepjs related API)
 */
if (typeof define !== 'function') {
	var define = require('amdefine')(module);
}
define(["require", "./sheet", "./promise", "./compose"],
function(require, sheet, promise, composer){
	var Sheeter = new composer.Composer(sheet.sheet);	// create composer manager for namespace deep.sheet
	Sheeter.add("deepLoad", "after", function(context, destructive) {
		return function(entry, options) {
			return deep.deepLoad(entry, context, destructive)
			.when(deep.Arguments([entry, options]));
		};
	});
	Sheeter.add("query", "after", function(q) {
		return function(entry, options) {
			return deep(entry).query(q)
			.done(function(s){
				return deep.Arguments([s,options]);
			});
		}
	});
	Sheeter.add("up", "after", function() {
		var args = arguments;
		return function(entry, options) {
			var d = deep(entry);
			return d.up.apply(d, args)
			.when(deep.Arguments([entry, options]));
		}
	});
	Sheeter.add("bottom", "after", function() {
		var args = arguments;
		return function(entry, options) {
			var d = deep(entry);
			return d.bottom.apply(d, args)
			.when(deep.Arguments([entry, options]));
		}
	});
	Sheeter.add("flatten", "after", function() {
		return function(entry, options) {
			return deep(entry).flatten()
			.when(deep.Arguments([entry, options]));
		}
	});
	Sheeter.add("sheet", "after", function() {
		var args = arguments;
		return function(entry, options) {
			var d = deep(entry);
			return d.sheet.apply(d, args)
			.when(deep.Arguments([entry, options]));
		}
	});
	Sheeter.add("transform", "after", function(fn) {
		return function(entry, options) {
			return deep(entry)
			.transform(fn)
			.when(deep.Arguments([entry, options]));
		}
	});
	Sheeter.add("interpret", "after", function(context) {
		return function(entry, options) {
			return deep(entry)
			.interpret(context, null, true)
			.when(deep.Arguments([entry, options]));
		}
	});
	return Sheeter;
});<commit_msg>rewrite deep-sheeers<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Chainable sheeter for js object/values sheets (deepjs related API)
 */
if (typeof define !== 'function') {
	var define = require('amdefine')(module);
}
define(["require", "./sheet", "./promise", "./compose", "./nodes", "./query", "./flatten", "./sheet", "./utils"],
function(require, sheet, promise, composer, nodes, querier, flattener, sheets, utils){
	var Sheeter = new composer.Composer(sheet.sheet);	// create composer manager for namespace deep.sheet
	var Arguments = composer.compose.Arguments;
	Sheeter.add("deepLoad", "after", function(context, destructive) {
		return function(entry, options) {
			return nodes.deepLoad(entry, context, destructive)
			.when(Arguments([entry, options]));
		};
	});
	Sheeter.add("query", "after", function(q) {
		return function(entry, options) {
			return querier.query(entry, q);
		}
	});
	Sheeter.add("up", "after", function() {
		var args = arguments;
		return function(entry, options) {
			return nodes.asyncUps(entry, Array.prototype.slice.call(args))
			.when(Arguments([entry, options]));
		}
	});
	Sheeter.add("bottom", "after", function() {
		var args = arguments;
		return function(entry, options) {
			return nodes.asyncBottoms(entry, Array.prototype.slice.call(args))
			.when(Arguments([entry, options]));
		}
	});
	Sheeter.add("flatten", "after", function() {
		return function(entry, options) {
			return promise.when(flattener.flatten(entry))
			.when(Arguments([entry, options]));
		}
	});
	Sheeter.add("sheet", "after", function() {
		var args = Array.prototype.slice.call(arguments);
		return function(entry, options) {
			args.push(entry);
			return sheets.sheet.apply({}, args)
			.when(Arguments([entry, options]));
		}
	});
	Sheeter.add("transform", "after", function(fn) {
		return function(entry, options) {
			return promise.when(nodes.transform(entry, fn))
			.when(Arguments([entry, options]));
		}
	});
	//_________________________________________________________________
	Sheeter.add("interpret", "after", function(context) {
		return function(entry, options) {
			entry.value = utils.interpret(entry.value, context);
			if(entry.ancestor)
				entry.ancestor.value[entry.key] = entry.value;
			return Arguments([entry, options]);
		}
	});
	return Sheeter;
});<|endoftext|>


<commit_before>import Immutable, { Map } from 'immutable'

import {
  FAILED_EXTERNAL_ACTION,
  LOGOUT,
  POOL_ACTION_IN_PROGRESS,
  REMOVE_MISSING_POOLS,
  REMOVE_MISSING_VMS,
  REMOVE_POOLS,
  REMOVE_VMS,
  SET_FILTERS,
  SET_VM_SORT,
  SET_VM_ACTION_RESULT,
  SET_VM_DISKS,
  SET_VM_NICS,
  SET_VM_SESSIONS,
  SET_VM_SNAPSHOTS,
  UPDATE_PAGING_DATA,
  UPDATE_POOLS,
  UPDATE_VM_SNAPSHOT,
  UPDATE_VMPOOLS_COUNT,
  UPDATE_VM_DISK,
  UPDATE_VMS,
  VM_ACTION_IN_PROGRESS,
} from '_/constants'
import { actionReducer, removeMissingItems } from './utils'
import { SortFields } from '_/utils'

const initialState = Immutable.fromJS({
  vms: {},
  pools: {},
  filters: {},
  sort: { ...SortFields.NAME, isAsc: true },

  missedVms: Immutable.Set(),

  vmsPage: 0,
  vmsExpectMorePages: true,

  poolsPage: 0,
  poolsExpectMorePages: true,

  correlationResult: {},
})

const vms = actionReducer(initialState, {

  // vms come in as Internal transformed JS objects that will be pushed to ImmutableJS
  //     objects after an optional merge with existing vm data
  [UPDATE_VMS] (state, { payload: { vms, copySubResources } }) {
    const updates = {}

    vms.forEach(vm => {
      const existingVm = state.hasIn(['vms', vm.id]) ? state.getIn(['vms', vm.id]).toJS() : false

      updates[vm.id] = vm
      updates[vm.id].actionResults = (existingVm && existingVm.actionResults) || {}

      // Copy across the VM_FETCH_ADDITIONAL_DEEP values from the existingVm
      if (existingVm && copySubResources) {
        // Only copy consoles if the VM does not already have any
        updates[vm.id].consoles = vm.consoles.length === 0 ? existingVm.consoles || [] : vm.consoles

        updates[vm.id].cdrom = existingVm.cdrom || { file: { id: '' } }
        updates[vm.id].disks = existingVm.disks || []
        updates[vm.id].nics = existingVm.nics || []
        updates[vm.id].sessions = existingVm.sessions || []
        updates[vm.id].snapshots = existingVm.snapshots || []
        updates[vm.id].statistics = existingVm.statistics || []

        updates[vm.id].permissions = existingVm.permissions || []
        updates[vm.id].userPermits = existingVm.userPermits || []
        updates[vm.id].canUserChangeCd = !!existingVm.canUserChangeCd
        updates[vm.id].canUserEditVm = !!existingVm.canUserEditVm
        updates[vm.id].canUserManipulateSnapshots = !!existingVm.canUserManipulateSnapshots
        updates[vm.id].canUserEditVmStorage = !!existingVm.canUserEditVmStorage
      }
    })

    let st = state.mergeIn(['vms'], Immutable.fromJS(updates))

    const vmsIds = Object.keys(updates)
    st = st.set('missedVms', st.get('missedVms').subtract(vmsIds))

    return st
  },
  [REMOVE_VMS] (state, { payload: { vmIds } }) {
    const mutable = state.asMutable()
    vmIds.forEach(vmId => mutable.deleteIn(['vms', vmId]))
    mutable.update('missedVms', missedVms => missedVms.union(vmIds))
    return mutable.asImmutable()
  },
  [REMOVE_MISSING_VMS] (state, { payload: { vmIdsToPreserve } }) {
    return removeMissingItems({ state, subStateName: 'vms', idsToPreserve: vmIdsToPreserve })
  },

  [SET_VM_DISKS] (state, { payload: { vmId, disks } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'disks'], Immutable.fromJS(disks)) // deep immutable
    } else { // fail, if VM not found
      console.error(`vms.setVmDisks() reducer: vmId ${vmId} not found`)
    }
    return state
  },
  [UPDATE_VM_DISK] (state, { payload: { vmId, disk } }) {
    if (state.getIn(['vms', vmId])) {
      const existing = state.getIn(['vms', vmId, 'disks']).findEntry(d => d.get('id') === disk.id)
      if (existing) {
        state = state.mergeDeepIn(['vms', vmId, 'disks', existing[0]], Immutable.fromJS(disk))
      }
    }
    return state
  },

  [SET_VM_SNAPSHOTS] (state, { payload: { vmId, snapshots } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'snapshots'], Immutable.fromJS(snapshots)) // deep immutable
    }

    console.error(`vms.setVmSnapshots() reducer: vmId ${vmId} not found`)
    return state
  },
  [UPDATE_VM_SNAPSHOT] (state, { payload: { vmId, snapshot } }) {
    if (state.getIn(['vms', vmId])) {
      const snapshotForUpdate = state.getIn(['vms', vmId, 'snapshots']).findIndex((s) => s.get('id') === snapshot.id)
      if (snapshotForUpdate > -1) {
        return state.updateIn(['vms', vmId, 'snapshots', snapshotForUpdate], (s) => s
          .set('description', snapshot.description)
          .set('type', snapshot.type)
          .set('status', snapshot.status)
          .set('persistMemoryState', snapshot.persistMemoryState)) // deep immutable
      }
      return state
    }

    console.error(`vms.setVmSnapshots() reducer: vmId ${vmId} not found`)
    return state
  },

  [SET_VM_NICS] (state, { payload: { vmId, nics } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'nics'], Immutable.fromJS(nics)) // deep immutable
    } else { // fail, if VM not found
      console.error(`vms.setVmNics() reducer: vmId ${vmId} not found`)
    }
    return state
  },

  [SET_VM_SESSIONS] (state, { payload: { vmId, sessions } }) {
    let consoleInUse = false
    for (const i in sessions) {
      if (sessions[i].consoleUser) {
        consoleInUse = true
        break
      }
    }
    state = state.setIn(['vms', vmId, 'sessions'], Immutable.fromJS(sessions))
    return state.setIn(['vms', vmId, 'consoleInUse'], consoleInUse)
  },

  [VM_ACTION_IN_PROGRESS] (state, { payload: { vmId, name, started } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'actionInProgress', name], started)
    }
    return state
  },

  [UPDATE_POOLS] (state, { payload: { pools } }) {
    const updates = {}
    pools.forEach(pool => {
      updates[pool.id] = pool
    })
    const imUpdates = Immutable.fromJS(updates)
    return state.mergeIn(['pools'], imUpdates)
  },
  [REMOVE_POOLS] (state, { payload: { poolIds } }) {
    const mutable = state.asMutable()
    poolIds.forEach(poolId => mutable.deleteIn(['pools', poolId]))
    return mutable.asImmutable()
  },
  [REMOVE_MISSING_POOLS] (state, { payload: { poolIdsToPreserve } }) {
    const newPools = poolIdsToPreserve
      .reduce((pools, poolId) => {
        const pool = state.getIn(['pools', poolId])
        if (pool) {
          pools.set(poolId, pool)
        }
        return pools
      }, Map().asMutable())
      .asImmutable()
    return state.set('pools', newPools)
  },

  [POOL_ACTION_IN_PROGRESS] (state, { payload: { poolId, name, started } }) {
    return state.setIn(['pools', poolId, 'vm', 'actionInProgress', name], started)
  },

  [UPDATE_VMPOOLS_COUNT] (state) {
    state = state.update('pools', pools => pools.map(pool => pool.set('vmsCount', 0)))

    state.get('vms').map(vm => {
      const poolId = vm.getIn(['pool', 'id'])
      if (poolId && state.getIn(['pools', poolId])) {
        // VM is in a known pool ... down VMs don't count against the user total unless it is a manual pool
        if (vm.get('status') !== 'down' || state.getIn(['pools', poolId, 'type']) === 'manual') {
          state = state.updateIn(['pools', poolId, 'vmsCount'], count => count + 1)
        }
      }
    })

    return state
  },

  [FAILED_EXTERNAL_ACTION] (state, { payload: { message, messageDescriptor, type, failedAction } }) {
    if (message && failedAction && failedAction.payload && failedAction.payload.vmId) {
      const vmId = failedAction.payload.vmId
      if (state.getIn(['vms', vmId])) {
        return state.setIn(['vms', vmId, 'lastMessage'], messageDescriptor || message)
      } else {
        console.error(`API reports an error associated to nonexistent VM ${vmId}, error`,
          { message, messageDescriptor, type, failedAction })
      }
    }

    return state
  },

  [SET_VM_ACTION_RESULT] (state, { payload: { vmId, correlationId, result } }) {
    if (!vmId) {
      return state.update('correlationResult', results => results.set(correlationId, result))
    }
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'actionResults', correlationId], result)
    }
    return state
  },

  [UPDATE_PAGING_DATA] (state, { payload: { vmsPage, vmsExpectMorePages, poolsPage, poolsExpectMorePages } }) {
    if (vmsPage) {
      state = state.set('vmsPage', vmsPage)
    }
    state = state.set('vmsExpectMorePages', vmsExpectMorePages)

    if (poolsPage) {
      state = state.set('poolsPage', poolsPage)
    }
    state = state.set('poolsExpectMorePages', poolsExpectMorePages)

    return state
  },

  [LOGOUT] (state) { // see the config() reducer
    return state.set('vms', Immutable.fromJS({}))
  },
  [SET_FILTERS] (state, { payload: { filters } }) { // see the config() reducer
    return state.set('filters', Immutable.fromJS(filters))
  },
  [SET_VM_SORT] (state, { payload: { sort } }) { // see the config() reducer
    return state.set('sort', Immutable.fromJS(sort))
  },
})

export default vms
export {
  initialState,
}
<commit_msg>eslint manual fix rule `array-callback-return`<commit_after>import Immutable, { Map } from 'immutable'

import {
  FAILED_EXTERNAL_ACTION,
  LOGOUT,
  POOL_ACTION_IN_PROGRESS,
  REMOVE_MISSING_POOLS,
  REMOVE_MISSING_VMS,
  REMOVE_POOLS,
  REMOVE_VMS,
  SET_FILTERS,
  SET_VM_SORT,
  SET_VM_ACTION_RESULT,
  SET_VM_DISKS,
  SET_VM_NICS,
  SET_VM_SESSIONS,
  SET_VM_SNAPSHOTS,
  UPDATE_PAGING_DATA,
  UPDATE_POOLS,
  UPDATE_VM_SNAPSHOT,
  UPDATE_VMPOOLS_COUNT,
  UPDATE_VM_DISK,
  UPDATE_VMS,
  VM_ACTION_IN_PROGRESS,
} from '_/constants'
import { actionReducer, removeMissingItems } from './utils'
import { SortFields } from '_/utils'

const initialState = Immutable.fromJS({
  vms: {},
  pools: {},
  filters: {},
  sort: { ...SortFields.NAME, isAsc: true },

  missedVms: Immutable.Set(),

  vmsPage: 0,
  vmsExpectMorePages: true,

  poolsPage: 0,
  poolsExpectMorePages: true,

  correlationResult: {},
})

const vms = actionReducer(initialState, {

  // vms come in as Internal transformed JS objects that will be pushed to ImmutableJS
  //     objects after an optional merge with existing vm data
  [UPDATE_VMS] (state, { payload: { vms, copySubResources } }) {
    const updates = {}

    vms.forEach(vm => {
      const existingVm = state.hasIn(['vms', vm.id]) ? state.getIn(['vms', vm.id]).toJS() : false

      updates[vm.id] = vm
      updates[vm.id].actionResults = (existingVm && existingVm.actionResults) || {}

      // Copy across the VM_FETCH_ADDITIONAL_DEEP values from the existingVm
      if (existingVm && copySubResources) {
        // Only copy consoles if the VM does not already have any
        updates[vm.id].consoles = vm.consoles.length === 0 ? existingVm.consoles || [] : vm.consoles

        updates[vm.id].cdrom = existingVm.cdrom || { file: { id: '' } }
        updates[vm.id].disks = existingVm.disks || []
        updates[vm.id].nics = existingVm.nics || []
        updates[vm.id].sessions = existingVm.sessions || []
        updates[vm.id].snapshots = existingVm.snapshots || []
        updates[vm.id].statistics = existingVm.statistics || []

        updates[vm.id].permissions = existingVm.permissions || []
        updates[vm.id].userPermits = existingVm.userPermits || []
        updates[vm.id].canUserChangeCd = !!existingVm.canUserChangeCd
        updates[vm.id].canUserEditVm = !!existingVm.canUserEditVm
        updates[vm.id].canUserManipulateSnapshots = !!existingVm.canUserManipulateSnapshots
        updates[vm.id].canUserEditVmStorage = !!existingVm.canUserEditVmStorage
      }
    })

    let st = state.mergeIn(['vms'], Immutable.fromJS(updates))

    const vmsIds = Object.keys(updates)
    st = st.set('missedVms', st.get('missedVms').subtract(vmsIds))

    return st
  },
  [REMOVE_VMS] (state, { payload: { vmIds } }) {
    const mutable = state.asMutable()
    vmIds.forEach(vmId => mutable.deleteIn(['vms', vmId]))
    mutable.update('missedVms', missedVms => missedVms.union(vmIds))
    return mutable.asImmutable()
  },
  [REMOVE_MISSING_VMS] (state, { payload: { vmIdsToPreserve } }) {
    return removeMissingItems({ state, subStateName: 'vms', idsToPreserve: vmIdsToPreserve })
  },

  [SET_VM_DISKS] (state, { payload: { vmId, disks } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'disks'], Immutable.fromJS(disks)) // deep immutable
    } else { // fail, if VM not found
      console.error(`vms.setVmDisks() reducer: vmId ${vmId} not found`)
    }
    return state
  },
  [UPDATE_VM_DISK] (state, { payload: { vmId, disk } }) {
    if (state.getIn(['vms', vmId])) {
      const existing = state.getIn(['vms', vmId, 'disks']).findEntry(d => d.get('id') === disk.id)
      if (existing) {
        state = state.mergeDeepIn(['vms', vmId, 'disks', existing[0]], Immutable.fromJS(disk))
      }
    }
    return state
  },

  [SET_VM_SNAPSHOTS] (state, { payload: { vmId, snapshots } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'snapshots'], Immutable.fromJS(snapshots)) // deep immutable
    }

    console.error(`vms.setVmSnapshots() reducer: vmId ${vmId} not found`)
    return state
  },
  [UPDATE_VM_SNAPSHOT] (state, { payload: { vmId, snapshot } }) {
    if (state.getIn(['vms', vmId])) {
      const snapshotForUpdate = state.getIn(['vms', vmId, 'snapshots']).findIndex((s) => s.get('id') === snapshot.id)
      if (snapshotForUpdate > -1) {
        return state.updateIn(['vms', vmId, 'snapshots', snapshotForUpdate], (s) => s
          .set('description', snapshot.description)
          .set('type', snapshot.type)
          .set('status', snapshot.status)
          .set('persistMemoryState', snapshot.persistMemoryState)) // deep immutable
      }
      return state
    }

    console.error(`vms.setVmSnapshots() reducer: vmId ${vmId} not found`)
    return state
  },

  [SET_VM_NICS] (state, { payload: { vmId, nics } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'nics'], Immutable.fromJS(nics)) // deep immutable
    } else { // fail, if VM not found
      console.error(`vms.setVmNics() reducer: vmId ${vmId} not found`)
    }
    return state
  },

  [SET_VM_SESSIONS] (state, { payload: { vmId, sessions } }) {
    let consoleInUse = false
    for (const i in sessions) {
      if (sessions[i].consoleUser) {
        consoleInUse = true
        break
      }
    }
    state = state.setIn(['vms', vmId, 'sessions'], Immutable.fromJS(sessions))
    return state.setIn(['vms', vmId, 'consoleInUse'], consoleInUse)
  },

  [VM_ACTION_IN_PROGRESS] (state, { payload: { vmId, name, started } }) {
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'actionInProgress', name], started)
    }
    return state
  },

  [UPDATE_POOLS] (state, { payload: { pools } }) {
    const updates = {}
    pools.forEach(pool => {
      updates[pool.id] = pool
    })
    const imUpdates = Immutable.fromJS(updates)
    return state.mergeIn(['pools'], imUpdates)
  },
  [REMOVE_POOLS] (state, { payload: { poolIds } }) {
    const mutable = state.asMutable()
    poolIds.forEach(poolId => mutable.deleteIn(['pools', poolId]))
    return mutable.asImmutable()
  },
  [REMOVE_MISSING_POOLS] (state, { payload: { poolIdsToPreserve } }) {
    const newPools = poolIdsToPreserve
      .reduce((pools, poolId) => {
        const pool = state.getIn(['pools', poolId])
        if (pool) {
          pools.set(poolId, pool)
        }
        return pools
      }, Map().asMutable())
      .asImmutable()
    return state.set('pools', newPools)
  },

  [POOL_ACTION_IN_PROGRESS] (state, { payload: { poolId, name, started } }) {
    return state.setIn(['pools', poolId, 'vm', 'actionInProgress', name], started)
  },

  [UPDATE_VMPOOLS_COUNT] (state) {
    state = state.update('pools', pools => pools.map(pool => pool.set('vmsCount', 0)))

    state.get('vms').forEach(vm => {
      const poolId = vm.getIn(['pool', 'id'])
      if (poolId && state.getIn(['pools', poolId])) {
        // VM is in a known pool ... down VMs don't count against the user total unless it is a manual pool
        if (vm.get('status') !== 'down' || state.getIn(['pools', poolId, 'type']) === 'manual') {
          state = state.updateIn(['pools', poolId, 'vmsCount'], count => count + 1)
        }
      }
    })

    return state
  },

  [FAILED_EXTERNAL_ACTION] (state, { payload: { message, messageDescriptor, type, failedAction } }) {
    if (message && failedAction && failedAction.payload && failedAction.payload.vmId) {
      const vmId = failedAction.payload.vmId
      if (state.getIn(['vms', vmId])) {
        return state.setIn(['vms', vmId, 'lastMessage'], messageDescriptor || message)
      } else {
        console.error(`API reports an error associated to nonexistent VM ${vmId}, error`,
          { message, messageDescriptor, type, failedAction })
      }
    }

    return state
  },

  [SET_VM_ACTION_RESULT] (state, { payload: { vmId, correlationId, result } }) {
    if (!vmId) {
      return state.update('correlationResult', results => results.set(correlationId, result))
    }
    if (state.getIn(['vms', vmId])) {
      return state.setIn(['vms', vmId, 'actionResults', correlationId], result)
    }
    return state
  },

  [UPDATE_PAGING_DATA] (state, { payload: { vmsPage, vmsExpectMorePages, poolsPage, poolsExpectMorePages } }) {
    if (vmsPage) {
      state = state.set('vmsPage', vmsPage)
    }
    state = state.set('vmsExpectMorePages', vmsExpectMorePages)

    if (poolsPage) {
      state = state.set('poolsPage', poolsPage)
    }
    state = state.set('poolsExpectMorePages', poolsExpectMorePages)

    return state
  },

  [LOGOUT] (state) { // see the config() reducer
    return state.set('vms', Immutable.fromJS({}))
  },
  [SET_FILTERS] (state, { payload: { filters } }) { // see the config() reducer
    return state.set('filters', Immutable.fromJS(filters))
  },
  [SET_VM_SORT] (state, { payload: { sort } }) { // see the config() reducer
    return state.set('sort', Immutable.fromJS(sort))
  },
})

export default vms
export {
  initialState,
}
<|endoftext|>


<commit_before>import setupEnv from '../env/sinopia';
const exec = require('child_process').exec;

function install(registry, path, modules) {
    exec(`npm i --force --prefix ${path} --registry="${registry}" ${modules.join(' ')}`, (err, stdout, stderr) => {
        if (!err)
            process.exit(0);
        process.exit(1)
    });
}

function fetch(port, config, path, modules) {
    setupEnv(port, config);
    require('sinopia/lib/cli');
    fetch(`http://localhost:${port}/`, path, modules);
}

let [proc, startPath, port, config, path, modules] = process.argv;
modules = modules.split(',');
fetch(port, config, path, modules);
<commit_msg>automatically whiten only if it was the startup module<commit_after>import setupEnv from '../env/sinopia';
const exec = require('child_process').exec;

function install(registry, path, modules) {
    exec(`npm i --force --prefix ${path} --registry="${registry}" ${modules.join(' ')}`, (err, stdout, stderr) => {
        if (!err)
            process.exit(0);
        process.exit(1)
    });
}

function fetch(port, config, path, modules) {
    setupEnv(port, config);
    require('sinopia/lib/cli');
    install(`http://localhost:${port}/`, path, modules);
}

if (require.main === module) {
    let [proc, startPath, port, config, path, modules] = process.argv;
    modules = modules.split(',');
    fetch(port, config, path, modules);
}
<|endoftext|>


<commit_before>'use strict';
import {Rect} from './helpers/rect';
import * as Utils from './helpers/utils.js';
import {Colour} from './helpers/colour';
import * as renderer from './renderer.base';
import * as constants from './constants';
import {Tayberry} from './base';

export class BarRenderer extends renderer.Renderer {
    constructor(ctx, tayberry, series) {
        super(ctx, tayberry, series);

        this.barPositions = null;

        this.tb.registerCallback('onResize', this.updateBarWidths.bind(this));
        this.tb.registerCallback('onInit', this.updateBarWidths.bind(this));
    }

    updateBarWidths() {
        const categoryCount = this.series[0].data.length;
        const isStacked = this.tb.options.barPlot.mode === 'stacked';
        const isOverlaid = this.tb.options.barPlot.mode === 'overlaid';
        const isNormal = !isStacked && !isOverlaid;
        const seriesCount = this.series.length;
        const plotArea = this.tb.options.swapAxes ? this.tb.plotArea.clone().swapXY() : this.tb.plotArea;
        const categoryWidth = (plotArea.width / categoryCount);
        let animatingSeriesCount = 0;
        let totalMultiplier = 0;

        for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {
            const series = this.series[seriesIndex];
            const rState = series.rState;
            if (series.animationState) {
                if (!series.animationState.subtype) {
                    const visibleSeriesCount = this.getVisibleSeriesCount(seriesIndex);
                    if (isNormal && visibleSeriesCount > 0) {
                        series.animationState.subtype = 'width';
                    } else if (isStacked  && visibleSeriesCount > 0) {
                        series.animationState.subtype = 'height';
                    } else {
                        series.animationState.subtype = 'fade';
                    }

                    rState.colour = series.colour;
                }

                const isShow = series.animationState.type === 'show';
                if (series.animationState.subtype === 'width') {
                    rState.multiplier = isShow ? series.animationState.stage : 1 - series.animationState.stage;
                    rState.yMultiplier = 1;
                } else if (series.animationState.subtype === 'height') {
                    rState.yMultiplier = isShow ? series.animationState.stage : 1 - series.animationState.stage;
                    rState.multiplier = 1;
                } else {
                    let transColour = new Colour(series.colour);
                    transColour.a = 0;
                    if (isShow)
                        rState.colour = Colour.createFromBlend(transColour, new Colour(series.colour), series.animationState.stage).toString();
                    else
                        rState.colour = Colour.createFromBlend(new Colour(series.colour), transColour, series.animationState.stage).toString();

                    rState.yMultiplier = 1;
                    rState.multiplier = 1;
                }
                ++animatingSeriesCount;
            } else if (series.visible & constants.visibilityState.visible) {
                rState.multiplier = 1;
                rState.yMultiplier = 1;
            } else {
                rState.multiplier = 0;
                rState.yMultiplier = 0;
            }
            totalMultiplier += rState.multiplier;
        }

        const totalBarsPerCategory = (isStacked || isOverlaid) ? 1 : totalMultiplier;
        const yOrigin = this.series[0].yAxis.getOrigin();

        this.barPositions = [];

        for (let categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {
            let yBottomPositive = yOrigin;
            let yBottomNegative = yOrigin;
            let yRunningTotalPositive = 0;
            let yRunningTotalNegative = 0;

            const categoryXStart = plotArea.left + Math.floor(categoryIndex * categoryWidth);
            const categoryXEnd = plotArea.left + Math.floor((categoryIndex + 1) * categoryWidth);
            // FIXME: Need to map this.tb.options.barPlot.categorySpacing
            const barXStart = categoryXStart + Math.ceil(categoryWidth * this.tb.options.barPlot.categorySpacing / 2);
            const barXEnd = categoryXEnd - Math.floor(categoryWidth * this.tb.options.barPlot.categorySpacing / 2);

            let categoryPositions = [];
            let barIndex = 0;

            let runningBarWidth = 0;

            for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {
                const series = this.series[seriesIndex];
                const rState = series.rState;
                const value = Tayberry.getDataValue(series.data[categoryIndex])*rState.yMultiplier;

                let barWidth = Math.floor(rState.multiplier * Math.floor((barXEnd - barXStart) / totalBarsPerCategory));

                const xStart = Math.floor(barXStart + runningBarWidth) + Math.ceil(series.xAxis.mapLogicalXOrYUnit(this.tb.options.barPlot.barPadding) / 2);
                const xEnd = Math.ceil(barXStart + runningBarWidth + barWidth) - Math.floor(series.xAxis.mapLogicalXOrYUnit(this.tb.options.barPlot.barPadding) / 2);
                const yTop = series.yAxis.getValueDisplacement(value + (value > 0 ? yRunningTotalPositive : yRunningTotalNegative));
                const yBottom = isStacked ? (value > 0 ? yBottomPositive : yBottomNegative) : yOrigin;

                categoryPositions.push([xStart, yTop, xEnd, yBottom]);

                if (isStacked) {
                    if (value > 0) {
                        yRunningTotalPositive += value;
                        yBottomPositive = yTop;
                    } else {
                        yRunningTotalNegative += value;
                        yBottomNegative = yTop;
                    }
                } else if (isNormal) {
                    barIndex++;
                    runningBarWidth += barWidth;
                }

            }

            this.barPositions.push(categoryPositions);
        }
    }

    onToggleSeriesAnimationFrame() {
        this.updateBarWidths();
    }

    drawPlot() {
        this.ctx.save();
        let barEnumerator = new BarEnumerator(this);
        let bar;
        while ((bar = barEnumerator.next())) {
            if (bar.series.visible & (constants.visibilityState.visible | constants.visibilityState.transitioning)) {
                this.ctx.fillStyle = bar.selected ? bar.series.rState.highlightColour : bar.series.rState.colour;
                this.ctx.fillRect(bar.rect.left, bar.rect.top, bar.rect.width, bar.rect.height);
            }
        }
        this.ctx.restore();
    }

    drawLabels() {
        if (this.tb.options.labels.enabled) {
            this.ctx.save();
            let barEnumerator = new BarEnumerator(this);
            let bar;
            while ((bar = barEnumerator.next())) {
                if ((bar.series.visible & (constants.visibilityState.visible | constants.visibilityState.transitioning)) === constants.visibilityState.visible) {
                    this.ctx.font = this.tb.labelFont;
                    this.ctx.fillStyle = this.tb.options.labels.font.colour;
                    this.drawLabel(bar.value, bar.series.yAxis.options.labelFormatter(bar.value), bar.rect);
                }
            }
            this.ctx.restore();
        }
    }

    hitTest(x, y) {
        // TODO: Optimise
        let ret = {
            found: false,
            plotType: 'bar',
            type: 'plotItem',
            isXRange: true
        };

        const categoryCount = this.series[0].data.length;
        const isHorizontal = this.tb.options.swapAxes;
        let plotArea = this.tb.plotArea.clone();
        if (isHorizontal)
            plotArea.swapXY();
        const categoryIndex = Math.floor(categoryCount * ((isHorizontal ? y : x) - plotArea.left) / plotArea.width);

        let matches = [];

        let barEnumerator = new BarEnumerator(this, categoryIndex);
        let bar;
        while ((bar = barEnumerator.next())) {
            if (bar.categoryIndex > categoryIndex)
                break;
            if (!(bar.series.visible & (constants.visibilityState.visible | constants.visibilityState.transitioning)))
                continue;

            let sortDistance, priority, realDistance;
            if (bar.rect.containsPoint(x, y)) {
                sortDistance = 0;
                priority = 0;
            }
            else if (bar.rect.containsX(x)) {
                sortDistance = y < bar.rect.top ? bar.rect.top - y : y - bar.rect.bottom;
                priority = isHorizontal ? 2 : 1;
            }
            else if (bar.rect.containsY(y)) {
                sortDistance = x < bar.rect.left ? bar.rect.left - x : x - bar.rect.right;
                priority = isHorizontal ? 1 : 2;
            }
            else {
                const xDist = Math.min(Math.abs(x - bar.rect.left), Math.abs(x - bar.rect.right));
                const yDist = Math.min(Math.abs(y - bar.rect.top), Math.abs(y - bar.rect.bottom));
                realDistance = Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
                sortDistance = isHorizontal ? yDist : xDist;
                priority = 3;
            }

            if (typeof realDistance === 'undefined')
                realDistance = sortDistance;

            if (!Utils.isMissingValue(realDistance)) {
                matches.push({
                    sortDistance: sortDistance,
                    distance: realDistance,
                    priority: priority,
                    data: {
                        categoryIndex: bar.categoryIndex,
                        seriesIndex: bar.seriesIndex,
                        rect: bar.rect,
                        series: bar.series,
                        value: Tayberry.getDataValue(this.series[bar.seriesIndex].data[bar.categoryIndex])
                    }
                });
            }
        }

        if (matches.length) {
            matches.sort((a, b) => {
                let ret = a.priority - b.priority;
                if (!ret) ret = a.sortDistance - b.sortDistance;
                if (!ret) ret = a.distance - b.distance;
                if (!ret) ret = a.data.rect.height - b.data.rect.height;
                return ret;
            });
            ret.found = true;
            ret.normalisedDistance = matches[0].distance + Math.sqrt(matches[0].data.rect.area);
            if (ret.normalisedDistance < 0) {
                ret.normalisedDistance = 0;
            }
            ret = Utils.assign(ret, matches[0].data);
        }
        return ret;
    }
}

export class BarEnumerator extends renderer.ByCategoryEnumerator {
    next() {
        let ret;

        if (this.categoryIndex < this.categoryCount) {
            const [xStart, yTop, xEnd, yBottom] = this.renderer.barPositions[this.categoryIndex][this.seriesIndex];

            let rect = new Rect(xStart, yTop, xEnd, yBottom);

            if (rect.right < rect.left)
                rect.right = rect.left;
            if (this.isHorizontal)
                rect.swapXY();
            rect.clip(this.tb.plotArea);

            ret = {
                seriesIndex: this.seriesIndex,
                categoryIndex: this.categoryIndex,
                series: this.renderer.series[this.seriesIndex],
                value: Tayberry.getDataValue(this.renderer.series[this.seriesIndex].data[this.categoryIndex]),
                rect: rect,
                selected: this.tb.selectedItem.type === 'plotItem' && this.tb.selectedItem.categoryIndex === this.categoryIndex && (this.tb.options.tooltips.shared || this.tb.selectedItem.series === this.renderer.series[this.seriesIndex])
            };

            this.nextValue();

        }
        return ret;
    }
}

<commit_msg>remove unused variables<commit_after>'use strict';
import {Rect} from './helpers/rect';
import * as Utils from './helpers/utils.js';
import {Colour} from './helpers/colour';
import * as renderer from './renderer.base';
import * as constants from './constants';
import {Tayberry} from './base';

export class BarRenderer extends renderer.Renderer {
    constructor(ctx, tayberry, series) {
        super(ctx, tayberry, series);

        this.barPositions = null;

        this.tb.registerCallback('onResize', this.updateBarWidths.bind(this));
        this.tb.registerCallback('onInit', this.updateBarWidths.bind(this));
    }

    updateBarWidths() {
        const categoryCount = this.series[0].data.length;
        const isStacked = this.tb.options.barPlot.mode === 'stacked';
        const isOverlaid = this.tb.options.barPlot.mode === 'overlaid';
        const isNormal = !isStacked && !isOverlaid;
        const seriesCount = this.series.length;
        const plotArea = this.tb.options.swapAxes ? this.tb.plotArea.clone().swapXY() : this.tb.plotArea;
        const categoryWidth = (plotArea.width / categoryCount);
        let totalMultiplier = 0;

        for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {
            const series = this.series[seriesIndex];
            const rState = series.rState;
            if (series.animationState) {
                if (!series.animationState.subtype) {
                    const visibleSeriesCount = this.getVisibleSeriesCount(seriesIndex);
                    if (isNormal && visibleSeriesCount > 0) {
                        series.animationState.subtype = 'width';
                    } else if (isStacked  && visibleSeriesCount > 0) {
                        series.animationState.subtype = 'height';
                    } else {
                        series.animationState.subtype = 'fade';
                    }

                    rState.colour = series.colour;
                }

                const isShow = series.animationState.type === 'show';
                if (series.animationState.subtype === 'width') {
                    rState.multiplier = isShow ? series.animationState.stage : 1 - series.animationState.stage;
                    rState.yMultiplier = 1;
                } else if (series.animationState.subtype === 'height') {
                    rState.yMultiplier = isShow ? series.animationState.stage : 1 - series.animationState.stage;
                    rState.multiplier = 1;
                } else {
                    let transColour = new Colour(series.colour);
                    transColour.a = 0;
                    if (isShow)
                        rState.colour = Colour.createFromBlend(transColour, new Colour(series.colour), series.animationState.stage).toString();
                    else
                        rState.colour = Colour.createFromBlend(new Colour(series.colour), transColour, series.animationState.stage).toString();

                    rState.yMultiplier = 1;
                    rState.multiplier = 1;
                }
            } else if (series.visible & constants.visibilityState.visible) {
                rState.multiplier = 1;
                rState.yMultiplier = 1;
            } else {
                rState.multiplier = 0;
                rState.yMultiplier = 0;
            }
            totalMultiplier += rState.multiplier;
        }

        const totalBarsPerCategory = (isStacked || isOverlaid) ? 1 : totalMultiplier;
        const yOrigin = this.series[0].yAxis.getOrigin();

        this.barPositions = [];

        for (let categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {
            let yBottomPositive = yOrigin;
            let yBottomNegative = yOrigin;
            let yRunningTotalPositive = 0;
            let yRunningTotalNegative = 0;

            const categoryXStart = plotArea.left + Math.floor(categoryIndex * categoryWidth);
            const categoryXEnd = plotArea.left + Math.floor((categoryIndex + 1) * categoryWidth);
            // FIXME: Need to map this.tb.options.barPlot.categorySpacing
            const barXStart = categoryXStart + Math.ceil(categoryWidth * this.tb.options.barPlot.categorySpacing / 2);
            const barXEnd = categoryXEnd - Math.floor(categoryWidth * this.tb.options.barPlot.categorySpacing / 2);

            let categoryPositions = [];

            let runningBarWidth = 0;

            for (let seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {
                const series = this.series[seriesIndex];
                const rState = series.rState;
                const value = Tayberry.getDataValue(series.data[categoryIndex])*rState.yMultiplier;

                let barWidth = Math.floor(rState.multiplier * Math.floor((barXEnd - barXStart) / totalBarsPerCategory));

                const xStart = Math.floor(barXStart + runningBarWidth) + Math.ceil(series.xAxis.mapLogicalXOrYUnit(this.tb.options.barPlot.barPadding) / 2);
                const xEnd = Math.ceil(barXStart + runningBarWidth + barWidth) - Math.floor(series.xAxis.mapLogicalXOrYUnit(this.tb.options.barPlot.barPadding) / 2);
                const yTop = series.yAxis.getValueDisplacement(value + (value > 0 ? yRunningTotalPositive : yRunningTotalNegative));
                const yBottom = isStacked ? (value > 0 ? yBottomPositive : yBottomNegative) : yOrigin;

                categoryPositions.push([xStart, yTop, xEnd, yBottom]);

                if (isStacked) {
                    if (value > 0) {
                        yRunningTotalPositive += value;
                        yBottomPositive = yTop;
                    } else {
                        yRunningTotalNegative += value;
                        yBottomNegative = yTop;
                    }
                } else if (isNormal) {
                    runningBarWidth += barWidth;
                }

            }

            this.barPositions.push(categoryPositions);
        }
    }

    onToggleSeriesAnimationFrame() {
        this.updateBarWidths();
    }

    drawPlot() {
        this.ctx.save();
        let barEnumerator = new BarEnumerator(this);
        let bar;
        while ((bar = barEnumerator.next())) {
            if (bar.series.visible & (constants.visibilityState.visible | constants.visibilityState.transitioning)) {
                this.ctx.fillStyle = bar.selected ? bar.series.rState.highlightColour : bar.series.rState.colour;
                this.ctx.fillRect(bar.rect.left, bar.rect.top, bar.rect.width, bar.rect.height);
            }
        }
        this.ctx.restore();
    }

    drawLabels() {
        if (this.tb.options.labels.enabled) {
            this.ctx.save();
            let barEnumerator = new BarEnumerator(this);
            let bar;
            while ((bar = barEnumerator.next())) {
                if ((bar.series.visible & (constants.visibilityState.visible | constants.visibilityState.transitioning)) === constants.visibilityState.visible) {
                    this.ctx.font = this.tb.labelFont;
                    this.ctx.fillStyle = this.tb.options.labels.font.colour;
                    this.drawLabel(bar.value, bar.series.yAxis.options.labelFormatter(bar.value), bar.rect);
                }
            }
            this.ctx.restore();
        }
    }

    hitTest(x, y) {
        // TODO: Optimise
        let ret = {
            found: false,
            plotType: 'bar',
            type: 'plotItem',
            isXRange: true
        };

        const categoryCount = this.series[0].data.length;
        const isHorizontal = this.tb.options.swapAxes;
        let plotArea = this.tb.plotArea.clone();
        if (isHorizontal)
            plotArea.swapXY();
        const categoryIndex = Math.floor(categoryCount * ((isHorizontal ? y : x) - plotArea.left) / plotArea.width);

        let matches = [];

        let barEnumerator = new BarEnumerator(this, categoryIndex);
        let bar;
        while ((bar = barEnumerator.next())) {
            if (bar.categoryIndex > categoryIndex)
                break;
            if (!(bar.series.visible & (constants.visibilityState.visible | constants.visibilityState.transitioning)))
                continue;

            let sortDistance, priority, realDistance;
            if (bar.rect.containsPoint(x, y)) {
                sortDistance = 0;
                priority = 0;
            }
            else if (bar.rect.containsX(x)) {
                sortDistance = y < bar.rect.top ? bar.rect.top - y : y - bar.rect.bottom;
                priority = isHorizontal ? 2 : 1;
            }
            else if (bar.rect.containsY(y)) {
                sortDistance = x < bar.rect.left ? bar.rect.left - x : x - bar.rect.right;
                priority = isHorizontal ? 1 : 2;
            }
            else {
                const xDist = Math.min(Math.abs(x - bar.rect.left), Math.abs(x - bar.rect.right));
                const yDist = Math.min(Math.abs(y - bar.rect.top), Math.abs(y - bar.rect.bottom));
                realDistance = Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
                sortDistance = isHorizontal ? yDist : xDist;
                priority = 3;
            }

            if (typeof realDistance === 'undefined')
                realDistance = sortDistance;

            if (!Utils.isMissingValue(realDistance)) {
                matches.push({
                    sortDistance: sortDistance,
                    distance: realDistance,
                    priority: priority,
                    data: {
                        categoryIndex: bar.categoryIndex,
                        seriesIndex: bar.seriesIndex,
                        rect: bar.rect,
                        series: bar.series,
                        value: Tayberry.getDataValue(this.series[bar.seriesIndex].data[bar.categoryIndex])
                    }
                });
            }
        }

        if (matches.length) {
            matches.sort((a, b) => {
                let ret = a.priority - b.priority;
                if (!ret) ret = a.sortDistance - b.sortDistance;
                if (!ret) ret = a.distance - b.distance;
                if (!ret) ret = a.data.rect.height - b.data.rect.height;
                return ret;
            });
            ret.found = true;
            ret.normalisedDistance = matches[0].distance + Math.sqrt(matches[0].data.rect.area);
            if (ret.normalisedDistance < 0) {
                ret.normalisedDistance = 0;
            }
            ret = Utils.assign(ret, matches[0].data);
        }
        return ret;
    }
}

export class BarEnumerator extends renderer.ByCategoryEnumerator {
    next() {
        let ret;

        if (this.categoryIndex < this.categoryCount) {
            const [xStart, yTop, xEnd, yBottom] = this.renderer.barPositions[this.categoryIndex][this.seriesIndex];

            let rect = new Rect(xStart, yTop, xEnd, yBottom);

            if (rect.right < rect.left)
                rect.right = rect.left;
            if (this.isHorizontal)
                rect.swapXY();
            rect.clip(this.tb.plotArea);

            ret = {
                seriesIndex: this.seriesIndex,
                categoryIndex: this.categoryIndex,
                series: this.renderer.series[this.seriesIndex],
                value: Tayberry.getDataValue(this.renderer.series[this.seriesIndex].data[this.categoryIndex]),
                rect: rect,
                selected: this.tb.selectedItem.type === 'plotItem' && this.tb.selectedItem.categoryIndex === this.categoryIndex && (this.tb.options.tooltips.shared || this.tb.selectedItem.series === this.renderer.series[this.seriesIndex])
            };

            this.nextValue();

        }
        return ret;
    }
}

<|endoftext|>


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

var util = require('util');
var AggregateFunction = require('./eep.aggregate_function').AggregateFunction;

// Count all the things
function CountFunction() {
  var self = this, n;
  self.name = "count";
  self.init = function() { n = 0; };
  self.accumulate = function(ignored) { n += 1; };
  self.compensate = function(ignored) { n -= 1; };
  self.emit = function()  { return n; };
  self.make = function() { return new CountFunction(); };
}
util.inherits(CountFunction, AggregateFunction);

// Sum all the things
function SumFunction() {
  var self = this, s;
  self.name = "sum";
  self.init = function() { s = 0; };
  self.accumulate = function(v) { s += v; };
  self.compensate = function(v) { s += v; };
  self.emit = function()  { return s; };
  self.make = function() { return new SumFunction(); };
}
util.inherits(SumFunction, AggregateFunction);

// Get the smallest of all the things
function MinFunction() {
  var self = this, r;
  self.name = "min";
  self.init = function() { r = null; };
  self.accumulate = function(v) { if (v == null) { return; } if (r == null) { r = v; return; } r = (v < r) ? v : r; };
  self.compensate = function(v) { if (v == null) { return; } if (v != null) { return; } else  r = (v < r) ? r : v; };
  self.emit = function()  { return r; };
  self.make = function() { return new MinFunction(); };
}
util.inherits(MinFunction, AggregateFunction);

// Get the biggest of all the things
function MaxFunction() {
  var self = this, r;
  self.name = "max";
  self.init = function() { r = null; };
  self.accumulate = function(v) { if (v == null) { return; } if (r == null) { r = v; return; } r = (v > r) ? v : r; };
  self.compensate = function(v) { if (v == null) { return; } if (v != null) { return; } else  r = (v > r) ? r : v; };
  self.emit = function()  { return r; };
  self.make = function() { return new MaxFunction(); };
}
util.inherits(MaxFunction, AggregateFunction);

// Get the average of all the things
function MeanFunction() {
  var self = this, m, d, n;
  self.name = "mean";
  self.init = function() { m = 0; d = 0; n = 0; };
  self.accumulate = function(v) { n+=1; d = v - m; m = (d)/n + m; };
  self.compensate = function(v) { n-=1; d = v + m; m = (v - m)/n - m; };
  self.emit = function()  { return m; };
  self.make = function() { return new MeanFunction(); };
}
util.inherits(MeanFunction, AggregateFunction);

// Get the sample variance of all the things
function VarianceFunction() {
  var self = this, m, m2, d, n;
  self.name = "vars";
  self.init = function() { m = 0; m2 = 0; d = 0; n = 0; };
  self.accumulate = function(v) { n+=1; d = v - m; m = d/n + m; m2 = m2 + d*(v - m); };
  self.compensate = function(v) { n-=1; d = v + m; var dp = v - m; m = (dp)/n - m; m2 = m2 - d*dp; };
  self.emit = function()  { return m2/(n-1); };
  self.make = function() { return new VarianceFunction(); };
}
util.inherits(VarianceFunction, AggregateFunction);

// Get the standard deviation of all the things
function StdevFunction() {
  var self = this, m, m2, d, n;
  self.name = "stdevs";
  self.init = function() { m = 0, m2 = 0, d = 0, n = 0; };
  self.accumulate = function(v) {
    n+=1;
    d = v - m;
    m = m + d/n;
    m2 = m2 + d*(v-m);
  };
  self.compensate = function(v) {
    n-=1;
    d = v + m;
    m = m - d/n;
    m2 = m2 - d*(v-m);
  };
  self.emit = function()  { return Math.sqrt(m2/(n-1)); };
  self.make = function() { return new StdevFunction(); };
}
util.inherits(StdevFunction, AggregateFunction);

// Get the kurtosis of all the things
function KurtosisFunction() {
  var self = this, m = 0, m4 = 0, m3 = 0, m2 = 0, d = 0, n = 0;
  self.name = "kurtosis";
  self.init = function() { };
  self.accumulate = function(v) {
    var o = n;
    n+=1;
    d = v - m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn * o;
    m = m + dn;
    m4 = m4 + t1 * dn2 * (n*n - 3*n + 3) + 6 * dn2 * m2 - 4 * dn * m3;
    m3 = m3 + t1 * dn * (n - 2) - 3 * dn * m2;
    m2 = m2 + t1;
  };
  self.compensate = function(v) {
    var o = n;
    n-=1;
    d = v + m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn * o;
    m = m - dn;
    m4 = m4 - t1 * dn2 * (n*n - 3*n + 3) - 6 * dn2 * m2 + 4 * dn * m3;
    m3 = m3 - t1 * dn * (n - 2) + 3 * dn * m2;
    m2 = m2 - t1;
  };
  self.emit = function()  { return (n*m4)/(m2*m2) - 3; };
  self.make = function() { return new KurtosisFunction(); };
}
util.inherits(KurtosisFunction, AggregateFunction);

function AllStatsFunction() {
  var self = this, m, m4, m3, m3, d, n, s, min, max;
  self.name = "kurtosis";
  self.init = function() {
    m = 0, m4 = 0, m3 = 0, m2 = 0, d = 0, n = 0, s = 0, min = null, max = null;
  };
  self.accumulate = function(v) {
    if (v == null) return;
    var o = n;
    s+=v;
    if (v != null) { if (min == null) { min = v; } else { min = (v < min) ? v : min; } };
    if (v != null) { if (max == null) { max = v; } else { max = (v > max) ? v : max; } };
    n+=1;
    d = v - m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn *  o;
    m = m + dn;
    m4 = m4 + t1 * dn2 * (n*n - 3*n + 3) + 6 * dn2 * m2 - 4 * dn * m3;
    m3 = m3 + t1 * dn * (n - 2) - 3 * dn * m2;
    m2 = m2 + t1;
  };
  self.compensate = function(v) {
    if (v == null) return;
    var o = n;
    s-=v;
    if (v == null) { return; } if (v != null) { return; } else  min = (v < min) ? min : v;
    if (v == null) { return; } if (v != null) { return; } else  max = (v < max) ? max : v;
    n-=1;
    d = v + m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn *  o;
    m = m - dn;
    m4 = m4 - t1 * dn2 * (n*n - 3*n + 3) - 6 * dn2 * m2 + 4 * dn * m3;
    m3 = m3 - t1 * dn * (n - 2) + 3 * dn * m2;
    m2 = m2 - t1;
  };
  self.emit = function()  {
    var variance = m2/(n-1);
    return results = {
      count: n,
      sum: s,
      min: min,
      max: max,
      mean: m,
      vars: variance,
      stdevs:  Math.sqrt(variance),
      kurtosis: (n*m4)/(m2*m2) - 3
    };
  };
  self.make = function() { return new AllStatsFunction(); };
}
util.inherits(AllStatsFunction, AggregateFunction);

// eep.js Statistics package
var Stats = function() {};

// Register statistics aggregate functions
Stats.count = new CountFunction();
Stats.sum = new SumFunction();
Stats.min = new MinFunction();
Stats.max = new MaxFunction();
Stats.mean = new MeanFunction();
Stats.vars = new VarianceFunction();
Stats.stdevs = new StdevFunction();
Stats.kurtosis = new KurtosisFunction();
Stats.all = new AllStatsFunction();

// Export the Statistics package
module.exports.Stats = Stats;
<commit_msg>Sliding windows now O(n) performance. Numerically stable Mean, Vars. Aggregate Function API change.<commit_after>// Copyright (c) Darach Ennis < darach at gmail dot com >.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var util = require('util');
var AggregateFunction = require('./eep.aggregate_function').AggregateFunction;

// Count all the things
function CountFunction() {
  var self = this, n;
  self.name = "count";
  self.init = function() { n = 0; };
  self.accumulate = function(ignored) { n += 1; };
  self.compensate = function(ignored) { n -= 1; };
  self.emit = function()  { return n; };
  self.make = function() { return new CountFunction(); };
}
util.inherits(CountFunction, AggregateFunction);

// Sum all the things
function SumFunction() {
  var self = this, s;
  self.name = "sum";
  self.init = function() { s = 0; };
  self.accumulate = function(v) { s += v; };
  self.compensate = function(v) { s -= v; };
  self.emit = function()  { return s; };
  self.make = function() { return new SumFunction(); };
}
util.inherits(SumFunction, AggregateFunction);

// Get the smallest of all the things
function MinFunction() {
  var self = this, r;
  self.name = "min";
  self.init = function() { r = null; };
  self.accumulate = function(v) { if (v == null) { return; } if (r == null) { r = v; return; } r = (v < r) ? v : r; };
  self.compensate = function(v) { if (v == null) { return; } if (v != null) { return; } else  r = (v < r) ? r : v; };
  self.emit = function()  { return r; };
  self.make = function() { return new MinFunction(); };
}
util.inherits(MinFunction, AggregateFunction);

// Get the biggest of all the things
function MaxFunction() {
  var self = this, r;
  self.name = "max";
  self.init = function() { r = null; };
  self.accumulate = function(v) { if (v == null) { return; } if (r == null) { r = v; return; } r = (v > r) ? v : r; };
  self.compensate = function(v) { if (v == null) { return; } if (v != null) { return; } else  r = (v > r) ? r : v; };
  self.emit = function()  { return r; };
  self.make = function() { return new MaxFunction(); };
}
util.inherits(MaxFunction, AggregateFunction);

// Get the average of all the things
function MeanFunction() {
  var self = this, m, d, n;
  self.name = "mean";
  self.init = function() { m = 0; d = 0; n = 0; };
  self.accumulate = function(v) { n+=1; d = v - m; m = (d)/n + m; };
  self.compensate = function(v) { n-=1; d = v + m; m = (v - m)/n - m; };
  self.emit = function()  { return m; };
  self.make = function() { return new MeanFunction(); };
}
util.inherits(MeanFunction, AggregateFunction);

// Get the sample variance of all the things
function VarianceFunction() {
  var self = this, m, m2, d, n;
  self.name = "vars";
  self.init = function() { m = 0; m2 = 0; d = 0; n = 0; };
  self.accumulate = function(v) { n+=1; d = v - m; m = d/n + m; m2 = m2 + d*(v - m); };
  self.compensate = function(v) { n-=1; d = v + m; var dp = v - m; m = (dp)/n - m; m2 = m2 - d*dp; };
  self.emit = function()  { return m2/(n-1); };
  self.make = function() { return new VarianceFunction(); };
}
util.inherits(VarianceFunction, AggregateFunction);

// Get the standard deviation of all the things
function StdevFunction() {
  var self = this, m, m2, d, n;
  self.name = "stdevs";
  self.init = function() { m = 0, m2 = 0, d = 0, n = 0; };
  self.accumulate = function(v) {
    n+=1;
    d = v - m;
    m = m + d/n;
    m2 = m2 + d*(v-m);
  };
  self.compensate = function(v) {
    n-=1;
    d = v + m;
    m = m - d/n;
    m2 = m2 - d*(v-m);
  };
  self.emit = function()  { return Math.sqrt(m2/(n-1)); };
  self.make = function() { return new StdevFunction(); };
}
util.inherits(StdevFunction, AggregateFunction);

// Get the kurtosis of all the things
function KurtosisFunction() {
  var self = this, m = 0, m4 = 0, m3 = 0, m2 = 0, d = 0, n = 0;
  self.name = "kurtosis";
  self.init = function() { };
  self.accumulate = function(v) {
    var o = n;
    n+=1;
    d = v - m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn * o;
    m = m + dn;
    m4 = m4 + t1 * dn2 * (n*n - 3*n + 3) + 6 * dn2 * m2 - 4 * dn * m3;
    m3 = m3 + t1 * dn * (n - 2) - 3 * dn * m2;
    m2 = m2 + t1;
  };
  self.compensate = function(v) {
    var o = n;
    n-=1;
    d = v + m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn * o;
    m = m - dn;
    m4 = m4 - t1 * dn2 * (n*n - 3*n + 3) - 6 * dn2 * m2 + 4 * dn * m3;
    m3 = m3 - t1 * dn * (n - 2) + 3 * dn * m2;
    m2 = m2 - t1;
  };
  self.emit = function()  { return (n*m4)/(m2*m2) - 3; };
  self.make = function() { return new KurtosisFunction(); };
}
util.inherits(KurtosisFunction, AggregateFunction);

function AllStatsFunction() {
  var self = this, m, m4, m3, m3, d, n, s, min, max;
  self.name = "kurtosis";
  self.init = function() {
    m = 0, m4 = 0, m3 = 0, m2 = 0, d = 0, n = 0, s = 0, min = null, max = null;
  };
  self.accumulate = function(v) {
    if (v == null) return;
    var o = n;
    s+=v;
    if (v != null) { if (min == null) { min = v; } else { min = (v < min) ? v : min; } };
    if (v != null) { if (max == null) { max = v; } else { max = (v > max) ? v : max; } };
    n+=1;
    d = v - m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn *  o;
    m = m + dn;
    m4 = m4 + t1 * dn2 * (n*n - 3*n + 3) + 6 * dn2 * m2 - 4 * dn * m3;
    m3 = m3 + t1 * dn * (n - 2) - 3 * dn * m2;
    m2 = m2 + t1;
  };
  self.compensate = function(v) {
    if (v == null) return;
    var o = n;
    s-=v;
    if (v == null) { return; } if (v != null) { return; } else  min = (v < min) ? min : v;
    if (v == null) { return; } if (v != null) { return; } else  max = (v < max) ? max : v;
    n-=1;
    d = v + m;
    var dn = d / n, dn2 = dn * dn, t1 = d * dn *  o;
    m = m - dn;
    m4 = m4 - t1 * dn2 * (n*n - 3*n + 3) - 6 * dn2 * m2 + 4 * dn * m3;
    m3 = m3 - t1 * dn * (n - 2) + 3 * dn * m2;
    m2 = m2 - t1;
  };
  self.emit = function()  {
    var variance = m2/(n-1);
    return results = {
      count: n,
      sum: s,
      min: min,
      max: max,
      mean: m,
      vars: variance,
      stdevs:  Math.sqrt(variance),
      kurtosis: (n*m4)/(m2*m2) - 3
    };
  };
  self.make = function() { return new AllStatsFunction(); };
}
util.inherits(AllStatsFunction, AggregateFunction);

// eep.js Statistics package
var Stats = function() {};

// Register statistics aggregate functions
Stats.count = new CountFunction();
Stats.sum = new SumFunction();
Stats.min = new MinFunction();
Stats.max = new MaxFunction();
Stats.mean = new MeanFunction();
Stats.vars = new VarianceFunction();
Stats.stdevs = new StdevFunction();
Stats.kurtosis = new KurtosisFunction();
Stats.all = new AllStatsFunction();

// Export the Statistics package
module.exports.Stats = Stats;
<|endoftext|>


<commit_before>'use strict';

var L            = require('../vendor/leaflet.js')
var EventEmitter = require('events').EventEmitter
var mapTileLayer = require('./tilelayer')
var mediator     = require('../lib/mediator')

L.Icon.Default.imagePath = 'http://cdn.leafletjs.com/leaflet-0.7/images'

class Map extends EventEmitter {

  /**
   * Creates a map with given config
   */
  constructor(config) {
    this.map           = L.map(config.domElementId, config.mapOptions).fitBounds(config.bounds)
    this.tileLayers    = {}
    this.geojsonLayers = {}
    this.map.on('click', (event) => this.emit('click', event))
    this.mediator      = mediator()
  }

  /**
   * Adds a tile layer to the map with given config
   */
  setTileLayer(name, config) {
    this.tileLayers[name] = mapTileLayer(config.url, config)
    this.tileLayers[name].addTo(this.map)
  }

  removeTileLayer(name) {
    this.tileLayers[name].removeFrom(this.map)
  }

  /**
   * Add a geojson layer to the map with given config
   */
  setGeojsonLayer(name, config) {
    var options = {}
    var map = this
    if (config.style)
      options.style = (feature) => config.style(feature.properties)
    if (config.listens) {
      config.listens.forEach(function (listenerConfig) {
        map.mediator.register(listenerConfig)
      })
    }
    if (config.popup || config.notifies) {
      options.onEachFeature = (feature, layer) => {
        if (!config.popupFilter || config.popupFilter(feature)) {

          // don't bind the feature popup if it isn't defined in config
          if (typeof config.popup(feature.properties) !== 'undefined') {
            layer.bindPopup(config.popup(feature.properties))
          }
        }

        if (config.notifies) {
          config.notifies.forEach(function (eventType) {
            layer.on(eventType, () => map.mediator.notify(eventType, name, feature, map))
          })
        }
      }
    }
    if (config.icon)
      options.pointToLayer = (feature, latLng) => L.marker(latLng, { icon: L.icon(config.icon(feature.properties)) })
    if (config.filter)
      options.filter = (feature) => config.filter(feature)

    if (this.geojsonLayers[name]) {
      this.geojsonLayers[name].removeFrom(this.map)
      delete this.geojsonLayers[name]
    }

    this.geojsonLayers[name] = L.geoJson(config.geojson, options)
  }

  showGeojsonLayer(name) {
    this.geojsonLayers[name].addTo(this.map)
  }

  hideGeojsonLayer(name) {
    this.geojsonLayers[name].removeFrom(this.map)
  }
}

module.exports = function (config) {
  return new Map(config)
}
<commit_msg>Refactor to es6 style function declarations<commit_after>'use strict';

var L            = require('../vendor/leaflet.js')
var EventEmitter = require('events').EventEmitter
var mapTileLayer = require('./tilelayer')
var mediator     = require('../lib/mediator')

L.Icon.Default.imagePath = 'http://cdn.leafletjs.com/leaflet-0.7/images'

class Map extends EventEmitter {

  /**
   * Creates a map with given config
   */
  constructor(config) {
    this.map           = L.map(config.domElementId, config.mapOptions).fitBounds(config.bounds)
    this.tileLayers    = {}
    this.geojsonLayers = {}
    this.map.on('click', (event) => this.emit('click', event))
    this.mediator      = mediator()
  }

  /**
   * Adds a tile layer to the map with given config
   */
  setTileLayer(name, config) {
    this.tileLayers[name] = mapTileLayer(config.url, config)
    this.tileLayers[name].addTo(this.map)
  }

  removeTileLayer(name) {
    this.tileLayers[name].removeFrom(this.map)
  }

  /**
   * Add a geojson layer to the map with given config
   */
  setGeojsonLayer(name, config) {
    var options = {}
    var map = this
    if (config.style)
      options.style = (feature) => config.style(feature.properties)
    if (config.listens) {
      config.listens.forEach((listenerConfig) => {
        map.mediator.register(listenerConfig)
      })
    }
    if (config.popup || config.notifies) {
      options.onEachFeature = (feature, layer) => {
        if (!config.popupFilter || config.popupFilter(feature)) {

          // don't bind the feature popup if it isn't defined in config
          if (typeof config.popup(feature.properties) !== 'undefined') {
            layer.bindPopup(config.popup(feature.properties))
          }
        }

        if (config.notifies) {
          config.notifies.forEach((eventType) => {
            layer.on(eventType, () => map.mediator.notify(eventType, name, feature, map))
          })
        }
      }
    }
    if (config.icon)
      options.pointToLayer = (feature, latLng) => L.marker(latLng, { icon: L.icon(config.icon(feature.properties)) })
    if (config.filter)
      options.filter = (feature) => config.filter(feature)

    if (this.geojsonLayers[name]) {
      this.geojsonLayers[name].removeFrom(this.map)
      delete this.geojsonLayers[name]
    }

    this.geojsonLayers[name] = L.geoJson(config.geojson, options)
  }

  showGeojsonLayer(name) {
    this.geojsonLayers[name].addTo(this.map)
  }

  hideGeojsonLayer(name) {
    this.geojsonLayers[name].removeFrom(this.map)
  }
}

module.exports = function (config) {
  return new Map(config)
}
<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import App from '../components/App';

// Child routes
import home from './home';
import userPage from './user';
import serverList from './serverList';
import server from './server';
import permissions from './permissions';
import login from './login';
import music from './music';
import content from './content';
import error from './error';

export default {

  path: '/',

  children: [
    login,
    home,
    userPage,
    server,
    serverList,
    permissions,
    music,
    content,
    error,
  ],

  async action({ next, render, context, user }) {
    const component = await next();
    if (component === undefined) return component;
    const userContext = context;
    userContext.user = user;
    return render(
      <App context={userContext} user={user} >{component}</App>
    );
  },

};
<commit_msg>If the component returns an error don't try to render it into the app.<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import App from '../components/App';

// Child routes
import home from './home';
import userPage from './user';
import serverList from './serverList';
import server from './server';
import permissions from './permissions';
import login from './login';
import music from './music';
import content from './content';
import error from './error';

export default {

  path: '/',

  children: [
    login,
    home,
    userPage,
    server,
    serverList,
    permissions,
    music,
    content,
    error,
  ],

  async action({ next, render, context, user }) {
    const component = await next();
    if (component === undefined) return component;
    if (component instanceof Error) return component;
    const userContext = context;
    userContext.user = user;
    return render(
      <App context={userContext} user={user} >{component}</App>
    );
  },

};
<|endoftext|>


<commit_before>var hash = location.hash.split('/'),
    API_HOST = 'http://' + window.location.hostname + ':5000/',
    API_BASE = API_HOST,
    REPO;

if (hash.length > 1) {
    REPO = hash[1] + '/' + hash[2];
    API_BASE += hash[1] + '/' + hash[2];
    initDashboard();
} else {
    getDefaultRepo();
}

/*
 * Bundle together different functions
 * used to load the widgets in the application
 */
function initDashboard () {
    populateOpenIssues();
    populateOpenPulls();
    populateTimeline();
    $('#user-repo').html(function(index, html) {
      return REPO + html;
    });
    changeTabs();
}

/*
 * According to URL path
 * navigate to different tabs in the application
 */
function changeTabs() {

    var href = location.href.split('/');
    if (href.length > 6) {
        var tab = href.pop();
        var tabs = $('ul.menu li');
        tabs.each(function (idx, el) {
            var text = $(el).text().toLowerCase();
            if (text == tab) {
                $(el).trigger('click');
            }
        });
    }

}

function loadKibana() {
    $('#kibana-iframe').attr('src', 'kibana-latest/index.html');
}

function fitTabContainer () {
    var $container = $('#tab-container');
    $container.height($(window).height() - $container.offset().top - 20);
}

window.onresize = fitTabContainer;
fitTabContainer();

$('#repo-select-trigger').on('click', function (e) {
    e.stopPropagation();

    var $container = $('.repo-select');
    var $repoList = $('ul', $container);

    $container.toggleClass('hidden');

    if (!$container.hasClass('hidden')) {
        getAvailableRepos(addRepos);
        $(window).on('click', function () {
            $('.show--fade-in').removeClass('show--fade-in');
            setTimeout(function () {
                $repoList.empty();
            }, 200);
            $(window).off('click');
            $container.toggleClass('hidden');
        })
    } else {
        $('.show--fade-in').removeClass('show--fade-in');
        setTimeout(function () {
            $repoList.empty();
        }, 200);
    }
});

function getAvailableRepos (cb) {
    $.get(API_HOST + 'available_repos')
        .success(cb)
    .fail(function (data) {
        console.log('An error has occured');
    });
}

function addRepos (data) {
    var $container = $('.repo-select');

    var $repoList = $('ul', $container);
    data.data.forEach(function (repo) {
        var repoLink = document.createElement('a');
        var repoLI = document.createElement('li');
        repoLink.href = location.origin + '/#/' + repo;
        repoLink.textContent = repo;
        repoLink.target = '_blank';
        repoLI.appendChild(repoLink);
        repoLI = $(repoLI);
        repoLI.on('click', function (e) {
            e.preventDefault();
            loadDashboard(repoLink.href);
        });
        $repoList.append(repoLI);
    });

    $repoList.toggleClass('show--fade-in');
}

function getDefaultRepo() {
    getAvailableRepos(function (data) {
        setLocation(location.origin + '/#/' + data.data[0]); // load first repo
        hash = data.data[0].split('/');
        REPO = hash[0] + '/' + hash[1];
        API_BASE += hash[0] + '/' + hash[1];
        initDashboard();
    });
}

function setLocation (newlocation) {
    location.href = newlocation;
}

function loadDashboard (newlocation) {
    setLocation(newlocation);
    location.reload();
}

function populateOpenIssues() {
    $.get(API_BASE + "/issues_count").success(function (data) {
        var count = data.data.open;
        $('#open-issues-count').text(count);

        if (!count) {
            return;
        }

        var $p = $('#open-issues');
        $p.click(function () {
            var url = 'http://github.com/' + REPO + '/issues?state=open';
            window.location.href = url;
        });
        $p.addClass('clickable');
    });
}

function populateOpenPulls() {
    $.get(API_BASE + "/pulls_count").success(function (data) {
        var count = data.data.open;
        $('#open-pulls-count').text(count);

        if (!count) {
            return;
        }

        var $p = $('#open-pulls');
        $p.click(function () {
            var url = 'http://github.com/' + REPO + '/pulls?state=open';
            window.location.href = url;
        });
        $p.addClass('clickable');
    });
}

function logFailure(fail) {
    console.log("Trouble getting data. API server down?");
    console.log(fail);
}
<commit_msg>make repo switching work for arbitrary pathnames<commit_after>var hash = location.hash.split('/'),
    API_HOST = 'http://' + window.location.hostname + ':5000/',
    API_BASE = API_HOST,
    REPO;

if (hash.length > 1) {
    REPO = hash[1] + '/' + hash[2];
    API_BASE += hash[1] + '/' + hash[2];
    initDashboard();
} else {
    getDefaultRepo();
}

/*
 * Bundle together different functions
 * used to load the widgets in the application
 */
function initDashboard () {
    populateOpenIssues();
    populateOpenPulls();
    populateTimeline();
    $('#user-repo').html(function(index, html) {
      return REPO + html;
    });
    changeTabs();
}

/*
 * According to URL path
 * navigate to different tabs in the application
 */
function changeTabs() {

    var href = location.href.split('/');
    if (href.length > 6) {
        var tab = href.pop();
        var tabs = $('ul.menu li');
        tabs.each(function (idx, el) {
            var text = $(el).text().toLowerCase();
            if (text == tab) {
                $(el).trigger('click');
            }
        });
    }

}

function loadKibana() {
    $('#kibana-iframe').attr('src', 'kibana-latest/index.html');
}

function fitTabContainer () {
    var $container = $('#tab-container');
    $container.height($(window).height() - $container.offset().top - 20);
}

window.onresize = fitTabContainer;
fitTabContainer();

$('#repo-select-trigger').on('click', function (e) {
    e.stopPropagation();

    var $container = $('.repo-select');
    var $repoList = $('ul', $container);

    $container.toggleClass('hidden');

    if (!$container.hasClass('hidden')) {
        getAvailableRepos(addRepos);
        $(window).on('click', function () {
            $('.show--fade-in').removeClass('show--fade-in');
            setTimeout(function () {
                $repoList.empty();
            }, 200);
            $(window).off('click');
            $container.toggleClass('hidden');
        })
    } else {
        $('.show--fade-in').removeClass('show--fade-in');
        setTimeout(function () {
            $repoList.empty();
        }, 200);
    }
});

function getAvailableRepos (cb) {
    $.get(API_HOST + 'available_repos')
        .success(cb)
    .fail(function (data) {
        console.log('An error has occured');
    });
}

function addRepos (data) {
    var $container = $('.repo-select');

    var $repoList = $('ul', $container);
    data.data.forEach(function (repo) {
        var repoLink = document.createElement('a');
        var repoLI = document.createElement('li');
        repoLink.href = location.origin + location.pathname + '#/' + repo;
        repoLink.textContent = repo;
        repoLink.target = '_blank';
        repoLI.appendChild(repoLink);
        repoLI = $(repoLI);
        repoLI.on('click', function (e) {
            e.preventDefault();
            loadDashboard(repoLink.href);
        });
        $repoList.append(repoLI);
    });

    $repoList.toggleClass('show--fade-in');
}

function getDefaultRepo() {
    getAvailableRepos(function (data) {
        setLocation(location.origin + location.pathname + '#/' + data.data[0]); // load first repo
        hash = data.data[0].split('/');
        REPO = hash[0] + '/' + hash[1];
        API_BASE += hash[0] + '/' + hash[1];
        initDashboard();
    });
}

function setLocation (newlocation) {
    location.href = newlocation;
}

function loadDashboard (newlocation) {
    setLocation(newlocation);
    location.reload();
}

function populateOpenIssues() {
    $.get(API_BASE + "/issues_count").success(function (data) {
        var count = data.data.open;
        $('#open-issues-count').text(count);

        if (!count) {
            return;
        }

        var $p = $('#open-issues');
        $p.click(function () {
            var url = 'http://github.com/' + REPO + '/issues?state=open';
            window.location.href = url;
        });
        $p.addClass('clickable');
    });
}

function populateOpenPulls() {
    $.get(API_BASE + "/pulls_count").success(function (data) {
        var count = data.data.open;
        $('#open-pulls-count').text(count);

        if (!count) {
            return;
        }

        var $p = $('#open-pulls');
        $p.click(function () {
            var url = 'http://github.com/' + REPO + '/pulls?state=open';
            window.location.href = url;
        });
        $p.addClass('clickable');
    });
}

function logFailure(fail) {
    console.log("Trouble getting data. API server down?");
    console.log(fail);
}
<|endoftext|>


<commit_before>module.exports = create_element_node

function create_element_node(el) {
  var altr_tags = {}
    , altr = this
    , attr

  var node = {
      el: el
    , update_children: this.update_children
    , hooks: []
  }

  var attrs = Array.prototype.filter.call(el.attributes, function(attr) {
    return altr.tags[attr.name] ?
      (altr_tags[attr.name] = attr.value) && false :
      true
  })

  attrs.forEach(function(attr) {
    var attr_hook = altr.template_string(attr.value, function(val) {
      el.setAttribute(attr.name, val)
    })

    if(attr_hook) {
      node.hooks.push(altr.batch.add(attr_hook))
    }
  })

  for(var i = 0, l = altr.tag_list.length; i < l; ++i) {
    attr = altr_tags[altr.tag_list[i].attr]

    if(attr) {
      altr.tag_list[i].constructor.call(altr, node, attr)
    }
  }

  node.children = [].map.call(
      el.childNodes
    , altr.create_node.bind(altr)
  ).filter(Boolean)

  if(node.children.length || node.hooks.length) {
    return node
  }
}
<commit_msg>slicing children before parsing<commit_after>module.exports = create_element_node

function create_element_node(el) {
  var altr_tags = {}
    , altr = this
    , attr

  var node = {
      el: el
    , update_children: this.update_children
    , hooks: []
  }

  var attrs = Array.prototype.filter.call(el.attributes, function(attr) {
    return altr.tags[attr.name] ?
      (altr_tags[attr.name] = attr.value) && false :
      true
  })

  attrs.forEach(function(attr) {
    var attr_hook = altr.template_string(attr.value, function(val) {
      el.setAttribute(attr.name, val)
    })

    if(attr_hook) {
      node.hooks.push(altr.batch.add(attr_hook))
    }
  })

  for(var i = 0, l = altr.tag_list.length; i < l; ++i) {
    attr = altr_tags[altr.tag_list[i].attr]

    if(attr) {
      altr.tag_list[i].constructor.call(altr, node, attr)
    }
  }

  node.children = [].map.call(
      Array.prototype.slice.call(el.childNodes)
    , altr.create_node.bind(altr)
  ).filter(Boolean)

  if(node.children.length || node.hooks.length) {
    return node
  }
}
<|endoftext|>