<commit_before>var rl = new RateLimiter();

function loadingScreen() {
	$('#body').html('
Loading from MusicBrainz webservice…
');
}

function webserviceError(jqXHR) {
	var error = {
		'header': 'Error ' + jqXHR.status,
		'text': [
			'The MusicBrainz webservice returned the following messages:'
		]
	};
	if (jqXHR.responseText) {
		error['text'].push(jqXHR.responseText);
	}
	$('body').html(layoutTemplate.expand({
		body: errorTemplate.expand(error)
	}));
	fixupLinks();
}

function parseURL(url) {
    var a =  document.createElement('a');
    a.href = url;
    return {
        source: url,
        protocol: a.protocol.replace(':',''),
        host: a.hostname,
        port: a.port,
        query: a.search,
        params: (function(){
            var ret = {},
                seg = a.search.replace(/^\?/,'').split('&'),
                len = seg.length, i = 0, s;
            for (;i<len;i++) {
                if (!seg[i]) { continue; }
                s = seg[i].split('=');
                ret[s[0]] = s[1];
            }
            return ret;
        })(),
        file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
        hash: a.hash.replace('#',''),
        path: a.pathname.replace(/^([^\/])/,'/$1'),
        relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
        segments: a.pathname.replace(/^\//,'').split('/')
    };
}

function getWikiText(o, callback) {
	if (!o['relations']) {
		callback('');
		return;
	}

	var wikiLink;
	for (var i = 0; i < o['relations'].length; ++i) {
		if (o['relations'][i]['type'] == 'wikipedia') {
			wikiLink = parseURL(o['relations'][i]['url']);
			break;
		}
	}
	if (!wikiLink) {
		callback('');
		return;
	}

	console.log(wikiLink);
	// OK, lets fetch the article text from the wikipedia API...
	$.get('http://' + wikiLink['host'] + '/w/api.php', {
		action:  'parse',
		prop:    'text',
		format:  'json',
		/* section: 0, */
		page:     decodeURIComponent(wikiLink['file']),
	}, function (data) {
		console.log(data);

		var wikipage = document.createElement('div');
		if (!data['parse']) {
			callback('');
			return;
		}
		wikipage.innerHTML = data['parse']['text']['*'];
		console.log(wikipage);

		var summary;
		for (var i = 0; i < wikipage.childNodes.length; ++i) {
			if (wikipage.childNodes.item(i).localName == 'p') {
				summary = wikipage.childNodes.item(i);
				break;
			}
		}

		if (!summary) {
			callback('');
			return;
		}

		var links = summary.getElementsByTagName('a');
		for (var i = 0; i < links.length; ++i) {
			links[i].href = links[i].href.replace(document.documentURI, wikiLink.source);
			links[i].host = wikiLink.host;
		}

		callback(summary.outerHTML /*+ wikiLinkTemplate.expand({link: wikiLink.source})*/);
	}, 'jsonp');
}

function coverArtMissing(image) {
	image.onerror = "";
	image.src = "http://people.scs.carleton.ca/~cwalton3/temp/mbmockups/ajax/missingart.png";
}

function loadArtist(mbid) {
	loadingScreen();
	rl.queue(function() {
		$.get('http://musicbrainz.org/ws/2/artist/' + mbid, {
			fmt: 'json',
			inc: 'url-rels+artist-rels+annotation',
		}, function (artist) {

			var bandmembers = [];
			var memberof = [];
			var legalname = [];
			var performsas = [];
			var voicedby = [];
			var voiceof = [];
			for (var i = 0; i < artist['relations'].length; ++i) {
				if (artist['relations'][i]['type'] == 'member of band') {
					if (artist['relations'][i]['direction'] == 'backward') {
						bandmembers.push(artist['relations'][i]['artist']);
					} else {
						memberof.push(artist['relations'][i]['artist']);
					}
				} else if (artist['relations'][i]['type'] == 'voice actor') {
					if (artist['relations'][i]['direction'] == 'backward') {
						voicedby.push(artist['relations'][i]['artist']);
					} else {
						voiceof.push(artist['relations'][i]['artist']);
					}
				} else if (artist['relations'][i]['type'] == 'is person') {
					if (artist['relations'][i]['direction'] == 'backward') {
						legalname.push(artist['relations'][i]['artist']);
					} else {
						performsas.push(artist['relations'][i]['artist']);
					}
				} else if (artist['relations'][i]['type'] == 'microblog') {
					var url = artist['relations'][i]['url'];
					var twitter_match = /^http:\/\/twitter\.com\/(.*)/.exec(url)
					if (twitter_match) {
						artist['twitter']  = twitter_match[1];
					}
				} else if (artist['relations'][i]['type'] == 'social network') {
					var url = artist['relations'][i]['url'];
					var fb_match = /^http:\/\/www\.facebook\.com/.exec(url);
					var gplus_match = /^https:\/\/plus.google.com/.exec(url);
					if (fb_match) {
						artist['facebook'] = url;
					} else if (gplus_match) {
						artist['gplus'] = url;
					}
				} else if (artist['relations'][i]['type'] == 'image') {
					artist['image'] = artist['relations'][i]['url'];
				}
			}
			if (bandmembers.length > 0) {
				artist['band-members'] = {artists: bandmembers};
			}
			if (memberof.length > 0) {
				artist['member-of'] = {artists: memberof};
			}
			if (voicedby.length > 0) {
				artist['voiced-by'] = {artists: voicedby};
			}
			if (voiceof.length > 0) {
				artist['voice-of'] = {artists: voiceof};
			}
			if (legalname.length > 0) {
				artist['legal-name'] = {artists: legalname};
			}
			if (performsas.length > 0) {
				artist['performs-as'] = {artists: performsas};
			}

			console.log(artist);

			getWikiText(artist, function (wikiText) {
				artist['wikipedia'] = wikiText;

				rl.queue(function() {
					$.get('http://musicbrainz.org/ws/2/release-group', {
						artist: artist['id'],
						inc:    'artist-credits',
						limit:  100,
						offset: 0,
						fmt:    'json',
					}, function (data) {
						console.log(data);

						artist['release-groups'] = data['release-groups'];
						artist['release-groups'].sort(function (a,b) {
							if (!a['first-release-date']) {
								if (!b['first-release-date']) {
									return 0;
								} else {
									return 1;
								}
							} else {
								if (!b['first-release-date']) {
									return -1;
								}
							}
							if (a['first-release-date']  b['first-release-date']) {
								return 1;
							} else {
								return 0;
							}
						});
						$('body').html(layoutTemplate.expand({
							body: artistTemplate.expand(artist)
						}));

						fixupLinks();
					}, 'json').error(webserviceError);
				});
			});

		}, 'json').error(webserviceError);
	});
}

function loadRelease(mbid) {
	loadingScreen();
	rl.queue(function() {
		$.get('http://musicbrainz.org/ws/2/release/' + mbid, {
			inc: 'artist-credits+labels+discids+recordings+release-groups+annotation',
			fms: 'json'
		}, function (release) {
			for (var i = 0; i < release['media'].length; ++i) {
				release['media'][i]['number'] = i + 1;
			}

			console.log(release);

			$('body').html(layoutTemplate.expand({
				body: releaseTemplate.expand(release)
			}));
			fixupLinks();
		}, 'json').error(webserviceError);
	});
}

function loadReleaseGroup(mbid) {
	loadingScreen();
	rl.queue(function() {
		$.get('http://musicbrainz.org/ws/2/release-group/' + mbid, {
			inc: 'artist-credits+url-rels+annotation',
			fmt: 'json',
		}, function (rg) {
			console.log(rg);

			getWikiText(rg, function (wikiText) {
				rg['wikipedia'] = wikiText;
				rl.queue(function() {
					$.get('http://musicbrainz.org/ws/2/release', {
						'release-group': rg['id'],
						inc:             'artist-credits+media+labels',
						limit:           100,
						offset:          0,
						fmt:             'json',
					}, function (data) {
						console.log(data);

						rg['releases'] = data['releases'].filter(function (r) {
							return (r['status'] != "Pseudo-Release");
						});

						rg['releases'].sort(function (a,b) {
							if (!a['date']) {
								if (!b['date']) {
									return 0;
								} else {
									return 1;
								}
							} else {
								if (!b['date']) {
									return -1;
								}
							}
							if (a['date']  b['date']) {
								return 1;
							} else {
								return 0;
							}
						});
						$('body').html(layoutTemplate.expand({
							body: releaseGroupTemplate.expand(rg)
						}));

						fixupLinks();
					}, 'json').error(webserviceError);
				});
			});
		}, 'json').error(webserviceError);
	});
}

function loadPage(state) {
	console.log(state);
	history.replaceState(state, '', window.location.pathname + state['search']);
	var body;
	if (!state['search']) {
		console.log('loaded index page.');
		body = indexTemplate.expand();
	} else {
		if (state['release']) {
			loadRelease(state['release']);
		} else if (state['release-group']) {
			loadReleaseGroup(state['release-group']);
		} else if (state['artist']) {
			loadArtist(state['artist']);
		} else {
			body = errorTemplate.expand({
				header: 'Error 400',
				text: [
					'I couldn’t understand the query parameters included in the URL: ' + state['search']
				]
			});
		}
		console.log('Loaded page ' + state['search']);
	}
	if (body) {
		$('body').html(layoutTemplate.expand({body: body}));
		fixupLinks();
	}
}

function parseState(searchString) {
	var state = {};
	if (searchString.charAt(0) == '?') {
		var params = searchString.slice(1).split('&');
		for (var i = 0; i < params.length; i++) {
			var equals = params[i].indexOf('=');
			state[params[i].slice(0,equals)] = params[i].slice(equals+1);
		}
	}
	state['search'] = searchString;
	return state;
}

function navigatePage(searchString) {
	var state = parseState(searchString);
	history.pushState(state, '', window.location.pathname + searchString);
	loadPage(state);
}

function fixupLinks() {
	$('a').each(function() {
		var href = $(this).attr('href');
		if (href == '') {
			$(this).click(function() {
				navigatePage('');
				return false;
			});
		} else if (href.charAt(0) == '?') {
			$(this).click(function() {
				navigatePage(href);
				return false;
			});
		}
	});
	twttr.widgets.load();
	FB.XFBML.parse();
	gapi.plus.go();
}

/* Generate a history "state" object from current browser state */
function generateState() {
	var path = [];
	var pathname = window.location.pathname;
	/*if (pathname.indexOf(basePath) === 0) {
		pathname = pathname.slice(basePath.length);
	}*/
	var path = pathname.split('/');
	return {
		path: path,
		scrollX: window.scrollX,
		scrollY: window.scrollY
	};
}

$(document).ready(function() {
	console.log(generateState());
	if (window.location.search.charAt(0) == '?') {
		var state = parseState(window.location.search);
		loadPage(state);
	} else {
		loadPage({search: ''});
	}

	window.onpopstate = function(event) {
		if (event.state) {
			loadPage(event.state);
		}
	};
})
<commit_msg>Fix wikipedia url parsing<commit_after>var rl = new RateLimiter();

function loadingScreen() {
	$('#body').html('
Loading from MusicBrainz webservice…
');
}

function webserviceError(jqXHR) {
	var error = {
		'header': 'Error ' + jqXHR.status,
		'text': [
			'The MusicBrainz webservice returned the following messages:'
		]
	};
	if (jqXHR.responseText) {
		error['text'].push(jqXHR.responseText);
	}
	$('body').html(layoutTemplate.expand({
		body: errorTemplate.expand(error)
	}));
	fixupLinks();
}

function parseURL(url) {
    var a =  document.createElement('a');
    a.href = url;
    return {
        source: url,
        protocol: a.protocol.replace(':',''),
        host: a.hostname,
        port: a.port,
        query: a.search,
        params: (function(){
            var ret = {},
                seg = a.search.replace(/^\?/,'').split('&'),
                len = seg.length, i = 0, s;
            for (;i<len;i++) {
                if (!seg[i]) { continue; }
                s = seg[i].split('=');
                ret[s[0]] = s[1];
            }
            return ret;
        })(),
        file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
        hash: a.hash.replace('#',''),
        path: a.pathname.replace(/^([^\/])/,'/$1'),
        relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
        segments: a.pathname.replace(/^\//,'').split('/')
    };
}

function getWikiText(o, callback) {
	if (!o['relations']) {
		callback('');
		return;
	}

	var wikiLink;
	for (var i = 0; i < o['relations'].length; ++i) {
		if (o['relations'][i]['type'] == 'wikipedia') {
			wikiLink = parseURL(o['relations'][i]['url']);
			break;
		}
	}
	if (!wikiLink) {
		callback('');
		return;
	}

	console.log(wikiLink);
	// OK, lets fetch the article text from the wikipedia API...
	$.get('http://' + wikiLink['host'] + '/w/api.php', {
		action:  'parse',
		prop:    'text',
		format:  'json',
		/* section: 0, */
		page:     decodeURIComponent(wikiLink['path'].slice(6)),
	}, function (data) {
		console.log(data);

		var wikipage = document.createElement('div');
		if (!data['parse']) {
			callback('');
			return;
		}
		wikipage.innerHTML = data['parse']['text']['*'];
		console.log(wikipage);

		var summary;
		for (var i = 0; i < wikipage.childNodes.length; ++i) {
			if (wikipage.childNodes.item(i).localName == 'p') {
				summary = wikipage.childNodes.item(i);
				break;
			}
		}

		if (!summary) {
			callback('');
			return;
		}

		var links = summary.getElementsByTagName('a');
		for (var i = 0; i < links.length; ++i) {
			links[i].href = links[i].href.replace(document.documentURI, wikiLink.source);
			links[i].host = wikiLink.host;
		}

		callback(summary.outerHTML /*+ wikiLinkTemplate.expand({link: wikiLink.source})*/);
	}, 'jsonp');
}

function coverArtMissing(image) {
	image.onerror = "";
	image.src = "http://people.scs.carleton.ca/~cwalton3/temp/mbmockups/ajax/missingart.png";
}

function loadArtist(mbid) {
	loadingScreen();
	rl.queue(function() {
		$.get('http://musicbrainz.org/ws/2/artist/' + mbid, {
			fmt: 'json',
			inc: 'url-rels+artist-rels+annotation',
		}, function (artist) {

			var bandmembers = [];
			var memberof = [];
			var legalname = [];
			var performsas = [];
			var voicedby = [];
			var voiceof = [];
			for (var i = 0; i < artist['relations'].length; ++i) {
				if (artist['relations'][i]['type'] == 'member of band') {
					if (artist['relations'][i]['direction'] == 'backward') {
						bandmembers.push(artist['relations'][i]['artist']);
					} else {
						memberof.push(artist['relations'][i]['artist']);
					}
				} else if (artist['relations'][i]['type'] == 'voice actor') {
					if (artist['relations'][i]['direction'] == 'backward') {
						voicedby.push(artist['relations'][i]['artist']);
					} else {
						voiceof.push(artist['relations'][i]['artist']);
					}
				} else if (artist['relations'][i]['type'] == 'is person') {
					if (artist['relations'][i]['direction'] == 'backward') {
						legalname.push(artist['relations'][i]['artist']);
					} else {
						performsas.push(artist['relations'][i]['artist']);
					}
				} else if (artist['relations'][i]['type'] == 'microblog') {
					var url = artist['relations'][i]['url'];
					var twitter_match = /^http:\/\/twitter\.com\/(.*)/.exec(url)
					if (twitter_match) {
						artist['twitter']  = twitter_match[1];
					}
				} else if (artist['relations'][i]['type'] == 'social network') {
					var url = artist['relations'][i]['url'];
					var fb_match = /^http:\/\/www\.facebook\.com/.exec(url);
					var gplus_match = /^https:\/\/plus.google.com/.exec(url);
					if (fb_match) {
						artist['facebook'] = url;
					} else if (gplus_match) {
						artist['gplus'] = url;
					}
				} else if (artist['relations'][i]['type'] == 'image') {
					artist['image'] = artist['relations'][i]['url'];
				}
			}
			if (bandmembers.length > 0) {
				artist['band-members'] = {artists: bandmembers};
			}
			if (memberof.length > 0) {
				artist['member-of'] = {artists: memberof};
			}
			if (voicedby.length > 0) {
				artist['voiced-by'] = {artists: voicedby};
			}
			if (voiceof.length > 0) {
				artist['voice-of'] = {artists: voiceof};
			}
			if (legalname.length > 0) {
				artist['legal-name'] = {artists: legalname};
			}
			if (performsas.length > 0) {
				artist['performs-as'] = {artists: performsas};
			}

			console.log(artist);

			getWikiText(artist, function (wikiText) {
				artist['wikipedia'] = wikiText;

				rl.queue(function() {
					$.get('http://musicbrainz.org/ws/2/release-group', {
						artist: artist['id'],
						inc:    'artist-credits',
						limit:  100,
						offset: 0,
						fmt:    'json',
					}, function (data) {
						console.log(data);

						artist['release-groups'] = data['release-groups'];
						artist['release-groups'].sort(function (a,b) {
							if (!a['first-release-date']) {
								if (!b['first-release-date']) {
									return 0;
								} else {
									return 1;
								}
							} else {
								if (!b['first-release-date']) {
									return -1;
								}
							}
							if (a['first-release-date']  b['first-release-date']) {
								return 1;
							} else {
								return 0;
							}
						});
						$('body').html(layoutTemplate.expand({
							body: artistTemplate.expand(artist)
						}));

						fixupLinks();
					}, 'json').error(webserviceError);
				});
			});

		}, 'json').error(webserviceError);
	});
}

function loadRelease(mbid) {
	loadingScreen();
	rl.queue(function() {
		$.get('http://musicbrainz.org/ws/2/release/' + mbid, {
			inc: 'artist-credits+labels+discids+recordings+release-groups+annotation',
			fms: 'json'
		}, function (release) {
			for (var i = 0; i < release['media'].length; ++i) {
				release['media'][i]['number'] = i + 1;
			}

			console.log(release);

			$('body').html(layoutTemplate.expand({
				body: releaseTemplate.expand(release)
			}));
			fixupLinks();
		}, 'json').error(webserviceError);
	});
}

function loadReleaseGroup(mbid) {
	loadingScreen();
	rl.queue(function() {
		$.get('http://musicbrainz.org/ws/2/release-group/' + mbid, {
			inc: 'artist-credits+url-rels+annotation',
			fmt: 'json',
		}, function (rg) {
			console.log(rg);

			getWikiText(rg, function (wikiText) {
				rg['wikipedia'] = wikiText;
				rl.queue(function() {
					$.get('http://musicbrainz.org/ws/2/release', {
						'release-group': rg['id'],
						inc:             'artist-credits+media+labels',
						limit:           100,
						offset:          0,
						fmt:             'json',
					}, function (data) {
						console.log(data);

						rg['releases'] = data['releases'].filter(function (r) {
							return (r['status'] != "Pseudo-Release");
						});

						rg['releases'].sort(function (a,b) {
							if (!a['date']) {
								if (!b['date']) {
									return 0;
								} else {
									return 1;
								}
							} else {
								if (!b['date']) {
									return -1;
								}
							}
							if (a['date']  b['date']) {
								return 1;
							} else {
								return 0;
							}
						});
						$('body').html(layoutTemplate.expand({
							body: releaseGroupTemplate.expand(rg)
						}));

						fixupLinks();
					}, 'json').error(webserviceError);
				});
			});
		}, 'json').error(webserviceError);
	});
}

function loadPage(state) {
	console.log(state);
	history.replaceState(state, '', window.location.pathname + state['search']);
	var body;
	if (!state['search']) {
		console.log('loaded index page.');
		body = indexTemplate.expand();
	} else {
		if (state['release']) {
			loadRelease(state['release']);
		} else if (state['release-group']) {
			loadReleaseGroup(state['release-group']);
		} else if (state['artist']) {
			loadArtist(state['artist']);
		} else {
			body = errorTemplate.expand({
				header: 'Error 400',
				text: [
					'I couldn’t understand the query parameters included in the URL: ' + state['search']
				]
			});
		}
		console.log('Loaded page ' + state['search']);
	}
	if (body) {
		$('body').html(layoutTemplate.expand({body: body}));
		fixupLinks();
	}
}

function parseState(searchString) {
	var state = {};
	if (searchString.charAt(0) == '?') {
		var params = searchString.slice(1).split('&');
		for (var i = 0; i < params.length; i++) {
			var equals = params[i].indexOf('=');
			state[params[i].slice(0,equals)] = params[i].slice(equals+1);
		}
	}
	state['search'] = searchString;
	return state;
}

function navigatePage(searchString) {
	var state = parseState(searchString);
	history.pushState(state, '', window.location.pathname + searchString);
	loadPage(state);
}

function fixupLinks() {
	$('a').each(function() {
		var href = $(this).attr('href');
		if (href == '') {
			$(this).click(function() {
				navigatePage('');
				return false;
			});
		} else if (href.charAt(0) == '?') {
			$(this).click(function() {
				navigatePage(href);
				return false;
			});
		}
	});
	twttr.widgets.load();
	FB.XFBML.parse();
	gapi.plus.go();
}

/* Generate a history "state" object from current browser state */
function generateState() {
	var path = [];
	var pathname = window.location.pathname;
	/*if (pathname.indexOf(basePath) === 0) {
		pathname = pathname.slice(basePath.length);
	}*/
	var path = pathname.split('/');
	return {
		path: path,
		scrollX: window.scrollX,
		scrollY: window.scrollY
	};
}

$(document).ready(function() {
	console.log(generateState());
	if (window.location.search.charAt(0) == '?') {
		var state = parseState(window.location.search);
		loadPage(state);
	} else {
		loadPage({search: ''});
	}

	window.onpopstate = function(event) {
		if (event.state) {
			loadPage(event.state);
		}
	};
})
<|endoftext|>


<commit_before>angular.module(PKG.name + '.feature.adapters')
  .controller('AdapterCreateController', function ($scope, AdapterCreateModel, AdapterApiFactory, $q, $alert, $state, $timeout) {
    this.model = new AdapterCreateModel();

    var defaultTabs = [
      {
        title: 'Default',
        icon: 'fa-cogs',
        isCloseable: false,
        partial: '/assets/features/adapters/templates/create/tabs/default.html'
      }
    ];

    this.tabs = defaultTabs.slice();

    this.closeTab = function(index) {
      this.tabs.splice(index, 1);
    };

    AdapterApiFactory.fetchTemplates()
      .$promise
      .then(function(res) {
        this.adapterTypes = res;
      }.bind(this));

    this.onMetadataChange = function() {
      this.tabs = defaultTabs.slice();
      this.model.resetPlugins();
      this.fetchDefaultPlugins();
    };

    function getIcon(plugin) {
      var iconMap = {
        'script': 'fa-code',
        'twitter': 'fa-twitter',
        'cube': 'fa-cubes',
        'data': 'fa-database',
        'database': 'fa-database',
        'table': 'fa-table',
        'kafka': 'icon-kafka',
        'stream': 'icon-plugin-stream',
        'avro': 'icon-avro',
        'jms': 'icon-jms'
      };

      var pluginName = plugin.toLowerCase(),
          icons = Object.keys(iconMap),
          icon = 'fa-plug';
      for(var i=0; i<icons.length; i++) {
        if (pluginName.indexOf(icons[i]) !== -1) {
          icon = iconMap[icons[i]];
          break;
        }
      }
      return icon;
    }

    this.fetchDefaultPlugins = function fetchDefaultPlugins() {
      var params = {scope: $scope, adapterType: this.model.metadata.type};
      $q.all([
        AdapterApiFactory.fetchSources(params).$promise,
        AdapterApiFactory.fetchSinks(params).$promise,
        AdapterApiFactory.fetchTransforms(params).$promise
      ])
        .then(function(res) {
          function setIcons(plugin) {
            plugin.icon = getIcon(plugin.name);
          }

          this.defaultSources = res[0];
          this.defaultSources.forEach(setIcons);
          this.defaultSinks = res[1];
          this.defaultSinks.forEach(setIcons);
          this.defaultTransforms = res[2];
          this.defaultTransforms.forEach(setIcons);
        }.bind(this));
    };
    this.fetchDefaultPlugins();

    this.publish = function() {
      this.model
          .save()
          .then(function() {
            $timeout(function() {
              $state.go('^.list', $state.params, {reload: true});
            });
            $alert({
              type: 'success',
              content: 'Adapter Template created successfully!'
            });
          }, function(err) {
            $alert({
              type: 'danger',
              content: err.message
            });
          });
    };

    this.saveAsDraft = function() {
      this.model
          .saveAsDraft()
          .then(
            function success() {
              $alert({
                type: 'success',
                content: 'The Adapter Template ' + this.model.metadata.name + ' has been saved as draft!'
              });
              $state.go('^.list');
            }.bind(this),
            function error(err) {
              $alert({
                type: 'info',
                content: err.message
              });
            }
          );
    };

    this.model.getDrafts()
      .then(function(res) {
        if ($state.params.data) {
          var draft = angular.copy(res[$state.params.data]);
          if (draft) {
            this.model.setMetadata(draft.config.metadata);
            this.onMetadataChange();
            this.model.setSource(draft.config.source);
            this.model.setSink(draft.config.sink);
            this.model.setTransform(draft.config.transforms);
            this.model.setSchedule(draft.config.schedule);
          }
        }
      }.bind(this));
  });
<commit_msg>Minor fix for setting icon for each plugin in adapter create view<commit_after>angular.module(PKG.name + '.feature.adapters')
  .controller('AdapterCreateController', function ($scope, AdapterCreateModel, AdapterApiFactory, $q, $alert, $state, $timeout) {
    this.model = new AdapterCreateModel();

    var defaultTabs = [
      {
        title: 'Default',
        icon: 'fa-cogs',
        isCloseable: false,
        partial: '/assets/features/adapters/templates/create/tabs/default.html'
      }
    ];

    this.tabs = defaultTabs.slice();

    this.closeTab = function(index) {
      this.tabs.splice(index, 1);
    };

    AdapterApiFactory.fetchTemplates()
      .$promise
      .then(function(res) {
        this.adapterTypes = res;
      }.bind(this));

    this.onMetadataChange = function() {
      this.tabs = defaultTabs.slice();
      this.model.resetPlugins();
      this.fetchDefaultPlugins();
    };

    function getIcon(plugin) {
      var iconMap = {
        'script': 'fa-code',
        'twitter': 'fa-twitter',
        'cube': 'fa-cubes',
        'data': 'fa-database',
        'database': 'fa-database',
        'table': 'fa-table',
        'kafka': 'icon-kafka',
        'stream': 'icon-plugin-stream',
        'avro': 'icon-avro',
        'jms': 'icon-jms'
      };

      var pluginName = plugin.toLowerCase();
      var icon = iconMap[pluginName] ? iconMap[pluginName]: 'fa-plug';
      return icon;
    }

    this.fetchDefaultPlugins = function fetchDefaultPlugins() {
      var params = {scope: $scope, adapterType: this.model.metadata.type};
      $q.all([
        AdapterApiFactory.fetchSources(params).$promise,
        AdapterApiFactory.fetchSinks(params).$promise,
        AdapterApiFactory.fetchTransforms(params).$promise
      ])
        .then(function(res) {
          function setIcons(plugin) {
            plugin.icon = getIcon(plugin.name);
          }

          this.defaultSources = res[0];
          this.defaultSources.forEach(setIcons);
          this.defaultSinks = res[1];
          this.defaultSinks.forEach(setIcons);
          this.defaultTransforms = res[2];
          this.defaultTransforms.forEach(setIcons);
        }.bind(this));
    };
    this.fetchDefaultPlugins();

    this.publish = function() {
      this.model
          .save()
          .then(function() {
            $timeout(function() {
              $state.go('^.list', $state.params, {reload: true});
            });
            $alert({
              type: 'success',
              content: 'Adapter Template created successfully!'
            });
          }, function(err) {
            $alert({
              type: 'danger',
              content: err.message
            });
          });
    };

    this.saveAsDraft = function() {
      this.model
          .saveAsDraft()
          .then(
            function success() {
              $alert({
                type: 'success',
                content: 'The Adapter Template ' + this.model.metadata.name + ' has been saved as draft!'
              });
              $state.go('^.list');
            }.bind(this),
            function error(err) {
              $alert({
                type: 'info',
                content: err.message
              });
            }
          );
    };

    this.model.getDrafts()
      .then(function(res) {
        if ($state.params.data) {
          var draft = angular.copy(res[$state.params.data]);
          if (draft) {
            this.model.setMetadata(draft.config.metadata);
            this.onMetadataChange();
            this.model.setSource(draft.config.source);
            this.model.setSink(draft.config.sink);
            this.model.setTransform(draft.config.transforms);
            this.model.setSchedule(draft.config.schedule);
          }
        }
      }.bind(this));
  });
<|endoftext|>


<commit_before>/* ======= Default Directives ======= */
directives["m-if"] = function(el, val, vdom) {
  var evaluated = new Function("return " + val);
  if(!evaluated()) {
    el.textContent = "";
  } else {
    el.textContent = compileTemplate(vdom.val, self.$data);
  }
}

directives["m-show"] = function(el, val, vdom) {
  var evaluated = new Function("return " + val);
  if(!evaluated()) {
    el.style.display = 'none';
  } else {
    el.style.display = 'block';
  }
}

directives["m-on"] = function(el, val, vdom) {
  var splitVal = val.split(":");
  var eventToCall = splitVal[0];
  var methodToCall = splitVal[1];
  el.addEventListener(eventToCall, function() {
    self.method(methodToCall);
  });
  delete vdom.props["m-on"];
}

directives["m-model"] = function(el, val, vdom) {
  el.value = self.get(val);
  el.addEventListener("input", function() {
    self.set(val, el.value);
  });
  delete vdom.props["m-model"];
}

directives["m-for"] = function(el, val, vdom) {
  var parts = val.split(" in ");
  var alias = parts[0];
  var array = self.get(parts[1]);
}

directives["m-once"] = function(el, val, vdom) {
  vdom.val = el.textContent;
  for(var child in vdom.children) {
    vdom.children[child].val = compileTemplate(vdom.children[child].val, self.$data);
  }
}

directives["m-text"] = function(el, val, vdom) {
  el.textContent = val;
}

directives["m-html"] = function(el, val, vdom) {
  el.innerHTML = val;
}

directives["m-mask"] = function(el, val, vdom) {

}
<commit_msg>call the method instead<commit_after>/* ======= Default Directives ======= */
directives["m-if"] = function(el, val, vdom) {
  var evaluated = new Function("return " + val);
  if(!evaluated()) {
    el.textContent = "";
  } else {
    el.textContent = compileTemplate(vdom.val, self.$data);
  }
}

directives["m-show"] = function(el, val, vdom) {
  var evaluated = new Function("return " + val);
  if(!evaluated()) {
    el.style.display = 'none';
  } else {
    el.style.display = 'block';
  }
}

directives["m-on"] = function(el, val, vdom) {
  var splitVal = val.split(":");
  var eventToCall = splitVal[0];
  var methodToCall = splitVal[1];
  el.addEventListener(eventToCall, function() {
    self.$data[methodToCall]();
  });
  delete vdom.props["m-on"];
}

directives["m-model"] = function(el, val, vdom) {
  el.value = self.get(val);
  el.addEventListener("input", function() {
    self.set(val, el.value);
  });
  delete vdom.props["m-model"];
}

directives["m-for"] = function(el, val, vdom) {
  var parts = val.split(" in ");
  var alias = parts[0];
  var array = self.get(parts[1]);
}

directives["m-once"] = function(el, val, vdom) {
  vdom.val = el.textContent;
  for(var child in vdom.children) {
    vdom.children[child].val = compileTemplate(vdom.children[child].val, self.$data);
  }
}

directives["m-text"] = function(el, val, vdom) {
  el.textContent = val;
}

directives["m-html"] = function(el, val, vdom) {
  el.innerHTML = val;
}

directives["m-mask"] = function(el, val, vdom) {

}
<|endoftext|>


<commit_before>// Generate same page layout for all routes
Router.configure({layoutTemplate: 'layout'});

// Route / to home.html
Router.route('/', {template: 'home'});

// Route /about to about.html
Router.route('/about');

// Test Node.js HTTP request/response processing
Router.route('/test/print/:val', httpTest, {where: 'server'});

// Test route for executing server-side javascript code
//Router.route('/test/hello', serverHello, {where: 'server'});

// Route for CSV export of issues
Router.route('issues.csv', exportIssuesCSV, {where: 'server'});

// Route for CSV export of issues.
Router.route('/report/csv/:prjName', genPrjIssueReportCSV, {where: 'server'});

// Route for HTML export of issues.
Router.route('/report/html/:prjName', genPrjIssueReportHtml, {where: 'server'});

/***  Functions used in above routes  ***/

// Generate issue report for a specific project in CSV format
function genPrjIssueReportCSV() {
    var prjName  = this.params.prjName;
    var filename = prjName + '-issues.csv';
    var fileData = "";
    var records = issueColl.find({PrjName: prjName}).fetch();

    // Build a CSV string. .
    console.log("Got " + records.length + " issue records for project " + prjName);
    fileData += toCsv(records);

    var headers = {
      'Content-type': 'text/csv',
      'Content-Disposition': "attachment; filename=" + filename,
      'Content-Length': fileData.length
    };
    this.response.writeHead(200, headers);
    this.response.end(fileData);
}

// Generate issue report for a specific project in CSV format
function genPrjIssueReportHtml() {
    var prjName  = this.params.prjName;
    var filename = prjName + '-issues.html';
    var fileData = "";
    var records = issueColl.find({PrjName: prjName},{sort: {IPriority: -1, TIssueName: 1}}).fetch();

    // Build a CSV string. .
    console.log("Got " + records.length + " issue records for project " + prjName);
    fileData += toHtml(records);

    var headers = {
      'Content-type': 'text/html',
      'Content-Disposition': "attachment; filename=" + filename,
      'Content-Length': fileData.length
    };
    this.response.writeHead(200, headers);
    this.response.end(fileData);
}

// Export all Issue data to CSV format
function exportIssuesCSV() {
    var filename = 'all-issues.csv';
    var fileData = "";
    var records = issueColl.find().fetch();

    // Build a CSV string. Oversimplified. You'd have to escape quotes and commas.
    //records.forEach(function(rec) {
    console.log("Got " + records.length + " issue records")
      fileData += toCsv(records);
    //});

    var headers = {
      'Content-type': 'text/csv',
      'Content-Disposition': "attachment; filename=" + filename,
      'Content-Length': fileData.length
    };
    this.response.writeHead(200, headers);
    this.response.end(fileData);
}

/**
* Converts a value to a string appropriate for entry into a CSV table (surrounded by quotes).
* @param {string|number|object} theValue
* @param {string} sDelimiter The string delimiter.  Defaults to a double quote (") if omitted.
*/
function toCsvValue(theValue, sDelimiter) {
    var t = typeof (theValue), output;
    if (theValue === null)
        theValue = "";

    theValue.replace(/"/g, '""');

    if (typeof (sDelimiter) === "undefined" || sDelimiter === null) {
            sDelimiter = '"';
    }

    if (t === "undefined" || t === null) {
            output = "";
    } else if (t === "string") {
            output = sDelimiter + theValue + sDelimiter;
    } else {
            output = String(theValue);
    }

    return output;
}

/**
* Converts an array of objects (with identical schemas) into a CSV table.
* @param {Array} objArray An array of objects.  Each object in the array must have the same property list.
* @param {string} sDelimiter The string delimiter.  Defaults to a double quote (") if omitted.
* @param {string} cDelimiter The column delimiter.  Defaults to a comma (,) if omitted.
* @return {string} The CSV equivalent of objArray.
*/
function toCsv(objArray, sDelimiter, cDelimiter) {
	var i, l, names = [], name, value, obj, row, output = "", n, nl;

	// Initialize default parameters.
	if (typeof (sDelimiter) === "undefined" || sDelimiter === null) {
		sDelimiter = '"';
	}
	if (typeof (cDelimiter) === "undefined" || cDelimiter === null) {
		cDelimiter = ",";
	}

	for (i = 0, l = objArray.length; i < l; i += 1) {
            // Get the names of the properties.
            obj = objArray[i];
            row = "";
            if (i === 0) {
                // Loop through the names
                for (name in obj) {
                    if (obj.hasOwnProperty(name)) {
                        if ((name !== 'IEvidence') && (name !== 'INotes')){
                            names.push(name);
                            row += [sDelimiter, name, sDelimiter, cDelimiter].join("");
                        }
                    }
                }
                row = row.substring(0, row.length - 1);
                output += row;
            }

            output += "\n";
            row = "";
            for (n = 0, nl = names.length; n < nl; n += 1) {
                name = names[n];
                if ((name !== 'IEvidence') && (name !== 'INotes')){
                    value = obj[name];
                    if (n > 0) {
                        row += cDelimiter;
                    }
                    row += toCsvValue(value, '"');
                }
            }
            output += row;
	}

	return output;
}

// Run a simple HTTP test with parameter
function httpTest() {
  // NodeJS request object
  var request = this.request;

  // NodeJS  response object
  var response = this.response;

  this.response.end('Parameter passed to httpTest(): ' + this.params.val);
}

/* Remove so that we don't have a dependency on npm-container/meteorhacks:npm (causing startup issues on waptr1)
// Run a simple test for node.js API (using os module)
function serverHello(){
  os = Npm.require('os');
  var req = this.request;
  var res = this.response;
  res.end('Hello from '+os.hostname());
}
*/

/**
* Converts an array of objects (with identical schemas) into HTML
* @param {Array} objArray An array of objects.  Each object in the array must have the same property list.
* @return {string} The CSV equivalent of objArray.
*/
function toHtml(objArray) {
	var obj = {};
        var output = "\n";
        var priority = "N/A", prevPrio = "";
        var cweUriBase   = "https://cwe.mitre.org/data/definitions/";
        output += "\n";

        // Traverse the array of issue objects
        output += "\n\n";
	for (var i = 0; i < objArray.length; i++) {
            // Get the names of the properties.
            obj = objArray[i];
            prevPrio = priority;
            priority = obj.IPriorityText;

            // Don't print the informational findings (for the tester)
            if (priority === 'Info')
                return;

            // Issues are printed in order or priority. When priority changes, print a header.
            if (priority !== prevPrio)
                output += "
" + priority + " Priority Issues
\n";

            // Print each issue with the issue as the header and the details as part of a table.
            output += "
" + obj.TIssueName + "
\n";
            output += "
\n";
            output += "
Issue	" + obj.TIssueName + "
\n";
            if ((obj.CweId !== undefined)&&(obj.CweId !== ""))
                output += "
CWE ID	" + obj.CweId + "
\n";
            if ((obj.IURIs !== undefined)&&(obj.IURIs !== ""))
                output += "
URI(s)	" + htmlEncode(obj.IURIs, true, 4) + "
\n";
            if ((obj.TSeverityText !== undefined)&&(obj.TSeverityText !== ""))
                output += "
Severity	" + obj.TSeverityText + "
\n";
            if ((obj.IPriorityText !== undefined)&&(obj.IPriorityText !== ""))
                output += "
Priority	" + obj.IPriorityText + "
\n";
            if ((obj.IEvidence !== undefined)&&(obj.IEvidence !== ""))
                output += "
Evidence	" + htmlEncode(obj.IEvidence, true, 4) + "
\n";
            if ((obj.INotes !== undefined)&&(obj.INotes !== ""))
                output += "
Notes	" + htmlEncode(obj.INotes, true, 4) + "
\n";
            output += "
\n";
	}
        output += "\n\n";
	return output;
}

/*
HTMLEncode - Encode HTML special characters.
Copyright (c) 2006-2010 Thomas Peri, http://www.tumuski.com/
MIT License
*/

/*jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true,
	plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true */

/**
 * HTML-Encode the supplied input
 *
 * Parameters:
 *
 * (String)  source    The text to be encoded.
 *
 * (boolean) display   The output is intended for display.
 *
 *                     If true:
 *                     * Tabs will be expanded to the number of spaces
 *                       indicated by the 'tabs' argument.
 *                     * Line breaks will be converted to
.
 *
 *                     If false:
 *                     * Tabs and linebreaks get turned into &#____;
 *                       entities just like all other control characters.
 *
 * (integer) tabs      The number of spaces to expand tabs to.  (Ignored
 *                     when the 'display' parameter evaluates to false.)
 *
 * version 2010-11-08
 */
var htmlEncode = function (source, display, tabs) {
	var i, s, ch, peek, line, result,
		next, endline, push,
		spaces;

        if (source === undefined)
            return "";

	// Stash the next character and advance the pointer
	next = function () {
		peek = source.charAt(i);
		i += 1;
	};

	// Start a new "line" of output, to be joined later by

	endline = function () {
		line = line.join('');
		if (display) {
			// If a line starts or ends with a space, it evaporates in html
			// unless it's an nbsp.
			line = line.replace(/(^ )|( $)/g, ' ');
		}
		result.push(line);
		line = [];
	};

	// Push a character or its entity onto the current line
	push = function () {
		if (ch < ' ' || ch > '~') {
			line.push('&#' + ch.charCodeAt(0) + ';');
		} else {
			line.push(ch);
		}
	};

	// Use only integer part of tabs, and default to 4
	tabs = (tabs >= 0) ? Math.floor(tabs) : 4;

	result = [];
	line = [];

	i = 0;
	next();
	while (i <= source.length) { // less than or equal, because i is always one ahead
		ch = peek;
		next();

		// HTML special chars.
		switch (ch) {
		case '<':
			line.push('<');
			break;
		case '>':
			line.push('>');
			break;
		case '&':
			line.push('&');
			break;
		case '"':
			line.push('"');
			break;
		case "'":
			line.push(''');
			break;
		default:
			// If the output is intended for display,
			// then end lines on newlines, and replace tabs with spaces.
			if (display) {
				switch (ch) {
				case '\r':
					// If this \r is the beginning of a \r\n, skip over the \n part.
					if (peek === '\n') {
						next();
					}
					endline();
					break;
				case '\n':
					endline();
					break;
				case '\t':
					// expand tabs
					spaces = tabs - (line.length % tabs);
					for (s = 0; s < spaces; s += 1) {
						line.push(' ');
					}
					break;
				default:
					// All other characters can be dealt with generically.
					push();
				}
			} else {
				// If the output is not for display,
				// then none of the characters need special treatment.
				push();
			}
		}
	}
	endline();

	// If you can't beat 'em, join 'em.
	result = result.join('
');

	if (display) {
		// Break up contiguous blocks of spaces with non-breaking spaces
		result = result.replace(/ {2}/g, '  ');
	}

	// tada!
	return result;
};
<commit_msg>Minor update.<commit_after>// Generate same page layout for all routes
Router.configure({layoutTemplate: 'layout'});

// Route / to home.html
Router.route('/', {template: 'home'});

// Route /about to about.html
Router.route('/about');

// Test Node.js HTTP request/response processing
Router.route('/test/print/:val', httpTest, {where: 'server'});

// Test route for executing server-side javascript code
//Router.route('/test/hello', serverHello, {where: 'server'});

// Route for CSV export of issues
Router.route('issues.csv', exportIssuesCSV, {where: 'server'});

// Route for CSV export of issues.
Router.route('/report/csv/:prjName', genPrjIssueReportCSV, {where: 'server'});

// Route for HTML export of issues.
Router.route('/report/html/:prjName', genPrjIssueReportHtml, {where: 'server'});

/***  Functions used in above routes  ***/

// Generate issue report for a specific project in CSV format
function genPrjIssueReportCSV() {
    var prjName  = this.params.prjName;
    var filename = prjName + '-issues.csv';
    var fileData = "";
    var records = issueColl.find({PrjName: prjName}).fetch();

    // Build a CSV string. .
    console.log("Got " + records.length + " issue records for project " + prjName);
    fileData += toCsv(records);

    var headers = {
      'Content-type': 'text/csv',
      'Content-Disposition': "attachment; filename=" + filename,
      'Content-Length': fileData.length
    };
    this.response.writeHead(200, headers);
    this.response.end(fileData);
}

// Generate issue report for a specific project in CSV format
function genPrjIssueReportHtml() {
    var prjName  = this.params.prjName;
    var filename = prjName + '-issues.html';
    var fileData = "";
    var records = issueColl.find({PrjName: prjName},{sort: {IPriority: -1, TIssueName: 1}}).fetch();

    // Build a CSV string. .
    console.log("Got " + records.length + " issue records for project " + prjName);
    fileData += toHtml(records);

    var headers = {
      'Content-type': 'text/html',
      'Content-Disposition': "attachment; filename=" + filename,
      'Content-Length': fileData.length
    };
    this.response.writeHead(200, headers);
    this.response.end(fileData);
}

// Export all Issue data to CSV format
function exportIssuesCSV() {
    var filename = 'all-issues.csv';
    var fileData = "";
    var records = issueColl.find().fetch();

    // Build a CSV string. Oversimplified. You'd have to escape quotes and commas.
    //records.forEach(function(rec) {
    console.log("Got " + records.length + " issue records")
      fileData += toCsv(records);
    //});

    var headers = {
      'Content-type': 'text/csv',
      'Content-Disposition': "attachment; filename=" + filename,
      'Content-Length': fileData.length
    };
    this.response.writeHead(200, headers);
    this.response.end(fileData);
}

/**
* Converts a value to a string appropriate for entry into a CSV table (surrounded by quotes).
* @param {string|number|object} theValue
* @param {string} sDelimiter The string delimiter.  Defaults to a double quote (") if omitted.
*/
function toCsvValue(theValue, sDelimiter) {
    var t = typeof (theValue), output;
    if (theValue === null)
        theValue = "";

    theValue.replace(/"/g, '""');

    if (typeof (sDelimiter) === "undefined" || sDelimiter === null) {
            sDelimiter = '"';
    }

    if (t === "undefined" || t === null) {
            output = "";
    } else if (t === "string") {
            output = sDelimiter + theValue + sDelimiter;
    } else {
            output = String(theValue);
    }

    return output;
}

/**
* Converts an array of objects (with identical schemas) into a CSV table.
* @param {Array} objArray An array of objects.  Each object in the array must have the same property list.
* @param {string} sDelimiter The string delimiter.  Defaults to a double quote (") if omitted.
* @param {string} cDelimiter The column delimiter.  Defaults to a comma (,) if omitted.
* @return {string} The CSV equivalent of objArray.
*/
function toCsv(objArray, sDelimiter, cDelimiter) {
	var i, l, names = [], name, value, obj, row, output = "", n, nl;

	// Initialize default parameters.
	if (typeof (sDelimiter) === "undefined" || sDelimiter === null) {
		sDelimiter = '"';
	}
	if (typeof (cDelimiter) === "undefined" || cDelimiter === null) {
		cDelimiter = ",";
	}

	for (i = 0, l = objArray.length; i < l; i += 1) {
            // Get the names of the properties.
            obj = objArray[i];
            row = "";
            if (i === 0) {
                // Loop through the names
                for (name in obj) {
                    if (obj.hasOwnProperty(name)) {
                        if ((name !== 'IEvidence') && (name !== 'INotes')){
                            names.push(name);
                            row += [sDelimiter, name, sDelimiter, cDelimiter].join("");
                        }
                    }
                }
                row = row.substring(0, row.length - 1);
                output += row;
            }

            output += "\n";
            row = "";
            for (n = 0, nl = names.length; n < nl; n += 1) {
                name = names[n];
                if ((name !== 'IEvidence') && (name !== 'INotes')){
                    value = obj[name];
                    if (n > 0) {
                        row += cDelimiter;
                    }
                    row += toCsvValue(value, '"');
                }
            }
            output += row;
	}

	return output;
}

// Run a simple HTTP test with parameter
function httpTest() {
  // NodeJS request object
  var request = this.request;

  // NodeJS  response object
  var response = this.response;

  this.response.end('Parameter passed to httpTest(): ' + this.params.val);
}

/* Remove so that we don't have a dependency on npm-container/meteorhacks:npm (causing startup issues on waptr1)
// Run a simple test for node.js API (using os module)
function serverHello(){
  os = Npm.require('os');
  var req = this.request;
  var res = this.response;
  res.end('Hello from '+os.hostname());
}
*/

/**
* Converts an array of objects (with identical schemas) into HTML
* @param {Array} objArray An array of objects.  Each object in the array must have the same property list.
* @return {string} The CSV equivalent of objArray.
*/
function toHtml(objArray) {
	var obj = {};
        var output = "\n";
        var priority = "N/A", prevPrio = "";
        var cweUriBase   = "https://cwe.mitre.org/data/definitions/";
        output += "\n";

        // Traverse the array of issue objects
        output += "\n\n";
	for (var i = 0; i < objArray.length; i++) {
            // Get the names of the properties.
            obj = objArray[i];
            prevPrio = priority;
            priority = obj.IPriorityText;

            // Don't print the informational findings (for the tester)
            if (priority === 'Info')
                continue;

            // Issues are printed in order or priority. When priority changes, print a header.
            if (priority !== prevPrio)
                output += "
" + priority + " Priority Issues
\n";

            // Print each issue with the issue as the header and the details as part of a table.
            output += "
" + obj.TIssueName + "
\n";
            output += "
\n";
            output += "
Issue	" + obj.TIssueName + "
\n";
            if ((obj.CweId !== undefined)&&(obj.CweId !== ""))
                output += "
CWE ID	" + obj.CweId + "
\n";
            if ((obj.IURIs !== undefined)&&(obj.IURIs !== ""))
                output += "
URI(s)	" + htmlEncode(obj.IURIs, true, 4) + "
\n";
            if ((obj.TSeverityText !== undefined)&&(obj.TSeverityText !== ""))
                output += "
Severity	" + obj.TSeverityText + "
\n";
            if ((obj.IPriorityText !== undefined)&&(obj.IPriorityText !== ""))
                output += "
Priority	" + obj.IPriorityText + "
\n";
            if ((obj.IEvidence !== undefined)&&(obj.IEvidence !== ""))
                output += "
Evidence	" + htmlEncode(obj.IEvidence, true, 4) + "
\n";
            if ((obj.INotes !== undefined)&&(obj.INotes !== ""))
                output += "
Notes	" + htmlEncode(obj.INotes, true, 4) + "
\n";
            output += "
\n";
	}
        output += "\n\n";
	return output;
}

/*
HTMLEncode - Encode HTML special characters.
Copyright (c) 2006-2010 Thomas Peri, http://www.tumuski.com/
MIT License
*/

/*jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true,
	plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true */

/**
 * HTML-Encode the supplied input
 *
 * Parameters:
 *
 * (String)  source    The text to be encoded.
 *
 * (boolean) display   The output is intended for display.
 *
 *                     If true:
 *                     * Tabs will be expanded to the number of spaces
 *                       indicated by the 'tabs' argument.
 *                     * Line breaks will be converted to
.
 *
 *                     If false:
 *                     * Tabs and linebreaks get turned into &#____;
 *                       entities just like all other control characters.
 *
 * (integer) tabs      The number of spaces to expand tabs to.  (Ignored
 *                     when the 'display' parameter evaluates to false.)
 *
 * version 2010-11-08
 */
var htmlEncode = function (source, display, tabs) {
	var i, s, ch, peek, line, result,
		next, endline, push,
		spaces;

        if (source === undefined)
            return "";

	// Stash the next character and advance the pointer
	next = function () {
		peek = source.charAt(i);
		i += 1;
	};

	// Start a new "line" of output, to be joined later by

	endline = function () {
		line = line.join('');
		if (display) {
			// If a line starts or ends with a space, it evaporates in html
			// unless it's an nbsp.
			line = line.replace(/(^ )|( $)/g, ' ');
		}
		result.push(line);
		line = [];
	};

	// Push a character or its entity onto the current line
	push = function () {
		if (ch < ' ' || ch > '~') {
			line.push('&#' + ch.charCodeAt(0) + ';');
		} else {
			line.push(ch);
		}
	};

	// Use only integer part of tabs, and default to 4
	tabs = (tabs >= 0) ? Math.floor(tabs) : 4;

	result = [];
	line = [];

	i = 0;
	next();
	while (i <= source.length) { // less than or equal, because i is always one ahead
		ch = peek;
		next();

		// HTML special chars.
		switch (ch) {
		case '<':
			line.push('<');
			break;
		case '>':
			line.push('>');
			break;
		case '&':
			line.push('&');
			break;
		case '"':
			line.push('"');
			break;
		case "'":
			line.push(''');
			break;
		default:
			// If the output is intended for display,
			// then end lines on newlines, and replace tabs with spaces.
			if (display) {
				switch (ch) {
				case '\r':
					// If this \r is the beginning of a \r\n, skip over the \n part.
					if (peek === '\n') {
						next();
					}
					endline();
					break;
				case '\n':
					endline();
					break;
				case '\t':
					// expand tabs
					spaces = tabs - (line.length % tabs);
					for (s = 0; s < spaces; s += 1) {
						line.push(' ');
					}
					break;
				default:
					// All other characters can be dealt with generically.
					push();
				}
			} else {
				// If the output is not for display,
				// then none of the characters need special treatment.
				push();
			}
		}
	}
	endline();

	// If you can't beat 'em, join 'em.
	result = result.join('
');

	if (display) {
		// Break up contiguous blocks of spaces with non-breaking spaces
		result = result.replace(/ {2}/g, '  ');
	}

	// tada!
	return result;
};
<|endoftext|>


<commit_before>var mContainer;
var mCamera, mRenderer;
var mControls;

var mScene;

var mTime = 0.0;
var mTimeStep = (1/60);
var mDuration = 10;

var mGameController;

window.onload = function () {
  init();
};

function init() {
  initTHREE();
  initControls();

  mGameController = new GameController(mScene);
  mGameController.init();

  requestAnimationFrame(tick);
  window.addEventListener('resize', resize, false);
}

function initTHREE() {
  mRenderer = new THREE.WebGLRenderer({antialias: false});
  mRenderer.setSize(window.innerWidth, window.innerHeight);
  mRenderer.setClearColor(0x666666);

  mContainer = document.getElementById('three-container');
  mContainer.appendChild(mRenderer.domElement);

  mCamera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000);
  mCamera.position.set(0, 2, -4);

  mScene = new THREE.Scene();
  //mScene.fog = new THREE.FogExp2(0x666666, 0.015);
  //mScene.add(new THREE.GridHelper(50, 10));

  var light;

  light = new THREE.DirectionalLight();
  light.position.set(0, 25, 50);
  mScene.add(light);

  light = new THREE.DirectionalLight(0xffffff, 0.5);
  light.position.set(0, 25, -50);
  mScene.add(light);
}

function initControls() {
  mControls = new THREE.OrbitControls(mCamera, mRenderer.domElement);
  mControls.target.y = 2;
}

function tick() {
  update();
  render();

  mTime += mTimeStep;
  mTime %= mDuration;

  requestAnimationFrame(tick);
}

function update() {
  mControls.update();

  mGameController.update();
}

function render() {
  mRenderer.render(mScene, mCamera);
}

function resize() {
  mCamera.aspect = window.innerWidth / window.innerHeight;
  mCamera.updateProjectionMatrix();

  mRenderer.setSize(window.innerWidth, window.innerHeight);
}

function GameController(scene) {
  var mPlayerTileIndex = 0;
  var mTilesInWorld = [];

  var mDebug = true;

  var mPlayerTile = null;
  var mMainSpline = null;
  var mCrossSpline = null;
  var mPlayerSplineProgress = 0;

  var mTileFactory = new TileFactory();
  var mTileWidth = mTileFactory.tileWidth, mHalfTileWidth = mTileWidth * 0.5;
  var mTileDepth = mTileFactory.tileDepth, mHalfTileDepth = mTileDepth * 0.5;

  var mEyeHeight = 3;

  var g = new THREE.OctahedronGeometry(1);
  var m = new THREE.MeshPhongMaterial({color:0xff0000, shading:THREE.FlatShading});
  var mPlayerObject = new THREE.Mesh(g, m);

  function placeNextTile() {
    var tile = mTileFactory.nextTile();

    tile.position.z = mTileFactory.tileDepth * mTilesInWorld.length;
    tile.setAnimationProgress(0);

    if (mDebug) {
      tile.userData.mainSplineHelper && tile.remove(tile.userData.mainSplineHelper);
      tile.userData.mainSplineHelper = new SplineHelper(tile.userData.mainSpline, 0xff0000);
      tile.userData.mainSplineHelper.position.y += mEyeHeight;
      tile.add(tile.userData.mainSplineHelper);
    }

    mTilesInWorld.push(tile);

    return tile;
  }

  function updatePlayerSpline() {
    mPlayerTile = mTilesInWorld[mPlayerTileIndex];
    mMainSpline = mPlayerTile.userData.mainSpline;
    mCrossSpline = mPlayerTile.userData.crossSpline;

    mPlayerTile.add(mPlayerObject);
  }

  return {
    init:function() {
      for (var i = 0; i < mTileFactory.cacheSize; i++) {
        scene.add(placeNextTile());
      }

      updatePlayerSpline();

      mPlayerObject.add(mCamera);
    },
    update:function() {
      if (mPlayerSplineProgress >= 1.0) {
        mPlayerSplineProgress = 0;
        mPlayerTileIndex++;

        placeNextTile();
        updatePlayerSpline();
      }

      mPlayerObject.position.copy(mMainSpline.getPointAt(mPlayerSplineProgress));

      var crossFraction = THREE.Math.mapLinear(mPlayerObject.position.x, -mHalfTileWidth, mHalfTileWidth, 0.0, 1.0);

      mPlayerObject.position.y += mCrossSpline.getPointAt(crossFraction).y;
      mPlayerObject.position.y += mEyeHeight;

      mPlayerSplineProgress += 0.005;

      //var animationProgress = mPlayerSplineProgress + 0.25;
      var animationProgress = THREE.Math.mapLinear(mPlayerObject.position.z, -mHalfTileDepth, mHalfTileDepth, 0.0, 1.0) + 0.25;

      if (animationProgress > 1.0) {
        var nextAnimationProgress = animationProgress - 1.0;
        var nextTile = mTilesInWorld[mPlayerTileIndex + 1];
        nextTile.setAnimationProgress(nextAnimationProgress);

        animationProgress = 1.0;
      }

      mPlayerTile.setAnimationProgress(animationProgress);
    }
  }
}

function SplineHelper(spline, color) {
  var g = new THREE.Geometry();
  var m = new THREE.LineBasicMaterial({color:color});

  g.vertices = spline.getPoints(100);

  THREE.Line.call(this, g, m);
}
SplineHelper.prototype = Object.create(THREE.Line.prototype);
SplineHelper.prototype.constructor = SplineHelper;

function TileBufferGeometry(prefab, count) {
  THREE.BAS.PrefabBufferGeometry.call(this, prefab, count);
}
TileBufferGeometry.prototype = Object.create(THREE.BAS.PrefabBufferGeometry.prototype);
TileBufferGeometry.prototype.constructor = TileBufferGeometry;
TileBufferGeometry.prototype.bufferPositions = function() {
  var positionBuffer = this.attributes['position'].array;

  for (var i = 0, offset = 0; i < this.prefabCount; i++) {
    for (var j = 0; j < this.prefabVertexCount; j++, offset += 3) {
      var prefabVertex = this.prefabGeometry.vertices[j];

      positionBuffer[offset    ] = prefabVertex.x;
      positionBuffer[offset + 1] = prefabVertex.y + THREE.Math.randFloatSpread(1);
      positionBuffer[offset + 2] = prefabVertex.z;
    }
  }
};

function Tile(prefabGeometry, prefabCount) {
  var geometry = new TileBufferGeometry(prefabGeometry, prefabCount);

  geometry.createAttribute('aDelayDuration', 2);
  geometry.createAttribute('aStartPosition', 3);
  geometry.createAttribute('aEndPosition', 3);

  var material = new THREE.BAS.PhongAnimationMaterial({
      shading: THREE.FlatShading,
      fog: true,
      uniforms: {
        uTime: {type: 'f', value: 0}
      },
      shaderFunctions: [
        THREE.BAS.ShaderChunk['ease_in_out_cubic']
      ],
      shaderParameters: [
        'uniform float uTime;',
        'attribute vec2 aDelayDuration;',
        'attribute vec3 aStartPosition;',
        'attribute vec3 aEndPosition;'
      ],
      shaderVertexInit: [
        'float tDelay = aDelayDuration.x;',
        'float tDuration = aDelayDuration.y;',
        'float tTime = clamp(uTime - tDelay, 0.0, tDuration);',
        'float tProgress = ease(tTime, 0.0, 1.0, tDuration);'
      ],
      shaderTransformPosition: [
        'transformed += mix(aStartPosition, aEndPosition, tProgress);'
      ]
    }, {
      shininess: 30,
      diffuse:0x333333
    }
  );

  THREE.Mesh.call(this, geometry, material);
}
Tile.prototype = Object.create(THREE.Mesh.prototype);
Tile.prototype.constructor = Tile;

Tile.prototype.setAnimationProgress = function(progress) {
  this.material.uniforms['uTime'].value = this.animationDuration * progress;
};

function TileFactory() {
  // pillar things
  var mPillarWidth = 2;
  var mPillarHeight = 60;
  var mPillarDepth = 4;
  var mPillarGeometry = new THREE.BoxGeometry(mPillarWidth, mPillarHeight, mPillarDepth);
  var mPrefabVertexCount = mPillarGeometry.vertices.length;

  mPillarGeometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, -mPillarHeight * 0.5, 0));

  // tile things
  var mGridWidth = 100;
  var mGridDepth = 50;
  var mTileWidth = mGridWidth * mPillarWidth, halfTileWidth = mTileWidth * 0.5;
  var mTileDepth = mGridDepth * mPillarDepth, halfTileDepth = mTileDepth * 0.5;
  var mPillarCount = mGridWidth * mGridDepth;
  // height variance along the x axis
  var mCrossSpline = createCrossSpline(8, 8);

  // tile cache
  var mTileCache = [];
  var mTileCacheIndex = 0;

  for (var i = 0; i < 2; i++) {
    mTileCache[i] = createTile();
  }

  // helpers
  function createTile() {
    var tile = new Tile(mPillarGeometry, mPillarCount);

    tile.frustumCulled = false;

    return tile;
  }

  function configureTile(tile, mainSpline, crossSpline) {
    var aDelayDuration = tile.geometry.attributes['aDelayDuration'];
    var aStartPosition = tile.geometry.attributes['aStartPosition'];
    var aEndPosition = tile.geometry.attributes['aEndPosition'];

    var i, j, offset;

    // buffer time offset
    var delay;
    var duration;
    var minDuration = 1;
    var maxDuration = 2;
    var rowDelay = 0.05;
    var vertexVariance = 0.5;

    for (i = 0, offset = 0; i < mPillarCount; i++) {
      delay = rowDelay * (i % mGridDepth);
      duration = THREE.Math.randFloat(minDuration, maxDuration);

      for (j = 0; j < mPrefabVertexCount; j++) {
        aDelayDuration.array[offset++] = delay + THREE.Math.randFloatSpread(vertexVariance * 2);
        aDelayDuration.array[offset++] = duration;
      }
    }

    tile.animationDuration = maxDuration + rowDelay * mGridDepth + vertexVariance;

    var x, y, z;

    var pathWidth = 40; // meters
    var pathWidthRange = pathWidth / mTileWidth * 0.5;
    var tileRandomSpreadY = 0; // meters
    var tileDensity = 0.25;

    for (x = -halfTileWidth, offset = 0; x < halfTileWidth; x += mPillarWidth) {
      for (z = -halfTileDepth; z < halfTileDepth; z += mPillarDepth) {

        var t1 = THREE.Math.mapLinear(z, -halfTileDepth, halfTileDepth, 0, 1);
        var mainSplinePoint = mainSpline.getPoint(t1);
        var t2 = THREE.Math.mapLinear(x, -halfTileWidth, halfTileWidth, 0, 1);
        var crossSplinePoint = crossSpline.getPoint(t2);

        y = mainSplinePoint.y + crossSplinePoint.y + THREE.Math.randFloat(0, tileRandomSpreadY);
        //y = mainSplinePoint.y + THREE.Math.randFloat(0, tileRandomSpreadY);

        var endY;

        if (Math.random() < tileDensity && Math.abs(mainSplinePoint.x - x) > mTileWidth * pathWidthRange) {
          endY = THREE.Math.randFloat(mPillarHeight * 0.25, mPillarHeight * 0.75);
        }
        else {
          endY = y;
        }

        for (j = 0; j < mPrefabVertexCount; j++, offset += 3) {
          aStartPosition.array[offset  ] = x;
          aStartPosition.array[offset+1] = y;
          aStartPosition.array[offset+2] = z;

          aEndPosition.array[offset  ] = x;
          aEndPosition.array[offset+1] = endY;
          aEndPosition.array[offset+2] = z;
        }
      }
    }

    aDelayDuration.needsUpdate = true;
    aEndPosition.needsUpdate = true;
    aStartPosition.needsUpdate = true;

    tile.userData.mainSpline = mainSpline;
    tile.userData.crossSpline = crossSpline;
  }

  function createMainSpline(pointCount, xVariance, yVariance) {
    var points = [];
    var point;

    for (var i = 0; i < pointCount; i++) {
      point = new THREE.Vector3();

      if (!i || pointCount - i === 1) {
        point.x = 0;
        point.y = 0;
      }
      else {
        point.x = THREE.Math.randFloatSpread(xVariance);
        point.y = THREE.Math.randFloatSpread(yVariance);
      }

      point.z = THREE.Math.mapLinear(i, 0, pointCount - 1, -halfTileDepth, halfTileDepth);

      points.push(point);
    }

    return new THREE.CatmullRomCurve3(points);
  }

  function createCrossSpline(pointCount, yVariance) {
    var points = [];
    var point;

    for (var i = 0; i < pointCount; i++) {
      point = new THREE.Vector3();
      point.x = THREE.Math.mapLinear(i, 0, pointCount - 1, -halfTileWidth, halfTileWidth);
      point.y = THREE.Math.randFloatSpread(yVariance);
      point.z = 0;

      points.push(point);
    }

    return new THREE.CatmullRomCurve3(points);
  }

  return {
    tileWidth:mTileWidth,
    tileDepth:mTileDepth,
    cacheSize:mTileCache.length,
    nextTile:function() {
      var tile = mTileCache[mTileCacheIndex];

      mTileCacheIndex++;
      mTileCacheIndex %= mTileCache.length;

      var mainSpline = createMainSpline(6, 32, 16);

      configureTile(tile, mainSpline, mCrossSpline);

      return tile;
    }
  }
}

<commit_msg>lanes<commit_after>var mContainer;
var mCamera, mRenderer;
var mControls;

var mScene;

var mTime = 0.0;
var mTimeStep = (1/60);
var mDuration = 10;

var mGameController;

window.onload = function () {
  init();
};

function init() {
  initTHREE();
  initControls();

  mGameController = new GameController(mScene);
  mGameController.init();

  requestAnimationFrame(tick);
  window.addEventListener('resize', resize, false);
}

function initTHREE() {
  mRenderer = new THREE.WebGLRenderer({antialias: false});
  mRenderer.setSize(window.innerWidth, window.innerHeight);
  mRenderer.setClearColor(0x666666);

  mContainer = document.getElementById('three-container');
  mContainer.appendChild(mRenderer.domElement);

  mCamera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000);
  mCamera.position.set(0, 2, -4);

  mScene = new THREE.Scene();
  //mScene.fog = new THREE.FogExp2(0x666666, 0.015);
  //mScene.add(new THREE.GridHelper(50, 10));

  var light;

  light = new THREE.DirectionalLight();
  light.position.set(0, 25, 50);
  mScene.add(light);

  light = new THREE.DirectionalLight(0xffffff, 0.5);
  light.position.set(0, 25, -50);
  mScene.add(light);
}

function initControls() {
  mControls = new THREE.OrbitControls(mCamera, mRenderer.domElement);
  mControls.target.y = 2;
  mControls.keys = false;
}

function tick() {
  update();
  render();

  mTime += mTimeStep;
  mTime %= mDuration;

  requestAnimationFrame(tick);
}

function update() {
  mControls.update();

  mGameController.update();
}

function render() {
  mRenderer.render(mScene, mCamera);
}

function resize() {
  mCamera.aspect = window.innerWidth / window.innerHeight;
  mCamera.updateProjectionMatrix();

  mRenderer.setSize(window.innerWidth, window.innerHeight);
}

function GameController(scene) {
  var mPlayerTileIndex = 0;
  var mTilesInWorld = [];

  var mDebug = true;

  var mPlayerTile = null;
  var mMainSpline = null;
  var mCrossSpline = null;
  var mPlayerSplineProgress = 0;

  var mPathWidth = 16;

  var mTileFactory = new TileFactory(mPathWidth);
  var mTileWidth = mTileFactory.tileWidth, mHalfTileWidth = mTileWidth * 0.5;
  var mTileDepth = mTileFactory.tileDepth, mHalfTileDepth = mTileDepth * 0.5;

  var mEyeHeight = 3;

  var g = new THREE.OctahedronGeometry(1);
  var m = new THREE.MeshPhongMaterial({color:0xff0000, shading:THREE.FlatShading});
  var mPlayerObject = new THREE.Mesh(g, m);

  var mPlayerController = new PlayerController(mPathWidth);

  function placeNextTile() {
    var tile = mTileFactory.nextTile();

    tile.position.z = mTileFactory.tileDepth * mTilesInWorld.length;
    tile.setAnimationProgress(0);

    if (mDebug) {
      tile.userData.mainSplineHelper && tile.remove(tile.userData.mainSplineHelper);
      tile.userData.mainSplineHelper = new SplineHelper(tile.userData.mainSpline, 0xff0000);
      tile.userData.mainSplineHelper.position.y += mEyeHeight;
      tile.add(tile.userData.mainSplineHelper);
    }

    mTilesInWorld.push(tile);

    return tile;
  }

  function updatePlayerSpline() {
    mPlayerTile = mTilesInWorld[mPlayerTileIndex];
    mMainSpline = mPlayerTile.userData.mainSpline;
    mCrossSpline = mPlayerTile.userData.crossSpline;

    mPlayerTile.add(mPlayerObject);
  }

  return {
    init:function() {
      for (var i = 0; i < mTileFactory.cacheSize; i++) {
        scene.add(placeNextTile());
      }

      updatePlayerSpline();

      mPlayerObject.add(mCamera);
    },
    update:function() {
      if (mPlayerSplineProgress >= 1.0) {
        mPlayerSplineProgress = 0;
        mPlayerTileIndex++;

        placeNextTile();
        updatePlayerSpline();
      }

      mPlayerObject.position.copy(mMainSpline.getPointAt(mPlayerSplineProgress));

      mPlayerController.update();
      var i = mPlayerController.getPlayerLaneIndex();
      mPlayerObject.position.x += i * mTileFactory.pillarWidth;

      var crossFraction = THREE.Math.mapLinear(mPlayerObject.position.x, -mHalfTileWidth, mHalfTileWidth, 0.0, 1.0);
      mPlayerObject.position.y += mCrossSpline.getPointAt(crossFraction).y;
      mPlayerObject.position.y += mEyeHeight;

      mPlayerSplineProgress += 0.005;

      //var animationProgress = mPlayerSplineProgress + 0.25;
      var animationProgress = THREE.Math.mapLinear(mPlayerObject.position.z, -mHalfTileDepth, mHalfTileDepth, 0.0, 1.0) + 0.25;

      if (animationProgress > 1.0) {
        var nextAnimationProgress = animationProgress - 1.0;
        var nextTile = mTilesInWorld[mPlayerTileIndex + 1];
        nextTile.setAnimationProgress(nextAnimationProgress);

        animationProgress = 1.0;
      }

      mPlayerTile.setAnimationProgress(animationProgress);
    }
  }
}

// horse animation, camera (+wobble), controls
function PlayerController(pathWidth) {
  var keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
  var keyboardHelper = new KeyboardHelper();

  var indexRange = pathWidth * 0.5 - 1;
  var laneIndex = 0;

  return {
    getPlayerSpeed:function() {

    },
    getPlayerLaneIndex:function() {
      return laneIndex;
    },
    update:function() {
      if (keyboardHelper.isDown(keys.RIGHT)) {
        laneIndex = Math.max(-indexRange, laneIndex - 1);
      }
      else if (keyboardHelper.isDown(keys.LEFT)) {
        laneIndex = Math.min( indexRange, laneIndex + 1);
      }
    }
  }
}

function KeyboardHelper() {
  var downKeys = {};

  window.addEventListener('keydown', onKeyDown);
  window.addEventListener('keyup', onKeyUp);

  function onKeyDown(e) {
    downKeys[e.keyCode] = true;
  }
  function onKeyUp(e) {
    delete downKeys[e.keyCode];
  }

  return {
    isDown:function(key) {
      return downKeys[key];
    }
  }
}

function SplineHelper(spline, color) {
  var g = new THREE.Geometry();
  var m = new THREE.LineBasicMaterial({color:color});

  g.vertices = spline.getPoints(100);

  THREE.Line.call(this, g, m);
}
SplineHelper.prototype = Object.create(THREE.Line.prototype);
SplineHelper.prototype.constructor = SplineHelper;

function TileBufferGeometry(prefab, count) {
  THREE.BAS.PrefabBufferGeometry.call(this, prefab, count);
}
TileBufferGeometry.prototype = Object.create(THREE.BAS.PrefabBufferGeometry.prototype);
TileBufferGeometry.prototype.constructor = TileBufferGeometry;
TileBufferGeometry.prototype.bufferPositions = function() {
  var positionBuffer = this.attributes['position'].array;

  for (var i = 0, offset = 0; i < this.prefabCount; i++) {
    for (var j = 0; j < this.prefabVertexCount; j++, offset += 3) {
      var prefabVertex = this.prefabGeometry.vertices[j];

      positionBuffer[offset    ] = prefabVertex.x;
      positionBuffer[offset + 1] = prefabVertex.y + THREE.Math.randFloatSpread(1);
      positionBuffer[offset + 2] = prefabVertex.z;
    }
  }
};

function Tile(prefabGeometry, prefabCount) {
  var geometry = new TileBufferGeometry(prefabGeometry, prefabCount);

  geometry.createAttribute('aDelayDuration', 2);
  geometry.createAttribute('aStartPosition', 3);
  geometry.createAttribute('aEndPosition', 3);

  var material = new THREE.BAS.PhongAnimationMaterial({
      shading: THREE.FlatShading,
      fog: true,
      uniforms: {
        uTime: {type: 'f', value: 0}
      },
      shaderFunctions: [
        THREE.BAS.ShaderChunk['ease_in_out_cubic']
      ],
      shaderParameters: [
        'uniform float uTime;',
        'attribute vec2 aDelayDuration;',
        'attribute vec3 aStartPosition;',
        'attribute vec3 aEndPosition;'
      ],
      shaderVertexInit: [
        'float tDelay = aDelayDuration.x;',
        'float tDuration = aDelayDuration.y;',
        'float tTime = clamp(uTime - tDelay, 0.0, tDuration);',
        'float tProgress = ease(tTime, 0.0, 1.0, tDuration);'
      ],
      shaderTransformPosition: [
        'transformed += mix(aStartPosition, aEndPosition, tProgress);'
      ]
    }, {
      shininess: 30,
      diffuse:0x333333
    }
  );

  THREE.Mesh.call(this, geometry, material);
}
Tile.prototype = Object.create(THREE.Mesh.prototype);
Tile.prototype.constructor = Tile;
Tile.prototype.setAnimationProgress = function(progress) {
  this.material.uniforms['uTime'].value = this.animationDuration * progress;
};

function TileFactory(pathWidth) {
  // pillar things
  var mPillarWidth = 4;
  var mPillarHeight = 60;
  var mPillarDepth = 4;
  var mPillarGeometry = new THREE.BoxGeometry(mPillarWidth, mPillarHeight, mPillarDepth);
  var mPrefabVertexCount = mPillarGeometry.vertices.length;

  mPillarGeometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, -mPillarHeight * 0.5, 0));

  // tile things
  var mGridWidth = 50;
  var mGridDepth = 50;
  var mTileWidth = mGridWidth * mPillarWidth, halfTileWidth = mTileWidth * 0.5;
  var mTileDepth = mGridDepth * mPillarDepth, halfTileDepth = mTileDepth * 0.5;
  var mPillarCount = mGridWidth * mGridDepth;

  var mPathWidth = pathWidth * mPillarWidth;

  // height variance along the x axis (same for all tiles)
  var mCrossSpline = createCrossSpline(8, 8);

  // tile cache
  var mTileCache = [];
  var mTileCacheIndex = 0;

  for (var i = 0; i < 2; i++) {
    mTileCache[i] = createTile();
  }

  // helpers
  function createTile() {
    var tile = new Tile(mPillarGeometry, mPillarCount);

    tile.frustumCulled = false;

    return tile;
  }

  function configureTile(tile, mainSpline, crossSpline) {
    var aDelayDuration = tile.geometry.attributes['aDelayDuration'];
    var aStartPosition = tile.geometry.attributes['aStartPosition'];
    var aEndPosition = tile.geometry.attributes['aEndPosition'];

    var i, j, offset;

    // buffer time offset
    var delay;
    var duration;
    var minDuration = 1;
    var maxDuration = 2;
    var rowDelay = 0.05;
    var vertexVariance = 0.5;

    for (i = 0, offset = 0; i < mPillarCount; i++) {
      delay = rowDelay * (i % mGridDepth);
      duration = THREE.Math.randFloat(minDuration, maxDuration);

      for (j = 0; j < mPrefabVertexCount; j++) {
        aDelayDuration.array[offset++] = delay + THREE.Math.randFloatSpread(vertexVariance * 2);
        aDelayDuration.array[offset++] = duration;
      }
    }

    tile.animationDuration = maxDuration + rowDelay * mGridDepth + vertexVariance;

    var x, y, z;

    var pathWidthRange = mPathWidth / mTileWidth * 0.5;
    var tileRandomSpreadY = 0; // meters
    var tileDensity = 0.25;

    for (x = -halfTileWidth, offset = 0; x < halfTileWidth; x += mPillarWidth) {
      for (z = -halfTileDepth; z < halfTileDepth; z += mPillarDepth) {

        var t1 = THREE.Math.mapLinear(z, -halfTileDepth, halfTileDepth, 0, 1);
        var mainSplinePoint = mainSpline.getPoint(t1);
        var t2 = THREE.Math.mapLinear(x, -halfTileWidth, halfTileWidth, 0, 1);
        var crossSplinePoint = crossSpline.getPoint(t2);

        y = mainSplinePoint.y + crossSplinePoint.y + THREE.Math.randFloat(0, tileRandomSpreadY);
        //y = mainSplinePoint.y + THREE.Math.randFloat(0, tileRandomSpreadY);

        var endY;

        if (Math.random() < tileDensity && Math.abs(mainSplinePoint.x - x) > mTileWidth * pathWidthRange) {
          endY = THREE.Math.randFloat(mPillarHeight * 0.25, mPillarHeight * 0.75);
        }
        else {
          endY = y;
        }

        for (j = 0; j < mPrefabVertexCount; j++, offset += 3) {
          aStartPosition.array[offset  ] = x;
          aStartPosition.array[offset+1] = y;
          aStartPosition.array[offset+2] = z;

          aEndPosition.array[offset  ] = x;
          aEndPosition.array[offset+1] = endY;
          aEndPosition.array[offset+2] = z;
        }
      }
    }

    aDelayDuration.needsUpdate = true;
    aEndPosition.needsUpdate = true;
    aStartPosition.needsUpdate = true;

    tile.userData.mainSpline = mainSpline;
    tile.userData.crossSpline = crossSpline;
  }

  function createMainSpline(pointCount, xVariance, yVariance) {
    var points = [];
    var point;

    for (var i = 0; i < pointCount; i++) {
      point = new THREE.Vector3();

      if (!i || pointCount - i === 1) {
        point.x = 0;
        point.y = 0;
      }
      else {
        point.x = THREE.Math.randFloatSpread(xVariance);
        point.y = THREE.Math.randFloatSpread(yVariance);
      }

      point.z = THREE.Math.mapLinear(i, 0, pointCount - 1, -halfTileDepth, halfTileDepth);

      points.push(point);
    }

    return new THREE.CatmullRomCurve3(points);
  }

  function createCrossSpline(pointCount, yVariance) {
    var points = [];
    var point;

    for (var i = 0; i < pointCount; i++) {
      point = new THREE.Vector3();
      point.x = THREE.Math.mapLinear(i, 0, pointCount - 1, -halfTileWidth, halfTileWidth);
      point.y = THREE.Math.randFloatSpread(yVariance);
      point.z = 0;

      points.push(point);
    }

    return new THREE.CatmullRomCurve3(points);
  }

  return {
    tileWidth:mTileWidth,
    tileDepth:mTileDepth,
    pillarWidth:mPillarWidth,
    pillarDepth:mPillarDepth,
    cacheSize:mTileCache.length,
    nextTile:function() {
      var tile = mTileCache[mTileCacheIndex];

      mTileCacheIndex++;
      mTileCacheIndex %= mTileCache.length;

      var mainSpline = createMainSpline(6, 32, 16);

      configureTile(tile, mainSpline, mCrossSpline);

      return tile;
    }
  }
}

<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {
    View,
    StyleSheet,
    Text,
    Dimensions,
} from 'react-native';

import * as CollapsedMetrics from 'app/utility/transforms/CollapsedMetrics';
import * as SetsSelectors from 'app/redux/selectors/SetsSelectors';

class SetAnalysis extends Component {

    _renderAnalysis(value, unit, description, isBigMetric) {
        if (isBigMetric) {
            return (
                <View style={styles.bigMetricBackground}>
                    <Text style={styles.bigMetricText}>{value}</Text>
                    <Text style={styles.bigMetric}>{description}</Text>
                    <Text style={styles.bigMetric}>{unit}</Text>
                </View>
            );
        } else {
            return (
                <View style={{flex: 1, marginTop: -2, justifyContent: 'center'}}>
                    <Text style={styles.text}>
                        {value}
                        <Text style={styles.unit}> {unit}</Text>

                    </Text>
                    <Text style={styles.metric}>{description}</Text>
                </View>
            );
        }
    }

    render() {
        let { height, width } = Dimensions.get('window');
        let lastColumn = null;
        if (width > 350) {
            lastColumn = this._renderAnalysis(this.props.value5, this.props.unit5, this.props.description5, false);
        }

        return (
            <View style={[styles.border, styles.container, {flex:1, flexDirection: 'row'}]}>
                {this._renderAnalysis(this.props.value1, this.props.unit1, this.props.description1, true)}
                {this._renderAnalysis(this.props.value2, this.props.unit2, this.props.description2, false)}
                {this._renderAnalysis(this.props.value3, this.props.unit3, this.props.description3, false)}
                {this._renderAnalysis(this.props.value4, this.props.unit4, this.props.description4, false)}
                {lastColumn}
            </View>
        );
    }

}

const styles = StyleSheet.create({
    container: {
        overflow: 'hidden',
        backgroundColor:'white',
        paddingTop: 10,
        paddingBottom: 10,
        paddingLeft: 5,
    },
    border: {
        borderColor: '#e0e0e0',
        borderLeftWidth: 1,
        borderRightWidth: 1,
    },
    text: {
        color: '#4d4d4d',
        fontSize: 18,
        fontWeight: 'bold',
        textAlign: 'center',
    },
    unit: {
        color: '#4d4d4d',
        fontSize: 10,
        fontWeight: "500",
        textAlign: 'center',
        marginTop: 8,
    },
    metric: {
        color: '#4d4d4d',
        fontSize: 10,
        fontWeight: "500",
        textAlign: 'center',
        marginTop: 1,
    },
    bigMetricBackground: {
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#fddddd',
        width: 80,
        height: 80,
        borderRadius: 80 / 2,
        borderColor: '#fddddd',
        overflow: 'hidden',
    },
    bigMetricText: {
        textAlign: 'center',
        color: '#f0565a',
        fontSize: 20,
        fontWeight: 'bold',
    },
    bigMetric: {
        textAlign: 'center',
        color: '#f0565a',
        fontSize: 10,
        fontWeight: 'bold',
    }
});

export default SetAnalysis;
<commit_msg>played with font<commit_after>import React, {Component} from 'react';
import {
    View,
    StyleSheet,
    Text,
    Dimensions,
} from 'react-native';

import * as CollapsedMetrics from 'app/utility/transforms/CollapsedMetrics';
import * as SetsSelectors from 'app/redux/selectors/SetsSelectors';

class SetAnalysis extends Component {

    _renderAnalysis(value, unit, description, isBigMetric) {
        if (isBigMetric) {
            return (
                <View style={styles.bigMetricBackground}>
                    <Text style={styles.bigMetricText}>{value}</Text>
                    <Text style={styles.bigMetric}>{description}</Text>
                    <Text style={styles.bigMetric}>{unit}</Text>
                </View>
            );
        } else {
            return (
                <View style={{flex: 1, marginTop: -2, justifyContent: 'center'}}>
                    <Text style={styles.text}>
                        {value}
                        <Text style={styles.unit}> {unit}</Text>

                    </Text>
                    <Text style={styles.metric}>{description}</Text>
                </View>
            );
        }
    }

    render() {
        let { height, width } = Dimensions.get('window');
        let lastColumn = null;
        if (width > 350) {
            lastColumn = this._renderAnalysis(this.props.value5, this.props.unit5, this.props.description5, false);
        }

        return (
            <View style={[styles.border, styles.container, {flex:1, flexDirection: 'row'}]}>
                {this._renderAnalysis(this.props.value1, this.props.unit1, this.props.description1, true)}
                {this._renderAnalysis(this.props.value2, this.props.unit2, this.props.description2, false)}
                {this._renderAnalysis(this.props.value3, this.props.unit3, this.props.description3, false)}
                {this._renderAnalysis(this.props.value4, this.props.unit4, this.props.description4, false)}
                {lastColumn}
            </View>
        );
    }

}

const styles = StyleSheet.create({
    container: {
        overflow: 'hidden',
        backgroundColor:'white',
        paddingTop: 10,
        paddingBottom: 10,
        paddingLeft: 5,
    },
    border: {
        borderColor: '#e0e0e0',
        borderLeftWidth: 1,
        borderRightWidth: 1,
    },
    text: {
        color: '#4d4d4d',
        fontSize: 15,
        fontWeight: 'bold',
        textAlign: 'center',
    },
    unit: {
        color: 'darkgray',
        fontSize: 10,
        fontWeight: "500",
        textAlign: 'center',
        marginTop: 8,
    },
    metric: {
        color: '#4d4d4d',
        fontSize: 10,
        fontWeight: "500",
        textAlign: 'center',
        marginTop: 1,
    },
    bigMetricBackground: {
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column',
        backgroundColor: '#fddddd',
        width: 80,
        height: 80,
        borderRadius: 80 / 2,
        borderColor: '#fddddd',
        overflow: 'hidden',
    },
    bigMetricText: {
        textAlign: 'center',
        color: '#f0565a',
        fontSize: 20,
        fontWeight: 'bold',
    },
    bigMetric: {
        textAlign: 'center',
        color: '#f0565a',
        fontSize: 10,
        fontWeight: 'bold',
    }
});

export default SetAnalysis;
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////

QUnit.test("2x high-res image call.", function(assert) {

  //////////
  // Given

  var ip = new ImgTagBuilder({ styles: { main: { breakPoints: [ { minViewportWidth: 0, maxImageDisplayWidth: 800, quality: 85 } ] } } });

  //////////
  // When

  ip._devicePixelRatio = 2; // Force to '2' so testing works across devices.
  ip.innerWidth = 1000; // Force for testing regardless of device.

  ip.prep({ image: "horses.jpg", alt: "some horses",  style: "main", maxWidth: 1600, maxHeight: 1000 });

  //////////
  // Then

  // This is the key requirement. Everything else supports it.
  assert.equal(ip.imgTag(),'', "Target `img` tag.");

  // Verify config details are ingested.
  assert.equal(ip._alt, "some horses", "_alt");
  assert.equal(ip._image, "horses.jpg", "_image");
  assert.equal(ip._maxHeight, 1000, "_maxHeight");
  assert.equal(ip._maxWidth, 1600, "_maxWidth");
  assert.equal(ip._devicePixelRatio, 2, "_devidePixelRatio");
  assert.equal(ip._style, "main", "_style");

  // TODO: Figure out how to move this out so it's called dynamically.
  assert.equal(ip._config.styles['main']['breakPoints'][0]['maxImageDisplayWidth'], 800, "maxImageDisplayWidth");

  // Method verification
  assert.equal(ip.callHeight(), 1000, "callHeight()");
  assert.equal(ip.callWidth(), 1600, "callWidth()");
  assert.equal(ip.displayHeight(), 500, "displayHeight()");
  assert.equal(ip.displayWidth(), 800, "displayWidth()");
  assert.equal(ip.url(),'http://res.cloudinary.com/demo/image/upload/c_fill,q_85,w_1600,h_1000/horses.jpg', "url()");
  assert.equal(ip.quality(), 85, "quality()");
  assert.equal(ip.ratio(), 0.625, "ratio()");

});

////////////////////////////////////////////////////////////////////////////////

QUnit.test("Verify window.devicePixelRatio is pulled in", function(assert) {

	// The other tests force an override to ensure the math works regardless of
	// the browser being tested. This one just makes sure the data is loaded
	// normally.

  ///////////
  // Given

  var ip = new ImgTagBuilder({});

  //////////
  // Then

  assert.equal(ip._devicePixelRatio, window.devicePixelRatio, "_devicePixelRatio");

});

////////////////////////////////////////////////////////////////////////////////

QUnit.test("Pick the larger of two config options (in decending order) based on innerWidth", function(assert) {

  //////////
  // Given

  var breakAlpha = { minViewportWidth: 900, maxImageDisplayWidth: 800, quality: 85 };
  var breakBravo = { minViewportWidth: 0, maxImageDisplayWidth: 400, quality: 85 };

  var ip = new ImgTagBuilder({ styles: { main: { breakPoints: [ breakAlpha, breakBravo ] } } });

  //////////
  // When

  ip._devicePixelRatio = 2; // Force to '2' so testing works across devices.
  ip.innerWidth = 1000; // Force for testing regardless of device.

  ip.prep({ image: "horses.jpg", alt: "some horses",  style: "main", maxWidth: 1600, maxHeight: 1000 });

  //////////
  // Then

  // This is the key requirement. Everything else supports it.
  assert.equal(ip.imgTag(),'', "Target `img` tag");

});

<commit_msg>Corrected "_innerWidth" in test3 and added test4 for the second breakpoint.<commit_after>////////////////////////////////////////////////////////////////////////////////

QUnit.test("2x high-res image call.", function(assert) {

  //////////
  // Given

  var ip = new ImgTagBuilder({ styles: { main: { breakPoints: [ { minViewportWidth: 0, maxImageDisplayWidth: 800, quality: 85 } ] } } });

  //////////
  // When

  ip._devicePixelRatio = 2; // Force to '2' so testing works across devices.
  ip.innerWidth = 1000; // Force for testing regardless of device.

  ip.prep({ image: "horses.jpg", alt: "some horses",  style: "main", maxWidth: 1600, maxHeight: 1000 });

  //////////
  // Then

  // This is the key requirement. Everything else supports it.
  assert.equal(ip.imgTag(),'', "Target `img` tag.");

  // Verify config details are ingested.
  assert.equal(ip._alt, "some horses", "_alt");
  assert.equal(ip._image, "horses.jpg", "_image");
  assert.equal(ip._maxHeight, 1000, "_maxHeight");
  assert.equal(ip._maxWidth, 1600, "_maxWidth");
  assert.equal(ip._devicePixelRatio, 2, "_devidePixelRatio");
  assert.equal(ip._style, "main", "_style");

  // TODO: Figure out how to move this out so it's called dynamically.
  assert.equal(ip._config.styles['main']['breakPoints'][0]['maxImageDisplayWidth'], 800, "maxImageDisplayWidth");

  // Method verification
  assert.equal(ip.callHeight(), 1000, "callHeight()");
  assert.equal(ip.callWidth(), 1600, "callWidth()");
  assert.equal(ip.displayHeight(), 500, "displayHeight()");
  assert.equal(ip.displayWidth(), 800, "displayWidth()");
  assert.equal(ip.url(),'http://res.cloudinary.com/demo/image/upload/c_fill,q_85,w_1600,h_1000/horses.jpg', "url()");
  assert.equal(ip.quality(), 85, "quality()");
  assert.equal(ip.ratio(), 0.625, "ratio()");

});

////////////////////////////////////////////////////////////////////////////////

QUnit.test("Verify window.devicePixelRatio is pulled in", function(assert) {

	// The other tests force an override to ensure the math works regardless of
	// the browser being tested. This one just makes sure the data is loaded
	// normally.

  ///////////
  // Given

  var ip = new ImgTagBuilder({});

  //////////
  // Then

  assert.equal(ip._devicePixelRatio, window.devicePixelRatio, "_devicePixelRatio");

});

////////////////////////////////////////////////////////////////////////////////

QUnit.test("Pick the larger of two config options (in decending order) based on innerWidth", function(assert) {

  //////////
  // Given

  var breakAlpha = { minViewportWidth: 900, maxImageDisplayWidth: 800, quality: 85 };
  var breakBravo = { minViewportWidth: 0, maxImageDisplayWidth: 400, quality: 85 };

  var ip = new ImgTagBuilder({ styles: { main: { breakPoints: [ breakAlpha, breakBravo ] } } });

  //////////
  // When

  ip._devicePixelRatio = 2; // Force to '2' so testing works across devices.
  ip._innerWidth = 1000; // Force for testing regardless of device.

  ip.prep({ image: "horses.jpg", alt: "some horses",  style: "main", maxWidth: 1600, maxHeight: 1000 });

  //////////
  // Then

  // This is the key requirement. Everything else supports it.
  assert.equal(ip.imgTag(),'', "Target `img` tag");

});

////////////////////////////////////////////////////////////////////////////////

QUnit.test("Pick the smaller of two config options (in decending order) based on innerWidth", function(assert) {

  //////////
  // Given

  var breakAlpha = { minViewportWidth: 900, maxImageDisplayWidth: 800, quality: 85 };
  var breakBravo = { minViewportWidth: 0, maxImageDisplayWidth: 400, quality: 85 };

  var ip = new ImgTagBuilder({ styles: { main: { breakPoints: [ breakAlpha, breakBravo ] } } });

  //////////
  // When

  ip._devicePixelRatio = 2; // Force to '2' so testing works across devices.
  ip._innerWidth = 700; // Force for testing regardless of device.

  ip.prep({ image: "horses.jpg", alt: "some horses",  style: "main", maxWidth: 1600, maxHeight: 1000 });

  //////////
  // Then

  // This is the key requirement. Everything else supports it.
  assert.equal(ip.imgTag(),'', "Target `img` tag");

});

<|endoftext|>