<commit_before>/* eslint-env mocha */
/* global expect, testContext */
/* eslint-disable prefer-arrow-callback, no-unused-expressions, max-nested-callbacks */

import factory from '../../../test/factories'
import {withDBCleanup} from '../../../test/helpers'
import {findProjects} from '../../db/project'

import {GOAL_SELECTION} from '../../../common/models/cycle'

import {formProjects, getTeamSizes, generateProjectName} from '../formProjectTeams'

const POPULAR_ISSUES = {ONE: 101, TWO: 102}
const UNPOPULAR_ISSUES = {ONE: 201, TWO: 202, THREE: 203, FOUR: 204, FIVE: 205, SIX: 206}
const ADVANCED_PLAYER_ECC = 500
const DEFAULT_RECOMMENDED_TEAM_SIZE = 5

describe(testContext(__filename), function () {
  withDBCleanup()

  describe('formProjects', function () {
    describe('10 players (2 advanced), 6 votes (2 popular)', function () {
      beforeEach(async function () {
        this.data = await _setup({
          players: {total: 10, advanced: 2},
        })
      })

      it('places all players on teams when not everyone voted', async function () {
        const {cycle, players} = this.data

        expect(players.regular.length).to.be.equal(8)
        expect(players.advanced.length).to.be.equal(2)

        await formProjects(cycle.id)

        const projects = await findProjects().run()
        const projectPlayerIds = _extractPlayerIdsFromProjects(cycle.id, projects)

        const allPlayers = players.regular.concat(players.advanced)
        expect(projectPlayerIds.length).to.equal(allPlayers.length)

        allPlayers.forEach(player => {
          const playerIdInProject = projectPlayerIds.find(playerId => playerId === player.id)
          expect(playerIdInProject).to.exist
        })
      })

      it('creates project teams that all contain at least one advanced player', async function () {
        const {cycle, players} = this.data

        await formProjects(cycle.id)

        const projects = await findProjects().run()
        const advancedPlayers = players.advanced.reduce((result, player) => {
          result[player.id] = player
          return result
        }, {})

        projects.forEach(project => {
          const playerIds = _extractPlayerIdsFromProjects(cycle.id, [project])
          const advancedPlayerId = playerIds.find(playerId => advancedPlayers[playerId])
          expect(advancedPlayerId).to.exist
        })
      })

      it('creates projects for as many goals as were voted for and can be supported by the number of available advanced players', async function () {
        const {cycle, votes, players} = this.data

        expect(votes.length).to.be.equal(6)

        await formProjects(cycle.id)

        const projects = await findProjects().run()
        const projectGoals = _extractGoalsFromProjects(projects)

        const votedForGoals = votes.reduce((result, vote) => {
          vote.goals.forEach(goal => result.set(goal.url, true))
          return result
        }, new Map())

        const maxNumExpectedProjectGoals = Math.min(votedForGoals.size, players.advanced.length)

        expect(projectGoals.length).to.be.within(1, maxNumExpectedProjectGoals)
      })

      it('creates projects for the most popular goals', async function () {
        const {cycle} = this.data

        await formProjects(cycle.id)

        const projects = await findProjects().run()
        const projectGoals = _extractGoalsFromProjects(projects)

        projectGoals.forEach(goal => {
          expect(POPULAR_ISSUES[goal.id] !== null)
        })
      })
    })
  })

  describe('getTeamSizes(recTeamSize, numPlayers)', function () {
    it('determines optimal team sizes based on recommended size and player count', function () {
      expect(getTeamSizes(4, 16)).to.deep.equal([4, 4, 4, 4])
      expect(getTeamSizes(4, 19)).to.deep.equal([4, 4, 4, 4, 3])
      expect(getTeamSizes(4, 18)).to.deep.equal([5, 5, 4, 4])
      expect(getTeamSizes(4, 17)).to.deep.equal([5, 4, 4, 4])
      expect(getTeamSizes(4, 5)).to.deep.equal([5])
      expect(getTeamSizes(4, 2)).to.deep.equal([2])
      expect(getTeamSizes(4, 6)).to.deep.equal([3, 3])
    })
  })

  describe('generateProjectName()', function () {
    it('generates a valid project name', function () {
      return generateProjectName().then(function (projectName) {
        expect(projectName).to.match(/^\w+(-\w+)+(-\d)?$/)
      })
    })
  })
})

async function _setup(options = {}) {
  // generate test cycle
  const cycle = await factory.create('cycle', {state: GOAL_SELECTION})

  // generate test players
  const numPlayers = options.players ? options.players.total : 10
  const numPlayersAdvanced = options.players ? options.players.advanced : 2
  const players = {
    regular: await _generatePlayers({chapterId: cycle.chapterId}, numPlayers - numPlayersAdvanced),
    advanced: await _generatePlayers({chapterId: cycle.chapterId, ecc: ADVANCED_PLAYER_ECC}, numPlayersAdvanced)
  }

  // generate test votes
  const votes = await _generateVotes(cycle.id, players.regular, options.votes)

  // return all test data
  return {cycle, players, votes}
}

function _generatePlayers(data, numPlayers) {
  return factory.createMany('player', data, numPlayers)
}

function _generateVotes(cycleId, players) {
  let votes = [
    [POPULAR_ISSUES.ONE, POPULAR_ISSUES.TWO],
    [POPULAR_ISSUES.ONE, UNPOPULAR_ISSUES.ONE],
    [POPULAR_ISSUES.ONE, UNPOPULAR_ISSUES.TWO],
    [POPULAR_ISSUES.TWO, UNPOPULAR_ISSUES.THREE],
    [POPULAR_ISSUES.TWO, UNPOPULAR_ISSUES.FOUR],
    [UNPOPULAR_ISSUES.FIVE, UNPOPULAR_ISSUES.SIX],
  ]

  if (!(players.length >= votes.length)) {
    throw new Error('Number of players must be greater than or equal to number of votes')
  }

  votes = votes.map((goalIssueIds, i) => ({
    cycleId,
    playerId: players[i].id,
    goals: goalIssueIds.map(goalIssueId => ({
      id: goalIssueId,
      url: `http://ex.co/${goalIssueId}`,
      title: `Goal ${goalIssueId}`,
      teamSize: DEFAULT_RECOMMENDED_TEAM_SIZE
    })),
  }))

  return factory.createMany('vote', votes, votes.length)
}

function _extractGoalsFromProjects(projects) {
  const goals = projects.reduce((result, project) => {
    result.set(project.goal.url, project.goal)
    return result
  }, new Map())

  return Array.from(goals.values())
}

function _extractPlayerIdsFromProjects(cycleId, projects) {
  const playerIds = projects.reduce((result, project) => {
    project.cycleHistory
      .find(projectCycle => projectCycle.cycleId === cycleId)
      .playerIds.forEach(playerId => result.set(playerId, playerId))
    return result
  }, new Map())

  return Array.from(playerIds.values())
}
<commit_msg>minor test refactoring to make it easy to test multiple cases<commit_after>/* eslint-env mocha */
/* global expect, testContext */
/* eslint-disable prefer-arrow-callback, no-unused-expressions, max-nested-callbacks */

import factory from '../../../test/factories'
import {withDBCleanup} from '../../../test/helpers'
import {findProjects} from '../../db/project'

import {GOAL_SELECTION} from '../../../common/models/cycle'

import {formProjects, getTeamSizes, generateProjectName} from '../formProjectTeams'

const POPULAR_ISSUES = {ONE: 101, TWO: 102, THREE: 103, FOUR: 104}
const UNPOPULAR_ISSUES = {ONE: 201, TWO: 202, THREE: 203, FOUR: 204, FIVE: 205, SIX: 206}
const ADVANCED_PLAYER_ECC = 500
const DEFAULT_RECOMMENDED_TEAM_SIZE = 5

const FOUR_VOTES_WITH_FOUR_POPULAR = [
  [POPULAR_ISSUES.ONE, POPULAR_ISSUES.TWO],
  [POPULAR_ISSUES.TWO, UNPOPULAR_ISSUES.ONE],
  [POPULAR_ISSUES.THREE, UNPOPULAR_ISSUES.TWO],
  [POPULAR_ISSUES.FOUR, UNPOPULAR_ISSUES.THREE],
]

const SIX_VOTES_WITH_TWO_POPULAR = [
  [POPULAR_ISSUES.ONE, POPULAR_ISSUES.TWO],
  [POPULAR_ISSUES.ONE, UNPOPULAR_ISSUES.ONE],
  [POPULAR_ISSUES.ONE, UNPOPULAR_ISSUES.TWO],
  [POPULAR_ISSUES.TWO, UNPOPULAR_ISSUES.THREE],
  [POPULAR_ISSUES.TWO, UNPOPULAR_ISSUES.FOUR],
  [UNPOPULAR_ISSUES.FIVE, UNPOPULAR_ISSUES.SIX],
]

describe(testContext(__filename), function () {
  withDBCleanup()

  describe('formProjects', function () {
    describe('10 players (2 advanced), 6 votes (2 popular)', function () {
      beforeEach(async function () {
        this.data = await _setup({
          players: {total: 10, advanced: 2},
          votes: SIX_VOTES_WITH_TWO_POPULAR,
        })
      })
      _itPerformsAsExpected()
    })

    describe.skip('more advanced players than teams', function () {
      beforeEach(async function () {
        this.data = await _setup({
          players: {total: 10, advanced: 4},
          votes: SIX_VOTES_WITH_TWO_POPULAR,
        })
      })
      _itPerformsAsExpected()
    })

    describe('19 players (4 advanced), 6 votes (4 popular)', function () {
      beforeEach(async function () {
        this.data = await _setup({
          players: {total: 19, advanced: 4},
          votes: FOUR_VOTES_WITH_FOUR_POPULAR,
        })
      })
      _itPerformsAsExpected()
    })
  })

  describe('getTeamSizes(recTeamSize, numPlayers)', function () {
    it('determines optimal team sizes based on recommended size and player count', function () {
      expect(getTeamSizes(4, 16)).to.deep.equal([4, 4, 4, 4])
      expect(getTeamSizes(4, 19)).to.deep.equal([4, 4, 4, 4, 3])
      expect(getTeamSizes(4, 18)).to.deep.equal([5, 5, 4, 4])
      expect(getTeamSizes(4, 17)).to.deep.equal([5, 4, 4, 4])
      expect(getTeamSizes(4, 5)).to.deep.equal([5])
      expect(getTeamSizes(4, 2)).to.deep.equal([2])
      expect(getTeamSizes(4, 6)).to.deep.equal([3, 3])
    })
  })

  describe('generateProjectName()', function () {
    it('generates a valid project name', function () {
      return generateProjectName().then(function (projectName) {
        expect(projectName).to.match(/^\w+(-\w+)+(-\d)?$/)
      })
    })
  })
})

function _itPerformsAsExpected() {
  it('places all players on teams when not everyone voted', async function () {
    const {cycle, players} = this.data

    await formProjects(cycle.id)

    const projects = await findProjects().run()
    const projectPlayerIds = _extractPlayerIdsFromProjects(cycle.id, projects)

    const allPlayers = players.regular.concat(players.advanced)
    expect(projectPlayerIds.length).to.equal(allPlayers.length)

    allPlayers.forEach(player => {
      const playerIdInProject = projectPlayerIds.find(playerId => playerId === player.id)
      expect(playerIdInProject).to.exist
    })
  })

  it('creates project teams that all contain at least one advanced player', async function () {
    const {cycle, players} = this.data

    await formProjects(cycle.id)

    const projects = await findProjects().run()
    const advancedPlayers = players.advanced.reduce((result, player) => {
      result[player.id] = player
      return result
    }, {})

    projects.forEach(project => {
      const playerIds = _extractPlayerIdsFromProjects(cycle.id, [project])
      const advancedPlayerId = playerIds.find(playerId => advancedPlayers[playerId])
      expect(advancedPlayerId).to.exist
    })
  })

  it('creates projects for as many goals as were voted for and can be supported by the number of available advanced players', async function () {
    const {cycle, votes, players} = this.data

    await formProjects(cycle.id)

    const projects = await findProjects().run()
    const projectGoals = _extractGoalsFromProjects(projects)

    const votedForGoals = votes.reduce((result, vote) => {
      vote.goals.forEach(goal => result.set(goal.url, true))
      return result
    }, new Map())

    const maxNumExpectedProjectGoals = Math.min(votedForGoals.size, players.advanced.length)

    expect(projectGoals.length).to.be.within(1, maxNumExpectedProjectGoals)
  })

  it('creates projects for the most popular goals', async function () {
    const {cycle} = this.data

    await formProjects(cycle.id)

    const projects = await findProjects().run()
    const projectGoals = _extractGoalsFromProjects(projects)

    projectGoals.forEach(goal => {
      expect(POPULAR_ISSUES[goal.id] !== null)
    })
  })
}

async function _setup(options = {}) {
  // generate test cycle
  const cycle = await factory.create('cycle', {state: GOAL_SELECTION})

  // generate test players
  const numPlayers = options.players ? options.players.total : 10
  const numPlayersAdvanced = options.players ? options.players.advanced : 2
  const players = {
    regular: await _generatePlayers({chapterId: cycle.chapterId}, numPlayers - numPlayersAdvanced),
    advanced: await _generatePlayers({chapterId: cycle.chapterId, ecc: ADVANCED_PLAYER_ECC}, numPlayersAdvanced)
  }

  // generate test votes
  const votes = await _generateVotes(cycle.id, players.regular, options.votes)

  // return all test data
  return {cycle, players, votes}
}

function _generatePlayers(data, numPlayers) {
  return factory.createMany('player', data, numPlayers)
}

function _generateVotes(cycleId, players, votes = SIX_VOTES_WITH_TWO_POPULAR) {
  if (!(players.length >= votes.length)) {
    throw new Error('Number of players must be greater than or equal to number of votes')
  }

  votes = votes.map((goalIssueIds, i) => ({
    cycleId,
    playerId: players[i].id,
    goals: goalIssueIds.map(goalIssueId => ({
      id: goalIssueId,
      url: `http://ex.co/${goalIssueId}`,
      title: `Goal ${goalIssueId}`,
      teamSize: DEFAULT_RECOMMENDED_TEAM_SIZE
    })),
  }))

  return factory.createMany('vote', votes, votes.length)
}

function _extractGoalsFromProjects(projects) {
  const goals = projects.reduce((result, project) => {
    result.set(project.goal.url, project.goal)
    return result
  }, new Map())

  return Array.from(goals.values())
}

function _extractPlayerIdsFromProjects(cycleId, projects) {
  const playerIds = projects.reduce((result, project) => {
    project.cycleHistory
      .find(projectCycle => projectCycle.cycleId === cycleId)
      .playerIds.forEach(playerId => result.set(playerId, playerId))
    return result
  }, new Map())

  return Array.from(playerIds.values())
}
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');

var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);

function coffeeorder(owner, order) {

	this.owner = owner;
	this.order = order;

}

function coffeerun(owner, expiry, maxcups) {

	this.owner = owner;
	this.expiry = expiry;
	this.maxcups = maxcups;
	this.orders = new Array();
	this.subscribers = [];
}

function coffeerun_viewmodel (coffeerun) {

	this.id = 0;
	this.owner = coffeerun.owner;
	this.maxcups = coffeerun.maxcups;
	this.orders = coffeerun.orders;
	this.expiry = Math.floor((coffeerun.expiry.getTime() - new Date().getTime()) / 1000);

	console.log('RUN EXPIRY: %s\nCURRENT TIME: %s\nDIFF: %d', coffeerun.expiry.toString(), new Date(), this.expiry);

}

var coffeeruns = [];

var staticdir = process.argv.length >= 3 ? process.argv[2] : 'src';
app.use(express.static('./' + staticdir));
app.use(bodyParser.json());

app.get('/api/coffeerun/:id', function (req, res) {

    var run = coffeeruns[req.params.id];

	if (run != undefined) {
		res.end(JSON.stringify( new coffeerun_viewmodel(run) ));

	} else {
		res.end('NOT FOUND :(');
	}

});

app.post('/api/order/:id', function (req, res) {

	console.log ('NEW ORDER: ' + req.body.owner );

	var run = coffeeruns[req.params.id];
	var newOrder = req.body;
	run.orders.push(newOrder);
	res.writeHead(200, {'Content-Type': 'application/json'});
	res.end('{}');

	console.log ('Sending event to %d subscribers', run.subscribers.length);

	for (var i = 0; i < run.subscribers.length; i++) {
		run.subscribers[i].emit('order', newOrder);
	}
});

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

	var currentTime = new Date();

	var newRun = new coffeerun(
		req.body.owner,
		new Date(currentTime.getTime() + req.body.leavingTime*60000),
		req.body.maxcups
	);

	coffeeruns.push(newRun);

	var newRunViewModel = new coffeerun_viewmodel(newRun);
	newRunViewModel.id = coffeeruns.length - 1;

	res.writeHead(200, {'Content-Type': 'application/json'});
	console.log ('NEW RUN: ', JSON.stringify(newRunViewModel) );
	res.end(JSON.stringify(newRunViewModel));

});

io.on('connection', function (socket) {

	socket.on('subscribe', function(runid) {
		console.log('Subscription to run %s', runid);
		var run = coffeeruns[runid];
		run.subscribers.push(this);
	});

    console.log('NEW CONNECTION');

});

// Port can be supplied as 2nd command-line argument. If omitted, we check for a PORT env variable (which is how Azure supplies it).
// If neither of the above present then we default to port 80
var port = process.argv.length >= 4 ? process.argv[3] : (process.env.PORT || 80);

server.listen(port, function () {

  console.log('coffeerun is listening on port %s', port);

});<commit_msg>Use random text IDs for runs<commit_after>var express = require('express');
var bodyParser = require('body-parser');

var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);

function coffeeorder(owner, order) {

	this.owner = owner;
	this.order = order;

}

function coffeerun(owner, expiry, maxcups) {

	this.owner = owner;
	this.expiry = expiry;
	this.maxcups = maxcups;
	this.orders = new Array();
	this.subscribers = [];
}

function coffeerun_viewmodel (coffeerun) {

	this.id = 0;
	this.owner = coffeerun.owner;
	this.maxcups = coffeerun.maxcups;
	this.orders = coffeerun.orders;
	this.expiry = Math.floor((coffeerun.expiry.getTime() - new Date().getTime()) / 1000);

	console.log('RUN EXPIRY: %s\nCURRENT TIME: %s\nDIFF: %d', coffeerun.expiry.toString(), new Date(), this.expiry);

}

function makeid()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    for( var i=0; i < 5; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

var coffeeruns = {};

var staticdir = process.argv.length >= 3 ? process.argv[2] : 'src';
app.use(express.static('./' + staticdir));
app.use(bodyParser.json());

app.get('/api/coffeerun/:id', function (req, res) {

    var run = coffeeruns[req.params.id];

	if (run != undefined) {
		res.end(JSON.stringify( new coffeerun_viewmodel(run) ));

	} else {
		res.end('NOT FOUND :(');
	}

});

app.post('/api/order/:id', function (req, res) {

	console.log ('NEW ORDER: ' + req.body.owner );

	var run = coffeeruns[req.params.id];
	var newOrder = req.body;
	run.orders.push(newOrder);
	res.writeHead(200, {'Content-Type': 'application/json'});
	res.end('{}');

	console.log ('Sending event to %d subscribers', run.subscribers.length);

	for (var i = 0; i < run.subscribers.length; i++) {
		run.subscribers[i].emit('order', newOrder);
	}
});

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

	var currentTime = new Date();

	var newRun = new coffeerun(
		req.body.owner,
		new Date(currentTime.getTime() + req.body.leavingTime*60000),
		req.body.maxcups
	);

	var newRunID = makeid();
	// It's pretty unlikely we've already used this ID, but check just in case, and generate a new ID if so
	while (coffeeruns[newRunID] != undefined)
		newRunID = makeid();

	coffeeruns[newRunID] = newRun;
	var newRunViewModel = new coffeerun_viewmodel(newRun);
	newRunViewModel.id = newRunID;

	res.writeHead(200, {'Content-Type': 'application/json'});
	console.log ('NEW RUN: ', JSON.stringify(newRunViewModel) );
	res.end(JSON.stringify(newRunViewModel));

});

io.on('connection', function (socket) {

	socket.on('subscribe', function(runid) {
		console.log('Subscription to run %s', runid);
		var run = coffeeruns[runid];
		run.subscribers.push(this);
	});

    console.log('NEW CONNECTION');

});

// Port can be supplied as 2nd command-line argument. If omitted, we check for a PORT env variable (which is how Azure supplies it).
// If neither of the above present then we default to port 80
var port = process.argv.length >= 4 ? process.argv[3] : (process.env.PORT || 80);

server.listen(port, function () {

  console.log('coffeerun is listening on port %s', port);

});<|endoftext|>


<commit_before><commit_msg>Implemented storage helper.<commit_after>define(function() {
    "use strict";

    return (function() {
        return {
            /*
                @function set

                Saves the specified key-value pair in the session storage.

                @param {string} key                 The desired key
                @param {(string|number)} value      The desired value
            */
            set: function(key, value) {
                sessionStorage.setItem(key, value);
            },

            /*
                @function get

                Retrieves the value of the specified key from the session storage.

                @param {string} key     The desired key

                @return {mixed}
            */
            get: function(key) {
                return sessionStorage.getItem(key);
            },

            /*
                @function reset

                Removes the specified key (and corresponding value) from the session storage.

                @param {string} key     The desired key
            */
            reset: function(key) {
                sessionStorage.removeItem(key);
            }
        };
    })();
});<|endoftext|>


<commit_before>var appStore = [
{
  name: 'The Old Reader',
  tags: ['web', 'popular', 'advanced'],
  description: 'The Old Reader was built to be a Google Reader replacement, and it does it well!',
  url: 'http://theoldreader.com/',
  icon: 'http://theoldreader.com/favicon.ico',
  registration: {
    name: 'The Old Reader',
    url: 'http://theoldreader.com/feeds/subscribe?url={feed}'
  },
  installed: false
},
{
  name: 'NewsBlur',
  tags: ['web', 'mobile', 'advanced', 'open source'],
  description: 'NewsBlur is a personal news reader bringing people together to talk about the world.',
  url: 'http://www.newsblur.com/',
  icon: 'http://newsblur.com/favicon.ico',
  registration: {
    name: 'NewsBlur',
    url: 'http://www.newsblur.com/?url={url}'
  },
    installed: true
},
{
  name: 'Rivered',
  tags: ['web'],
  description: 'An uncluttered River of News; no unread item count, no complexity. Just the content you subscribe to.',
  url: 'http://www.rivered.io/',
  icon: 'http://www.rivered.io/favicon.ico',
  registration: {
    name: 'Rivered',
    url: 'http://www.rivered.io/add?url={url}'
  }
},
{
  name: 'Bloglovin',
  tags: ['web', 'iOS', 'blog'],
  description: 'Bloglovin was created to make reading blogs awesome.',
  url: 'http://www.bloglovin.com/',
  icon: 'http://www.bloglovin.com/images/favicon.ico',
  registration: {
    name: 'Bloglovin',
    url: 'http://www.bloglovin.com/search/{url}'
  }
},
{
  name: 'Blogtrottr',
  tags: ['email', 'digests'],
  description: 'Blogtrottr delivers updates from all of your favourite news, feeds, and blogs directly to your email inbox.',
  url: 'http://blogtrottr.com/',
  icon: 'http://blogtrottr.com/favicon.ico',
  registration: {
    name: 'Blogtrottr',
    url: 'http://blogtrottr.com/?subscribe={feed}'
  }
},
{
  name: 'BazQux Reader',
  tags: ['web', 'comments'],
  description: 'RSS feed reader that shows comments to posts and supports reading of Facebook and Google+ pages.',
  url: 'https://bazqux.com/',
  icon: 'https://bazqux.com/favicon.ico',
  registration: {
    name: 'BazQux',
    url: 'https://bazqux.com/add?url={url}'
  }
},
{
  name: 'Feedleap',
  tags: ['web', 'kippt', 'bookmark', 'open source'],
  description: 'FeedLeap lets you subscribe to your favorite RSS feeds and store new entries as Clips in any Kippt List you want.',
  url: 'https://feedleap.herokuapp.com',
  icon: 'https://feedleap.herokuapp.com/static/favicon.ico',
  registration: {
    name: 'Feedleap',
    url: 'https://feedleap.herokuapp.com/feeds/new/?feed={feed}&source=subtome'
  }
},
{
  name: 'FeedHQ',
  tags: ['web', 'mobile', 'open source'],
  description: 'FeedHQ is a feed reader built with readability and mobility in mind',
  url: 'https://feedhq.org/',
  icon: 'https://feedhq.org/static/core/img/icon-rss.png',
  registration: {
    name: 'FeedHQ',
    url: 'https://feedhq.org/subscribe/?feeds={feeds}&url={url}'
  }
},
{
  name: 'Feedbin',
  tags: ['web'],
  description: 'A fast, simple RSS feed reader that delivers a great reading experience.',
  url: 'https://feedbin.me/',
  icon: 'https://feedbin.me/favicon.ico',
  registration: {
    name: 'Feedbin',
    url: 'https://feedbin.me/?subscribe={feed}'
  }
},
{
  name: 'Feedly',
  tags: ['chrome', 'firefox', 'mobile'],
  description: 'Feedly is a news aggregator application for various Web browsers and mobile devices running iOS and Android.',
  url: 'http://feedly.com/',
  icon: 'http://feedly.com/favicon.ico',
  registration: {
    name: 'Feedly',
    url: 'http://www.feedly.com/home#subscription/feed/{feed}'
  }
},
{
  name: 'Msgboy',
  tags: ['chrome', 'open source'],
  description: 'Msgboy delivers a custom feed of stories in realtime, all based on websites you\'ve bookmarked and visited most often',
  url: 'http://www.msgboy.com/',
  icon: 'https://raw.github.com/superfeedr/msgboy/master/views/img/icon16.png',
  registration: {
    name: 'Msgboy',
    url: 'chrome-extension://ligglcbjgpiljeoenbhnnfdipkealakb/data/html/subscribe.html?url={url}'
  }
},
{
  name: 'InoReader',
  tags: ['web', 'advanced'],
  description: 'Light and Fast RSS/Atom Reader inspired by Google Reader',
  url: 'https://inoreader.com/',
  icon: 'https://inoreader.com/images/icons/72_x_72_pixels.png',
  registration: {
    name: 'InoReader',
    url: 'https://www.inoreader.com/?add_feed={feed}'
  }
}
];
<commit_msg>Added ReadHQ<commit_after>var appStore = [
{
  name: 'The Old Reader',
  tags: ['web', 'popular', 'advanced'],
  description: 'The Old Reader was built to be a Google Reader replacement, and it does it well!',
  url: 'http://theoldreader.com/',
  icon: 'http://theoldreader.com/favicon.ico',
  registration: {
    name: 'The Old Reader',
    url: 'http://theoldreader.com/feeds/subscribe?url={feed}'
  },
  installed: false
},
{
  name: 'NewsBlur',
  tags: ['web', 'mobile', 'advanced', 'open source'],
  description: 'NewsBlur is a personal news reader bringing people together to talk about the world.',
  url: 'http://www.newsblur.com/',
  icon: 'http://newsblur.com/favicon.ico',
  registration: {
    name: 'NewsBlur',
    url: 'http://www.newsblur.com/?url={url}'
  },
    installed: true
},
{
  name: 'Rivered',
  tags: ['web'],
  description: 'An uncluttered River of News; no unread item count, no complexity. Just the content you subscribe to.',
  url: 'http://www.rivered.io/',
  icon: 'http://www.rivered.io/favicon.ico',
  registration: {
    name: 'Rivered',
    url: 'http://www.rivered.io/add?url={url}'
  }
},
{
  name: 'Bloglovin',
  tags: ['web', 'iOS', 'blog'],
  description: 'Bloglovin was created to make reading blogs awesome.',
  url: 'http://www.bloglovin.com/',
  icon: 'http://www.bloglovin.com/images/favicon.ico',
  registration: {
    name: 'Bloglovin',
    url: 'http://www.bloglovin.com/search/{url}'
  }
},
{
  name: 'Blogtrottr',
  tags: ['email', 'digests'],
  description: 'Blogtrottr delivers updates from all of your favourite news, feeds, and blogs directly to your email inbox.',
  url: 'http://blogtrottr.com/',
  icon: 'http://blogtrottr.com/favicon.ico',
  registration: {
    name: 'Blogtrottr',
    url: 'http://blogtrottr.com/?subscribe={feed}'
  }
},
{
  name: 'BazQux Reader',
  tags: ['web', 'comments'],
  description: 'RSS feed reader that shows comments to posts and supports reading of Facebook and Google+ pages.',
  url: 'https://bazqux.com/',
  icon: 'https://bazqux.com/favicon.ico',
  registration: {
    name: 'BazQux',
    url: 'https://bazqux.com/add?url={url}'
  }
},
{
  name: 'Feedleap',
  tags: ['web', 'kippt', 'bookmark', 'open source'],
  description: 'FeedLeap lets you subscribe to your favorite RSS feeds and store new entries as Clips in any Kippt List you want.',
  url: 'https://feedleap.herokuapp.com',
  icon: 'https://feedleap.herokuapp.com/static/favicon.ico',
  registration: {
    name: 'Feedleap',
    url: 'https://feedleap.herokuapp.com/feeds/new/?feed={feed}&source=subtome'
  }
},
{
  name: 'FeedHQ',
  tags: ['web', 'mobile', 'open source'],
  description: 'FeedHQ is a feed reader built with readability and mobility in mind',
  url: 'https://feedhq.org/',
  icon: 'https://feedhq.org/static/core/img/icon-rss.png',
  registration: {
    name: 'FeedHQ',
    url: 'https://feedhq.org/subscribe/?feeds={feeds}&url={url}'
  }
},
{
  name: 'Feedbin',
  tags: ['web'],
  description: 'A fast, simple RSS feed reader that delivers a great reading experience.',
  url: 'https://feedbin.me/',
  icon: 'https://feedbin.me/favicon.ico',
  registration: {
    name: 'Feedbin',
    url: 'https://feedbin.me/?subscribe={feed}'
  }
},
{
  name: 'Feedly',
  tags: ['chrome', 'firefox', 'mobile'],
  description: 'Feedly is a news aggregator application for various Web browsers and mobile devices running iOS and Android.',
  url: 'http://feedly.com/',
  icon: 'http://feedly.com/favicon.ico',
  registration: {
    name: 'Feedly',
    url: 'http://www.feedly.com/home#subscription/feed/{feed}'
  }
},
{
  name: 'Msgboy',
  tags: ['chrome', 'open source'],
  description: 'Msgboy delivers a custom feed of stories in realtime, all based on websites you\'ve bookmarked and visited most often',
  url: 'http://www.msgboy.com/',
  icon: 'https://raw.github.com/superfeedr/msgboy/master/views/img/icon16.png',
  registration: {
    name: 'Msgboy',
    url: 'chrome-extension://ligglcbjgpiljeoenbhnnfdipkealakb/data/html/subscribe.html?url={url}'
  }
},
{
  name: 'InoReader',
  tags: ['web', 'advanced'],
  description: 'Light and Fast RSS/Atom Reader inspired by Google Reader',
  url: 'https://inoreader.com/',
  icon: 'https://inoreader.com/images/icons/72_x_72_pixels.png',
  registration: {
    name: 'InoReader',
    url: 'https://www.inoreader.com/?add_feed={feed}'
  }
},
{
  name: 'ReadHQ',
  tags: ['web', 'mobile'],
  description: "",
  url:"https://www.readhq.com",
  icon:"https://www.readhq.com/favicon.ico",
  registration:{
    name: "ReadHQ",
    url: 'https://www.readhq.com/api/v1/subtome?url={url}'
  }
}
];
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var es = require('event-stream');
var gutil = require('gulp-util');
var clean = require('gulp-clean');
var coffee = require('gulp-coffee');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var less = require('gulp-less');
var handlebars = require('gulp-handlebars');
var wrap = require('gulp-wrap');
var declare = require('gulp-declare');
var watch = require('gulp-watch');
var connect = require('gulp-connect');

/*
 * Clean ups ./dist folder
*/
gulp.task('clean', function() {

  return gulp
    .src('./dist', {read: false})
    .pipe(clean({force: true}))
    .on('error', gutil.log);
});

/*
 * Processes Handlebars templates
*/
function templates() {
  return gulp
    .src(['./src/main/template/**/*'])
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      namespace: 'Handlebars.templates',
      noRedeclare: true, // Avoid duplicate declarations
    }))
    .on('error', gutil.log);
}

/*
 * Processes CoffeeScript files
*/
function coffeescript () {
  return gulp
    .src(['./src/main/coffeescript/**/*.coffee'])
    .pipe(coffee({bare: true}))
    .on('error', gutil.log);
}

/*
 * Build a distribution
*/
gulp.task('dist', ['clean'], function() {

  return es.merge(
      gulp.src('./src/main/javascript/doc.js'),
      coffeescript(),
      templates()
    )
    .pipe(concat('swagger-ui.js'))
    .pipe(gulp.dest('./dist'))
    .pipe(uglify())
    .pipe(rename({extname: '.min.js'}))
    .on('error', gutil.log)
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
});

/*
 * Processes less files into CSS files
*/
gulp.task('less', ['clean'], function() {

  return gulp
    .src([
      './src/main/less/screen.less',
      './src/main/less/reset.less'
    ])
    .pipe(less())
    .on('error', gutil.log)
    .pipe(gulp.dest('./src/main/html/css/'))
    .pipe(connect.reload());
});

/*
 * Copy lib and html folders
*/
gulp.task('copy', ['less'], function() {

  // copy JavaScript files inside lib folder
  gulp
    .src(['./lib/**/*.js'])
    .pipe(gulp.dest('./dist/lib'))
    .on('error', gutil.log)

  // copy all files inside html folder
  gulp
    .src(['./src/main/html/**/*'])
    .pipe(gulp.dest('./dist'))
    .on('error', gutil.log)
});

/*
 * Watch for changes and recompile
*/
gulp.task('watch', function() {
  return watch(['./src/**/*.{coffee,js,less}'], function() {
    gulp.start('default');
  });
});

/*
 * Live reload web server of `dist`
*/
gulp.task('connect', function() {
  connect.server({
    root: 'dist',
    livereload: true
  });
});

gulp.task('default', ['dist', 'copy']);
gulp.task('serve', ['connect', 'watch'])
<commit_msg>added gulp-header to write metadata in comments of output library #900<commit_after>'use strict';

var gulp = require('gulp');
var es = require('event-stream');
var gutil = require('gulp-util');
var clean = require('gulp-clean');
var coffee = require('gulp-coffee');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var less = require('gulp-less');
var handlebars = require('gulp-handlebars');
var wrap = require('gulp-wrap');
var declare = require('gulp-declare');
var watch = require('gulp-watch');
var connect = require('gulp-connect');
var header = require('gulp-header');
var pkg = require('./package.json');
var banner = ['/**',
  ' * <%= pkg.name %> - <%= pkg.description %>',
  ' * @version v<%= pkg.version %>',
  ' * @link <%= pkg.homepage %>',
  ' * @license <%= pkg.license %>',
  ' */',
  ''].join('\n');

/**
 * Clean ups ./dist folder
 */
gulp.task('clean', function() {
  return gulp
    .src('./dist', {read: false})
    .pipe(clean({force: true}))
    .on('error', gutil.log);
});

/**
 * Processes Handlebars templates
 */
function templates() {
  return gulp
    .src(['./src/main/template/**/*'])
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      namespace: 'Handlebars.templates',
      noRedeclare: true, // Avoid duplicate declarations
    }))
    .on('error', gutil.log);
}

/**
 * Processes CoffeeScript files
 */
function coffeescript () {
  return gulp
    .src(['./src/main/coffeescript/**/*.coffee'])
    .pipe(coffee({bare: true}))
    .on('error', gutil.log);
}

/**
 * Build a distribution
 */
gulp.task('dist', ['clean'], function() {

  return es.merge(
      gulp.src('./src/main/javascript/doc.js'),
      coffeescript(),
      templates()
    )
    .pipe(concat('swagger-ui.js'))
    .pipe(header(banner, { pkg: pkg } ))
    .pipe(gulp.dest('./dist'))
    .pipe(uglify())
    .pipe(rename({extname: '.min.js'}))
    .on('error', gutil.log)
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
});

/**
 * Processes less files into CSS files
 */
gulp.task('less', ['clean'], function() {

  return gulp
    .src([
      './src/main/less/screen.less',
      './src/main/less/reset.less'
    ])
    .pipe(less())
    .on('error', gutil.log)
    .pipe(gulp.dest('./src/main/html/css/'))
    .pipe(connect.reload());
});

/**
 * Copy lib and html folders
 */
gulp.task('copy', ['less'], function() {

  // copy JavaScript files inside lib folder
  gulp
    .src(['./lib/**/*.js'])
    .pipe(gulp.dest('./dist/lib'))
    .on('error', gutil.log)

  // copy all files inside html folder
  gulp
    .src(['./src/main/html/**/*'])
    .pipe(gulp.dest('./dist'))
    .on('error', gutil.log)
});

/**
 * Watch for changes and recompile
 */
gulp.task('watch', function() {
  return watch(['./src/**/*.{coffee,js,less}'], function() {
    gulp.start('default');
  });
});

/**
 * Live reload web server of `dist`
 */
gulp.task('connect', function() {
  connect.server({
    root: 'dist',
    livereload: true
  });
});

gulp.task('default', ['dist', 'copy']);
gulp.task('serve', ['connect', 'watch'])
<|endoftext|>


<commit_before>/*
 * jscompare 1.04
 * Author: Graham Ellsmore (ellsmo.re)
 * Website: https://github.com/CelloSounds/jscompare
 * Date: 11-Jan-14
 */

/*Global abatement */
var jscompare = jscompare || {};

/*Create instance for Levenshtein scoring */
jscompare.scoreObject = new diff_match_patch();

/* Score weighting for individual word matches */
jscompare.compareWordsConf = {
	weighting : 10,
	rejectThreshold : 5
};

/* ************* */
/* MAIN FUNCTION */
/* ************* */

jscompare.analyseContent = function analyseContent(primaryString, secondaryString) {

	/* Attributes */
	var primaryWordList = primaryString.split(' ')
	secondaryWordList = secondaryString.split(' ')
	primaryPhrasePermutations = {}
	secondaryPhrasePermutations = {}
	jscompare.matchScore = null
	jscompare.matchesList = {};

	/* Methods */

	/* Natural logarithm - from web */
	var ln = function ln(val) {
		return Math.log(val) / Math.LOG10E;
	};

	/* Function to request a levenshtein score for a word or phrase comparison
	 This is called multiple times untile all combinations between the 2 texts being compared are exhausted */
	var getScore = function getScore(primarySubstring, secondarySubstring) {
		/* Return Levenshtein score */
		return jscompare.scoreObject.diff_levenshtein(jscompare.scoreObject.diff_main(primarySubstring, secondarySubstring));
	};

	/* Iterate through each combination of individual words from both texts and request a match score if levenshtein score is within threshold */
	var compareSubtext = function compareSubtext(primaryArray, secondaryArray) {
		var scoreValue;
		/* for each primary text related word */
		primaryArray.forEach(function(primaryItem) {
			/* compare that word with each secondary related word in turn and get a match scoring */
			secondaryArray.forEach(function(secondaryItem) {
				jscompare.matchScore = getScore(primaryItem, secondaryItem);
				/* check if the levenshtein score is low enough to meet the threshold for a useful match */
				if (jscompare.matchScore <= jscompare.compareWordsConf.rejectThreshold) {
					/* Calculate match score value */
					scoreValue = (25 / ln(jscompare.matchScore + 2)) * (ln(primaryItem.length));
					/* determine if match is new or scores less than an existing match */
					if (jscompare.matchesList[primaryItem] === undefined || scoreValue > jscompare.matchesList[primaryItem]) {
						jscompare.matchesList[primaryItem] = scoreValue;
					}
				}
			});
		});
	};

	/* Call primary function to return comparative scores */
	compareSubtext(primaryWordList, secondaryWordList);

	return jscompare.matchesList;
};
/* Calculate the total of all the match scores as a final match total */
jscompare.CalculateCumulativeMatchScore = function(matchesListObject) {
	var runningScore = 0;
	for (match in matchesListObject) {
		runningScore += matchesListObject[match];
	}
	return runningScore;
};
<commit_msg>Added missing smicolons<commit_after>/*
 * jscompare 1.04
 * Author: Graham Ellsmore (ellsmo.re)
 * Website: https://github.com/CelloSounds/jscompare
 * Date: 11-Jan-14
 */

/*Global abatement */
var jscompare = jscompare || {};

/*Create instance for Levenshtein scoring */
jscompare.scoreObject = new diff_match_patch();

/* Score weighting for individual word matches */
jscompare.compareWordsConf = {
	weighting : 10,
	rejectThreshold : 5
};

/* ************* */
/* MAIN FUNCTION */
/* ************* */

jscompare.analyseContent = function analyseContent(primaryString, secondaryString) {

	/* Attributes */
	var primaryWordList = primaryString.split(' ');
	secondaryWordList = secondaryString.split(' ');
	primaryPhrasePermutations = {};
	secondaryPhrasePermutations = {};
	jscompare.matchScore = null;
	jscompare.matchesList = {};

	/* Methods */

	/* Natural logarithm - from web */
	var ln = function ln(val) {
		return Math.log(val) / Math.LOG10E;
	};

	/* Function to request a levenshtein score for a word or phrase comparison
	 This is called multiple times untile all combinations between the 2 texts being compared are exhausted */
	var getScore = function getScore(primarySubstring, secondarySubstring) {
		/* Return Levenshtein score */
		return jscompare.scoreObject.diff_levenshtein(jscompare.scoreObject.diff_main(primarySubstring, secondarySubstring));
	};

	/* Iterate through each combination of individual words from both texts and request a match score if levenshtein score is within threshold */
	var compareSubtext = function compareSubtext(primaryArray, secondaryArray) {
		var scoreValue;
		/* for each primary text related word */
		primaryArray.forEach(function(primaryItem) {
			/* compare that word with each secondary related word in turn and get a match scoring */
			secondaryArray.forEach(function(secondaryItem) {
				jscompare.matchScore = getScore(primaryItem, secondaryItem);
				/* check if the levenshtein score is low enough to meet the threshold for a useful match */
				if (jscompare.matchScore <= jscompare.compareWordsConf.rejectThreshold) {
					/* Calculate match score value */
					scoreValue = (25 / ln(jscompare.matchScore + 2)) * (ln(primaryItem.length));
					/* determine if match is new or scores less than an existing match */
					if (jscompare.matchesList[primaryItem] === undefined || scoreValue > jscompare.matchesList[primaryItem]) {
						jscompare.matchesList[primaryItem] = scoreValue;
					}
				}
			});
		});
	};

	/* Call primary function to return comparative scores */
	compareSubtext(primaryWordList, secondaryWordList);

	return jscompare.matchesList;
};
/* Calculate the total of all the match scores as a final match total */
jscompare.CalculateCumulativeMatchScore = function(matchesListObject) {
	var runningScore = 0;
	for (match in matchesListObject) {
		runningScore += matchesListObject[match];
	}
	return runningScore;
};
<|endoftext|>


<commit_before>var gulp = require('gulp'),
    gutil = require('gulp-util'),
    del = require('del'),
    fs = require("fs"),
    minimist = require('minimist'),
    targz = require('targz'),
    slog = require('single-line-log').stdout,
    dateFormat = require('dateformat'),
    progress = require('progress-stream'),
    request = require("request"),
    uglify = require('gulp-tm-uglify'),
    rename = require('gulp-rename'),
    changed = require('gulp-changed'),
    gulpif = require('gulp-if'),
    http = require('http');
var fg = require('fast-glob');
var logger = require('gulp-logger');

//var downloadHost = "download.o2oa.net";
var downloadHost = "release.o2oa.net";
var protocol = "http";
var commonUrl = "/build/commons.tar.gz";

var jvmUrls = {
    "all": "/build/jvm.tar.gz",
    "linux": "/build/linux.tar.gz",
    "aix": "/build/aix.tar.gz",
    "kylinos": "/build/kylinos_phytium.tar",
    "macos": "/build/macos.tar.gz",
    "neokylin": "/build/neokylin_loongson.tar.gz",
    "raspberrypi": "/build/raspberrypi.tar.gz",
    "windows": "/build/windows.tar.gz"
};
var scripts = {
    "all": ["o2server/*.sh", "o2server/*.jar", "o2server/*.html", "o2server/*.bat", "o2server/version.o2"],
    "linux": ["o2server/*linux*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "aix": ["o2server/*aix*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "kylinos": ["o2server/*kylinos_phytium*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "macos": ["o2server/*macos*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "neokylin": ["o2server/*neokylin_loongson*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "raspberrypi": ["o2server/*raspberrypi*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "windows": ["o2server/*windows*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"]
};

var o_options = minimist(process.argv.slice(2), {//upload: local ftp or sftp
    string: ["e"]
});
var options = {};
options.ev = o_options.e || "all";
var jvmUrl = jvmUrls[options.ev];
var scriptSource = scripts[options.ev];

function ProgressBar(description, bar_length){
    this.description = description || 'Progress';
    this.length = bar_length || 50;

    this.render = function (opts){
        var percent = (opts.completed / opts.total).toFixed(4);
        var cell_num = Math.floor(percent * this.length);

        var speed = "";
        if (opts.time){
            speed = (opts.completed/1024/1024)/(opts.time/1000);
            speed = speed.toFixed(2);
            speed = speed+"M/S";
        }
        var count = "";
        if (opts.count){
            count = "["+opts.count+"/"+opts.total+"]"
        }

        var cell = '';
        for (var i=0;i<cell_num;i++) { cell += '>'; }

        var empty = '';
        for (var i=0;i<this.length-cell_num;i++) { empty += '-'; }

        var d = new Date();
        var cmdText = "["+dateFormat(d, "HH:MM:ss")+"]"+" "+this.description + ': ' + cell + empty + ' ' + (100*percent).toFixed(2) + '% '+speed+count;
        slog(cmdText);
    };
}

function downloadFile(path, filename, headcb, progresscb, cb){
    var dest = `o2server/${filename}`;

    // fs.exists(dest, function(exists) {
    //     if (exists){
    //         headcb(1);
    //         progresscb({transferred:1});
    //         cb();
    //     }else{
            let stream = fs.createWriteStream(dest);
            var options = { url:protocol+"://"+downloadHost+path };
            var fileHost = downloadHost;
            var filePath =  path;
            stream.on('finish', () => {
                //gutil.log("download", ":", gutil.colors.green(filename), " completed!");
                cb();
            });
            stream.on('error', (err) => {
                gutil.log(gutil.colors.red("download error"), ":", gutil.colors.red(filename), err);
            });

            var req = http.request({
                host:fileHost,
                path:filePath,
                method:'HEAD'
            },function (res){
                if (res.statusCode == 200) {
                    res.setEncoding(null);
                    var time = 0;
                    var l = res.headers['content-length'];
                    var str = progress({
                        length: l,
                        time: 100 /* ms */
                    });
                    headcb(l);

                    str.on('progress', function(progress) {
                        if (pb){
                            progresscb(progress);
                            pb.render({ completed: currentLength, total: totalLength, time: time+=100 });
                        }

                    });
                    request.get(options).pipe(str).pipe(stream);
                } else {
                    gutil.log(gutil.colors.red("download error"), ":", gutil.colors.red(filename), "statusCode:"+response.statusCode);
                }
            })
            req.on('error', (e) => {
                gutil.log(gutil.colors.red("download error"), ":", gutil.colors.red(filename), e);
            });
            req.end();
    //    }
    //});
}

var commonsLength = 0;
var jvmLenght = 0;
var totalLength = 0;
var currentLength = 0;
var commonsCurrentLength = 0;
var jvmCurrentLength = 0;

var pb = null;
function initProgress(){
    if (commonsLength && jvmLenght){
        totalLength = +commonsLength + jvmLenght;
        var t = (totalLength/1024/1024).toFixed(2);
        pb = new ProgressBar('total: '+t+"M", 50);

    }
}

function download_commons_and_jvm(cb){
    gutil.log(gutil.colors.green("begin download commons and jvm"));
    console.log(`---------------------------------------------------------------------
  . Start to download the dependencies needed for compilation ...
---------------------------------------------------------------------`);
    var downloader = new Promise((resolve, reject) => {
        var commonLoaded = false;
        var jvmLoaded = false;
        downloadFile(commonUrl, "commons.tar.gz", (length)=>{
            commonsLength = +length;
            initProgress();
        }, (progress)=>{
            commonsCurrentLength = progress.transferred;
            currentLength = +commonsCurrentLength+jvmCurrentLength;
        }, ()=>{
            commonLoaded = true;
            if (jvmLoaded && commonLoaded) resolve();
        });
        // var jvmName = jvmUrl.substr(jvmUrl.lastIndexOf("/"+1, jvmUrl.length));
        // console.log(jvmName);
        // console.log(jvmUrl);
        downloadFile(jvmUrl, "jvm.tar.gz", (length)=>{
            jvmLenght = +length;
            initProgress();
        }, (progress)=>{
            jvmCurrentLength = progress.transferred;
            currentLength = +commonsCurrentLength+jvmCurrentLength;
        }, ()=>{
            jvmLoaded = true;
            if (jvmLoaded && commonLoaded) resolve();
        });
    });
    downloader.then(()=>{
        console.log();
        gutil.log(gutil.colors.green("download commons and jvm completed"));
        cb();
    });
}

function decompress_commons_and_jvm(cb){
    console.log(`---------------------------------------------------------------------
  . Start to decompress the dependencies needed for compilation ...
---------------------------------------------------------------------`);
    gutil.log(gutil.colors.green("begin decompress commons and jvm"));
    var count =0;
    var decompressor = new Promise((resolve, reject) => {
        var commonUnziped = false;
        var jvmUnziped = false;
        targz.decompress({
            src: 'o2server/commons.tar.gz',
            dest: 'o2server',
            tar: {map: function(header){
                count++;
                    var d = new Date();
                    slog("["+dateFormat(d, "HH:MM:ss")+"] " + count +" "+ header.name+" ...");
                //gutil.log(gutil.colors.cyan(header.name), gutil.colors.yellow("..."));
            }}
        }, function(err){
            if(err) {
                gutil.log(gutil.colors.red("decompress error"), ":", gutil.colors.red("common.tar.gz "), err);
            } else {
                commonUnziped = true;
                if (jvmUnziped && commonUnziped) resolve();
            }
        });
        targz.decompress({
            src: 'o2server/jvm.tar.gz',
            dest: 'o2server',
            tar: {map: function(header){
                    count++;
                    var d = new Date();
                    slog("["+dateFormat(d, "HH:MM:ss")+"] " + count +" "+ header.name+" ...");
                    //slog(count +" "+ header.name+" ...");
                    //gutil.log(gutil.colors.cyan(header.name), gutil.colors.yellow("..."));
                }}
        }, function(err){
            if(err) {
                gutil.log(gutil.colors.red("decompress error"), ":", gutil.colors.red("jvm.tar.gz "), err);
            } else {
                jvmUnziped = true;
                if (jvmUnziped && commonUnziped) resolve();
            }
        });
    });
    decompressor.then(()=>{
        gutil.log(gutil.colors.green("decompress commons and jvm completed. " + count+" files"));
        cb();
    });
}

function getJsFileCount(p){
    var fileCount = 0;
    function readFile(path,filesList, ){
        files = fs.readdirSync(path);
        files.forEach(walk);
        function walk(file){
            states = fs.statSync(path+'/'+file);
            if(states.isDirectory()){
                readFile(path+'/'+file,filesList);
            }else{
                // fileCount+=states.size;
                fileCount++;
            }
        }
    }
    var filesList = [];
    readFile(p, filesList);
    return fileCount;
}

function build_web_minimize(cb) {
    console.log(`---------------------------------------------------------------------
  . Start compiling the web ...
---------------------------------------------------------------------`);

    var dest = 'target/o2server/webServer/';
    var src_min = ['o2web/source/**/*.js', '!**/*.spec.js', '!**/test/**', '!o2web/source/o2_lib/**/*'];
    //var src_min = ['o2web/source/o2_core/**/*.js', '!**/*.spec.js', '!**/test/**', '!o2web/source/o2_lib/**/*'];

    var entries = fg.sync(src_min, { dot: true});
    var size = entries.length;

    var pb = new ProgressBar('total: '+size, 50);
    var doCount = 0;
    return gulp.src(src_min)
        .pipe(uglify())
        .pipe(rename({ extname: '.min.js' }))
        .pipe(gulp.dest(dest))
        .pipe(logger(function(){
            doCount++;
            pb.render({ completed: doCount, total: size, count: doCount});
            if (doCount == size) console.log();
        }))
        .pipe(gutil.noop());
}

function build_web_move() {
    var dest = 'target/o2server/webServer/';
    var src_move = ['o2web/source/**/*', '!**/*.spec.js', '!**/test/**'];

    var entries = fg.sync(src_move, { dot: true});
    var size = entries.length;
    var pb = new ProgressBar('total: '+size, 50);
    var doCount = 0;

    return gulp.src(src_move)
        .pipe(gulp.dest(dest))
        .pipe(logger(function(){
            doCount++;
            pb.render({ completed: doCount, total: size, count: doCount});
            if (doCount == size) console.log();
        }))
        .pipe(gutil.noop());
}
exports.build_web_move = build_web_move;

function clear_build(cb){
    console.log(`---------------------------------------------------------------------
  . clear old build ...
---------------------------------------------------------------------`);
    var dest = 'target';
    del(dest, { dryRun: true, force: true });
    cb();
}
exports.clear_build = clear_build;

function deploy_server(){
    console.log(`---------------------------------------------------------------------
  . deploy to target ...
---------------------------------------------------------------------`);
    var source1 = ["o2server/store/**/*", "o2server/commons/**/*", "o2server/jvm/**/*", "o2server/configSample/**/*", "o2server/localSample/**/*"];
    source = source1.concat(scriptSource);
    var dest = "target/o2server/servers/"

    var entries = fg.sync(source, { dot: true});
    var size = entries.length;
    var pb = new ProgressBar('total: '+size, 50);
    var doCount = 0;

    return gulp.src(source)
        .pipe(gulp.dest(dest))
        .pipe(logger(function(){
            doCount++;
            if (doCount <= size) pb.render({ completed: doCount, total: size, count: doCount});
            if (doCount > size) {console.log();}
        }));
    //.pipe(gutil.noop());
}

exports.preperation =  gulp.series(download_commons_and_jvm, decompress_commons_and_jvm);

var shell = require('gulp-shell')
exports.build_server = function(){
    console.log(`---------------------------------------------------------------------
  . Start compiling the server ...
---------------------------------------------------------------------`);
    return (shell.task('npm run build_server_script'))();
};
exports.build_web = gulp.series(build_web_minimize, build_web_move);
exports.deploy = deploy_server;
<commit_msg>修改打包脚本<commit_after>var gulp = require('gulp'),
    gutil = require('gulp-util'),
    del = require('del'),
    fs = require("fs"),
    minimist = require('minimist'),
    targz = require('targz'),
    slog = require('single-line-log').stdout,
    dateFormat = require('dateformat'),
    progress = require('progress-stream'),
    request = require("request"),
    uglify = require('gulp-tm-uglify'),
    rename = require('gulp-rename'),
    changed = require('gulp-changed'),
    gulpif = require('gulp-if'),
    http = require('http');
var fg = require('fast-glob');
var logger = require('gulp-logger');

//var downloadHost = "download.o2oa.net";
var downloadHost = "release.o2oa.net";
var protocol = "http";
var commonUrl = "/build/commons.tar.gz";

var jvmUrls = {
    "all": "/build/jvm.tar.gz",
    "linux": "/build/linux.tar.gz",
    "aix": "/build/aix.tar.gz",
    "kylinos": "/build/kylinos_phytium.tar",
    "macos": "/build/macos.tar.gz",
    "neokylin": "/build/neokylin_loongson.tar.gz",
    "raspberrypi": "/build/raspberrypi.tar.gz",
    "windows": "/build/windows.tar.gz"
};
var scripts = {
    "all": ["o2server/*.sh", "o2server/*.jar", "o2server/*.html", "o2server/*.bat", "o2server/version.o2"],
    "linux": ["o2server/*linux*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "aix": ["o2server/*aix*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "kylinos": ["o2server/*kylinos_phytium*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "macos": ["o2server/*macos*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "neokylin": ["o2server/*neokylin_loongson*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "raspberrypi": ["o2server/*raspberrypi*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"],
    "windows": ["o2server/*windows*", "o2server/*.jar", "o2server/*.html", "o2server/version.o2"]
};

var o_options = minimist(process.argv.slice(2), {//upload: local ftp or sftp
    string: ["e"]
});
var options = {};
options.ev = o_options.e || "all";
var jvmUrl = jvmUrls[options.ev];
var scriptSource = scripts[options.ev];

function ProgressBar(description, bar_length){
    this.description = description || 'Progress';
    this.length = bar_length || 50;

    this.render = function (opts){
        var percent = (opts.completed / opts.total).toFixed(4);
        var cell_num = Math.floor(percent * this.length);

        var speed = "";
        if (opts.time){
            speed = (opts.completed/1024/1024)/(opts.time/1000);
            speed = speed.toFixed(2);
            speed = speed+"M/S";
        }
        var count = "";
        if (opts.count){
            count = "["+opts.count+"/"+opts.total+"]"
        }

        var cell = '';
        for (var i=0;i<cell_num;i++) { cell += '>'; }

        var empty = '';
        for (var i=0;i<this.length-cell_num;i++) { empty += '-'; }

        var d = new Date();
        var cmdText = "["+dateFormat(d, "HH:MM:ss")+"]"+" "+this.description + ': ' + cell + empty + ' ' + (100*percent).toFixed(2) + '% '+speed+count;
        slog(cmdText);
    };
}

function downloadFile(path, filename, headcb, progresscb, cb){
    var dest = `o2server/${filename}`;

    // fs.exists(dest, function(exists) {
    //     if (exists){
    //         headcb(1);
    //         progresscb({transferred:1});
    //         cb();
    //     }else{
            let stream = fs.createWriteStream(dest);
            var options = { url:protocol+"://"+downloadHost+path };
            var fileHost = downloadHost;
            var filePath =  path;
            stream.on('finish', () => {
                //gutil.log("download", ":", gutil.colors.green(filename), " completed!");
                cb();
            });
            stream.on('error', (err) => {
                gutil.log(gutil.colors.red("download error"), ":", gutil.colors.red(filename), err);
            });

            var req = http.request({
                host:fileHost,
                path:filePath,
                method:'HEAD'
            },function (res){
                if (res.statusCode == 200) {
                    res.setEncoding(null);
                    var time = 0;
                    var l = res.headers['content-length'];
                    var str = progress({
                        length: l,
                        time: 100 /* ms */
                    });
                    headcb(l);

                    str.on('progress', function(progress) {
                        if (pb){
                            progresscb(progress);
                            pb.render({ completed: currentLength, total: totalLength, time: time+=100 });
                        }

                    });
                    request.get(options).pipe(str).pipe(stream);
                } else {
                    gutil.log(gutil.colors.red("download error"), ":", gutil.colors.red(filename), "statusCode:"+response.statusCode);
                }
            })
            req.on('error', (e) => {
                gutil.log(gutil.colors.red("download error"), ":", gutil.colors.red(filename), e);
            });
            req.end();
    //    }
    //});
}

var commonsLength = 0;
var jvmLenght = 0;
var totalLength = 0;
var currentLength = 0;
var commonsCurrentLength = 0;
var jvmCurrentLength = 0;

var pb = null;
function initProgress(){
    if (commonsLength && jvmLenght){
        totalLength = +commonsLength + jvmLenght;
        var t = (totalLength/1024/1024).toFixed(2);
        pb = new ProgressBar('total: '+t+"M", 50);

    }
}

function download_commons_and_jvm(cb){
    gutil.log(gutil.colors.green("begin download commons and jvm"));
    console.log(`---------------------------------------------------------------------
  . Start to download the dependencies needed for compilation ...
---------------------------------------------------------------------`);
    var downloader = new Promise((resolve, reject) => {
        var commonLoaded = false;
        var jvmLoaded = false;
        downloadFile(commonUrl, "commons.tar.gz", (length)=>{
            commonsLength = +length;
            initProgress();
        }, (progress)=>{
            commonsCurrentLength = progress.transferred;
            currentLength = +commonsCurrentLength+jvmCurrentLength;
        }, ()=>{
            commonLoaded = true;
            if (jvmLoaded && commonLoaded) resolve();
        });
        // var jvmName = jvmUrl.substr(jvmUrl.lastIndexOf("/"+1, jvmUrl.length));
        // console.log(jvmName);
        // console.log(jvmUrl);
        downloadFile(jvmUrl, "jvm.tar.gz", (length)=>{
            jvmLenght = +length;
            initProgress();
        }, (progress)=>{
            jvmCurrentLength = progress.transferred;
            currentLength = +commonsCurrentLength+jvmCurrentLength;
        }, ()=>{
            jvmLoaded = true;
            if (jvmLoaded && commonLoaded) resolve();
        });
    });
    downloader.then(()=>{
        console.log();
        gutil.log(gutil.colors.green("download commons and jvm completed"));
        cb();
    });
}

function decompress_commons_and_jvm(cb){
    console.log(`---------------------------------------------------------------------
  . Start to decompress the dependencies needed for compilation ...
---------------------------------------------------------------------`);
    gutil.log(gutil.colors.green("begin decompress commons and jvm"));
    var count =0;
    var decompressor = new Promise((resolve, reject) => {
        var commonUnziped = false;
        var jvmUnziped = false;
        targz.decompress({
            src: 'o2server/commons.tar.gz',
            dest: 'o2server',
            tar: {map: function(header){
                count++;
                    var d = new Date();
                    slog("["+dateFormat(d, "HH:MM:ss")+"] " + count +" "+ header.name+" ...");
                //gutil.log(gutil.colors.cyan(header.name), gutil.colors.yellow("..."));
            }}
        }, function(err){
            if(err) {
                gutil.log(gutil.colors.red("decompress error"), ":", gutil.colors.red("common.tar.gz "), err);
            } else {
                commonUnziped = true;
                if (jvmUnziped && commonUnziped) resolve();
            }
        });
        targz.decompress({
            src: 'o2server/jvm.tar.gz',
            dest: 'o2server',
            tar: {map: function(header){
                    count++;
                    var d = new Date();
                    slog("["+dateFormat(d, "HH:MM:ss")+"] " + count +" "+ header.name+" ...");
                    //slog(count +" "+ header.name+" ...");
                    //gutil.log(gutil.colors.cyan(header.name), gutil.colors.yellow("..."));
                }}
        }, function(err){
            if(err) {
                gutil.log(gutil.colors.red("decompress error"), ":", gutil.colors.red("jvm.tar.gz "), err);
            } else {
                jvmUnziped = true;
                if (jvmUnziped && commonUnziped) resolve();
            }
        });
    });
    decompressor.then(()=>{
        gutil.log(gutil.colors.green("decompress commons and jvm completed. " + count+" files"));
        cb();
    });
}

function build_web_minimize(cb) {
    console.log(`---------------------------------------------------------------------
  . Start compiling the web ...
---------------------------------------------------------------------`);

    var dest = 'target/o2server/webServer/';
    var src_min = ['o2web/source/**/*.js', '!**/*.spec.js', '!**/test/**', '!o2web/source/o2_lib/**/*'];
    //var src_min = ['o2web/source/o2_core/**/*.js', '!**/*.spec.js', '!**/test/**', '!o2web/source/o2_lib/**/*'];

    var entries = fg.sync(src_min, { dot: true});
    var size = entries.length;

    var pb = new ProgressBar('total: '+size, 50);
    var doCount = 0;
    return gulp.src(src_min)
        .pipe(uglify())
        .pipe(rename({ extname: '.min.js' }))
        .pipe(gulp.dest(dest))
        .pipe(logger(function(){
            doCount++;
            if (doCount <= size) pb.render({ completed: doCount, total: size, count: doCount});
            if (doCount > size) {console.log();}
        }))
        .pipe(gutil.noop());
}

function build_web_move() {
    var dest = 'target/o2server/webServer/';
    var src_move = ['o2web/source/**/*', '!**/*.spec.js', '!**/test/**'];

    var entries = fg.sync(src_move, { dot: true});
    var size = entries.length;
    var pb = new ProgressBar('total: '+size, 50);
    var doCount = 0;

    return gulp.src(src_move)
        .pipe(gulp.dest(dest))
        .pipe(logger(function(){
            doCount++;
            if (doCount <= size) pb.render({ completed: doCount, total: size, count: doCount});
            if (doCount > size) {console.log();}
        }))
        .pipe(gutil.noop());
}
exports.build_web_move = build_web_move;

function clear_build(cb){
    console.log(`---------------------------------------------------------------------
  . clear old build ...
---------------------------------------------------------------------`);
    var dest = 'target';
    del(dest, { dryRun: true, force: true });
    cb();
}
exports.clear_build = clear_build;

function deploy_server(){
    console.log(`---------------------------------------------------------------------
  . deploy to target ...
---------------------------------------------------------------------`);
    var source1 = ["o2server/store/**/*", "o2server/commons/**/*", "o2server/jvm/**/*", "o2server/configSample/**/*", "o2server/localSample/**/*"];
    source = source1.concat(scriptSource);
    var dest = "target/o2server/servers/"

    var entries = fg.sync(source, { dot: true});
    var size = entries.length;
    var pb = new ProgressBar('total: '+size, 50);
    var doCount = 0;

    return gulp.src(source)
        .pipe(gulp.dest(dest))
        .pipe(logger(function(){
            doCount++;
            if (doCount <= size) pb.render({ completed: doCount, total: size, count: doCount});
            if (doCount > size) {console.log();}
        }));
    //.pipe(gutil.noop());
}

exports.preperation =  gulp.series(download_commons_and_jvm, decompress_commons_and_jvm);

var shell = require('gulp-shell')
exports.build_server = function(){
    console.log(`---------------------------------------------------------------------
  . Start compiling the server ...
---------------------------------------------------------------------`);
    return (shell.task('npm run build_server_script'))();
};
exports.build_web = gulp.series(build_web_minimize, build_web_move);
exports.deploy = deploy_server;
<|endoftext|>


<commit_before>/**
 * Baobab-React Higher Order Component
 * ====================================
 *
 * ES6 state of the art higher order component.
 */
import React from 'react';
import Baobab from 'baobab';
import {curry, solveMapping} from './utils/helpers';
import PropTypes from './utils/prop-types';

const makeError = Baobab.helpers.makeError,
      isPlainObject = Baobab.type.object;

/**
 * Helpers
 */
function displayName(Component) {
  return Component.name || Component.displayName || 'Component';
}

function invalidMapping(name, mapping) {
  throw makeError(
    'baobab-react/higher-order.branch: given cursors mapping is invalid (check the "' + name + '" component).',
    {mapping}
  );
}

/**
 * Root component
 */
function root(tree, Component) {
  if (!(tree instanceof Baobab))
    throw makeError(
      'baobab-react/higher-order.root: given tree is not a Baobab.',
      {target: tree}
    );

  if (typeof Component !== 'function')
    throw Error('baobab-react/higher-order.root: given target is not a valid React component.');

  const name = displayName(Component);

  const ComposedComponent = class extends React.Component {

    // Handling child context
    getChildContext() {
      return {
        tree
      };
    }

    // Render shim
    render() {
      return <Component {...this.props} />;
    }
  };

  ComposedComponent.displayName = 'Rooted' + name;
  ComposedComponent.childContextTypes = {
    tree: PropTypes.baobab
  };

  return ComposedComponent;
}

/**
 * Branch component
 */
function branch(cursors, Component) {
  if (typeof Component !== 'function')
    throw Error('baobab-react/higher-order.branch: given target is not a valid React component.');

  const name = displayName(Component);

  if (!isPlainObject(cursors) && typeof cursors !== 'function')
    invalidMapping(name, cursors);

  const ComposedComponent = class extends React.Component {

    // Building initial state
    constructor(props, context) {
      super(props, context);

      if (cursors) {
        const mapping = solveMapping(cursors, props, context);

        if (!mapping)
          invalidMapping(name, mapping);

        // Creating the watcher
        this.watcher = this.context.tree.watch(mapping);

        // Hydrating initial state
        this.state = this.watcher.get();
      }
    }

    // On component mount
    componentWillMount() {

      // Creating dispatcher
      this.dispatcher = (fn, ...args) => fn(this.context.tree, ...args);

      if (!this.watcher)
        return;

      const handler = () => {
        if (this.watcher)
          this.setState(this.watcher.get());
      };

      this.watcher.on('update', handler);
    }

    // Render shim
    render() {
      const {decoratedComponentRef, ...props} = {this.props};
      const suppl = {dispatch: this.dispatcher};

      return <Component {...props} {...suppl} {...this.state} ref={decoratedComponentRef} />;
    }

    // On component unmount
    componentWillUnmount() {
      if (!this.watcher)
        return;

      // Releasing watcher
      this.watcher.release();
      this.watcher = null;
    }

    // On new props
    componentWillReceiveProps(props) {
      if (!this.watcher || typeof cursors !== 'function')
        return;

      const mapping = solveMapping(cursors, props, this.context);

      if (!mapping)
        invalidMapping(name, mapping);

      // Refreshing the watcher
      this.watcher.refresh(mapping);
      this.setState(this.watcher.get());
    }
  };

  ComposedComponent.displayName = 'Branched' + name;
  ComposedComponent.contextTypes = {
    tree: PropTypes.baobab
  };

  return ComposedComponent;
}

// Currying the functions so that they could be used as decorators
const curriedRoot = curry(root, 2),
      curriedBranch = curry(branch, 2);

export {curriedRoot as root, curriedBranch as branch};
<commit_msg>Fixed typo<commit_after>/**
 * Baobab-React Higher Order Component
 * ====================================
 *
 * ES6 state of the art higher order component.
 */
import React from 'react';
import Baobab from 'baobab';
import {curry, solveMapping} from './utils/helpers';
import PropTypes from './utils/prop-types';

const makeError = Baobab.helpers.makeError,
      isPlainObject = Baobab.type.object;

/**
 * Helpers
 */
function displayName(Component) {
  return Component.name || Component.displayName || 'Component';
}

function invalidMapping(name, mapping) {
  throw makeError(
    'baobab-react/higher-order.branch: given cursors mapping is invalid (check the "' + name + '" component).',
    {mapping}
  );
}

/**
 * Root component
 */
function root(tree, Component) {
  if (!(tree instanceof Baobab))
    throw makeError(
      'baobab-react/higher-order.root: given tree is not a Baobab.',
      {target: tree}
    );

  if (typeof Component !== 'function')
    throw Error('baobab-react/higher-order.root: given target is not a valid React component.');

  const name = displayName(Component);

  const ComposedComponent = class extends React.Component {

    // Handling child context
    getChildContext() {
      return {
        tree
      };
    }

    // Render shim
    render() {
      return <Component {...this.props} />;
    }
  };

  ComposedComponent.displayName = 'Rooted' + name;
  ComposedComponent.childContextTypes = {
    tree: PropTypes.baobab
  };

  return ComposedComponent;
}

/**
 * Branch component
 */
function branch(cursors, Component) {
  if (typeof Component !== 'function')
    throw Error('baobab-react/higher-order.branch: given target is not a valid React component.');

  const name = displayName(Component);

  if (!isPlainObject(cursors) && typeof cursors !== 'function')
    invalidMapping(name, cursors);

  const ComposedComponent = class extends React.Component {

    // Building initial state
    constructor(props, context) {
      super(props, context);

      if (cursors) {
        const mapping = solveMapping(cursors, props, context);

        if (!mapping)
          invalidMapping(name, mapping);

        // Creating the watcher
        this.watcher = this.context.tree.watch(mapping);

        // Hydrating initial state
        this.state = this.watcher.get();
      }
    }

    // On component mount
    componentWillMount() {

      // Creating dispatcher
      this.dispatcher = (fn, ...args) => fn(this.context.tree, ...args);

      if (!this.watcher)
        return;

      const handler = () => {
        if (this.watcher)
          this.setState(this.watcher.get());
      };

      this.watcher.on('update', handler);
    }

    // Render shim
    render() {
      const {decoratedComponentRef, ...props} = this.props;
      const suppl = {dispatch: this.dispatcher};

      return <Component {...props} {...suppl} {...this.state} ref={decoratedComponentRef} />;
    }

    // On component unmount
    componentWillUnmount() {
      if (!this.watcher)
        return;

      // Releasing watcher
      this.watcher.release();
      this.watcher = null;
    }

    // On new props
    componentWillReceiveProps(props) {
      if (!this.watcher || typeof cursors !== 'function')
        return;

      const mapping = solveMapping(cursors, props, this.context);

      if (!mapping)
        invalidMapping(name, mapping);

      // Refreshing the watcher
      this.watcher.refresh(mapping);
      this.setState(this.watcher.get());
    }
  };

  ComposedComponent.displayName = 'Branched' + name;
  ComposedComponent.contextTypes = {
    tree: PropTypes.baobab
  };

  return ComposedComponent;
}

// Currying the functions so that they could be used as decorators
const curriedRoot = curry(root, 2),
      curriedBranch = curry(branch, 2);

export {curriedRoot as root, curriedBranch as branch};
<|endoftext|>


<commit_before>var express = require("express");
var app = express();
var router = express.Router();
var path = __dirname + '/views/';
var lib = __dirname + '/lib/';

router.use(function (req,res,next) {
  console.log("/" + req.method);
  next();
});

router.get("/",function(req,res){
  res.sendFile(path + "index.html");
});

router.get("/about",function(req,res){
  res.sendFile(path + "about.html");
});

router.get("/contact",function(req,res){
  res.sendFile(path + "contact.html");
});

// will server as api for testing
router.get("/data",function(req,res){
  var q = url.parse(req.url, true).query;
  console.log(q);
  // try {
  //   var txt = q.user + " is your user request";
  // } catch(err) {
  //   var txt = "incorrect query string, try 'user'";
  // }
  //res.end(txt);
});

app.use("/",router);

app.use("*",function(req,res){
  res.sendFile(path + "404.html");
  res.send('404 Error: Invalid Path.', 404);
});

app.listen(3000,function(){
  console.log("Live at Port 3000");
});
<commit_msg>update routing and response of /data<commit_after>var express = require("express");
var app = express();
var router = express.Router();
var path = __dirname + '/views/';
var lib = __dirname + '/lib/';
var bodyParser = require('body-parser');
var yt = require('./lib/yelp-testing.js');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

router.use(function (req,res,next) {
  console.log("/" + req.method);
  next();
});

router.get("/",function(req,res){
  res.sendFile(path + "index.html");
});

router.get("/about",function(req,res){
  res.sendFile(path + "about.html");
});

router.get("/contact",function(req,res){
  res.sendFile(path + "contact.html");
});

// will server as api for testing
router.get("/data",function(req,res){
  var lat = req.query.lat;
  var long = req.query.long;

  // just for testing display, remove when correct JSON returned from getYelpFood
  var ob = {
      "lat": lat,
      "long": long
  }
  // everything works but I -think-
  // I need a callback based on the value returned from getYelpFood
  // or a callback in yelp-testing function to return data

  //var final = yt.getYelpFood(lat, long);
  //res.json(ob);
  if(lat == undefined || long == undefined) {
    res.send("Please specify query string with lat and long ex. /data?lat=100&long=100");
  } else {
    res.json(ob);
  }

});

app.use("/",router);

app.use("*",function(req,res){
  res.sendFile(path + "404.html");
  res.send('404 Error: Invalid Path.', 404);
});

app.listen(3000,function(){
  console.log("Live at Port 3000");
});
<|endoftext|>


<commit_before>var $jq = jQuery.noConflict(true);

function updateSelectors() {
    if (window.location.pathname !== '/') {
        $jq('a[href="' + window.location.pathname + '"].task-link').addClass("white-text");
    }

}

$jq(document).ready(function() {
    updateSelectors();
});
<commit_msg>update colspan of th.pane to 4 in sidebar<commit_after>var $jq = jQuery.noConflict(true);

function updateSelectors() {
    if (window.location.pathname !== '/') {
        $jq('a[href="' + window.location.pathname + '"].task-link').addClass("white-text");
    }
}

$jq(document).change(function() {
    updateSelectors();
});

$jq(document).bind('DOMSubtreeModified', function () {
    $jq('th.pane').attr('colspan', 4);
});
<|endoftext|>


<commit_before>"use strict";

var fluid = require("infusion"),
    gpii = fluid.registerNamespace("gpii");

require("gpii-nexus-client");

var nexusHost = "localhost";
var nexusPort = 9081;
var updateDelayMs = 1000;
var sinPeriodMs = 10000;

fluid.defaults("gpii.nexus.fakeSensor", {
    gradeNames: ["gpii.nexusWebSocketBoundComponent"],
    members: {
        nexusHost: nexusHost,
        nexusPort: nexusPort,
        nexusBoundModelPath: "sensorData",
        sendsChangesToNexus: true,
        managesPeer: true
    },
    invokers: {
        "update": {
            "funcName": "gpii.nexus.fakeSensor.update",
            "args": "{that}"
        }
    },
    listeners: {
        "onPeerDestroyed.exitProcess": {
            funcName: "gpii.nexus.fakeSensor.exitProcess"
        }
    }
});

fluid.defaults("gpii.nexus.fakeSensor.sinValue", {
    gradeNames: ["gpii.nexus.fakeSensor"],
    members: {
        nexusPeerComponentPath: "fakeSensor",
        nexusPeerComponentOptions: {
            type: "gpii.nexus.fakeSensor"
        }
    },
    model: {
        sensorData: {
            name: "Fake Sensor",
            rangeMin: -1,
            rangeMax: 1,
            value: 0
        }
    },
        invokers: {
        "getFakeSensorValue": {
            "funcName": "gpii.nexus.fakeSensor.getFakeSensorValueSin"
        }
    }
});

fluid.defaults("gpii.nexus.fakeSensor.pHValue", {
    gradeNames: ["gpii.nexus.fakeSensor"],
    members: {
        nexusPeerComponentPath: "fakeSensorPH",
        nexusPeerComponentOptions: {
            type: "gpii.nexus.fakeSensorPH"
        }
    },
    model: {
        sensorData: {
            name: "Fake pH Sensor",
            rangeMin: 0,
            rangeMax: 14,
            value: 7
        }
    },
        invokers: {
        "getFakeSensorValue": {
            "funcName": "gpii.nexus.fakeSensor.getFakeSensorValuePH"
        }
    }
});

gpii.nexus.fakeSensor.exitProcess = function () {
    process.exit();
};

gpii.nexus.fakeSensor.update = function (that) {
    var nextValue = that.getFakeSensorValue();
    console.log("Fake sensor: " + nextValue);
    that.applier.change("sensorData.value", nextValue);
    setTimeout(function () {
        gpii.nexus.fakeSensor.update(that);
    }, updateDelayMs);
};

// A fairly even sin-based sensor value that moves between -1 and 1
gpii.nexus.fakeSensor.getFakeSensorValueSin = function () {
    return Math.sin((new Date().getTime() % sinPeriodMs) * Math.PI * 2 / sinPeriodMs);
};

// a pH sensor type value between 0 and 14
gpii.nexus.fakeSensor.getFakeSensorValuePH = function () {
    return gpii.nexus.fakeSensor.randomFloat(0,14);
};

gpii.nexus.fakeSensor.randomInt = function(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
};

gpii.nexus.fakeSensor.randomFloat = function(min, max) {
    return Math.random() * (max - min) + min;
};

var fakeSensor = gpii.nexus.fakeSensor.sinValue();

var fakeSensorPH = gpii.nexus.fakeSensor.pHValue();

process.on("SIGINT", function () {
    fakeSensor.destroyNexusPeerComponent();
    fakeSensorPH.destroyNexusPeerComponent();
});

fakeSensor.update();
fakeSensorPH.update();
<commit_msg>GPII-2190: make fakeSensor update time configurable.<commit_after>"use strict";

var fluid = require("infusion"),
    gpii = fluid.registerNamespace("gpii");

require("gpii-nexus-client");

var nexusHost = "localhost";
var nexusPort = 9081;

fluid.defaults("gpii.nexus.fakeSensor", {
    gradeNames: ["gpii.nexusWebSocketBoundComponent"],
    model: {
        fakeSensorConfig: {
            updateDelayMs: 1000
        }
    },
    members: {
        nexusHost: nexusHost,
        nexusPort: nexusPort,
        nexusBoundModelPath: "sensorData",
        sendsChangesToNexus: true,
        managesPeer: true
    },
    invokers: {
        "update": {
            "funcName": "gpii.nexus.fakeSensor.update",
            "args": "{that}"
        }
    },
    listeners: {
        "onPeerDestroyed.exitProcess": {
            funcName: "gpii.nexus.fakeSensor.exitProcess"
        }
    }
});

fluid.defaults("gpii.nexus.fakeSensor.sinValue", {
    gradeNames: ["gpii.nexus.fakeSensor"],
    members: {
        nexusPeerComponentPath: "fakeSensor",
        nexusPeerComponentOptions: {
            type: "gpii.nexus.fakeSensor"
        }
    },
    model: {
        fakeSensorConfig: {
            updateDelayMs: 2000
        },
        sensorData: {
            name: "Fake Sensor",
            rangeMin: -1,
            rangeMax: 1,
            value: 0
        }
    },
        invokers: {
        "getFakeSensorValue": {
            "funcName": "gpii.nexus.fakeSensor.getFakeSensorValueSin",
            "args": ["{that}"]
        }
    }
});

fluid.defaults("gpii.nexus.fakeSensor.pHValue", {
    gradeNames: ["gpii.nexus.fakeSensor"],
    members: {
        nexusPeerComponentPath: "fakeSensorPH",
        nexusPeerComponentOptions: {
            type: "gpii.nexus.fakeSensorPH"
        }
    },
    model: {
        fakeSensorConfig: {
            updateDelayMs: 10000
        },
        sensorData: {
            name: "Fake pH Sensor",
            rangeMin: 0,
            rangeMax: 14,
            value: 7
        }
    },
        invokers: {
        "getFakeSensorValue": {
            "funcName": "gpii.nexus.fakeSensor.getFakeSensorValuePH"
        }
    }
});

gpii.nexus.fakeSensor.exitProcess = function () {
    process.exit();
};

gpii.nexus.fakeSensor.update = function (that) {
    var nextValue = that.getFakeSensorValue();
    console.log(that.model.sensorData.name + ": " + nextValue);
    that.applier.change("sensorData.value", nextValue);
    setTimeout(function () {
        gpii.nexus.fakeSensor.update(that);
    }, that.model.fakeSensorConfig.updateDelayMs);
};

// A fairly even sin-based sensor value that moves between -1 and 1
// Calculates the sin period based on the update frequency
gpii.nexus.fakeSensor.getFakeSensorValueSin = function (that) {
    var sinPeriodMs = that.model.fakeSensorConfig.updateDelayMs * 10;
    return Math.sin((new Date().getTime() % sinPeriodMs) * Math.PI * 2 / sinPeriodMs);
};

// a pH sensor type value between 0 and 14
gpii.nexus.fakeSensor.getFakeSensorValuePH = function () {
    return gpii.nexus.fakeSensor.randomFloat(0,14);
};

gpii.nexus.fakeSensor.randomInt = function(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
};

gpii.nexus.fakeSensor.randomFloat = function(min, max) {
    return Math.random() * (max - min) + min;
};

var fakeSensor = gpii.nexus.fakeSensor.sinValue();

var fakeSensorPH = gpii.nexus.fakeSensor.pHValue();

process.on("SIGINT", function () {
    fakeSensor.destroyNexusPeerComponent();
    fakeSensorPH.destroyNexusPeerComponent();
});

fakeSensor.update();
fakeSensorPH.update();
<|endoftext|>