<commit_before>var View = function(){};
var util = require('util');
util.inherits(View, require('events').EventEmitter);
var _view = new View();

var $editor = document.querySelector('#editor');
var $preview = document.querySelector('#preview');
var $sidebar = document.querySelector('#sidebar');

var openNewWindow = function(cssArr,jsArr,action,message){

	var newWindow = window.open('file://' + __dirname + '/../blank.html','newWindow','');

	newWindow.webContents.on('did-finish-load',function(){
		console.log('ready');
		newWindow.webContents.send('loadCss',cssArr);
		newWindow.webContents.send('loadJs',jsArr);
		newWindow.webContents.send(action,message);
		// 开发环境打开调试工具
		if(!/app$/.test(__dirname)){
			newWindow.openDevTools();
		}
	});
};

_view.openNoteInNewWindow = function(note){
	openNewWindow([
		'./editor.css',
		'./monokai_sublime.css'
	],[
		'./highlight.pack.js',
	],'loadNote',note);
};

_view.renderPreview = function(note){
	var $preview = document.querySelector('#preview');
	var Remarkable = require('remarkable');
	// var marked = require('marked');
	// var previewRenderer = new marked.Renderer();
	var previewRenderer = new Remarkable();
	var index = 0;
	/*previewRenderer.heading = function (text, level) {
		return '<h' + level + '>'+ text + '</h' + level + '>';
	};*/
	// var html = marked(note.content,{renderer:previewRenderer});
	previewRenderer.renderer.rules.paragraph_open = function (tokens, idx) {
		var line;
		if (tokens[idx].lines && tokens[idx].level === 0) {
			line = tokens[idx].lines[0];
			return '
';
		}
		return '
';
	};

	previewRenderer.renderer.rules.heading_open = function (tokens, idx) {
		var line;
		if (tokens[idx].lines && tokens[idx].level === 0) {
			line = tokens[idx].lines[0];
			return '<h' + tokens[idx].hLevel + ' class="line" data-line="' + line + '">';
		}
		return '<h' + tokens[idx].hLevel + '>';
	};
	var html = previewRenderer.render(note.content);
	$preview.innerHTML = html;

	Array.prototype.forEach.call($preview.querySelectorAll('pre code'),function($code){
		hljs.highlightBlock($code.parentNode);
	});
	var todo = require('./todo');
	var $allLi = $preview.querySelectorAll('li');
	for(var i = $allLi.length;i--;){
		var $li = $allLi[i];
		$li.innerHTML = todo.parseTodo($li.innerHTML);
	}

	/*var toc = require('marked-toc');
	var tocMarkdown = toc(note.content);
	var tocRenderer = new marked.Renderer();
	index = 1;
	tocRenderer.link = function(href,title,text){
		return ''+text+'';
	};
	var tocHtml = marked(tocMarkdown,{renderer:tocRenderer});
	var $toc = document.querySelector('#toc');
	if(tocHtml && this.isVisible('preview')){
		$toc.innerHTML = tocHtml;
		$toc.classList.remove('hide');
	}else{
		$toc.classList.add('hide');
	}*/
};

_view.init = function(){
	var _this = this;
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	window.addEventListener('DOMContentLoaded',function(){
		hideTabs.forEach(function(hideTab){
			_this.switchVisible(hideTab);
		});
	});
};

// 切换各栏显示状态
_view.switchVisible = function(eleName){

	var $ele;

	switch(eleName){
		case 'sidebar':
			$ele = $sidebar;
			break;
		case 'editor':
			$ele = $editor;
			break;
		case 'preview':
			$ele = $preview;
			break;
	}

	if($ele.classList.contains('hide')){
		$ele.classList.remove('hide');
	}else{
		$ele.classList.add('hide');
	}

	var sidebarVisible = !$sidebar.classList.contains('hide');
	var editorVisible = !$editor.classList.contains('hide');
	var previewVisible = !$preview.classList.contains('hide');

	var editorStatus = sidebarVisible?
		(previewVisible?'normal':'aloneWithSidebar'):
		(previewVisible?'noSidebar':'alone');
	var previewStatus = sidebarVisible?
		(editorVisible?'normal':'aloneWithSidebar'):
		(editorVisible?'noSidebar':'alone');

	if(editorVisible){
		$editor.classList.remove('aloneWithSidebar','noSidebar','alone');
		$editor.classList.add(editorStatus);
	}
	if(previewVisible){
		$preview.classList.remove('aloneWithSidebar','noSidebar','alone');
		$preview.classList.add(previewStatus);
	}

	var hideTabs = [];
	if(!sidebarVisible){
		hideTabs.push('sidebar');
	}
	if(!editorVisible){
		hideTabs.push('editor');
	}
	if(!previewVisible){
		hideTabs.push('preview');
	}

	// 处理TOC显示隐藏
	if(hideTabs.indexOf('preview') > -1){
		document.querySelector('#toc').classList.add('hide');
	}else{
		document.querySelector('#toc').classList.remove('hide');
	}

	_view.emit('layoutChange',hideTabs);

	localStorage.setItem('toonote_hideTabs',JSON.stringify(hideTabs));

};

_view.isVisible = function(eleName){
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	return hideTabs.indexOf(eleName) === -1;
};

var bindEvents = function(){

	// 折叠笔记
	$sidebar.querySelector('#noteList').addEventListener('click',function(e){
		if(e.target.tagName !== 'LI') return false;
		var $tmpNode = e.target.nextSibling;
		if(!$tmpNode) return;
		var thisLevel = +e.target.dataset.level;
		var isVisible = getComputedStyle($tmpNode).display !== 'none';
		while($tmpNode && +$tmpNode.dataset.level > thisLevel){
			if(isVisible){
				$tmpNode.style.display = 'none';
			}else{
				$tmpNode.style.display = '';
			}
			$tmpNode = $tmpNode.nextSibling;
		}

	},false);
};

_view.syncScroll = function(editor){
	var scrollMap = [];
	var lastBuildTime = 0;
	var buildScrollMap = function(){
		var $previewAnchors = $preview.querySelectorAll('h1,h2,h3,h4,h5,h6,p');
		Array.prototype.forEach.call($previewAnchors, function($previewAnchor){
			if(typeof $previewAnchor.dataset.line !== 'undefined'){
				scrollMap[$previewAnchor.dataset.line] = $previewAnchor.offsetTop;
			}
		});

		var content = editor.getContent();
		var contentLines = content.split('\n').length;
		if(!scrollMap[0]) scrollMap[0] = 0;
		if(!scrollMap[contentLines - 1]) scrollMap[contentLines - 1] = $preview.scrollHeight;
		for(var i = 1; i<contentLines -1; i++){
			if(!scrollMap[i]){
				var j = i+1;
				while(!scrollMap[j] && j < contentLines - 1){
					j++;
				}
				scrollMap[i] = scrollMap[i-1] + (scrollMap[j] - scrollMap[i-1]) / (j-i+1);
			}
		}
		// console.log(scrollMap);
		lastBuildTime = Date.now();
		return scrollMap;
	};

	var isRunning = false;
	var currentScroll;
	var delta;
	var lastTime;
	var animateDuring;
	var animatedScroll = function($elem, target, during){

		currentScroll = $elem.scrollTop;
		delta = target - currentScroll;
		if(!delta) return;
		lastTime = 0;
		animateDuring = during;

		// console.log('target:%d,delta:%d',target,delta);

		var animateFunc = function(time){
			if(lastTime){
				var timeDelta = time - lastTime;
				var animateDelta = delta * (timeDelta / animateDuring);
				// console.log('timeDelta %d, animateDelta, %d', timeDelta, animateDelta);
				if(Math.abs(animateDelta) < 1){
					$elem.scrollTop = target;
					isRunning = false;
				}else{
					$elem.scrollTop += animateDelta;
				}
			}
			lastTime = time;
			if((delta > 0 && $elem.scrollTop >= target) || (delta < 0 && $elem.scrollTop <= target) ||
				$elem.scrollTop + $elem.clientHeight >= $elem.scrollHeight){
				// console.log('target 2',target,delta > 0 && $elem.scrollTop >= target,delta < 0 && $elem.scrollTop <= target,$elem.scrollTop + $elem.clientHeight >= $elem.scrollHeight);
				$elem.scrollTop = target;
				isRunning = false;
			}else if(!isRunning){
				$elem.scrollTop = target;
				isRunning = false;
			}else{
				requestAnimationFrame(animateFunc);
			}
		};
		if(!isRunning){
			isRunning = true;
			requestAnimationFrame(animateFunc);
		}
	};

	var waitStart = Date.now();
	var timing;
	editor.session.on('changeScrollTop', function(scroll) {
		if(!lastBuildTime || Date.now() - lastBuildTime > 5000){
			buildScrollMap();
		}
		var targetRow = editor.getFirstVisibleRow();

		if(timing && Date.now() - waitStart < 500) clearTimeout(timing);
		timing = setTimeout(function(){
			animatedScroll($preview, scrollMap[targetRow], 500);
			waitStart = Date.now();
			timing = 0;
		},500);
		// console.log('scroll',scroll);
	});
};

bindEvents();

module.exports = _view;<commit_msg>修改滚动动画，引入tween.js<commit_after>var View = function(){};
var util = require('util');
util.inherits(View, require('events').EventEmitter);
var _view = new View();

var $editor = document.querySelector('#editor');
var $preview = document.querySelector('#preview');
var $sidebar = document.querySelector('#sidebar');

var openNewWindow = function(cssArr,jsArr,action,message){

	var newWindow = window.open('file://' + __dirname + '/../blank.html','newWindow','');

	newWindow.webContents.on('did-finish-load',function(){
		console.log('ready');
		newWindow.webContents.send('loadCss',cssArr);
		newWindow.webContents.send('loadJs',jsArr);
		newWindow.webContents.send(action,message);
		// 开发环境打开调试工具
		if(!/app$/.test(__dirname)){
			newWindow.openDevTools();
		}
	});
};

_view.openNoteInNewWindow = function(note){
	openNewWindow([
		'./editor.css',
		'./monokai_sublime.css'
	],[
		'./highlight.pack.js',
	],'loadNote',note);
};

_view.renderPreview = function(note){
	var $preview = document.querySelector('#preview');
	var Remarkable = require('remarkable');
	// var marked = require('marked');
	// var previewRenderer = new marked.Renderer();
	var previewRenderer = new Remarkable();
	var index = 0;
	/*previewRenderer.heading = function (text, level) {
		return '<h' + level + '>'+ text + '</h' + level + '>';
	};*/
	// var html = marked(note.content,{renderer:previewRenderer});
	previewRenderer.renderer.rules.paragraph_open = function (tokens, idx) {
		var line;
		if (tokens[idx].lines && tokens[idx].level === 0) {
			line = tokens[idx].lines[0];
			return '
';
		}
		return '
';
	};

	previewRenderer.renderer.rules.heading_open = function (tokens, idx) {
		var line;
		if (tokens[idx].lines && tokens[idx].level === 0) {
			line = tokens[idx].lines[0];
			return '<h' + tokens[idx].hLevel + ' class="line" data-line="' + line + '">';
		}
		return '<h' + tokens[idx].hLevel + '>';
	};
	var html = previewRenderer.render(note.content);
	$preview.innerHTML = html;

	Array.prototype.forEach.call($preview.querySelectorAll('pre code'),function($code){
		hljs.highlightBlock($code.parentNode);
	});
	var todo = require('./todo');
	var $allLi = $preview.querySelectorAll('li');
	for(var i = $allLi.length;i--;){
		var $li = $allLi[i];
		$li.innerHTML = todo.parseTodo($li.innerHTML);
	}

	/*var toc = require('marked-toc');
	var tocMarkdown = toc(note.content);
	var tocRenderer = new marked.Renderer();
	index = 1;
	tocRenderer.link = function(href,title,text){
		return ''+text+'';
	};
	var tocHtml = marked(tocMarkdown,{renderer:tocRenderer});
	var $toc = document.querySelector('#toc');
	if(tocHtml && this.isVisible('preview')){
		$toc.innerHTML = tocHtml;
		$toc.classList.remove('hide');
	}else{
		$toc.classList.add('hide');
	}*/
};

_view.init = function(){
	var _this = this;
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	window.addEventListener('DOMContentLoaded',function(){
		hideTabs.forEach(function(hideTab){
			_this.switchVisible(hideTab);
		});
	});
};

// 切换各栏显示状态
_view.switchVisible = function(eleName){

	var $ele;

	switch(eleName){
		case 'sidebar':
			$ele = $sidebar;
			break;
		case 'editor':
			$ele = $editor;
			break;
		case 'preview':
			$ele = $preview;
			break;
	}

	if($ele.classList.contains('hide')){
		$ele.classList.remove('hide');
	}else{
		$ele.classList.add('hide');
	}

	var sidebarVisible = !$sidebar.classList.contains('hide');
	var editorVisible = !$editor.classList.contains('hide');
	var previewVisible = !$preview.classList.contains('hide');

	var editorStatus = sidebarVisible?
		(previewVisible?'normal':'aloneWithSidebar'):
		(previewVisible?'noSidebar':'alone');
	var previewStatus = sidebarVisible?
		(editorVisible?'normal':'aloneWithSidebar'):
		(editorVisible?'noSidebar':'alone');

	if(editorVisible){
		$editor.classList.remove('aloneWithSidebar','noSidebar','alone');
		$editor.classList.add(editorStatus);
	}
	if(previewVisible){
		$preview.classList.remove('aloneWithSidebar','noSidebar','alone');
		$preview.classList.add(previewStatus);
	}

	var hideTabs = [];
	if(!sidebarVisible){
		hideTabs.push('sidebar');
	}
	if(!editorVisible){
		hideTabs.push('editor');
	}
	if(!previewVisible){
		hideTabs.push('preview');
	}

	// 处理TOC显示隐藏
	if(hideTabs.indexOf('preview') > -1){
		document.querySelector('#toc').classList.add('hide');
	}else{
		document.querySelector('#toc').classList.remove('hide');
	}

	_view.emit('layoutChange',hideTabs);

	localStorage.setItem('toonote_hideTabs',JSON.stringify(hideTabs));

};

_view.isVisible = function(eleName){
	var hideTabs = JSON.parse(localStorage.getItem('toonote_hideTabs') || '[]');
	return hideTabs.indexOf(eleName) === -1;
};

var bindEvents = function(){

	// 折叠笔记
	$sidebar.querySelector('#noteList').addEventListener('click',function(e){
		if(e.target.tagName !== 'LI') return false;
		var $tmpNode = e.target.nextSibling;
		if(!$tmpNode) return;
		var thisLevel = +e.target.dataset.level;
		var isVisible = getComputedStyle($tmpNode).display !== 'none';
		while($tmpNode && +$tmpNode.dataset.level > thisLevel){
			if(isVisible){
				$tmpNode.style.display = 'none';
			}else{
				$tmpNode.style.display = '';
			}
			$tmpNode = $tmpNode.nextSibling;
		}

	},false);
};

_view.syncScroll = function(editor){
	var scrollMap = [];
	var lastBuildTime = 0;
	var buildScrollMap = function(){
		var $previewAnchors = $preview.querySelectorAll('h1,h2,h3,h4,h5,h6,p');
		Array.prototype.forEach.call($previewAnchors, function($previewAnchor){
			if(typeof $previewAnchor.dataset.line !== 'undefined'){
				scrollMap[$previewAnchor.dataset.line] = $previewAnchor.offsetTop;
			}
		});

		var content = editor.getContent();
		var contentLines = content.split('\n').length;
		if(!scrollMap[0]) scrollMap[0] = 0;
		if(!scrollMap[contentLines - 1]) scrollMap[contentLines - 1] = $preview.scrollHeight;
		for(var i = 1; i<contentLines -1; i++){
			if(!scrollMap[i]){
				var j = i+1;
				while(!scrollMap[j] && j < contentLines - 1){
					j++;
				}
				scrollMap[i] = scrollMap[i-1] + (scrollMap[j] - scrollMap[i-1]) / (j-i+1);
			}
		}
		// console.log(scrollMap);
		lastBuildTime = Date.now();
		return scrollMap;
	};

	var TWEEN = require('tween.js');
	var animatedScroll = function($elem, target, during){

	    init();
	    animate();

	    function init() {
	    	TWEEN.removeAll();
	        var tween = new TWEEN.Tween( {scrollTop:$elem.scrollTop} )
	            .to( {scrollTop: target}, 500 )
	            .easing( TWEEN.Easing.Quadratic.Out )
	            .onUpdate( function () {

	            	$elem.scrollTop = this.scrollTop;

	            })
	            .start();
	    }

	    function animate(time) {

	        requestAnimationFrame(animate);
	        TWEEN.update(time);
	    }

	};

	var waitStart = Date.now();
	var timing;
	editor.session.on('changeScrollTop', function(scroll) {
		if(!lastBuildTime || Date.now() - lastBuildTime > 5000){
			buildScrollMap();
		}
		var targetRow = editor.getFirstVisibleRow();

		if(timing && Date.now() - waitStart < 100) clearTimeout(timing);
		timing = setTimeout(function(){
			// console.log(targetRow,scrollMap[targetRow]);
			animatedScroll($preview, scrollMap[targetRow], 500);
			waitStart = Date.now();
			timing = 0;
		},100);
		// console.log('scroll',scroll);
	});
};

bindEvents();

module.exports = _view;<|endoftext|>


<commit_before>var Demand = function (data) {
  this.data = data;
  this.push = function(){
    var postsRef = global.rootRef.child("demands/"+this.data.id);
    postsRef.set({
      fname: this.data.asker,
      comments: this.data.comments,
      deliverer: this.data.deliverer,
      destination: {
        long: this.data.destination.long,
        lat: this.data.destination.lat
      },
      item: this.data.item,
      price: this.data.price,
      shop: this.data.shop,
      tip: this.data.tip
    });
  }
}

User.findByUsername = function (id, callback) {
  global.rootRef.child("demands/"+id).on("value", function(snapshot) {
    var ret = snapshot.val();
    if(ret === null){
      callback(null);
    }else{
      ret.id = id;
      callback(ret);
    }
  });
}

module.exports = Demand;
<commit_msg>Fixed conflict<commit_after>var Demand = function (data) {
  this.data = data;
  this.push = function(){
    var postsRef = global.rootRef.child("demands/"+this.data.id);
    postsRef.set({
      fname: this.data.asker,
      comments: this.data.comments,
      deliverer: this.data.deliverer,
      destination: {
        long: this.data.destination.long,
        lat: this.data.destination.lat
      },
      item: this.data.item,
      price: this.data.price,
      shop: this.data.shop,
      tip: this.data.tip
    });
  }
}

Demand.findById = function (id, callback) {
  global.rootRef.child("demands/"+id).on("value", function(snapshot) {
    var ret = snapshot.val();
    if(ret === null){
      callback(null);
    }else{
      ret.id = id;
      callback(ret);
    }
  });
}

module.exports = Demand;
<|endoftext|>


<commit_before>'use strict';

const ConnManager = require("./conn_manager");
const MapManager = require("./map_manager");
const World = require("./world");
const PlayerManager = require("./player_manager");
const Vector2D = require("./utils/vector");
const Resource = require("./resource");
const Config = require("./config");

class CraftingZone {

    constructor(id, position, diameter)
    {
        this.id = id;
        this.diameter = diameter;
        this.position = position;
        this.dropZone = Config.CRAFTING_ZONE_DROP_DIAMETER;
        this.progress = 0;
        this.spendResources = Config.CRAFTING_RESOURCES;
    }

}

class Team {

    constructor(teamPosition, id) {
        this.id = id;
        this.position = teamPosition;
        this.resourceStash = {};
        this.craftingZone = null;
    }

    getAsJson() {
        return { "position" : this.position, "resourceStash" : this.resourceStash };
    }

}

class Match {

    constructor(io) {
        this.io = io;

        this.isRunning = false;
        this.winnerTeam = null;
        this.teamCount = 2;
        this.neededResources = Config.CRAFTING_MAX_RESOURCES;
        this.teams = [];
        var marginX = Config.MAP_MARGIN_X*Config.TILE_SIZE_X;
        var marginY = Config.MAP_MARGIN_Y*Config.TILE_SIZE_Y;
        var mapSizeX = Config.MAP_SIZE_X*Config.TILE_SIZE_X;
        var mapSizeY = Config.MAP_SIZE_Y*Config.TILE_SIZE_Y;
        var spawnMarginX = Config.TILE_SIZE_X*5;
        var spawnMarginY = Config.TILE_SIZE_Y*5;

        this.teamSpawnPoints = [
            new Vector2D(marginX+spawnMarginX, marginY+spawnMarginX),
            new Vector2D(mapSizeX-marginX-spawnMarginX, mapSizeY-marginY-spawnMarginY)];
        this.resourceSpawnPoints = [new Vector2D(Config.TILE_SIZE_X*9, Config.TILE_SIZE_Y*9), new Vector2D(Config.TILE_SIZE_X*32, Config.TILE_SIZE_Y*32), new Vector2D(Config.TILE_SIZE_X*32, Config.TILE_SIZE_X*54)];
        this.resources = [];
        this.resourceCount = 0;

        this.craftingZoneCount = 0;
        this.craftingZones = [];

        this.setupMatch();
    }

    setupMatch()
    {
        for(let i = 0; i < this.teamCount; i++)
        {
            this.teams.push(new Team(this.teamSpawnPoints[i], i));
        }

        for(let i=0; i < this.teams.length; i++)
        {
            this.teams[i].resourceStash = {};
            for(let resource in this.neededResources)
            {
                this.teams[i].resourceStash[resource] = 0;
            }

            // initialize crafting Zones
            this.craftingZoneCount++;
            let currCZ = new CraftingZone(this.craftingZoneCount, this.teamSpawnPoints[i], Config.CRAFTING_ZONE_DIAMETER);
            this.craftingZones.push(currCZ);

            this.teams[i].craftingZone = currCZ;
        }

        for (let i = 0; i < this.resourceSpawnPoints.length; i++) {
                this.resources.push(new Resource(this.getResourceId(),
                    this.resourceSpawnPoints[i].addScalar(Math.floor(Math.random() * 5)), Resource.getResourceType(i), 10));
        }

    }

    getResourceId() {
        this.resourceCount++;
        return this.resourceCount;
    }

    getCraftingZoneOfTeam(teamNumber)
    {
        var team = this.teams[teamNumber];
        if(team) return team.craftingZone; else {
            console.log("Error! There was no team with the team-number\""+teamNumber+"\"");
            return null;
        }
    }

    getAsJson() {
        let allTeams = [];
        for(let i = 0; i < this.teams.length; i++) {
            allTeams.push(this.teams[i]);
        }

        return { "neededResources": this.neededResources, "resources" : this.resources, "teamSpawns" : this.teamSpawnPoints, "teamData" : allTeams };
    }

    dropResource(player) {
        if (player.inventory.length < 0) { return; }

        let teamData = [];
        for (let i = 0; i < this.teams.length; i++) {
            if(player.team.id == this.teams[i].id) this.teams[i].resourceStash[player.inventory.pop()] += 1
            teamData.push(this.teams[i].getAsJson());
        }

        this.io.emit("resource pickup", {
            player: player.id,
            resource : "none"
        });

        this.io.emit("resources changed", {
            resources : this.resources,
            teamResources : teamData
        });

        player.inventory = [];
    }

    craft(team) {

        let spendSum = 0;
        let neededSum = 0;

        for (let res of Object.keys(team.resourceStash)) {

            while (team.resourceStash[res] > 0) {
                team.resourceStash[res]--;
                team.craftingZone.spendResources[res]++;
            }

            spendSum += team.craftingZone.spendResources[res];
            neededSum += this.neededResources[res];

        }

        team.craftingZone.progress = spendSum / neededSum;

        this.io.emit("crafting progress", {
            team: team.id,
            progress: team.craftingZone.progress
        });

        if (team.craftingZone.progress >= 1) {
            this.winnerTeam = team;

            this.io.emit("game won", {
                winner : team
            });
        }

    }

    checkMouseHit(mousePos, player) {

        const playerPos = new Vector2D(player.collisionObject.position.x, player.collisionObject.position.y);

        for (let i = 0; i < this.resources.length; i++) {
            let res = this.resources[i];

            if (playerPos.subVec(res.position).abs() < res.farmRange && mousePos.subVec(res.position).abs() < res.area) {

                player.inventory.push(res.type);
                res.amount -= 1;

                this.io.emit("resource pickup", {
                    player: player.id,
                    resource : res.type
                });

                if (res.amount <= 0) {
                    this.resources.splice(i, 1);

                    let teamData = [];
                    for (let i = 0; i < this.teams.length; i++) {
                        teamData.push(this.teams[i].getAsJson());
                    }

                    this.io.emit("resources changed", {
                        resources : this.resources,
                        teamResources : teamData
                    });
                }

            }
        }

        for (let i = 0; i < this.craftingZones.length; i++) {
            let crafting = this.craftingZones[i];

            if (playerPos.subVec(crafting.position).abs() < crafting.diameter && mousePos.subVec(crafting.position).abs() < crafting.diameter) {

                this.craft(player.team);
            }
        }

    }

    createResource(resourceType, position) {
        this.resources.push(new Resource(this.getResourceId(), position, resourceType, 1));

        let teamData = [];
        for (let i = 0; i < this.teams.length; i++) {
            teamData.push(this.teams[i].getAsJson());
        }

        this.io.emit("resources changed", {
            resources : this.resources,
            teamResources : teamData
        });
    }

    update(delta) {

    }
}

module.exports = Match;<commit_msg>spawn triangle better<commit_after>'use strict';

const ConnManager = require("./conn_manager");
const MapManager = require("./map_manager");
const World = require("./world");
const PlayerManager = require("./player_manager");
const Vector2D = require("./utils/vector");
const Resource = require("./resource");
const Config = require("./config");

class CraftingZone {

    constructor(id, position, diameter)
    {
        this.id = id;
        this.diameter = diameter;
        this.position = position;
        this.dropZone = Config.CRAFTING_ZONE_DROP_DIAMETER;
        this.progress = 0;
        this.spendResources = Config.CRAFTING_RESOURCES;
    }

}

class Team {

    constructor(teamPosition, id) {
        this.id = id;
        this.position = teamPosition;
        this.resourceStash = {};
        this.craftingZone = null;
    }

    getAsJson() {
        return { "position" : this.position, "resourceStash" : this.resourceStash };
    }

}

class Match {

    constructor(io) {
        this.io = io;

        this.isRunning = false;
        this.winnerTeam = null;
        this.teamCount = 2;
        this.neededResources = Config.CRAFTING_MAX_RESOURCES;
        this.teams = [];
        var marginX = Config.MAP_MARGIN_X*Config.TILE_SIZE_X;
        var marginY = Config.MAP_MARGIN_Y*Config.TILE_SIZE_Y;
        var mapSizeX = Config.MAP_SIZE_X*Config.TILE_SIZE_X;
        var mapSizeY = Config.MAP_SIZE_Y*Config.TILE_SIZE_Y;
        var spawnMarginX = Config.TILE_SIZE_X*5;
        var spawnMarginY = Config.TILE_SIZE_Y*5;

        this.teamSpawnPoints = [
            new Vector2D(marginX+spawnMarginX, marginY+spawnMarginX),
            new Vector2D(mapSizeX-marginX-spawnMarginX, mapSizeY-marginY-spawnMarginY)];
        this.resourceSpawnPoints = [new Vector2D(Config.TILE_SIZE_X*32, Config.TILE_SIZE_Y*10), new Vector2D(Config.TILE_SIZE_X*32, Config.TILE_SIZE_Y*32), new Vector2D(Config.TILE_SIZE_X*32, Config.TILE_SIZE_X*54)];
        this.resources = [];
        this.resourceCount = 0;

        this.craftingZoneCount = 0;
        this.craftingZones = [];

        this.setupMatch();
    }

    setupMatch()
    {
        for(let i = 0; i < this.teamCount; i++)
        {
            this.teams.push(new Team(this.teamSpawnPoints[i], i));
        }

        for(let i=0; i < this.teams.length; i++)
        {
            this.teams[i].resourceStash = {};
            for(let resource in this.neededResources)
            {
                this.teams[i].resourceStash[resource] = 0;
            }

            // initialize crafting Zones
            this.craftingZoneCount++;
            let currCZ = new CraftingZone(this.craftingZoneCount, this.teamSpawnPoints[i], Config.CRAFTING_ZONE_DIAMETER);
            this.craftingZones.push(currCZ);

            this.teams[i].craftingZone = currCZ;
        }

        for (let i = 0; i < this.resourceSpawnPoints.length; i++) {
                this.resources.push(new Resource(this.getResourceId(),
                    this.resourceSpawnPoints[i].addScalar(Math.floor(Math.random() * 5)), Resource.getResourceType(i), 10));
        }

    }

    getResourceId() {
        this.resourceCount++;
        return this.resourceCount;
    }

    getCraftingZoneOfTeam(teamNumber)
    {
        var team = this.teams[teamNumber];
        if(team) return team.craftingZone; else {
            console.log("Error! There was no team with the team-number\""+teamNumber+"\"");
            return null;
        }
    }

    getAsJson() {
        let allTeams = [];
        for(let i = 0; i < this.teams.length; i++) {
            allTeams.push(this.teams[i]);
        }

        return { "neededResources": this.neededResources, "resources" : this.resources, "teamSpawns" : this.teamSpawnPoints, "teamData" : allTeams };
    }

    dropResource(player) {
        if (player.inventory.length < 0) { return; }

        let teamData = [];
        for (let i = 0; i < this.teams.length; i++) {
            if(player.team.id == this.teams[i].id) this.teams[i].resourceStash[player.inventory.pop()] += 1
            teamData.push(this.teams[i].getAsJson());
        }

        this.io.emit("resource pickup", {
            player: player.id,
            resource : "none"
        });

        this.io.emit("resources changed", {
            resources : this.resources,
            teamResources : teamData
        });

        player.inventory = [];
    }

    craft(team) {

        let spendSum = 0;
        let neededSum = 0;

        for (let res of Object.keys(team.resourceStash)) {

            while (team.resourceStash[res] > 0) {
                team.resourceStash[res]--;
                team.craftingZone.spendResources[res]++;
            }

            spendSum += team.craftingZone.spendResources[res];
            neededSum += this.neededResources[res];

        }

        team.craftingZone.progress = spendSum / neededSum;

        this.io.emit("crafting progress", {
            team: team.id,
            progress: team.craftingZone.progress
        });

        if (team.craftingZone.progress >= 1) {
            this.winnerTeam = team;

            this.io.emit("game won", {
                winner : team
            });
        }

    }

    checkMouseHit(mousePos, player) {

        const playerPos = new Vector2D(player.collisionObject.position.x, player.collisionObject.position.y);

        for (let i = 0; i < this.resources.length; i++) {
            let res = this.resources[i];

            if (playerPos.subVec(res.position).abs() < res.farmRange && mousePos.subVec(res.position).abs() < res.area) {

                player.inventory.push(res.type);
                res.amount -= 1;

                this.io.emit("resource pickup", {
                    player: player.id,
                    resource : res.type
                });

                if (res.amount <= 0) {
                    this.resources.splice(i, 1);

                    let teamData = [];
                    for (let i = 0; i < this.teams.length; i++) {
                        teamData.push(this.teams[i].getAsJson());
                    }

                    this.io.emit("resources changed", {
                        resources : this.resources,
                        teamResources : teamData
                    });
                }

            }
        }

        for (let i = 0; i < this.craftingZones.length; i++) {
            let crafting = this.craftingZones[i];

            if (playerPos.subVec(crafting.position).abs() < crafting.diameter && mousePos.subVec(crafting.position).abs() < crafting.diameter) {

                this.craft(player.team);
            }
        }

    }

    createResource(resourceType, position) {
        this.resources.push(new Resource(this.getResourceId(), position, resourceType, 1));

        let teamData = [];
        for (let i = 0; i < this.teams.length; i++) {
            teamData.push(this.teams[i].getAsJson());
        }

        this.io.emit("resources changed", {
            resources : this.resources,
            teamResources : teamData
        });
    }

    update(delta) {

    }
}

module.exports = Match;<|endoftext|>


<commit_before>/**
 * 从 16 进制的色值解析成 rgba 格式的色值
 * @param { string } hex, #000、#000A、#000000、#000000AA，参数只能是这四种格式
 * @returns {
  r: number;
  g: number;
  b: number;
  a: number;
}
 */
export function hexToRgba (hex) {
  // 异常情况
  if (!hex) {
    return {
      r: 0,
      g: 0,
      b: 0,
      a: 0
    }
  }
  // 去掉 #
  let tmpHex = hex.slice(1)
  const tmpHexLen = tmpHex.length
  // 处理 16 进制色值位数异常的情况
  if (![3, 4, 6, 8].includes(tmpHexLen)) {
    return {
      r: 0,
      g: 0,
      b: 0,
      a: 0
    }
  }
  // 格式化 tmpHex，使其变成 rrggbb 或 rrggbbaa
  if (tmpHexLen === 3 || tmpHexLen === 4) {
    // rgb => rrggbb || rgba => rrggbbaa
    tmpHex = tmpHex.replace(/(\w{1})/g, 'r1r1')
  }
  // r1 ~ a2
  const [r1, r2, g1, g2, b1, b2, a1, a2] = tmpHex.match(/(\w{1})/g)
  // rgb
  const r = parseInt(r1) * 16 + parseInt(r2); const g = parseInt(g1) * 16 + parseInt(g2); const b = parseInt(b1) * 16 + parseInt(b2)

  if (!a1) {
    return { r, g, b, a: 1 }
  }

  return {
    r, g, b, a: (`0x100${a1}${a2}` - 0x10000) / 255
  }
}
<commit_msg>fix: 修复 hexToRgba 转换出错的 bug<commit_after>/**
 * 从 16 进制的色值解析成 rgba 格式的色值
 * @param { string } hex, #000、#000A、#000000、#000000AA，参数只能是这四种格式
 * @returns {
  r: number;
  g: number;
  b: number;
  a: number;
}
 */
export function hexToRgba(hex) {
  // 异常情况
  if (!hex) {
    return {
      r: 0,
      g: 0,
      b: 0,
      a: 0,
    }
  }
  // 去掉 #
  let tmpHex = hex.slice(1)
  const tmpHexLen = tmpHex.length
  // 处理 16 进制色值位数异常的情况
  if (![3, 4, 6, 8].includes(tmpHexLen)) {
    return {
      r: 0,
      g: 0,
      b: 0,
      a: 0,
    }
  }
  // 格式化 tmpHex，使其变成 rrggbb 或 rrggbbaa
  if (tmpHexLen === 3 || tmpHexLen === 4) {
    // rgb => rrggbb || rgba => rrggbbaa
    tmpHex = tmpHex.replace(/(\w{1})/g, '$1$1')
  }
  // rgba
  let [sr, sg, sb, sa] = tmpHex.match(/(\w{2})/g)
  // rgb
  const r = parseInt(sr, 16), g = parseInt(sg, 16), b = parseInt(sb, 16)

  if (!sa) {
    return { r, g, b, a: 1 }
  }

  return {
    r, g, b, a: (`0x100${sa}` - 0x10000) / 255
  }
}
<|endoftext|>


<commit_before>"use strict";

var smallModifiers = ['kon', 'lili', 'mute', 'sin'],
    narrowModifiers = ['wan', 'tu', 'anu', 'en', 'kin'];

function getSizeOf(token) {
    if (smallModifiers.indexOf(token) > -1) {
        return [1, 0.5];
    } else if (narrowModifiers.indexOf(token) > -1) {
        return [0.5, 1];
    } else {
        return [1, 1];
    }
}

var options = [], hash = {};

function go(tokens, state, size, direction, index, length) {

    var newState = state.slice(0),
        newSize = size.slice(0);

    var prevSize = getSizeOf(tokens[index]),
        glyphPosition = [direction === 'right' ? size[0] : 0, direction === 'down' ? size[1] : 0];

    var sizeSum = [0, 0], addSize;
    // determine size sum
    for (var i = index; i < index + length; i++) {
        addSize = getSizeOf(tokens[i]);
        if ((direction === 'down' && addSize[1] !== prevSize[1]) ||
            (direction === 'right' && addSize[0] !== prevSize[0])) {

            console.log('returning ', state.length, index, length);
            return;
        }
        sizeSum = [sizeSum[0] + addSize[0], sizeSum[1] + addSize[1]];
    }

    var actualAdded = 0;
    // now add the glyphs one by one
    for (var i = index; i < index + length; i++) {
        var glyphSize = [], addX = 0, addY = 0;
        addSize = getSizeOf(tokens[i]);

        switch (direction) {
            case 'down':
                addY = addSize[1] * size[0] / sizeSum[0];
                glyphSize = [addSize[0] * addY / addSize[1], addY];

                newSize = [size[0], size[1] + addY];

                break;
            case 'right':
                addX = addSize[0] * size[1] / sizeSum[1];
                glyphSize = [addX, addSize[1] * addX / addSize[0]];

                newSize = [size[0] + addX, size[1]];
                break;
        }
        prevSize = addSize;
        newState.push({token: tokens[i], size: glyphSize, position: glyphPosition});
        actualAdded++;

        // update glyphposition
        glyphPosition = [glyphPosition[0] + (direction === 'down' ? glyphSize[0] : 0),
            glyphPosition[1] + (direction === 'right' ? glyphSize[1] : 0)];
    }

    if (index + actualAdded === tokens.length) {
        var newOption = {
            state: newState,
            size: newSize,
            ratio: newSize[0] / newSize[1],
            normedRatio: newSize[0] / newSize[1] < 1 ? newSize[0] / newSize[1] : newSize[1] / newSize[0],
            surface: newSize[0] * newSize[1]
        };
        if (!hash[JSON.stringify(newOption)]) {
            options.push(newOption);
            hash[JSON.stringify(newOption)] = newOption;
        }
        return;
    }

    for (var j = 1; j < tokens.length - index; j++) {
        go(tokens, newState, newSize, 'right', index + actualAdded, j);
        go(tokens, newState, newSize, 'down', index + actualAdded, j);
    }
}

function convertNounPhrase(tokens) {
    // choose both to go right and down
    for (var j = 1; j < tokens.length; j++) {
        go(tokens, [{token: tokens[0], size: [1, 1], position: [0, 0]}], [1, 1], 'right', 1, j);
        go(tokens, [{token: tokens[0], size: [1, 1], position: [0, 0]}], [1, 1], 'down', 1, j);
    }

    options.sort(function (a, b) {
        return a.surface - b.surface;
    });

    console.log(options);
    options.forEach(function (option) {
        renderOption(option);
    });

}

function renderOption(option) {
    var container = document.createElement('div');
    container.classList.add('toki-nounphrase');
    container.style.width = option.size[0] + 'em';
    container.style.height = option.size[1] + 'em';

    option.state.forEach(function (glyph) {
        var element = document.createElement('div');
        element.style.width = glyph.size[0] + 'em';
        element.style.height = glyph.size[1] + 'em';
        element.style.left = glyph.position[0] + 'em';
        element.style.top = glyph.position[1] + 'em';
        element.setAttribute('data-toki-word', glyph.token);

        container.appendChild(element);
    });
    document.getElementById('sitelen').appendChild(container);
}

var tokens = ['jan', 'utala', 'pona', 'wan', 'lili', 'wan'];
//var tokens = ['jan', 'utala', 'pona', 'mi', 'wan'];
//var tokens = ['jan', 'wan'];

setTimeout(function () {
    convertNounPhrase(tokens);
}, 500);

//function convertToInstructions(structuredSentence) {
//
//    var instructions = [],
//        size;
//
//    structuredSentence.forEach(function (part) {
//
//        switch (part.part) {
//            case 'subject':
//            case 'verbPhrase':
//            case 'directObject':
//                instructions.push.apply(instructions, convertNounPhrase(part));
//                break;
//            case 'punctuation':
//                instructions.push({rule: 'addPunctuation', glyph: part.token === '.' ? 'period' : '', size: 'wide'});
//                break;
//            default:
//                console.log('ERR: unknown part');
//                break;
//        }
//    });
//
//    // determine container sizes
//    for (var i = 0; i < instructions.length; i++) {
//        if (instructions[i].rule === 'openContainer') {
//            var closure = 0, regularGlyphs = 0, narrowGlyphs = 0;
//            for (var j = i; j < instructions.length; j++) {
//                switch (instructions[j].rule) {
//                    case 'openContainer':
//                        closure++;
//                        break;
//                    case 'closeContainer':
//                        closure--;
//                        if (closure === 0) {
//                            // round narrow glyphs
//                            var roundglyphs = Math.round(regularGlyphs + narrowGlyphs / 2);
//                            // add metadata to the container
//                            instructions[i].size = roundglyphs === 1 ? 'regular' :
//                                roundglyphs > 3 || (roundglyphs === 3 && narrowGlyphs === 1) ? 'double' : 'wide';
//                            instructions[i].children = roundglyphs;
//                            closure = -1;
//                        }
//                        break;
//                    case 'addGlyph':
//                        // narrow glyphs only count as half
//                        if (narrowModifiers.indexOf(instructions[j].glyph) > -1) {
//                            narrowGlyphs++;
//                        } else {
//                            regularGlyphs++;
//                        }
//                        break;
//                }
//                if (closure === -1) {
//                    break;
//                }
//            }
//        }
//    }
//    return instructions;
//}

<commit_msg>Fixed forbidden locations problem and normalizing all options.<commit_after>"use strict";

var smallModifiers = ['kon', 'lili', 'mute', 'sin'],
    narrowModifiers = ['wan', 'tu', 'anu', 'en', 'kin'];

function getSizeOf(token) {
    if (smallModifiers.indexOf(token) > -1) {
        return [1, 0.5];
    } else if (narrowModifiers.indexOf(token) > -1) {
        return [0.5, 1];
    } else {
        return [1, 1];
    }
}

var options = [], hash = {};

function go(tokens, state, size, direction, index, length, forbidden) {
    var newSize, newState, newForbidden, i, j;

    if (!state) {
        newSize = getSizeOf(tokens[0]);
        newState = [{token: tokens[0], size: newSize, position: [0, 0]}];
        newForbidden = [];
        newForbidden.push(JSON.stringify(newSize));

        for (j = 1; j < tokens.length; j++) {
            go(tokens, newState, newSize, 'right', 1, j, newForbidden);
            go(tokens, newState, newSize, 'down', 1, j, newForbidden);
        }
        return;
    }

    newState = state.slice(0);
    newSize = size.slice(0);
    newForbidden = forbidden.slice(0);

    var prevSize = getSizeOf(tokens[index]),
        glyphPosition = [direction === 'right' ? size[0] : 0, direction === 'down' ? size[1] : 0];

    var sizeSum = [0, 0], addSize;
    // determine size sum
    for (var i = index; i < index + length; i++) {
        addSize = getSizeOf(tokens[i]);
        if ((direction === 'down' && addSize[1] !== prevSize[1]) ||
            (direction === 'right' && addSize[0] !== prevSize[0])) {
            return;
        }
        sizeSum = [sizeSum[0] + addSize[0], sizeSum[1] + addSize[1]];
    }

    var actualAdded = 0;
    // now add the glyphs one by one
    for (var i = index; i < index + length; i++) {
        var glyphSize = [], addX = 0, addY = 0;
        addSize = getSizeOf(tokens[i]);

        switch (direction) {
            case 'down':
                addY = addSize[1] * size[0] / sizeSum[0];
                glyphSize = [addSize[0] * addY / addSize[1], addY];

                newSize = [size[0], size[1] + addY];
                break;
            case 'right':
                addX = addSize[0] * size[1] / sizeSum[1];
                glyphSize = [addX, addSize[1] * addX / addSize[0]];

                newSize = [size[0] + addX, size[1]];
                break;
        }

        if (direction === 'down' && newForbidden.indexOf(JSON.stringify(glyphPosition)) > -1) {
            return;
        } else {
            prevSize = addSize;
            newState.push({token: tokens[i], size: glyphSize, position: glyphPosition});
            actualAdded++;

            // update glyphposition
            glyphPosition = [glyphPosition[0] + (direction === 'down' ? glyphSize[0] : 0),
                glyphPosition[1] + (direction === 'right' ? glyphSize[1] : 0)];

            newForbidden.push(JSON.stringify([glyphPosition[0] + glyphSize[0], glyphPosition[1] + glyphSize[1]]));
        }
    }

    if (index + actualAdded === tokens.length) {
        var newOption = {
            state: newState,
            size: newSize,
            ratio: newSize[0] / newSize[1],
            normedRatio: newSize[0] / newSize[1] < 1 ? newSize[0] / newSize[1] : newSize[1] / newSize[0],
            surface: newSize[0] * newSize[1]
        };
        newOption = normalizeOption(JSON.stringify(newOption));

        if (!hash[JSON.stringify(newOption)]) {
            options.push(newOption);
            hash[JSON.stringify(newOption)] = newOption;
        }
        return;
    }

    for (var j = 1; j < tokens.length - index; j++) {
        go(tokens, newState, newSize, 'right', index + actualAdded, j, newForbidden);
        go(tokens, newState, newSize, 'down', index + actualAdded, j, newForbidden);
    }
}

function convertNounPhrase(tokens) {
    go(tokens);

    options.sort(function (a, b) {
        return a.surface - b.surface;
        //return b.normedRatio - a.normedRatio;
    });

    options.forEach(function (option) {
        renderOption(option);
    });

}

function renderOption(option) {
    var container = document.createElement('div');
    container.classList.add('toki-nounphrase');
    container.style.width = option.size[0] + 'em';
    container.style.height = option.size[1] + 'em';
    //container.style.fontSize = getNormalizerScale(option)/2 + 'em';

    option.state.forEach(function (glyph) {
        var element = document.createElement('div');
        element.style.width = glyph.size[0] + 'em';
        element.style.height = glyph.size[1] + 'em';
        element.style.left = glyph.position[0] + 'em';
        element.style.top = glyph.position[1] + 'em';
        element.setAttribute('data-toki-word', glyph.token);

        container.appendChild(element);
    });
    document.getElementById('sitelen').appendChild(container);
}

function normalizeOption(option) {
    option = JSON.parse(option);

    var minSize = 1;
    option.state.forEach(function (glyph) {
        if (glyph.size[0] < minSize) {
            minSize = glyph.size[0];
        }
        if (glyph.size[1] < minSize) {
            minSize = glyph.size[1];
        }
    });

    option.size = [option.size[0] / minSize, option.size[1] / minSize];
    option.surface /= minSize * minSize;
    option.state.forEach(function (glyph) {
        console.log(glyph);
        glyph.size[0] /= minSize;
        glyph.size[1] /= minSize;
        glyph.position[0] /= minSize;
        glyph.position[1] /= minSize;
    });

    return option;
}

var tokens = ['jan', 'utala', 'pona', 'wan', 'lili', 'wan'];
//var tokens = ['jan', 'utala', 'pona', 'mi', 'wan'];
//var tokens = ['jan', 'lili', 'pona'];
//tokens = 'kili suli pona wan mi'.split(' ');

setTimeout(function () {
    convertNounPhrase(tokens);
}, 500);

//function convertToInstructions(structuredSentence) {
//
//    var instructions = [],
//        size;
//
//    structuredSentence.forEach(function (part) {
//
//        switch (part.part) {
//            case 'subject':
//            case 'verbPhrase':
//            case 'directObject':
//                instructions.push.apply(instructions, convertNounPhrase(part));
//                break;
//            case 'punctuation':
//                instructions.push({rule: 'addPunctuation', glyph: part.token === '.' ? 'period' : '', size: 'wide'});
//                break;
//            default:
//                console.log('ERR: unknown part');
//                break;
//        }
//    });
//
//    // determine container sizes
//    for (var i = 0; i < instructions.length; i++) {
//        if (instructions[i].rule === 'openContainer') {
//            var closure = 0, regularGlyphs = 0, narrowGlyphs = 0;
//            for (var j = i; j < instructions.length; j++) {
//                switch (instructions[j].rule) {
//                    case 'openContainer':
//                        closure++;
//                        break;
//                    case 'closeContainer':
//                        closure--;
//                        if (closure === 0) {
//                            // round narrow glyphs
//                            var roundglyphs = Math.round(regularGlyphs + narrowGlyphs / 2);
//                            // add metadata to the container
//                            instructions[i].size = roundglyphs === 1 ? 'regular' :
//                                roundglyphs > 3 || (roundglyphs === 3 && narrowGlyphs === 1) ? 'double' : 'wide';
//                            instructions[i].children = roundglyphs;
//                            closure = -1;
//                        }
//                        break;
//                    case 'addGlyph':
//                        // narrow glyphs only count as half
//                        if (narrowModifiers.indexOf(instructions[j].glyph) > -1) {
//                            narrowGlyphs++;
//                        } else {
//                            regularGlyphs++;
//                        }
//                        break;
//                }
//                if (closure === -1) {
//                    break;
//                }
//            }
//        }
//    }
//    return instructions;
//}

<|endoftext|>


<commit_before>/*
 * Copyright 2009 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

RenderPipes = function() {
  var pipes = []
  return {
    add: function(pipe) {
      pipes.push(pipe)
    },

    render: function(content) {
      $.each(pipes, function() {
        content = this(content)
      })
      return content
    }
  }
}()

// html escape
RenderPipes.add(function(content) {
  return content.escapeHTML()
})

// cr
RenderPipes.add(function(content) {
  return content.replace(/\n/g, "\n
")
})

// general link
RenderPipes.add(function(content){
  return content.gsub(/(http:\/\/|https:\/\/|www)[\w\-.+:%?&#;=/^s]*/, function(match){
    return ''+ match[0].replace(/&/g, "&") +''
  })
})

// card link
RenderPipes.add(function(content) {
  var card_url = function(number) {
    var preference = new Preference()
    return preference.host() + "/projects/" + preference.project_id() + "/cards/" + number
  }

  return content.gsub(/#(\d+)/, function(match) {
    return '' + match[0] + ''
  })
})

// extract mentions
RenderPipes.add(function(content) {
  return content.gsub(/@\w+/, function(match) {
    return ''+ match[0] + ''
  })
})<commit_msg>refactoring, loading preference only once in render_pipes<commit_after>/*
 * Copyright 2009 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

RenderPipes = function() {
  var pipes = []
  var preference = new Preference()
  return {
    add: function(pipe) {
      pipes.push(pipe)
    },

    render: function(content) {
      $.each(pipes, function() {
        content = this(content, {'preference': preference})
      })
      return content
    }
  }
}()

// html escape
RenderPipes.add(function(content) {
  return content.escapeHTML()
})

// cr
RenderPipes.add(function(content) {
  return content.replace(/\n/g, "\n
")
})

// general link
RenderPipes.add(function(content){
  return content.gsub(/(http:\/\/|https:\/\/|www)[\w\-.+:%?&#;=/^s]*/, function(match){
    return ''+ match[0].replace(/&/g, "&") +''
  })
})

// card link
RenderPipes.add(function(content, context) {
  var card_url = function(number) {
    var p = context.preference
    return p.host() + "/projects/" + p.project_id() + "/cards/" + number
  }

  return content.gsub(/#(\d+)/, function(match) {
    return '' + match[0] + ''
  })
})

// extract mentions
RenderPipes.add(function(content) {
  return content.gsub(/@\w+/, function(match) {
    return ''+ match[0] + ''
  })
})<|endoftext|>


<commit_before>import ReactGA from 'react-ga';
import { setAppName, setVersion, APP_SOURCE_MANAGER } from './config';
import { setAppColors } from './styles/colors';
import routes from './routes/sourceRoutes';
import initializeApp from './index';

/**
 * This serves as the primary entry point to the Media Cloud Source Manager app.
 */

ReactGA.initialize('UA-60744513-8');

setVersion('3.4.2');

setAppName(APP_SOURCE_MANAGER);

setAppColors({
  light: '#5CB6DD',
  dark: '#3C96BD', // primary
  darker: '#1C769D',
  main: '#3C96BD',
});

initializeApp(routes);
<commit_msg>Version bump for sources release<commit_after>import ReactGA from 'react-ga';
import { setAppName, setVersion, APP_SOURCE_MANAGER } from './config';
import { setAppColors } from './styles/colors';
import routes from './routes/sourceRoutes';
import initializeApp from './index';

/**
 * This serves as the primary entry point to the Media Cloud Source Manager app.
 */

ReactGA.initialize('UA-60744513-8');

setVersion('3.4.3');

setAppName(APP_SOURCE_MANAGER);

setAppColors({
  light: '#5CB6DD',
  dark: '#3C96BD', // primary
  darker: '#1C769D',
  main: '#3C96BD',
});

initializeApp(routes);
<|endoftext|>


<commit_before>
settings.primaryColor = "#F9D4D4";
settings.primaryLight = "#F9EDED";
//settings.autocomplete = false;
settings.lemgramSelect = false;
settings.wordpicture = false;

$("#lemgram_list_item").remove();
$("#results-lemgram").remove();
$("#showLineDiagram").remove();

settings.corpora = {};
settings.corporafolders = {};

settings.corporafolders.bd1700 = {
	title : "Brev och dagböcker 1700-tal",
	contents : ["fsbbrev1700tal"],
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser."
};

settings.corporafolders.bd1800 = {
	title : "Brev och dagböcker 1800-tal",
	contents : ["fsbbrev1800tal"],
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser."
};

settings.corporafolders.sakprosa = {
	title : "Sakprosa",
	contents : ["sakprosa1750-1799", "sakprosa1800-1849", "sakprosa1850-1899", "sakprosa1900-1959"],
	description : ""
};

settings.corporafolders.tidskrifter = {
	title : "Tidskrifter",
	contents : ["filosofia1850-1899", "filosofia1900-1959", "spanskaflugan"],
	description : ""
};

settings.corpora.fsbbrev1700tal = {
	id : "fsbbrev1700tal",
	title : "Brev 1700-tal",
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser.",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_sender" : {label : "sender"},
		"text_recipient" : {label : "text_recipient"},
		"text_title" : {label : "title"},
		"text_date" : {label : "date"},
		"text_source" : {label : "source"},
		"text_archivecode" : {label : "archivecode"}
	}
};

settings.corpora.fsbbrev1800tal = {
	id : "fsbbrev1800tal",
	title : "Brev 1800-tal",
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser.",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_sender" : {label : "sender"},
		"text_recipient" : {label : "text_recipient"},
		"text_title" : {label : "title"},
		"text_date" : {label : "date"},
		"text_source" : {label : "source"},
		"text_archivecode" : {label : "archivecode"}
	}
};

settings.corpora.fsbskonlit1800tal = {
	id : "fsbskonlit1800tal",
	title : "Skönlitteratur 1800-tal",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"}
	}
};

settings.corpora["fsbskonlit1900-1959"] = {
	id : "fsbskonlit1900-1959",
	title : "Skönlitteratur 1900–1959",
	description : "Material ur skönlitterära verk publicerade under 1900–1959.",
	morf : 'saldom|dalinm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"}
	}
};

settings.corpora["filosofia1850-1899"] = {
	id : "filosofia1850-1899",
	title : "Filosofia.fi 1850–1899",
	description : "Tidskriftstexter från webbsidan filosofia.fi",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_source" : {label : "source"},
		"text_url" : {label : "url", type : "url"}
	}
};

settings.corpora["filosofia1900-1959"] = {
	id : "filosofia1900-1959",
	title : "Filosofia.fi 1900–1959",
	description : "Tidskriftstexter från webbsidan filosofia.fi",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_source" : {label : "source"},
		"text_url" : {label : "url", type : "url"}
	}
};

settings.corpora["sakprosa1750-1799"] = {
	id : "sakprosa1750-1799",
	title : "Sakprosa 1750–1799",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora["sakprosa1800-1849"] = {
	id : "sakprosa1800-1849",
	title : "Sakprosa 1800–1849",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora["sakprosa1850-1899"] = {
	id : "sakprosa1850-1899",
	title : "Sakprosa 1850–1899",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora["sakprosa1900-1959"] = {
	id : "sakprosa1900-1959",
	title : "Sakprosa 1900–1959",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora.spanskaflugan = {
	id : "spanskaflugan",
	title : "Spanska Flugan 1839–1841",
	description : "Spanska Flugan är en polemisk tidskrift, vars redaktör var J.V. Snellman.",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_title" : {label : "title"},
		"text_date" : {label : "year"}
	}
};

settings.corpusListing = new CorpusListing(settings.corpora);
<commit_msg>Nya korpusar<commit_after>
settings.primaryColor = "#F9D4D4";
settings.primaryLight = "#F9EDED";
//settings.autocomplete = false;
settings.lemgramSelect = false;
settings.wordpicture = false;

$("#lemgram_list_item").remove();
$("#results-lemgram").remove();
$("#showLineDiagram").remove();

settings.corpora = {};
settings.corporafolders = {};

settings.corporafolders.bd1700 = {
	title : "Brev och dagböcker 1700-tal",
	contents : ["fsbbrev1700tal"],
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser."
};

settings.corporafolders.bd1800 = {
	title : "Brev och dagböcker 1800-tal",
	contents : ["fsbbrev1800tal"],
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser."
};

settings.corporafolders.sakprosa = {
	title : "Sakprosa",
	contents : ["sakprosa1750-1799", "sakprosa1800-1849", "sakprosa1850-1899", "sakprosa1900-1959"],
	description : ""
};

settings.corporafolders.tidskrifter = {
	title : "Tidskrifter",
	contents : [],
	description : ""
};

settings.corporafolders.tidskrifter.tidskrifter1849 = {
	title : "Tidskrifter 1800–1849",
	contents : ["spanskaflugan"],
	description : ""
};

settings.corporafolders.tidskrifter.tidskrifter1899 = {
	title : "Tidskrifter 1850–1899",
	contents : ["filosofia1850-1899"],
	description : ""
};

settings.corporafolders.tidskrifter.tidskrifter1959 = {
	title : "Tidskrifter 1900–1959",
	contents : ["astra", "euterpe", "filosofia1900-1959"],
	description : ""
};

settings.corpora.fsbbrev1700tal = {
	id : "fsbbrev1700tal",
	title : "Brev 1700-tal",
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser.",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_sender" : {label : "sender"},
		"text_recipient" : {label : "text_recipient"},
		"text_title" : {label : "title"},
		"text_date" : {label : "date"},
		"text_source" : {label : "source"},
		"text_archivecode" : {label : "archivecode"}
	}
};

settings.corpora.fsbbrev1800tal = {
	id : "fsbbrev1800tal",
	title : "Brev 1800-tal",
	description : "Privatkorrespondens, dagböcker, resejournaler och andra icke skönlitterära texter såsom meddelanden och uppsatser.",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_sender" : {label : "sender"},
		"text_recipient" : {label : "text_recipient"},
		"text_title" : {label : "title"},
		"text_date" : {label : "date"},
		"text_source" : {label : "source"},
		"text_archivecode" : {label : "archivecode"}
	}
};

settings.corpora.fsbskonlit1800tal = {
	id : "fsbskonlit1800tal",
	title : "Skönlitteratur 1800-tal",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"}
	}
};

settings.corpora["fsbskonlit1900-1959"] = {
	id : "fsbskonlit1900-1959",
	title : "Skönlitteratur 1900–1959",
	description : "Material ur skönlitterära verk publicerade under 1900–1959.",
	morf : 'saldom|dalinm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"}
	}
};

settings.corpora["filosofia1850-1899"] = {
	id : "filosofia1850-1899",
	title : "Filosofia.fi 1850–1899",
	description : "Tidskriftstexter från webbsidan filosofia.fi",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_source" : {label : "source"},
		"text_url" : {label : "url", type : "url"}
	}
};

settings.corpora["filosofia1900-1959"] = {
	id : "filosofia1900-1959",
	title : "Filosofia.fi 1900–1959",
	description : "Tidskriftstexter från webbsidan filosofia.fi",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_source" : {label : "source"},
		"text_url" : {label : "url", type : "url"}
	}
};

settings.corpora["sakprosa1750-1799"] = {
	id : "sakprosa1750-1799",
	title : "Sakprosa 1750–1799",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora["sakprosa1800-1849"] = {
	id : "sakprosa1800-1849",
	title : "Sakprosa 1800–1849",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora["sakprosa1850-1899"] = {
	id : "sakprosa1850-1899",
	title : "Sakprosa 1850–1899",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora["sakprosa1900-1959"] = {
	id : "sakprosa1900-1959",
	title : "Sakprosa 1900–1959",
	description : "",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_author" : {label : "author"},
		"text_title" : {label : "title"},
		"text_date" : {label : "year"},
		"text_publisher" : {label : "publisher"},
		"text_url" : {label : "url", type : "url"},
		"text_pages" : {label : "page"}
	}
};

settings.corpora.spanskaflugan = {
	id : "spanskaflugan",
	title : "Spanska Flugan 1839–1841",
	description : "Spanska Flugan är en polemisk tidskrift, vars redaktör var J.V. Snellman.",
	morf : 'saldom|dalinm|swedbergm',
	within : settings.defaultWithin,
	context : settings.defaultContext,
	attributes : {
		pos : attrs.pos,
		msd : attrs.msd,
		lemma : attrs.baseform,
		lex : attrs.lemgram,
		saldo : attrs.saldo,
		prefix : attrs.prefix,
		suffix : attrs.suffix,
		dephead : attrs.dephead,
		deprel : attrs.deprel,
		ref : attrs.ref,
	},
	struct_attributes : {
		"text_title" : {label : "title"},
		"text_date" : {label : "year"}
	}
};

settings.corpora.astra = {
    id : "astra",
    title : "Astra 1929–1959",
    description : "",
    within : settings.defaultWithin,
    context : settings.defaultContext,
    attributes : modernAttrs,
    struct_attributes : {
        text_date : {label : "year"},
        text_issue : {label : "issue"}
    }
};

settings.corpora.euterpe = {
    id : "euterpe",
    title : "Euterpe 1900–1905",
    description : "Euterpe var en litterär, konstnärlig och samhällskritisk kulturtidskrift.",
    within : settings.defaultWithin,
    context : settings.defaultContext,
    attributes : modernAttrs,
    struct_attributes : {
        text_date : {label : "year"},
        text_issue : {label : "issue"}
    }
};

settings.corpusListing = new CorpusListing(settings.corpora);
<|endoftext|>


<commit_before>/*
 * sshowjs
 * mjhoy | 2011
 *
 * ermm, beta...
 *
 */

(function ( $, undefined ) {

  // Helper function. Returns the indexes `k` items away from
  // index `n` for an array of length `len`. Useful for
  // getting nearby images in the slideshow to pre-load.
  var indexNeighbors = function ( n, k, len ) {
    if ( n >= len ) return undefined;
    var arr = [],
        i, x, r, offset;
    for ( i = 0, x = k * 2; i <= x; i += 1 ) {
      offset = ( i - k ) + n;
      if ( offset < 0 ) {
        r = len + offset;
      } else if ( offset >= len ) {
        r = offset - len;
      } else {
        r = offset;
      }
      if ( ( r >= 0 ) && ( r < len ) && ( arr.indexOf( r ) < 0 ) ) {
        arr.push( r );
      }
      if ( arr.length === len ) {
        break;
      }
    }
    return arr;
  }

  // The classes we will use in constructing new elements.
  var domClass = {
    sshow        : 'sshow',
    wrapper      : 'sshow_wrapper',
    stage        : 'sshow_stage',
    source       : 'sshow_source',
    status       : 'sshow_status',
    navigation   : 'sshow_navigation',
    location     : 'sshow_location',
    nextLink     : 'sshow_nextLink',
    prevLink     : 'sshow_prevLink',
    placeholder  : 'sshow_placeholder',
    imageWrapper : 'sshow_image_wrapper'
  };

  // Same as `domClass` but with the dot in front, for CSS selectors.
  var sel = (function() {
    var obj = {};
    $.each( domClass, function ( k, v ) {
      obj[k] = '.' + v;
    } );
    return obj;
  })();

  // The default DOM set up of status and next/prev indicators.
  var statusSetup = function ( el ) {
    var status     = $( "
" ),
        navigation = $( "
" ),
        next       = $( "Next" ),
        location   = $( "" ),
        prev       = $( "Prev" );
    // status
    // `- navigation
    //    |- next
    //    |- location
    //    `- prev
    status.prepend( navigation.prepend( location ) );
    navigation.prepend( next ).append( prev );
    $( sel.wrapper, el ).prepend( status );
  };

  var handlerSetup = function ( el ) {
    var self = this;
    $( sel.nextLink, el ).click( function() { self.next(); } );
    $( sel.prevLink, el ).click( function() { self.prev(); } );
  };

  // Set the caption
  var setCaption = function ( caption, index ) {
    $( sel.caption, this.el ).html( caption );
  };

  // Set the location (e.g., "2 of 5")
  var setLocation = function ( index ) {
    var num = index + 1,
        total = this.fulls.length;
    $( sel.location, this.el ).text( num + " of " + total );
  };

  // Default options for the sshow function.
  var defaultOptions = {
    statusSetup : statusSetup,
    handlerSetup : handlerSetup,
    prefetch : 3,
    allowLoop : true,
    animationTime : 100,
    setCaption : setCaption,
    setLocation : setLocation
  };

  Sshow = function() {
    // Options are provided to the `init` method.
    this.options = {};

    // The `el` variable contains the jQuery-wrapped DOM element.
    this.el = undefined;

    // Current index displaying.
    this.currentIndex = 0;

    // Array of URLs to the full-sized (non-thumbnail) images.
    this.fulls  = [];

    // Array of URLs to thumbnail images.
    this.thumbs = [];

    // References the original elements if they are anchors to
    // full-sized images.
    this.originalElements = [];

    // Captions
    this.captions = [];
  };

  $.extend( Sshow.prototype, {

    _setupDom : function () {

      var options = this.options,
          el = this.el,
          wrapper, stage, placeholder, source;

      wrapper = $( '

' );
      stage   = $( '

' );

      el.wrapInner( '

' );
      source = $( sel.source, el );
      wrapper.prepend( stage );
      el.prepend( wrapper );

      // Call "status" setup -- meant for DOM insertion of status elements.
      if ( $.isFunction( options.statusSetup ) ) options.statusSetup.call( this, el );
      // Call "handler" setup -- meant to attach handlers to DOM events.
      if ( $.isFunction( options.handlerSetup ) ) options.handlerSetup.call( this, el );

      placeholder = $( '

' ).
        appendTo( stage );

      // Hide the original elements.
      $( source ).hide();
    },

    _setupImages : function() {

      var el = this.el,
          self = this,
          options = this.options,
          source = $( sel.source, el );

      // Finding our images
      // The first type of information we look for are links that wrap
      // images. We assume the link goes to a display (large) version
      // of the image it wraps, which maints a lot of usability with
      // no JavaScript running.
      if ( $( source ).find( 'a' ).length > 0 ) {
        $( source ).find( 'a' ).each( function() {
          var ln = $( this ), // The anchor element
              src = ln.attr( 'href' ),
              caption;

          self.originalElements.push( ln );
          self.fulls.push( src );

          if ( $.isFunction( options.getCaption ) ) {
            self.captions.push( options.getCaption.call( this, ln ) );
          }
        });
      } else {
      // Just look for all images, and use the `src` attribute as the
      // display src.
        $( source ).find( 'img' ).each( function() {
          var img = $(this),
              src = img.attr( 'src' ),
              caption;
          self.originalElements.push( img );
          self.fulls.push( src );
          if ( $.isFunction( options.getCaption ) ) {
            self.captions.push( options.getCaption.call( this, img ) );
          }

        });
      }

      // Push any `img` elements' `src` atttributes as thumbs.
      $( source ).find( 'img' ).each( function() {
        self.thumbs.push( $( this ).attr( 'src' ) );
      });

    },

    init : function ( el, opts ) {
      var self = this,
          options;

      el = $( el ).addClass( domClass.sshow ).css( { position : 'relative'} );
      this.el = el;
      options = this.options = $.extend( defaultOptions, ( opts || {} ) );

      this._setupDom();
      this._setupImages();

      self.set( 0 );

      return this;
    },

    // Setting an image
    set : function ( index ) {
      var el = this.el,
          // Are we showing the current image?
          same = ( this.currentIndex === index ),
          options = this.options,
          prefetch = options.prefetch,
          neighbors = indexNeighbors(index, prefetch, this.fulls.length ),
          href = this.fulls[index],
          placeholder = sel.placeholder,
          _currentImage, _i, _l;

      // Update currentIndex.
      this.currentIndex = index;

      if ( href ) {

        // Load the image.
        this.load( index );

        // Load neighboring images, too (prefetch for better interaction.)
        if ( neighbors ) {
          for ( _i = 0, _l = neighbors.length; _i < _l; _i+=1 ) {
            this.load( neighbors[_i] );
          }
        }

        // If it's a new image, fade out the old one.
        if ( !same ) {
          $( placeholder + ' img.active', el ).fadeOut( options.animationTime , function() {
            $( this ).css( { opacity: 0.0 } );
          });
          $( placeholder + ' img', el ).removeClass( 'active' );
        }

        // Get the new image.
        _currentImage = $( placeholder + ' img[src="' + href + '"]', el ).
          addClass( 'active' ).css( { display: 'inline' } );

        if ( same ) {
          _currentImage.css( { opacity: 1.0 } );
        } else {
          _currentImage.animate( { opacity: 1.0 }, options.animationTime );
        }

        // Update our status (caption and navigation text)
        this.updateStatus();

        // Call onImageChange.
        if ( $.isFunction( options.onImageChange ) ) options.onImageChange.call( this, _currentImage );

      }

      return this;
    },

    load : function ( index ) {
      var href = this.fulls[index],
          orig = this.originalElements[index],
          self = this,
          el   = this.el,
          options = this.options,
          placeholder = sel.placeholder,
          _newImage, _i, _l, _attr;

      // Check whether this image exists already.
      if ( $( placeholder + ' img[src="' + href + '"]', el ).length === 0 ) {
        // Create an image element for the full-sized image source.
        // Put in the "placeholder" tray and hide it.
        _newImage = $( '' ).
          appendTo( $( placeholder ) ).css( {
            position : 'absolute',
            display  : 'none',
            opacity  : 0
          } ).wrap( '

' );

        // Copy any "data-" attributes from the original link to the image.
        if ( orig ) {
          for ( _i = 0, _l = orig[0].attributes.length; _i < _l; _i+=1 ) {
            _attr = orig[0].attributes[_i];
            if ( _attr.name.indexOf( 'data-' ) === 0 ) {
              _newImage.attr( _attr.name, _attr.value );
            }
          }
        }

        // Call onImageLoad and onImageClick handler setup.
        if ( $.isFunction( options.onImageLoad ) ) options.onImageLoad.call( this, _newImage, index );
        if ( $.isFunction( options.onImageClick ) ) {
          $( _newImage ).click( function ( e ) {
            options.onImageClick.call( self, _newImage, e );
          });
        }
      }

      return this;
    },

    updateStatus : function() {
      var options = this.options,
          index = this.currentIndex,
          caption = this.captions[index],
          el = this.el,
          total = this.fulls.length;
      if ( $.isFunction( options.setLocation ) ) options.setLocation.call( this, index );
      if ( $.isFunction( options.setCaption ) ) options.setCaption.call( this, caption, index );
    },

    next : function() {
      var canChange = true,
          index = this.currentIndex,
          fulls = this.fulls,
          allowLoop = this.options.allowLoop;

      if ( index < fulls.length - 1 ) {
        index += 1;
      } else if ( allowLoop ) {
        index = 0;
      } else {
        canChange = false;
      }

      if ( canChange ) {
        this.set( index );
      }

      return this;
    },

    prev : function() {
      var canChange = true,
          index = this.currentIndex,
          fulls = this.fulls,
          allowLoop = this.options.allowLoop;

      if ( index > 0 ) {
        index -= 1;
      } else if ( allowLoop ) {
        index = fulls.length - 1;
      } else {
        canChange = false;
      }

      if ( canChange ) {
        this.set( index );
      }

      return this;
    },

  });

  // The main sshow function.
  $.fn.sshow = function ( opts ) {
    return this.each( function() {
      $( this ).data( 'sshow', new Sshow().init( this, opts ) );
    });
  };

})( jQuery );
<commit_msg>create a caption div<commit_after>/*
 * sshowjs
 * mjhoy | 2011
 *
 * ermm, beta...
 *
 */

(function ( $, undefined ) {

  // Helper function. Returns the indexes `k` items away from
  // index `n` for an array of length `len`. Useful for
  // getting nearby images in the slideshow to pre-load.
  var indexNeighbors = function ( n, k, len ) {
    if ( n >= len ) return undefined;
    var arr = [],
        i, x, r, offset;
    for ( i = 0, x = k * 2; i <= x; i += 1 ) {
      offset = ( i - k ) + n;
      if ( offset < 0 ) {
        r = len + offset;
      } else if ( offset >= len ) {
        r = offset - len;
      } else {
        r = offset;
      }
      if ( ( r >= 0 ) && ( r < len ) && ( arr.indexOf( r ) < 0 ) ) {
        arr.push( r );
      }
      if ( arr.length === len ) {
        break;
      }
    }
    return arr;
  }

  // The classes we will use in constructing new elements.
  var domClass = {
    sshow        : 'sshow',
    wrapper      : 'sshow_wrapper',
    stage        : 'sshow_stage',
    source       : 'sshow_source',
    status       : 'sshow_status',
    caption      : 'sshow_caption',
    navigation   : 'sshow_navigation',
    location     : 'sshow_location',
    nextLink     : 'sshow_nextLink',
    prevLink     : 'sshow_prevLink',
    placeholder  : 'sshow_placeholder',
    imageWrapper : 'sshow_image_wrapper'
  };

  // Same as `domClass` but with the dot in front, for CSS selectors.
  var sel = (function() {
    var obj = {};
    $.each( domClass, function ( k, v ) {
      obj[k] = '.' + v;
    } );
    return obj;
  })();

  // The default DOM set up of status and next/prev indicators.
  var statusSetup = function ( el ) {
    var status     = $( "
" ),
        navigation = $( "
" ),
        next       = $( "Next" ),
        location   = $( "" ),
        prev       = $( "Prev" ),
        caption    = $( "
" );
    // status
    // |- caption
    // `- navigation
    //    |- next
    //    |- location
    //    `- prev
    status.prepend( caption ).
      append( navigation.prepend( location ) );
    navigation.prepend( next ).append( prev );
    $( sel.wrapper, el ).prepend( status );
  };

  var handlerSetup = function ( el ) {
    var self = this;
    $( sel.nextLink, el ).click( function() { self.next(); } );
    $( sel.prevLink, el ).click( function() { self.prev(); } );
  };

  // Set the caption
  var setCaption = function ( caption, index ) {
    $( sel.caption, this.el ).html( caption );
  };

  // Set the location (e.g., "2 of 5")
  var setLocation = function ( index ) {
    var num = index + 1,
        total = this.fulls.length;
    $( sel.location, this.el ).text( num + " of " + total );
  };

  // Default options for the sshow function.
  var defaultOptions = {
    statusSetup : statusSetup,
    handlerSetup : handlerSetup,
    prefetch : 3,
    allowLoop : true,
    animationTime : 100,
    setCaption : setCaption,
    setLocation : setLocation
  };

  Sshow = function() {
    // Options are provided to the `init` method.
    this.options = {};

    // The `el` variable contains the jQuery-wrapped DOM element.
    this.el = undefined;

    // Current index displaying.
    this.currentIndex = 0;

    // Array of URLs to the full-sized (non-thumbnail) images.
    this.fulls  = [];

    // Array of URLs to thumbnail images.
    this.thumbs = [];

    // References the original elements if they are anchors to
    // full-sized images.
    this.originalElements = [];

    // Captions
    this.captions = [];
  };

  $.extend( Sshow.prototype, {

    _setupDom : function () {

      var options = this.options,
          el = this.el,
          wrapper, stage, placeholder, source;

      wrapper = $( '

' );
      stage   = $( '

' );

      el.wrapInner( '

' );
      source = $( sel.source, el );
      wrapper.prepend( stage );
      el.prepend( wrapper );

      // Call "status" setup -- meant for DOM insertion of status elements.
      if ( $.isFunction( options.statusSetup ) ) options.statusSetup.call( this, el );
      // Call "handler" setup -- meant to attach handlers to DOM events.
      if ( $.isFunction( options.handlerSetup ) ) options.handlerSetup.call( this, el );

      placeholder = $( '

' ).
        appendTo( stage );

      // Hide the original elements.
      $( source ).hide();
    },

    _setupImages : function() {

      var el = this.el,
          self = this,
          options = this.options,
          source = $( sel.source, el );

      // Finding our images
      // The first type of information we look for are links that wrap
      // images. We assume the link goes to a display (large) version
      // of the image it wraps, which maints a lot of usability with
      // no JavaScript running.
      if ( $( source ).find( 'a' ).length > 0 ) {
        $( source ).find( 'a' ).each( function() {
          var ln = $( this ), // The anchor element
              src = ln.attr( 'href' ),
              caption;

          self.originalElements.push( ln );
          self.fulls.push( src );

          if ( $.isFunction( options.getCaption ) ) {
            self.captions.push( options.getCaption.call( this, ln ) );
          }
        });
      } else {
      // Just look for all images, and use the `src` attribute as the
      // display src.
        $( source ).find( 'img' ).each( function() {
          var img = $(this),
              src = img.attr( 'src' ),
              caption;
          self.originalElements.push( img );
          self.fulls.push( src );
          if ( $.isFunction( options.getCaption ) ) {
            self.captions.push( options.getCaption.call( this, img ) );
          }

        });
      }

      // Push any `img` elements' `src` atttributes as thumbs.
      $( source ).find( 'img' ).each( function() {
        self.thumbs.push( $( this ).attr( 'src' ) );
      });

    },

    init : function ( el, opts ) {
      var self = this,
          options;

      el = $( el ).addClass( domClass.sshow ).css( { position : 'relative'} );
      this.el = el;
      options = this.options = $.extend( defaultOptions, ( opts || {} ) );

      this._setupDom();
      this._setupImages();

      self.set( 0 );

      return this;
    },

    // Setting an image
    set : function ( index ) {
      var el = this.el,
          // Are we showing the current image?
          same = ( this.currentIndex === index ),
          options = this.options,
          prefetch = options.prefetch,
          neighbors = indexNeighbors(index, prefetch, this.fulls.length ),
          href = this.fulls[index],
          placeholder = sel.placeholder,
          _currentImage, _i, _l;

      // Update currentIndex.
      this.currentIndex = index;

      if ( href ) {

        // Load the image.
        this.load( index );

        // Load neighboring images, too (prefetch for better interaction.)
        if ( neighbors ) {
          for ( _i = 0, _l = neighbors.length; _i < _l; _i+=1 ) {
            this.load( neighbors[_i] );
          }
        }

        // If it's a new image, fade out the old one.
        if ( !same ) {
          $( placeholder + ' img.active', el ).fadeOut( options.animationTime , function() {
            $( this ).css( { opacity: 0.0 } );
          });
          $( placeholder + ' img', el ).removeClass( 'active' );
        }

        // Get the new image.
        _currentImage = $( placeholder + ' img[src="' + href + '"]', el ).
          addClass( 'active' ).css( { display: 'inline' } );

        if ( same ) {
          _currentImage.css( { opacity: 1.0 } );
        } else {
          _currentImage.animate( { opacity: 1.0 }, options.animationTime );
        }

        // Update our status (caption and navigation text)
        this.updateStatus();

        // Call onImageChange.
        if ( $.isFunction( options.onImageChange ) ) options.onImageChange.call( this, _currentImage );

      }

      return this;
    },

    load : function ( index ) {
      var href = this.fulls[index],
          orig = this.originalElements[index],
          self = this,
          el   = this.el,
          options = this.options,
          placeholder = sel.placeholder,
          _newImage, _i, _l, _attr;

      // Check whether this image exists already.
      if ( $( placeholder + ' img[src="' + href + '"]', el ).length === 0 ) {
        // Create an image element for the full-sized image source.
        // Put in the "placeholder" tray and hide it.
        _newImage = $( '' ).
          appendTo( $( placeholder ) ).css( {
            position : 'absolute',
            display  : 'none',
            opacity  : 0
          } ).wrap( '

' );

        // Copy any "data-" attributes from the original link to the image.
        if ( orig ) {
          for ( _i = 0, _l = orig[0].attributes.length; _i < _l; _i+=1 ) {
            _attr = orig[0].attributes[_i];
            if ( _attr.name.indexOf( 'data-' ) === 0 ) {
              _newImage.attr( _attr.name, _attr.value );
            }
          }
        }

        // Call onImageLoad and onImageClick handler setup.
        if ( $.isFunction( options.onImageLoad ) ) options.onImageLoad.call( this, _newImage, index );
        if ( $.isFunction( options.onImageClick ) ) {
          $( _newImage ).click( function ( e ) {
            options.onImageClick.call( self, _newImage, e );
          });
        }
      }

      return this;
    },

    updateStatus : function() {
      var options = this.options,
          index = this.currentIndex,
          caption = this.captions[index],
          el = this.el,
          total = this.fulls.length;
      if ( $.isFunction( options.setLocation ) ) options.setLocation.call( this, index );
      if ( $.isFunction( options.setCaption ) ) options.setCaption.call( this, caption, index );
    },

    next : function() {
      var canChange = true,
          index = this.currentIndex,
          fulls = this.fulls,
          allowLoop = this.options.allowLoop;

      if ( index < fulls.length - 1 ) {
        index += 1;
      } else if ( allowLoop ) {
        index = 0;
      } else {
        canChange = false;
      }

      if ( canChange ) {
        this.set( index );
      }

      return this;
    },

    prev : function() {
      var canChange = true,
          index = this.currentIndex,
          fulls = this.fulls,
          allowLoop = this.options.allowLoop;

      if ( index > 0 ) {
        index -= 1;
      } else if ( allowLoop ) {
        index = fulls.length - 1;
      } else {
        canChange = false;
      }

      if ( canChange ) {
        this.set( index );
      }

      return this;
    },

  });

  // The main sshow function.
  $.fn.sshow = function ( opts ) {
    return this.each( function() {
      $( this ).data( 'sshow', new Sshow().init( this, opts ) );
    });
  };

})( jQuery );
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

var express = require('express');
var http = require('http');
var makeApp = require('./make_app');
var open = require('open');
var util = require('util');
var findPort = require('find-port');

function startWithPort(options) {

  options.port = options.port || 8080;

  console.log('Starting Polyserve on port ' + options.port);

  var app = express();
  var polyserve = makeApp(options.componentDir, options.packageName);

  app.use('/components/', polyserve);

  var server = http.createServer(app);

  server = app.listen(options.port);

  server.on('error', function(err) {
    if (err.code === 'EADDRINUSE')
      console.error("ERROR: Port in use", options.port, "\nPlease choose another port, or let an unused port be chosen automatically.");
    process.exit(69);
  });

  var baseUrl = util.format('http://localhost:%d/components/%s/', options.port,
    polyserve.packageName);
  console.log('Files in this directory are available under ' + baseUrl);

  if (options.page) {
    var url = baseUrl + (options.page === true ? 'index.html' : options.page);
    if (Array.isArray(options.browser)) {
      for (var i=0; i<options.browser.length; i++)
        open(url, options.browser[i]);
    }
    else {
      open(url, options.browser);
    }
  }
}

function startServer(options) {
  if (!options.port) {
    findPort(8080, 8180, function(ports) {
      options.port = ports[0];
      startWithPort(options);
    });
  }
  else {
    startWithPort(options);
  }
}

module.exports = startServer;
<commit_msg>code review fixes<commit_after>/**
 * @license
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */

var express = require('express');
var http = require('http');
var makeApp = require('./make_app');
var open = require('open');
var util = require('util');
var findPort = require('find-port');

function startServer(options) {
  if (!options.port) {
    findPort(8080, 8180, function(ports) {
      options.port = ports[0];
      startWithPort(options);
    });
  }
  else {
    startWithPort(options);
  }
}

/**
 * @param {Object} options
 * @param {Number} options.port -- port number
 * @param {String=} options.page -- page path, ex: "/", "/index.html"
 * @param {(String|String[])} options.browser -- names of browser apps to launch
 */
function startWithPort(options) {

  options.port = options.port || 8080;

  console.log('Starting Polyserve on port ' + options.port);

  var app = express();
  var polyserve = makeApp(options.componentDir, options.packageName);

  app.use('/components/', polyserve);

  var server = http.createServer(app);

  server = app.listen(options.port);

  server.on('error', function(err) {
    if (err.code === 'EADDRINUSE')
      console.error("ERROR: Port in use", options.port,
        "\nPlease choose another port, or let an unused port be chosen automatically.");
    process.exit(69);
  });

  var baseUrl = util.format('http://localhost:%d/components/%s/', options.port,
    polyserve.packageName);
  console.log('Files in this directory are available under ' + baseUrl);

  if (options.page) {
    var url = baseUrl + (options.page === true ? 'index.html' : options.page);
    if (Array.isArray(options.browser)) {
      for (var i = 0; i < options.browser.length; i++)
        open(url, options.browser[i]);
    }
    else {
      open(url, options.browser);
    }
  }
}

module.exports = startServer;
<|endoftext|>