<commit_before>var container = $(".container")
container.attr("ng-app", 'math3dApp')

// app = angular.module('math3dApp', ['ui.sortable']);
app = angular.module('math3dApp', ['ui.tree', 'ngAnimate', 'ui.bootstrap']);

app.directive('compileTemplate', ["$compile", "$parse", function($compile, $parse) {
    // http://stackoverflow.com/a/25407201/2747370
    return {
        restrict: 'A',
        link: function($scope, element, attr) {
            var parse = $parse(attr.ngBindHtml);
            function value() { return (parse($scope) || '').toString(); }

            $scope.$watch(value, function() {
                $compile(element, null, -9999)($scope);
            });
        }
    }
}]);

// http://stackoverflow.com/a/29571230/2747370
app.directive( 'elemReady', function( $parse ) {
   return {
       restrict: 'A',
       link: function( $scope, elem, attrs ) {
          elem.ready(function(){
            $scope.$apply(function(){
                var func = $parse(attrs.elemReady);
                func($scope);
            })
          })
       }
    }
})

// https://gist.github.com/BobNisco/9885852 (modifications in comments)
// Add this directive where you keep your directives
app.directive('onLongPress', function($timeout) {
    return {
		restrict: 'A',
        link: function(scope, elem, attrs) {
            var timeoutHandler;

            elem.bind('mousedown touchstart', function() {
                timeoutHandler = $timeout(function() {
                    scope.$eval(attrs.onLongPress);
                }, 600);
            });

            elem.bind('mouseup touchend', function() {
                $timeout.cancel(timeoutHandler);
            });
		}
	};
})
app.directive('onShortPress', function($timeout) {
	return {
		restrict: 'A',
		link: function($scope, $elm, $attrs) {
			$elm.bind('mousedown touchstart', function(evt) {
				// Locally scoped variable that will keep track of the short press
				$scope.shortPress = true;

				// After a timeout of 600 ms, shortPress is false;
				$timeout(function() {
					$scope.shortPress=false;
				}, 600);
			});

			$elm.bind('mouseup touchend', function(evt) {
				// Prevent the onShortPress event from firing
                if ($scope.shortPress){
					$scope.$apply(function() {
						$scope.$eval($attrs.onShortPress)
					});
                }
				// If there is an on-touch-end function attached to this element, apply it
				if ($attrs.onTouchEnd) {
					$scope.$apply(function() {
						$scope.$eval($attrs.onTouchEnd)
					});
				}
			});
		}
	};
})

app.controller('treeCtrl', function($scope)  {
    $scope.treeOptions = {
        accept: function(sourceNodeScope, destNodesScope, destIndex) {
            return sourceNodeScope.depth() - 1 === destNodesScope.depth()
        },
        toggle: function(collapsed, sourceNodeScope){
            sourceNodeScope.branch.collapsed = collapsed;
            var reflowInterval = setInterval(function(){
                var failures = reflowBranch(sourceNodeScope['branch']);
                if (failures===0){
                    clearInterval(reflowInterval);
                }
            }, 100);
        }
    };

    function reflowBranch(branch){
        // If folders are collapsed on page load, mathquill mathfields are initialized in zero-height spans. We need to reflow each of them when the folder is expanded.
        // Reflow only really needs to be done once, has the mq-reflow tracking class.
        var failures = 0;
        _.forEach(branch.objects, function(obj){
            _.forEach(obj.wrappedMathFields, function(wmf){

                var mf = wmf.mathfield;
                var el = $(mf.el());
                if (el.css('height')==='0px'){
                    failures += 1;
                }
                else if ( !el.hasClass('mq-reflowed') ){
                    mf.reflow();
                    el.addClass('mq-reflowed');
                }

            })
        })

        return failures;
    }
});

app.controller('saveCtrl', ['$scope', function($scope){
    $scope.saveURL = function(){
        var url = math3d.saveSettingsAsURL();
        $("#save-modal textarea").val(url);
        $("#url-length").html(url.length);
    };
}])

app.controller('axesSettingsCtrl', ['$scope', function($scope){
    $scope.settings = math3d.settings;
}])

app.controller('addObjectCtrl',['$scope', '$sce', function($scope, $sce) {
    $scope.debug = arg => console.log(arg);

    $scope.mathTree = math3d.mathTree;

    $scope.createNewObject = function(type){
        var metaMathObj = {type:type, settings:{}};
        var mathObj = MathObject.renderNewObject(math3d, metaMathObj);
    }

    $scope.createNewFolder = function(){
        $scope.mathTree.push({name:'Untitled', objects:[], collapsed:false});
    }

    $scope.addOjbectToUi = function(obj){
        var content = `

`;

        //Re-initialize jscolor palletes. This seems hacky.
        setTimeout(function(){ jscolor.installByClassName("jscolor"); }, 0);
        //Re-initialize textarea autosizing
        autosize($("textarea.object-description"))

        return $sce.trustAsHtml(content)
    };

    $scope.removeFolder = function(branch){
        // Should only be used if branch is empty
        if (branch.objects.length===0){
            _.remove(math3d.mathTree, function(arg){return arg===branch;});
        }
    }

    $scope.setupMathGraphicMF = function(obj){
        var el = $(`#object-${obj.id} span.mathquill-large`)
        if (!el.hasClass('has-mq')){
            var keys = {
                Vector: 'components',
                ExplicitSurface: 'rawExpressionZ',
                ExplicitSurfacePolar:'rawExpressionZ',
            }
            var key = keys[obj.type];
            if (key === undefined){ key = 'rawExpression' };
            var mf = new WrappedMathFieldMain(el[0],obj, key);
        }

    }

    $scope.setupVariableMF = function(obj){
        var elName = $(`#object-${obj.id} span.mathquill-large .variable-rawName`);
        var elEqual = $(`#object-${obj.id} span.mathquill-large .variable-equal`);
        var elExpression = $(`#object-${obj.id} span.mathquill-large .variable-rawExpression`);

        if (!elName.hasClass('has-mq')){
            new WrappedMathFieldMain(elName[0], obj, 'rawName', $scope);
            new MathQuill.getInterface(2).StaticMath(elEqual[0]);
        }
        if (!elExpression.hasClass('has-mq')){
            new WrappedMathFieldMain(elExpression[0], obj, 'rawExpression');
        }
    }

}]);

app.controller('mathObjectCtrl',['$scope', function($scope){
    $scope.debug = arg => console.log(arg)
    $scope.setColor = function(obj){
        document.getElementById(`jscolor-${obj.id}`).jscolor.show()
    }
    $scope.getStyle = function(obj){
        if (obj.settings.visible){
            var backgroundColor = obj.settings.color;
            var borderColor = Utility.lightenColor(obj.settings.color,-0.5);
        } else {
            var backgroundColor = 'lightgray';
            var borderColor = 'darkgray';
        }
        return `background-color:${backgroundColor}; border-color:${borderColor}`
    }
}])

app.controller('sliderCtrl', ['$scope', function($scope){
    $scope.intervalID = null;
    $scope.toggleAnimate = function(obj){
        if (!obj.settings.animationRunning){
            $scope.startAnimation(obj)
        }
        else {
            $scope.stopAnimation(obj)
        }
        return
    }
    $scope.startAnimation = function(obj){
        obj.settings.animationRunning = true;
        var ele = document.getElementById("slider-"+obj.id);
        ele.step = ((ele.max-ele.min)/200) * obj.speeds[obj.settings.speedIdx].value;
        $scope.intervalID = setInterval(function(){
           ele.stepUp();
           if (ele.value > ele.max - ele.step){
               ele.value = ele.min
           }
           angular.element(ele).trigger('input')
        },20)
    }
    $scope.stopAnimation = function(obj){
        obj.settings.animationRunning = false;
        clearInterval($scope.intervalID);
    }

    $scope.incrementSpeed = function(obj, incr){
        obj.settings.speedIdx += incr;
        obj.settings.speedIdx = MathUtility.clamp(0, obj.settings.speedIdx, obj.speeds.length);
        $scope.toggleAnimate(obj);
        $scope.toggleAnimate(obj);
    }

    $scope.initSlider = function(obj){
        var ele = document.getElementById("slider-"+obj.id);
        ele.step = ((ele.max-ele.min)/200) * obj.speeds[obj.settings.speedIdx].value;
        if (obj.animationStarted === undefined && obj.settings.animationRunning){
            $scope.startAnimation(obj);
            obj.animationStarted = true;
        }
    }

}])

//http://stackoverflow.com/a/32366115/2747370
//http://codepen.io/dmvianna/pen/OyNNJx
app.controller('popoverCtrl', ['$scope', function($scope) {
    // query popover
    $scope.myPopover = {
        isOpen: false,
        templateUrl: 'templates/settings_popover.html',
        open: function open() {
            $scope.myPopover.isOpen = true;
            $scope.myPopover.data = 'Hello!';
        },
        close: function close() {
            $scope.myPopover.isOpen = false;
        }
    };
}]);

// Prevent key events from bubbling up to the 3d scene
container.on("keypress keydown keyup", function(e) {
    e.stopPropagation();
});<commit_msg>switch to using pointer events instead of mouse and touch<commit_after>var container = $(".container")
container.attr("ng-app", 'math3dApp')

// app = angular.module('math3dApp', ['ui.sortable']);
app = angular.module('math3dApp', ['ui.tree', 'ngAnimate', 'ui.bootstrap']);

app.directive('compileTemplate', ["$compile", "$parse", function($compile, $parse) {
    // http://stackoverflow.com/a/25407201/2747370
    return {
        restrict: 'A',
        link: function($scope, element, attr) {
            var parse = $parse(attr.ngBindHtml);
            function value() { return (parse($scope) || '').toString(); }

            $scope.$watch(value, function() {
                $compile(element, null, -9999)($scope);
            });
        }
    }
}]);

// http://stackoverflow.com/a/29571230/2747370
app.directive( 'elemReady', function( $parse ) {
   return {
       restrict: 'A',
       link: function( $scope, elem, attrs ) {
          elem.ready(function(){
            $scope.$apply(function(){
                var func = $parse(attrs.elemReady);
                func($scope);
            })
          })
       }
    }
})

// https://gist.github.com/BobNisco/9885852 (modifications in comments)
// Add this directive where you keep your directives
app.directive('onLongPress', function($timeout) {
    return {
		restrict: 'A',
        link: function(scope, elem, attrs) {
            var timeoutHandler;

            elem.bind('pointerdown', function() {
                timeoutHandler = $timeout(function() {
                    scope.$eval(attrs.onLongPress);
                }, 600);
            });

            elem.bind('pointerup', function() {
                $timeout.cancel(timeoutHandler);
            });
		}
	};
})
app.directive('onShortPress', function($timeout) {
	return {
		restrict: 'A',
		link: function($scope, $elm, $attrs) {
			$elm.bind('pointerdown', function(evt) {
				// Locally scoped variable that will keep track of the short press
				$scope.shortPress = true;

				// After a timeout of 600 ms, shortPress is false;
				$timeout(function() {
					$scope.shortPress=false;
				}, 600);
			});

			$elm.bind('pointerup', function(evt) {
				// Prevent the onShortPress event from firing
                if ($scope.shortPress){
					$scope.$apply(function() {
						$scope.$eval($attrs.onShortPress)
					});
                }
				// If there is an on-touch-end function attached to this element, apply it
				if ($attrs.onTouchEnd) {
					$scope.$apply(function() {
						$scope.$eval($attrs.onTouchEnd)
					});
				}
			});
		}
	};
})

app.controller('treeCtrl', function($scope)  {
    $scope.treeOptions = {
        accept: function(sourceNodeScope, destNodesScope, destIndex) {
            return sourceNodeScope.depth() - 1 === destNodesScope.depth()
        },
        toggle: function(collapsed, sourceNodeScope){
            sourceNodeScope.branch.collapsed = collapsed;
            var reflowInterval = setInterval(function(){
                var failures = reflowBranch(sourceNodeScope['branch']);
                if (failures===0){
                    clearInterval(reflowInterval);
                }
            }, 100);
        }
    };

    function reflowBranch(branch){
        // If folders are collapsed on page load, mathquill mathfields are initialized in zero-height spans. We need to reflow each of them when the folder is expanded.
        // Reflow only really needs to be done once, has the mq-reflow tracking class.
        var failures = 0;
        _.forEach(branch.objects, function(obj){
            _.forEach(obj.wrappedMathFields, function(wmf){

                var mf = wmf.mathfield;
                var el = $(mf.el());
                if (el.css('height')==='0px'){
                    failures += 1;
                }
                else if ( !el.hasClass('mq-reflowed') ){
                    mf.reflow();
                    el.addClass('mq-reflowed');
                }

            })
        })

        return failures;
    }
});

app.controller('saveCtrl', ['$scope', function($scope){
    $scope.saveURL = function(){
        var url = math3d.saveSettingsAsURL();
        $("#save-modal textarea").val(url);
        $("#url-length").html(url.length);
    };
}])

app.controller('axesSettingsCtrl', ['$scope', function($scope){
    $scope.settings = math3d.settings;
}])

app.controller('addObjectCtrl',['$scope', '$sce', function($scope, $sce) {
    $scope.debug = arg => console.log(arg);

    $scope.mathTree = math3d.mathTree;

    $scope.createNewObject = function(type){
        var metaMathObj = {type:type, settings:{}};
        var mathObj = MathObject.renderNewObject(math3d, metaMathObj);
    }

    $scope.createNewFolder = function(){
        $scope.mathTree.push({name:'Untitled', objects:[], collapsed:false});
    }

    $scope.addOjbectToUi = function(obj){
        var content = `

`;

        //Re-initialize jscolor palletes. This seems hacky.
        setTimeout(function(){ jscolor.installByClassName("jscolor"); }, 0);
        //Re-initialize textarea autosizing
        autosize($("textarea.object-description"))

        return $sce.trustAsHtml(content)
    };

    $scope.removeFolder = function(branch){
        // Should only be used if branch is empty
        if (branch.objects.length===0){
            _.remove(math3d.mathTree, function(arg){return arg===branch;});
        }
    }

    $scope.setupMathGraphicMF = function(obj){
        var el = $(`#object-${obj.id} span.mathquill-large`)
        if (!el.hasClass('has-mq')){
            var keys = {
                Vector: 'components',
                ExplicitSurface: 'rawExpressionZ',
                ExplicitSurfacePolar:'rawExpressionZ',
            }
            var key = keys[obj.type];
            if (key === undefined){ key = 'rawExpression' };
            var mf = new WrappedMathFieldMain(el[0],obj, key);
        }

    }

    $scope.setupVariableMF = function(obj){
        var elName = $(`#object-${obj.id} span.mathquill-large .variable-rawName`);
        var elEqual = $(`#object-${obj.id} span.mathquill-large .variable-equal`);
        var elExpression = $(`#object-${obj.id} span.mathquill-large .variable-rawExpression`);

        if (!elName.hasClass('has-mq')){
            new WrappedMathFieldMain(elName[0], obj, 'rawName', $scope);
            new MathQuill.getInterface(2).StaticMath(elEqual[0]);
        }
        if (!elExpression.hasClass('has-mq')){
            new WrappedMathFieldMain(elExpression[0], obj, 'rawExpression');
        }
    }

}]);

app.controller('mathObjectCtrl',['$scope', function($scope){
    $scope.debug = arg => console.log(arg)
    $scope.setColor = function(obj){
        document.getElementById(`jscolor-${obj.id}`).jscolor.show()
    }
    $scope.getStyle = function(obj){
        if (obj.settings.visible){
            var backgroundColor = obj.settings.color;
            var borderColor = Utility.lightenColor(obj.settings.color,-0.5);
        } else {
            var backgroundColor = 'lightgray';
            var borderColor = 'darkgray';
        }
        return `background-color:${backgroundColor}; border-color:${borderColor}`
    }
}])

app.controller('sliderCtrl', ['$scope', function($scope){
    $scope.intervalID = null;
    $scope.toggleAnimate = function(obj){
        if (!obj.settings.animationRunning){
            $scope.startAnimation(obj)
        }
        else {
            $scope.stopAnimation(obj)
        }
        return
    }
    $scope.startAnimation = function(obj){
        obj.settings.animationRunning = true;
        var ele = document.getElementById("slider-"+obj.id);
        ele.step = ((ele.max-ele.min)/200) * obj.speeds[obj.settings.speedIdx].value;
        $scope.intervalID = setInterval(function(){
           ele.stepUp();
           if (ele.value > ele.max - ele.step){
               ele.value = ele.min
           }
           angular.element(ele).trigger('input')
        },20)
    }
    $scope.stopAnimation = function(obj){
        obj.settings.animationRunning = false;
        clearInterval($scope.intervalID);
    }

    $scope.incrementSpeed = function(obj, incr){
        obj.settings.speedIdx += incr;
        obj.settings.speedIdx = MathUtility.clamp(0, obj.settings.speedIdx, obj.speeds.length);
        $scope.toggleAnimate(obj);
        $scope.toggleAnimate(obj);
    }

    $scope.initSlider = function(obj){
        var ele = document.getElementById("slider-"+obj.id);
        ele.step = ((ele.max-ele.min)/200) * obj.speeds[obj.settings.speedIdx].value;
        if (obj.animationStarted === undefined && obj.settings.animationRunning){
            $scope.startAnimation(obj);
            obj.animationStarted = true;
        }
    }

}])

//http://stackoverflow.com/a/32366115/2747370
//http://codepen.io/dmvianna/pen/OyNNJx
app.controller('popoverCtrl', ['$scope', function($scope) {
    // query popover
    $scope.myPopover = {
        isOpen: false,
        templateUrl: 'templates/settings_popover.html',
        open: function open() {
            $scope.myPopover.isOpen = true;
            $scope.myPopover.data = 'Hello!';
        },
        close: function close() {
            $scope.myPopover.isOpen = false;
        }
    };
}]);

// Prevent key events from bubbling up to the 3d scene
container.on("keypress keydown keyup", function(e) {
    e.stopPropagation();
});<|endoftext|>


<commit_before>/**
* ViewData.js
*
* @description :: This model represents the data for all the video statistics.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {
	attributes: {
		coordinates: {
			type: 'array',
			required: true
		},

		width: {
			type: 'float',
			required: true
		},

		videoTime: {
			type: 'float',
			required: true
		},

		// Add a reference to ViewSession
    sessionObj: {
      model: 'ViewSession'
    }
	}
}
<commit_msg>Fix indentation<commit_after>/**
* ViewData.js
*
* @description :: This model represents the data for all the video statistics.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {
	attributes: {
		coordinates: {
			type: 'array',
			required: true
		},

		width: {
			type: 'float',
			required: true
		},

		videoTime: {
			type: 'float',
			required: true
		},

		// Add a reference to ViewSession
		sessionObj: {
			model: 'ViewSession'
		}
	}
}
<|endoftext|>


<commit_before>const { request, buildUserHeaders, factories } = require('./helper')
const { describe, it } = require('mocha')
const expect = require('expect.js')

describe('Request:Users', () => {
  describe('GET /api/users/current', () => {
    it('returns current user', async () => {
      const user = await factories.createUser()
      const headers = buildUserHeaders(user)

      const res = await request
        .get('/api/users/current')
        .set(headers)
        .expect(200)

      expect(res.body).to.eql(JSON.parse(JSON.stringify(user)))
    })

    it('creates a user for you', async () => {
      await request
        .get('/api/users/current')
        .expect(200)
    })
  })
})
<commit_msg>Update tests to use ES6 modules<commit_after>import { request, buildUserHeaders, factories } from './helper'
import { describe, it } from 'mocha'
import expect from 'expect.js'

describe('Request:Users', () => {
  describe('GET /api/users/current', () => {
    it('returns current user', async () => {
      const user = await factories.createUser()
      const headers = buildUserHeaders(user)

      const res = await request
        .get('/api/users/current')
        .set(headers)
        .expect(200)

      expect(res.body).to.eql(JSON.parse(JSON.stringify(user)))
    })

    it('creates a user for you', async () => {
      await request
        .get('/api/users/current')
        .expect(200)
    })
  })
})
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const {app, BrowserWindow, ipcMain} = require('electron')
const appActions = require('../../js/actions/appActions')
const appUrlUtil = require('../../js/lib/appUrlUtil')
const debounce = require('../../js/lib/debounce')
const {getSetting} = require('../../js/settings')
const locale = require('../locale')
const LocalShortcuts = require('../localShortcuts')
const { makeImmutable } = require('../common/state/immutableUtil')
const messages = require('../../js/constants/messages')
const settings = require('../../js/constants/settings')
const windowState = require('../common/state/windowState')

// TODO(bridiver) - set window uuid
let currentWindows = {}

const cleanupWindow = (windowId) => {
  delete currentWindows[windowId]
  appActions.windowClosed({ windowId })
}

const getWindowState = (win) => {
  if (win.isFullScreen()) {
    return 'fullscreen'
  } else if (win.isMinimized()) {
    return 'minimized'
  } else if (win.isMaximized()) {
    return 'maximized'
  } else {
    return 'normal'
  }
}

const getWindowValue = (windowId) => {
  let win = BrowserWindow.fromId(windowId)
  if (win) {
    return makeImmutable({
      windowId: win.id,
      focused: win.isFocused(),
      top: win.getBounds().y,
      left: win.getBounds().x,
      width: win.getSize()[0],
      height: win.getSize()[1],
      type: 'normal',
      state: getWindowState(win)
    })
  }
}

const updateWindow = (windowId) => {
  let windowValue = getWindowValue(windowId)
  if (windowValue) {
    appActions.windowUpdated(windowValue)
  }
}

const api = {
  init: (state, action) => {
    app.on('browser-window-created', function (event, win) {
      let windowId = -1
      const updateWindowMove = debounce(updateWindow, 100)
      const updateWindowDebounce = debounce(updateWindow, 5)

      win.once('initialized', () => {
        windowId = win.id
        currentWindows[windowId] = win
        let windowValue = getWindowValue(windowId)

        win.setMenuBarVisibility(true)
        win.webContents.once('will-destroy', () => {
          LocalShortcuts.unregister(win)
        })
        win.webContents.once('close', () => {
          LocalShortcuts.unregister(win)
        })
        win.once('close', () => {
          LocalShortcuts.unregister(win)
        })
        win.on('scroll-touch-begin', function (e) {
          win.webContents.send('scroll-touch-begin')
        })
        win.on('scroll-touch-end', function (e) {
          win.webContents.send('scroll-touch-end')
        })
        win.on('scroll-touch-edge', function (e) {
          win.webContents.send('scroll-touch-edge')
        })
        win.on('enter-full-screen', function () {
          if (win.isMenuBarVisible()) {
            win.setMenuBarVisibility(false)
          }
        })
        win.on('leave-full-screen', function () {
          win.webContents.send(messages.LEAVE_FULL_SCREEN)

          if (getSetting(settings.AUTO_HIDE_MENU) === false) {
            win.setMenuBarVisibility(true)
          }
        })
        win.on('app-command', function (e, cmd) {
          switch (cmd) {
            case 'browser-backward':
              win.webContents.send(messages.SHORTCUT_ACTIVE_FRAME_BACK)
              return
            case 'browser-forward':
              win.webContents.send(messages.SHORTCUT_ACTIVE_FRAME_FORWARD)
          }
        })
        win.webContents.on('crashed', (e) => {
          console.error('Window crashed. Reloading...')
          win.loadURL(appUrlUtil.getBraveExtIndexHTML())

          ipcMain.on(messages.NOTIFICATION_RESPONSE, function notificationResponseCallback (e, message, buttonIndex, persist) {
            if (message === locale.translation('unexpectedErrorWindowReload')) {
              appActions.hideMessageBox(message)
              ipcMain.removeListener(messages.NOTIFICATION_RESPONSE, notificationResponseCallback)
            }
          })

          appActions.showNotification({
            buttons: [
              {text: locale.translation('ok')}
            ],
            options: {
              persist: false
            },
            message: locale.translation('unexpectedErrorWindowReload')
          })
        })

        appActions.windowCreated(windowValue)
      })
      win.once('show', () => {
        LocalShortcuts.register(win)
      })
      win.once('closed', () => {
        cleanupWindow(windowId)
      })
      win.on('blur', () => {
        updateWindowDebounce(windowId)
      })
      win.on('focus', () => {
        updateWindowDebounce(windowId)
      })
      win.on('show', () => {
        updateWindowDebounce(windowId)
      })
      win.on('hide', () => {
        updateWindowDebounce(windowId)
      })
      win.on('maximize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('unmaximize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('minimize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('restore', () => {
        updateWindowDebounce(windowId)
      })
      win.on('resize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('move', () => {
        updateWindowMove(windowId)
      })
      win.on('enter-full-screen', () => {
        updateWindowDebounce(windowId)
      })
      win.on('leave-full-screen', () => {
        updateWindowDebounce(windowId)
      })
    })
    // TODO(bridiver) - handle restoring windows
    // windowState.getWindows(state).forEach((win) => {
    //   console.log('restore', win.toJS())
    //   // restore window
    // })
    return state
  },

  closeWindow: (state, action) => {
    action = makeImmutable(action)
    let windowId = action.get('windowId')
    let win = api.getWindow(windowId)
    try {
      if (!win.isDestroyed()) {
        win.close()
      }
    } catch (e) {
      // ignore
    }
    return windowState.removeWindowByWindowId(state, windowId)
  },

  getWindow: (windowId) => {
    return currentWindows[windowId]
  }
}

module.exports = api
<commit_msg>Register local shortcuts when creating BrowserWindow object. This was reworked with https://github.com/brave/browser-laptop/commit/6d722101025835ee4c92403901ee6d2cfe2fedde and it was missed<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const {app, BrowserWindow, ipcMain} = require('electron')
const appActions = require('../../js/actions/appActions')
const appUrlUtil = require('../../js/lib/appUrlUtil')
const debounce = require('../../js/lib/debounce')
const {getSetting} = require('../../js/settings')
const locale = require('../locale')
const LocalShortcuts = require('../localShortcuts')
const { makeImmutable } = require('../common/state/immutableUtil')
const messages = require('../../js/constants/messages')
const settings = require('../../js/constants/settings')
const windowState = require('../common/state/windowState')

// TODO(bridiver) - set window uuid
let currentWindows = {}

const cleanupWindow = (windowId) => {
  delete currentWindows[windowId]
  appActions.windowClosed({ windowId })
}

const getWindowState = (win) => {
  if (win.isFullScreen()) {
    return 'fullscreen'
  } else if (win.isMinimized()) {
    return 'minimized'
  } else if (win.isMaximized()) {
    return 'maximized'
  } else {
    return 'normal'
  }
}

const getWindowValue = (windowId) => {
  let win = BrowserWindow.fromId(windowId)
  if (win) {
    return makeImmutable({
      windowId: win.id,
      focused: win.isFocused(),
      top: win.getBounds().y,
      left: win.getBounds().x,
      width: win.getSize()[0],
      height: win.getSize()[1],
      type: 'normal',
      state: getWindowState(win)
    })
  }
}

const updateWindow = (windowId) => {
  let windowValue = getWindowValue(windowId)
  if (windowValue) {
    appActions.windowUpdated(windowValue)
  }
}

const api = {
  init: (state, action) => {
    app.on('browser-window-created', function (event, win) {
      let windowId = -1
      const updateWindowMove = debounce(updateWindow, 100)
      const updateWindowDebounce = debounce(updateWindow, 5)

      win.once('initialized', () => {
        windowId = win.id
        currentWindows[windowId] = win
        let windowValue = getWindowValue(windowId)

        win.setMenuBarVisibility(true)
        win.webContents.once('will-destroy', () => {
          LocalShortcuts.unregister(win)
        })
        win.webContents.once('close', () => {
          LocalShortcuts.unregister(win)
        })
        win.once('close', () => {
          LocalShortcuts.unregister(win)
        })
        win.on('scroll-touch-begin', function (e) {
          win.webContents.send('scroll-touch-begin')
        })
        win.on('scroll-touch-end', function (e) {
          win.webContents.send('scroll-touch-end')
        })
        win.on('scroll-touch-edge', function (e) {
          win.webContents.send('scroll-touch-edge')
        })
        win.on('enter-full-screen', function () {
          if (win.isMenuBarVisible()) {
            win.setMenuBarVisibility(false)
          }
        })
        win.on('leave-full-screen', function () {
          win.webContents.send(messages.LEAVE_FULL_SCREEN)

          if (getSetting(settings.AUTO_HIDE_MENU) === false) {
            win.setMenuBarVisibility(true)
          }
        })
        win.on('app-command', function (e, cmd) {
          switch (cmd) {
            case 'browser-backward':
              win.webContents.send(messages.SHORTCUT_ACTIVE_FRAME_BACK)
              return
            case 'browser-forward':
              win.webContents.send(messages.SHORTCUT_ACTIVE_FRAME_FORWARD)
          }
        })
        win.webContents.on('crashed', (e) => {
          console.error('Window crashed. Reloading...')
          win.loadURL(appUrlUtil.getBraveExtIndexHTML())

          ipcMain.on(messages.NOTIFICATION_RESPONSE, function notificationResponseCallback (e, message, buttonIndex, persist) {
            if (message === locale.translation('unexpectedErrorWindowReload')) {
              appActions.hideMessageBox(message)
              ipcMain.removeListener(messages.NOTIFICATION_RESPONSE, notificationResponseCallback)
            }
          })

          appActions.showNotification({
            buttons: [
              {text: locale.translation('ok')}
            ],
            options: {
              persist: false
            },
            message: locale.translation('unexpectedErrorWindowReload')
          })
        })

        LocalShortcuts.register(win)

        appActions.windowCreated(windowValue)
      })
      win.once('show', () => {
        LocalShortcuts.register(win)
      })
      win.once('closed', () => {
        cleanupWindow(windowId)
      })
      win.on('blur', () => {
        updateWindowDebounce(windowId)
      })
      win.on('focus', () => {
        updateWindowDebounce(windowId)
      })
      win.on('show', () => {
        updateWindowDebounce(windowId)
      })
      win.on('hide', () => {
        updateWindowDebounce(windowId)
      })
      win.on('maximize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('unmaximize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('minimize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('restore', () => {
        updateWindowDebounce(windowId)
      })
      win.on('resize', () => {
        updateWindowDebounce(windowId)
      })
      win.on('move', () => {
        updateWindowMove(windowId)
      })
      win.on('enter-full-screen', () => {
        updateWindowDebounce(windowId)
      })
      win.on('leave-full-screen', () => {
        updateWindowDebounce(windowId)
      })
    })
    // TODO(bridiver) - handle restoring windows
    // windowState.getWindows(state).forEach((win) => {
    //   console.log('restore', win.toJS())
    //   // restore window
    // })
    return state
  },

  closeWindow: (state, action) => {
    action = makeImmutable(action)
    let windowId = action.get('windowId')
    let win = api.getWindow(windowId)
    try {
      if (!win.isDestroyed()) {
        win.close()
      }
    } catch (e) {
      // ignore
    }
    return windowState.removeWindowByWindowId(state, windowId)
  },

  getWindow: (windowId) => {
    return currentWindows[windowId]
  }
}

module.exports = api
<|endoftext|>


<commit_before>// @flow

import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import DocumentTitle from 'react-document-title';

import Navigation from './layout/Navigation';
import Footer from './layout/Footer';
import Flashes from './layout/Flashes';

type Props = {
  children: React$Node,
  viewer: Object,
  organization?: Object
};

class Main extends React.PureComponent<Props> {
  static propTypes = {
    children: PropTypes.node.isRequired,
    viewer: PropTypes.object.isRequired,
    organization: PropTypes.object
  };

  render() {
    return (
      <DocumentTitle title="Buildkite">

          <Navigation organization={this.props.organization} viewer={this.props.viewer} />
          <Flashes />
          {this.props.children}

      </DocumentTitle>
    );
  }
}

export default Relay.createContainer(Main, {
  fragments: {
    organization: () => Relay.QL`
      fragment on Organization {
        ${Navigation.getFragment('organization')}
      }
    `,
    viewer: () => Relay.QL`
      fragment on Viewer {
        ${Navigation.getFragment('viewer')}
        ${Footer.getFragment('viewer')}
      }
    `
  }
});
<commit_msg>Tweak Main's prop definitions<commit_after>// @flow

import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import DocumentTitle from 'react-document-title';

import Navigation from './layout/Navigation';
import Footer from './layout/Footer';
import Flashes from './layout/Flashes';

type Props = {
  children: React$Node,
  viewer?: Object,
  organization?: Object
};

class Main extends React.PureComponent<Props> {
  render() {
    return (
      <DocumentTitle title="Buildkite">

          <Navigation
            organization={this.props.organization}
            viewer={this.props.viewer}
          />
          <Flashes />
          {this.props.children}

      </DocumentTitle>
    );
  }
}

export default Relay.createContainer(Main, {
  fragments: {
    organization: () => Relay.QL`
      fragment on Organization {
        ${Navigation.getFragment('organization')}
      }
    `,
    viewer: () => Relay.QL`
      fragment on Viewer {
        ${Navigation.getFragment('viewer')}
        ${Footer.getFragment('viewer')}
      }
    `
  }
});
<|endoftext|>


<commit_before>'use strict';

import localForage from 'localForage';
import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import { persistStore } from 'redux-persist';

import routes from '../routes';

export default class Root extends Component {
  constructor() {
    super();
    this.state = { rehydrated: false };
  }

  // Moving the persistStore() call to this event handler to prevent the root
  // view from loading until after the store has been rehydrated
  componentWillMount() {
    persistStore(this.props.store, { storage: localForage }, () => {
      this.setState({ rehydrated: true });
    });
  }

  render() {
    if (!this.state.rehydrated) {
      return null;
    }

    const { history, store } = this.props;
    return (
      <Provider store={store}>

          <Router history={history} routes={routes} />

      </Provider>
    );
  }
}

Root.propTypes = {
  store: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
};
<commit_msg>Attempt to fix localforage missing module issue on Heroku<commit_after>'use strict';

import localForage from 'localforage';
import React, { Component, PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import { persistStore } from 'redux-persist';

import routes from '../routes';

export default class Root extends Component {
  constructor() {
    super();
    this.state = { rehydrated: false };
  }

  // Moving the persistStore() call to this event handler to prevent the root
  // view from loading until after the store has been rehydrated
  componentWillMount() {
    persistStore(this.props.store, { storage: localForage }, () => {
      this.setState({ rehydrated: true });
    });
  }

  render() {
    if (!this.state.rehydrated) {
      return null;
    }

    const { history, store } = this.props;
    return (
      <Provider store={store}>

          <Router history={history} routes={routes} />

      </Provider>
    );
  }
}

Root.propTypes = {
  store: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired
};
<|endoftext|>


<commit_before>var app    = require('express').createServer()
  , Step   = require(global.settings.app_root + '/lib/step')
  , oAuth  = require(global.settings.app_root + '/app/models/oauth')
  , PSQL   = require(global.settings.app_root + '/app/models/psql')
  , _      = require('underscore');
  _.mixin(require('underscore.string'));

// CartoDB v1 SQL API
//
// all requests expect the following URL args:
// - `sql` {String} SQL to execute
//
// for private (read/write) queries:
// - `auth_token` {String} oAuth API token from CartoDB. In URL or request header.
//
// eg. /v1/?sql=SELECT 1 as one&auth_token=my_token
//
// for public (read only) queries:
// - `database` {String} The database to execute queries on
//
// eg. /v1/?sql=SELECT 1 as one&database=my_public_db
//
// NOTE: private queries can only be ran on databases the oAuth key gives access to.
app.get('/v1/', function(req, res){

  //sanitize input
  var sql       = req.query.sql;
  var database  = req.query.database;
  sql      = (sql == "")      ? null : sql;
  database = (database == "") ? null : database;

  try {
    if (!_.isString(sql)) throw new Error("You must indicate a sql query");
    var pg;

    Step(
      function getUser() {
        oAuth.authorize(req, this);
      },
      function querySql(err, user_id){
        if (err) throw err;
        pg = new PSQL(user_id, database);
        pg.query(sql, this);
      },
      function packageResults(err, result){
        if (err) throw err;
        pg.end();
        res.send(result.rows);
      },
      function exceptionHandle(err, result){
        handleException(res,err);
      }
    );
  } catch (err) {
    handleException(res,err);
  }
});

function handleException(res, err){
  var msg = (global.settings.environment == 'development') ? {error:[err.message], stack: err.stack} : {error:[err.message]}
  res.send(msg, 400);
}

app.listen(global.settings.node_port);
//module.exports = app;
<commit_msg>fix postgres issue<commit_after>var app    = require('express').createServer()
  , Step   = require(global.settings.app_root + '/lib/step')
  , oAuth  = require(global.settings.app_root + '/app/models/oauth')
  , PSQL   = require(global.settings.app_root + '/app/models/psql')
  , _      = require('underscore');
  _.mixin(require('underscore.string'));

// CartoDB v1 SQL API
//
// all requests expect the following URL args:
// - `sql` {String} SQL to execute
//
// for private (read/write) queries:
// - `auth_token` {String} oAuth API token from CartoDB. In URL or request header.
//
// eg. /v1/?sql=SELECT 1 as one&auth_token=my_token
//
// for public (read only) queries:
// - `database` {String} The database to execute queries on
//
// eg. /v1/?sql=SELECT 1 as one&database=my_public_db
//
// NOTE: private queries can only be ran on databases the oAuth key gives access to.
app.get('/v1/', function(req, res){

  //sanitize input
  var sql       = req.query.sql;
  var database  = req.query.database;
  sql      = (sql == "")      ? null : sql;
  database = (database == "") ? null : database;

  try {
    if (!_.isString(sql)) throw new Error("You must indicate a sql query");
    var pg;

    Step(
      function getUser() {
        oAuth.authorize(req, this);
      },
      function querySql(err, user_id){
        if (err) throw err;
        pg = new PSQL(user_id, database);
        pg.query(sql, this);
      },
      function packageResults(err, result){
        if (err) throw err;
        //pg.end(); TODO: Fix this - we should use a proper pool?
        res.send(result.rows);
      },
      function exceptionHandle(err, result){
        handleException(res,err);
      }
    );
  } catch (err) {
    handleException(res,err);
  }
});

function handleException(res, err){
  var msg = (global.settings.environment == 'development') ? {error:[err.message], stack: err.stack} : {error:[err.message]}
  res.send(msg, 400);
}

app.listen(global.settings.node_port);
//module.exports = app;
<|endoftext|>


<commit_before>import Ember from "ember";
import config from '../config/environment';
import Settings from '../models/settings';
import ErrorMessages from 'ember-twiddle/helpers/error-messages';

const {
  computed,
  run
} = Ember;

const MAX_COLUMNS = 3;

export default Ember.Controller.extend({
  emberCli: Ember.inject.service('ember-cli'),
  version: config.APP.version,

  queryParams: ['numColumns'],
  numColumns: 2,

  init() {
    this._super(...arguments);
    this.setupWindowUpdate();
  },

  /**
   * Output from the build, sets the `code` attr on the component
   * @type {String}
   */
  buildOutput: '',

  /**
   * If the code is currently being built
   * @type {boolean}
   */
  isBuilding: false,

  /**
   * If the edited code has not been saved by the user
   * @type {boolean}
   */
  unsaved: true,

  /**
   * File in the current active editor column
   * @type {Object}
   */
  activeFile: null,

  /**
   * Column which has the currently focused editor
   * @type {Number}
   */
  activeEditorCol: null,

  col1File: null,
  col2File: null,
  col3File: null,
  col1Active: computed.equal('activeEditorCol','1'),
  col2Active: computed.equal('activeEditorCol','2'),
  col3Active: computed.equal('activeEditorCol','3'),
  showCol1: computed.gte('realNumColumns', 1),
  showCol2: computed.gte('realNumColumns', 2),
  showCol3: computed.gte('realNumColumns', 3),

  settings: Settings.create(),

  /**
   * Errors during build
   * @type {Array}     Array of errors
   */
  buildErrors: null,

  /**
   * Whether user wishes the code to automatically run
   * @type {boolean}
   */
  isLiveReload: true,

  /**
   * Build the application and set the iframe code
   */
  buildApp () {
    if (this.get('isDestroyed')) {
      return;
    }

    this.set('isBuilding', true);
    this.set('buildErrors', []);

    this.get('emberCli').compileGist(this.get('model')).then(buildOutput => {
      this.set('isBuilding', false);
      this.set('buildOutput', buildOutput);
    })
    .catch(errors => {
      this.set('isBuilding', false);
      this.set('buildErrors', errors);
      errors.forEach(error => {
        console.error(error);
      });
    });
  },

  realNumColumns: computed('numColumns', function() {
    return Math.min(this.get('numColumns'), MAX_COLUMNS);
  }),
  noColumns: computed.equal('numColumns', 0),

  /**
   * Set the initial file columns
   */
  initializeColumns() {
    let files = this.get('model.files');
    let numColumns = this.get('realNumColumns');

    let j = 0;
    for (let i = 0; i < numColumns; ++i) {
      let key = 'col' + (i + 1) + 'File';
      if (!this.get(key)) {
        if (files) {
          j = 0;
          while (!this.isOpen(files.objectAt(j))) {
            j++;
          }
          let file = files.objectAt(j);
          if (file) {
            this.set(key, file);
          }
        }
      }
    }
  },

  /**
   * Returns true if the passed in file is currently open
   * @param {Object} one of the files in the gist
   * @return {boolean}
   */
  isOpen(file) {
    if (!file) {
      return false;
    }

    if (this.get('col1File.fileName') === file.get('fileName')) {
      return false;
    }
    if (this.get('col2File.fileName') === file.get('fileName')) {
      return false;
    }
    if (this.get('col3File.fileName') === file.get('fileName')) {
      return false;
    }

    return true;
  },

  rebuildApp: function() {
    if (this.get('isLiveReload')) {
      run.debounce(this, this.buildApp, 500);
    }
  },

  createFile(filePath, fileProperties, fileColumn=1) {
    if (filePath) {
      if(this.get('model.files').findBy('filePath', filePath)) {
        alert('A file with the name %@ already exists'.fmt(filePath));
        return;
      }

      fileProperties.filePath = filePath;
      let file = this.store.createRecord('gistFile', fileProperties);

      this.get('model.files').pushObject(file);
      this.notify.info('File %@ was added'.fmt(file.get('filePath')));
      this.setColumnFile(fileColumn, file);
      this.set('activeEditorCol', '1');
      this.send('contentsChanged');
    }
  },

  /*
   *  Test whether path is valid.  Presently only tests whether components are hyphenated.
   */
  isPathInvalid(type, path){
    let errorMsg = null;
    if (type.match(/^component/)) {
      if(!path.match(/-[^\/]+$/)) {
         errorMsg = ErrorMessages.componentsNeedHyphens;
      }
    }
    if (errorMsg) {
      alert(errorMsg);
      return true;
    }
    return false;
  },

  setColumnFile(column, file){
    let fileColumn = `col${column}File`;
    this.set(fileColumn, file);
  },

  actions: {
    contentsChanged() {
      this.set('unsaved', true);
      this.rebuildApp();
    },

    liveReloadChanged(isLiveReload) {
      this.set('isLiveReload', isLiveReload);
      this.rebuildApp();
    },

    focusEditor (editor) {
      this.set('activeEditorCol', editor.get('col'));
      this.set('activeFile', editor.get('file'));
    },

    selectFile (file) {
      this.set('activeFile', file);
    },

    runNow () {
      this.buildApp();
    },

    deleteGist (gist) {
      if(confirm(`Are you sure you want to remove this gist from Github?\n\n${gist.get('description')}`)) {
        gist.destroyRecord();
        this.transitionToRoute('gist.new');
        this.notify.info('Gist %@ was deleted from Github'.fmt(gist.get('id')));
      }
    },

    addComponent() {
      let path = prompt('Component path (without file extension)', 'components/my-component');
      if (Ember.isBlank(path)){
        return;
      }

      //strip file extension if present
      path = path.replace(/\.[^/.]+$/, "");

      if (this.isPathInvalid('component', path)) {
        return;
      }
      ['js', 'hbs'].forEach((fileExt, i)=>{
        let fileProperties = this.get('emberCli').buildProperties(`component-${fileExt}`);
        let filePath =  `${fileExt === 'hbs' ? 'templates/' : ''}${path}.${fileExt}`;
        let fileColumn = i+1;
        this.createFile(filePath, fileProperties, fileColumn);
      });
    },

    /**
     * Add a new file to the model
     * @param {String|null} type Blueprint name or null for empty file
     */
    addFile (type) {
      let fileProperties = type ? this.get('emberCli').buildProperties(type) : {filePath:'file.js'};
      let filePath = fileProperties.filePath;

      if (['twiddle.json','router', 'css'].indexOf(type)===-1) {
        filePath = prompt('File path', filePath);
      }
      if (this.isPathInvalid(type, filePath)) {
        return;
      }
      this.createFile(filePath, fileProperties);
    },

    renameFile (file) {
      let filePath = prompt('File path', file.get('filePath'));
      if (filePath) {
        if(this.get('model.files').findBy('filePath', filePath)) {
          alert('A file with the name %@ already exists'.fmt(filePath));
          return;
        }

        file.set('filePath', filePath);
        this.notify.info('File %@ was added'.fmt(file.get('filePath')));
      }
    },

    removeFile (file) {
      if(confirm(`Are you sure you want to remove this file?\n\n${file.get('filePath')}`)) {
        file.deleteRecord();
        this.notify.info('File %@ was deleted'.fmt(file.get('filePath')));
        this._removeFileFromColumns(file);

        this.send('contentsChanged');
      }
    },

    removeColumn (col) {
      let numColumns = this.get('realNumColumns');

      for (var i = (col|0); i < numColumns; ++i) {
        this.set("col" + i + "File", this.get("col" + (i + 1) + "File"));
      }
      this.set("col" + numColumns + "File", undefined);

      let activeCol = this.get('activeEditorCol');
      if (activeCol >= col) {
        this.set('activeEditorCol', ((activeCol|0) - 1).toString());
      }

      this.transitionToRoute({queryParams: {numColumns: numColumns - 1}});
    },

    addColumn() {
      let numColumns = this.get('realNumColumns');

      this.transitionToRoute({queryParams: {numColumns: numColumns + 1}}).then(this.initializeColumns.bind(this));
    },

    setEditorKeyMap (keyMap) {
      const settings = this.get('settings');
      settings.set('keyMap', keyMap);
      settings.save();
    }
  },

  _removeFileFromColumns (file) {
    if(this.get('col1File') === file) {
      this.setColumnFile(1, null);
    }
    if(this.get('col2File') === file) {
      this.setColumnFile(2, null);
    }
    if(this.get('col3File') === file) {
      this.setColumnFile(3, null);
    }
  },

  setupWindowUpdate: function() {
    // TODO: this in a controller seems suspect, rather this should likely be
    // part of some handshake, to ensure no races exist. This should likley not
    // be something a controller would handle - (SP)
    window.addEventListener('message', (m) => {
      run(() => {
        if(typeof m.data==='object' && 'setDemoAppUrl' in m.data) {
          if (!this.get('isDestroyed')) {
            this.set('applicationUrl', m.data.setDemoAppUrl || '/');
          }
        }
      });
    });
  }
});
<commit_msg>Cleanup after merge<commit_after>import Ember from "ember";
import config from '../config/environment';
import Settings from '../models/settings';
import ErrorMessages from 'ember-twiddle/helpers/error-messages';

const {
  computed,
  run
} = Ember;

const MAX_COLUMNS = 3;

export default Ember.Controller.extend({
  emberCli: Ember.inject.service('ember-cli'),
  version: config.APP.version,

  queryParams: ['numColumns'],
  numColumns: 2,

  init() {
    this._super(...arguments);
    this.setupWindowUpdate();
  },

  /**
   * Output from the build, sets the `code` attr on the component
   * @type {String}
   */
  buildOutput: '',

  /**
   * If the code is currently being built
   * @type {boolean}
   */
  isBuilding: false,

  /**
   * If the edited code has not been saved by the user
   * @type {boolean}
   */
  unsaved: true,

  /**
   * File in the current active editor column
   * @type {Object}
   */
  activeFile: null,

  /**
   * Column which has the currently focused editor
   * @type {Number}
   */
  activeEditorCol: null,

  col1File: null,
  col2File: null,
  col3File: null,
  col1Active: computed.equal('activeEditorCol','1'),
  col2Active: computed.equal('activeEditorCol','2'),
  col3Active: computed.equal('activeEditorCol','3'),
  showCol1: computed.gte('realNumColumns', 1),
  showCol2: computed.gte('realNumColumns', 2),
  showCol3: computed.gte('realNumColumns', 3),

  settings: Settings.create(),

  /**
   * Errors during build
   * @type {Array}     Array of errors
   */
  buildErrors: null,

  /**
   * Whether user wishes the code to automatically run
   * @type {boolean}
   */
  isLiveReload: true,

  /**
   * Build the application and set the iframe code
   */
  buildApp () {
    if (this.get('isDestroyed')) {
      return;
    }

    this.set('isBuilding', true);
    this.set('buildErrors', []);

    this.get('emberCli').compileGist(this.get('model')).then(buildOutput => {
      this.set('isBuilding', false);
      this.set('buildOutput', buildOutput);
    })
    .catch(errors => {
      this.set('isBuilding', false);
      this.set('buildErrors', errors);
      errors.forEach(error => {
        console.error(error);
      });
    });
  },

  realNumColumns: computed('numColumns', function() {
    return Math.min(this.get('numColumns'), MAX_COLUMNS);
  }),
  noColumns: computed.equal('numColumns', 0),

  /**
   * Set the initial file columns
   */
  initializeColumns() {
    let files = this.get('model.files');
    let numColumns = this.get('realNumColumns');

    let j = 0;
    for (let i = 0; i < numColumns; ++i) {
      let key = 'col' + (i + 1) + 'File';
      if (!this.get(key)) {
        if (files) {
          j = 0;
          while (!this.isOpen(files.objectAt(j))) {
            j++;
          }
          let file = files.objectAt(j);
          if (file) {
            this.set(key, file);
          }
        }
      }
    }
  },

  /**
   * Returns true if the passed in file is currently open
   * @param {Object} one of the files in the gist
   * @return {boolean}
   */
  isOpen(file) {
    if (!file) {
      return false;
    }

    for (let i = 1; i <= MAX_COLUMNS; ++i) {
      if (this.get(`col${i}File.fileName`) === file.get('fileName')){
        return false;
      }
    }

    return true;
  },

  rebuildApp: function() {
    if (this.get('isLiveReload')) {
      run.debounce(this, this.buildApp, 500);
    }
  },

  createFile(filePath, fileProperties, fileColumn=1) {
    if (filePath) {
      if(this.get('model.files').findBy('filePath', filePath)) {
        alert('A file with the name %@ already exists'.fmt(filePath));
        return;
      }

      fileProperties.filePath = filePath;
      let file = this.store.createRecord('gistFile', fileProperties);

      this.get('model.files').pushObject(file);
      this.notify.info('File %@ was added'.fmt(file.get('filePath')));
      this.setColumnFile(fileColumn, file);
      this.set('activeEditorCol', '1');
      this.send('contentsChanged');
    }
  },

  /*
   *  Test whether path is valid.  Presently only tests whether components are hyphenated.
   */
  isPathInvalid(type, path){
    let errorMsg = null;
    if (type.match(/^component/)) {
      if(!path.match(/-[^\/]+$/)) {
         errorMsg = ErrorMessages.componentsNeedHyphens;
      }
    }
    if (errorMsg) {
      alert(errorMsg);
      return true;
    }
    return false;
  },

  getColumnFile(column) {
    return this.get(`col${column}File`);
  },

  setColumnFile(column, file){
    let fileColumn = `col${column}File`;
    this.set(fileColumn, file);
  },

  actions: {
    contentsChanged() {
      this.set('unsaved', true);
      this.rebuildApp();
    },

    liveReloadChanged(isLiveReload) {
      this.set('isLiveReload', isLiveReload);
      this.rebuildApp();
    },

    focusEditor (editor) {
      this.set('activeEditorCol', editor.get('col'));
      this.set('activeFile', editor.get('file'));
    },

    selectFile (file) {
      this.set('activeFile', file);
    },

    runNow () {
      this.buildApp();
    },

    deleteGist (gist) {
      if(confirm(`Are you sure you want to remove this gist from Github?\n\n${gist.get('description')}`)) {
        gist.destroyRecord();
        this.transitionToRoute('gist.new');
        this.notify.info('Gist %@ was deleted from Github'.fmt(gist.get('id')));
      }
    },

    addComponent() {
      let path = prompt('Component path (without file extension)', 'components/my-component');
      if (Ember.isBlank(path)){
        return;
      }

      //strip file extension if present
      path = path.replace(/\.[^/.]+$/, "");

      if (this.isPathInvalid('component', path)) {
        return;
      }
      ['js', 'hbs'].forEach((fileExt, i)=>{
        let fileProperties = this.get('emberCli').buildProperties(`component-${fileExt}`);
        let filePath =  `${fileExt === 'hbs' ? 'templates/' : ''}${path}.${fileExt}`;
        let fileColumn = i+1;
        this.createFile(filePath, fileProperties, fileColumn);
      });
    },

    /**
     * Add a new file to the model
     * @param {String|null} type Blueprint name or null for empty file
     */
    addFile (type) {
      let fileProperties = type ? this.get('emberCli').buildProperties(type) : {filePath:'file.js'};
      let filePath = fileProperties.filePath;

      if (['twiddle.json','router', 'css'].indexOf(type)===-1) {
        filePath = prompt('File path', filePath);
      }
      if (this.isPathInvalid(type, filePath)) {
        return;
      }
      this.createFile(filePath, fileProperties);
    },

    renameFile (file) {
      let filePath = prompt('File path', file.get('filePath'));
      if (filePath) {
        if(this.get('model.files').findBy('filePath', filePath)) {
          alert('A file with the name %@ already exists'.fmt(filePath));
          return;
        }

        file.set('filePath', filePath);
        this.notify.info('File %@ was added'.fmt(file.get('filePath')));
      }
    },

    removeFile (file) {
      if(confirm(`Are you sure you want to remove this file?\n\n${file.get('filePath')}`)) {
        file.deleteRecord();
        this.notify.info('File %@ was deleted'.fmt(file.get('filePath')));
        this._removeFileFromColumns(file);

        this.send('contentsChanged');
      }
    },

    removeColumn (col) {
      let numColumns = this.get('realNumColumns');

      for (var i = (col|0); i < numColumns; ++i) {
        this.setColumnFile(i, this.getColumnFile(i + 1));
      }
      this.setColumnFile(numColumns, undefined);

      let activeCol = this.get('activeEditorCol');
      if (activeCol >= col) {
        this.set('activeEditorCol', ((activeCol|0) - 1).toString());
      }

      this.transitionToRoute({queryParams: {numColumns: numColumns - 1}});
    },

    addColumn() {
      let numColumns = this.get('realNumColumns');

      this.transitionToRoute({queryParams: {numColumns: numColumns + 1}}).then(this.initializeColumns.bind(this));
    },

    setEditorKeyMap (keyMap) {
      const settings = this.get('settings');
      settings.set('keyMap', keyMap);
      settings.save();
    }
  },

  _removeFileFromColumns (file) {
    for (let i = 1; i <= MAX_COLUMNS; ++i) {
      if (this.getColumnFile(i) === file) {
        this.setColumnFile(i, null);
      }
    }
  },

  setupWindowUpdate: function() {
    // TODO: this in a controller seems suspect, rather this should likely be
    // part of some handshake, to ensure no races exist. This should likley not
    // be something a controller would handle - (SP)
    window.addEventListener('message', (m) => {
      run(() => {
        if(typeof m.data==='object' && 'setDemoAppUrl' in m.data) {
          if (!this.get('isDestroyed')) {
            this.set('applicationUrl', m.data.setDemoAppUrl || '/');
          }
        }
      });
    });
  }
});
<|endoftext|>


<commit_before>import AbstractModuleRoute from 'hospitalrun/routes/abstract-module-route';
import FulfillRequest from "hospitalrun/mixins/fulfill-request";
import InventoryId from "hospitalrun/mixins/inventory-id";
import InventoryLocations from "hospitalrun/mixins/inventory-locations"; //inventory-locations mixin is needed for fulfill-request mixin!
export default AbstractModuleRoute.extend(FulfillRequest, InventoryId, InventoryLocations, {
    addCapability: 'add_inventory_item',
    additionalModels: [{
        name: 'aisleLocationList',
        findArgs: ['lookup','aisle_location_list']
    }, {
        name: 'deliveryLocationList',
        findArgs: ['lookup','delivery_location_list']
    }, {
        name: 'expenseAccountList',
        findArgs: ['lookup','expense_account_list']
    }, {
        name: 'warehouseList',
        findArgs: ['lookup','warehouse_list']
    }
  ],

    currentItem: null,
    modelName: 'inventory',
    moduleName: 'inventory',

    newButtonText: '+ new request',
    subActions: [{
        text: 'Requests',
        linkTo: 'inventory.index'
    }, {
        text: 'Items',
        linkTo: 'inventory.listing'
    }, {
        text: 'History',
        linkTo: 'inventory.completed'
    }],
    sectionTitle: 'Inventory',

    actions: {
        addPurchase: function(newPurchase) {
            var currentItem = this.get('currentItem'),
                purchases = currentItem.get('purchases');
            purchases.addObject(newPurchase);
            this.newPurchaseAdded(currentItem, newPurchase);
            currentItem.updateQuantity();
            currentItem.save();
            this.send('closeModal');
        },

        newRequest: function() {
            var newId = this.generateId();
            var data = this.getNewData();
            if (newId) {
                data.id = newId;
            }
            var item = this.get('store').createRecord('inv-request', {
                transactionType: 'Request'
            });
            this.transitionTo('inventory.request', item);
        },

        allItems: function() {
            this.transitionTo('inventory.listing');
        },

        newDelivery: function() {
            var item = this.get('store').createRecord('inv-request', {
                dateCompleted: new Date(),
                transactionType: 'Delivery'
            });
            this.transitionTo('inventory.delivery', item);
        },

        showAddPurchase: function(inventoryItem) {
            var newPurchase = this.get('store').createRecord('inv-purchase', {
                distributionUnit: inventoryItem.get('distributionUnit')
            });
            this.set('currentItem', inventoryItem);
            this.send('openModal', 'inventory.purchase.edit', newPurchase);
        }

    },

    /**
     * Define what data a new inventory item should be instantiated with.
     * The only default is to set the type to asset; at some point this may be driven by subsection of inventory you are in.
     * @return the default properties for a new inventory item.
     */
    getNewData: function() {
        return  {
            type: 'Asset'
        };
    }
});<commit_msg>Removed unused code.<commit_after>import AbstractModuleRoute from 'hospitalrun/routes/abstract-module-route';
import FulfillRequest from "hospitalrun/mixins/fulfill-request";
import InventoryId from "hospitalrun/mixins/inventory-id";
import InventoryLocations from "hospitalrun/mixins/inventory-locations"; //inventory-locations mixin is needed for fulfill-request mixin!
export default AbstractModuleRoute.extend(FulfillRequest, InventoryId, InventoryLocations, {
    addCapability: 'add_inventory_item',
    additionalModels: [{
        name: 'aisleLocationList',
        findArgs: ['lookup','aisle_location_list']
    }, {
        name: 'deliveryLocationList',
        findArgs: ['lookup','delivery_location_list']
    }, {
        name: 'expenseAccountList',
        findArgs: ['lookup','expense_account_list']
    }, {
        name: 'warehouseList',
        findArgs: ['lookup','warehouse_list']
    }
  ],

    currentItem: null,
    modelName: 'inventory',
    moduleName: 'inventory',

    newButtonText: '+ new request',
    subActions: [{
        text: 'Requests',
        linkTo: 'inventory.index'
    }, {
        text: 'Items',
        linkTo: 'inventory.listing'
    }, {
        text: 'History',
        linkTo: 'inventory.completed'
    }],
    sectionTitle: 'Inventory',

    actions: {
        addPurchase: function(newPurchase) {
            var currentItem = this.get('currentItem'),
                purchases = currentItem.get('purchases');
            purchases.addObject(newPurchase);
            this.newPurchaseAdded(currentItem, newPurchase);
            currentItem.updateQuantity();
            currentItem.save();
            this.send('closeModal');
        },

        newRequest: function() {
            var newId = this.generateId();
            var data = this.getNewData();
            if (newId) {
                data.id = newId;
            }
            var item = this.get('store').createRecord('inv-request', {
                transactionType: 'Request'
            });
            this.transitionTo('inventory.request', item);
        },

        allItems: function() {
            this.transitionTo('inventory.listing');
        },

        showAddPurchase: function(inventoryItem) {
            var newPurchase = this.get('store').createRecord('inv-purchase', {
                distributionUnit: inventoryItem.get('distributionUnit')
            });
            this.set('currentItem', inventoryItem);
            this.send('openModal', 'inventory.purchase.edit', newPurchase);
        }

    },

    /**
     * Define what data a new inventory item should be instantiated with.
     * The only default is to set the type to asset; at some point this may be driven by subsection of inventory you are in.
     * @return the default properties for a new inventory item.
     */
    getNewData: function() {
        return  {
            type: 'Asset'
        };
    }
});<|endoftext|>


<commit_before>var OMDB_URL = 'https://www.omdbapi.com/?';
var API_KEY = "placeholder";
var TIMEOUT = 3000;

var fetchedCache = {};
var fetchingCache = {};

function fetchRatings(title, season, episode, year, callback) {
	argsString = Array.from(arguments).slice(0, 4).join(", ");
	var cacheKey = hashKey(title, season, episode, year);
	if (fetchedCache[cacheKey]) {
		log("Cached ratings for " + argsString);
		callback(fetchedCache[cacheKey]);
	} else if (!fetchingCache[cacheKey]) {
		log("Fetching ratings for " + argsString);
		fetchingCache[cacheKey] = true;
		$.ajax({
			url: OMDB_URL,
			dataType: 'json',
			data: requestOptions(title, season, episode, year),
			success: function(response) {
				if (!response.imdbRating && year) {
					log("Failed to fetch ratings for " + argsString);
					delete fetchingCache[cacheKey];
					return fetchRatings(title, season, episode, null, callback);
				}
				var ratings = {
					imdb: response.imdbRating,
					imdbID: response.imdbID,
					rt: fetchRTRating(response),
					metacritic: response.Metascore
				}
				log("Fetched ratings for " + argsString + ": " + JSON.stringify(ratings));
				fetchedCache[cacheKey] = ratings;
				callback(ratings);
			},
			error: function(jqXHR, status, errorThrown) {
				if (status == "timeout") {
					log("Failed to fetch ratings for " + argsString + " due to timeout");
					delete fetchingCache[cacheKey];
					fetchRatings(title, season, episode, null, callback);
				}
			},
			timeout: TIMEOUT
		});
	}
}

function fetchRTRating(response) {
	var ratingsArray = response["Ratings"];
	if (ratingsArray) {
		var rtRating = ratingsArray.find(rtFilter);
		if (rtRating) {
			return rtRating["Value"];
		}
	}
}

function rtFilter(rating) {
	return rating["Source"] == "Rotten Tomatoes";
}

function requestOptions(title, season, episode, year) {
	var options = {
		"apikey": API_KEY
	};
	if (title) {
		options["t"] = title;
	}
	if (season) {
		options["Season"] = season;
	}
	if (episode) {
		options["Episode"] = episode;
	}
	if (year) {
		options["y"] = year;
	}
	return options;
}

function hashKey(title, season, episode, year) {
	return "Title:" + title + "&Season:" + season + "&Episode:" + episode + "&Year:" + year;
}<commit_msg>Use new omdb url<commit_after>var OMDB_URL = 'https://private.omdbapi.com/?';
var API_KEY = "placeholder";
var TIMEOUT = 3000;

var fetchedCache = {};
var fetchingCache = {};

function fetchRatings(title, season, episode, year, callback) {
	argsString = Array.from(arguments).slice(0, 4).join(", ");
	var cacheKey = hashKey(title, season, episode, year);
	if (fetchedCache[cacheKey]) {
		log("Cached ratings for " + argsString);
		callback(fetchedCache[cacheKey]);
	} else if (!fetchingCache[cacheKey]) {
		log("Fetching ratings for " + argsString);
		fetchingCache[cacheKey] = true;
		$.ajax({
			url: OMDB_URL,
			dataType: 'json',
			data: requestOptions(title, season, episode, year),
			success: function(response) {
				if (!response.imdbRating && year) {
					log("Failed to fetch ratings for " + argsString);
					delete fetchingCache[cacheKey];
					return fetchRatings(title, season, episode, null, callback);
				}
				var ratings = {
					imdb: response.imdbRating,
					imdbID: response.imdbID,
					rt: fetchRTRating(response),
					metacritic: response.Metascore
				}
				log("Fetched ratings for " + argsString + ": " + JSON.stringify(ratings));
				fetchedCache[cacheKey] = ratings;
				callback(ratings);
			},
			error: function(jqXHR, status, errorThrown) {
				if (status == "timeout") {
					log("Failed to fetch ratings for " + argsString + " due to timeout");
					delete fetchingCache[cacheKey];
					fetchRatings(title, season, episode, null, callback);
				}
			},
			timeout: TIMEOUT
		});
	}
}

function fetchRTRating(response) {
	var ratingsArray = response["Ratings"];
	if (ratingsArray) {
		var rtRating = ratingsArray.find(rtFilter);
		if (rtRating) {
			return rtRating["Value"];
		}
	}
}

function rtFilter(rating) {
	return rating["Source"] == "Rotten Tomatoes";
}

function requestOptions(title, season, episode, year) {
	var options = {
		"apikey": API_KEY
	};
	if (title) {
		options["t"] = title;
	}
	if (season) {
		options["Season"] = season;
	}
	if (episode) {
		options["Episode"] = episode;
	}
	if (year) {
		options["y"] = year;
	}
	return options;
}

function hashKey(title, season, episode, year) {
	return "Title:" + title + "&Season:" + season + "&Episode:" + episode + "&Year:" + year;
}<|endoftext|>


<commit_before>// import {} from "../stylesheets/app.css";
import 'react-notifications/lib/notifications.css';
import React from 'react';
import ReactDOM from 'react-dom';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import FlatButton from 'material-ui/FlatButton';
import ConferenceDetail from './ConferenceDetail';
import FormInput from './FormInput';
import Notification from './Notification';
import Instruction from './Instruction';
import Participants from './Participants';
import Avatar from 'material-ui/Avatar';
import AppBar from 'material-ui/AppBar';
import {List, ListItem} from 'material-ui/List';
import EventEmitter from 'event-emitter';
import Paper from 'material-ui/Paper';
import math from 'mathjs';
import injectTapEventPlugin from 'react-tap-event-plugin';

const styles = {
  div:{
    display: 'flex',
    justifyContent: 'space-between',
    flexDirection: 'row wrap',
    width: '100%'
  }
};

const web3 = new Web3;
const provider = new Web3.providers.HttpProvider("http://localhost:8545");
web3.setProvider(provider);
Conference.setProvider(provider);
const contract = Conference.deployed();
const eventEmitter = EventEmitter()

// Functions to interact with contract
function getDetail(callback){
  Promise.all(['name', 'deposit', 'payout', 'balance', 'registered', 'attended'].map(attributeName => {
    return contract[attributeName].call();
  })).then(values => {
    var detail = {
      'name': values[0],
      'deposit': values[1],
      'payout': values[2],
      'balance': values[3],
      'registered': values[4],
      'attended': values[5],
      'contractBalance': web3.fromWei(web3.eth.getBalance(contract.address), "ether").toNumber()
    }

    if(detail.registered.toNumber() > 0 && detail.attended.toNumber() > 0 && detail.payout.toNumber() > 0){
      detail.canPayback = true
    }
    if(detail.registered.toNumber() > 0 && detail.attended.toNumber() > 0 && detail.payout.toNumber() == 0){
      detail.canReset = true
    }
    if(!detail.canReset){
      detail.canRegister = true
    }

    callback(detail);
  })
}

function getParticipants(callback){
  contract.registered.call().then(value => {
    let participantsArray = []
    for (var i = 1; i <= value.toNumber(); i++) {
      participantsArray.push(i);
    }
    Promise.all(participantsArray.map(index => {
      return contract.participantsIndex.call(index).then(address => {
        return contract.participants.call(address);
      })
    })).then(function(participants){
      return participants.map(participant => {
        var balance =  web3.fromWei(web3.eth.getBalance(participant[1]), "ether").toNumber();
        var object =  {
          name: participant[0],
          address: participant[1],
          attended: participant[2],
          balance: balance
        }
        console.log('participant', object);
        return object
      })
    }).then(participant => { if(participant) callback(participant); })
  })
}
var gas = 1000000;
window.gas = gas
window.eventEmitter = eventEmitter;
function action(name, address, argument) {
  var options = {from:address, gas:window.gas}
  eventEmitter.emit('notification', {status:'info', message:'Requested'});
  if (name == "register") {
    options.value = Math.pow(10,18)
  }

  console.log('name', name, 'address', address, 'argument', argument)
  contract[name](argument, options).then(function() {
    getDetail(function(model){
      eventEmitter.emit('change', model);
      eventEmitter.emit('notification', {status:'success', message:'Successfully Updated'});
    });
  }).catch(function(e) {
    eventEmitter.emit('notification', {status:'error', message:'Error has occored'});
  });
}

function watchEvent(){
  var event = contract.allEvents({fromBlock: 0, toBlock: 'latest'}).watch(function(error, result){
    if (error) {
      console.log("Error: " + error);
    } else {
      console.log('watchEvent result', result);
    }
  });
}

function getAccounts(callback){
  web3.eth.getAccounts(function(err, accs) {
    if (err != null) {
      eventEmitter.emit('instruction')
      return;
    }
    if (accs.length == 0) {
      var message = "Couldn't get any accounts! Make sure your Ethereum client is configured correctly.";
      eventEmitter.emit('notification', {status:'error', message:message});
      return;
    }
    callback(accs);
  })
}

const App = (props) => (

    <MuiThemeProvider muiTheme={getMuiTheme()}>

        <AppBar titleStyle={{textAlign:'center', fontSize:'xx-large', fontFamily:'Lobster'}} style={{backgroundColor:"#607D8B"}}
          title={
            Block Party - NO BLOCK NO PARTY -
          }
          iconElementLeft={<Avatar src="/images/nightclub-white.png" size="50" backgroundColor="white" />}
          iconElementRight={<FlatButton label="About" onClick={ () => {eventEmitter.emit('instruction')}} />}
        />
        <Instruction eventEmitter={eventEmitter} />
        <Notification eventEmitter={eventEmitter} />

          <ConferenceDetail eventEmitter={eventEmitter} getDetail={getDetail} web3={web3} math={math} contract={contract} web3={web3} />
          <Participants eventEmitter={eventEmitter} getDetail={getDetail} getParticipants={getParticipants} web3={web3} math={math} />

        <FormInput eventEmitter={eventEmitter} getAccounts = {getAccounts} getDetail = {getDetail} action = {action} />

    </MuiThemeProvider>

);

window.web3 = web3;
window.onload = function() {
  console.log("LOAD")
  injectTapEventPlugin();
  ReactDOM.render(
    <App
      getAccounts = {getAccounts}
      getDetail = {getDetail}
      eventEmitter = {eventEmitter}
      action = {action}
      getParticipants = {getParticipants}
      web3 = {web3}
      math = {math}
      contract={contract}
    />,
    document.getElementById('app')
  );
}
<commit_msg>Load web3 only if undefined<commit_after>// import {} from "../stylesheets/app.css";
import 'react-notifications/lib/notifications.css';
import React from 'react';
import ReactDOM from 'react-dom';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import FlatButton from 'material-ui/FlatButton';
import ConferenceDetail from './ConferenceDetail';
import FormInput from './FormInput';
import Notification from './Notification';
import Instruction from './Instruction';
import Participants from './Participants';
import Avatar from 'material-ui/Avatar';
import AppBar from 'material-ui/AppBar';
import {List, ListItem} from 'material-ui/List';
import EventEmitter from 'event-emitter';
import Paper from 'material-ui/Paper';
import math from 'mathjs';
import injectTapEventPlugin from 'react-tap-event-plugin';

const styles = {
  div:{
    display: 'flex',
    justifyContent: 'space-between',
    flexDirection: 'row wrap',
    width: '100%'
  }
};

let web3, provider;

if(typeof(web3) == 'undefined'){
  web3 = new Web3;
  provider = new Web3.providers.HttpProvider("http://localhost:8545");
  console.log('NO MIST');
}else{
  provider = web3.currentProvider;
  console.log('MIST');
}
web3.setProvider(provider);
Conference.setProvider(provider);

const contract = Conference.deployed();
const eventEmitter = EventEmitter()

// Functions to interact with contract
function getDetail(callback){
  Promise.all(['name', 'deposit', 'payout', 'balance', 'registered', 'attended'].map(attributeName => {
    return contract[attributeName].call();
  })).then(values => {
    var detail = {
      'name': values[0],
      'deposit': values[1],
      'payout': values[2],
      'balance': values[3],
      'registered': values[4],
      'attended': values[5],
      'contractBalance': web3.fromWei(web3.eth.getBalance(contract.address), "ether").toNumber()
    }

    if(detail.registered.toNumber() > 0 && detail.attended.toNumber() > 0 && detail.payout.toNumber() > 0){
      detail.canPayback = true
    }
    if(detail.registered.toNumber() > 0 && detail.attended.toNumber() > 0 && detail.payout.toNumber() == 0){
      detail.canReset = true
    }
    if(!detail.canReset){
      detail.canRegister = true
    }

    callback(detail);
  })
}

function getParticipants(callback){
  contract.registered.call().then(value => {
    let participantsArray = []
    for (var i = 1; i <= value.toNumber(); i++) {
      participantsArray.push(i);
    }
    Promise.all(participantsArray.map(index => {
      return contract.participantsIndex.call(index).then(address => {
        return contract.participants.call(address);
      })
    })).then(function(participants){
      return participants.map(participant => {
        var balance =  web3.fromWei(web3.eth.getBalance(participant[1]), "ether").toNumber();
        var object =  {
          name: participant[0],
          address: participant[1],
          attended: participant[2],
          balance: balance
        }
        console.log('participant', object);
        return object
      })
    }).then(participant => { if(participant) callback(participant); })
  })
}
var gas = 1000000;
window.gas = gas
window.eventEmitter = eventEmitter;
function action(name, address, argument) {
  var options = {from:address, gas:window.gas}
  eventEmitter.emit('notification', {status:'info', message:'Requested'});
  if (name == "register") {
    options.value = Math.pow(10,18)
  }

  console.log('name', name, 'address', address, 'argument', argument)
  contract[name](argument, options).then(function() {
    getDetail(function(model){
      eventEmitter.emit('change', model);
      eventEmitter.emit('notification', {status:'success', message:'Successfully Updated'});
    });
  }).catch(function(e) {
    eventEmitter.emit('notification', {status:'error', message:'Error has occored'});
  });
}

function watchEvent(){
  var event = contract.allEvents({fromBlock: 0, toBlock: 'latest'}).watch(function(error, result){
    if (error) {
      console.log("Error: " + error);
    } else {
      console.log('watchEvent result', result);
    }
  });
}

function getAccounts(callback){
  web3.eth.getAccounts(function(err, accs) {
    if (err != null) {
      eventEmitter.emit('instruction')
      return;
    }
    if (accs.length == 0) {
      var message = "Couldn't get any accounts! Make sure your Ethereum client is configured correctly.";
      eventEmitter.emit('notification', {status:'error', message:message});
      return;
    }
    callback(accs);
  })
}

const App = (props) => (

    <MuiThemeProvider muiTheme={getMuiTheme()}>

        <AppBar titleStyle={{textAlign:'center', fontSize:'xx-large', fontFamily:'Lobster'}} style={{backgroundColor:"#607D8B"}}
          title={
            Block Party - NO BLOCK NO PARTY -
          }
          iconElementLeft={<Avatar src="/images/nightclub-white.png" size="50" backgroundColor="white" />}
          iconElementRight={<FlatButton label="About" onClick={ () => {eventEmitter.emit('instruction')}} />}
        />
        <Instruction eventEmitter={eventEmitter} />
        <Notification eventEmitter={eventEmitter} />

          <ConferenceDetail eventEmitter={eventEmitter} getDetail={getDetail} web3={web3} math={math} contract={contract} web3={web3} />
          <Participants eventEmitter={eventEmitter} getDetail={getDetail} getParticipants={getParticipants} web3={web3} math={math} />

        <FormInput eventEmitter={eventEmitter} getAccounts = {getAccounts} getDetail = {getDetail} action = {action} />

    </MuiThemeProvider>

);

window.web3 = web3;
window.onload = function() {
  console.log("LOAD")
  injectTapEventPlugin();
  ReactDOM.render(
    <App
      getAccounts = {getAccounts}
      getDetail = {getDetail}
      eventEmitter = {eventEmitter}
      action = {action}
      getParticipants = {getParticipants}
      web3 = {web3}
      math = {math}
      contract={contract}
    />,
    document.getElementById('app')
  );
}
<|endoftext|>


<commit_before>// import {} from "../stylesheets/app.css";
import React from 'react';
import ReactDOM from 'react-dom';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import ConferenceDetail from './ConferenceDetail';
import FormInput from './FormInput';
import IconButton from 'material-ui/IconButton';
import AccountBalanceIcon from 'material-ui/svg-icons/action/account-balance'
import AppBar from 'material-ui/AppBar';
import Subheader from 'material-ui/Subheader';
import EventEmitter from 'event-emitter';

const App = (props) => (

    <MuiThemeProvider muiTheme={getMuiTheme()}>

        <AppBar
          title="Block Party - NO BLOCK NO PARTY"
          iconElementLeft={<IconButton><AccountBalanceIcon /></IconButton>}
        />
        <ConferenceDetail eventEmitter={eventEmitter} getDetail={getDetail} web3={web3} />
        <Subheader>Registration</Subheader>
        <FormInput action={action} />

    </MuiThemeProvider>

);

// Some settings to connect to Ethereum.
const Pudding = require("ether-pudding");
const web3 = new Web3();
Pudding.setWeb3(web3);
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
Conference.load(Pudding);
const contract = Conference.deployed();
const eventEmitter = EventEmitter()

// Functions to interact with contract
function getDetail(callback){
  Promise.all(['name', 'deposit', 'pot', 'balance', 'registered', 'attended'].map(name => {
    return contract[name].call();
  })).then(values => {
    callback({
      'name': values[0],
      'deposit': values[1],
      'pot': values[2],
      'balance': values[3],
      'registered': values[4],
      'attended': values[5]
    });
  }).catch(errors => {
    console.log('errors', errors);
  });
}

function action(name, address, callback) {
  var amount = Math.pow(10,18)
  console.log('name', name, 'address', address, 'callback', callback)
  var gas = 2000000;
  contract[name](null, {from:address, value:amount, gas:gas}).then(function() {
    getDetail(function(model){
      eventEmitter.emit('change', model);
    });
    if(callback) callback();
  }).catch(function(e) {
    console.log(e);
  });
}

function watchEvent(){
  var event = contract.allEvents({fromBlock: 0, toBlock: 'latest'}).watch(function(error, result){
    if (error) {
      console.log("Error: " + error);
    } else {

    }
  });
}

// Log all available accounts
web3.eth.getAccounts(function(err, accs) {
  if (err != null) {
    alert("There was an error fetching your accounts.");
    return;
  }
  if (accs.length == 0) {
    alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
    return;
  }
  console.log(accs);
});

window.onload = function() {
  ReactDOM.render(
    <App getDetail={getDetail} eventEmitter={eventEmitter} action={action} web3={web3} />,
    document.getElementById('app')
  );
}
<commit_msg>Add helper function to show the balance of contract and all participants<commit_after>// import {} from "../stylesheets/app.css";
import React from 'react';
import ReactDOM from 'react-dom';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import ConferenceDetail from './ConferenceDetail';
import FormInput from './FormInput';
import IconButton from 'material-ui/IconButton';
import AccountBalanceIcon from 'material-ui/svg-icons/action/account-balance'
import AppBar from 'material-ui/AppBar';
import Subheader from 'material-ui/Subheader';
import EventEmitter from 'event-emitter';

const App = (props) => (

    <MuiThemeProvider muiTheme={getMuiTheme()}>

        <AppBar
          title="Block Party - NO BLOCK NO PARTY"
          iconElementLeft={<IconButton><AccountBalanceIcon /></IconButton>}
        />
        <ConferenceDetail eventEmitter={eventEmitter} getDetail={getDetail} web3={web3} />
        <Subheader>Registration</Subheader>
        <FormInput action={action} />

    </MuiThemeProvider>

);

// Some settings to connect to Ethereum.
const Pudding = require("ether-pudding");
const web3 = new Web3();
Pudding.setWeb3(web3);
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
Conference.load(Pudding);
const contract = Conference.deployed();
const eventEmitter = EventEmitter()

// Functions to interact with contract
function getDetail(callback){
  Promise.all(['name', 'deposit', 'pot', 'balance', 'registered', 'attended'].map(name => {
    return contract[name].call();
  })).then(values => {
    callback({
      'name': values[0],
      'deposit': values[1],
      'pot': values[2],
      'balance': values[3],
      'registered': values[4],
      'attended': values[5]
    });
  }).catch(errors => {
    console.log('errors', errors);
  });
}

function getParticipants(callback){
  contract.registered.call().then(function(value){
    // var contractBalance = web3.eth.getBalance(contract.address);
    console.log('contract', contract.address, web3.fromWei(contractBalance, "ether").toNumber());
    let participantsArray = []
    for (var i = 1; i <= value.toNumber(); i++) {
      contract.participantsIndex.call(i).then(function(address){
        var balance = web3.eth.getBalance(address)
        console.log('address', address, web3.fromWei(balance, "ether").toNumber())
        return address;
      }).then(function(address){
        return contract.participants.call(address)
      }).then(function(participant){
        console.log('participant', participant)
      })
    }
  })
}

function action(name, address, callback) {
  var amount = Math.pow(10,18)
  console.log('name', name, 'address', address, 'callback', callback)
  var gas = 2000000;
  contract[name](null, {from:address, value:amount, gas:gas}).then(function() {
    getDetail(function(model){
      eventEmitter.emit('change', model);
    });
    if(callback) callback();
  }).catch(function(e) {
    console.log(e);
  });
}

function watchEvent(){
  var event = contract.allEvents({fromBlock: 0, toBlock: 'latest'}).watch(function(error, result){
    if (error) {
      console.log("Error: " + error);
    } else {

    }
  });
}

// Log all available accounts
web3.eth.getAccounts(function(err, accs) {
  window.accounts = accs;
  window.web3 = web3;
  window.getParticipants = getParticipants;
  window.contract = contract;
  if (err != null) {
    alert("There was an error fetching your accounts.");
    return;
  }
  if (accs.length == 0) {
    alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
    return;
  }
  console.log(accs);
});

window.onload = function() {
  ReactDOM.render(
    <App getDetail={getDetail} eventEmitter={eventEmitter} action={action} web3={web3} />,
    document.getElementById('app')
  );
}
<|endoftext|>


<commit_before>var Ξ=[],//stack
		//I/O functions
		ô=i=>document.getElementById('o').value+=i!=[]._?i:(Ξ.shift(),Ξ.join`\n`),//output
		ℹ=i=>[i=i!=[]._?document.getElementById("c").value[i]:document.getElementById("c").value,Ξ.push(i)][0],//source

		//stack functions
		ᵖ=(i=0,...r)=>{Ξ.push(i,...r)},
		ᵍ=i=>i!=[]._?Ξ[i<0?Ξ.length+i:i]:Ξ[Ξ.length-1],
		ʳ=(i=Ξ.length-1)=>Ξ.splice(i,1),
		ᶜ=i=>Ξ=[],

		//super-basic aliasing
		ȉ=Infinity,
		ߎ=[]._,
		ℇ=math.e,
		ε=Number.EPSILON,
		ȋ=math.sqrt(-1),
		ɸ=(1+math.sqrt(5))/2,
		π=math.pi,
		τ=math.pi*2,
		М=math,
		Ϛ=String,
		Ѧ=Array,
		Ⱥ=_,
		П=Number,
		Ø=Object,
		ʝ=JSON,
		ɼ=RegExp,
		Ḍ=Date,
		ש=window,
		ß='toString',
		ξ=s,
		ɘ=i=>LZString.decompress(i),
		ᴙ=i=>[...i].reverse().join``,
		ë=eval;
[Ϛ,Ѧ,П,Ø,ɼ,Ḍ,ξ,Ⱥ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v.prototype[String.fromCharCode(y+248)]=v.prototype[x]));
[М,Ϛ,Ѧ,П,Ø,ʝ,ɼ,Ḍ,Ⱥ,ξ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v[String.fromCharCode(y+248)]=v[x]));
[ש].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v['ש'+String.fromCharCode(y+248)]=v[x]));
var Σ=(c,asdf=0)=>{
	//syntax from esmin to es6
	c=c
		.replace(/ɘ(.+)#/g,(x,y)=>ɘ(y))
		.replace(/ℍ/g,'00')
		.replace(/𝕜/g,'000')
		.replace(/𝕄/g,'000000')
		.replace(/𝔾/g,'000000000')
		.replace(/𝕋/g,'000000000000')
		.replace(/ℙ/g,'000000000000000')
		.replace(/𝔼/g,'000000000000000000')
		.replace(/ℤ/g,'000000000000000000000')
		.replace(/𝕐/g,'000000000000000000000000')
		.replace(/⬮/g,'()')
		.replace(/⬯/g,'(``)')
		.replace(/⇝/g,'((a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/⇀/g,'(($,_,ã)=>')
		.replace(/§/g,'($1)')
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØȺɼḌᴙξëß\u00f8-\u01ef])([A-Za-z$_ãï]+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?|[ȉℇεȋɸπτ])/g,'$1($2)')
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØɼȺḌᴙξëß\u00f8-\u01ef])([^(\u00f8-\u01ef])/g,'$1($2')
		.replace(/ï(\d+)/g,'ï[$1]')
		.replace(/⇏/g,'(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↛/g,'=(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↪/g,'($,_,ã)=>')
		.replace(/⤤/g,'=($,_,ã)=>')
		.replace(/→/g,'=>')
		.replace(/”/g,'`)')
		.replace(/‘/g,'\\`')
		.replace(/’/g,'\\`)')
		.replace(/⸩/g,'))')
		.replace(/⎞/g,'/)')
		.replace(/⦃/g,'${')
		.replace(/…/g,'...')
		.replace(/⟦/g,'[...')
		.replace(/˖/g,'+=')
		.replace(/⧺/g,'++')
		.replace(/˗/g,'-=')
		.replace(/‡/g,'--')
		.replace(/×/g,'*=')
		.replace(/÷/g,'/=')
		.replace(/٪/g,'%=')
		.replace(/¡/g,'!!')
		.replace(/≔/g,'==')
		.replace(/≠/g,'!=')
		.replace(/≤/g,'<=')
		.replace(/≥/g,'>=')
		.replace(/⅋/g,'&&')
		.replace(/⋎/g,'||')
		.replace(/↺/g,'for(')
		.replace(/ᶉ/g,'return ')
		.replace(/ŋ/g,'new ')
		.replace(/\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)²/g,'Math.pow($1,2)')
		.replace(/\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)³/g,'Math.pow($1,3)')
		.replace(/\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)ⁿ\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)/g,'Math.pow($1,$2)')
		.replace(/√\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)/g,'Math.sqrt($1)')
		.replace(/∛\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)/g,'Math.cbrt($1)')
		.replace(/½/g,'0.5')
		.replace(/¼/g,'0.25')
		.replace(/¾/g,'0.75')
		.replace(/⅐/g,'(1/7)')
		.replace(/⅑/g,'(1/9)')
		.replace(/⅒/g,'0.1')
		.replace(/⅓/g,'(1/3)')
		.replace(/⅔/g,'(2/3)')
		.replace(/⅕/g,'0.2')
		.replace(/⅖/g,'0.4')
		.replace(/⅗/g,'0.6')
		.replace(/⅘/g,'0.8')
		.replace(/⅙/g,'(1/6)')
		.replace(/⅚/g,'(5/6)')
		.replace(/⅛/g,'(1/8)')
		.replace(/⅜/g,'(3/8)')
		.replace(/⅝/g,'(5/8)')
		.replace(/⅞/g,'(7/8)')
		.replace(/ᶀ/g,'0b')
		.replace(/ᶍ/g,'0x')
		.replace(/Ⅹ/g,'10')
		.replace(/([\u00f8-\u01ef])/g,'["$1"]')
		.replace(/ß/g,'[ß]')
		.replace(/⌿/g,'/g')
		.replace(/⍀/g,'/ig')
		.replace(/⊨/g,'true')
		.replace(/⊭/g,'false')
		.replace(/«/g,'<<')
		.replace(/»/g,'>>')
		.replace(/⫸/g,'>>>')
		.replace(/˜/g,'~~')
	;
	if(asdf==1e4&&!c.match(/ô/g))c+=';ô()';console.log(c);eval(c)
}
<commit_msg>added number vars 0-256<commit_after>var Ξ=[],//stack
		//I/O functions
		ô=i=>document.getElementById('o').value+=i!=[]._?i:(Ξ.shift(),Ξ.join`\n`),//output
		ℹ=i=>[i=i!=[]._?document.getElementById("c").value[i]:document.getElementById("c").value,Ξ.push(i)][0],//source

		//stack functions
		ᵖ=(i=0,...r)=>{Ξ.push(i,...r)},
		ᵍ=i=>i!=[]._?Ξ[i<0?Ξ.length+i:i]:Ξ[Ξ.length-1],
		ʳ=(i=Ξ.length-1)=>Ξ.splice(i,1),
		ᶜ=i=>Ξ=[],

		//aliasing
		ȉ=Infinity,
		ߎ=[]._,
		ℇ=math.e,
		ε=Number.EPSILON,
		ȋ=math.sqrt(-1),
		ɸ=(1+math.sqrt(5))/2,
		π=math.pi,
		τ=math.pi*2,
		М=math,
		Ϛ=String,
		Ѧ=Array,
		Ⱥ=_,
		П=Number,
		Ø=Object,
		ʝ=JSON,
		ɼ=RegExp,
		Ḍ=Date,
		ש=window,
		ß='toString',
		ξ=s,
		ɘ=i=>LZString.decompress(i),
		ᴙ=i=>[...i].reverse().join``,
		ë=eval;
[Ϛ,Ѧ,П,Ø,ɼ,Ḍ,ξ,Ⱥ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v.prototype[String.fromCharCode(y+248)]=v.prototype[x]));
[М,Ϛ,Ѧ,П,Ø,ʝ,ɼ,Ḍ,Ⱥ,ξ].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v[String.fromCharCode(y+248)]=v[x]));
[ש].map(v=>Object.getOwnPropertyNames(v).map((x,y)=>v['ש'+String.fromCharCode(y+248)]=v[x]));
[...`ḀḁḂḃḄḅḆḇḈḉḊḋḌḍḎḏḐḑḒḓḔḕḖḗḘḙḚḛḜḝḞḟḠḡḢḣḤḥḦḧḨḩḪḫḬḭḮḯḰḱḲḳḴḵḶḷḸḹḺḻḼḽḾḿṀṁṂṃṄṅṆṇṈṉṊṋṌṍṎṏṐṑṒṓṔṕṖṗṘṙṚṛṜṝṞṟṠṡṢṣṤṥṦṧṨṩṪṫṬṭṮṯṰṱṲṳṴṵṶṷṸṹṺṻṼṽṾṿẀẁẂẃẄẅẆẇẈẉẊẋẌẍẎẏẐẑẒẓẔẕẖẗẘẙaʾẛẜẝẞẟẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐốỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹỺỻỼỽỾỿ`].map((x,y)=>{eval(`var ${v}=`+x)});
var Σ=(c,asdf=0)=>{
	//syntax from esmin to es6
	c=c
		.replace(/ɘ(.+)#/g,(x,y)=>ɘ(y))
		.replace(/ℍ/g,'00')
		.replace(/𝕜/g,'000')
		.replace(/𝕄/g,'000000')
		.replace(/𝔾/g,'000000000')
		.replace(/𝕋/g,'000000000000')
		.replace(/ℙ/g,'000000000000000')
		.replace(/𝔼/g,'000000000000000000')
		.replace(/ℤ/g,'000000000000000000000')
		.replace(/𝕐/g,'000000000000000000000000')
		.replace(/⬮/g,'()')
		.replace(/⬯/g,'(``)')
		.replace(/⇝/g,'((a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/⇀/g,'(($,_,ã)=>')
		.replace(/§/g,'($1)')
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØȺɼḌᴙξëß\u00f8-\u01ef])([A-Za-z$_ãï]+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?|[ȉℇεȋɸπτ])/g,'$1($2)')
		.replace(/([ᵖᵍʳᶜôℹΣɘϚѦПØɼȺḌᴙξëß\u00f8-\u01ef])([^(\u00f8-\u01ef])/g,'$1($2')
		.replace(/ï(\d+)/g,'ï[$1]')
		.replace(/⇏/g,'(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↛/g,'=(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)=>')
		.replace(/↪/g,'($,_,ã)=>')
		.replace(/⤤/g,'=($,_,ã)=>')
		.replace(/→/g,'=>')
		.replace(/”/g,'`)')
		.replace(/‘/g,'\\`')
		.replace(/’/g,'\\`)')
		.replace(/⸩/g,'))')
		.replace(/⎞/g,'/)')
		.replace(/⦃/g,'${')
		.replace(/…/g,'...')
		.replace(/⟦/g,'[...')
		.replace(/˖/g,'+=')
		.replace(/⧺/g,'++')
		.replace(/˗/g,'-=')
		.replace(/‡/g,'--')
		.replace(/×/g,'*=')
		.replace(/÷/g,'/=')
		.replace(/٪/g,'%=')
		.replace(/¡/g,'!!')
		.replace(/≔/g,'==')
		.replace(/≠/g,'!=')
		.replace(/≤/g,'<=')
		.replace(/≥/g,'>=')
		.replace(/⅋/g,'&&')
		.replace(/⋎/g,'||')
		.replace(/↺/g,'for(')
		.replace(/ᶉ/g,'return ')
		.replace(/ŋ/g,'new ')
		.replace(/\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)²/g,'Math.pow($1,2)')
		.replace(/\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)³/g,'Math.pow($1,3)')
		.replace(/\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)ⁿ\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)/g,'Math.pow($1,$2)')
		.replace(/√\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)/g,'Math.sqrt($1)')
		.replace(/∛\((.+|-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?)\)/g,'Math.cbrt($1)')
		.replace(/½/g,'0.5')
		.replace(/¼/g,'0.25')
		.replace(/¾/g,'0.75')
		.replace(/⅐/g,'(1/7)')
		.replace(/⅑/g,'(1/9)')
		.replace(/⅒/g,'0.1')
		.replace(/⅓/g,'(1/3)')
		.replace(/⅔/g,'(2/3)')
		.replace(/⅕/g,'0.2')
		.replace(/⅖/g,'0.4')
		.replace(/⅗/g,'0.6')
		.replace(/⅘/g,'0.8')
		.replace(/⅙/g,'(1/6)')
		.replace(/⅚/g,'(5/6)')
		.replace(/⅛/g,'(1/8)')
		.replace(/⅜/g,'(3/8)')
		.replace(/⅝/g,'(5/8)')
		.replace(/⅞/g,'(7/8)')
		.replace(/ᶀ/g,'0b')
		.replace(/ᶍ/g,'0x')
		.replace(/Ⅹ/g,'10')
		.replace(/([\u00f8-\u01ef])/g,'["$1"]')
		.replace(/ß/g,'[ß]')
		.replace(/⌿/g,'/g')
		.replace(/⍀/g,'/ig')
		.replace(/⊨/g,'true')
		.replace(/⊭/g,'false')
		.replace(/«/g,'<<')
		.replace(/»/g,'>>')
		.replace(/⫸/g,'>>>')
		.replace(/˜/g,'~~')
	;
	if(asdf==1e4&&!c.match(/ô/g))c+=';ô()';console.log(c);eval(c)
}
<|endoftext|>