<commit_before>var express = require('express');
var router = express.Router();
var request = require('request');

var mongoose = require('mongoose');

var Highlight = require('../models/Highlight');
var Reaction = require('../models/Reaction');
var Video = require('../models/Video');

var fs = require('fs');
var youtubedl = require('youtube-dl');
var ffmpeg = require('fluent-ffmpeg');

var cron = require('node-cron');

cron.schedule('* * * * *', function() {
    Video.find()
    .exec(function (err, videos) {
        for (var i = 0; i < videos.length; i++) {
            generate_highlight(videos[i].video_id);
        }
    });
});

/*
 * GET highlight info
 * Query: video_id (?video_id=xxxxx)
 */
router.get('/', function(req, res, next) {
    //generate_highlight(req.query.video_id);
    Highlight.findOne({
        video_id: req.query.video_id
    })
    .exec(function (err, highlight) {
        if (err) return console.log(err);
        res.send(highlight);
    });
});

function generate_highlight(query_video_id) {
    console.log("generate highlight for " + query_video_id);
    var highlightId = 0;

    Reaction.find({
        video_id: query_video_id
    })
    .exec(function (err, reactions) {
        var happinessAt = {};
        var maxTime = 0;
        /* Build a map (floor(time) -> listof<happiness_value>)
           and find maximum value of timestamp. */
        for (var i = 0; i < reactions.length; i++) {
            var time = parseInt(reactions[i].time / 1000);
            if (time > maxTime) maxTime = time;
            happinessAt[time] = happinessAt[time] || [];
            happinessAt[time].push(reactions[i].happiness);
        }
        /* Calculate the average of happiness values of each timestamp.
           Create an array whose index is floor(time) and value is the average. */
        var happinessAverage = Array(maxTime + 1).fill(0.0);
        for (var time in happinessAt) {
            var sum = happinessAt[time].reduce(function(a, b) { return a + b; });
            var avg = sum / happinessAt[time].length;
            happinessAverage[time] = avg;
        }
        /* Find the time region where happinessAverage > 0.7. (This is an empirical value)
           In order to ignore small holes, at most 3 consecutive disqualified values are tolerated.
           If a region is found, highlight is stored in the database, with 3 seconds back and front of the actual highlight.
           A region should be longer than 3 seconds. */
        var isHighlight = false;
        var tolerateCount = 0;
        var regionStartIndex = 0;
        var regionEndIndex = 0;
        for (var i = 0; i < happinessAverage.length; i++) {
            if (happinessAverage[i] > 0.7) {
                if (!isHighlight) {
                    isHighlight = true;
                    regionStartIndex = i;
                    console.log("regionStartIndex: " + regionStartIndex);
                }
                tolerateCount = 0;
            }
            else {
                if (isHighlight) {
                    tolerateCount += 1;
                    if (tolerateCount > 6) {
                        isHighlight = false;
                        regionEndIndex = i;
                        if (regionEndIndex - regionStartIndex > 5) {
                            var newHighlight = new Highlight({
                                video_id: query_video_id,
                                start: regionStartIndex,
                                end: regionEndIndex,
                                highlight_url: "./" + query_video_id + '_highlight_' + highlightId + '.mp4'
                            });
                            newHighlight.save();
                            highlightId += 1;
                        }
                    }
                }
            }
        }
    });

    if (highlightId >= 0) {
        var video = youtubedl('http://www.youtube.com/watch?v=' + query_video_id, [], {maxBuffer: 100000*1024});
        video.on('info', function(info) {
            console.log('Download started');
            console.log('filename: ' + info._filename);
            console.log('size: ' + info.size);
        });
        video.pipe(fs.createWriteStream(query_video_id + '.mp4'));

        video.on('end', function() {
            console.log('Download done');
            Highlight.find({
                video_id: query_video_id
            })
            .exec(function (err, highlights) {
                for (var i = 0; i < highlights.length; i++) {
                    var start = highlights[i].start;
                    var end = highlights[i].end;

                    start -= 3;
                    if (start < 0) start = 0;
                    var duration = end - start;
                    console.log("ffmpeg start: " + start);
                    console.log("ffmpeg duration: " + duration);
                    console.log(query_video_id + '.mp4');

                    ffmpeg('./' + query_video_id + '.mp4')
                    .setStartTime(start)
                    .setDuration(parseInt(duration))
                    .output('./' + query_video_id + '_highlight_' + i + '.mp4')
                    .on('end', function(err) {
                        if(!err)
                        {
                            console.log('conversion Done');
                        }
                    })
                    .on('error', function(err){
                        console.error(err);
                    }).run();
                }
            });
        });
    }
}

/*
 * POST save highlight info to DB
 * Parameters: video_id, start, end, highlight_url
 */
router.post('/save', function(req, res, next) {
    var newHighlight = new Highlight({
        video_id: req.body.video_id,
        start: req.body.start,
        end: req.body.end,
        highlight_url: req.body.highlight_url,
    });

    newHighlight.save();
    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end();
});

module.exports = router;
<commit_msg>Change video location to public/ and change highlight generating period to 5 min.<commit_after>var express = require('express');
var router = express.Router();
var request = require('request');

var mongoose = require('mongoose');

var Highlight = require('../models/Highlight');
var Reaction = require('../models/Reaction');
var Video = require('../models/Video');

var fs = require('fs');
var youtubedl = require('youtube-dl');
var ffmpeg = require('fluent-ffmpeg');

var cron = require('node-cron');

cron.schedule('*/5 * * * *', function() {
    Video.find()
    .exec(function (err, videos) {
        for (var i = 0; i < videos.length; i++) {
            generate_highlight(videos[i].video_id);
        }
    });
});

/*
 * GET highlight info
 * Query: video_id (?video_id=xxxxx)
 */
router.get('/', function(req, res, next) {
    //generate_highlight(req.query.video_id);
    Highlight.findOne({
        video_id: req.query.video_id
    })
    .exec(function (err, highlight) {
        if (err) return console.log(err);
        if (!highlight) {
            console.log("No highlight")
        }
        else {
            res.end("http://143.248.198.101:3000/" + highlight.highlight_url);
        }
    });
});

function generate_highlight(query_video_id) {
    console.log("generate highlight for " + query_video_id);
    var highlightId = 0;

    Reaction.find({
        video_id: query_video_id
    })
    .exec(function (err, reactions) {
        var happinessAt = {};
        var maxTime = 0;
        /* Build a map (floor(time) -> listof<happiness_value>)
           and find maximum value of timestamp. */
        for (var i = 0; i < reactions.length; i++) {
            var time = parseInt(reactions[i].time / 1000);
            if (time > maxTime) maxTime = time;
            happinessAt[time] = happinessAt[time] || [];
            happinessAt[time].push(reactions[i].happiness);
        }
        /* Calculate the average of happiness values of each timestamp.
           Create an array whose index is floor(time) and value is the average. */
        var happinessAverage = Array(maxTime + 1).fill(0.0);
        for (var time in happinessAt) {
            var sum = happinessAt[time].reduce(function(a, b) { return a + b; });
            var avg = sum / happinessAt[time].length;
            happinessAverage[time] = avg;
        }
        /* Find the time region where happinessAverage > 0.7. (This is an empirical value)
           In order to ignore small holes, at most 3 consecutive disqualified values are tolerated.
           If a region is found, highlight is stored in the database, with 3 seconds back and front of the actual highlight.
           A region should be longer than 3 seconds. */
        var isHighlight = false;
        var tolerateCount = 0;
        var regionStartIndex = 0;
        var regionEndIndex = 0;
        for (var i = 0; i < happinessAverage.length; i++) {
            if (happinessAverage[i] > 0.7) {
                if (!isHighlight) {
                    isHighlight = true;
                    regionStartIndex = i;
                    console.log("regionStartIndex: " + regionStartIndex);
                }
                tolerateCount = 0;
            }
            else {
                if (isHighlight) {
                    tolerateCount += 1;
                    if (tolerateCount > 6) {
                        isHighlight = false;
                        regionEndIndex = i;
                        if (regionEndIndex - regionStartIndex > 5) {
                            var newHighlight = new Highlight({
                                video_id: query_video_id,
                                start: regionStartIndex,
                                end: regionEndIndex,
                                highlight_url: query_video_id + '_highlight_' + highlightId + '.mp4'
                            });
                            newHighlight.save();
                            highlightId += 1;
                        }
                    }
                }
            }
        }
    });

    if (highlightId >= 0) {
        var video = youtubedl('http://www.youtube.com/watch?v=' + query_video_id, [], {maxBuffer: 100000*1024});
        video.on('info', function(info) {
            console.log('Download started');
            console.log('filename: ' + info._filename);
            console.log('size: ' + info.size);
        });
        video.pipe(fs.createWriteStream('./public/' + query_video_id + '.mp4'));

        video.on('end', function() {
            console.log('Download done');
            Highlight.find({
                video_id: query_video_id
            })
            .exec(function (err, highlights) {
                for (var i = 0; i < highlights.length; i++) {
                    var start = highlights[i].start;
                    var end = highlights[i].end;

                    start -= 3;
                    if (start < 0) start = 0;
                    var duration = end - start;
                    console.log("ffmpeg start: " + start);
                    console.log("ffmpeg duration: " + duration);
                    console.log(query_video_id + '.mp4');

                    ffmpeg('./public/' + query_video_id + '.mp4')
                    .setStartTime(start)
                    .setDuration(parseInt(duration))
                    .output('./public/' + query_video_id + '_highlight_' + i + '.mp4')
                    .on('end', function(err) {
                        if(!err)
                        {
                            console.log('conversion Done');
                        }
                    })
                    .on('error', function(err){
                        console.error(err);
                    }).run();
                }
            });
        });
    }
}

/*
 * POST save highlight info to DB
 * Parameters: video_id, start, end, highlight_url
 */
router.post('/save', function(req, res, next) {
    var newHighlight = new Highlight({
        video_id: req.body.video_id,
        start: req.body.start,
        end: req.body.end,
        highlight_url: req.body.highlight_url,
    });

    newHighlight.save();
    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end();
});

module.exports = router;
<|endoftext|>


<commit_before>define(['config','helper/view','cache','model.manage','msg'],function(config,View,Cache){
	var handerObj = $(Schhandler);

	var navTarget = $('#pageNav'),
		addTarget = $('#addGroup'),
		listTarget = $('#groupList'),
		editTarget = $('#groupEdit');

	var userList,
		myid,
		g2k,
		preplist;

	function init(){
		handerObj.triggerHandler('manage:user');
		handerObj.triggerHandler('manage:alluser');
		handerObj.triggerHandler('manage:grouplist');
	}

	function userloadSuc(e,d){
		myid = d.id;
		var view = new View({
			target : navTarget,
			tplid : 'manage.user',
			data : d,
		});
		view.createPanel();
	}

	function alluserloadSuc(e,d){
		userList = Cache.get('alluser2key');
		var view = new View({
			target : $("#userList"),
			tplid : 'manage.userlist',
			data : {
				list : userList
			},
			handlers : {
				'.btn-search' : {
					'click' : searchUser
				}
			}
		});
		view.createPanel();
	}

	function createSuc(e,d){
		addTarget.addClass('hide');
		listTarget.removeClass('hide');
		var obj = d.list;
		if(obj.type == 3 && !obj.parent){
		var view = new View({
			target : $('#prepYearList'),
			tplid : 'manage.prep.year',
			data : {
				list : [obj]
			}
		});
		view.appendPanel();
		}

		var view = new View({
			target : $("#groupList"),
			tplid : 'manage.group.list',
			data : {
				list : [d.list],
				show : 0
			}
		});
		view.appendPanel();

	}

	function groupLoad(e,d){
		g2k = d.g2k;
		preplist = d.prep;
		if(d.school){
			$('.group-type').eq(0).attr('disabled',true);
		}
		if(d.haspt){
			$('.prep-type').attr('disabled',true);
		}
		var view = new View({
			target : $('#prepYearList'),
			tplid : 'manage.prep.year',
			data : {
				list : d.prep,
				ul : userList
			}
		});
		view.appendPanel();

		var view = new View({
			target : $("#groupList"),
			tplid : 'manage.group.list',
			data : {
				list : d.list,
				show : 1
			}
		});
		view.createPanel();
	}

	function appSuc(e,d){

		if(d.type == 1){
			$('.group'+d.id).html('审核通过');
		}else{
			$('.group'+d.id).html('审核不通过');
		}
	}

	function searchUser(e){
		var t = $(e.target);
		var v = t.prevAll('.search-member').val();
		var p = t.parents('td');
		console.log(v);
		if(v == ''){
			p.find('.group-members').removeClass('hide');
		}else{
			for(var i in userList){
				var item = userList[i];
				if(item.nick.indexOf(v)<0){
					p.find('.mb'+i).addClass('hide');
				}else{
					p.find('.mb'+i).removeClass('hide');
				}
			}
		}
	}

	function groupOne(e,d){
		addTarget.addClass('hide');
		listTarget.addClass('hide');
		editTarget.removeClass('hide');
		d.ul = userList;
		d.my = myid;
		d.prep = preplist;

		//var data = g2k[id];
		var view = new View({
			target : editTarget,
			tplid : 'manage.group.edit',
			data : d,
			after : function(){
				$('#editGroupBtn').bind('click',function(){
					editgroup(d.id);
				});
			},
			handlers : {
				'.btn-search' : {
					'click' : searchUser
				}
			}
		});
		view.createPanel();
	}

	function showEdit(id){
		handerObj.triggerHandler('manage:groupinfo',id)
		// addTarget.hide();
		// listTarget.hide();
		// editTarget.show();
		// var data = g2k[id];
		// console.log(data);
		// var view = new View({
		// 	target : editTarget,
		// 	tplid : 'manage.group.edit',
		// 	data : data,
		// });
		// view.createPanel();
	}

	function modifySuc(){
		addTarget.addClass('hide');
		listTarget.removeClass('hide');
		editTarget.addClass('hide');
	}

	var handlers = {
		'manage:appsuc' : appSuc,
		'manage:createsuc' : createSuc,
		'manage:userloadsuc' : userloadSuc,
		'manage:alluserloadsuc' : alluserloadSuc,
		'manage:groupload' : groupLoad,
		'manage:groupinfosuc' : groupOne,
		'modifysuc' : modifySuc
	}

	for(var i in handlers){
		handerObj.bind(i,handlers[i]);
	}

	$('#groupList').bind('click',function(e){
		var target = $(e.target),
			cmd = target.attr('cmd');

			var id = target.attr('data-id');

		switch(cmd){
			case 'edit':
				showEdit(id);
				break;
			case 'pass':
				handerObj.triggerHandler('manage:approve',{
					groupId:id,
					validateText : 'pass',
					validateStatus : 1
				});
			break;
			case 'notpass':
				handerObj.triggerHandler('manage:approve',{
					groupId:id,
					validateText : 'notpass',
					validateStatus : 0
				});
			break;
		}
	});

	var editgroup = function(id){
		var name = editTarget.find('.group-name').val();
		var desc = editTarget.find('.group-desc').val();
		var members = [],
			manages = [];
		editTarget.find('.check-member:checked').each(function(){
			members.push($(this).val());
		});
		editTarget.find('.check-manage:checked').each(function(){
			manages.push($(this).val());
		});
		if(name == ''){
			handerObj.triggerHandler('msg:err',77);
			return;
		}
		var obj = {
			groupId : id,
			name : name,
			content : desc,
			members : members,
			managers : manages,
		}
		//console.log(obj);
		handerObj.triggerHandler('manage:modify',obj);
	};

	$('#newGroupBtn').bind('click',function(e){
		var gn = $('#groupName').val(),
			type = parseInt($('.group-type:checked').val()),
			desc = $("#desc").val();

		var ul = [],
			ml = [];
		//managers
		$(".check-member:checked").each(function(){
			ul.push($(this).val());
		});
		$(".check-manage:checked").each(function(){
			ml.push($(this).val());
		});
		var pid = 0,
			grade = 0,
			tag = 0,
			pt = 0;
		if(type == 3){
			var tag =  $('.check-prep:checked');
			if(tag){
				pid = parseInt(tag.val());
			}
			if(pid){
				grade = $('.check-grade:checked').val();
				tag = $('.check-tag:checked').val();
			}
		}else if(type == 2){
			if($('.prep-type:checked').length){
				pt = 1;
			}
		}

		var obj = {
			name : gn,
			content : desc,
			status : 0,
			type : type,
			members : ul,
			managers : ml,
		}
		if(pt){
			obj.pt = pt;
		}

		if(pid){
			var parent = $('.check-prepyear:checked').val();
			if(parent){
				obj.parentId = parent;
			}
			if(grade){
				obj.grade = grade;
			}
			if(tag){
				obj.tag = tag;
			}

			if(type == 3){
				if(!parent){
					alert('备课小组必须选择学年！');
					return;
				}
				if((!grade || !tag)){
					alert('备课小组必须选择年级和科目！');
					return;
				}
			}
			obj.name = config.grade[grade]+config.tag[tag];
		}else{
			if(type == 3){

			}
		}

		if(obj.name == ''){
			alert('小组名称不能为空!');
			return;
		}
		//return ;

		handerObj.triggerHandler('manage:create',obj);
	});

	$('#aside a').bind('click',function(e){
		var target = $(e.target),
			type = target.attr('type');
		if(type == 'add'){
		addTarget.removeClass('hide');
		listTarget.addClass('hide');
		editTarget.addClass('hide');
		}else{
		addTarget.addClass('hide');
		listTarget.removeClass('hide');
		editTarget.addClass('hide');

		}
	})

	$('.group-type').bind('click',function(e){
		var v = $(this).val();
		if(v == 3){
			$('#prepYear').removeClass('hide');
			if($('.check-prep:checked').val() == 1){
				$('#prepTag').removeClass('hide');
			}
			//$('#prepTag').removeClass('hide');
		}else{
			$('#prepYear').addClass('hide');
			$('#prepTag').addClass('hide');
			$('#groupName').attr('disabled',false);
		}
	});

	$('.check-prep').bind('click',function(e){
		var v = $(this).val();
		if(v == 1){
			$('#prepTag').removeClass('hide');
			$('#groupName').attr('disabled',true);
		}else{
			$('#prepTag').addClass('hide');
			$('#groupName').attr('disabled',false);
		}
	});

	$('.check-grade').bind('click',function(e){
		var v = $(this).val();
		var tag = $('.check-tag:checked').val();
		var n = config.grade[v];
		if(tag){
			n += config.tag[v];
		}
		$('#groupName').val(n);
	});

	$('.check-tag').bind('click',function(e){
		var v = $(this).val();
		var grade = $('.check-grade:checked').val();
		var n = config.tag[v];
		if(grade){
			n = config.grade[grade] + n;
		}
		$('#groupName').val(n);
	});

	return {
		init : init
	}
});<commit_msg>bug fix<commit_after>define(['config','helper/view','cache','model.manage','msg'],function(config,View,Cache){
	var handerObj = $(Schhandler);

	var navTarget = $('#pageNav'),
		addTarget = $('#addGroup'),
		listTarget = $('#groupList'),
		editTarget = $('#groupEdit');

	var userList,
		myid,
		g2k,
		preplist;

	function init(){
		handerObj.triggerHandler('manage:user');
		handerObj.triggerHandler('manage:alluser');
		handerObj.triggerHandler('manage:grouplist');
	}

	function userloadSuc(e,d){
		myid = d.id;
		var view = new View({
			target : navTarget,
			tplid : 'manage.user',
			data : d,
		});
		view.createPanel();
	}

	function alluserloadSuc(e,d){
		userList = Cache.get('alluser2key');
		var view = new View({
			target : $("#userList"),
			tplid : 'manage.userlist',
			data : {
				list : userList
			},
			handlers : {
				'.btn-search' : {
					'click' : searchUser
				}
			}
		});
		view.createPanel();
	}

	function createSuc(e,d){
		addTarget.addClass('hide');
		listTarget.removeClass('hide');
		var obj = d.list;
		if(obj.type == 3 && !obj.parent){
		var view = new View({
			target : $('#prepYearList'),
			tplid : 'manage.prep.year',
			data : {
				list : [obj]
			}
		});
		view.appendPanel();
		}

		var view = new View({
			target : $("#groupList"),
			tplid : 'manage.group.list',
			data : {
				list : [d.list],
				show : 0
			}
		});
		view.appendPanel();

	}

	function groupLoad(e,d){
		g2k = d.g2k;
		preplist = d.prep;
		if(d.school){
			$('.group-type').eq(0).attr('disabled',true);
		}
		if(d.haspt){
			$('.prep-type').attr('disabled',true);
		}
		var view = new View({
			target : $('#prepYearList'),
			tplid : 'manage.prep.year',
			data : {
				list : d.prep,
				ul : userList
			}
		});
		view.appendPanel();

		var view = new View({
			target : $("#groupList"),
			tplid : 'manage.group.list',
			data : {
				list : d.list,
				show : 1
			}
		});
		view.createPanel();
	}

	function appSuc(e,d){

		if(d.type == 1){
			$('.group'+d.id).html('审核通过');
		}else{
			$('.group'+d.id).html('审核不通过');
		}
	}

	function searchUser(e){
		var t = $(e.target);
		var v = t.prevAll('.search-member').val();
		var p = t.parents('td');
		if(v == ''){
			p.find('.group-members').removeClass('hide');
		}else{
			for(var i in userList){
				var item = userList[i];
				if(item.nick.indexOf(v)<0){
					p.find('.mb'+i).addClass('hide');
				}else{
					p.find('.mb'+i).removeClass('hide');
				}
			}
		}
	}

	function groupOne(e,d){
		addTarget.addClass('hide');
		listTarget.addClass('hide');
		editTarget.removeClass('hide');
		d.ul = userList;
		d.my = myid;
		d.prep = preplist;

		//var data = g2k[id];
		var view = new View({
			target : editTarget,
			tplid : 'manage.group.edit',
			data : d,
			after : function(){
				$('#editGroupBtn').bind('click',function(){
					editgroup(d.id);
				});
			},
			handlers : {
				'.btn-search' : {
					'click' : searchUser
				}
			}
		});
		view.createPanel();
	}

	function showEdit(id){
		handerObj.triggerHandler('manage:groupinfo',id)
		// addTarget.hide();
		// listTarget.hide();
		// editTarget.show();
		// var data = g2k[id];
		// console.log(data);
		// var view = new View({
		// 	target : editTarget,
		// 	tplid : 'manage.group.edit',
		// 	data : data,
		// });
		// view.createPanel();
	}

	function modifySuc(){
		addTarget.addClass('hide');
		listTarget.removeClass('hide');
		editTarget.addClass('hide');
	}

	var handlers = {
		'manage:appsuc' : appSuc,
		'manage:createsuc' : createSuc,
		'manage:userloadsuc' : userloadSuc,
		'manage:alluserloadsuc' : alluserloadSuc,
		'manage:groupload' : groupLoad,
		'manage:groupinfosuc' : groupOne,
		'modifysuc' : modifySuc
	}

	for(var i in handlers){
		handerObj.bind(i,handlers[i]);
	}

	$('#groupList').bind('click',function(e){
		var target = $(e.target),
			cmd = target.attr('cmd');

			var id = target.attr('data-id');

		switch(cmd){
			case 'edit':
				showEdit(id);
				break;
			case 'pass':
				handerObj.triggerHandler('manage:approve',{
					groupId:id,
					validateText : 'pass',
					validateStatus : 1
				});
			break;
			case 'notpass':
				handerObj.triggerHandler('manage:approve',{
					groupId:id,
					validateText : 'notpass',
					validateStatus : 0
				});
			break;
		}
	});

	var editgroup = function(id){
		var name = editTarget.find('.group-name').val();
		var desc = editTarget.find('.group-desc').val();
		var members = [],
			manages = [];
		editTarget.find('.check-member:checked').each(function(){
			members.push($(this).val());
		});
		editTarget.find('.check-manage:checked').each(function(){
			manages.push($(this).val());
		});
		if(name == ''){
			handerObj.triggerHandler('msg:err',77);
			return;
		}
		var obj = {
			groupId : id,
			name : name,
			content : desc,
			members : members,
			managers : manages,
		}
		//console.log(obj);
		handerObj.triggerHandler('manage:modify',obj);
	};

	$('#newGroupBtn').bind('click',function(e){
		var gn = $('#groupName').val(),
			type = parseInt($('.group-type:checked').val()),
			desc = $("#desc").val();

		var ul = [],
			ml = [];
		//managers
		addTarget.find(".check-member:checked").each(function(){
			ul.push($(this).val());
		});
		addTarget.find(".check-manage:checked").each(function(){
			ml.push($(this).val());
		});
		var pid = 0,
			grade = 0,
			tag = 0,
			pt = 0;
		if(type == 3){
			var tag =  $('.check-prep:checked');
			if(tag){
				pid = parseInt(tag.val());
			}
			if(pid){
				grade = $('.check-grade:checked').val();
				tag = $('.check-tag:checked').val();
			}
		}else if(type == 2){
			if($('.prep-type:checked').length){
				pt = 1;
			}
		}

		var obj = {
			name : gn,
			content : desc,
			status : 0,
			type : type,
			members : ul,
			managers : ml,
		}
		if(pt){
			obj.pt = pt;
		}

		if(pid){
			var parent = $('.check-prepyear:checked').val();
			if(parent){
				obj.parentId = parent;
			}
			if(grade){
				obj.grade = grade;
			}
			if(tag){
				obj.tag = tag;
			}

			if(type == 3){
				if(!parent){
					alert('备课小组必须选择学年！');
					return;
				}
				if((!grade || !tag)){
					alert('备课小组必须选择年级和科目！');
					return;
				}
			}
			obj.name = config.grade[grade]+config.tag[tag];
		}else{
			if(type == 3){

			}
		}

		if(obj.name == ''){
			alert('小组名称不能为空!');
			return;
		}
		//return ;

		handerObj.triggerHandler('manage:create',obj);
	});

	$('#aside a').bind('click',function(e){
		var target = $(e.target),
			type = target.attr('type');
		if(type == 'add'){
		addTarget.removeClass('hide');
		listTarget.addClass('hide');
		editTarget.addClass('hide');
		}else{
		addTarget.addClass('hide');
		listTarget.removeClass('hide');
		editTarget.addClass('hide');

		}
	})

	$('.group-type').bind('click',function(e){
		var v = $(this).val();
		if(v == 3){
			$('#prepYear').removeClass('hide');
			if($('.check-prep:checked').val() == 1){
				$('#prepTag').removeClass('hide');
			}
			//$('#prepTag').removeClass('hide');
		}else{
			$('#prepYear').addClass('hide');
			$('#prepTag').addClass('hide');
			$('#groupName').attr('disabled',false);
		}
	});

	$('.check-prep').bind('click',function(e){
		var v = $(this).val();
		if(v == 1){
			$('#prepTag').removeClass('hide');
			$('#groupName').attr('disabled',true);
		}else{
			$('#prepTag').addClass('hide');
			$('#groupName').attr('disabled',false);
		}
	});

	$('.check-grade').bind('click',function(e){
		var v = $(this).val();
		var tag = $('.check-tag:checked').val();
		var n = config.grade[v];
		if(tag){
			n += config.tag[v];
		}
		$('#groupName').val(n);
	});

	$('.check-tag').bind('click',function(e){
		var v = $(this).val();
		var grade = $('.check-grade:checked').val();
		var n = config.tag[v];
		if(grade){
			n = config.grade[grade] + n;
		}
		$('#groupName').val(n);
	});

	return {
		init : init
	}
});<|endoftext|>


<commit_before>/*!
 * benchmark.js
 * Copyright Mathias Bynens <http://mths.be/>
 * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
 * Modified by John-David Dalton <http://allyoucanleet.com/>
 * Available under MIT license <http://mths.be/mit>
 */

(function(global) {

  // MAX_COUNT divisors used to avoid hz of Infinity
  var CYCLE_DIVISORS = { '1': 8, '2': 6, '3': 4, '4': 2, '5': 1 };

  /*--------------------------------------------------------------------------*/

  function Benchmark(fn, options) {
    options = extend({ }, options);
    extend(this, options);
    this.fn = fn;
    this.options = options;
  }

  function Calibration(fn, options) {
    Benchmark.call(this, fn, options);
  }

  function Klass() { }

  Klass.prototype = Benchmark.prototype;

  (function(proto) {
    // bypass calibrating the Calibration tests
    function run(count, synchronous) {
      var me = this;
      me.reset();
      me.running = true;
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
    proto.constructor = Calibration;
    proto.run = run;
  }(Calibration.prototype = new Klass));

  /*--------------------------------------------------------------------------*/

  // when uncalibrated it returns true and fires the callback after calibration
  function calibrate(callback) {
    var cal = Benchmark.CALIBRATION;
    if (!cal.cycles) {
      cal.onComplete = callback;
      cal.average(30);
      return true;
    }
    return false;
  }

  // call a method either sync or async (to allow UI redraws)
  function call(me, callback, synchronous) {
    synchronous
      ? callback(me, synchronous)
      : setTimeout(function() { callback(me); }, me.CYCLE_DELAY * 1e3);
  }

  // copies results from the source to the destination test
  function copyResults(destination, source) {
    destination.count = source.count;
    destination.cycles = source.cycles;
    destination.error = source.error;
    destination.hz = source.hz;
    destination.period = source.period;
    return destination;
  }

  // copies properties from the source to the destination object
  function extend(destination, source) {
    source || (source = { });
    for (var key in source) {
      destination[key] = source[key];
    }
    return destination;
  }

  // generic Array#filter
  function filter(array, callback) {
    var length = array.length,
        result = [];

    while (length--) {
      if (length in array && callback(array[length], length, array)) {
        result.unshift(array[length]);
      }
    }
    return result;
  }

  // generic Array#reduce
  function reduce(array, callback, accumulator) {
    var length = array.length;
    while (length--) {
      if (length in array) {
        accumulator = callback(accumulator, array[length], length, array);
      }
    }
    return accumulator;
  }

  // clock the time it takes to execute a test N times (milliseconds)
  var clock = (function() {
    // enable benchmarking via the --enable-benchmarking flag
    // in at least Chrome 7 to use chrome.Interval
    var __c = typeof global.chromium != 'undefined' ? chromium :
      typeof global.chrome != 'undefined' ? chrome : null;

    if (__c && typeof __c.Interval == 'function') {
      clock = function clock(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = new __c.Interval;
        __t.start();
        while (__i--) { __f() }
        __t.stop();
        __m.time = __t.microseconds() / 1000;
      };
    }
    else if (typeof Date.now == 'function') {
      clock = function clock(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = Date.now();
        while (__i--){ __f() }
        __m.time = Date.now() - __t;
      };
    }
    else {
      clock = function clock(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = (new Date).getTime();
        while (__i--) { __f() }
        __m.time = (new Date).getTime() - __t;
      };
    }
    // if supported, dynamically create tests to avoid extra function calls
    try {
      var __clock = clock,
          code = String(clock);
      if (Function('x,__c', code + 'clock(x);return x')({ }, __c).time === 0) {
        clock = function(__m) {
          var errored;
          try {
            // embed test body in while loop
            Function('__m,__c',
              code.replace('__f()',
              (String(__m.fn).match(/^[^{]+{([^\x00]*)}\s*$/) || [])[1]) +
              'clock(__m)')(__m, __c);
          } catch(e) {
            errored = 1;
          }
          if (errored) {
            __clock(__m);
          }
        };
      }
    } catch(e) { }
    return clock;
  }());

  /*--------------------------------------------------------------------------*/

  function getPlatform() {
    var result,
        description = [],
        ua = navigator.userAgent,
        os = (ua.match(/(?:Windows 98;|Windows |iP[ao]d|iPhone|Mac OS X|Linux)(?:[^);]| )*/) || [])[0],
        name = (ua.match(/Chrome|MSIE|Safari|Opera|Firefox|Minefield/) || [])[0],
        version = {}.toString.call(global.opera) == '[object Opera]' && opera.version(),
        mses = { '6.1': '7', '6.0': 'Vista', '5.2': 'Server 2003 / XP x64', '5.1': 'XP', '5.0': '2000', '4.0': 'NT', '4.9': 'ME' };

    // IE platform tokens
    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
    mses = os && os.indexOf('Windows') > -1 && mses[(os.match(/[456]\.\d/) || [])[0]];
    if (mses) {
      os = 'Windows ' + mses;
    } else if (/iP[ao]d|iPhone/.test(os)) {
      os = (ua.match(/\bOS ([\d_]+)/) || [])[1];
      os = 'iOS' + (os ? ' ' + os : '');
    }
    if (name && !version) {
      version = typeof document.documentMode == 'number'
        ? document.documentMode
        : (ua.match(RegExp('(?:version|' + name + ')[ /]([^ ;]*)', 'i')) || [])[1];
    }
    return {
      'name':        name ? description.push(name) && name : null,
      'version':     version ? description.push(version) && version : null,
      'os':          os ? description.push('on ' + (os = os.replace(/_/g, '.'))) && os : null,
      'description': description.length ? description.join(' ') : 'unknown platform',
      'toString':    function() { return this.description; }
    };
  }

  function noop() { }

  /*--------------------------------------------------------------------------*/

  function average(times, count, synchronous) {
    var deviation,
        mean,
        stopped,
        i = times,
        me = this,
        tests = [];
        cbSum = function(sum, test) { return sum + test.period; },
        cbVariance = function(sum, test) { return sum + Math.pow(test.period - mean, 2); },
        cbOutlier = function(test) { return test.period < (mean + deviation) && test.period > (mean - deviation); };

    function loop() {
      var test = me.clone();
      tests.push(test);
      test.onCycle =
      test.onStart = function() {
        if (stopped = !me.running) {
          test.stop();
        } else {
          me.onCycle(copyResults(me, test));
        }
      };
      test.onComplete = function() {
        if (stopped || !--times) {
          if (!stopped) {
            copyResults(me, test);
            if (!me.error) {
              // compute average period and sample standard deviation
              mean = reduce(tests, cbSum, 0) / tests.length;
              deviation = Math.sqrt(reduce(tests, cbVariance, 0) / (tests.length - 1));

              if (deviation) {
                // remove outliers and compute average period on filtered results
                tests = filter(tests, cbOutlier, 0);
                mean = me.period = reduce(tests, cbSum, 0) / tests.length;
              }
              // compute other results
              me.time = mean * me.count;
              me.hz = mean ? Math.round(1 / mean) : Number.MAX_VALUE;
            }
          }
          me.running = false;
          me.onCycle(me);
          me.onComplete(me);
        }
        else if (!synchronous) {
          call(test = tests[times], function() { test.run(); });
        }
      };
      if (synchronous || !i) {
        test.run(count, synchronous);
      }
    }

    me.reset();
    me.running = true;
    me.onStart(me);

    while (i--) {
      loop();
    }
  }

  function clone() {
    var key,
        me = this,
        result = new me.constructor(me.fn, me.options);

    // copy manually added properties
    for (key in me) {
      if (!result[key]) {
        result[key] = me[key];
      }
    }
    result.reset();
    return result;
  }

  function stop() {
    var me = this,
        cal = Benchmark.CALIBRATION,
        error = me.error;

    if (me.running) {
      if (me != cal && cal.running) {
        cal.stop();
      }
      me.reset();
      me.error = error;
      me.onStop(me);
    }
  }

  function reset() {
    var me = this,
        proto = this.constructor.prototype;

    me.count = proto.count;
    me.cycles = proto.cycles;
    me.error = proto.error;
    me.hz = proto.hz;
    me.period = proto.period;
    me.running = proto.running;
    me.time = proto.time;
    me.onReset(me);
  }

  function run(count, synchronous) {
    var me = this;
    me.reset();
    me.running = true;

    // ensure calibration test has run
    if (!calibrate(function() {
          function rerun() {
            // continue, if not stopped during calibration
            if (me.running) {
              me.run(count, synchronous);
            } else {
              me.onStart(me);
              me.onStop(me);
              me.onComplete(me);
            }
          }
          call(me, rerun, synchronous);
        })) {
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
  }

  function _run(me, synchronous) {
    var divisor,
        period,
        time,
        count = me.count,
        cycles = me.cycles,
        max = me.MAX_COUNT,
        min = me.MIN_TIME;

    // continue, if not stopped between cycles
    if (me.running) {

      if (cycles) {
        cycles = ++me.cycles;
      } else {
        cycles = me.cycles = 1;
      }
      try {
        // clock executions of me.fn
        clock(me);

        time = me.time =
          // ensure positive numbers
          Math.max(0,
          // convert time from milliseconds to seconds
          (me.time / 1e3) -
          // calibrate by subtracting the base loop time
          (Benchmark.CALIBRATION.period || 0) * count);

        // per-operation time
        period = me.period = time / count;

        // ops per second
        me.hz = period ? Math.round(1 / period) : Number.MAX_VALUE;

        // do we need to do another cycle?
        me.running = time < min;

        // if so, compute the iteration count needed
        if (me.running) {
          // tests may return an initial time of 0 when INIT_COUNT is a small number,
          // to avoid that we set its count to something a bit higher
          if (!time && (divisor = CYCLE_DIVISORS[cycles])) {
            // try a fraction of the MAX_COUNT
            count = Math.floor(max / divisor);
          }
          else {
            // calculate how many more iterations it will take to achive the min testing time
            count += Math.ceil((min - time) / period);

            // to avoid freezing the browser stop running if the
            // next cycle would exceed the max count allowed
            if (count > max) {
              me.running = false;
            }
          }
        }
        me.count = count;
      }
      catch(e) {
        me.reset();
        me.error = e;
      }
      me.onCycle(me);
    }

    // figure out what to do next
    if (me.running) {
      call(me, _run, synchronous);
    } else {
      me.onComplete(me);
    }
  }

  /*--------------------------------------------------------------------------*/

  // test to establish iteration loop overhead
  Benchmark.CALIBRATION = new Calibration(noop, { 'INIT_COUNT': 3e3 });

  Benchmark.getPlatform = getPlatform;

  Benchmark.noop = noop;

  extend(Benchmark.prototype, {
    // delay between test cycles (secs)
    'CYCLE_DELAY': 0.01,

    // initial number of iterations
    'INIT_COUNT': 10,

    // max iterations allowed per cycle (used avoid locking up the browser)
    'MAX_COUNT': 1e6, // 1 million

    // minimum time a test should take to get valid results (secs)
    'MIN_TIME': 0.2,

    // number of times a test was executed
    'count': null,

    // number of cycles performed during testing
    'cycles': null,

    // an error object if the test failed
    'error': null,

    // number of test executions per second
    'hz': null,

    // time a test takes to do one execution (secs)
    'period': null,

    // flag to indicate if the test is running
    'running': false,

    // time a test takes to do the `count` number of executions (secs)
    'time': null,

    // callback invoked when testing is complete
    'onComplete': noop,

    // callback invoked when one test cycle ends
    'onCycle': noop,

    // callback invoked when test is reset
    'onReset': noop,

    // callback invoked when testing is started
    'onStart': noop,

    // callback invoked when testing is stopped
    'onStop': noop,

    // runs the test `n` times and returns the averaged test results
    'average': average,

    // create new benchmark with the same test function and options
    'clone': clone,

    // reset test state
    'reset': reset,

    // run the test
    'run': run,

    // stop testing (does not record times)
    'stop': stop
  });

  // expose
  global.Benchmark = Benchmark;

}(this));<commit_msg>benchmark.js: Make compiled vars unique by appending a UID to them. [jddalton]<commit_after>/*!
 * benchmark.js
 * Copyright Mathias Bynens <http://mths.be/>
 * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
 * Modified by John-David Dalton <http://allyoucanleet.com/>
 * Available under MIT license <http://mths.be/mit>
 */

(function(global) {

  // MAX_COUNT divisors used to avoid hz of Infinity
  var CYCLE_DIVISORS = { '1': 8, '2': 6, '3': 4, '4': 2, '5': 1 };

  /*--------------------------------------------------------------------------*/

  function Benchmark(fn, options) {
    options = extend({ }, options);
    extend(this, options);
    this.fn = fn;
    this.options = options;
  }

  function Calibration(fn, options) {
    Benchmark.call(this, fn, options);
  }

  function Klass() { }

  Klass.prototype = Benchmark.prototype;

  (function(proto) {
    // bypass calibrating the Calibration tests
    function run(count, synchronous) {
      var me = this;
      me.reset();
      me.running = true;
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
    proto.constructor = Calibration;
    proto.run = run;
  }(Calibration.prototype = new Klass));

  /*--------------------------------------------------------------------------*/

  // when uncalibrated it returns true and fires the callback after calibration
  function calibrate(callback) {
    var cal = Benchmark.CALIBRATION;
    if (!cal.cycles) {
      cal.onComplete = callback;
      cal.average(30);
      return true;
    }
    return false;
  }

  // call a method either sync or async (to allow UI redraws)
  function call(me, callback, synchronous) {
    synchronous
      ? callback(me, synchronous)
      : setTimeout(function() { callback(me); }, me.CYCLE_DELAY * 1e3);
  }

  // copies results from the source to the destination test
  function copyResults(destination, source) {
    destination.count = source.count;
    destination.cycles = source.cycles;
    destination.error = source.error;
    destination.hz = source.hz;
    destination.period = source.period;
    return destination;
  }

  // copies properties from the source to the destination object
  function extend(destination, source) {
    source || (source = { });
    for (var key in source) {
      destination[key] = source[key];
    }
    return destination;
  }

  // generic Array#filter
  function filter(array, callback) {
    var length = array.length,
        result = [];

    while (length--) {
      if (length in array && callback(array[length], length, array)) {
        result.unshift(array[length]);
      }
    }
    return result;
  }

  // generic Array#reduce
  function reduce(array, callback, accumulator) {
    var length = array.length;
    while (length--) {
      if (length in array) {
        accumulator = callback(accumulator, array[length], length, array);
      }
    }
    return accumulator;
  }

  // clock the time it takes to execute a test N times (milliseconds)
  var clock
  (function() {
    // enable benchmarking via the --enable-benchmarking flag
    // in at least Chrome 7 to use chrome.Interval
    var __c = typeof global.chromium != 'undefined' ? chromium :
      typeof global.chrome != 'undefined' ? chrome : null;

    if (__c && typeof __c.Interval == 'function') {
      clock = function(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = new __c.Interval;
        __t.start();
        while (__i--) { __f() }
        __t.stop();
        __m.time = __t.microseconds() / 1000;
      };
    }
    else if (typeof Date.now == 'function') {
      clock = function(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = Date.now();
        while (__i--){ __f() }
        __m.time = Date.now() - __t;
      };
    }
    else {
      clock = function(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = (new Date).getTime();
        while (__i--) { __f() }
        __m.time = (new Date).getTime() - __t;
      };
    }
    // if supported, compile tests to avoid extra function calls
    try {
      var __clock = clock,
          uid     = (new Date).getTime(),
          fnToken = '__f' + uid + '()',
          fnArg   = '__m' + uid + ',__c'  + uid,
          fnBody  = ('('  + String(clock) + ')(__m);return __m').replace(/(__[a-z])/g, '$1' + uid);

      if (Function(fnArg, fnBody)({ }, __c).time === 0) {

        clock = function(me) {
          // TODO: Test function body regexp matching in Safari 2.0.0
          var errored,
              embed = String(me.fn).match(/^[^{]+{((?:.|\n)*)}\s*$/) || '';
          try {
            Function(fnArg, fnBody.replace(fnToken, embed && embed[1]))(me, __c);
          } catch(e) {
            errored = 1;
          }
          if (errored) {
            __clock(me);
          }
        };
      }
    } catch(e) { }
  }());

  /*--------------------------------------------------------------------------*/

  function getPlatform() {
    var result,
        description = [],
        ua = navigator.userAgent,
        os = (ua.match(/(?:Windows 98;|Windows |iP[ao]d|iPhone|Mac OS X|Linux)(?:[^);]| )*/) || [])[0],
        name = (ua.match(/Chrome|MSIE|Safari|Opera|Firefox|Minefield/) || [])[0],
        version = {}.toString.call(global.opera) == '[object Opera]' && opera.version(),
        mses = { '6.1': '7', '6.0': 'Vista', '5.2': 'Server 2003 / XP x64', '5.1': 'XP', '5.0': '2000', '4.0': 'NT', '4.9': 'ME' };

    // IE platform tokens
    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
    mses = os && os.indexOf('Windows') > -1 && mses[(os.match(/[456]\.\d/) || [])[0]];
    if (mses) {
      os = 'Windows ' + mses;
    } else if (/iP[ao]d|iPhone/.test(os)) {
      os = (ua.match(/\bOS ([\d_]+)/) || [])[1];
      os = 'iOS' + (os ? ' ' + os : '');
    }
    if (name && !version) {
      version = typeof document.documentMode == 'number'
        ? document.documentMode
        : (ua.match(RegExp('(?:version|' + name + ')[ /]([^ ;]*)', 'i')) || [])[1];
    }
    return {
      'name':        name ? description.push(name) && name : null,
      'version':     version ? description.push(version) && version : null,
      'os':          os ? description.push('on ' + (os = os.replace(/_/g, '.'))) && os : null,
      'description': description.length ? description.join(' ') : 'unknown platform',
      'toString':    function() { return this.description; }
    };
  }

  function noop() { }

  /*--------------------------------------------------------------------------*/

  function average(times, count, synchronous) {
    var deviation,
        mean,
        stopped,
        i = times,
        me = this,
        tests = [];
        cbSum = function(sum, test) { return sum + test.period; },
        cbVariance = function(sum, test) { return sum + Math.pow(test.period - mean, 2); },
        cbOutlier = function(test) { return test.period < (mean + deviation) && test.period > (mean - deviation); };

    function loop() {
      var test = me.clone();
      tests.push(test);
      test.onCycle =
      test.onStart = function() {
        if (stopped = !me.running) {
          test.stop();
        } else {
          me.onCycle(copyResults(me, test));
        }
      };
      test.onComplete = function() {
        if (stopped || !--times) {
          if (!stopped) {
            copyResults(me, test);
            if (!me.error) {
              // compute average period and sample standard deviation
              mean = reduce(tests, cbSum, 0) / tests.length;
              deviation = Math.sqrt(reduce(tests, cbVariance, 0) / (tests.length - 1));

              if (deviation) {
                // remove outliers and compute average period on filtered results
                tests = filter(tests, cbOutlier, 0);
                mean = me.period = reduce(tests, cbSum, 0) / tests.length;
              }
              // compute other results
              me.time = mean * me.count;
              me.hz = mean ? Math.round(1 / mean) : Number.MAX_VALUE;
            }
          }
          me.running = false;
          me.onCycle(me);
          me.onComplete(me);
        }
        else if (!synchronous) {
          call(test = tests[times], function() { test.run(); });
        }
      };
      if (synchronous || !i) {
        test.run(count, synchronous);
      }
    }

    me.reset();
    me.running = true;
    me.onStart(me);

    while (i--) {
      loop();
    }
  }

  function clone() {
    var key,
        me = this,
        result = new me.constructor(me.fn, me.options);

    // copy manually added properties
    for (key in me) {
      if (!result[key]) {
        result[key] = me[key];
      }
    }
    result.reset();
    return result;
  }

  function stop() {
    var me = this,
        cal = Benchmark.CALIBRATION,
        error = me.error;

    if (me.running) {
      if (me != cal && cal.running) {
        cal.stop();
      }
      me.reset();
      me.error = error;
      me.onStop(me);
    }
  }

  function reset() {
    var me = this,
        proto = this.constructor.prototype;

    me.count = proto.count;
    me.cycles = proto.cycles;
    me.error = proto.error;
    me.hz = proto.hz;
    me.period = proto.period;
    me.running = proto.running;
    me.time = proto.time;
    me.onReset(me);
  }

  function run(count, synchronous) {
    var me = this;
    me.reset();
    me.running = true;

    // ensure calibration test has run
    if (!calibrate(function() {
          function rerun() {
            // continue, if not stopped during calibration
            if (me.running) {
              me.run(count, synchronous);
            } else {
              me.onStart(me);
              me.onStop(me);
              me.onComplete(me);
            }
          }
          call(me, rerun, synchronous);
        })) {
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
  }

  function _run(me, synchronous) {
    var divisor,
        period,
        time,
        count = me.count,
        cycles = me.cycles,
        max = me.MAX_COUNT,
        min = me.MIN_TIME;

    // continue, if not stopped between cycles
    if (me.running) {

      if (cycles) {
        cycles = ++me.cycles;
      } else {
        cycles = me.cycles = 1;
      }
      try {
        // clock executions of me.fn
        clock(me);

        time = me.time =
          // ensure positive numbers
          Math.max(0,
          // convert time from milliseconds to seconds
          (me.time / 1e3) -
          // calibrate by subtracting the base loop time
          (Benchmark.CALIBRATION.period || 0) * count);

        // per-operation time
        period = me.period = time / count;

        // ops per second
        me.hz = period ? Math.round(1 / period) : Number.MAX_VALUE;

        // do we need to do another cycle?
        me.running = time < min;

        // if so, compute the iteration count needed
        if (me.running) {
          // tests may return an initial time of 0 when INIT_COUNT is a small number,
          // to avoid that we set its count to something a bit higher
          if (!time && (divisor = CYCLE_DIVISORS[cycles])) {
            // try a fraction of the MAX_COUNT
            count = Math.floor(max / divisor);
          }
          else {
            // calculate how many more iterations it will take to achive the min testing time
            count += Math.ceil((min - time) / period);

            // to avoid freezing the browser stop running if the
            // next cycle would exceed the max count allowed
            if (count > max) {
              me.running = false;
            }
          }
        }
        me.count = count;
      }
      catch(e) {
        me.reset();
        me.error = e;
      }
      me.onCycle(me);
    }

    // figure out what to do next
    if (me.running) {
      call(me, _run, synchronous);
    } else {
      me.onComplete(me);
    }
  }

  /*--------------------------------------------------------------------------*/

  // test to establish iteration loop overhead
  Benchmark.CALIBRATION = new Calibration(noop, { 'INIT_COUNT': 3e3 });

  Benchmark.getPlatform = getPlatform;

  Benchmark.noop = noop;

  extend(Benchmark.prototype, {
    // delay between test cycles (secs)
    'CYCLE_DELAY': 0.01,

    // initial number of iterations
    'INIT_COUNT': 10,

    // max iterations allowed per cycle (used avoid locking up the browser)
    'MAX_COUNT': 1e6, // 1 million

    // minimum time a test should take to get valid results (secs)
    'MIN_TIME': 0.2,

    // number of times a test was executed
    'count': null,

    // number of cycles performed during testing
    'cycles': null,

    // an error object if the test failed
    'error': null,

    // number of test executions per second
    'hz': null,

    // time a test takes to do one execution (secs)
    'period': null,

    // flag to indicate if the test is running
    'running': false,

    // time a test takes to do the `count` number of executions (secs)
    'time': null,

    // callback invoked when testing is complete
    'onComplete': noop,

    // callback invoked when one test cycle ends
    'onCycle': noop,

    // callback invoked when test is reset
    'onReset': noop,

    // callback invoked when testing is started
    'onStart': noop,

    // callback invoked when testing is stopped
    'onStop': noop,

    // runs the test `n` times and returns the averaged test results
    'average': average,

    // create new benchmark with the same test function and options
    'clone': clone,

    // reset test state
    'reset': reset,

    // run the test
    'run': run,

    // stop testing (does not record times)
    'stop': stop
  });

  // expose
  global.Benchmark = Benchmark;

}(this));<|endoftext|>


<commit_before>import { combineReducers } from 'redux'
import flow from './flow'
import header from './header'

// TODO: Just move ducks/ui/* into ducks/?
export default combineReducers({
    flow,
    header,
})
<commit_msg>[web] Add modal to js/ducks/ui/index.js<commit_after>import { combineReducers } from 'redux'
import flow from './flow'
import header from './header'
import modal from './modal'

// TODO: Just move ducks/ui/* into ducks/?
export default combineReducers({
    flow,
    header,
    modal
})
<|endoftext|>


<commit_before>"use strict";

var Benchmark = require("benchmark");
var FlowdockText = require("./flowdock-text.js");

var samples = (function () {
  var result = [];
  var size = 1000;
  var evilchars = "().#,";
  var i = 0;
  var text;

  while (size > 0) {
    text = "foo bar #hashtag http://www.google.com/lol";
    for(i=0; i < size; i++) {
      text += evilchars.charAt(Math.floor(Math.random() * evilchars.length));
    }

    result.push(text);
    size--;
  }
  return result;
}());

var suite = new Benchmark.Suite;

suite
.add("All", function() {
  var i;
  for (var i = samples.length; i >= 0; i--) {
    FlowdockText.extractUrls(samples[i]);
    FlowdockText.extractHashtags(samples[i]);
  }
})
.add("Long: 1000 evil chars", function() {
  FlowdockText.extractUrls(samples[0]);
  FlowdockText.extractHashtags(samples[0]);
})
.add("Short: 100 evil chars", function() {
  FlowdockText.extractUrls(samples[900]);
  FlowdockText.extractHashtags(samples[900]);
})
.add("Nice: 0 evil chars", function() {
  FlowdockText.extractUrls(samples[999]);
  FlowdockText.extractHashtags(samples[999]);
})
.on("cycle", function(event) {
  console.log(String(event.target));
})
.run();
<commit_msg>Add extractMentions and extractEmails to benchmark<commit_after>"use strict";

var Benchmark = require("benchmark");
var FlowdockText = require("./flowdock-text.js");

var samples = (function () {
  var result = [];
  var size = 1000;
  var evilchars = "().#,";
  var i = 0;
  var text;

  while (size > 0) {
    text = "foo bar #hashtag http://www.google.com/lol";
    for(i=0; i < size; i++) {
      text += evilchars.charAt(Math.floor(Math.random() * evilchars.length));
    }

    result.push(text);
    size--;
  }
  return result;
}());

var suite = new Benchmark.Suite;

suite
.add("All", function() {
  var i;
  for (var i = samples.length; i >= 0; i--) {
    FlowdockText.extractUrls(samples[i]);
    FlowdockText.extractHashtags(samples[i]);
    FlowdockText.extractMentions(samples[i]);
    FlowdockText.extractEmails(samples[i]);
  }
})
.add("Long: 1000 evil chars", function() {
  FlowdockText.extractUrls(samples[0]);
  FlowdockText.extractHashtags(samples[0]);
  FlowdockText.extractMentions(samples[0]);
  FlowdockText.extractEmails(samples[0]);
})
.add("Short: 100 evil chars", function() {
  FlowdockText.extractUrls(samples[900]);
  FlowdockText.extractHashtags(samples[900]);
  FlowdockText.extractMentions(samples[900]);
  FlowdockText.extractEmails(samples[900]);
})
.add("Nice: 0 evil chars", function() {
  FlowdockText.extractUrls(samples[999]);
  FlowdockText.extractHashtags(samples[999]);
  FlowdockText.extractMentions(samples[999]);
  FlowdockText.extractEmails(samples[999]);
})
.on("cycle", function(event) {
  console.log(String(event.target));
})
.run();
<|endoftext|>


<commit_before>/*!
 * benchmark.js
 * Copyright Mathias Bynens <http://mths.be/>
 * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
 * Modified by John-David Dalton <http://allyoucanleet.com/>
 * Available under MIT license <http://mths.be/mit>
 */

(function(global) {

  // MAX_COUNT divisors used to avoid hz of Infinity
  var CYCLE_DIVISORS = { '1': 8, '2': 6, '3': 4, '4': 2, '5': 1 };

  /*--------------------------------------------------------------------------*/

  function Benchmark(fn, options) {
    options = extend({ }, options);
    extend(this, options);
    this.fn = fn;
    this.options = options;
  }

  function Calibration(fn, options) {
    Benchmark.call(this, fn, options);
  }

  function Klass() { }

  Klass.prototype = Benchmark.prototype;

  (function(proto) {
    // bypass calibrating the Calibration tests
    function run(count, synchronous) {
      var me = this;
      me.reset();
      me.running = true;
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
    proto.constructor = Calibration;
    proto.run = run;
  }(Calibration.prototype = new Klass));

  /*--------------------------------------------------------------------------*/

  // when uncalibrated it returns true and fires the callback after calibration
  function calibrate(callback) {
    var cal = Benchmark.CALIBRATION;
    if (!cal.cycles) {
      cal.onComplete = callback;
      cal.average(30);
      return true;
    }
    return false;
  }

  // call a method either sync or async (to allow UI redraws)
  function call(me, callback, synchronous) {
    synchronous
      ? callback(me, synchronous)
      : setTimeout(function() { callback(me); }, me.CYCLE_DELAY * 1e3);
  }

  // merge source results with destinations
  function merge(destination, source) {
    destination.count = source.count;
    destination.cycles += source.cycles;
    destination.error = source.error;
    destination.hz = source.hz;
    destination.period = source.period;
    return destination;
  }

  // copies properties from the source to the destination object
  function extend(destination, source) {
    source || (source = { });
    for (var key in source) {
      destination[key] = source[key];
    }
    return destination;
  }

  // generic Array#filter
  function filter(array, callback) {
    var length = array.length,
        result = [];

    while (length--) {
      if (length in array && callback(array[length], length, array)) {
        result.unshift(array[length]);
      }
    }
    return result;
  }

  // generic Array#reduce
  function reduce(array, callback, accumulator) {
    var length = array.length;
    while (length--) {
      if (length in array) {
        accumulator = callback(accumulator, array[length], length, array);
      }
    }
    return accumulator;
  }

  // clock the time it takes to execute a test N times (milliseconds)
  var clock
  (function() {
    // enable benchmarking via the --enable-benchmarking flag
    // in at least Chrome 7 to use chrome.Interval
    var __c = typeof global.chromium != 'undefined' ? chromium :
      typeof global.chrome != 'undefined' ? chrome : null;

    if (__c && typeof __c.Interval == 'function') {
      clock = function(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = new __c.Interval;
        __t.start();
        while (__i--) { __f() }
        __t.stop();
        __m.time = __t.microseconds() / 1000;
      };
    }
    else if (typeof Date.now == 'function') {
      clock = function(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = Date.now();
        while (__i--){ __f() }
        __m.time = Date.now() - __t;
      };
    }
    else {
      clock = function(__m) {
        var __i = __m.count,
            __f = __m.fn,
            __t = (new Date).getTime();
        while (__i--) { __f() }
        __m.time = (new Date).getTime() - __t;
      };
    }
    // if supported, compile tests to avoid extra function calls
    try {
      var __clock = clock,
          uid     = (new Date).getTime(),
          fnToken = '__f' + uid + '()',
          fnArg   = '__m' + uid + ',__c'  + uid,
          fnBody  = ('('  + String(clock) + ')(__m);return __m').replace(/(__[a-z])/g, '$1' + uid);

      if (Function(fnArg, fnBody)({ }, __c).time === 0) {
        clock = function(me) {
          // TODO: Test function body regexp matching in Safari 2.0.0
          var errored,
              embed = String(me.fn).match(/^[^{]+{((?:.|\n)*)}\s*$/) || '';
          try {
            Function(fnArg, fnBody.replace(fnToken, embed && embed[1]))(me, __c);
          } catch(e) {
            errored = 1;
          }
          if (errored) {
            __clock(me);
          }
        };
      }
    } catch(e) { }
  }());

  /*--------------------------------------------------------------------------*/

  function getPlatform() {
    var result,
        description = [],
        ua = navigator.userAgent,
        os = (ua.match(/(?:Windows 98;|Windows |iP[ao]d|iPhone|Mac OS X|Linux)(?:[^);]| )*/) || [])[0],
        name = (ua.match(/Chrome|MSIE|Safari|Opera|Firefox|Minefield/) || [])[0],
        version = {}.toString.call(global.opera) == '[object Opera]' && opera.version(),
        mses = { '6.1': '7', '6.0': 'Vista', '5.2': 'Server 2003 / XP x64', '5.1': 'XP', '5.0': '2000', '4.0': 'NT', '4.9': 'ME' };

    // IE platform tokens
    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
    mses = os && os.indexOf('Windows') > -1 && mses[(os.match(/[456]\.\d/) || [])[0]];
    if (mses) {
      os = 'Windows ' + mses;
    } else if (/iP[ao]d|iPhone/.test(os)) {
      os = (ua.match(/\bOS ([\d_]+)/) || [])[1];
      os = 'iOS' + (os ? ' ' + os : '');
    }
    if (name && !version) {
      version = typeof document.documentMode == 'number'
        ? document.documentMode
        : (ua.match(RegExp('(?:version|' + name + ')[ /]([^ ;]*)', 'i')) || [])[1];
    }
    return {
      'name':        name ? description.push(name) && name : null,
      'version':     version ? description.push(version) && version : null,
      'os':          os ? description.push('on ' + (os = os.replace(/_/g, '.'))) && os : null,
      'description': description.length ? description.join(' ') : 'unknown platform',
      'toString':    function() { return this.description; }
    };
  }

  function noop() { }

  /*--------------------------------------------------------------------------*/

  function average(times, count, synchronous) {
    var deviation,
        mean,
        stopped,
        clones = [],
        i = times,
        me = this;

    function cbSum(sum, clone) {
      return sum + clone.period;
    }

    function cbVariance(sum, clone) {
      return sum + Math.pow(clone.period - mean, 2);
    }

    function cbOutlier(clone) {
      return clone.period < (mean + deviation) && clone.period > (mean - deviation);
    }

    function onCycle(clone) {
      // stop clone and raise flag if host has stopped running
      if (stopped = !me.running) {
        clone.stop();
      } else {
        // update host and fire its onCycle callback
        me.onCycle(merge(me, clone));
      }
    }

    function onComplete(clone) {
      // if host has stopped or this is the last clone to finish
      if (stopped || !--times) {
        if (!stopped && !merge(me, clone).error) {
          // compute average period and sample standard deviation
          mean = reduce(clones, cbSum, 0) / clones.length;
          deviation = Math.sqrt(reduce(clones, cbVariance, 0) / (clones.length - 1));

          if (deviation) {
            // remove outliers and compute average period on filtered results
            clones = filter(clones, cbOutlier, 0);
            mean = me.period = reduce(clones, cbSum, 0) / clones.length;
          }
          // compute other host results
          me.time = mean * me.count;
          me.hz = mean ? Math.round(1 / mean) : Number.MAX_VALUE;
        }
        delete me.averaging;
        me.running = false;
        me.onCycle(me);
        me.onComplete(me);
      }
      else if (!synchronous) {
        // run next clone in the sample
        clone = clones[times];
        call(clone, function() { clone.run(); });
      }
    }

    me.reset();
    me.averaging = me.running = true;
    me.onStart(me);

    while (i--) {
      // create clone and add to sample
      clones.push(me.clone({
        'onStart': onCycle,
        'onCycle': onCycle,
        'onComplete': onComplete
      }));
      // run instantly if sync or init async
      if (synchronous || !i) {
        clones[clones.length - 1].run(count, synchronous);
      }
    }
  }

  /*--------------------------------------------------------------------------*/

  function clone(options) {
    var key,
        me = this,
        result = new me.constructor(me.fn, extend(extend({ }, me.options), options));

    // copy manually added properties
    for (key in me) {
      if (!result[key]) {
        result[key] = me[key];
      }
    }
    result.reset();
    return result;
  }

  function stop() {
    var me = this,
        cal = Benchmark.CALIBRATION,
        error = me.error;

    if (me.running) {
      if (me != cal && cal.running) {
        cal.stop();
      }
      me.reset();
      me.error = error;
      me.onStop(me);
    }
  }

  function reset() {
    var me = this,
        proto = this.constructor.prototype;

    me.count = proto.count;
    me.cycles = proto.cycles;
    me.error = proto.error;
    me.hz = proto.hz;
    me.period = proto.period;
    me.running = proto.running;
    me.time = proto.time;
    me.onReset(me);
  }

  function run(count, synchronous) {
    var me = this;
    me.reset();
    me.running = true;

    // ensure calibration test has run
    if (!calibrate(function() {
          function rerun() {
            // continue, if not stopped during calibration
            if (me.running) {
              me.run(count, synchronous);
            } else {
              me.onStart(me);
              me.onStop(me);
              me.onComplete(me);
            }
          }
          call(me, rerun, synchronous);
        })) {
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
  }

  function _run(me, synchronous) {
    var divisor,
        period,
        time,
        count = me.count,
        cycles = me.cycles,
        max = me.MAX_COUNT,
        min = me.MIN_TIME;

    // continue, if not stopped between cycles
    if (me.running) {

      if (cycles) {
        cycles = ++me.cycles;
      } else {
        cycles = me.cycles = 1;
      }
      try {
        // clock executions of me.fn
        clock(me);

        time = me.time =
          // ensure positive numbers
          Math.max(0,
          // convert time from milliseconds to seconds
          (me.time / 1e3) -
          // calibrate by subtracting the base loop time
          (Benchmark.CALIBRATION.period || 0) * count);

        // per-operation time
        period = me.period = time / count;

        // ops per second
        me.hz = period ? Math.round(1 / period) : Number.MAX_VALUE;

        // do we need to do another cycle?
        me.running = time < min;

        // if so, compute the iteration count needed
        if (me.running) {
          // tests may return an initial time of 0 when INIT_COUNT is a small number,
          // to avoid that we set its count to something a bit higher
          if (!time && (divisor = CYCLE_DIVISORS[cycles])) {
            // try a fraction of the MAX_COUNT
            count = Math.floor(max / divisor);
          }
          else {
            // calculate how many more iterations it will take to achive the min testing time
            count += Math.ceil((min - time) / period);

            // to avoid freezing the browser stop running if the
            // next cycle would exceed the max count allowed
            if (count > max) {
              me.running = false;
            }
          }
        }
        me.count = count;
      }
      catch(e) {
        me.reset();
        me.error = e;
      }
      me.onCycle(me);
    }

    if (me.running) {
      call(me, _run, synchronous);
    }
    else if (me.averaging || me.error || (me.time * me.DEFAULT_AVERAGE) > 1) {
      me.onComplete(me);
    }
    else {
      // fast tests get their results averaged
      me.average(me.DEFAULT_AVERAGE, count, synchronous);
    }
  }

  /*--------------------------------------------------------------------------*/

  // test to establish iteration loop overhead
  Benchmark.CALIBRATION = new Calibration(noop, { 'INIT_COUNT': 3e3 });

  Benchmark.getPlatform = getPlatform;

  Benchmark.noop = noop;

  extend(Benchmark.prototype, {
    // delay between test cycles (secs)
    'CYCLE_DELAY': 0.01,

    // number of runs to average for fast tests
    'DEFAULT_AVERAGE': 30,

    // initial number of iterations
    'INIT_COUNT': 10,

    // max iterations allowed per cycle (used avoid locking up the browser)
    'MAX_COUNT': 1e6, // 1 million

    // minimum time a test should take to get valid results (secs)
    'MIN_TIME': 0.2,

    // number of times a test was executed
    'count': null,

    // number of cycles performed during testing
    'cycles': null,

    // an error object if the test failed
    'error': null,

    // number of test executions per second
    'hz': null,

    // time a test takes to do one execution (secs)
    'period': null,

    // flag to indicate if the test is running
    'running': false,

    // time a test takes to do the `count` number of executions (secs)
    'time': null,

    // callback invoked when testing is complete
    'onComplete': noop,

    // callback invoked when one test cycle ends
    'onCycle': noop,

    // callback invoked when test is reset
    'onReset': noop,

    // callback invoked when testing is started
    'onStart': noop,

    // callback invoked when testing is stopped
    'onStop': noop,

    // runs the test `n` times and returns the averaged test results
    'average': average,

    // create new benchmark with the same test function and options
    'clone': clone,

    // reset test state
    'reset': reset,

    // run the test
    'run': run,

    // stop testing (does not record times)
    'stop': stop
  });

  // expose
  global.Benchmark = Benchmark;

}(this));<commit_msg>benchmark: Cleanup clock() and make average() use Benchmark#DEFAULT_AVERAGE if called with no arguments. [jddalton]<commit_after>/*!
 * benchmark.js
 * Copyright Mathias Bynens <http://mths.be/>
 * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
 * Modified by John-David Dalton <http://allyoucanleet.com/>
 * Available under MIT license <http://mths.be/mit>
 */

(function(global) {

  // MAX_COUNT divisors used to avoid hz of Infinity
  var CYCLE_DIVISORS = { '1': 8, '2': 6, '3': 4, '4': 2, '5': 1 };

  /*--------------------------------------------------------------------------*/

  function Benchmark(fn, options) {
    options = extend({ }, options);
    extend(this, options);
    this.fn = fn;
    this.options = options;
  }

  function Calibration(fn, options) {
    Benchmark.call(this, fn, options);
  }

  function Klass() { }

  Klass.prototype = Benchmark.prototype;

  (function(proto) {
    // bypass calibrating the Calibration tests
    function run(count, synchronous) {
      var me = this;
      me.reset();
      me.running = true;
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
    proto.constructor = Calibration;
    proto.run = run;
  }(Calibration.prototype = new Klass));

  /*--------------------------------------------------------------------------*/

  // fires callback after calibration or returns false
  function calibrate(callback) {
    var cal = Benchmark.CALIBRATION;
    if (!cal.cycles) {
      cal.onComplete = callback;
      cal.average();
      return true;
    }
    return false;
  }

  // call method sync or async (to allow UI redraws)
  function call(me, callback, synchronous) {
    synchronous
      ? callback(me, synchronous)
      : setTimeout(function() { callback(me); }, me.CYCLE_DELAY * 1e3);
  }

  // merge source results with destinations
  function merge(destination, source) {
    destination.count = source.count;
    destination.cycles += source.cycles;
    destination.error = source.error;
    destination.hz = source.hz;
    destination.period = source.period;
    return destination;
  }

  // copies source properties to destination object
  function extend(destination, source) {
    source || (source = { });
    for (var key in source) {
      destination[key] = source[key];
    }
    return destination;
  }

  // generic Array#filter
  function filter(array, callback) {
    var length = array.length,
        result = [];

    while (length--) {
      if (length in array && callback(array[length], length, array)) {
        result.unshift(array[length]);
      }
    }
    return result;
  }

  // generic Array#reduce
  function reduce(array, callback, accumulator) {
    var length = array.length;
    while (length--) {
      if (length in array) {
        accumulator = callback(accumulator, array[length], length, array);
      }
    }
    return accumulator;
  }

  /*--------------------------------------------------------------------------*/

  // clock the time it takes to execute a function N times (milliseconds)
  var clock;

  // variable names are prefixed with $ to replace during compilation
  (function() {

    function interval($m) {
      var $i = $m.count, $t = new $c.Interval;
      $t.start(); while ($i--) { $f() } $t.stop();
      $m.time = $t.microseconds() / 1000;
    }

    function now($m) {
      var $i = $m.count, $f = $m.fn, $t = Date.now();
      while ($i--){ $f() }
      $m.time = Date.now() - $t;
    }

    function time($m) {
      var $i = $m.count, $f = $m.fn, $t = (new Date).getTime();
      while ($i--) { $f() }
      $m.time = (new Date).getTime() - $t;
    }

    // enable benchmarking via the --enable-benchmarking flag
    // in at least Chrome 7 to use chrome.Interval
    var $c = typeof global.chromium != 'undefined' ? chromium :
      typeof global.chrome != 'undefined' ? chrome : null;

    // choose which timing api to use
    clock = ($c && typeof $c.Interval == 'function') ? interval :
      (typeof Date.now == 'function') ? now : time;

    // if supported, compile tests to avoid extra function calls
    // TODO: check regexps in Safari 2.0.0
    try {
      var $clock  = clock,
          uid     = (new Date).getTime(),
          fnToken = '$f' + uid + '()',
          fnArg   = '$m' + uid + ',$c'  + uid,
          fnBody  = ('(' + String(clock).replace(/interval|now|time/, '') +
                    ')($m);return $m').replace(/(\$[a-z])/g, '$1' + uid);

      if (Function(fnArg, fnBody)({ }, $c).time === 0) {
        clock = function(me) {
          var embed = String(me.fn).match(/^[^{]+{((?:.|\n)*)}\s*$/) || '';
          try {
            Function(fnArg, fnBody.replace(fnToken, embed && embed[1]))(me, $c);
          } catch(e) {
            embed = false;
          }
          if (embed === false) {
            $clock(me);
          }
        };
      }
    } catch(e) { }
  }());

  /*--------------------------------------------------------------------------*/

  function getPlatform() {
    var result,
        description = [],
        ua = navigator.userAgent,
        os = (ua.match(/(?:Windows 98;|Windows |iP[ao]d|iPhone|Mac OS X|Linux)(?:[^);]| )*/) || [])[0],
        name = (ua.match(/Chrome|MSIE|Safari|Opera|Firefox|Minefield/) || [])[0],
        version = {}.toString.call(global.opera) == '[object Opera]' && opera.version(),
        mses = { '6.1': '7', '6.0': 'Vista', '5.2': 'Server 2003 / XP x64', '5.1': 'XP', '5.0': '2000', '4.0': 'NT', '4.9': 'ME' };

    // IE platform tokens
    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
    mses = os && os.indexOf('Windows') > -1 && mses[(os.match(/[456]\.\d/) || [])[0]];
    if (mses) {
      os = 'Windows ' + mses;
    } else if (/iP[ao]d|iPhone/.test(os)) {
      os = (ua.match(/\bOS ([\d_]+)/) || [])[1];
      os = 'iOS' + (os ? ' ' + os : '');
    }
    if (name && !version) {
      version = typeof document.documentMode == 'number'
        ? document.documentMode
        : (ua.match(RegExp('(?:version|' + name + ')[ /]([^ ;]*)', 'i')) || [])[1];
    }
    return {
      'name':        name ? description.push(name) && name : null,
      'version':     version ? description.push(version) && version : null,
      'os':          os ? description.push('on ' + (os = os.replace(/_/g, '.'))) && os : null,
      'description': description.length ? description.join(' ') : 'unknown platform',
      'toString':    function() { return this.description; }
    };
  }

  /*--------------------------------------------------------------------------*/

  function average(times, count, synchronous) {
    var deviation,
        mean,
        stopped,
        me = this,
        clones = [],
        i = times || (times = me.DEFAULT_AVERAGE);

    function cbSum(sum, clone) {
      return sum + clone.period;
    }

    function cbVariance(sum, clone) {
      return sum + Math.pow(clone.period - mean, 2);
    }

    function cbOutlier(clone) {
      return clone.period < (mean + deviation) && clone.period > (mean - deviation);
    }

    function onCycle(clone) {
      // stop clone and raise flag if host has stopped running
      if (stopped = !me.running) {
        clone.stop();
      } else {
        // update host and fire its onCycle callback
        me.onCycle(merge(me, clone));
      }
    }

    function onComplete(clone) {
      // if host has stopped or this is the last clone to finish
      if (stopped || !--times) {
        if (!stopped && !merge(me, clone).error) {
          // compute average period and sample standard deviation
          mean = reduce(clones, cbSum, 0) / clones.length;
          deviation = Math.sqrt(reduce(clones, cbVariance, 0) / (clones.length - 1));

          if (deviation) {
            // remove outliers and compute average period on filtered results
            clones = filter(clones, cbOutlier, 0);
            mean = me.period = reduce(clones, cbSum, 0) / clones.length;
          }
          // compute other host results
          me.time = mean * me.count;
          me.hz = mean ? Math.round(1 / mean) : Number.MAX_VALUE;
        }
        delete me.averaging;
        me.running = false;
        me.onCycle(me);
        me.onComplete(me);
      }
      else if (!synchronous) {
        // run next clone in the sample
        clone = clones[times];
        call(clone, function() { clone.run(); });
      }
    }

    me.reset();
    me.averaging = me.running = true;
    me.onStart(me);

    while (i--) {
      // create clone and add to sample
      clones.push(me.clone({
        'onStart': onCycle,
        'onCycle': onCycle,
        'onComplete': onComplete
      }));
      // run instantly if sync or init async
      if (synchronous || !i) {
        clones[clones.length - 1].run(count, synchronous);
      }
    }
  }

  /*--------------------------------------------------------------------------*/

  function clone(options) {
    var key,
        me = this,
        result = new me.constructor(me.fn, extend(extend({ }, me.options), options));

    // copy manually added properties
    for (key in me) {
      if (!result[key]) {
        result[key] = me[key];
      }
    }
    result.reset();
    return result;
  }

  function noop() {
    // no operation performed
  }

  function stop() {
    var me = this,
        cal = Benchmark.CALIBRATION,
        error = me.error;

    if (me.running) {
      if (me != cal && cal.running) {
        cal.stop();
      }
      me.reset();
      me.error = error;
      me.onStop(me);
    }
  }

  function reset() {
    var me = this,
        proto = this.constructor.prototype;

    me.count = proto.count;
    me.cycles = proto.cycles;
    me.error = proto.error;
    me.hz = proto.hz;
    me.period = proto.period;
    me.running = proto.running;
    me.time = proto.time;
    me.onReset(me);
  }

  function run(count, synchronous) {
    var me = this;
    me.reset();
    me.running = true;

    // ensure calibration test has run
    if (!calibrate(function() {
          function rerun() {
            // continue, if not stopped during calibration
            if (me.running) {
              me.run(count, synchronous);
            } else {
              me.onStart(me);
              me.onStop(me);
              me.onComplete(me);
            }
          }
          call(me, rerun, synchronous);
        })) {
      me.count = count || me.INIT_COUNT;
      me.onStart(me);
      _run(me, synchronous);
    }
  }

  function _run(me, synchronous) {
    var divisor,
        period,
        time,
        count = me.count,
        cycles = me.cycles,
        max = me.MAX_COUNT,
        min = me.MIN_TIME;

    // continue, if not stopped between cycles
    if (me.running) {

      if (cycles) {
        cycles = ++me.cycles;
      } else {
        cycles = me.cycles = 1;
      }
      try {
        // clock executions of me.fn
        clock(me);

        time = me.time =
          // ensure positive numbers
          Math.max(0,
          // convert time from milliseconds to seconds
          (me.time / 1e3) -
          // calibrate by subtracting the base loop time
          (Benchmark.CALIBRATION.period || 0) * count);

        // per-operation time
        period = me.period = time / count;

        // ops per second
        me.hz = period ? Math.round(1 / period) : Number.MAX_VALUE;

        // do we need to do another cycle?
        me.running = time < min;

        // if so, compute the iteration count needed
        if (me.running) {
          // tests may return an initial time of 0 when INIT_COUNT is a small number,
          // to avoid that we set its count to something a bit higher
          if (!time && (divisor = CYCLE_DIVISORS[cycles])) {
            // try a fraction of the MAX_COUNT
            count = Math.floor(max / divisor);
          }
          else {
            // calculate how many more iterations it will take to achive the min testing time
            count += Math.ceil((min - time) / period);

            // to avoid freezing the browser stop running if the
            // next cycle would exceed the max count allowed
            if (count > max) {
              me.running = false;
            }
          }
        }
        me.count = count;
      }
      catch(e) {
        me.reset();
        me.error = e;
      }
      me.onCycle(me);
    }

    // figure out what to do next
    if (me.running) {
      call(me, _run, synchronous);
    }
    else if (me.averaging || me.error || (me.time * me.DEFAULT_AVERAGE) > 1) {
      me.onComplete(me);
    }
    else {
      // fast tests get their results averaged
      me.average(me.DEFAULT_AVERAGE, count, synchronous);
    }
  }

  /*--------------------------------------------------------------------------*/

  // test to establish iteration loop overhead
  Benchmark.CALIBRATION = new Calibration(noop, { 'INIT_COUNT': 3e3 });

  Benchmark.getPlatform = getPlatform;

  Benchmark.noop = noop;

  extend(Benchmark.prototype, {
    // delay between test cycles (secs)
    'CYCLE_DELAY': 0.01,

    // number of runs to average for fast tests
    'DEFAULT_AVERAGE': 30,

    // initial number of iterations
    'INIT_COUNT': 10,

    // max iterations allowed per cycle (used avoid locking up the browser)
    'MAX_COUNT': 1e6, // 1 million

    // minimum time a test should take to get valid results (secs)
    'MIN_TIME': 0.2,

    // number of times a test was executed
    'count': null,

    // number of cycles performed during testing
    'cycles': null,

    // an error object if the test failed
    'error': null,

    // number of test executions per second
    'hz': null,

    // time a test takes to do one execution (secs)
    'period': null,

    // flag to indicate if the test is running
    'running': false,

    // time a test takes to do the `count` number of executions (secs)
    'time': null,

    // callback invoked when testing is complete
    'onComplete': noop,

    // callback invoked when one test cycle ends
    'onCycle': noop,

    // callback invoked when test is reset
    'onReset': noop,

    // callback invoked when testing is started
    'onStart': noop,

    // callback invoked when testing is stopped
    'onStop': noop,

    // runs the test `n` times and returns the averaged test results
    'average': average,

    // create new benchmark with the same test function and options
    'clone': clone,

    // reset test state
    'reset': reset,

    // run the test
    'run': run,

    // stop testing (does not record times)
    'stop': stop
  });

  // expose
  global.Benchmark = Benchmark;

}(this));<|endoftext|>


<commit_before>import 'babel/polyfill';

import App from './components/App';
import AppHomeRoute from './routes/AppHomeRoute';
import React from 'react';
import ReactDOM from 'react-dom';
import Relay from 'react-relay';

ReactDOM.render(
  <Relay.RootContainer
    Component={App}
    route={new AppHomeRoute()}
  />,
  document.getElementById('app')
);
<commit_msg>fixed url<commit_after>import 'babel/polyfill';

import App from './components/App';
import AppHomeRoute from './routes/AppHomeRoute';
import React from 'react';
import ReactDOM from 'react-dom';
import Relay from 'react-relay';

Relay.injectNetworkLayer(
  new Relay.DefaultNetworkLayer('/api/v1/graphql')
);

ReactDOM.render(
  <Relay.RootContainer
    Component={App}
    route={new AppHomeRoute()}
  />,
  document.getElementById('app')
);
<|endoftext|>


<commit_before>import * as ACTIONS from 'constants/action_types';
import Lbryio from 'lbryio';
import { doNotify, MODALS } from 'lbry-redux';
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
import { selectUserIsRewardApproved } from 'redux/selectors/user';
import rewards from 'rewards';

export function doRewardList() {
  return dispatch => {
    dispatch({
      type: ACTIONS.FETCH_REWARDS_STARTED,
    });

    Lbryio.call('reward', 'list', { multiple_rewards_per_type: true })
      .then(userRewards => {
        dispatch({
          type: ACTIONS.FETCH_REWARDS_COMPLETED,
          data: { userRewards },
        });
      })
      .catch(() => {
        dispatch({
          type: ACTIONS.FETCH_REWARDS_COMPLETED,
          data: { userRewards: [] },
        });
      });
  };
}

export function doClaimRewardType(rewardType, options) {
  return (dispatch, getState) => {
    const state = getState();
    const unclaimedRewards = selectUnclaimedRewards(state);
    const reward = unclaimedRewards.find(ur => ur.reward_type === rewardType);
    const userIsRewardApproved = selectUserIsRewardApproved(state);

    if (!reward || reward.transaction_id) {
      // already claimed or doesn't exist, do nothing
      return;
    }

    if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) {
      const action = doNotify({
        id: MODALS.REWARD_APPROVAL_REQUIRED,
        isError: false,
      });
      dispatch(action);

      return;
    }

    dispatch({
      type: ACTIONS.CLAIM_REWARD_STARTED,
      data: { reward },
    });

    const success = successReward => {
      dispatch({
        type: ACTIONS.CLAIM_REWARD_SUCCESS,
        data: {
          reward: successReward,
        },
      });
      if (successReward.reward_type === rewards.TYPE_NEW_USER) {
        const action = doNotify({
          id: MODALS.FIRST_REWARD,
          isError: false,
        });
        dispatch(action);
      }
    };

    const failure = error => {
      dispatch({
        type: ACTIONS.CLAIM_REWARD_FAILURE,
        data: {
          reward,
          error: !options || !options.failSilently ? error : undefined,
        },
      });
    };

    rewards.claimReward(rewardType).then(success, failure);
  };
}

export function doClaimEligiblePurchaseRewards() {
  return (dispatch, getState) => {
    const state = getState();
    const unclaimedRewards = selectUnclaimedRewards(state);
    const userIsRewardApproved = selectUserIsRewardApproved(state);

    if (!userIsRewardApproved || !Lbryio.enabled) {
      return;
    }

    if (unclaimedRewards.find(ur => ur.reward_type === rewards.TYPE_FIRST_STREAM)) {
      dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
    } else {
      [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => {
        dispatch(doClaimRewardType(type, { failSilently: true }));
      });
    }
  };
}

export function doClaimRewardClearError(reward) {
  return dispatch => {
    dispatch({
      type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR,
      data: { reward },
    });
  };
}
<commit_msg>fetch rewards after successfully claiming reward<commit_after>import * as ACTIONS from 'constants/action_types';
import Lbryio from 'lbryio';
import { doNotify, MODALS } from 'lbry-redux';
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
import { selectUserIsRewardApproved } from 'redux/selectors/user';
import rewards from 'rewards';

export function doRewardList() {
  return dispatch => {
    dispatch({
      type: ACTIONS.FETCH_REWARDS_STARTED,
    });

    Lbryio.call('reward', 'list', { multiple_rewards_per_type: true })
      .then(userRewards => {
        dispatch({
          type: ACTIONS.FETCH_REWARDS_COMPLETED,
          data: { userRewards },
        });
      })
      .catch(() => {
        dispatch({
          type: ACTIONS.FETCH_REWARDS_COMPLETED,
          data: { userRewards: [] },
        });
      });
  };
}

export function doClaimRewardType(rewardType, options) {
  return (dispatch, getState) => {
    const state = getState();
    const unclaimedRewards = selectUnclaimedRewards(state);
    const reward = unclaimedRewards.find(ur => ur.reward_type === rewardType);
    const userIsRewardApproved = selectUserIsRewardApproved(state);

    if (!reward || reward.transaction_id) {
      // already claimed or doesn't exist, do nothing
      return;
    }

    if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) {
      const action = doNotify({
        id: MODALS.REWARD_APPROVAL_REQUIRED,
        isError: false,
      });
      dispatch(action);

      return;
    }

    dispatch({
      type: ACTIONS.CLAIM_REWARD_STARTED,
      data: { reward },
    });

    const success = successReward => {
      dispatch(doRewardList());
      dispatch({
        type: ACTIONS.CLAIM_REWARD_SUCCESS,
        data: {
          reward: successReward,
        },
      });
      if (successReward.reward_type === rewards.TYPE_NEW_USER) {
        const action = doNotify({
          id: MODALS.FIRST_REWARD,
          isError: false,
        });
        dispatch(action);
      }
    };

    const failure = error => {
      dispatch({
        type: ACTIONS.CLAIM_REWARD_FAILURE,
        data: {
          reward,
          error: !options || !options.failSilently ? error : undefined,
        },
      });
    };

    rewards.claimReward(rewardType).then(success, failure);
  };
}

export function doClaimEligiblePurchaseRewards() {
  return (dispatch, getState) => {
    const state = getState();
    const unclaimedRewards = selectUnclaimedRewards(state);
    const userIsRewardApproved = selectUserIsRewardApproved(state);

    if (!userIsRewardApproved || !Lbryio.enabled) {
      return;
    }

    if (unclaimedRewards.find(ur => ur.reward_type === rewards.TYPE_FIRST_STREAM)) {
      dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
    } else {
      [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => {
        dispatch(doClaimRewardType(type, { failSilently: true }));
      });
    }
  };
}

export function doClaimRewardClearError(reward) {
  return dispatch => {
    dispatch({
      type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR,
      data: { reward },
    });
  };
}
<|endoftext|>