<commit_before>
var splay_tree_t = function ( diff ) {

	var zig, zag, zigzig, zigzag, zagzig, zagzag, z, zz;
	var insert, splay, remove, in_order_traversal, splay_tree;

	zig = function ( x, y ) { y[0] = x[1]; x[1] = y; };
	zag = function ( x, y ) { y[1] = x[0]; x[0] = y; };

	zigzig = function ( x, p, g ) { zig(p, g); zig(x, p); };
	zigzag = function ( x, p, g ) { zig(x, g); zag(x, p); };
	zagzig = function ( x, p, g ) { zag(x, g); zig(x, p); };
	zagzag = function ( x, p, g ) { zag(p, g); zag(x, p); };

	z  = [zig, zag];
	zz = [ [zigzig, zigzag], [zagzig, zagzag] ];

	insert = function ( pt, v ) {

		var w;

		w = diff( v, pt[2] ) > 0 | 0;

		if ( pt[w] === null ) {
			pt[w] = [null, null, v];
		}

		else {
			insert(pt[w], v);
		}

	};

	splay = function ( el, v ) {

		var turn, path, pt, f, d, w, i;

		turn = [];
		path = [];
		pt = el;
		f = undefined;

		while ( f === undefined ) {

			if ( pt === null ) {
				f = false;
				pt = path[path.length - 1];
				--turn.length;
			}
			else {

				d = diff( v, pt[2] );

				if ( d === 0 ) {
					f = true;
				}

				else {
					w = d > 0 | 0;
					path.push( pt );
					turn.push( w );
					pt = pt[w];
				}
			}

		}

		i = turn.length - 1;

		for ( ; i > 0 ; i -= 2 ) {
			zz[turn[i-1]][turn[i]](pt, path[i], path[i-1]);
		}

		if ( i === 0 ) {
			z[turn[0]](pt, el);
		}

		return [f, pt];
	};

	remove = function ( el, v ) {
		var r;

		r = splay( el, v );

		if ( !r[0] ) {
			return r[1];
		}

		if ( r[1][0] === null ) {
			return r[1][1];
		}

		else if ( r[1][1] === null ) {
			return r[1][0];
		}

		else {
			r[1][0] = splay( r[1][0], v )[1];
			r[1][0][1] = r[1][1];
			return r[1][0];
		}

	};

	in_order_traversal = function ( pt, callback ) {

		if ( pt[0] !== null ) {
			in_order_traversal( pt[0], callback );
		}

		callback( pt[2] );

		if ( pt[1] !== null ) {
			in_order_traversal( pt[1], callback );
		}

	};

	splay_tree = function () {
		this.pt = null;
	};

	splay_tree.prototype.insert = function ( v ) {

		if ( this.pt === null ) {
			this.pt = [null, null, v];
		}

		else {
			insert( this.pt, v );
		}

	};

	splay_tree.prototype.find = function ( v ) {

		var r;

		if ( this.pt === null ) {
			return [false, null];
		}

		r = splay( this.pt, v );
		this.pt = r[1];

		return [r[0], r[1][2]];
	};

	splay_tree.prototype.remove = function ( v ) {
		if ( this.pt !== null ) {
			this.pt = remove( this.pt, v );
		}
	};

	splay_tree.prototype.in_order_traversal = function ( fn ) {
		if ( this.pt !== null ) {
			in_order_traversal( this.pt, fn );
		}
	};

	return splay_tree;

};

exports.splay_tree_t = splay_tree_t;
<commit_msg>style<commit_after>
var splay_tree_t = function ( diff ) {

	var zig, zag, zigzig, zigzag, zagzig, zagzag, z, zz;
	var insert, splay, remove, in_order_traversal, splay_tree;

	zig = function ( x, y ) { y[0] = x[1]; x[1] = y; };
	zag = function ( x, y ) { y[1] = x[0]; x[0] = y; };

	zigzig = function ( x, p, g ) { zig( p, g ); zig( x, p ); };
	zigzag = function ( x, p, g ) { zig( x, g ); zag( x, p ); };
	zagzig = function ( x, p, g ) { zag( x, g ); zig( x, p ); };
	zagzag = function ( x, p, g ) { zag( p, g ); zag( x, p ); };

	z  = [zig, zag];
	zz = [ [zigzig, zigzag], [zagzig, zagzag] ];

	insert = function ( pt, v ) {

		var w;

		w = diff( v, pt[2] ) > 0 | 0;

		if ( pt[w] === null ) {
			pt[w] = [null, null, v];
		}

		else {
			insert(pt[w], v);
		}

	};

	splay = function ( el, v ) {

		var turn, path, pt, f, d, w, i;

		turn = [];
		path = [];
		pt = el;
		f = undefined;

		while ( f === undefined ) {

			if ( pt === null ) {
				f = false;
				pt = path[path.length - 1];
				--turn.length;
			}
			else {

				d = diff( v, pt[2] );

				if ( d === 0 ) {
					f = true;
				}

				else {
					w = d > 0 | 0;
					path.push( pt );
					turn.push( w );
					pt = pt[w];
				}
			}

		}

		i = turn.length - 1;

		for ( ; i > 0 ; i -= 2 ) {
			zz[turn[i-1]][turn[i]](pt, path[i], path[i-1]);
		}

		if ( i === 0 ) {
			z[turn[0]](pt, el);
		}

		return [f, pt];
	};

	remove = function ( el, v ) {
		var r;

		r = splay( el, v );

		if ( !r[0] ) {
			return r[1];
		}

		if ( r[1][0] === null ) {
			return r[1][1];
		}

		else if ( r[1][1] === null ) {
			return r[1][0];
		}

		else {
			r[1][0] = splay( r[1][0], v )[1];
			r[1][0][1] = r[1][1];
			return r[1][0];
		}

	};

	in_order_traversal = function ( pt, callback ) {

		if ( pt[0] !== null ) {
			in_order_traversal( pt[0], callback );
		}

		callback( pt[2] );

		if ( pt[1] !== null ) {
			in_order_traversal( pt[1], callback );
		}

	};

	splay_tree = function () {
		this.pt = null;
	};

	splay_tree.prototype.insert = function ( v ) {

		if ( this.pt === null ) {
			this.pt = [null, null, v];
		}

		else {
			insert( this.pt, v );
		}

	};

	splay_tree.prototype.find = function ( v ) {

		var r;

		if ( this.pt === null ) {
			return [false, null];
		}

		r = splay( this.pt, v );
		this.pt = r[1];

		return [r[0], r[1][2]];
	};

	splay_tree.prototype.remove = function ( v ) {
		if ( this.pt !== null ) {
			this.pt = remove( this.pt, v );
		}
	};

	splay_tree.prototype.in_order_traversal = function ( fn ) {
		if ( this.pt !== null ) {
			in_order_traversal( this.pt, fn );
		}
	};

	return splay_tree;

};

exports.splay_tree_t = splay_tree_t;
<|endoftext|>


<commit_before>/**
 * EditorUpload.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/**
 * Handles image uploads, updates undo stack and patches over various internal functions.
 *
 * @private
 * @class tinymce.EditorUpload
 */
define("tinymce/EditorUpload", [
	"tinymce/util/Tools",
	"tinymce/file/Uploader",
	"tinymce/file/ImageScanner",
	"tinymce/file/BlobCache"
], function(Tools, Uploader, ImageScanner, BlobCache) {
	return function(editor) {
		var blobCache = new BlobCache();

		function regExpEscape(str) {
			return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
		}

		function replaceAttribValue(content, name, targetValue, newValue) {
			return content.replace(
				new RegExp(name + '="' + regExpEscape(targetValue) + '"', 'g'),
				function() {
					return name + '="' + newValue + '"';
				}
			);
		}

		function replaceImageUrl(content, targetUrl, replacementUrl) {
			content = replaceAttribValue(content, "src", targetUrl, replacementUrl);
			content = replaceAttribValue(content, "data-mce-src", targetUrl, replacementUrl);

			return content;
		}

		function replaceUrlInUndoStack(targetUrl, replacementUrl) {
			Tools.each(editor.undoManager.data, function(level) {
				level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
			});
		}

		function uploadImages(callback) {
			var uploader = new Uploader({
				url: editor.settings.images_upload_url,
				basePath: editor.settings.images_upload_base_path,
				credentials: editor.settings.images_upload_credentials,
				handler: editor.settings.images_upload_handler
			});

			function imageInfosToBlobInfos(imageInfos) {
				return Tools.map(imageInfos, function(imageInfo) {
					return imageInfo.blobInfo;
				});
			}

			return scanForImages().then(imageInfosToBlobInfos).then(uploader.upload).then(function(result) {
				result = Tools.map(result, function(uploadInfo) {
					var image;

					image = editor.dom.select('img[src="' + uploadInfo.blobInfo.blobUri() + '"]')[0];

					if (image) {
						replaceUrlInUndoStack(image.src, uploadInfo.url);
						image.src = uploadInfo.url;
					}

					return {
						element: image,
						status: uploadInfo.status
					};
				});

				if (callback) {
					callback(result);
				}

				return result;
			});
		}

		function scanForImages() {
			return ImageScanner.findAll(editor.getBody(), blobCache).then(function(result) {
				Tools.each(result, function(resultItem) {
					replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
					resultItem.image.src = resultItem.blobInfo.blobUri();
				});

				return result;
			});
		}

		function destroy() {
			blobCache.destroy();
		}

		editor.on('setContent paste', scanForImages);

		editor.on('getContent', function(e) {
			if (e.source_view || e.format == 'raw') {
				return;
			}

			e.content = e.content.replace(/src="(blob:[^"]+)"/g, function(match, blobUri) {
				var blobInfo = blobCache.getByUri(blobUri);

				return 'src="data:' + blobInfo.blob().type + ';base64,' + blobInfo.base64() + '"';
			});
		});

		return {
			blobCache: blobCache,
			uploadImages: uploadImages,
			scanForImages: scanForImages,
			destroy: destroy
		};
	};
});<commit_msg>Fixed issue with data-mce-src not being properly updated.<commit_after>/**
 * EditorUpload.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/**
 * Handles image uploads, updates undo stack and patches over various internal functions.
 *
 * @private
 * @class tinymce.EditorUpload
 */
define("tinymce/EditorUpload", [
	"tinymce/util/Tools",
	"tinymce/file/Uploader",
	"tinymce/file/ImageScanner",
	"tinymce/file/BlobCache"
], function(Tools, Uploader, ImageScanner, BlobCache) {
	return function(editor) {
		var blobCache = new BlobCache();

		function regExpEscape(str) {
			return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
		}

		function replaceAttribValue(content, name, targetValue, newValue) {
			return content.replace(
				new RegExp(name + '="' + regExpEscape(targetValue) + '"', 'g'),
				function() {
					return name + '="' + newValue + '"';
				}
			);
		}

		function replaceImageUrl(content, targetUrl, replacementUrl) {
			content = replaceAttribValue(content, "src", targetUrl, replacementUrl);
			content = replaceAttribValue(content, "data-mce-src", targetUrl, replacementUrl);

			return content;
		}

		function replaceUrlInUndoStack(targetUrl, replacementUrl) {
			Tools.each(editor.undoManager.data, function(level) {
				level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
			});
		}

		function uploadImages(callback) {
			var uploader = new Uploader({
				url: editor.settings.images_upload_url,
				basePath: editor.settings.images_upload_base_path,
				credentials: editor.settings.images_upload_credentials,
				handler: editor.settings.images_upload_handler
			});

			function imageInfosToBlobInfos(imageInfos) {
				return Tools.map(imageInfos, function(imageInfo) {
					return imageInfo.blobInfo;
				});
			}

			return scanForImages().then(imageInfosToBlobInfos).then(uploader.upload).then(function(result) {
				result = Tools.map(result, function(uploadInfo) {
					var image;

					image = editor.dom.select('img[src="' + uploadInfo.blobInfo.blobUri() + '"]')[0];

					if (image) {
						replaceUrlInUndoStack(image.src, uploadInfo.url);

						editor.$(image).attr({
							src: uploadInfo.url,
							'data-mce-src': editor.convertURL(uploadInfo.url, 'src')
						});
					}

					return {
						element: image,
						status: uploadInfo.status
					};
				});

				if (callback) {
					callback(result);
				}

				return result;
			}, function() {
				// Silent
				// TODO: Maybe execute some failure callback here?
			});
		}

		function scanForImages() {
			return ImageScanner.findAll(editor.getBody(), blobCache).then(function(result) {
				Tools.each(result, function(resultItem) {
					replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
					resultItem.image.src = resultItem.blobInfo.blobUri();
				});

				return result;
			});
		}

		function destroy() {
			blobCache.destroy();
		}

		editor.on('setContent paste', scanForImages);

		editor.on('getContent', function(e) {
			if (e.source_view || e.format == 'raw') {
				return;
			}

			e.content = e.content.replace(/src="(blob:[^"]+)"/g, function(match, blobUri) {
				var blobInfo = blobCache.getByUri(blobUri);

				return 'src="data:' + blobInfo.blob().type + ';base64,' + blobInfo.base64() + '"';
			});
		});

		return {
			blobCache: blobCache,
			uploadImages: uploadImages,
			scanForImages: scanForImages,
			destroy: destroy
		};
	};
});<|endoftext|>


<commit_before>'use strict';
const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const install = require('gulp-install');
const zip = require('gulp-zip');
const strip = require('gulp-strip-comments');
const removeEmptyLines = require('gulp-remove-empty-lines');
const del = require('del');
const deptree = require('dependency-tree');
const pkg = require('./package.json');

const regex = new RegExp('node_modules/(.*?)/');

function clean(tree, module) {
	const result = {};

	Object.keys(tree).forEach(key => {
		if (key.indexOf(`node_modules/${module}`) === -1) {
			result[key] = clean(tree[key], module);
		}
	});

	return result;
}

function deps(tree, result) {
	result = result || {};

	Object.keys(tree).forEach(key => {
		const match = regex.exec(key);

		if (match) {
			result[match[1]] = (result[match[1]] || 0) + 1;
		}

		deps(tree[key], result);
	});

	return result;
}

const tree = deptree({filename: pkg.main, root: __dirname});
const cleaned = deps(clean(tree, 'aws-sdk'));
const cleanUpArray = Object.keys(deps(tree)).filter(key => cleaned[key] === undefined);

gulp.task('clean', ['zip'], () => del('.temp'));

gulp.task('cleanDeps', ['copyAndInstall'], () => {
	return del(cleanUpArray.map(x => `.temp/node_modules/{${x},${x}/**}`));
});

gulp.task('copyAndInstall', () => {
	let files = ['package.json'].concat(pkg.files);

	if (pkg.files === undefined) {
		files = ['./**', '!./**/*.md', '!gulpfile.js', '!./{dist,dist/**}', '!./{test,test/**}', '!./{node_modules,node_modules/**}'];
	} else {
		files = files.map(file => {
			try {
				if (fs.statSync(path.join(__dirname, file)).isDirectory()) {
					return path.join(file, '**/*');
				}
			} catch (err) {
				// do nothing
			}

			return file;
		});
	}

	return gulp.src(files, {base: '.'})
		.pipe(strip())
		.pipe(removeEmptyLines())
		.pipe(gulp.dest('.temp'))
		.pipe(install({production: true}));
});

gulp.task('zip', ['copyAndInstall', 'cleanDeps'], () => {
	return gulp.src('.temp/**')
		.pipe(zip('build.zip'))
		.pipe(gulp.dest('dist'));
});

gulp.task('build', ['copyAndInstall', 'cleanDeps', 'zip', 'clean']);
gulp.task('default', ['build']);
<commit_msg>fix gulpfile<commit_after>'use strict';
const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const install = require('gulp-install');
const zip = require('gulp-zip');
const strip = require('gulp-strip-comments');
const removeEmptyLines = require('gulp-remove-empty-lines');
const del = require('del');
const deptree = require('dependency-tree');
const pkg = require('./package.json');

const regex = new RegExp('node_modules/(.*?)/', 'g');

function clean(tree, module) {
	const result = {};

	Object.keys(tree).forEach(key => {
		if (key.indexOf(`node_modules/${module}`) === -1) {
			result[key] = clean(tree[key], module);
		}
	});

	return result;
}

function deps(tree, result) {
	result = result || {};

	Object.keys(tree).forEach(key => {
		let match = regex.exec(key);

		while (match) {
			result[match[1]] = (result[match[1]] || 0) + 1;

			match = regex.exec(key);
		}

		deps(tree[key], result);
	});

	return result;
}

const tree = deptree({filename: pkg.main, root: __dirname});
const cleaned = deps(clean(tree, 'aws-sdk'));
const cleanUpArray = Object.keys(deps(tree)).filter(key => cleaned[key] === undefined);

gulp.task('clean', ['zip'], () => del('.temp'));

gulp.task('cleanDeps', ['copyAndInstall'], () => {
	return del(cleanUpArray.map(x => `.temp/node_modules/{${x},${x}/**}`));
});

gulp.task('copyAndInstall', () => {
	let files = ['package.json'].concat(pkg.files);

	if (pkg.files === undefined) {
		files = ['./**', '!./**/*.md', '!gulpfile.js', '!./{dist,dist/**}', '!./{test,test/**}', '!./{node_modules,node_modules/**}'];
	} else {
		files = files.map(file => {
			try {
				if (fs.statSync(path.join(__dirname, file)).isDirectory()) {
					return path.join(file, '**/*');
				}
			} catch (err) {
				// do nothing
			}

			return file;
		});
	}

	return gulp.src(files, {base: '.'})
		.pipe(strip())
		.pipe(removeEmptyLines())
		.pipe(gulp.dest('.temp'))
		.pipe(install({production: true}));
});

gulp.task('zip', ['copyAndInstall', 'cleanDeps'], () => {
	return gulp.src('.temp/**')
		.pipe(zip('build.zip'))
		.pipe(gulp.dest('dist'));
});

gulp.task('build', ['copyAndInstall', 'cleanDeps', 'zip', 'clean']);
gulp.task('default', ['build']);
<|endoftext|>


<commit_before>process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

var fs = require('fs');
var winston = require('winston');
var moment = require('moment');
var Client = require('node-rest-client').Client;
var client = new Client();

var routerlist = null;
var routers = null;

var path = './cache_routerlist.json';

var metacommunity = {
	"id" : "franken",
	"data" : {
		"name" : "Freifunk Franken",
		"url" : "http://freifunk-franken.de",
		"state" : {
			"message" : "Jeder darf mitmachen!"
		},
		"location" : {
			"city" : "Nürnberg",
			"lat" : 49.448856931202,
			"lon" : 11.082108258271
		},
		"contact" : {
			"email" : "fragen@freifunk-franken.de",
			"facebook" : "https://www.facebook.com/FreifunkFranken",
			"ml" : "http://lists.freifunk.net/mailman/listinfo/franken-freifunk.net",
			"phone" : "+49 9101 7018607",
			"twitter" : "FreifunkFranken"
		},
		"techDetails" : {
			"stoererhaftung" : "VPN nach Rumänien und zum Freie Netze e.V.",
			"bootstrap" : "http://freifunk-franken.de/checkliste_routerinstallation",
			"firmware" : {
				"url" : "https://dev.freifunk-franken.de/firmware/",
				"name" : "Freifunk-Franken Firmware"
			},
			"routing" : "BATMAN",
			"topodata" : "https://netmon.freifunk-franken.de/batman.png",
			"updatemode" : "manual over ssh",
			"vpn" : "fastd"
		},
		"api" : "0.1"
	}
};

var communities = [ {
	"id" : "fuerth",
	"radius" : 4, // community radius in km
	"data" : {
		"name" : "Freifunk Fürth",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Fürth",
			"lat" : 49.47833,
			"lon" : 10.99027
		}
	}
}, {
	"id" : "unfinden",
	"radius" : 10, // community radius in km
	"data" : {
		"name" : "Freifunk Unfinden",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Unfinden",
			"lat" : 50.093555895082,
			"lon" : 10.568013390003
		}
	}
} ];

function extend(destination, source) {
	for ( var property in source) {
		if (!destination[property]) {
			destination[property] = source[property];
		}
	}
	return destination;
}

function saveCommunityData(data, output_filename) {
	fs.writeFile(output_filename, JSON.stringify(data, null, 4), function(err) {
		if (err) {
			winston.error(err);
		} else {
			winston.info("Updated " + output_filename);
		}
	});
}

function updateCommunity(community, count) {
	var output_filename = "freifunk" + community.id + ".json";
	if (!community.data.state) {
		community.data.state = {};
	}
	community.data.state.nodes = count;
	community.data.state.lastchange = Math.round((new Date()).getTime() / 1000);

	winston.info("==============================================================");
	winston.info("Online nodes in community '" + community.data.name + "': " + count + "\n");
	saveCommunityData(community.data, output_filename);
}

function getDistance(p1, p2) {
	function toRad(n) {
		return n * (Math.PI / 180);
	}
	var dLat = toRad(p2.lat - p1.lat);
	var dLon = toRad(p2.lon - p1.lon);
	var lat1 = toRad(p1.lat);
	var lat2 = toRad(p2.lat);
	var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(p1.lat) * Math.cos(p2.lat);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
	var R = 6371; // km
	var d = R * c;
	return d;
}

function updateCommunities() {
	var count = 0;
	for (var n = 0; n < routers.length; n = n + 1) {
		if (routers[n].statusdata[0].status[0] !== "online") {
			continue;
		}
		count = count + 1;
	}
	// write meta-community file
	updateCommunity(metacommunity, count);

	// write community files
	var length = communities.length;
	var community = {};
	for (var i = 0; i < length; i = i + 1) {
		count = 0;
		winston.info("Routers in " + communities[i].data.name + " (radius: " + communities[i].radius + " km): ");
		winston.info("-------------------------------------------------------------");
		for (var j = 0; j < routers.length; j = j + 1) {
//			if (routers[j].statusdata[0].status !== "online") {
//				continue;
//			}

			var distance = getDistance({
				"lat" : parseFloat(routers[j].latitude),
				"lon" : parseFloat(routers[j].longitude)
			}, communities[i].data.location).toFixed(2);

			if (distance < communities[i].radius) {
				winston.info("Node " + routers[j].hostname[0] + ", distance: " + distance + " km");
				count = count + 1;
			}
		}

		community.id = communities[i].id;
		community.data = extend(communities[i].data, metacommunity.data);
		updateCommunity(community, count);
	}
}

function processCommunityData(data) {
	routerlist = data.netmon_response.routerlist;
	routers = data.netmon_response.routerlist[0].router;
	updateCommunities();
}

fs.stat(path, function(err, stats) {
	var minutesDiff = 9999999;
	if (!err) {
		var mtime = stats.mtime;
		var fileDate = moment(mtime);
		var now = moment();
		minutesDiff = now.diff(fileDate, 'minutes');
		winston.info("Age of local routerlist: " + minutesDiff + " minutes\n");
	}

	if (minutesDiff > 60) {
		winston.info("Loading routerlist from netmon...");
		client.get("https://netmon.freifunk-franken.de/api/rest/routerlist/?limit=500",
			function(data, response) {
				winston.info("saving data to file " + path + "\n");
				fs.writeFile(path, JSON.stringify(data, null, 4), function(err) {
					if (err) {
						winston.error(err);
					}
				});
				processCommunityData(data);
			}
		);
	} else  {
		winston.info("Loading local routerlist...");
		fs.readFile(path, 'utf8', function read(err, data) {
			if (err) {
				throw err;
			}
			processCommunityData(JSON.parse(data));
		});
	}
});

<commit_msg>working prototype<commit_after>process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

var fs = require('fs');
var winston = require('winston');
var moment = require('moment');
var Client = require('node-rest-client').Client;
var client = new Client();

var routerlist = null;
var routers = null;

var options = {
	netmonUrl: "https://netmon.freifunk-franken.de/api/rest/routerlist/?limit=500",
	outputDir: '../freifunkfranken-community/',
	outputPrefix: '',
	cacheRouterlistFile: './cache.routerlist.json',
	cacheMaxAge: 60,
};

var metacommunity = {
	"id" : "franken",
	"data" : {
		"name" : "Freifunk Franken",
		"url" : "http://freifunk-franken.de",
		"state" : {
			"message" : "Jeder darf mitmachen!"
		},
		"location" : {
			"city" : "Nürnberg",
			"lat" : 49.448856931202,
			"lon" : 11.082108258271
		},
		"contact" : {
			"email" : "fragen@freifunk-franken.de",
			"facebook" : "https://www.facebook.com/FreifunkFranken",
			"ml" : "http://lists.freifunk.net/mailman/listinfo/franken-freifunk.net",
			"phone" : "+49 9101 7018607",
			"twitter" : "FreifunkFranken"
		},
		"techDetails" : {
			"stoererhaftung" : "VPN nach Rumänien und zum Freie Netze e.V.",
			"bootstrap" : "http://freifunk-franken.de/checkliste_routerinstallation",
			"firmware" : {
				"url" : "https://dev.freifunk-franken.de/firmware/",
				"name" : "Freifunk-Franken Firmware"
			},
			"routing" : "BATMAN",
			"topodata" : "https://netmon.freifunk-franken.de/batman.png",
			"updatemode" : "manual over ssh",
			"vpn" : "fastd"
		},
		"api" : "0.1"
	}
};

var communities = [ {
	"id" : "nuernberg",
	"radius" : 10,
	"data" : {
		"name" : "Freifunk Nürnberg",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Nürnberg",
			"lat" : 49.448856931202,
			"lon" : 11.082108258271
		}
	}
}, {
	"id" : "fuerth",
	"radius" : 4,
	"data" : {
		"name" : "Freifunk Fürth",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Fürth",
			"lat" : 49.47833,
			"lon" : 10.99027
		}
	}
}, {
	"id" : "unfinden",
	"radius" : 10,
	"data" : {
		"name" : "Freifunk Unfinden",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Unfinden",
			"lat" : 50.093555895082,
			"lon" : 10.568013390003
		}
	}
}, {
	"id" : "erlangen",
	"radius" : 10,
	"data" : {
		"name" : "Freifunk Erlangen",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Erlangen",
			"lat" : 49.6005981,
			"lon" : 11.0019221
		}
	}
}, {
	"id" : "wuerzburg",
	"radius" : 20,
	"data" : {
		"name" : "Freifunk Würzburg",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Würzburg",
			"lat" : 49.79688,
			"lon" : 9.93489
		}
	}
}, {
	"id" : "ansbach",
	"radius" : 10,
	"data" : {
		"name" : "Freifunk Ansbach",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Ansbach",
			"lat" : 49.300833,
			"lon" : 10.571667
		}
	}
}, {
	"id" : "haag",
	"radius" : 10,
	"data" : {
		"name" : "Freifunk Haag/Neuendettelsau",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Haag",
			"lat" : 49.295278,
			"lon" : 10.816111
		}
	}
}, {
	"id" : "regensburg",
	"radius" : 20,
	"data" : {
		"name" : "Freifunk Regensburg",
		"metacommunity" : "Freifunk Franken",
		"location" : {
			"city" : "Regensburg",
			"lat" : 49.031974,
			"lon" : 12.116186
		}
	}
} ];

function extend(destination, source) {
	for ( var property in source) {
		if (!destination[property]) {
			destination[property] = source[property];
		}
	}
	return destination;
}

function saveCommunityData(data, output_filename) {
	fs.writeFile(output_filename, JSON.stringify(data, null, 4), function(err) {
		if (err) {
			winston.error(err);
		} else {
			winston.info("Updated " + output_filename);
		}
	});
}

function updateCommunity(community, count) {
	var output_filename = options.outputDir + options.outputPrefix + community.id + ".json";
	if (!community.data.state) {
		community.data.state = {};
	}
	community.data.state.nodes = count;
	community.data.state.lastchange = Math.round((new Date()).getTime() / 1000);

	winston.info("==============================================================");
	winston.info("Online nodes in community '" + community.data.name + "': " + count + "\n");
	saveCommunityData(community.data, output_filename);
}

function getDistance(p1, p2) {
	function toRad(n) {
		return n * (Math.PI / 180);
	}
	var dLat = toRad(p2.lat - p1.lat);
	var dLon = toRad(p2.lon - p1.lon);
	var lat1 = toRad(p1.lat);
	var lat2 = toRad(p2.lat);
	var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(p1.lat) * Math.cos(p2.lat);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
	var R = 6371; // km
	var d = R * c;
	return d;
}

function updateCommunities(data) {
	var count = 0;
	routerlist = data.netmon_response.routerlist;
	routers = data.netmon_response.routerlist[0].router;

//	for (var n = 0; n < routers.length; n = n + 1) {
//		if (routers[n].statusdata[0].status[0] !== "online") {
//			continue;
//		}
//		count = count + 1;
//	}
//	// write meta-community file
//	updateCommunity(metacommunity, count);

	// write community files
	var length = communities.length;
	var community = {};
	for (var i = 0; i < length; i = i + 1) {
		count = 0;
		winston.info("Routers in " + communities[i].data.name + " (radius: " + communities[i].radius + " km): ");
		winston.info("-------------------------------------------------------------");
		for (var j = 0; j < routers.length; j = j + 1) {
			if (routers[j].statusdata[0].status[0] !== "online") {
				continue;
			}

			var distance = getDistance({
				"lat" : parseFloat(routers[j].latitude),
				"lon" : parseFloat(routers[j].longitude)
			}, communities[i].data.location).toFixed(2);

			if (distance < communities[i].radius) {
				winston.info("Node " + routers[j].hostname[0] + ", distance: " + distance + " km");
				count = count + 1;
			}
		}
		community.id = communities[i].id;
		community.data = extend(communities[i].data, metacommunity.data);
		updateCommunity(community, count);
	}
}

function exec(instructions) {
	var terminal = require('child_process').spawn('bash');
	terminal.stdout.on('data', function (data) {
		console.log("" + data);
	});
	terminal.on('exit', function (code) {
		console.log("-------------------------------------------------------");
		console.log("DONE");
	});

	for (var i=0; i<instructions.length; i=i+1) {
		console.log('\n' + instructions[i]);
		console.log("-------------------------------------------------------");
		terminal.stdin.write(instructions[i] + "\n");
	}
	terminal.stdin.end();
}

function run() {
	fs.stat(options.cacheRouterlistFile, function(err, stats) {
		var minutesDiff = -1;
		if (!err) {
			var mtime = stats.mtime;
			var fileDate = moment(mtime);
			var now = moment();
			minutesDiff = now.diff(fileDate, 'minutes');
			winston.info("Age of local routerlist: " + minutesDiff + " minutes\n");
		}
		if (err || (minutesDiff > options.cacheMaxAge)) {
			winston.info("Loading routerlist from netmon...");
			//TODO split into multible requests
			client.get(options.netmonUrl,
				function(data, response) {
					winston.info("saving data to file " + options.cacheRouterlistFile + "\n");
					fs.writeFile(options.cacheRouterlistFile, JSON.stringify(data, null, 4), function(err) {
						if (err) {
							winston.error(err);
						}
					});
					updateCommunities(data);
				}
			);
		} else  {
			winston.info("Loading local routerlist...");
			fs.readFile(options.cacheRouterlistFile, 'utf8', function read(err, data) {
				if (err) {
					throw err;
				}
				updateCommunities(JSON.parse(data));
			});
		}
	});
}

run();

<|endoftext|>


<commit_before>import { allProcedureNames, entryPointType } from './blocks'

// GLOBAL EXPECTATIONS
export const declaresAnyProcedure = (/* workspace */) =>
  newExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    `declares something unlike ${toEDLString(entryPointType)}`, declaresProcedureId, { declaration: entryPointType })

export const allProceduresShould = (...expectations) => (workspace) =>
  join(allProcedureNames(workspace).map(multiExpect(...expectations)))

export const multiExpect = (...expectations) => (element) =>
  join(expectations.map(e => e(element)))

export const usesConditionalAlternative = () =>
  newGlobalExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    'uses if', conditionalAlternativeId)

export const usesConditionalRepetition = () =>
  newGlobalExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    'uses while', conditionalRepetitionId)

export const usesSimpleRepetition = () =>
  newGlobalExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    'uses repeat', simpleRepetitionId)

// DECLARATION EXPECTATIONS
export const doSomething = (declaration) =>
  newExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    `${countCallsWithin(declaration)} >= 1`, doSomethingId, { declaration })

export const isUsed = (declaration) =>
  newExpectation(
    { isSuggestion: true },
    `calls ${toEDLString(declaration)}`, isUsedId, { declaration })

export const isUsedFromMain = (declaration) =>
  newExpectation(
    { isSuggestion: true },
    `through ${toEDLString(entryPointType)} calls ${toEDLString(declaration)}`, isUsedFromMainId, { declaration })

const declarationNotTooLong = (limit, declaration, expectationName) =>
  newExpectation(
    { isSuggestion: true, isForControlGroup: true, isSuggestion: true },
    `${countCallsWithin(declaration)} <= ${limit - 1}`, expectationName, { declaration, limit })

export const notTooLong = (limit = 7) => (declaration) =>
  declarationNotTooLong(limit, declaration, tooLongId)

export const mainNotTooLong = (limit = 7) =>
  declarationNotTooLong(limit, entryPointType, "main_too_long")

export const noExpectation = (declaration) => '' // jshint ignore: line

export const doesNotUseRecursion = (declaration) =>
  newExpectation(
    { isCritical: true, isSuggestion: true },
    `not (through ${toEDLString(declaration)} calls ${toEDLString(declaration)})`, doesNotUseRecursionId, { declaration }
  )

export const nameWasChanged = (intl) => (declaration) =>
  newSimpleCondition(
    { isSuggestion: true, isScoreable: true, isForControlGroup: true },
    !declaration.includes(intl.t('blocks.procedures.name').string), nameWasChangedId, { declaration })

// UTILS
const newGlobalExpectation = (types, expect, id) =>
  newExpectation(types, `through ${toEDLString(entryPointType)} ${expect}`, id, { declaration: entryPointType })

export const newExpectation = (types, expect, id, opts = {}) =>
  `expectation "${stringify(id, { ...types, ...opts })}": ${expect};`

// Use this to count number of calls inside a procedure, including recursive calls
// Mulang count does not count recursive calls
export const countCallsWithin = (declaration) =>
  `within ${toEDLString(declaration)} count(calls) + count(calls ${toEDLString(declaration)})`

export const stringify = (id, opts) =>
  `${id}|${Object.entries(opts).map(([key, value]) => `${key}=${value}`).join(';')}`

const newSimpleCondition = (types, condition, id, opt = {}) =>
  newExpectation(types, condition ? pass : fail, id, opt)

const pass = `calls || ! calls`
const fail = `calls && ! calls`

export const parseExpect = (name) => {
  const expectationName = name.split('|')[0]
  const stringToBool = (string) => (string === 'true' || string === 'false') ? string === 'true' : string
  const expectationParams = Object.fromEntries(name.split('|')[1].split(';').map(entry => entry.split('=')).map(([paramName, paramValue]) => [paramName, stringToBool(paramValue)]))
  return [expectationName, expectationParams]

}

export const expectationDescription = (intl, name, result, expectationParams) => {
  const descriptionParams = { result, ...expectationParams }
  const translateAs = (prefix) => {
    const tag = `components.spects.${prefix}.${name}`
    return intl.t(tag, descriptionParams).toString()
  }

  return {
    asScoring: expectationParams?.isScoreable ? translateAs('scoreable') : '',
    asSuggestion: expectationParams?.isSuggestion ? translateAs('suggestions') : '',
    forControlGroup: expectationParams?.isForControlGroup ? translateAs('control_group') : ''
  }

}

const toEDLString = name => `\`${name}\``

const join = expectations => expectations.join('\n')

export const doesNotUseRecursionId = 'does_not_use_recursion'
const isUsedId = 'is_used'
const isUsedFromMainId = 'is_used_from_main'

const doSomethingId = 'do_something'
const tooLongId = 'too_long'
const nameWasChangedId = 'name_was_changed'
const conditionalAlternativeId = 'uses_conditional_alternative'
const conditionalRepetitionId = 'uses_conditional_repetition'
const simpleRepetitionId = 'uses_simple_repetition'
const declaresProcedureId = 'declares_procedure'

export const isCritical = (expectationResult) => expectationResult?.isCritical

export const notCritical = (expectationResult) => !isCritical(expectationResult)

<commit_msg>Removing optional chaining<commit_after>import { allProcedureNames, entryPointType } from './blocks'

// GLOBAL EXPECTATIONS
export const declaresAnyProcedure = (/* workspace */) =>
  newExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    `declares something unlike ${toEDLString(entryPointType)}`, declaresProcedureId, { declaration: entryPointType })

export const allProceduresShould = (...expectations) => (workspace) =>
  join(allProcedureNames(workspace).map(multiExpect(...expectations)))

export const multiExpect = (...expectations) => (element) =>
  join(expectations.map(e => e(element)))

export const usesConditionalAlternative = () =>
  newGlobalExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    'uses if', conditionalAlternativeId)

export const usesConditionalRepetition = () =>
  newGlobalExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    'uses while', conditionalRepetitionId)

export const usesSimpleRepetition = () =>
  newGlobalExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    'uses repeat', simpleRepetitionId)

// DECLARATION EXPECTATIONS
export const doSomething = (declaration) =>
  newExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    `${countCallsWithin(declaration)} >= 1`, doSomethingId, { declaration })

export const isUsed = (declaration) =>
  newExpectation(
    { isSuggestion: true },
    `calls ${toEDLString(declaration)}`, isUsedId, { declaration })

export const isUsedFromMain = (declaration) =>
  newExpectation(
    { isSuggestion: true },
    `through ${toEDLString(entryPointType)} calls ${toEDLString(declaration)}`, isUsedFromMainId, { declaration })

const declarationNotTooLong = (limit, declaration, expectationName) =>
  newExpectation(
    { isSuggestion: true, isForControlGroup: true, isScoreable: true },
    `${countCallsWithin(declaration)} <= ${limit - 1}`, expectationName, { declaration, limit })

export const notTooLong = (limit = 7) => (declaration) =>
  declarationNotTooLong(limit, declaration, tooLongId)

export const mainNotTooLong = (limit = 7) =>
  declarationNotTooLong(limit, entryPointType, "main_too_long")

export const noExpectation = (declaration) => '' // jshint ignore: line

export const doesNotUseRecursion = (declaration) =>
  newExpectation(
    { isCritical: true, isSuggestion: true },
    `not (through ${toEDLString(declaration)} calls ${toEDLString(declaration)})`, doesNotUseRecursionId, { declaration }
  )

export const nameWasChanged = (intl) => (declaration) =>
  newSimpleCondition(
    { isSuggestion: true, isScoreable: true, isForControlGroup: true },
    !declaration.includes(intl.t('blocks.procedures.name').string), nameWasChangedId, { declaration })

// UTILS
const newGlobalExpectation = (types, expect, id) =>
  newExpectation(types, `through ${toEDLString(entryPointType)} ${expect}`, id, { declaration: entryPointType })

export const newExpectation = (types, expect, id, opts = {}) =>
  `expectation "${stringify(id, { ...types, ...opts })}": ${expect};`

// Use this to count number of calls inside a procedure, including recursive calls
// Mulang count does not count recursive calls
export const countCallsWithin = (declaration) =>
  `within ${toEDLString(declaration)} count(calls) + count(calls ${toEDLString(declaration)})`

export const stringify = (id, opts) =>
  `${id}|${Object.entries(opts).map(([key, value]) => `${key}=${value}`).join(';')}`

const newSimpleCondition = (types, condition, id, opt = {}) =>
  newExpectation(types, condition ? pass : fail, id, opt)

const pass = `calls || ! calls`
const fail = `calls && ! calls`

export const parseExpect = (name) => {
  const expectationName = name.split('|')[0]
  const stringToBool = (string) => (string === 'true' || string === 'false') ? string === 'true' : string
  const expectationParams = Object.fromEntries(name.split('|')[1].split(';').map(entry => entry.split('=')).map(([paramName, paramValue]) => [paramName, stringToBool(paramValue)]))
  return [expectationName, expectationParams]

}

export const expectationDescription = (intl, name, result, expectationParams) => {
  const descriptionParams = { result, ...expectationParams }
  const translateAs = (prefix) => {
    const tag = `components.spects.${prefix}.${name}`
    return intl.t(tag, descriptionParams).toString()
  }

  return {
    asScoring: (expectationParams && expectationParams.isScoreable) ? translateAs('scoreable') : '',
    asSuggestion: (expectationParams && expectationParams.isSuggestion) ? translateAs('suggestions') : '',
    forControlGroup: (expectationParams && expectationParams.isForControlGroup) ? translateAs('control_group') : ''
  }

}

const toEDLString = name => `\`${name}\``

const join = expectations => expectations.join('\n')

export const doesNotUseRecursionId = 'does_not_use_recursion'
const isUsedId = 'is_used'
const isUsedFromMainId = 'is_used_from_main'

const doSomethingId = 'do_something'
const tooLongId = 'too_long'
const nameWasChangedId = 'name_was_changed'
const conditionalAlternativeId = 'uses_conditional_alternative'
const conditionalRepetitionId = 'uses_conditional_repetition'
const simpleRepetitionId = 'uses_simple_repetition'
const declaresProcedureId = 'declares_procedure'

export const isCritical = (expectationResult) => expectationResult && expectationResult.isCritical

export const notCritical = (expectationResult) => !isCritical(expectationResult)

<|endoftext|>


<commit_before>import translationModule from './translationModule';
import coreLibrary from '../coreLibrary';

/**
 * Module with utility functions
 * @module utilModule
 */
export default {

   /**
    * Util method for return unique items between arrays
    * @param {Array} A First array
    * @param {Array} B Second array
    * @returns {Array}
    * @private
    */
   diffArray (A, B) {
      var map = {}, C = [];

      for (var i = B.length; i--;) {
         map[B[i]] = null;
      } // any other value would do

      for (var i = A.length; i--;) {
         if (!map.hasOwnProperty(A[i])) {
            C.push(A[i]);
         }
      }
      return C;
   },

   /**
    * Checks deep equality of two object.
    * @param {object} x First object
    * @param {object} y Second object
    * @returns {boolean}
    */
   equals (x, y) {
      if (x === y) return true;
      if ( !(x instanceof Object) || !(y instanceof Object)) return false;
      if (x.constructor !== y.constructor) return false;
      for (var p in x) {
         if (!x.hasOwnProperty(p)) continue;
         if (!y.hasOwnProperty(p)) return false;
         if (x[p] === y[p]) continue;
         if (typeof x[p] !== 'object') return false;
         if (!this.equals(x[p], y[p])) return false;
      }

      for (p in y) {
         if (y.hasOwnProperty(p) && !x.hasOwnProperty(p) ) return false;
      }

      return true;
   },

   /**
    * Returns deep copy of given object.
    * @param {object} x Object to be cloned
    */
   clone (x) {
      return JSON.parse(JSON.stringify(x));
   },

   /* Replaces expressions like "{customer}" from the provided string
    * to the value the have in the coreLibrary.config object
    * @param {String} str the string to replace the expressions in
    */
   replaceConfigParameters (str) {
      if (str == null) {
         return str;
      }
      const config = coreLibrary.config;
      Object.keys(config).forEach((key) => {
         var regex = new RegExp('{' + key + '}', 'g');
         var value = config[key];
         str = str.replace(regex, value);
      });
      return str;
   },

   /**
    * Get decimal formatted odds.
    * @param {Number} odds Odds number
    * @returns {Number}
    */
   getOddsDecimalValue (odds) {
      if (odds < 100) {
         return odds.toFixed(2);
      } else if (odds < 1000) {
         return odds.toFixed(1);
      } else {
         return odds.toFixed(0);
      }
   },

   /**
    * Returns the outcome label translated.
    * @param {Object} outcome A betoffer outcome object
    * @param {Object} event Event object
    * @returns {string}
    */
   getOutcomeLabel (outcome, event) {
      switch (outcome.type) {
         case 'OT_ONE': // Outcome has label 1. Applies to Threeway bet offers.
            return event.homeLabelCustom && event.homeLabelCustom !== '' ? event.homeLabelCustom : event.homeName;
         case 'OT_CROSS': // Outcome has label X. Applies to Threeway bet offers.
            return translationModule.getTranslation('draw');
         case 'OT_TWO': // Outcome has label 2. Applies to Threeway bet offers.
            return event.awayLabelCustom && event.awayLabelCustom !== '' ? event.awayLabelCustom : event.awayName;
         case 'OT_OVER': // The “Over” outcome in Over/Under bet offer.
            return outcome.label + ' ' + (outcome.line / 1000);
         case 'OT_UNDER': // The “Under” outcome in Over/Under bet offer.
            return outcome.label + ' ' + (outcome.line / 1000);
         // Todo: Impelement these responses with translations
         // case 'OT_ODD': //The “Odd” outcome in Odd/Even bet offer.
         // break;
         // case 'OT_EVEN': //The “Even” outcome in Odd/Even bet offer.
         // break;
         // case 'OT_ONE_ONE': //1-1 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_ONE_TWO': //1-2 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_ONE_CROSS': //1-X outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_TWO_ONE': //2-1 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_TWO_TWO': //2-2 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_TWO_CROSS': //2-X outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_CROSS_ONE': //X-1 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_CROSS_TWO': //X-2 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_CROSS_CROSS': //X-X outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_ONE_OR_TWO': //1 or 2 outcome in Double Chance bet offer.
         // break;
         // case 'OT_ONE_OR_CROSS': //1 or X outcome in Double Chance bet offer.
         // break;
         // case 'OT_CROSS_OR_TWO': //X or 2 outcome in Double Chance bet offer.
         // break;
         // case 'OT_YES': //“Yes” outcome in Head To Head and Yes/No bet offer.
         // break;
         // case 'OT_NO': //“No” outcome in Head To Head and Yes/No bet offer.
         // break;
         // case 'OT_OTHER': //“Other results” outcome in Result bet offer.
         // break;
         // case 'OT_UNTYPED': //Outcome does not have type.
         // break;
         // case 'OT_WC_HOME': //Outcome has label Home Win. Applies to WinCast bet offers.
         // break;
         // case 'OT_WC_DRAW': //Outcome has label Draw. Applies to WinCast bet offers.
         // break;
         // case 'OT_WC_AWAY': //Outcome has label Away Win. Applies to WinCast bet offers.
         // break;

         default:
            console.warn('Unhandled outcome type: ' + outcome.type, outcome);
            return outcome.label;
      }
   }
};
<commit_msg>Removed left-over hack from the old core for custom labels in outcome buttons<commit_after>import translationModule from './translationModule';
import coreLibrary from '../coreLibrary';

/**
 * Module with utility functions
 * @module utilModule
 */
export default {

   /**
    * Util method for return unique items between arrays
    * @param {Array} A First array
    * @param {Array} B Second array
    * @returns {Array}
    * @private
    */
   diffArray (A, B) {
      var map = {}, C = [];

      for (var i = B.length; i--;) {
         map[B[i]] = null;
      } // any other value would do

      for (var i = A.length; i--;) {
         if (!map.hasOwnProperty(A[i])) {
            C.push(A[i]);
         }
      }
      return C;
   },

   /**
    * Checks deep equality of two object.
    * @param {object} x First object
    * @param {object} y Second object
    * @returns {boolean}
    */
   equals (x, y) {
      if (x === y) return true;
      if ( !(x instanceof Object) || !(y instanceof Object)) return false;
      if (x.constructor !== y.constructor) return false;
      for (var p in x) {
         if (!x.hasOwnProperty(p)) continue;
         if (!y.hasOwnProperty(p)) return false;
         if (x[p] === y[p]) continue;
         if (typeof x[p] !== 'object') return false;
         if (!this.equals(x[p], y[p])) return false;
      }

      for (p in y) {
         if (y.hasOwnProperty(p) && !x.hasOwnProperty(p) ) return false;
      }

      return true;
   },

   /**
    * Returns deep copy of given object.
    * @param {object} x Object to be cloned
    */
   clone (x) {
      return JSON.parse(JSON.stringify(x));
   },

   /* Replaces expressions like "{customer}" from the provided string
    * to the value the have in the coreLibrary.config object
    * @param {String} str the string to replace the expressions in
    */
   replaceConfigParameters (str) {
      if (str == null) {
         return str;
      }
      const config = coreLibrary.config;
      Object.keys(config).forEach((key) => {
         var regex = new RegExp('{' + key + '}', 'g');
         var value = config[key];
         str = str.replace(regex, value);
      });
      return str;
   },

   /**
    * Get decimal formatted odds.
    * @param {Number} odds Odds number
    * @returns {Number}
    */
   getOddsDecimalValue (odds) {
      if (odds < 100) {
         return odds.toFixed(2);
      } else if (odds < 1000) {
         return odds.toFixed(1);
      } else {
         return odds.toFixed(0);
      }
   },

   /**
    * Returns the outcome label translated.
    * @param {Object} outcome A betoffer outcome object
    * @param {Object} event Event object
    * @returns {string}
    */
   getOutcomeLabel (outcome, event) {
      switch (outcome.type) {
         case 'OT_ONE': // Outcome has label 1. Applies to Threeway bet offers.
            return event.homeName;
         case 'OT_CROSS': // Outcome has label X. Applies to Threeway bet offers.
            return translationModule.getTranslation('draw');
         case 'OT_TWO': // Outcome has label 2. Applies to Threeway bet offers.
            return event.awayName;
         case 'OT_OVER': // The “Over” outcome in Over/Under bet offer.
            return outcome.label + ' ' + (outcome.line / 1000);
         case 'OT_UNDER': // The “Under” outcome in Over/Under bet offer.
            return outcome.label + ' ' + (outcome.line / 1000);
         // Todo: Impelement these responses with translations
         // case 'OT_ODD': //The “Odd” outcome in Odd/Even bet offer.
         // break;
         // case 'OT_EVEN': //The “Even” outcome in Odd/Even bet offer.
         // break;
         // case 'OT_ONE_ONE': //1-1 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_ONE_TWO': //1-2 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_ONE_CROSS': //1-X outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_TWO_ONE': //2-1 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_TWO_TWO': //2-2 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_TWO_CROSS': //2-X outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_CROSS_ONE': //X-1 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_CROSS_TWO': //X-2 outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_CROSS_CROSS': //X-X outcome in Halftime/fulltime bet offer.
         // break;
         // case 'OT_ONE_OR_TWO': //1 or 2 outcome in Double Chance bet offer.
         // break;
         // case 'OT_ONE_OR_CROSS': //1 or X outcome in Double Chance bet offer.
         // break;
         // case 'OT_CROSS_OR_TWO': //X or 2 outcome in Double Chance bet offer.
         // break;
         // case 'OT_YES': //“Yes” outcome in Head To Head and Yes/No bet offer.
         // break;
         // case 'OT_NO': //“No” outcome in Head To Head and Yes/No bet offer.
         // break;
         // case 'OT_OTHER': //“Other results” outcome in Result bet offer.
         // break;
         // case 'OT_UNTYPED': //Outcome does not have type.
         // break;
         // case 'OT_WC_HOME': //Outcome has label Home Win. Applies to WinCast bet offers.
         // break;
         // case 'OT_WC_DRAW': //Outcome has label Draw. Applies to WinCast bet offers.
         // break;
         // case 'OT_WC_AWAY': //Outcome has label Away Win. Applies to WinCast bet offers.
         // break;

         default:
            console.warn('Unhandled outcome type: ' + outcome.type, outcome);
            return outcome.label;
      }
   }
};
<|endoftext|>


<commit_before>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* global ol */

Ext.define("viewer.viewercontroller.ol.OlVectorLayer", {
    extend: "viewer.viewercontroller.controller.VectorLayer",
    mixins: {
        olLayer: "viewer.viewercontroller.ol.OlLayer"
    },
    draw: null,
    point: null,
    line: null,
    polygon: null,
    circle: null,
    source: null,
    box: null,
    tempFeature: null,
    tempStyle: null,
    idNumber: 0,
    freehand: null,
    drawFeatureControls: null,
    activeDrawFeatureControl: null,
    modifyFeature: null,
    constructor: function (config) {
        var me = this;
        viewer.viewercontroller.ol.OlVectorLayer.superclass.constructor.call(this, config);
        this.mixins.olLayer.constructor.call(this, config);
        //this.defColor = config.defaultFeatureStyle.config['fillColor'];
        //this.defaultFeatureStyle = config.defaultFeatureStyle || this.mapStyleConfigToFeatureStyle();
        this.draw = new ol.interaction.Draw({type: 'Point'});
        this.drawBox = new ol.interaction.DragBox({
            condition: ol.events.condition.noModifierKeys,
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: [0, 0, 255, 1]
                })
            })
        });
        this.maps = this.config.viewerController.mapComponent.getMap().getFrameworkMap();
        var index = this.config.viewerController.mapComponent.getMap().getFrameworkMap().getLayers().getLength() + 1;
        this.source = new ol.source.Vector();

        var selectFill = new ol.style.Fill({
            color: '#42FF00'
        });
        var selectStroke = new ol.style.Stroke({
            color: '#42FF00',
            width: 8
        });
        this.selectStyle = new ol.style.Style({
            image: new ol.style.Circle({
                fill: selectFill,
                stroke: selectStroke,
                radius: 6
            }),
            fill: selectFill,
            stroke: selectStroke
        });

        this.frameworkLayer = new ol.layer.Vector({
            zIndex: index,
            source: this.source
        });

        this.select = new ol.interaction.Select({
            layers: [this.frameworkLayer]
            //style: this.selectStyle
        });

        this.modify = new ol.interaction.Modify({
            features: this.select.getFeatures(),
            //style: this.selectStyle
        });

        this.select.getFeatures().on('add', function (args) {
            me.activeFeatureChanged(args);
        }, me);
        this.source.on('addfeature', function (args) {
            me.featureAdded(args);
        }, me);
        this.modify.on('modifyend',function(args){me.featureModified(args);},me);
        this.drawBox.on('boxend', function (evt) {
            var geom = evt.target.getGeometry();
            var feat = new ol.Feature({geometry: geom});
            this.source.addFeature(feat);
            this.drawBox.setActive(false);
        }, this);

        this.maps.addInteraction(this.drawBox);
        this.maps.addInteraction(this.select);
        this.maps.addInteraction(this.modify);
        this.select.setActive(false);
        this.drawBox.setActive(false);

        this.type = viewer.viewercontroller.controller.Layer.VECTOR_TYPE;

    },

    getCurrtentStyle: function () {
        var color = ol.color.asArray(this.defaultFeatureStyle.config['fillColor']);
        color = color.slice();
        color[3] = 0.2;
        var featureFill = new ol.style.Fill({
            //color: this.colorPrefix+ this.style['strokecolor']
            color: color
        });
        var featureStroke = new ol.style.Stroke({
            color: this.defaultFeatureStyle.config['fillColor'],
            width: 3,
            opacity: 0.5
        });
        var featureStyle = new ol.style.Style({
            image: new ol.style.Circle({
                fill: featureFill,
                stroke: featureStroke,
                radius: 5
            }),
            fill: featureFill,
            stroke: featureStroke
        });
        return featureStyle;
    },
    removeAllFeatures: function () {
        this.select.getFeatures().clear();
        this.source.clear();
        this.maps.removeInteraction(this.draw);
        this.drawBox.setActive(false);
    },
    removeFeature: function (feature) {
        var olFeature = this.source.getFeatureById(feature.getId());
        this.select.getFeatures().clear();
        this.source.removeFeature(olFeature);
    },
    getFeature: function (id) {
        Ext.Error.raise({msg: "VectorLayer.getFeature() Not implemented! Must be implemented in sub-class"});
    },
    getFeatureById: function (featureId) {
        return this.fromOpenLayersFeature(this.source.getFeatureById(featureId));
    },
    getAllFeatures: function () {
        var olFeatures = this.source.getFeatures();
        var features = new Array();
        for (var i = 0; i < olFeatures.length; i++) {
            var olFeature = olFeatures[i];
            var feature = this.fromOpenLayersFeature(olFeature);
            features.push(feature);
        }
        return features;
    },

    getActiveFeature: function () {
        var olFeature = this.select.getFeatures().item(0);
        if (olFeature) {
            var feature = this.fromOpenLayersFeature(olFeature);
            return feature;
        } else {
            return null;
        }
    },

    addFeature: function (feature) {
        var features = new Array();
        features.push(feature);
        this.addFeatures(features);

    },
    addFeatures: function (features) {
        var olFeatures = new Array();
        for (var i = 0; i < features.length; i++) {
            var feature = features[i];
            var olFeature = this.toOpenLayersFeature(feature);
            olFeatures.push(olFeature);
            //olFeature.setStyle(this.getCurrtentStyle());
            if (feature.config.label) {
                olFeature.getStyle().setText(new ol.style.Text({text: feature.config.label}));
            }
            // check if a colour was specified on the feature and set that for drawing
            if (feature.config.color) {
                olFeature.getStyle().getStroke().setColor(this.colorPrefix + feature.config.color);
                var color = ol.color.asArray(this.colorPrefix + feature.config.color);
                color = color.slice();
                color[3] = 0.2;
                olFeature.getStyle().getFill().setColor(color);
            }
        }
        return this.source.addFeatures(olFeatures);
    },
    setLabel: function (id, label) {
        var olFeature = this.source.getFeatureById(id);
        if (olFeature && olFeature.getStyle()) {
            if (label) {
                olFeature.getStyle().setText(new ol.style.Text({text: label}));
            } else {
                olFeature.getStyle().setText(new ol.style.Text({text: ''}));
            }
            //this.selectStyle.setText(new ol.style.Text({text:label}));
            //this.source.refresh();
            //this.selectStyle.setText(new ol.style.Text({text:''}));
        }
        this.frameworkLayer.getSource().refresh();
    },
    /**
     ** Note: subclasses should call this method to add the keylistener.
     * @param {String} type geometry type to draw
     *
     */
    drawFeature: function (type) {
        this.drawBox.setActive(false);
        this.select.setActive(false);
        this.maps.removeInteraction(this.draw);
        this.type = type;
        this.superclass.drawFeature.call(this, type);
        if (type === "Point") {
            this.addInteraction(type, false);
        } else if (type === "LineString") {
            this.addInteraction(type, false);
        } else if (type === "Polygon") {
            this.addInteraction(type, false);
        } else if (type === "Circle") {
            this.addInteraction(type, false);
        } else if (type === "Box") {
            this.drawBox.setActive(true);
        } else if (type === "Freehand") {
            this.addInteraction("Polygon", true);
        } else {
            this.config.viewerController.logger.warning("Feature type >" + type + "< not implemented!");
        }
    },

    addInteraction: function (type, free) {
        var me = this;
        this.draw = new ol.interaction.Draw({type: type,
            source: this.source,
            freehand: free
        });
        this.maps.addInteraction(this.draw);
        this.draw.on('drawend', function (evt) {
            me.select.setActive(true);
            evt.feature.setId("OpenLayers_Feature_Vector_" + me.idNumber);
            //this.select.setActive(true);
            me.idNumber++;
            me.maps.removeInteraction(me.draw);
        }, this);
    },

    /**
     * Note: subclasses should call this method to remove the added keylistener.
     */
    stopDrawing: function () {
        // remove the previously added key listener
        var me = this;
        Ext.getDoc().un('keydown', me._keyListener, me);
    },

    /** handle CTRL-Z key when drawing. */
    undoSketch: function () {
        Ext.Error.raise({msg: "VectorLayer.undoSketch() Not implemented! Must be implemented in sub-class"});
    },
    /** handle CTRL-Y key when drawing. */
    redoSketch: function () {
        Ext.Error.raise({msg: "VectorLayer.redoSketch() Not implemented! Must be implemented in sub-class"});
    },
    /** handle ESC key when drawing. */
    cancelSketch: function () {
        Ext.Error.raise({msg: "VectorLayer.cancelSketch() Not implemented! Must be implemented in sub-class"});
    },

    /**
     * Helper function: Converts the given OpenLayers Feature to the generic feature.
     * @param openLayersFeature The OpenLayersFeature to be converted
     * @return The generic feature
     */
    fromOpenLayersFeature: function (openLayersFeature) {
        var wktFormat = new ol.format.WKT();
        var wkt = null;

        if (openLayersFeature.getGeometry().getType() === 'Circle') {
            wkt = wktFormat.writeGeometry(ol.geom.Polygon.fromCircle(openLayersFeature.getGeometry()));
        } else {
            wkt = wktFormat.writeGeometry(openLayersFeature.getGeometry());
        }

        var feature = new viewer.viewercontroller.controller.Feature(
                {
                    id: openLayersFeature.getId(),
                    wktgeom: wkt
                });
        if (openLayersFeature.getStyle()) {
            if (openLayersFeature.getStyle().getText()) {
                feature.label = openLayersFeature.getStyle().getText().getText();
            }
            var color = openLayersFeature.getStyle().getFill().getColor();
            if (color.indexOf("#") !== -1) {
                color = color.substring(color.indexOf("#") + 1, color.length);
            }
            feature.color = color;
        }
        feature.style = this.frameworkStyleToFeatureStyle(openLayersFeature).getProperties();
        if (this.config.addAttributesToFeature) {
            feature.attributes = openLayersFeature.attributes;
        }
        return feature;
    },

    toOpenLayersFeature: function (feature) {
        var wktFormat = new ol.format.WKT();
        var geom = wktFormat.readGeometry(feature.config.wktgeom);
        console.log(feature);
        console.log(geom);
        var olFeature = new ol.Feature();
        olFeature.setGeometry(geom);
        //olFeature.setStyle(this.getCurrtentStyle(feature.config.color));
        olFeature.getStyle().setText(new ol.style.Text({text: feature.config.label}));
        olFeature.setId(feature.config.id);
        return olFeature;
    },

    /**
     * Called when a feature is added to the vectorlayer. and fires @see viewer.viewercontroller.controller.Event.ON_FEATURE_ADDED
     */

    featureAdded: function (object) {
        var feature = this.fromOpenLayersFeature(object.feature);

        // If no stylehash is set for the feature, set it to the current settings
        if (!feature.getStyle()) {
            feature.setStyle(this.getCurrtentStyle());
        }else {
            this.setFeatureStyle(feature.config.id,{config:feature.getStyle()});
        }
        this.editFeature(object.feature);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_FEATURE_ADDED, this, feature);
    },

    editFeature: function (feature) {
        this.select.getFeatures().clear();
        this.select.getFeatures().push(feature);
        var featureObject = this.fromOpenLayersFeature(feature);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_ACTIVE_FEATURE_CHANGED, this, featureObject);
    },

    featureModified: function (evt) {
        var featureObject = this.fromOpenLayersFeature(evt.features.getArray()[0]);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_ACTIVE_FEATURE_CHANGED, this, featureObject);
    },

    activeFeatureChanged: function (object) {
        //object.element.setStyle(this.selectStyle);
        var feature = this.fromOpenLayersFeature(object.element);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_ACTIVE_FEATURE_CHANGED, this, feature);
    },

    adjustStyle: function () {

    },

    getVisible: function () {
        return this.mixins.olLayer.getVisible.call(this);
    },

    reload: function () {
        this.mixins.olLayer.reload.call(this);
    },
    getType: function () {
        return this.mixins.olLayer.getType.call(this);
    },

    frameworkStyleToFeatureStyle: function (feature) {
        var styleProps = this.getCurrentStyleHash();
        return Ext.create('viewer.viewercontroller.controller.FeatureStyle', styleProps);
    },

    getCurrentStyleHash: function (featureStyle) {
        if (!featureStyle) {
            featureStyle = this.defaultFeatureStyle;
        }
        var featureStyleProps = featureStyle.getProperties();
        return Ext.Object.merge({}, {
            'strokeWidth': 3,
            'pointRadius': 6
        }, featureStyleProps);
    },

    setFeatureStyle: function (id, featureStyle, noUpdate) {
        var olFeature = this.getFrameworkLayer().getSource().getFeatureById(id);
        if (olFeature) {
            var c = ol.color.asArray(featureStyle.config.fillColor);
            var colorFinal = 'rgba('+c[0]+','+ c[1]+','+ c[2]+','+featureStyle.config.fillOpacity+')';

            var strokeStyle = new ol.style.Stroke({
                color: featureStyle.config.strokeColor,
                width: featureStyle.config.strokeWidth

            });
            var fillStyle = new ol.style.Fill({
                color: colorFinal
            });

            var style = new ol.style.Style({
                stroke: strokeStyle,
                fill: fillStyle,
                image: new ol.style.Circle({
                    fill: fillStyle,
                    stroke: strokeStyle,
                    radius: featureStyle.config.pointRadius
                })
                });

            olFeature.setStyle(style);
            }
        }
});
   <commit_msg>Save the current style, so the properties can be set when the feature is clicked<commit_after>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* global ol */

Ext.define("viewer.viewercontroller.ol.OlVectorLayer", {
    extend: "viewer.viewercontroller.controller.VectorLayer",
    mixins: {
        olLayer: "viewer.viewercontroller.ol.OlLayer"
    },
    draw: null,
    point: null,
    line: null,
    polygon: null,
    circle: null,
    source: null,
    box: null,
    tempFeature: null,
    tempStyle: null,
    idNumber: 0,
    freehand: null,
    drawFeatureControls: null,
    activeDrawFeatureControl: null,
    modifyFeature: null,
    constructor: function (config) {
        var me = this;
        viewer.viewercontroller.ol.OlVectorLayer.superclass.constructor.call(this, config);
        this.mixins.olLayer.constructor.call(this, config);
        //this.defColor = config.defaultFeatureStyle.config['fillColor'];
        //this.defaultFeatureStyle = config.defaultFeatureStyle || this.mapStyleConfigToFeatureStyle();
        this.draw = new ol.interaction.Draw({type: 'Point'});
        this.drawBox = new ol.interaction.DragBox({
            condition: ol.events.condition.noModifierKeys,
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: [0, 0, 255, 1]
                })
            })
        });
        this.maps = this.config.viewerController.mapComponent.getMap().getFrameworkMap();
        var index = this.config.viewerController.mapComponent.getMap().getFrameworkMap().getLayers().getLength() + 1;
        this.source = new ol.source.Vector();

        var selectFill = new ol.style.Fill({
            color: '#42FF00'
        });
        var selectStroke = new ol.style.Stroke({
            color: '#42FF00',
            width: 8
        });
        this.selectStyle = new ol.style.Style({
            image: new ol.style.Circle({
                fill: selectFill,
                stroke: selectStroke,
                radius: 6
            }),
            fill: selectFill,
            stroke: selectStroke
        });

        this.frameworkLayer = new ol.layer.Vector({
            zIndex: index,
            source: this.source
        });

        this.select = new ol.interaction.Select({
            layers: [this.frameworkLayer]
            //style: this.selectStyle
        });

        this.modify = new ol.interaction.Modify({
            features: this.select.getFeatures()
            //style: this.selectStyle
        });

        this.select.getFeatures().on('add', function (args) {
            me.activeFeatureChanged(args);
        }, me);
        this.source.on('addfeature', function (args) {
            me.featureAdded(args);
        }, me);
        this.modify.on('modifyend',function(args){me.featureModified(args);},me);
        this.drawBox.on('boxend', function (evt) {
            var geom = evt.target.getGeometry();
            var feat = new ol.Feature({geometry: geom});
            this.source.addFeature(feat);
            this.drawBox.setActive(false);
        }, this);

        this.maps.addInteraction(this.drawBox);
        this.maps.addInteraction(this.select);
        this.maps.addInteraction(this.modify);
        this.select.setActive(false);
        this.drawBox.setActive(false);

        this.type = viewer.viewercontroller.controller.Layer.VECTOR_TYPE;

    },

    getCurrtentStyle: function () {
        var color = ol.color.asArray(this.defaultFeatureStyle.config['fillColor']);
        color = color.slice();
        color[3] = 0.2;
        var featureFill = new ol.style.Fill({
            //color: this.colorPrefix+ this.style['strokecolor']
            color: color
        });
        var featureStroke = new ol.style.Stroke({
            color: this.defaultFeatureStyle.config['fillColor'],
            width: 3,
            opacity: 0.5
        });
        var featureStyle = new ol.style.Style({
            image: new ol.style.Circle({
                fill: featureFill,
                stroke: featureStroke,
                radius: 5
            }),
            fill: featureFill,
            stroke: featureStroke
        });
        return featureStyle;
    },
    removeAllFeatures: function () {
        this.select.getFeatures().clear();
        this.source.clear();
        this.maps.removeInteraction(this.draw);
        this.drawBox.setActive(false);
    },
    removeFeature: function (feature) {
        var olFeature = this.source.getFeatureById(feature.getId());
        this.select.getFeatures().clear();
        this.source.removeFeature(olFeature);
    },
    getFeature: function (id) {
        Ext.Error.raise({msg: "VectorLayer.getFeature() Not implemented! Must be implemented in sub-class"});
    },
    getFeatureById: function (featureId) {
        return this.fromOpenLayersFeature(this.source.getFeatureById(featureId));
    },
    getAllFeatures: function () {
        var olFeatures = this.source.getFeatures();
        var features = new Array();
        for (var i = 0; i < olFeatures.length; i++) {
            var olFeature = olFeatures[i];
            var feature = this.fromOpenLayersFeature(olFeature);
            features.push(feature);
        }
        return features;
    },

    getActiveFeature: function () {
        var olFeature = this.select.getFeatures().item(0);
        if (olFeature) {
            var feature = this.fromOpenLayersFeature(olFeature);
            return feature;
        } else {
            return null;
        }
    },

    addFeature: function (feature) {
        var features = new Array();
        features.push(feature);
        this.addFeatures(features);

    },
    addFeatures: function (features) {
        var olFeatures = new Array();
        for (var i = 0; i < features.length; i++) {
            var feature = features[i];
            var olFeature = this.toOpenLayersFeature(feature);
            olFeatures.push(olFeature);
            //olFeature.setStyle(this.getCurrtentStyle());
            if (feature.config.label) {
                olFeature.getStyle().setText(new ol.style.Text({text: feature.config.label}));
            }
            // check if a colour was specified on the feature and set that for drawing
            if (feature.config.color) {
                olFeature.getStyle().getStroke().setColor(this.colorPrefix + feature.config.color);
                var color = ol.color.asArray(this.colorPrefix + feature.config.color);
                color = color.slice();
                color[3] = 0.2;
                olFeature.getStyle().getFill().setColor(color);
            }
        }
        return this.source.addFeatures(olFeatures);
    },
    setLabel: function (id, label) {
        var olFeature = this.source.getFeatureById(id);
        if (olFeature && olFeature.getStyle()) {
            if (label) {
                olFeature.getStyle().setText(new ol.style.Text({text: label}));
            } else {
                olFeature.getStyle().setText(new ol.style.Text({text: ''}));
            }
            //this.selectStyle.setText(new ol.style.Text({text:label}));
            //this.source.refresh();
            //this.selectStyle.setText(new ol.style.Text({text:''}));
        }
        this.frameworkLayer.getSource().refresh();
    },
    /**
     ** Note: subclasses should call this method to add the keylistener.
     * @param {String} type geometry type to draw
     *
     */
    drawFeature: function (type) {
        this.drawBox.setActive(false);
        this.select.setActive(false);
        this.maps.removeInteraction(this.draw);
        this.type = type;
        this.superclass.drawFeature.call(this, type);
        if (type === "Point") {
            this.addInteraction(type, false);
        } else if (type === "LineString") {
            this.addInteraction(type, false);
        } else if (type === "Polygon") {
            this.addInteraction(type, false);
        } else if (type === "Circle") {
            this.addInteraction(type, false);
        } else if (type === "Box") {
            this.drawBox.setActive(true);
        } else if (type === "Freehand") {
            this.addInteraction("Polygon", true);
        } else {
            this.config.viewerController.logger.warning("Feature type >" + type + "< not implemented!");
        }
    },

    addInteraction: function (type, free) {
        var me = this;
        this.draw = new ol.interaction.Draw({type: type,
            source: this.source,
            freehand: free
        });
        this.maps.addInteraction(this.draw);
        this.draw.on('drawend', function (evt) {
            me.select.setActive(true);
            evt.feature.setId("OpenLayers_Feature_Vector_" + me.idNumber);
            //this.select.setActive(true);
            me.idNumber++;
            me.maps.removeInteraction(me.draw);
        }, this);
    },

    /**
     * Note: subclasses should call this method to remove the added keylistener.
     */
    stopDrawing: function () {
        // remove the previously added key listener
        var me = this;
        Ext.getDoc().un('keydown', me._keyListener, me);
    },

    /** handle CTRL-Z key when drawing. */
    undoSketch: function () {
        Ext.Error.raise({msg: "VectorLayer.undoSketch() Not implemented! Must be implemented in sub-class"});
    },
    /** handle CTRL-Y key when drawing. */
    redoSketch: function () {
        Ext.Error.raise({msg: "VectorLayer.redoSketch() Not implemented! Must be implemented in sub-class"});
    },
    /** handle ESC key when drawing. */
    cancelSketch: function () {
        Ext.Error.raise({msg: "VectorLayer.cancelSketch() Not implemented! Must be implemented in sub-class"});
    },

    /**
     * Helper function: Converts the given OpenLayers Feature to the generic feature.
     * @param openLayersFeature The OpenLayersFeature to be converted
     * @return The generic feature
     */
    fromOpenLayersFeature: function (openLayersFeature) {
        var wktFormat = new ol.format.WKT();
        var wkt = null;

        if (openLayersFeature.getGeometry().getType() === 'Circle') {
            wkt = wktFormat.writeGeometry(ol.geom.Polygon.fromCircle(openLayersFeature.getGeometry()));
        } else {
            wkt = wktFormat.writeGeometry(openLayersFeature.getGeometry());
        }

        var feature = new viewer.viewercontroller.controller.Feature(
                {
                    id: openLayersFeature.getId(),
                    wktgeom: wkt
                });
        if (openLayersFeature.getStyle()) {
            if (openLayersFeature.getStyle().getText()) {
                feature.label = openLayersFeature.getStyle().getText().getText();
            }
            var color = openLayersFeature.getStyle().getFill().getColor();
            if (color.indexOf("#") !== -1) {
                color = color.substring(color.indexOf("#") + 1, color.length);
            }
            feature.color = color;
        }
        feature.style = this.frameworkStyleToFeatureStyle(openLayersFeature).getProperties();
        if (this.config.addAttributesToFeature) {
            feature.attributes = openLayersFeature.attributes;
        }
        return feature;
    },

    toOpenLayersFeature: function (feature) {
        var wktFormat = new ol.format.WKT();
        var geom = wktFormat.readGeometry(feature.config.wktgeom);
        console.log(feature);
        console.log(geom);
        var olFeature = new ol.Feature();
        olFeature.setGeometry(geom);
        //olFeature.setStyle(this.getCurrtentStyle(feature.config.color));
        olFeature.getStyle().setText(new ol.style.Text({text: feature.config.label}));
        olFeature.setId(feature.config.id);
        return olFeature;
    },

    /**
     * Called when a feature is added to the vectorlayer. and fires @see viewer.viewercontroller.controller.Event.ON_FEATURE_ADDED
     */

    featureAdded: function (object) {
        var feature = this.fromOpenLayersFeature(object.feature);

        // If no stylehash is set for the feature, set it to the current settings
        if (!feature.getStyle()) {
            feature.setStyle(this.getCurrtentStyle());
        }else {
            this.setFeatureStyle(feature.config.id,{config:feature.getStyle()});
        }
        this.editFeature(object.feature);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_FEATURE_ADDED, this, feature);
    },

    editFeature: function (feature) {
        this.select.getFeatures().clear();
        this.select.getFeatures().push(feature);
        var featureObject = this.fromOpenLayersFeature(feature);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_ACTIVE_FEATURE_CHANGED, this, featureObject);
    },

    featureModified: function (evt) {
        var featureObject = this.fromOpenLayersFeature(evt.features.getArray()[0]);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_ACTIVE_FEATURE_CHANGED, this, featureObject);
    },

    activeFeatureChanged: function (object) {
        //object.element.setStyle(this.selectStyle);
        var feature = this.fromOpenLayersFeature(object.element);
        this.fireEvent(viewer.viewercontroller.controller.Event.ON_ACTIVE_FEATURE_CHANGED, this, feature);
    },

    adjustStyle: function () {

    },

    getVisible: function () {
        return this.mixins.olLayer.getVisible.call(this);
    },

    reload: function () {
        this.mixins.olLayer.reload.call(this);
    },
    getType: function () {
        return this.mixins.olLayer.getType.call(this);
    },

    frameworkStyleToFeatureStyle: function (feature) {
        var styleProps;
        if(feature.style ){
            styleProps = feature.style;
        }else if(feature.getStyle()){
            styleProps = feature.getStyle().featureStyle;
        }
        else{
            styleProps = this.getCurrentStyleHash();
        }
        return Ext.create('viewer.viewercontroller.controller.FeatureStyle', styleProps);
    },

    getCurrentStyleHash: function (featureStyle) {
        if (!featureStyle) {
            featureStyle = this.defaultFeatureStyle;
        }
        var featureStyleProps = featureStyle.getProperties();
        return Ext.Object.merge({}, {
            'strokeWidth': 3,
            'pointRadius': 6
        }, featureStyleProps);
    },

    setFeatureStyle: function (id, featureStyle, noUpdate) {
        var olFeature = this.getFrameworkLayer().getSource().getFeatureById(id);
        if (olFeature) {
            var c = ol.color.asArray(featureStyle.config.fillColor);
            var colorFinal = 'rgba('+c[0]+','+ c[1]+','+ c[2]+','+featureStyle.config.fillOpacity+')';
            var lineDash;
            if(featureStyle.config.strokeDashstyle === "solid"){
                lineDash = null;
            } else if(featureStyle.config.strokeDashstyle === "dot"){
                lineDash = [1,8];
            } else if(featureStyle.config.strokeDashstyle === "dash"){
                lineDash = [10,10];
            }

            var strokeStyle = new ol.style.Stroke({
                color: featureStyle.config.strokeColor,
                width: featureStyle.config.strokeWidth,
                lineDash: lineDash

            });
            var fillStyle = new ol.style.Fill({
                color: colorFinal
            });

            var style = new ol.style.Style({
                stroke: strokeStyle,
                fill: fillStyle,
                image: new ol.style.Circle({
                    fill: fillStyle,
                    stroke: strokeStyle,
                    radius: featureStyle.config.pointRadius
                })
                });
            style.featureStyle = featureStyle.config;
            olFeature.setStyle(style);
            }
        }
});
   <|endoftext|>


<commit_before>import './BorderlessButton';
import { merge } from './updates.js';
import * as symbols from './symbols.js';

const inject = Symbol('inject');
const controlButtonTagKey = Symbol('controlButtonTag');

/**
 * Template mixin which adds buttons for managing playback of a slideshow, audio
 * playlist, etc.
 *
 * [Play controls let the user go back, pause/resume, or forward](/demos/slideshowWithPlayControls.html)
 *
 * @module PlayControlsMixin
 * @elementtag {BorderlessButton} controlButton
 */
export default function PlayControlsMixin(Base) {

  // The class prototype added by the mixin.
  class PlayControls extends Base {

    componentDidMount() {
      if (super.componentDidMount) { super.componentDidMount(); }
      this.$.previousButton.addEventListener('click', event => {
        this.selectPrevious();
        event.stopPropagation();
      });
      this.$.playButton.addEventListener('click', event => {
        if (!this.playing) {
          this.play();
        } else {
          this.pause();
        }
        event.stopPropagation();
      });
      this.$.nextButton.addEventListener('click', event => {
        this.selectNext();
        event.stopPropagation();
      });
      assumeButtonFocus(this, this.$.previousButton);
      assumeButtonFocus(this, this.$.playButton);
      assumeButtonFocus(this, this.$.nextButton);
    }

    get defaults() {
      return {
        tags: {
          controlButton: 'elix-borderless-button'
        }
      };
    }

    /**
     * The tag used to create the play control buttons.
     *
     * @type {string}
     * @default 'elix-borderless-button'
     */
    get controlButtonTag() {
      return this[controlButtonTagKey];
    }
    set controlButtonTag(controlButtonTag) {
      this[symbols.hasDynamicTemplate] = true;
      this[controlButtonTagKey] = controlButtonTag;
    }

    [inject](template) {
      const controlButtonTag = this.controlButtonTag || this.defaults.tags.controlButton;
      return `

          <${controlButtonTag} class="controlButton" id="previousButton" aria-hidden="true" tabindex="-1">
            <slot name="previousButton">
              <svg class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="skip-previous">
                  <path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/>
                </g>
              </svg>
            </slot>
          </${controlButtonTag}>
          <${controlButtonTag} class="controlButton" id="playButton" aria-hidden="true" tabindex="-1">
            <slot name="playButton">
              <svg id="playingIcon" class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="pause-circle-outline">
                  <path d="M9 16h2V8H9v8zm3-14C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm1-4h2V8h-2v8z"></path>
                </g>
              </svg>
              <svg id="pausedIcon" class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="play-circle-outline">
                  <path d="M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"></path>
                </g>
              </svg>
            </slot>
          </${controlButtonTag}>
          <${controlButtonTag} class="controlButton" id="nextButton" aria-hidden="true" tabindex="-1">
            <slot name="nextButton">
              <svg class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="skip-next">
                  <path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/>
                </g>
              </svg>
            </slot>
          </${controlButtonTag}>

          ${template}

      `;
    }

    // Pressing Space is the same as clicking the button.
    [symbols.keydown](event) {
      let handled;

      switch (event.keyCode) {
        case 32: /* Space */
          this.click();
          handled = true;
          break;
      }

      // Prefer mixin result if it's defined, otherwise use base result.
      return handled || (super[symbols.keydown] && super[symbols.keydown](event));
    }

    get updates() {
      const playing = this.playing;
      return merge(super.updates, {
        $: {
          pausedIcon: {
            style: {
              display: playing ? 'none' : ''
            }
          },
          playingIcon: {
            style: {
              display: playing ? '' : 'none'
            }
          }
        }
      })
    }

  }

  return PlayControls;
}

PlayControlsMixin.inject = inject;

/*
 * By default, a button will always take focus on mousedown. For this component,
 * we want to override that behavior, such that a mousedown on a button keeps
 * the focus on the outer component.
 */
function assumeButtonFocus(element, button) {
  button.addEventListener('mousedown', event => {
    // Given the main element the focus if it doesn't already have it.
    element.focus();
    // Prevent the default focus-on-mousedown behavior.
    event.preventDefault();
  });
}
<commit_msg>Flip icons in right-to-left so they point the right direction.<commit_after>import './BorderlessButton.js';
import { merge } from './updates.js';
import * as symbols from './symbols.js';

const inject = Symbol('inject');
const controlButtonTagKey = Symbol('controlButtonTag');

/**
 * Template mixin which adds buttons for managing playback of a slideshow, audio
 * playlist, etc.
 *
 * [Play controls let the user go back, pause/resume, or forward](/demos/slideshowWithPlayControls.html)
 *
 * @module PlayControlsMixin
 * @elementtag {BorderlessButton} controlButton
 */
export default function PlayControlsMixin(Base) {

  // The class prototype added by the mixin.
  class PlayControls extends Base {

    componentDidMount() {
      if (super.componentDidMount) { super.componentDidMount(); }
      this.$.previousButton.addEventListener('click', event => {
        this.selectPrevious();
        event.stopPropagation();
      });
      this.$.playButton.addEventListener('click', event => {
        if (!this.playing) {
          this.play();
        } else {
          this.pause();
        }
        event.stopPropagation();
      });
      this.$.nextButton.addEventListener('click', event => {
        this.selectNext();
        event.stopPropagation();
      });
      assumeButtonFocus(this, this.$.previousButton);
      assumeButtonFocus(this, this.$.playButton);
      assumeButtonFocus(this, this.$.nextButton);
    }

    get defaults() {
      return {
        tags: {
          controlButton: 'elix-borderless-button'
        }
      };
    }

    /**
     * The tag used to create the play control buttons.
     *
     * @type {string}
     * @default 'elix-borderless-button'
     */
    get controlButtonTag() {
      return this[controlButtonTagKey];
    }
    set controlButtonTag(controlButtonTag) {
      this[symbols.hasDynamicTemplate] = true;
      this[controlButtonTagKey] = controlButtonTag;
    }

    /**
     * Add the play controls to a template.
     *
     * @param {string} template - the inner template placed inside the play controls container
     */
    [inject](template) {
      const controlButtonTag = this.controlButtonTag || this.defaults.tags.controlButton;
      return `

          <${controlButtonTag} class="controlButton" id="previousButton" aria-hidden="true" tabindex="-1">
            <slot name="previousButton">
              <svg id="previousIcon" class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="skip-previous">
                  <path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/>
                </g>
              </svg>
            </slot>
          </${controlButtonTag}>
          <${controlButtonTag} class="controlButton" id="playButton" aria-hidden="true" tabindex="-1">
            <slot name="playButton">
              <svg id="playingIcon" class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="pause-circle-outline">
                  <path d="M9 16h2V8H9v8zm3-14C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm1-4h2V8h-2v8z"></path>
                </g>
              </svg>
              <svg id="pausedIcon" class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="play-circle-outline">
                  <path d="M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"></path>
                </g>
              </svg>
            </slot>
          </${controlButtonTag}>
          <${controlButtonTag} class="controlButton" id="nextButton" aria-hidden="true" tabindex="-1">
            <slot name="nextButton">
              <svg id="nextIcon" class="icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet">
                <g id="skip-next">
                  <path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/>
                </g>
              </svg>
            </slot>
          </${controlButtonTag}>

          ${template}

      `;
    }

    // Pressing Space is the same as clicking the button.
    [symbols.keydown](event) {
      let handled;

      switch (event.keyCode) {
        case 32: /* Space */
          this.click();
          handled = true;
          break;
      }

      // Prefer mixin result if it's defined, otherwise use base result.
      return handled || (super[symbols.keydown] && super[symbols.keydown](event));
    }

    get updates() {
      const playing = this.playing;

      const rightToLeft = this[symbols.rightToLeft];
      const transform = rightToLeft ?
        'rotate(180deg)' :
        '';

      return merge(super.updates, {
        $: {
          nextIcon: {
            style: {
              transform
            }
          },
          pausedIcon: {
            style: {
              display: playing ? 'none' : ''
            }
          },
          playingIcon: {
            style: {
              display: playing ? '' : 'none'
            }
          },
          previousIcon: {
            style: {
              transform
            }
          },
        }
      })
    }

  }

  return PlayControls;
}

PlayControlsMixin.inject = inject;

/*
 * By default, a button will always take focus on mousedown. For this component,
 * we want to override that behavior, such that a mousedown on a button keeps
 * the focus on the outer component.
 */
function assumeButtonFocus(element, button) {
  button.addEventListener('mousedown', event => {
    // Given the main element the focus if it doesn't already have it.
    element.focus();
    // Prevent the default focus-on-mousedown behavior.
    event.preventDefault();
  });
}
<|endoftext|>