<commit_before>tm.main(function() {
    var app = tm.hybrid.Application("#canvas2d", "#canvas3d");
    app.resize(640, 960).fitWindow().run();
    app.enableStats();

    app.replaceScene(tm.game.LoadingScene({
        width: 640, height: 960,
        assets: {
            hiyoko: "assets/hiyoco_nomal_full.png",
            bgm: "assets/smile.mp3",

            //urlをモデルデータ、モーションデータのの順に指定
            miku: {
                type: "mmd",
                url: ["pmd/miku_v2.pmd", "vmd/wavefile_v2.vmd"],
            },
        },
        nextScene: MikuOnStage,
    }));
});

tm.define("MikuOnStage", {
    superClass: "tm.hybrid.Scene", // tm.app.Sceneの3D向け拡張
    init: function() {
        this.superInit();

        // カメラ調整
        this.camera.setPosition(0, 20, 30);
        this.camera.lookAt(new THREE.Vector3(0, 10, 0));

        // ライトを動かす
        this.directionalLight.setPosition(0, 100, -80);

        // メッシュを表示する
        var miku = tm.hybrid.Mesh("miku")
            .addChildTo(this)
            .setPosition(0, 0, 0)
            .on("enterframe", function() {
                if (this.rolling) this.rotationY += 10; // Y軸回転
            });
        miku.rolling = false;

        // 2Dスプライトとの併用も可能
        var hiyoko = tm.display.Sprite("hiyoko", 32, 32)
            .setScale(4)
            .setFrameIndex(0)
//            .addChildTo(this)
            .on("enterframe", function() {
                this.x += this.vx * 10;
                this.y += this.vy * 10;
                if (this.x < 0 || 640 < this.x) this.vx *= -1;
                if (this.y < 0 || 960 < this.y) this.vy *= -1;

                this.frameIndex = (this.frameIndex + 1) % 4;
                this.rotation += 2;
            });
        hiyoko.vx = 1;
        hiyoko.vy = 1;

        var btn = tm.ui.FlatButton({ text: "スタート" })
            .setPosition(320, 960*0.5)
            .addChildTo(this)
            .on("push", function() {
                btn.visible = false;
            }.bind(this));

        this.bgm = tm.asset.AssetManager.get("bgm");
        THREE.AnimationHandler.update(0);

        this.start = false;

        this.time = 0;
    },
    update: function(app) {
        if (!this.start) return;
        var t = this.bgm.context.currentTime;
        var delta = t - this.beforeTime;
        THREE.AnimationHandler.update(app.deltaTime/1000);
        this.beforeTime = t;
    },
    ontouchstart: function(e) {
        if (!this.start) {
            tm.sound.WebAudio.unlock();
            this.bgm.context.currentTime = 0;
            this.bgm.play();
            this.start = true;
            this.beforeTime = 0;
        }
    },
});
<commit_msg>60 frame per second<commit_after>tm.main(function() {
    var app = tm.hybrid.Application("#canvas2d", "#canvas3d");
    app.fps = 60;
    app.resize(640, 960).fitWindow().run();
    app.enableStats();

    app.replaceScene(tm.game.LoadingScene({
        width: 640, height: 960,
        assets: {
            hiyoko: "assets/hiyoco_nomal_full.png",
            bgm: "assets/smile.mp3",

            //urlをモデルデータ、モーションデータのの順に指定
            miku: {
                type: "mmd",
                url: ["pmd/miku_v2.pmd", "vmd/wavefile_v2.vmd"],
            },
        },
        nextScene: MikuOnStage,
    }));
});

tm.define("MikuOnStage", {
    superClass: "tm.hybrid.Scene", // tm.app.Sceneの3D向け拡張
    init: function() {
        this.superInit();

        // カメラ調整
        this.camera.setPosition(0, 20, 30);
        this.camera.lookAt(new THREE.Vector3(0, 10, 0));

        // ライトを動かす
        this.directionalLight.setPosition(0, 100, -80);

        // メッシュを表示する
        var miku = tm.hybrid.Mesh("miku")
            .addChildTo(this)
            .setPosition(0, 0, 0)
            .on("enterframe", function() {
                if (this.rolling) this.rotationY += 10; // Y軸回転
            });
        miku.rolling = false;

        // 2Dスプライトとの併用も可能
        var hiyoko = tm.display.Sprite("hiyoko", 32, 32)
            .setScale(4)
            .setFrameIndex(0)
//            .addChildTo(this)
            .on("enterframe", function() {
                this.x += this.vx * 10;
                this.y += this.vy * 10;
                if (this.x < 0 || 640 < this.x) this.vx *= -1;
                if (this.y < 0 || 960 < this.y) this.vy *= -1;

                this.frameIndex = (this.frameIndex + 1) % 4;
                this.rotation += 2;
            });
        hiyoko.vx = 1;
        hiyoko.vy = 1;

        var btn = tm.ui.FlatButton({ text: "スタート" })
            .setPosition(320, 960*0.5)
            .addChildTo(this)
            .on("push", function() {
                btn.visible = false;
            }.bind(this));

        this.bgm = tm.asset.AssetManager.get("bgm");
        THREE.AnimationHandler.update(0);

        this.start = false;

        this.time = 0;
    },
    update: function(app) {
        if (!this.start) return;
        var t = this.bgm.context.currentTime;
        var delta = t - this.beforeTime;
        THREE.AnimationHandler.update(app.deltaTime/1000);
        this.beforeTime = t;
    },
    ontouchstart: function(e) {
        if (!this.start) {
            tm.sound.WebAudio.unlock();
            this.bgm.context.currentTime = 0;
            this.bgm.play();
            this.start = true;
            this.beforeTime = 0;
        }
    },
});
<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, eqeq: true, devel: true, nomen: true,  regexp: true, indent: 4 */
/*global define, brackets, $, Mustache, document, window */

define(function (require, exports, module) {
	"use strict";

	var ExtensionUtils		= brackets.getModule('utils/ExtensionUtils'),
		AppInit				= brackets.getModule('utils/AppInit'),
		PreferencesManager	= brackets.getModule('preferences/PreferencesManager'),
		CommandManager		= brackets.getModule('command/CommandManager'),
		Dialogs				= brackets.getModule('widgets/Dialogs'),
		Menus				= brackets.getModule('command/Menus'),
		Trello				= require('Trello'),
		strings				= require('i18n!nls/strings');

	var mainPanel			= require('text!html/mainPanel.html'),
		prefDialogHTML		= require('text!html/prefsDialog.html'),
		newBoardHTML		= require('text!html/newBoard.html'),
		newListHTML			= require('text!html/newList.html'),
		boardsTemplate		= require('text!html/boardsTemplate.html'),
		listsTemplate		= require('text!html/listsTemplate.html'),
		cardsTemplate		= require('text!html/cardsTemplate.html'),
		tasksTemplate		= require('text!html/tasksTemplate.html'),
		errorTemplate		= require('text!html/errorTemplate.html');

	// Extension Info.
	var _ExtensionID		= 'brackets-trello',
		_ExtensionLabel		= 'Brackets Trello',
		_ExtensionShortcut	= 'Alt-B';

	// Define preferences.
	var _prefs = PreferencesManager.getExtensionPrefs('brackets-trello');
	_prefs.definePreference('width', 'integer', 260);
	_prefs.definePreference('apitoken', 'string', '');
	_prefs.definePreference('autosynctime', 'integer', 0);
	_prefs.definePreference('storagepref', 'boolean', false);
	_prefs.definePreference('selected-board', 'string', '');
	_prefs.definePreference('selected-board-name', 'string', '');
	_prefs.definePreference('selected-list', 'string', '');
	_prefs.definePreference('selected-list-name', 'string', '');
	_prefs.definePreference('selected-card', 'string', '');

	// Prefs that will be saved in .brackets.json
	var _projectPrefs = ['selected-board', 'selected-board-name', 'selected-list', 'selected-list-name', 'selected-card'];

	var realVisibility, isVisible, isMenuVisible, autoSyncIntervalId, $icon, $panel;

	function _toggleAddMenu() {
		var $menu = $('.add-menu', $panel);
		if (!isMenuVisible) {
			$menu.show();
			isMenuVisible = true;
			return;
		}
		$menu.hide();
		isMenuVisible = false;
	}

	function _savePrefs(name, value) {
		if (_prefs.get('storagepref') && _projectPrefs.indexOf(name) >= 0) {
			return _prefs.set(name, value, {
				location: {
					scope: 'project'
				}
			});
		}
		return _prefs.set(name, value);
	}

	function _openPreferencesDialog() {
		var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(prefDialogHTML, strings)),
			$dialog	= dialog.getElement(),
			tempPrefs = {};

		$dialog.find('.trello-api-token').val(_prefs.get('apitoken')).on('change', function (e) {
			tempPrefs.apitoken = $(this).val();
		});
		$dialog.find('.autosync-time').val(_prefs.get('autosynctime')).on('change', function (e) {
			tempPrefs.autosynctime = $(this).val();
		});
		$dialog.find('.storage-pref').attr('checked', _prefs.get('storagepref')).on('change', function(e) {
			tempPrefs.storagepref = e.target.checked;
		});

		dialog.done(function (id) {
			if (id === 'save') {
				for (var i in tempPrefs) {
					_savePrefs(i, tempPrefs[i]);
				}
				// Reset AutoSync
				_initAutoSync(false);
				_initAutoSync(true);
			}
			if (!isVisible && _prefs.get('apitoken')) {
				_toggleVisibility();
			}
		});
	}

	function _initAutoSync(init) {
		if (init && _prefs.get('autosynctime') >= 1) {
			autoSyncIntervalId = window.setInterval(_initSync, _prefs.get('autosynctime') * 1000);
			return;
		}
		window.clearInterval(autoSyncIntervalId);
	}

	function _initSync() {
		console.log('Syncing....', Math.ceil(Math.random() * 10));
	}

	function _openNewBoardDialog() {
		var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(newBoardHTML, strings)),
			$dialog = dialog.getElement();

		dialog.done(function(id) {
			if (id === 'save') {
				Trello._createNewBoard($dialog.find('.board-name').val());
			}
		});
	}

	function _openNewListDialog() {
		var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(newListHTML, strings)),
			$dialog = dialog.getElement();

		dialog.done(function(id) {
			if (id === 'save') {
				Trello._createNewList($dialog.find('.list-name').val());
			}
		});
	}

	function _openNewCardDialog() {

	}

	function _openNewTasksDialog() {

	}

	/**
	 * Event Controldd
	 *
	 * @param {Object} $panel
	 */
	function _panelEventController($panel) {
		// Resizer
		var pageX, width;
		$('.horz-resizer', $panel).mousedown(function(e) {
			pageX = e.pageX;
			width = $panel.width();

			$(document).mousemove(function(e) {
				$panel.width(width - (e.pageX - pageX));
			}).mouseup(function() {
				$(document).off('mousemove').off('mouseup');
				_savePrefs('width', $panel.width());
			});
		}).dblclick(function() {
			_toggleVisibility();
		});

		// Hide on escape
		$(document).keydown(function(e) {
			if (e.which === 27 && isVisible)
				_toggleVisibility();
		});

		// Hide on click
		$(document).click(function() {
			if (isMenuVisible) _toggleAddMenu();
		});

		// Show/Hide Add Dropdown Menu
		$('.btn-add', $panel).click(function(e) {
			e.stopPropagation();
			_toggleAddMenu();
		});
		$('.btn-prefs', $panel).click(_openPreferencesDialog);
		$('.btn-sync', $panel).click(_initSync);

		// Add Menu Item
		$('.cmd-new-board', $panel).click(_openNewBoardDialog);
		$('.cmd-new-list', $panel).click(_openNewListDialog);
		$('.cmd-new-card', $panel).click(_openNewCardDialog);
		$('.cmd-new-tasks', $panel).click(_openNewTasksDialog);

		// Button Actions
		$('.btn-boards', $panel).click(_displayBoards);
		$('.btn-lists', $panel).click(_displayLists);
		$('.btn-tasks', $panel).click(_displayTasks);

		// Trello Content Listeners
		// Board Name
		$panel.on('click', '.board-item', function () {
			_savePrefs('selected-board', $(this).attr('id'));
			_displayLists();
		});

		// List Name
		$panel.on('click', '.list-item', function() {
			_savePrefs('selected-list', $(this).attr('id'));
			_displayCards(this);
		});

		// Card Name
		$panel.on('click', '.card-item', function() {
			_savePrefs('selected-card', $(this).attr('id'));
			_displayTasks();
		});
	}

	function _setButtonActive(button) {
		$('.btn', $panel).each(function() {
			$(this).removeClass('active');
		});
		$('.tab', $panel).each(function() {
			$(this).hide();
		});
		$(button).addClass('active');
	}

	function _displayBoards() {
		Trello._getUserBoards().done(function(data) {
			_setButtonActive($panel.find('.btn-boards'));
			$('.tab-boards', $panel).empty().show().append(Mustache.render(boardsTemplate, data));
		})
		.fail(_displayError);
	}

	function _displayLists() {
		Trello._getBoardLists().done(function(data) {
			_savePrefs('selected-board-name', data.name);
			_setButtonActive($panel.find('.btn-lists'));
			$('.tab-lists', $panel).empty().show().append(Mustache.render(listsTemplate, data));
		})
		.fail(_displayError);
	}

	function _displayCards(elem) {
		Trello._getListCards().done(function(data) {
			_savePrefs('selected-list-name', data.listName);
			_toggleCardsInline(elem, Mustache.render(cardsTemplate, data));
		})
		.fail(_displayError);
	}

	function _displayTasks() {
		Trello._getCardTasks().done(function(data) {
			_setButtonActive($panel.find('.btn-tasks'));
			$('.tab-tasks', $panel).empty().show().append(Mustache.render(tasksTemplate, data));
			data.tasks.forEach(function(task) {
				$('#' + task.id).attr('checked', task.checked);
			});
		})
		.fail(_displayError);
	}

	function _displayError(error) {
		_setButtonActive(null);
		$('.tab-error', $panel).empty().show().append(Mustache.render(errorTemplate, { error: error }));
	}

	function _toggleCardsInline(elem, data) {
		$('.card-space', $panel).each(function() {
			$(this).hide();
		});
		$(elem).find('.card-space').empty().show().append(data);
	}

	function _displaySpinner(visible) {
		if (visible) {}
	}

	// Toggle Panel Visibility
	function _toggleVisibility() {
		if (!isVisible && !realVisibility) {
			realVisibility = true;
			$panel = $(Mustache.render(mainPanel, strings)).width(_prefs.get('width'));
			_panelEventController($panel);
			$('#editor-holder').append($panel);
			CommandManager.get(_ExtensionID).setChecked(true);
			$icon.addClass('active');

			if (_prefs.get('selected-board')) {
				_displayLists();
			} else {
				_displayBoards();
			}

			_initAutoSync(true);
		} else if (!isVisible && realVisibility) {
			CommandManager.get(_ExtensionID).setChecked(true);
			$panel.show();
			$icon.addClass('active');
			_initAutoSync(true);
		} else {
			CommandManager.get(_ExtensionID).setChecked(false);
			$panel.hide();
			$icon.removeClass('active');
			_initAutoSync(false);
		}
		isVisible = !isVisible;
	}

	function _Main() {
		if (!_prefs.get('apitoken') && !isVisible) {
			_openPreferencesDialog();
			return;
		}
		_toggleVisibility();
	}

	AppInit.appReady(function () {
		ExtensionUtils.loadStyleSheet(module, 'styles/styles.css');
		var navigateMenu = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU);
		CommandManager.register(_ExtensionLabel, _ExtensionID, _Main);
		navigateMenu.addMenuItem(_ExtensionID, _ExtensionShortcut);
	});

	$icon = $('<a>').attr({
		id: 'brackets-trello-icon',
		href: '#',
		title: 'Brackets Trello'
	}).click(_Main).appendTo($('#main-toolbar .buttons'));
});<commit_msg>Removed a typo<commit_after>/*jslint vars: true, plusplus: true, eqeq: true, devel: true, nomen: true,  regexp: true, indent: 4 */
/*global define, brackets, $, Mustache, document, window */

define(function (require, exports, module) {
	"use strict";

	var ExtensionUtils		= brackets.getModule('utils/ExtensionUtils'),
		AppInit				= brackets.getModule('utils/AppInit'),
		PreferencesManager	= brackets.getModule('preferences/PreferencesManager'),
		CommandManager		= brackets.getModule('command/CommandManager'),
		Dialogs				= brackets.getModule('widgets/Dialogs'),
		Menus				= brackets.getModule('command/Menus'),
		Trello				= require('Trello'),
		strings				= require('i18n!nls/strings');

	var mainPanel			= require('text!html/mainPanel.html'),
		prefDialogHTML		= require('text!html/prefsDialog.html'),
		newBoardHTML		= require('text!html/newBoard.html'),
		newListHTML			= require('text!html/newList.html'),
		boardsTemplate		= require('text!html/boardsTemplate.html'),
		listsTemplate		= require('text!html/listsTemplate.html'),
		cardsTemplate		= require('text!html/cardsTemplate.html'),
		tasksTemplate		= require('text!html/tasksTemplate.html'),
		errorTemplate		= require('text!html/errorTemplate.html');

	// Extension Info.
	var _ExtensionID		= 'brackets-trello',
		_ExtensionLabel		= 'Brackets Trello',
		_ExtensionShortcut	= 'Alt-B';

	// Define preferences.
	var _prefs = PreferencesManager.getExtensionPrefs('brackets-trello');
	_prefs.definePreference('width', 'integer', 260);
	_prefs.definePreference('apitoken', 'string', '');
	_prefs.definePreference('autosynctime', 'integer', 0);
	_prefs.definePreference('storagepref', 'boolean', false);
	_prefs.definePreference('selected-board', 'string', '');
	_prefs.definePreference('selected-board-name', 'string', '');
	_prefs.definePreference('selected-list', 'string', '');
	_prefs.definePreference('selected-list-name', 'string', '');
	_prefs.definePreference('selected-card', 'string', '');

	// Prefs that will be saved in .brackets.json
	var _projectPrefs = ['selected-board', 'selected-board-name', 'selected-list', 'selected-list-name', 'selected-card'];

	var realVisibility, isVisible, isMenuVisible, autoSyncIntervalId, $icon, $panel;

	function _toggleAddMenu() {
		var $menu = $('.add-menu', $panel);
		if (!isMenuVisible) {
			$menu.show();
			isMenuVisible = true;
			return;
		}
		$menu.hide();
		isMenuVisible = false;
	}

	function _savePrefs(name, value) {
		if (_prefs.get('storagepref') && _projectPrefs.indexOf(name) >= 0) {
			return _prefs.set(name, value, {
				location: {
					scope: 'project'
				}
			});
		}
		return _prefs.set(name, value);
	}

	function _openPreferencesDialog() {
		var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(prefDialogHTML, strings)),
			$dialog	= dialog.getElement(),
			tempPrefs = {};

		$dialog.find('.trello-api-token').val(_prefs.get('apitoken')).on('change', function (e) {
			tempPrefs.apitoken = $(this).val();
		});
		$dialog.find('.autosync-time').val(_prefs.get('autosynctime')).on('change', function (e) {
			tempPrefs.autosynctime = $(this).val();
		});
		$dialog.find('.storage-pref').attr('checked', _prefs.get('storagepref')).on('change', function(e) {
			tempPrefs.storagepref = e.target.checked;
		});

		dialog.done(function (id) {
			if (id === 'save') {
				for (var i in tempPrefs) {
					_savePrefs(i, tempPrefs[i]);
				}
				// Reset AutoSync
				_initAutoSync(false);
				_initAutoSync(true);
			}
			if (!isVisible && _prefs.get('apitoken')) {
				_toggleVisibility();
			}
		});
	}

	function _initAutoSync(init) {
		if (init && _prefs.get('autosynctime') >= 1) {
			autoSyncIntervalId = window.setInterval(_initSync, _prefs.get('autosynctime') * 1000);
			return;
		}
		window.clearInterval(autoSyncIntervalId);
	}

	function _initSync() {
		console.log('Syncing....', Math.ceil(Math.random() * 10));
	}

	function _openNewBoardDialog() {
		var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(newBoardHTML, strings)),
			$dialog = dialog.getElement();

		dialog.done(function(id) {
			if (id === 'save') {
				Trello._createNewBoard($dialog.find('.board-name').val());
			}
		});
	}

	function _openNewListDialog() {
		var dialog = Dialogs.showModalDialogUsingTemplate(Mustache.render(newListHTML, strings)),
			$dialog = dialog.getElement();

		dialog.done(function(id) {
			if (id === 'save') {
				Trello._createNewList($dialog.find('.list-name').val());
			}
		});
	}

	function _openNewCardDialog() {

	}

	function _openNewTasksDialog() {

	}

	/**
	 * Event Controldd
	 *
	 * @param {Object} $panel
	 */
	function _panelEventController($panel) {
		// Resizer
		var pageX, width;
		$('.horz-resizer', $panel).mousedown(function(e) {
			pageX = e.pageX;
			width = $panel.width();

			$(document).mousemove(function(e) {
				$panel.width(width - (e.pageX - pageX));
			}).mouseup(function() {
				$(document).off('mousemove').off('mouseup');
				_savePrefs('width', $panel.width());
			});
		}).dblclick(function() {
			_toggleVisibility();
		});

		// Hide on escape
		$(document).keydown(function(e) {
			if (e.which === 27 && isVisible)
				_toggleVisibility();
		});

		// Hide on click
		$(document).click(function() {
			if (isMenuVisible) _toggleAddMenu();
		});

		// Show/Hide Add Dropdown Menu
		$('.btn-add', $panel).click(function(e) {
			e.stopPropagation();
			_toggleAddMenu();
		});
		$('.btn-prefs', $panel).click(_openPreferencesDialog);
		$('.btn-sync', $panel).click(_initSync);

		// Add Menu Item
		$('.cmd-new-board', $panel).click(_openNewBoardDialog);
		$('.cmd-new-list', $panel).click(_openNewListDialog);
		$('.cmd-new-card', $panel).click(_openNewCardDialog);
		$('.cmd-new-tasks', $panel).click(_openNewTasksDialog);

		// Button Actions
		$('.btn-boards', $panel).click(_displayBoards);
		$('.btn-lists', $panel).click(_displayLists);
		$('.btn-tasks', $panel).click(_displayTasks);

		// Trello Content Listeners
		// Board Name
		$panel.on('click', '.board-item', function () {
			_savePrefs('selected-board', $(this).attr('id'));
			_displayLists();
		});

		// List Name
		$panel.on('click', '.list-item', function() {
			_savePrefs('selected-list', $(this).attr('id'));
			_displayCards(this);
		});

		// Card Name
		$panel.on('click', '.card-item', function() {
			_savePrefs('selected-card', $(this).attr('id'));
			_displayTasks();
		});
	}

	function _setButtonActive(button) {
		$('.btn', $panel).each(function() {
			$(this).removeClass('active');
		});
		$('.tab', $panel).each(function() {
			$(this).hide();
		});
		$(button).addClass('active');
	}

	function _displayBoards() {
		Trello._getUserBoards().done(function(data) {
			_setButtonActive($panel.find('.btn-boards'));
			$('.tab-boards', $panel).empty().show().append(Mustache.render(boardsTemplate, data));
		})
		.fail(_displayError);
	}

	function _displayLists() {
		Trello._getBoardLists().done(function(data) {
			_savePrefs('selected-board-name', data.name);
			_setButtonActive($panel.find('.btn-lists'));
			$('.tab-lists', $panel).empty().show().append(Mustache.render(listsTemplate, data));
		})
		.fail(_displayError);
	}

	function _displayCards(elem) {
		Trello._getListCards().done(function(data) {
			_savePrefs('selected-list-name', data.listName);
			_toggleCardsInline(elem, Mustache.render(cardsTemplate, data));
		})
		.fail(_displayError);
	}

	function _displayTasks() {
		Trello._getCardTasks().done(function(data) {
			_setButtonActive($panel.find('.btn-tasks'));
			$('.tab-tasks', $panel).empty().show().append(Mustache.render(tasksTemplate, data));
			data.tasks.forEach(function(task) {
				$('#' + task.id).attr('checked', task.checked);
			});
		})
		.fail(_displayError);
	}

	function _displayError(error) {
		_setButtonActive(null);
		$('.tab-error', $panel).empty().show().append(Mustache.render(errorTemplate, { error: error }));
	}

	function _toggleCardsInline(elem, data) {
		$('.card-space', $panel).each(function() {
			$(this).hide();
		});
		$(elem).find('.card-space').empty().show().append(data);
	}

	function _displaySpinner(visible) {
		if (visible) {}
	}

	// Toggle Panel Visibility
	function _toggleVisibility() {
		if (!isVisible && !realVisibility) {
			realVisibility = true;
			$panel = $(Mustache.render(mainPanel, strings)).width(_prefs.get('width'));
			_panelEventController($panel);
			$('#editor-holder').append($panel);
			CommandManager.get(_ExtensionID).setChecked(true);
			$icon.addClass('active');

			if (_prefs.get('selected-board')) {
				_displayLists();
			} else {
				_displayBoards();
			}

			_initAutoSync(true);
		} else if (!isVisible && realVisibility) {
			CommandManager.get(_ExtensionID).setChecked(true);
			$panel.show();
			$icon.addClass('active');
			_initAutoSync(true);
		} else {
			CommandManager.get(_ExtensionID).setChecked(false);
			$panel.hide();
			$icon.removeClass('active');
			_initAutoSync(false);
		}
		isVisible = !isVisible;
	}

	function _Main() {
		if (!_prefs.get('apitoken') && !isVisible) {
			_openPreferencesDialog();
			return;
		}
		_toggleVisibility();
	}

	AppInit.appReady(function () {
		ExtensionUtils.loadStyleSheet(module, 'styles/styles.css');
		var viewMenu = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU);
		CommandManager.register(_ExtensionLabel, _ExtensionID, _Main);
		navigateMenu.addMenuItem(_ExtensionID, _ExtensionShortcut);
	});

	$icon = $('<a>').attr({
		id: 'brackets-trello-icon',
		href: '#',
		title: 'Brackets Trello'
	}).click(_Main).appendTo($('#main-toolbar .buttons'));
});<|endoftext|>


<commit_before>import { navigator, window, document } from 'global';
import React from 'react';
import ReactDOM from 'react-dom';
import deprecate from 'util-deprecate';
import AnsiToHtml from 'ansi-to-html';

import addons from '@storybook/addons';
import createChannel from '@storybook/channel-postmessage';
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import { toId, storyNameFromExport, isExportStory } from '@storybook/csf';
import { logger } from '@storybook/client-logger';
import Events from '@storybook/core-events';

import { initializePath, setPath } from './url';
import { NoDocs } from './NoDocs';

const ansiConverter = new AnsiToHtml({
  escapeXML: true,
});

const classes = {
  MAIN: 'sb-show-main',
  NOPREVIEW: 'sb-show-nopreview',
  ERROR: 'sb-show-errordisplay',
};

function showMain() {
  document.body.classList.remove(classes.NOPREVIEW);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.MAIN);
}

function showNopreview() {
  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.NOPREVIEW);
}

function showErrorDisplay({ message = '', stack = '' }) {
  document.getElementById('error-message').innerHTML = ansiConverter.toHtml(message);
  document.getElementById('error-stack').innerHTML = ansiConverter.toHtml(stack);

  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.NOPREVIEW);

  document.body.classList.add(classes.ERROR);
}

// showError is used by the various app layers to inform the user they have done something
// wrong -- for instance returned the wrong thing from a story
function showError({ title, description }) {
  addons.getChannel().emit(Events.STORY_ERRORED, { title, description });
  showErrorDisplay({
    message: title,
    stack: description,
  });
}

// showException is used if we fail to render the story and it is uncaught by the app layer
function showException(exception) {
  addons.getChannel().emit(Events.STORY_THREW_EXCEPTION, exception);
  showErrorDisplay(exception);

  // Log the stack to the console. So, user could check the source code.
  logger.error(exception);
}

const isBrowser =
  navigator &&
  navigator.userAgent &&
  navigator.userAgent !== 'storyshots' &&
  !(navigator.userAgent.indexOf('Node.js') > -1) &&
  !(navigator.userAgent.indexOf('jsdom') > -1);

export const getContext = (() => {
  let cache;
  return decorateStory => {
    if (cache) {
      return cache;
    }
    let channel = null;
    if (isBrowser) {
      try {
        channel = addons.getChannel();
      } catch (e) {
        channel = createChannel({ page: 'preview' });
        addons.setChannel(channel);
      }
    }
    let storyStore;
    let clientApi;
    if (typeof window !== 'undefined' && window.__STORYBOOK_CLIENT_API__) {
      clientApi = window.__STORYBOOK_CLIENT_API__;
      // eslint-disable-next-line no-underscore-dangle
      storyStore = clientApi._storyStore;
    } else {
      storyStore = new StoryStore({ channel });
      clientApi = new ClientApi({ storyStore, decorateStory });
    }
    const { clearDecorators } = clientApi;
    const configApi = new ConfigApi({ clearDecorators, storyStore, channel, clientApi });

    return {
      configApi,
      storyStore,
      channel,
      clientApi,
      showMain,
      showError,
      showException,
    };
  };
})();

function focusInInput(event) {
  return (
    /input|textarea/i.test(event.target.tagName) ||
    event.target.getAttribute('contenteditable') !== null
  );
}

let previousStyles;
const applyLayout = (layout, ctx) => {
  const layouts = {
    centered: `
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      margin: 0;
      padding: 1rem;
      box-sizing: border-box;
    `,
    fullscreen: `
      margin: 0;
    `,
    padded: `
      margin: 0;
      padding: 1rem;
    `,
  };
  const styles = layouts[typeof layout === 'function' ? layout(ctx) : layout] || layouts.padded;
  if (styles !== previousStyles) {
    document.body.style = styles;
    previousStyles = styles;
  }
};

export default function start(render, { decorateStory } = {}) {
  const context = getContext(decorateStory);

  const { clientApi, channel, configApi, storyStore } = context;
  // Provide access to external scripts if `window` is defined.
  // NOTE this is different to isBrowser, primarily for the JSDOM use case
  let previousKind = '';
  let previousStory = '';
  let previousRevision = -1;
  let previousViewMode = '';
  let previousId = null;

  const renderMain = forceRender => {
    const revision = storyStore.getRevision();
    const loadError = storyStore.getError();
    const { storyId, viewMode: urlViewMode } = storyStore.getSelection();

    const data = storyStore.fromId(storyId);

    const { kind, name, getDecorated, id, parameters = {}, error } = data || {};

    const { docsOnly, layout } = parameters;
    applyLayout(layout, data);

    const viewMode = docsOnly ? 'docs' : urlViewMode;

    const renderContext = {
      ...context,
      ...data,
      selectedKind: kind,
      selectedStory: name,
      parameters,
      forceRender,
    };

    if (loadError || error) {
      showErrorDisplay(loadError || error);
      return;
    }

    // Render story only if selectedKind or selectedStory have changed.
    // However, we DO want the story to re-render if the store itself has changed
    // (which happens at the moment when HMR occurs)
    if (
      !forceRender &&
      revision === previousRevision &&
      viewMode === previousViewMode &&
      kind === previousKind &&
      name === previousStory
    ) {
      addons.getChannel().emit(Events.STORY_UNCHANGED, {
        id,
        revision,
        kind,
        name,
        viewMode,
      });
      return;
    }

    if (!forceRender && previousKind && previousStory && revision === previousRevision) {
      addons.getChannel().emit(Events.STORY_CHANGED, id);
    }

    switch (previousViewMode) {
      case 'docs':
        if (previousKind != null && (kind !== previousKind || viewMode !== previousViewMode)) {
          storyStore.cleanHooksForKind(previousKind);
          ReactDOM.unmountComponentAtNode(document.getElementById('docs-root'));
        }
        break;
      case 'story':
      default:
        if (previousId != null && (id !== previousId || viewMode !== previousViewMode)) {
          storyStore.cleanHooks(previousId);
          ReactDOM.unmountComponentAtNode(document.getElementById('root'));
        }
    }

    // Docs view renders into a different root ID to avoid conflicts
    // with the user's view layer. Therefore we need to clean up whenever
    // we transition between view modes
    if (viewMode !== previousViewMode) {
      switch (viewMode) {
        case 'docs': {
          showMain();
          document.getElementById('root').setAttribute('hidden', true);
          document.getElementById('docs-root').removeAttribute('hidden');
          break;
        }
        case 'story':
        default: {
          if (previousViewMode === 'docs') {
            document.getElementById('docs-root').setAttribute('hidden', true);
            document.getElementById('root').removeAttribute('hidden');
          }
        }
      }
    }
    // Given a cleaned up state, render the appropriate view mode
    switch (viewMode) {
      case 'docs': {
        const docs = (parameters && parameters.docs) || {};
        const DocsContainer = docs.container || (({ children }) => <>{children}</>);
        const Page = docs.page || NoDocs;
        ReactDOM.render(
          <DocsContainer context={renderContext}>
            <Page />
          </DocsContainer>,
          document.getElementById('docs-root'),
          () => addons.getChannel().emit(Events.DOCS_RENDERED, kind)
        );
        break;
      }
      case 'story':
      default: {
        if (getDecorated) {
          (async () => {
            try {
              await render(renderContext);
              addons.getChannel().emit(Events.STORY_RENDERED, id);
            } catch (ex) {
              showException(ex);
            }
          })();
        } else {
          showNopreview();
          addons.getChannel().emit(Events.STORY_MISSING, id);
        }
        break;
      }
    }

    previousRevision = revision;
    previousKind = kind;
    previousStory = name;
    previousViewMode = viewMode;
    previousId = id;

    if (!forceRender && viewMode !== 'docs') {
      document.documentElement.scrollTop = 0;
      document.documentElement.scrollLeft = 0;
    }
  };

  // initialize the UI
  const renderUI = forceRender => {
    if (isBrowser) {
      try {
        renderMain(forceRender);
      } catch (ex) {
        showException(ex);
      }
    }
  };

  const forceReRender = () => renderUI(true);

  // channel can be null in NodeJS
  if (isBrowser) {
    const deprecatedToId = deprecate(
      toId,
      `Passing name+kind to the SET_CURRENT_STORY event is deprecated, use a storyId instead`
    );

    channel.on(Events.FORCE_RE_RENDER, forceReRender);
    channel.on(Events.SET_CURRENT_STORY, ({ storyId: inputStoryId, name, kind, viewMode }) => {
      let storyId = inputStoryId;
      // For backwards compatibility
      if (!storyId) {
        if (!name || !kind) {
          throw new Error('You should pass `storyId` into SET_CURRENT_STORY');
        }
        storyId = deprecatedToId(kind, name);
      }

      storyStore.setSelection({ storyId, viewMode });
      setPath({ storyId, viewMode });
    });

    // Handle keyboard shortcuts
    window.onkeydown = event => {
      if (!focusInInput(event)) {
        // We have to pick off the keys of the event that we need on the other side
        const { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode } = event;
        channel.emit(Events.PREVIEW_KEYDOWN, {
          event: { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode },
        });
      }
    };
  }

  storyStore.on(Events.STORY_INIT, () => {
    const { storyId, viewMode } = initializePath();
    storyStore.setSelection({ storyId, viewMode });
  });

  storyStore.on(Events.STORY_RENDER, renderUI);

  if (typeof window !== 'undefined') {
    window.__STORYBOOK_CLIENT_API__ = clientApi;
    window.__STORYBOOK_STORY_STORE__ = storyStore;
    window.__STORYBOOK_ADDONS_CHANNEL__ = channel; // may not be defined
  }

  let previousExports = new Map();
  const loadStories = (loadable, framework) => () => {
    let reqs = null;
    if (Array.isArray(loadable)) {
      reqs = loadable;
    } else if (loadable.keys) {
      reqs = [loadable];
    }

    let currentExports = new Map();
    if (reqs) {
      reqs.forEach(req => {
        req.keys().forEach(filename => {
          const fileExports = req(filename);
          currentExports.set(
            fileExports,
            typeof req.resolve === 'function' ? req.resolve(filename) : null
          );
        });
      });
    } else {
      const exported = loadable();
      if (Array.isArray(exported) && exported.every(obj => obj.default != null)) {
        currentExports = new Map(exported.map(fileExports => [fileExports, null]));
      } else if (exported) {
        logger.warn(
          `Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(
            exported
          )}`
        );
      }
    }

    const removed = [...previousExports.keys()].filter(exp => !currentExports.has(exp));
    removed.forEach(exp => {
      if (exp.default) {
        storyStore.removeStoryKind(exp.default.title);
      }
    });
    if (removed.length > 0) {
      storyStore.incrementRevision();
    }

    const added = [...currentExports.keys()].filter(exp => !previousExports.has(exp));
    added.forEach(fileExports => {
      // An old-style story file
      if (!fileExports.default) {
        return;
      }

      if (!fileExports.default.title) {
        throw new Error(
          `Unexpected default export without title: ${JSON.stringify(fileExports.default)}`
        );
      }

      const { default: meta, __namedExportsOrder, ...namedExports } = fileExports;
      let exports = namedExports;

      // prefer a user/loader provided `__namedExportsOrder` array if supplied
      // we do this as es module exports are always ordered alphabetically
      // see https://github.com/storybookjs/storybook/issues/9136
      if (Array.isArray(__namedExportsOrder)) {
        exports = {};
        __namedExportsOrder.forEach(name => {
          if (namedExports[name]) {
            exports[name] = namedExports[name];
          }
        });
      }

      const {
        title: kindName,
        id: componentId,
        parameters: params,
        decorators: decos,
        component,
        subcomponents,
      } = meta;
      // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this
      const kind = clientApi.storiesOf(kindName, true);

      // we should always have a framework, rest optional
      kind.addParameters({
        framework,
        component,
        subcomponents,
        fileName: currentExports.get(fileExports),
        ...params,
      });

      (decos || []).forEach(decorator => {
        kind.addDecorator(decorator);
      });

      Object.keys(exports).forEach(key => {
        if (isExportStory(key, meta)) {
          const storyFn = exports[key];
          const { name, parameters, decorators } = storyFn.story || {};
          if (parameters && parameters.decorators) {
            deprecate(() => {},
            `${kindName} => ${name || key}: story.parameters.decorators is deprecated; use story.decorators instead.`)();
          }
          const decoratorParams = decorators ? { decorators } : null;
          const exportName = storyNameFromExport(key);
          const idParams = { __id: toId(componentId || kindName, exportName) };
          kind.add(name || exportName, storyFn, {
            ...parameters,
            ...decoratorParams,
            ...idParams,
          });
        }
      });
    });
    previousExports = currentExports;
  };

  let loaded = false;
  /**
   * Load a collection of stories. If it has a default export, assume that it is a module-style
   * file and process its named exports as stories. If not, assume it's an old-style
   * storiesof file and require it.
   *
   * @param {*} loadable a require.context `req`, an array of `req`s, or a loader function that returns void or an array of exports
   * @param {*} m - ES module object for hot-module-reloading (HMR)
   * @param {*} framework - name of framework in use, e.g. "react"
   */
  const configure = (loadable, m, framework) => {
    if (typeof m === 'string') {
      throw new Error(
        `Invalid module '${m}'. Did you forget to pass \`module\` as the second argument to \`configure\`"?`
      );
    }
    if (m && m.hot && m.hot.dispose) {
      ({ previousExports = new Map() } = m.hot.data || {});

      m.hot.dispose(data => {
        loaded = false;
        // eslint-disable-next-line no-param-reassign
        data.previousExports = previousExports;
      });
    }
    if (loaded) {
      logger.warn('Unexpected loaded state. Did you call `load` twice?');
    }
    loaded = true;
    configApi.configure(loadStories(loadable, framework), m);
  };

  return { configure, context, clientApi, configApi, forceReRender };
}
<commit_msg>FIX linting<commit_after>import { navigator, window, document } from 'global';
import React from 'react';
import ReactDOM from 'react-dom';
import deprecate from 'util-deprecate';
import AnsiToHtml from 'ansi-to-html';

import addons from '@storybook/addons';
import createChannel from '@storybook/channel-postmessage';
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import { toId, storyNameFromExport, isExportStory } from '@storybook/csf';
import { logger } from '@storybook/client-logger';
import Events from '@storybook/core-events';

import { initializePath, setPath } from './url';
import { NoDocs } from './NoDocs';

const ansiConverter = new AnsiToHtml({
  escapeXML: true,
});

const classes = {
  MAIN: 'sb-show-main',
  NOPREVIEW: 'sb-show-nopreview',
  ERROR: 'sb-show-errordisplay',
};

function showMain() {
  document.body.classList.remove(classes.NOPREVIEW);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.MAIN);
}

function showNopreview() {
  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.NOPREVIEW);
}

function showErrorDisplay({ message = '', stack = '' }) {
  document.getElementById('error-message').innerHTML = ansiConverter.toHtml(message);
  document.getElementById('error-stack').innerHTML = ansiConverter.toHtml(stack);

  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.NOPREVIEW);

  document.body.classList.add(classes.ERROR);
}

// showError is used by the various app layers to inform the user they have done something
// wrong -- for instance returned the wrong thing from a story
function showError({ title, description }) {
  addons.getChannel().emit(Events.STORY_ERRORED, { title, description });
  showErrorDisplay({
    message: title,
    stack: description,
  });
}

// showException is used if we fail to render the story and it is uncaught by the app layer
function showException(exception) {
  addons.getChannel().emit(Events.STORY_THREW_EXCEPTION, exception);
  showErrorDisplay(exception);

  // Log the stack to the console. So, user could check the source code.
  logger.error(exception);
}

const isBrowser =
  navigator &&
  navigator.userAgent &&
  navigator.userAgent !== 'storyshots' &&
  !(navigator.userAgent.indexOf('Node.js') > -1) &&
  !(navigator.userAgent.indexOf('jsdom') > -1);

export const getContext = (() => {
  let cache;
  return decorateStory => {
    if (cache) {
      return cache;
    }
    let channel = null;
    if (isBrowser) {
      try {
        channel = addons.getChannel();
      } catch (e) {
        channel = createChannel({ page: 'preview' });
        addons.setChannel(channel);
      }
    }
    let storyStore;
    let clientApi;
    if (typeof window !== 'undefined' && window.__STORYBOOK_CLIENT_API__) {
      clientApi = window.__STORYBOOK_CLIENT_API__;
      // eslint-disable-next-line no-underscore-dangle
      storyStore = clientApi._storyStore;
    } else {
      storyStore = new StoryStore({ channel });
      clientApi = new ClientApi({ storyStore, decorateStory });
    }
    const { clearDecorators } = clientApi;
    const configApi = new ConfigApi({ clearDecorators, storyStore, channel, clientApi });

    return {
      configApi,
      storyStore,
      channel,
      clientApi,
      showMain,
      showError,
      showException,
    };
  };
})();

function focusInInput(event) {
  return (
    /input|textarea/i.test(event.target.tagName) ||
    event.target.getAttribute('contenteditable') !== null
  );
}

let previousStyles;
const applyLayout = (layout, ctx) => {
  const layouts = {
    centered: `
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      margin: 0;
      padding: 1rem;
      box-sizing: border-box;
    `,
    fullscreen: `
      margin: 0;
    `,
    padded: `
      margin: 0;
      padding: 1rem;
    `,
  };
  const styles = layouts[typeof layout === 'function' ? layout(ctx) : layout] || layouts.padded;
  if (styles !== previousStyles) {
    document.body.style = styles;
    previousStyles = styles;
  }
};

export default function start(render, { decorateStory } = {}) {
  const context = getContext(decorateStory);

  const { clientApi, channel, configApi, storyStore } = context;
  // Provide access to external scripts if `window` is defined.
  // NOTE this is different to isBrowser, primarily for the JSDOM use case
  let previousKind = '';
  let previousStory = '';
  let previousRevision = -1;
  let previousViewMode = '';
  let previousId = null;

  const renderMain = forceRender => {
    const revision = storyStore.getRevision();
    const loadError = storyStore.getError();
    const { storyId, viewMode: urlViewMode } = storyStore.getSelection();

    const data = storyStore.fromId(storyId);

    const { kind, name, getDecorated, id, parameters = {}, error } = data || {};

    const { docsOnly, layout } = parameters;
    applyLayout(layout, data);

    const viewMode = docsOnly ? 'docs' : urlViewMode;

    const renderContext = {
      ...context,
      ...data,
      selectedKind: kind,
      selectedStory: name,
      parameters,
      forceRender,
    };

    if (loadError || error) {
      showErrorDisplay(loadError || error);
      return;
    }

    // Render story only if selectedKind or selectedStory have changed.
    // However, we DO want the story to re-render if the store itself has changed
    // (which happens at the moment when HMR occurs)
    if (
      !forceRender &&
      revision === previousRevision &&
      viewMode === previousViewMode &&
      kind === previousKind &&
      name === previousStory
    ) {
      addons.getChannel().emit(Events.STORY_UNCHANGED, {
        id,
        revision,
        kind,
        name,
        viewMode,
      });
      return;
    }

    if (!forceRender && previousKind && previousStory && revision === previousRevision) {
      addons.getChannel().emit(Events.STORY_CHANGED, id);
    }

    switch (previousViewMode) {
      case 'docs':
        if (previousKind != null && (kind !== previousKind || viewMode !== previousViewMode)) {
          storyStore.cleanHooksForKind(previousKind);
          ReactDOM.unmountComponentAtNode(document.getElementById('docs-root'));
        }
        break;
      case 'story':
      default:
        if (previousId != null && (id !== previousId || viewMode !== previousViewMode)) {
          storyStore.cleanHooks(previousId);
          ReactDOM.unmountComponentAtNode(document.getElementById('root'));
        }
    }

    // Docs view renders into a different root ID to avoid conflicts
    // with the user's view layer. Therefore we need to clean up whenever
    // we transition between view modes
    if (viewMode !== previousViewMode) {
      switch (viewMode) {
        case 'docs': {
          showMain();
          document.getElementById('root').setAttribute('hidden', true);
          document.getElementById('docs-root').removeAttribute('hidden');
          break;
        }
        case 'story':
        default: {
          if (previousViewMode === 'docs') {
            document.getElementById('docs-root').setAttribute('hidden', true);
            document.getElementById('root').removeAttribute('hidden');
          }
        }
      }
    }
    // Given a cleaned up state, render the appropriate view mode
    switch (viewMode) {
      case 'docs': {
        const docs = parameters.docs || {};
        const DocsContainer = docs.container || (({ children }) => <>{children}</>);
        const Page = docs.page || NoDocs;
        ReactDOM.render(
          <DocsContainer context={renderContext}>
            <Page />
          </DocsContainer>,
          document.getElementById('docs-root'),
          () => addons.getChannel().emit(Events.DOCS_RENDERED, kind)
        );
        break;
      }
      case 'story':
      default: {
        if (getDecorated) {
          (async () => {
            try {
              await render(renderContext);
              addons.getChannel().emit(Events.STORY_RENDERED, id);
            } catch (ex) {
              showException(ex);
            }
          })();
        } else {
          showNopreview();
          addons.getChannel().emit(Events.STORY_MISSING, id);
        }
        break;
      }
    }

    previousRevision = revision;
    previousKind = kind;
    previousStory = name;
    previousViewMode = viewMode;
    previousId = id;

    if (!forceRender && viewMode !== 'docs') {
      document.documentElement.scrollTop = 0;
      document.documentElement.scrollLeft = 0;
    }
  };

  // initialize the UI
  const renderUI = forceRender => {
    if (isBrowser) {
      try {
        renderMain(forceRender);
      } catch (ex) {
        showException(ex);
      }
    }
  };

  const forceReRender = () => renderUI(true);

  // channel can be null in NodeJS
  if (isBrowser) {
    const deprecatedToId = deprecate(
      toId,
      `Passing name+kind to the SET_CURRENT_STORY event is deprecated, use a storyId instead`
    );

    channel.on(Events.FORCE_RE_RENDER, forceReRender);
    channel.on(Events.SET_CURRENT_STORY, ({ storyId: inputStoryId, name, kind, viewMode }) => {
      let storyId = inputStoryId;
      // For backwards compatibility
      if (!storyId) {
        if (!name || !kind) {
          throw new Error('You should pass `storyId` into SET_CURRENT_STORY');
        }
        storyId = deprecatedToId(kind, name);
      }

      storyStore.setSelection({ storyId, viewMode });
      setPath({ storyId, viewMode });
    });

    // Handle keyboard shortcuts
    window.onkeydown = event => {
      if (!focusInInput(event)) {
        // We have to pick off the keys of the event that we need on the other side
        const { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode } = event;
        channel.emit(Events.PREVIEW_KEYDOWN, {
          event: { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode },
        });
      }
    };
  }

  storyStore.on(Events.STORY_INIT, () => {
    const { storyId, viewMode } = initializePath();
    storyStore.setSelection({ storyId, viewMode });
  });

  storyStore.on(Events.STORY_RENDER, renderUI);

  if (typeof window !== 'undefined') {
    window.__STORYBOOK_CLIENT_API__ = clientApi;
    window.__STORYBOOK_STORY_STORE__ = storyStore;
    window.__STORYBOOK_ADDONS_CHANNEL__ = channel; // may not be defined
  }

  let previousExports = new Map();
  const loadStories = (loadable, framework) => () => {
    let reqs = null;
    if (Array.isArray(loadable)) {
      reqs = loadable;
    } else if (loadable.keys) {
      reqs = [loadable];
    }

    let currentExports = new Map();
    if (reqs) {
      reqs.forEach(req => {
        req.keys().forEach(filename => {
          const fileExports = req(filename);
          currentExports.set(
            fileExports,
            typeof req.resolve === 'function' ? req.resolve(filename) : null
          );
        });
      });
    } else {
      const exported = loadable();
      if (Array.isArray(exported) && exported.every(obj => obj.default != null)) {
        currentExports = new Map(exported.map(fileExports => [fileExports, null]));
      } else if (exported) {
        logger.warn(
          `Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(
            exported
          )}`
        );
      }
    }

    const removed = [...previousExports.keys()].filter(exp => !currentExports.has(exp));
    removed.forEach(exp => {
      if (exp.default) {
        storyStore.removeStoryKind(exp.default.title);
      }
    });
    if (removed.length > 0) {
      storyStore.incrementRevision();
    }

    const added = [...currentExports.keys()].filter(exp => !previousExports.has(exp));
    added.forEach(fileExports => {
      // An old-style story file
      if (!fileExports.default) {
        return;
      }

      if (!fileExports.default.title) {
        throw new Error(
          `Unexpected default export without title: ${JSON.stringify(fileExports.default)}`
        );
      }

      const { default: meta, __namedExportsOrder, ...namedExports } = fileExports;
      let exports = namedExports;

      // prefer a user/loader provided `__namedExportsOrder` array if supplied
      // we do this as es module exports are always ordered alphabetically
      // see https://github.com/storybookjs/storybook/issues/9136
      if (Array.isArray(__namedExportsOrder)) {
        exports = {};
        __namedExportsOrder.forEach(name => {
          if (namedExports[name]) {
            exports[name] = namedExports[name];
          }
        });
      }

      const {
        title: kindName,
        id: componentId,
        parameters: params,
        decorators: decos,
        component,
        subcomponents,
      } = meta;
      // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this
      const kind = clientApi.storiesOf(kindName, true);

      // we should always have a framework, rest optional
      kind.addParameters({
        framework,
        component,
        subcomponents,
        fileName: currentExports.get(fileExports),
        ...params,
      });

      (decos || []).forEach(decorator => {
        kind.addDecorator(decorator);
      });

      Object.keys(exports).forEach(key => {
        if (isExportStory(key, meta)) {
          const storyFn = exports[key];
          const { name, parameters, decorators } = storyFn.story || {};
          if (parameters && parameters.decorators) {
            deprecate(() => {},
            `${kindName} => ${name || key}: story.parameters.decorators is deprecated; use story.decorators instead.`)();
          }
          const decoratorParams = decorators ? { decorators } : null;
          const exportName = storyNameFromExport(key);
          const idParams = { __id: toId(componentId || kindName, exportName) };
          kind.add(name || exportName, storyFn, {
            ...parameters,
            ...decoratorParams,
            ...idParams,
          });
        }
      });
    });
    previousExports = currentExports;
  };

  let loaded = false;
  /**
   * Load a collection of stories. If it has a default export, assume that it is a module-style
   * file and process its named exports as stories. If not, assume it's an old-style
   * storiesof file and require it.
   *
   * @param {*} loadable a require.context `req`, an array of `req`s, or a loader function that returns void or an array of exports
   * @param {*} m - ES module object for hot-module-reloading (HMR)
   * @param {*} framework - name of framework in use, e.g. "react"
   */
  const configure = (loadable, m, framework) => {
    if (typeof m === 'string') {
      throw new Error(
        `Invalid module '${m}'. Did you forget to pass \`module\` as the second argument to \`configure\`"?`
      );
    }
    if (m && m.hot && m.hot.dispose) {
      ({ previousExports = new Map() } = m.hot.data || {});

      m.hot.dispose(data => {
        loaded = false;
        // eslint-disable-next-line no-param-reassign
        data.previousExports = previousExports;
      });
    }
    if (loaded) {
      logger.warn('Unexpected loaded state. Did you call `load` twice?');
    }
    loaded = true;
    configApi.configure(loadStories(loadable, framework), m);
  };

  return { configure, context, clientApi, configApi, forceReRender };
}
<|endoftext|>


<commit_before>
(function () {

  var secondsTime;

  /**
   * Convert HH:MM:SS format to seconds time.
   * @param {string} formattedTime HH:MM:SS format on a 24-hour clock.
   * @return {number} seconds time up to to 86,400.
   */
  var toSecondsTime = function (formattedTime) {
    var hour = Number(formattedTime.substring(0, 2));
    var min = Number(formattedTime.substring(3, 5));
    var sec = Number(formattedTime.substring(6, 8));
    return (60 * 60 * hour) + (60 * min) + (sec);
  };

  /**
   * Pull current time from the local system and convert to seconds time.
   * @return {number} time of day in total seconds.
   */
  var getCurrentTime = function () {
    var dateNow = new Date();
    var timeNow24 = dateNow.toLocaleTimeString('en-GB');
    return toSecondsTime(timeNow24);
  };

  /**
   * Convert a number to a zero-padded string.
   * @param {number} num A one or two digit integer.
   * @return {string} A two character string.
   */
  var zeroPad = function (num) {
    return num < 10 ? '0' + num : String(num);
  };

  /**
   * Convert total seconds to HH:MM:SS format.
   * @param {number} secondsTime up to to 43,200.
   * @return {string} HH:MM:SS format.
   */
   var formatTime = function (secondsTime) {
    var hour, min, sec;

    // Convert from secondsTime to HH:MM:SS.
    hour = parseInt(secondsTime / (60 * 60))
    min  = parseInt(secondsTime / 60) - (hour * 60);
    sec  = secondsTime % 60;

    // Add a leading zero if a single digit.
    hour = zeroPad(hour);
    min = zeroPad(min);
    sec = zeroPad(sec);

    // If hour is 0, show it as a 12.
    hour = hour === '00' ? 12 : hour;

    return String(hour) + ':' + String(min) + ':' + String(sec);
  };

  /**
   * Increment secondsTime by 1 second.
   */
  var timeStep = function () {

    var elem = document.getElementById('clock'),
        halfDay = 12 * 60 * 60;  // seconds in 12 hours

    // Convert secondsTime to a 12-hour clock.
    secondsTime = secondsTime >= halfDay ? secondsTime - halfDay : secondsTime;

    // Increment by 1 second.
    secondsTime++

    // Display updated time in browser.
    elem.textContent = formatTime(secondsTime);
  };

  /**
   * Run the timeStep function once every second.
   */
  var tick = function () {
    window.setInterval(timeStep, 1000);
  };

  /**
   * Capture the current time when program starts, then internally
   * increment the clock thereafter and update the display in the browser.
   */
  var main = function () {
    secondsTime = getCurrentTime();
    tick();
  };

  // Kick off the program.
  main();

}());

<commit_msg>Syntax tweak<commit_after>
(function () {

  var secondsTime;

  /**
   * Convert HH:MM:SS format to seconds time.
   * @param {string} formattedTime HH:MM:SS format on a 24-hour clock.
   * @return {number} seconds time up to to 86,400.
   */
  var toSecondsTime = function (formattedTime) {
    var hour = Number(formattedTime.substring(0, 2)),
        min = Number(formattedTime.substring(3, 5)),
        sec = Number(formattedTime.substring(6, 8));
    return (60 * 60 * hour) + (60 * min) + (sec);
  };

  /**
   * Pull current time from the local system and convert to seconds time.
   * @return {number} time of day in total seconds.
   */
  var getCurrentTime = function () {
    var dateNow = new Date(),
        timeNow24 = dateNow.toLocaleTimeString('en-GB');
    return toSecondsTime(timeNow24);
  };

  /**
   * Convert a number to a zero-padded string.
   * @param {number} num A one or two digit integer.
   * @return {string} A two character string.
   */
  var zeroPad = function (num) {
    return num < 10 ? '0' + num : String(num);
  };

  /**
   * Convert total seconds to HH:MM:SS format.
   * @param {number} secondsTime up to to 43,200.
   * @return {string} HH:MM:SS format.
   */
   var formatTime = function (secondsTime) {
    var hour, min, sec;

    // Convert from secondsTime to HH:MM:SS.
    hour = parseInt(secondsTime / (60 * 60))
    min  = parseInt(secondsTime / 60) - (hour * 60);
    sec  = secondsTime % 60;

    // Add a leading zero if a single digit.
    hour = zeroPad(hour);
    min = zeroPad(min);
    sec = zeroPad(sec);

    // If hour is 0, show it as a 12.
    hour = hour === '00' ? 12 : hour;

    return String(hour) + ':' + String(min) + ':' + String(sec);
  };

  /**
   * Increment secondsTime by 1 second.
   */
  var timeStep = function () {

    var elem = document.getElementById('clock'),
        halfDay = 12 * 60 * 60;  // seconds in 12 hours

    // Convert secondsTime to a 12-hour clock.
    secondsTime = secondsTime >= halfDay ? secondsTime - halfDay : secondsTime;

    // Increment by 1 second.
    secondsTime++

    // Display updated time in browser.
    elem.textContent = formatTime(secondsTime);
  };

  /**
   * Run the timeStep function once every second.
   */
  var tick = function () {
    window.setInterval(timeStep, 1000);
  };

  /**
   * Capture the current time when program starts, then internally
   * increment the clock thereafter and update the display in the browser.
   */
  var main = function () {
    secondsTime = getCurrentTime();
    tick();
  };

  // Kick off the program.
  main();

}());

<|endoftext|>


<commit_before>'use strict';

var
    BinaryStream = require('./../utils/binary-stream'),
    KdbxError = require('./../errors/kdbx-error'),
    Consts = require('./../defs/consts'),
    ByteUtils = require('./../utils/byte-utils'),
    CryptoEngine = require('./crypto-engine');

var BlockSize = 1024*1024;

/**
 * Encrypt buffer
 * @param {ArrayBuffer} data
 * @returns {Promise.<ArrayBuffer>}
 */
function decrypt(data) {
    return Promise.resolve().then(function() {
        var stm = new BinaryStream(data);
        var buffers = [];
        var blockIndex = 0, blockLength = 0, blockHash, totalLength = 0;
        return next();

        function next() {
            blockIndex = stm.getUint32(true);
            blockHash = stm.readBytes(32);
            blockLength = stm.getUint32(true);
            if (blockLength > 0) {
                totalLength += blockLength;
                var blockData = stm.readBytes(blockLength);
                return CryptoEngine.sha256(blockData).then(function(calculatedHash) {
                    if (!ByteUtils.arrayBufferEquals(calculatedHash, blockHash)) {
                        throw new KdbxError(Consts.ErrorCodes.FileCorrupt, 'invalid hash block');
                    } else {
                        buffers.push(blockData);
                        return next();
                    }
                });
            } else {
                var ret = new Uint8Array(totalLength);
                var offset = 0;
                for (var i = 0; i < buffers.length; i++) {
                    ret.set(new Uint8Array(buffers[i]), offset);
                    offset += buffers[i].byteLength;
                }
                return ret.buffer;
            }
        }
    });
}

/**
 * Decrypt buffer
 * @param {ArrayBuffer} data
 * @returns {Promise.<ArrayBuffer>}
 */
function encrypt(data) {
    return Promise.resolve().then(function() {
        var bytesLeft = data.byteLength;
        var currentOffset = 0, blockIndex = 0, totalLength = 0;
        var buffers = [];
        return next();

        function next() {
            if (bytesLeft > 0) {
                var blockLength = Math.min(BlockSize, bytesLeft);
                bytesLeft -= blockLength;

                var blockData = data.slice(currentOffset, currentOffset + blockLength);
                return CryptoEngine.sha256(blockData).then(function(blockHash) {
                    var blockBuffer = new ArrayBuffer(4 + 32 + 4);
                    var stm = new BinaryStream(blockBuffer);
                    stm.setUint32(blockIndex, true);
                    stm.writeBytes(blockHash);
                    stm.setUint32(blockLength, true);

                    buffers.push(blockBuffer);
                    totalLength += blockBuffer.byteLength;
                    buffers.push(blockData);
                    totalLength += blockData.byteLength;

                    blockIndex++;
                    currentOffset += blockLength;

                    return next();
                });
            } else {
                var endBlockData = new ArrayBuffer(4 + 32 + 4);
                buffers.push(endBlockData);
                totalLength += endBlockData.byteLength;

                var ret = new Uint8Array(totalLength);
                var offset = 0;
                for (var i = 0; i < buffers.length; i++) {
                    ret.set(new Uint8Array(buffers[i]), offset);
                    offset += buffers[i].byteLength;
                }
                return ret.buffer;
            }
        }
    });
}

module.exports.decrypt = decrypt;
module.exports.encrypt = encrypt;
<commit_msg>fix old hashed block transform<commit_after>'use strict';

var
    BinaryStream = require('./../utils/binary-stream'),
    KdbxError = require('./../errors/kdbx-error'),
    Consts = require('./../defs/consts'),
    ByteUtils = require('./../utils/byte-utils'),
    CryptoEngine = require('./crypto-engine');

var BlockSize = 1024*1024;

/**
 * Encrypt buffer
 * @param {ArrayBuffer} data
 * @returns {Promise.<ArrayBuffer>}
 */
function decrypt(data) {
    return Promise.resolve().then(function() {
        var stm = new BinaryStream(data);
        var buffers = [];
        var blockIndex = 0, blockLength = 0, blockHash, totalLength = 0;
        return next();

        function next() {
            blockIndex = stm.getUint32(true);
            blockHash = stm.readBytes(32);
            blockLength = stm.getUint32(true);
            if (blockLength > 0) {
                totalLength += blockLength;
                var blockData = stm.readBytes(blockLength);
                return CryptoEngine.sha256(blockData).then(function(calculatedHash) {
                    if (!ByteUtils.arrayBufferEquals(calculatedHash, blockHash)) {
                        throw new KdbxError(Consts.ErrorCodes.FileCorrupt, 'invalid hash block');
                    } else {
                        buffers.push(blockData);
                        return next();
                    }
                });
            } else {
                var ret = new Uint8Array(totalLength);
                var offset = 0;
                for (var i = 0; i < buffers.length; i++) {
                    ret.set(new Uint8Array(buffers[i]), offset);
                    offset += buffers[i].byteLength;
                }
                return ret.buffer;
            }
        }
    });
}

/**
 * Decrypt buffer
 * @param {ArrayBuffer} data
 * @returns {Promise.<ArrayBuffer>}
 */
function encrypt(data) {
    return Promise.resolve().then(function() {
        var bytesLeft = data.byteLength;
        var currentOffset = 0, blockIndex = 0, totalLength = 0;
        var buffers = [];
        return next();

        function next() {
            if (bytesLeft > 0) {
                var blockLength = Math.min(BlockSize, bytesLeft);
                bytesLeft -= blockLength;

                var blockData = data.slice(currentOffset, currentOffset + blockLength);
                return CryptoEngine.sha256(blockData).then(function(blockHash) {
                    var blockBuffer = new ArrayBuffer(4 + 32 + 4);
                    var stm = new BinaryStream(blockBuffer);
                    stm.setUint32(blockIndex, true);
                    stm.writeBytes(blockHash);
                    stm.setUint32(blockLength, true);

                    buffers.push(blockBuffer);
                    totalLength += blockBuffer.byteLength;
                    buffers.push(blockData);
                    totalLength += blockData.byteLength;

                    blockIndex++;
                    currentOffset += blockLength;

                    return next();
                });
            } else {
                var endBlockData = new ArrayBuffer(4 + 32 + 4);
                var view = new DataView(endBlockData);
                view.setUint32(0, blockIndex, true);
                buffers.push(endBlockData);
                totalLength += endBlockData.byteLength;

                var ret = new Uint8Array(totalLength);
                var offset = 0;
                for (var i = 0; i < buffers.length; i++) {
                    ret.set(new Uint8Array(buffers[i]), offset);
                    offset += buffers[i].byteLength;
                }
                return ret.buffer;
            }
        }
    });
}

module.exports.decrypt = decrypt;
module.exports.encrypt = encrypt;
<|endoftext|>


<commit_before>// ==UserScript==
// @id             ingress-intel-total-conversion@jonatkins
// @name           IITC: Ingress intel map total conversion
// @version        0.18.4.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Total conversion for the ingress intel map.
// @include        http://www.ingress.com/intel*
// @include        https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

// REPLACE ORIG SITE ///////////////////////////////////////////////////
if(document.getElementsByTagName('html')[0].getAttribute('itemscope') != null)
  throw('Ingress Intel Website is down, not a userscript issue.');
window.iitcBuildDate = '@@BUILDDATE@@';

// disable vanilla JS
window.onload = function() {};
document.body.onload = function() {};

// rescue user data from original page
var scr = document.getElementsByTagName('script');
for(var x in scr) {
  var s = scr[x];
  if(s.src) continue;
  if(s.type !== 'text/javascript') continue;
  var d = s.innerHTML.split('\n');
  break;
}

if(!d) {
  // page doesn’t have a script tag with player information.
  if(document.getElementById('header_email')) {
    // however, we are logged in.
    // it used to be regularly common to get temporary 'account not enabled' messages from the intel site.
    // however, this is no longer common. more common is users getting account suspended/banned - and this
    // currently shows the 'not enabled' message. so it's safer to not repeatedly reload in this case
//    setTimeout('location.reload();', 3*1000);
    throw("Page doesn't have player data, but you are logged in.");
  }
  // FIXME: handle nia takedown in progress
  throw("Couldn't retrieve player data. Are you logged in?");
}

for(var i = 0; i < d.length; i++) {
  if(!d[i].match('var PLAYER = ')) continue;
  eval(d[i].match(/^var /, 'window.'));
  break;
}
// player information is now available in a hash like this:
// window.PLAYER = {"ap": "123", "energy": 123, "available_invites": 123, "nickname": "somenick", "team": "ENLIGHTENED||RESISTANCE"};

// remove complete page. We only wanted the user-data and the page’s
// security context so we can access the API easily. Setup as much as
// possible without requiring scripts.
document.getElementsByTagName('head')[0].innerHTML = ''
  + '<title>Ingress Intel Map</title>'
  + ''
  + ''
//note: smartphone.css injection moved into code/smartphone.js
  + '<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Roboto:100,100italic,300,300italic,400,400italic,500,500italic,700,700italic&subset=latin,cyrillic-ext,greek-ext,greek,vietnamese,latin-ext,cyrillic"/>';

document.getElementsByTagName('body')[0].innerHTML = ''
  + '
Loading, please wait
'
  + '
'
  + ''
  + 'fullcompact'
  + 'publicfaction'
  + '
'
  + '
'
  + '

'
  + '

'
  + '

'
  + '

'
  + '
'
  + '<form id="chatinput" style="display:none">

'
  + '  <time></time>	'
  + '  tell faction:	'
  + '  <input id="chattext" type="text" maxlength="256" accesskey="c" title="[c]" />	'
  + '

</form>'
  + ''
  + '
' // enable scrolling for small screens
  + '
'
  + '
t
'
  + '
 loading global control stats
'
  + '
'
  + '      <input id="geosearch" placeholder="Search location…" type="text" accesskey="f" title="Search for a place [f]"/>'
  + '      '
  + '
'
  + '

'
  + '    <input id="redeem" placeholder="Redeem code…" type="text"/>'
  + '
'
  + '      Permalink'
  + '      About IITC'
  + '
'
  + '
'
  + '
'
  + '

'
  // avoid error by stock JS
  + '

';

// putting everything in a wrapper function that in turn is placed in a
// script tag on the website allows us to execute in the site’s context
// instead of in the Greasemonkey/Extension/etc. context.
function wrapper(info) {
// a cut-down version of GM_info is passed as a parameter to the script
// (not the full GM_info - it contains the ENTIRE script source!)
window.script_info = info;

// LEAFLET PREFER CANVAS ///////////////////////////////////////////////
// Set to true if Leaflet should draw things using Canvas instead of SVG
// Disabled for now because it has several bugs: flickering, constant
// CPU usage and it continuously fires the moveend event.

//L_PREFER_CANVAS = false;

// CONFIG OPTIONS ////////////////////////////////////////////////////
window.REFRESH = 30; // refresh view every 30s (base time)
window.ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level
window.ON_MOVE_REFRESH = 2.5;  //refresh time to use after a movement event
window.MINIMUM_OVERRIDE_REFRESH = 10; //limit on refresh time since previous refresh, limiting repeated move refresh rate
window.REFRESH_GAME_SCORE = 15*60; // refresh game score every 15 minutes
window.MAX_IDLE_TIME = 4*60; // stop updating map after 4min idling
window.HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20;
window.SIDEBAR_WIDTH = 300;

// how many items to request each query
window.CHAT_PUBLIC_ITEMS = 50;
window.CHAT_FACTION_ITEMS = 50;
// how many pixels to the top before requesting new data
window.CHAT_REQUEST_SCROLL_TOP = 200;
window.CHAT_SHRINKED = 60;

// Minimum area to zoom ratio that field MU's will display
window.FIELD_MU_DISPLAY_AREA_ZOOM_RATIO = 0.001;

// Point tolerance for displaying MU's
window.FIELD_MU_DISPLAY_POINT_TOLERANCE = 60

window.COLOR_SELECTED_PORTAL = '#f0f';
window.COLORS = ['#FF6600', '#0088FF', '#03DC03']; // none, res, enl
window.COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4'];
window.COLORS_MOD = {VERY_RARE: '#b08cff', RARE: '#73a8ff', COMMON: '#8cffbf'};

window.MOD_TYPE = {RES_SHIELD:'Shield', MULTIHACK:'Multi-hack', FORCE_AMP:'Force Amp', HEATSINK:'Heat Sink', TURRET:'Turret', LINK_AMPLIFIER: 'Link Amp'};

// circles around a selected portal that show from where you can hack
// it and how far the portal reaches (i.e. how far links may be made
// from this portal)
window.ACCESS_INDICATOR_COLOR = 'orange';
window.RANGE_INDICATOR_COLOR = 'red'

// by how much pixels should the portal range be expanded on mobile
// devices. This should make clicking them easier.
window.PORTAL_RADIUS_ENLARGE_MOBILE = 5;

window.DEFAULT_PORTAL_IMG = '//commondatastorage.googleapis.com/ingress.com/img/default-portal-image.png';
window.NOMINATIM = '//nominatim.openstreetmap.org/search?format=json&limit=1&q=';

// INGRESS CONSTANTS /////////////////////////////////////////////////
// http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/
window.RESO_NRG = [0, 1000, 1500, 2000, 2500, 3000, 4000, 5000, 6000];
window.HACK_RANGE = 40; // in meters, max. distance from portal to be able to access it
window.OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE'];
window.OCTANTS_ARROW = ['→', '↗', '↑', '↖', '←', '↙', '↓', '↘'];
window.DESTROY_RESONATOR = 75; //AP for destroying portal
window.DESTROY_LINK = 187; //AP for destroying link
window.DESTROY_FIELD = 750; //AP for destroying field
window.CAPTURE_PORTAL = 500; //AP for capturing a portal
window.DEPLOY_RESONATOR = 125; //AP for deploying a resonator
window.COMPLETION_BONUS = 250; //AP for deploying all resonators on portal
window.UPGRADE_ANOTHERS_RESONATOR = 65; //AP for upgrading another's resonator
window.MAX_PORTAL_LEVEL = 8;
window.MAX_RESO_PER_PLAYER = [0, 8, 4, 4, 4, 2, 2, 1, 1];

// OTHER MORE-OR-LESS CONSTANTS //////////////////////////////////////
window.TEAM_NONE = 0;
window.TEAM_RES = 1;
window.TEAM_ENL = 2;
window.TEAM_TO_CSS = ['none', 'res', 'enl'];

window.SLOT_TO_LAT = [0, Math.sqrt(2)/2, 1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2];
window.SLOT_TO_LNG = [1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2, 0, Math.sqrt(2)/2];
window.EARTH_RADIUS=6378137;
window.DEG2RAD = Math.PI / 180;

// STORAGE ///////////////////////////////////////////////////////////
// global variables used for storage. Most likely READ ONLY. Proper
// way would be to encapsulate them in an anonymous function and write
// getters/setters, but if you are careful enough, this works.
window.refreshTimeout = undefined;
window.urlPortal = null;
window.selectedPortal = null;
window.portalRangeIndicator = null;
window.portalAccessIndicator = null;
window.mapRunsUserAction = false;
//var portalsLayers, linksLayer, fieldsLayer;
var portalsFactionLayers, linksFactionLayers, fieldsFactionLayers;

// contain references to all entities loaded from the server. If render limits are hit,
// not all may be added to the leaflet layers
window.portals = {};
window.links = {};
window.fields = {};

window.resonators = {};

// contain current status(on/off) of overlay layerGroups.
// But you should use isLayerGroupDisplayed(name) to check the status
window.overlayStatus = {};

// plugin framework. Plugins may load earlier than iitc, so don’t
// overwrite data
if(typeof window.plugin !== 'function') window.plugin = function() {};

@@INJECTCODE@@

} // end of wrapper

// inject code into site context
var script = document.createElement('script');
var info = { buildName: '@@BUILDNAME@@', dateTimeVersion: '@@DATETIMEVERSION@@' };
if (this.GM_info && this.GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description };
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
(document.body || document.head || document.documentElement).appendChild(script);
<commit_msg>switch from openstreetmap nominatim search to the mapquest api version - openstreetmap has broken via https, and opemstreetmap has less limits on usage so better suits us anyway<commit_after>// ==UserScript==
// @id             ingress-intel-total-conversion@jonatkins
// @name           IITC: Ingress intel map total conversion
// @version        0.18.4.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Total conversion for the ingress intel map.
// @include        http://www.ingress.com/intel*
// @include        https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

// REPLACE ORIG SITE ///////////////////////////////////////////////////
if(document.getElementsByTagName('html')[0].getAttribute('itemscope') != null)
  throw('Ingress Intel Website is down, not a userscript issue.');
window.iitcBuildDate = '@@BUILDDATE@@';

// disable vanilla JS
window.onload = function() {};
document.body.onload = function() {};

// rescue user data from original page
var scr = document.getElementsByTagName('script');
for(var x in scr) {
  var s = scr[x];
  if(s.src) continue;
  if(s.type !== 'text/javascript') continue;
  var d = s.innerHTML.split('\n');
  break;
}

if(!d) {
  // page doesn’t have a script tag with player information.
  if(document.getElementById('header_email')) {
    // however, we are logged in.
    // it used to be regularly common to get temporary 'account not enabled' messages from the intel site.
    // however, this is no longer common. more common is users getting account suspended/banned - and this
    // currently shows the 'not enabled' message. so it's safer to not repeatedly reload in this case
//    setTimeout('location.reload();', 3*1000);
    throw("Page doesn't have player data, but you are logged in.");
  }
  // FIXME: handle nia takedown in progress
  throw("Couldn't retrieve player data. Are you logged in?");
}

for(var i = 0; i < d.length; i++) {
  if(!d[i].match('var PLAYER = ')) continue;
  eval(d[i].match(/^var /, 'window.'));
  break;
}
// player information is now available in a hash like this:
// window.PLAYER = {"ap": "123", "energy": 123, "available_invites": 123, "nickname": "somenick", "team": "ENLIGHTENED||RESISTANCE"};

// remove complete page. We only wanted the user-data and the page’s
// security context so we can access the API easily. Setup as much as
// possible without requiring scripts.
document.getElementsByTagName('head')[0].innerHTML = ''
  + '<title>Ingress Intel Map</title>'
  + ''
  + ''
//note: smartphone.css injection moved into code/smartphone.js
  + '<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Roboto:100,100italic,300,300italic,400,400italic,500,500italic,700,700italic&subset=latin,cyrillic-ext,greek-ext,greek,vietnamese,latin-ext,cyrillic"/>';

document.getElementsByTagName('body')[0].innerHTML = ''
  + '
Loading, please wait
'
  + '
'
  + ''
  + 'fullcompact'
  + 'publicfaction'
  + '
'
  + '
'
  + '

'
  + '

'
  + '

'
  + '

'
  + '
'
  + '<form id="chatinput" style="display:none">

'
  + '  <time></time>	'
  + '  tell faction:	'
  + '  <input id="chattext" type="text" maxlength="256" accesskey="c" title="[c]" />	'
  + '

</form>'
  + ''
  + '
' // enable scrolling for small screens
  + '
'
  + '
t
'
  + '
 loading global control stats
'
  + '
'
  + '      <input id="geosearch" placeholder="Search location…" type="text" accesskey="f" title="Search for a place [f]"/>'
  + '      '
  + '
'
  + '

'
  + '    <input id="redeem" placeholder="Redeem code…" type="text"/>'
  + '
'
  + '      Permalink'
  + '      About IITC'
  + '
'
  + '
'
  + '
'
  + '

'
  // avoid error by stock JS
  + '

';

// putting everything in a wrapper function that in turn is placed in a
// script tag on the website allows us to execute in the site’s context
// instead of in the Greasemonkey/Extension/etc. context.
function wrapper(info) {
// a cut-down version of GM_info is passed as a parameter to the script
// (not the full GM_info - it contains the ENTIRE script source!)
window.script_info = info;

// LEAFLET PREFER CANVAS ///////////////////////////////////////////////
// Set to true if Leaflet should draw things using Canvas instead of SVG
// Disabled for now because it has several bugs: flickering, constant
// CPU usage and it continuously fires the moveend event.

//L_PREFER_CANVAS = false;

// CONFIG OPTIONS ////////////////////////////////////////////////////
window.REFRESH = 30; // refresh view every 30s (base time)
window.ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level
window.ON_MOVE_REFRESH = 2.5;  //refresh time to use after a movement event
window.MINIMUM_OVERRIDE_REFRESH = 10; //limit on refresh time since previous refresh, limiting repeated move refresh rate
window.REFRESH_GAME_SCORE = 15*60; // refresh game score every 15 minutes
window.MAX_IDLE_TIME = 4*60; // stop updating map after 4min idling
window.HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20;
window.SIDEBAR_WIDTH = 300;

// how many items to request each query
window.CHAT_PUBLIC_ITEMS = 50;
window.CHAT_FACTION_ITEMS = 50;
// how many pixels to the top before requesting new data
window.CHAT_REQUEST_SCROLL_TOP = 200;
window.CHAT_SHRINKED = 60;

// Minimum area to zoom ratio that field MU's will display
window.FIELD_MU_DISPLAY_AREA_ZOOM_RATIO = 0.001;

// Point tolerance for displaying MU's
window.FIELD_MU_DISPLAY_POINT_TOLERANCE = 60

window.COLOR_SELECTED_PORTAL = '#f0f';
window.COLORS = ['#FF6600', '#0088FF', '#03DC03']; // none, res, enl
window.COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4'];
window.COLORS_MOD = {VERY_RARE: '#b08cff', RARE: '#73a8ff', COMMON: '#8cffbf'};

window.MOD_TYPE = {RES_SHIELD:'Shield', MULTIHACK:'Multi-hack', FORCE_AMP:'Force Amp', HEATSINK:'Heat Sink', TURRET:'Turret', LINK_AMPLIFIER: 'Link Amp'};

// circles around a selected portal that show from where you can hack
// it and how far the portal reaches (i.e. how far links may be made
// from this portal)
window.ACCESS_INDICATOR_COLOR = 'orange';
window.RANGE_INDICATOR_COLOR = 'red'

// by how much pixels should the portal range be expanded on mobile
// devices. This should make clicking them easier.
window.PORTAL_RADIUS_ENLARGE_MOBILE = 5;

window.DEFAULT_PORTAL_IMG = '//commondatastorage.googleapis.com/ingress.com/img/default-portal-image.png';
//window.NOMINATIM = '//nominatim.openstreetmap.org/search?format=json&limit=1&q=';
window.NOMINATIM = '//open.mapquestapi.com/nominatim/v1/search.php?format=json&limit=1&q=';

// INGRESS CONSTANTS /////////////////////////////////////////////////
// http://decodeingress.me/2012/11/18/ingress-portal-levels-and-link-range/
window.RESO_NRG = [0, 1000, 1500, 2000, 2500, 3000, 4000, 5000, 6000];
window.HACK_RANGE = 40; // in meters, max. distance from portal to be able to access it
window.OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE'];
window.OCTANTS_ARROW = ['→', '↗', '↑', '↖', '←', '↙', '↓', '↘'];
window.DESTROY_RESONATOR = 75; //AP for destroying portal
window.DESTROY_LINK = 187; //AP for destroying link
window.DESTROY_FIELD = 750; //AP for destroying field
window.CAPTURE_PORTAL = 500; //AP for capturing a portal
window.DEPLOY_RESONATOR = 125; //AP for deploying a resonator
window.COMPLETION_BONUS = 250; //AP for deploying all resonators on portal
window.UPGRADE_ANOTHERS_RESONATOR = 65; //AP for upgrading another's resonator
window.MAX_PORTAL_LEVEL = 8;
window.MAX_RESO_PER_PLAYER = [0, 8, 4, 4, 4, 2, 2, 1, 1];

// OTHER MORE-OR-LESS CONSTANTS //////////////////////////////////////
window.TEAM_NONE = 0;
window.TEAM_RES = 1;
window.TEAM_ENL = 2;
window.TEAM_TO_CSS = ['none', 'res', 'enl'];

window.SLOT_TO_LAT = [0, Math.sqrt(2)/2, 1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2];
window.SLOT_TO_LNG = [1, Math.sqrt(2)/2, 0, -Math.sqrt(2)/2, -1, -Math.sqrt(2)/2, 0, Math.sqrt(2)/2];
window.EARTH_RADIUS=6378137;
window.DEG2RAD = Math.PI / 180;

// STORAGE ///////////////////////////////////////////////////////////
// global variables used for storage. Most likely READ ONLY. Proper
// way would be to encapsulate them in an anonymous function and write
// getters/setters, but if you are careful enough, this works.
window.refreshTimeout = undefined;
window.urlPortal = null;
window.selectedPortal = null;
window.portalRangeIndicator = null;
window.portalAccessIndicator = null;
window.mapRunsUserAction = false;
//var portalsLayers, linksLayer, fieldsLayer;
var portalsFactionLayers, linksFactionLayers, fieldsFactionLayers;

// contain references to all entities loaded from the server. If render limits are hit,
// not all may be added to the leaflet layers
window.portals = {};
window.links = {};
window.fields = {};

window.resonators = {};

// contain current status(on/off) of overlay layerGroups.
// But you should use isLayerGroupDisplayed(name) to check the status
window.overlayStatus = {};

// plugin framework. Plugins may load earlier than iitc, so don’t
// overwrite data
if(typeof window.plugin !== 'function') window.plugin = function() {};

@@INJECTCODE@@

} // end of wrapper

// inject code into site context
var script = document.createElement('script');
var info = { buildName: '@@BUILDNAME@@', dateTimeVersion: '@@DATETIMEVERSION@@' };
if (this.GM_info && this.GM_info.script) info.script = { version: GM_info.script.version, name: GM_info.script.name, description: GM_info.script.description };
script.appendChild(document.createTextNode('('+ wrapper +')('+JSON.stringify(info)+');'));
(document.body || document.head || document.documentElement).appendChild(script);
<|endoftext|>


<commit_before>var clientApp = clientApp || {};
var helpers = clientApp.helpers || {};
var input = input || {};
var upload = upload || {};
var editor = editor || {};

var demo_sets = {};

// Print in the web Interface the sets.
input.printSets = function(sets) {
  demo_sets = sets;
  for (var i = 0; i < sets.length; i++) {
    var set = sets[i].blobs;
    var blobs = Object.keys(set);
    var name = sets[i].name;
    $(".setContainer").append("

")
      .append("

");
    var blobSet = $(".blobSet-body-" + i);
    var blobSetArray = [];

    addSetClickEvent(blobSet, i);

    blobSetArray += ""; // first photo
    if (blobs.length == 3) { // Middle photo (3 photos)
      blobSetArray += "";
    }
    if (blobs.length >= 4) { // +3 photo set. ···
      blobSetArray += "···";
    }
    if (blobs.length > 1) { // +1 photo. last photo.
      blobSetArray += "";
    }
    blobSet.html(blobSetArray);
    $(".blobSet_" + i).append($(".blobSet-body-" + i));
    if (blobs.length == 1) {
      $(".blobSet_" + i).append("" + set[blobs].title + "");
    } else {
      $(".blobSet_" + i).append("" + sets[i].name + "");
    }
    $(".blobSet_" + i).addClass("text-center");
  }

  var setsContainer = document.getElementById("sets");
  var isChrome = !!window.chrome && !!window.chrome.webstore;
  var isFirefox = typeof InstallTrigger !== 'undefined';
  var isSafari = /constructor/i.test(window.HTMLElement) || (function(p) {
    return p.toString() === "[object SafariRemoteNotification]";
  })(!window['safari'] || safari.pushNotification);
  if (isFirefox) {
    setsContainer.addEventListener("DOMMouseScroll", scrollHorizontally, false);
  } else {
    setsContainer.addEventListener("mousewheel", MouseWheelHandler(), false);
  }
}

input.printInputInformationIcon = function(ddl_general) {
  checkInputDescriptionIconVisibility(ddl_general);
  $('#inputs-description').addDescription(ddl_general.input_description);
}

function scrollHorizontally(e) {
  e = window.event || e;
  if (e.deltaY) deltaValue = e.deltaY;
  else deltaValue = e.wheelDelta;
  var delta = Math.max(-1, Math.min(1, (deltaValue || -e.detail)));
  this.scrollLeft -= (delta * 70);
  e.preventDefault();
}

function MouseWheelHandler() {
  return function(e) {
    // cross-browser wheel delta
    var e = window.event || e;
    // Get delta value from deltaY instead of wheelDelta for trackpad support.
    var deltaValue;
    if (e.deltaY) deltaValue = e.deltaY;
    else deltaValue = e.wheelDelta;
    var delta = Math.max(-1, Math.min(1, (deltaValue || -e.detail)));
    if (delta < 0) this.scrollLeft += 20;
    else this.scrollLeft -= 20;

    e.preventDefault();
    return false;
  }
}

function addSetClickEvent(blobSet, index) {
  blobSet.addClass("blobSet")
    .click(function() {
      setEditor(index, null);
    });
}

function setEditor(index, crop_info) {
  var blobs = demo_sets[index].blobs;
  var id_blobs = [];
  for (let i = 0; i < Object.keys(blobs).length; i++) {
    id_blobs.push(blobs[i].id);
  }
  helpers.addToStorage("demoSet", blobs);
  helpers.addToStorage("setId", parseInt(index));
  helpers.addToStorage("id_blobs", {
    "id_blobs": id_blobs
  });
  helpers.setOrigin("blobSet");
  editor.printEditor(crop_info);
}

function setUploadEditor(files_count, blobs, crop_info) {
  if (files_count == blobs.length) {
    for (let i = 0; i < files.length; i++) {
      uploadedFiles[i] = {
        blob: blobs[i],
        format: "image",
        thumbnail: ""
      };
    }
    helpers.setOrigin("upload");
    editor.printEditor(crop_info);
  }
}

$.fn.addDescription = function(description) {
  if (!description) return;
  var text = typeof description != 'string' ? description.join('') : description;
  if (description) $(this).attr('title', text);
}

function checkInputDescriptionIconVisibility(ddl_general) {
  if (ddl_general.input_description != undefined) $('#inputs-description').removeClass('di-none');
}
<commit_msg>[ClientApp2/input] blobs position id fix.<commit_after>var clientApp = clientApp || {};
var helpers = clientApp.helpers || {};
var input = input || {};
var upload = upload || {};
var editor = editor || {};

var demo_sets = {};

// Print in the web Interface the sets.
input.printSets = function(sets) {
  demo_sets = sets;
  for (var i = 0; i < sets.length; i++) {
    var set = sets[i].blobs;
    var blobs = Object.keys(set);
    var name = sets[i].name;
    $(".setContainer").append("

")
      .append("

");
    var blobSet = $(".blobSet-body-" + i);
    var blobSetArray = [];

    addSetClickEvent(blobSet, i);

    blobSetArray += ""; // first photo
    if (blobs.length == 3) { // Middle photo (3 photos)
      blobSetArray += "";
    }
    if (blobs.length >= 4) { // +3 photo set. ···
      blobSetArray += "···";
    }
    if (blobs.length > 1) { // +1 photo. last photo.
      blobSetArray += "";
    }
    blobSet.html(blobSetArray);
    $(".blobSet_" + i).append($(".blobSet-body-" + i));
    if (blobs.length == 1) {
      $(".blobSet_" + i).append("" + set[blobs].title + "");
    } else {
      $(".blobSet_" + i).append("" + sets[i].name + "");
    }
    $(".blobSet_" + i).addClass("text-center");
  }

  var setsContainer = document.getElementById("sets");
  var isChrome = !!window.chrome && !!window.chrome.webstore;
  var isFirefox = typeof InstallTrigger !== 'undefined';
  var isSafari = /constructor/i.test(window.HTMLElement) || (function(p) {
    return p.toString() === "[object SafariRemoteNotification]";
  })(!window['safari'] || safari.pushNotification);
  if (isFirefox) {
    setsContainer.addEventListener("DOMMouseScroll", scrollHorizontally, false);
  } else {
    setsContainer.addEventListener("mousewheel", MouseWheelHandler(), false);
  }
}

input.printInputInformationIcon = function(ddl_general) {
  checkInputDescriptionIconVisibility(ddl_general);
  $('#inputs-description').addDescription(ddl_general.input_description);
}

function scrollHorizontally(e) {
  e = window.event || e;
  if (e.deltaY) deltaValue = e.deltaY;
  else deltaValue = e.wheelDelta;
  var delta = Math.max(-1, Math.min(1, (deltaValue || -e.detail)));
  this.scrollLeft -= (delta * 70);
  e.preventDefault();
}

function MouseWheelHandler() {
  return function(e) {
    // cross-browser wheel delta
    var e = window.event || e;
    // Get delta value from deltaY instead of wheelDelta for trackpad support.
    var deltaValue;
    if (e.deltaY) deltaValue = e.deltaY;
    else deltaValue = e.wheelDelta;
    var delta = Math.max(-1, Math.min(1, (deltaValue || -e.detail)));
    if (delta < 0) this.scrollLeft += 20;
    else this.scrollLeft -= 20;

    e.preventDefault();
    return false;
  }
}

function addSetClickEvent(blobSet, index) {
  blobSet.addClass("blobSet")
    .click(function() {
      setEditor(index, null);
    });
}

function setEditor(index, crop_info) {
  var blobs = demo_sets[index].blobs;
  var id_blobs = [];
  for (let i = 0; i < Object.keys(blobs).length; i++) {
    id_blobs.push(blobs[Object.keys(blobs)[i]].id);
  }
  helpers.addToStorage("demoSet", blobs);
  helpers.addToStorage("setId", parseInt(index));
  helpers.addToStorage("id_blobs", {
    "id_blobs": id_blobs
  });
  helpers.setOrigin("blobSet");
  editor.printEditor(crop_info);
}

function setUploadEditor(files_count, blobs, crop_info) {
  if (files_count == blobs.length) {
    for (let i = 0; i < files.length; i++) {
      uploadedFiles[i] = {
        blob: blobs[i],
        format: "image",
        thumbnail: ""
      };
    }
    helpers.setOrigin("upload");
    editor.printEditor(crop_info);
  }
}

$.fn.addDescription = function(description) {
  if (!description) return;
  var text = typeof description != 'string' ? description.join('') : description;
  if (description) $(this).attr('title', text);
}

function checkInputDescriptionIconVisibility(ddl_general) {
  if (ddl_general.input_description != undefined) $('#inputs-description').removeClass('di-none');
}
<|endoftext|>


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

var nconf = require('./lib/conf');
var winston = require('./lib/logger');

var deviceRegister = require('./lib/register-service');
var appDownloader = require('./lib/pi-downloader');

var gcmSender = new gcm.Sender(nconf.get('gcm-key'));

var app = express();
var port = 3000;

var router = express.Router();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

router.get('/', function(req, res) {
  res.send('api home page');
});

router.get('/register', function(req, res) {
  res.send('post registration key');
});

router.post('/register', function(req, res) {
  winston.log('info', req.body);
  var registration = req.body.regId;
  deviceRegister.register(registration, function (returnObj) {
    res.send(returnObj);
  });
});

if (nconf.get('test-page')) {
  router.get('/test', function(req, res) {
  	var gcmMsg = new gcm.Message({
  		collapseKey: 'test',
  		delayWhileIdle: true,
  		timeToLive: 3,
  		data: {
  			testkey: 'message key',
  			msg: 'test message from api'
  		}
  	});
    deviceRegister.findRegistered(function(registrationIds) {
      gcmSender.send(gcmMsg, registrationIds, function (err, result) {
        if(err) {
          winston.log('error', err);
          deviceRegister.handleError(registrationIds, err);
          res.send({code:"401", msg: err});
        }
        else {
          winston.log('info', result);
          res.send({code:"200"});
        }
      });
    });
  });

}
// apply the routes to our application
app.use('/api', router);

// app.listen(port);
winston.log('info', 'application started on:'+port, {cloud:true});

// appDownloader.testDownload();

appDownloader.testEpisodesSuptitle();

// appDownloader.testBetaSeriesUpdate([
//     5010, // Arrow
//     196, // Grey's Anatomy
//     14, // TBBT
//     1474, // Rizzoli & Isles
//     6197 // The Blacklist
//   ]
// );<commit_msg>launch express on start<commit_after>var gcm = require('node-gcm');
var bodyParser = require('body-parser');
var express = require('express');

var nconf = require('./lib/conf');
var winston = require('./lib/logger');

var deviceRegister = require('./lib/register-service');
var appDownloader = require('./lib/pi-downloader');

var gcmSender = new gcm.Sender(nconf.get('gcm-key'));

var app = express();
var port = 3000;

var router = express.Router();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

router.get('/', function(req, res) {
  res.send('api home page');
});

router.get('/register', function(req, res) {
  res.send('post registration key');
});

router.post('/register', function(req, res) {
  winston.log('info', req.body);
  var registration = req.body.regId;
  deviceRegister.register(registration, function (returnObj) {
    res.send(returnObj);
  });
});

if (nconf.get('test-page')) {
  router.get('/test', function(req, res) {
  	var gcmMsg = new gcm.Message({
  		collapseKey: 'test',
  		delayWhileIdle: true,
  		timeToLive: 3,
  		data: {
  			testkey: 'message key',
  			msg: 'test message from api'
  		}
  	});
    deviceRegister.findRegistered(function(registrationIds) {
      gcmSender.send(gcmMsg, registrationIds, function (err, result) {
        if(err) {
          winston.log('error', err);
          deviceRegister.handleError(registrationIds, err);
          res.send({code:"401", msg: err});
        }
        else {
          winston.log('info', result);
          res.send({code:"200"});
        }
      });
    });
  });

}
// apply the routes to our application
app.use('/api', router);

app.listen(port);
winston.log('info', 'application started on:'+port, {cloud:true});

// appDownloader.testDownload();

// appDownloader.testEpisodesSuptitle();

// appDownloader.testBetaSeriesUpdate([
//     5010, // Arrow
//     196, // Grey's Anatomy
//     14, // TBBT
//     1474, // Rizzoli & Isles
//     6197 // The Blacklist
//   ]
// );<|endoftext|>