<commit_before>class ApiEndpoint {
    constructor(baseRoute, httpParamSerializerJQLikeMode, endpointConfig, $httpParamSerializerJQLike, $injector, $resource, $q, CacheFactory) {
        'ngInject';

        this.config = endpointConfig;
        this.$injector = $injector;
        this.$q = $q;
        this.resource = $resource(baseRoute + endpointConfig.route, {}, endpointConfig.actions);
        this.httpParamSerializerJQLikeMode = httpParamSerializerJQLikeMode;
        this.$httpParamSerializerJQLike = $httpParamSerializerJQLike;
        this.CacheFactory = CacheFactory;
        this.cacher = false;

        if (angular.isString(this.config.modelClass)) {
            this.config.modelClass = $injector.get(this.config.modelClass);
        }

        // Set behavior for actions
        angular.forEach(endpointConfig.actions, (action, actionName, availableActions = {}) => {
            action.method = action.method.toUpperCase();

            let actionMethod = this.request,
                params = availableActions[actionName] ? availableActions[actionName] : {},
                actionParams = {
                    name: actionName,
                    instantiateModel: params.instantiateModel !== false,
                    headersForReading: params.headersForReading || false,
                    isSaveRequest: (action.method === 'PUT' || action.method === 'POST' || action.method === 'PATCH')
                };

            if (endpointConfig.model) {
                actionMethod = (actionParams.isSaveRequest) ? this.saveRequestWithModel : this.getRequestWithModel;
            }

            this[actionName] = angular.bind(this, actionMethod, actionParams);
        });
    }

    instantiateModel(data) {
        let model = this.config.modelClass ? new this.config.modelClass(data) : data;

        if (model && angular.isFunction(model.afterLoad)) {
            model.afterLoad();
        }

        return model;
    };

    request(actionParams, params = {}, data = {}) {
        let _headersForReturn = false;

        if ((this.httpParamSerializerJQLikeMode && actionParams.httpParamSerializerJQLikeMode !== false) || actionParams.httpParamSerializerJQLikeMode) {
            data = this.$httpParamSerializerJQLike(data);
        }

        this.config.actions[actionParams.name].transformResponse = (response, headers) => {
            if (actionParams.headersForReading && Array.isArray(actionParams.headersForReading)) {
                let responseHeaders = headers();
                _headersForReturn = {};
                actionParams.headersForReading.map((header) => {
                    if (responseHeaders[header]) {
                        _headersForReturn[header] = responseHeaders[header];
                    }
                });
            }

            return (actionParams.instantiateModel && response) ? angular.fromJson(response) : {data: response};
        };
        let cacheResult = false;
        let cacheKey = angular.isString(this.config.actions[actionParams.name].cache) ? this.config.actions[actionParams.name].cache : false;
        if (cacheKey) {
            if (params['force']) {
                this.CacheFactory.destroy(cacheKey);
                delete params['force'];
            }
            this.cacher = this.CacheFactory.get(cacheKey) || this.CacheFactory.createCache(cacheKey, {storageMode: 'localStorage'});
            cacheResult = this.cacher.get(JSON.stringify(Object.assign({}, actionParams.name, params, data)));
        }

        let resultPromise =  (cacheResult) ? new Promise((resolve) => resolve(cacheResult)) : this.resource[actionParams.name](params, data).$promise

        resultPromise.then((response) => {
                let result = null;

                if (!actionParams.instantiateModel) {
                    result = response.data;
                } else if (angular.isArray(response)) {
                    result = response.map((element) => this.instantiateModel(element))
                } else {
                    result = (() => this.instantiateModel(response))()
                }

                result = !!_headersForReturn ? [result, _headersForReturn] : result;

                if (this.cacher) {
                    this.cacher.put(JSON.stringify(Object.assign({}, actionParams.name, params, data)), result);
                }

                return result;
            });
    };

    // For GET requests
    getRequestWithModel(action, params) {
        return this.request(action, params);
    };

    // For POST and PUT request
    saveRequestWithModel(action, params, data) {

        // if empty data - assume that the parameters have not been transferred
        if (!data) {
            data = params;
            params = {};
        }

        let model = angular.copy(data);

        if (model && angular.isFunction(model.beforeSave)) {
            model.beforeSave();
        }

        return this.request(action, params, model);
    };
}

export default ApiEndpoint;<commit_msg>Fix cache issue (then after resolve promise)<commit_after>class ApiEndpoint {
    constructor(baseRoute, httpParamSerializerJQLikeMode, endpointConfig, $httpParamSerializerJQLike, $injector, $resource, $q, CacheFactory) {
        'ngInject';

        this.config = endpointConfig;
        this.$injector = $injector;
        this.$q = $q;
        this.resource = $resource(baseRoute + endpointConfig.route, {}, endpointConfig.actions);
        this.httpParamSerializerJQLikeMode = httpParamSerializerJQLikeMode;
        this.$httpParamSerializerJQLike = $httpParamSerializerJQLike;
        this.CacheFactory = CacheFactory;
        this.cacher = false;

        if (angular.isString(this.config.modelClass)) {
            this.config.modelClass = $injector.get(this.config.modelClass);
        }

        // Set behavior for actions
        angular.forEach(endpointConfig.actions, (action, actionName, availableActions = {}) => {
            action.method = action.method.toUpperCase();

            let actionMethod = this.request,
                params = availableActions[actionName] ? availableActions[actionName] : {},
                actionParams = {
                    name: actionName,
                    instantiateModel: params.instantiateModel !== false,
                    headersForReading: params.headersForReading || false,
                    isSaveRequest: (action.method === 'PUT' || action.method === 'POST' || action.method === 'PATCH')
                };

            if (endpointConfig.model) {
                actionMethod = (actionParams.isSaveRequest) ? this.saveRequestWithModel : this.getRequestWithModel;
            }

            this[actionName] = angular.bind(this, actionMethod, actionParams);
        });
    }

    instantiateModel(data) {
        let model = this.config.modelClass ? new this.config.modelClass(data) : data;

        if (model && angular.isFunction(model.afterLoad)) {
            model.afterLoad();
        }

        return model;
    };

    request(actionParams, params = {}, data = {}) {
        let _headersForReturn = false;

        if ((this.httpParamSerializerJQLikeMode && actionParams.httpParamSerializerJQLikeMode !== false) || actionParams.httpParamSerializerJQLikeMode) {
            data = this.$httpParamSerializerJQLike(data);
        }

        this.config.actions[actionParams.name].transformResponse = (response, headers) => {
            if (actionParams.headersForReading && Array.isArray(actionParams.headersForReading)) {
                let responseHeaders = headers();
                _headersForReturn = {};
                actionParams.headersForReading.map((header) => {
                    if (responseHeaders[header]) {
                        _headersForReturn[header] = responseHeaders[header];
                    }
                });
            }

            return (actionParams.instantiateModel && response) ? angular.fromJson(response) : {data: response};
        };
        let cacheResult = false;
        let cacheKey = angular.isString(this.config.actions[actionParams.name].cache) ? this.config.actions[actionParams.name].cache : false;
        if (cacheKey) {
            if (params['force']) {
                this.CacheFactory.destroy(cacheKey);
                delete params['force'];
            }
            this.cacher = this.CacheFactory.get(cacheKey) || this.CacheFactory.createCache(cacheKey, {storageMode: 'localStorage'});
            cacheResult = this.cacher.get(JSON.stringify(Object.assign({}, actionParams.name, params, data)));
        }

        let resultPromise = (cacheResult) ? new Promise((resolve) => resolve(cacheResult)) : this.resource[actionParams.name](params, data).$promise

        return resultPromise.then((response) => {
                let result = null;

                if (!actionParams.instantiateModel) {
                    result = response.data;
                } else if (angular.isArray(response)) {
                    result = response.map((element) => this.instantiateModel(element))
                } else {
                    result = (() => this.instantiateModel(response))()
                }

                result = !!_headersForReturn ? [result, _headersForReturn] : result;

                if (this.cacher) {
                    this.cacher.put(JSON.stringify(Object.assign({}, actionParams.name, params, data)), result);
                }

                return result;
            });
    };

    // For GET requests
    getRequestWithModel(action, params) {
        return this.request(action, params);
    };

    // For POST and PUT request
    saveRequestWithModel(action, params, data) {

        // if empty data - assume that the parameters have not been transferred
        if (!data) {
            data = params;
            params = {};
        }

        let model = angular.copy(data);

        if (model && angular.isFunction(model.beforeSave)) {
            model.beforeSave();
        }

        return this.request(action, params, model);
    };
}

export default ApiEndpoint;<|endoftext|>


<commit_before>/*
 *   This file is part of 6502.ts, an emulator for 6502 based systems built
 *   in Typescript
 *
 *   Copyright (c) 2014 -- 2020 Christian Speckner and contributors
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in all
 *   copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *   SOFTWARE.
 */

'use strict';

import typescript from 'rollup-plugin-typescript2';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import builtins from 'rollup-plugin-node-builtins';
import elm from 'rollup-plugin-elm';
import { terser } from 'rollup-plugin-terser';
import html from 'rollup-plugin-bundle-html';
import scss from 'rollup-plugin-scss';
import copy from 'rollup-plugin-copy';
import globals from 'rollup-plugin-node-globals';
import replace from 'rollup-plugin-replace';
import sizes from 'rollup-plugin-sizes';
import rollupGitVersion from 'rollup-plugin-git-version';
import path from 'path';
const { generateSW } = require('rollup-plugin-workbox');

const DEVELOPMENT = !!process.env.DEVELOPMENT;
const dist = p => path.join(DEVELOPMENT ? 'dist-dev' : 'dist', p);

const worker = ({ input, output, distributeTo }) => ({
    input,
    output: {
        file: output,
        format: 'iife',
        sourcemap: true,
        name: 'worker'
    },
    plugins: [
        resolve({ preferBuiltins: true }),
        commonjs({
            ignore: [],
            namedExports: {
                'node_modules/seedrandom/index.js': ['alea'],
                'node_modules/setimmediate2/dist/setImmediate.js': ['setImmediate']
            }
        }),
        typescript({
            tsconfigOverride: {
                compilerOptions: {
                    module: 'es2015'
                }
            },
            tsconfig: 'worker/tsconfig.json',
            objectHashIgnoreUnknownHack: true
        }),
        globals(),
        builtins(),
        ...(DEVELOPMENT ? [] : [terser()]),
        ...(distributeTo
            ? [
                  copy({
                      targets: [output, `${output}.map`]
                          .map(src => distributeTo.map(x => ({ src, dest: dist(x) })))
                          .reduce((acc, x) => acc.concat(x), []),
                      hook: 'writeBundle'
                  })
              ]
            : []),
        sizes()
    ],
    onwarn: (warning, warn) => {
        if (warning.code === 'EVAL' && warning.id.match(/thumbulator\.js$/)) return;
        warn(warning);
    }
});

const library = ({ input, output, name, copy: copyCfg }) => ({
    input,
    output: {
        file: output,
        format: 'umd',
        sourcemap: true,
        name
    },
    plugins: [
        resolve({ preferBuiltins: true }),
        commonjs({
            ignore: [],
            namedExports: {
                'node_modules/seedrandom/index.js': ['alea'],
                'node_modules/setimmediate2/dist/setImmediate.js': ['setImmediate']
            }
        }),
        typescript({
            tsconfigOverride: {
                compilerOptions: {
                    module: 'es2015'
                }
            },
            tsconfig: 'tsconfig.json',
            objectHashIgnoreUnknownHack: true
        }),
        globals(),
        builtins(),
        ...(DEVELOPMENT ? [] : [terser()]),
        ...(copyCfg ? [copy(copyCfg)] : []),
        sizes()
    ],
    onwarn: (warning, warn) => {
        if (warning.code === 'EVAL' && warning.id.match(/thumbulator\.js$/)) return;
        warn(warning);
    }
});

const elmFrontend = ({ input, output, template, extraAssets = [], serviceWorker }) => ({
    input,
    output: {
        file: path.join(output, 'app.js'),
        format: 'iife',
        sourcemap: true,
        name: 'app'
    },
    plugins: [
        resolve({ preferBuiltins: true }),
        elm({
            compiler: {
                optimize: !DEVELOPMENT,
                pathToElm: path.resolve(__dirname, 'node_modules/.bin/elm')
            }
        }),
        scss({
            includePaths: [path.resolve(__dirname, 'node_modules')],
            outputStyle: 'compressed'
        }),
        rollupGitVersion(),
        replace({
            include: 'node_modules/jszip/**/*.js',
            values: {
                'readable-stream': `stream`
            }
        }),
        replace({ 'process.env.DEVELOPMENT': JSON.stringify(DEVELOPMENT) }),
        commonjs({
            namedExports: {
                'node_modules/seedrandom/index.js': ['alea'],
                'node_modules/setimmediate2/dist/setImmediate.js': ['setImmediate']
            },
            extensions: ['.js']
        }),
        typescript({
            tsconfigOverride: {
                compilerOptions: {
                    module: 'es2015'
                }
            },
            tsconfig: 'tsconfig.json',
            objectHashIgnoreUnknownHack: true
        }),
        globals(),
        builtins(),
        ...(DEVELOPMENT ? [] : [terser()]),
        html({
            template: template,
            dest: output,
            filename: 'index.html',
            inject: 'head',
            ignore: /worker/
        }),
        ...(serviceWorker && !DEVELOPMENT ? [generateSW(serviceWorker)] : []),
        copy({
            targets: ['src/frontend/theme/assets', 'assets', ...extraAssets].map(src => ({ src, dest: output }))
        }),
        sizes()
    ],
    onwarn: (warning, warn) => {
        if (warning.code === 'EVAL' && warning.id.match(/thumbulator\.js$/)) return;
        warn(warning);
    }
});

export default [
    worker({
        input: 'worker/src/main/stellerator.ts',
        output: dist('worker/stellerator.min.js'),
        distributeTo: ['frontend/stellerator/worker', 'stellerator-embedded/worker']
    }),
    worker({
        input: 'worker/src/main/video-pipeline.ts',
        output: dist('worker/video-pipeline.min.js'),
        distributeTo: ['frontend/stellerator/worker']
    }),
    library({
        input: 'src/web/embedded/stellerator/index.ts',
        output: dist('stellerator-embedded/stellerator-embedded.min.js'),
        name: '$6502',
        copy: {
            targets: [{ src: 'template/stellerator-embedded.html', dest: dist('stellerator-embedded') }]
        }
    }),
    elmFrontend({
        input: 'src/frontend/stellerator/index.ts',
        output: dist('frontend/stellerator'),
        template: 'template/stellerator.html',
        extraAssets: ['doc'],
        serviceWorker: {
            swDest: dist('frontend/stellerator/service-worker.js'),
            globDirectory: dist('frontend/stellerator'),
            globPatterns: ['**/*'],
            globIgnores: ['**/*.map', '**/doc/images/orig/**'],
            importWorkboxFrom: 'cdn',
            cacheId: 'stellerator-ng',
            skipWaiting: true,
            clientsClaim: true
        }
    }),
    elmFrontend({
        input: 'src/frontend/ui-playground/index.ts',
        output: dist('frontend/ui-playground'),
        template: 'template/ui-playground.html'
    })
];
<commit_msg>Simplify build system.<commit_after>/*
 *   This file is part of 6502.ts, an emulator for 6502 based systems built
 *   in Typescript
 *
 *   Copyright (c) 2014 -- 2020 Christian Speckner and contributors
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in all
 *   copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *   SOFTWARE.
 */

'use strict';

import typescript from 'rollup-plugin-typescript2';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import builtins from 'rollup-plugin-node-builtins';
import elm from 'rollup-plugin-elm';
import { terser } from 'rollup-plugin-terser';
import html from 'rollup-plugin-bundle-html';
import scss from 'rollup-plugin-scss';
import copy from 'rollup-plugin-copy';
import globals from 'rollup-plugin-node-globals';
import replace from 'rollup-plugin-replace';
import sizes from 'rollup-plugin-sizes';
import rollupGitVersion from 'rollup-plugin-git-version';
import path from 'path';
const { generateSW } = require('rollup-plugin-workbox');

const DEVELOPMENT = !!process.env.DEVELOPMENT;
const dist = p => path.join(DEVELOPMENT ? 'dist-dev' : 'dist', p);

const cfg = {
    commonjs: {
        ignore: [],
        namedExports: {
            'node_modules/seedrandom/index.js': ['alea'],
            'node_modules/setimmediate2/dist/setImmediate.js': ['setImmediate']
        }
    },
    typescript: {
        tsconfigOverride: {
            compilerOptions: {
                module: 'es2015'
            }
        },
        tsconfig: 'tsconfig.json',
        objectHashIgnoreUnknownHack: true
    },
    replace: {
        include: 'node_modules/jszip/**/*.js',
        values: {
            'readable-stream': `stream`
        }
    },
    elm: {
        compiler: {
            optimize: !DEVELOPMENT,
            pathToElm: path.resolve(__dirname, 'node_modules/.bin/elm')
        }
    },
    scss: {
        includePaths: [path.resolve(__dirname, 'node_modules')],
        outputStyle: 'compressed'
    }
};

const onwarn = (warning, warn) => {
    if (warning.code === 'EVAL' && warning.id.match(/thumbulator\.js$/)) return;
    warn(warning);
};

const worker = ({ input, output, distributeTo }) => ({
    input,
    output: {
        file: output,
        format: 'iife',
        sourcemap: true,
        name: 'worker'
    },
    plugins: [
        resolve({ preferBuiltins: true }),
        commonjs(cfg.commonjs),
        typescript({ ...cfg.typescript, config: 'worker/tsconfig.json' }),
        globals(),
        builtins(),
        ...(DEVELOPMENT ? [] : [terser()]),
        ...(distributeTo
            ? [
                  copy({
                      targets: [output, `${output}.map`]
                          .map(src => distributeTo.map(x => ({ src, dest: dist(x) })))
                          .reduce((acc, x) => acc.concat(x), []),
                      hook: 'writeBundle'
                  })
              ]
            : []),
        sizes()
    ],
    onwarn
});

const library = ({ input, output, name, copy: copyCfg }) => ({
    input,
    output: {
        file: output,
        format: 'umd',
        sourcemap: true,
        name
    },
    plugins: [
        resolve({ preferBuiltins: true }),
        commonjs(cfg.commonjs),
        typescript(cfg.typescript),
        globals(),
        builtins(),
        ...(DEVELOPMENT ? [] : [terser()]),
        ...(copyCfg ? [copy(copyCfg)] : []),
        sizes()
    ],
    onwarn
});

const elmFrontend = ({ input, output, template, extraAssets = [], serviceWorker }) => ({
    input,
    output: {
        file: path.join(output, 'app.js'),
        format: 'iife',
        sourcemap: true,
        name: 'app'
    },
    plugins: [
        resolve({ preferBuiltins: true }),
        elm(cfg.elm),
        scss(cfg.scss),
        rollupGitVersion(),
        replace(cfg.replace),
        replace({ 'process.env.DEVELOPMENT': JSON.stringify(DEVELOPMENT) }),
        commonjs(cfg.commonjs),
        typescript(cfg.typescript),
        globals(),
        builtins(),
        ...(DEVELOPMENT ? [] : [terser()]),
        html({
            template: template,
            dest: output,
            filename: 'index.html',
            inject: 'head',
            ignore: /worker/
        }),
        ...(serviceWorker && !DEVELOPMENT ? [generateSW(serviceWorker)] : []),
        copy({
            targets: ['src/frontend/theme/assets', 'assets', ...extraAssets].map(src => ({ src, dest: output }))
        }),
        sizes()
    ],
    onwarn
});

export default [
    worker({
        input: 'worker/src/main/stellerator.ts',
        output: dist('worker/stellerator.min.js'),
        distributeTo: ['frontend/stellerator/worker', 'stellerator-embedded/worker']
    }),
    worker({
        input: 'worker/src/main/video-pipeline.ts',
        output: dist('worker/video-pipeline.min.js'),
        distributeTo: ['frontend/stellerator/worker']
    }),
    library({
        input: 'src/web/embedded/stellerator/index.ts',
        output: dist('stellerator-embedded/stellerator-embedded.min.js'),
        name: '$6502',
        copy: {
            targets: [{ src: 'template/stellerator-embedded.html', dest: dist('stellerator-embedded') }]
        }
    }),
    elmFrontend({
        input: 'src/frontend/stellerator/index.ts',
        output: dist('frontend/stellerator'),
        template: 'template/stellerator.html',
        extraAssets: ['doc'],
        serviceWorker: {
            swDest: dist('frontend/stellerator/service-worker.js'),
            globDirectory: dist('frontend/stellerator'),
            globPatterns: ['**/*'],
            globIgnores: ['**/*.map', '**/doc/images/orig/**'],
            importWorkboxFrom: 'cdn',
            cacheId: 'stellerator-ng',
            skipWaiting: true,
            clientsClaim: true
        }
    }),
    elmFrontend({
        input: 'src/frontend/ui-playground/index.ts',
        output: dist('frontend/ui-playground'),
        template: 'template/ui-playground.html'
    })
];
<|endoftext|>


<commit_before>const { Command } = require('discord-akairo');
const Logger = require('../../../util/Logger');

function exec(message, args) {
    return this.client.user.setStatus(args.status).then(() => {
        Logger.debug(`Status set to "${this.client.user.presence.status}"`);
        return message.delete();
    });
}

module.exports = new Command('status', exec, {
    aliases: ['status','playing'],
    args: [
        {
            id: 'status',
            type: ['online', 'idle', 'dnd', 'invisible'],
            default: 'online'
        }
    ],
    category: 'util'
});
<commit_msg>Delete status.js<commit_after><|endoftext|>


<commit_before>// Karma configuration
// Generated on Sat Jun 20 2015 21:15:25 GMT+0900 (JST)

module.exports = function (config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '../',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],

        // list of files / patterns to load in the browser
        files: [
            // Libraries
            'bower_components/jquery/dist/jquery.js',
            'bower_components/jasmine-jquery/lib/jasmine-jquery.js',
            'bower_components/angular/angular.js',
            'bower_components/angular-mocks/angular-mocks.js',

            // App
            'src/*.js',

            // Test
            'test/*.js',
            'test/directives/*.js'
        ],

        // list of files to exclude
        exclude: [
        ],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
        },

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['Chrome'],

        // list of karma plugins
        plugins: [
            'karma-junit-reporter',
            'karma-chrome-launcher',
            'karma-jasmine'
        ],

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true,

        customLaunchers: {
            Chrome_travis_ci: {
                base: 'Chrome',
                flags: ['--no-sandbox']
            }
        }
    });
};
<commit_msg>Update karma config<commit_after>// Karma configuration
// Generated on Sat Jun 20 2015 21:15:25 GMT+0900 (JST)

module.exports = function (config) {
    var configuration = {

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '../',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],

        // list of files / patterns to load in the browser
        files: [
            // Libraries
            'bower_components/jquery/dist/jquery.js',
            'bower_components/jasmine-jquery/lib/jasmine-jquery.js',
            'bower_components/angular/angular.js',
            'bower_components/angular-mocks/angular-mocks.js',

            // App
            'src/*.js',

            // Test
            'test/*.js',
            'test/directives/*.js'
        ],

        // list of files to exclude
        exclude: [
        ],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
        },

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['Chrome'],
        customLaunchers: {
            Chrome_travis_ci: {
                base: 'Chrome',
                flags: ['--no-sandbox']
            }
        },

        // list of karma plugins
        plugins: [
            'karma-junit-reporter',
            'karma-chrome-launcher',
            'karma-jasmine'
        ],

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true
    };

    if (process.env.TRAVIS) {
        configuration.browsers = ['Chrome_travis_ci'];
    }

    config.set(configuration);
};
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import Realm from 'realm';

import { UIDatabase } from '..';

import { generalStrings } from '../../localization';
import { getTotal } from '../utilities';
import { dailyUsage } from '../../utilities/dailyUsage';

/**
 * An item.
 *
 * @property  {string}            id
 * @property  {string}            code
 * @property  {string}            name
 * @property  {number}            defaultPackSize
 * @property  {List.<ItemBatch>}  batches
 * @property  {ItemDepartment}    department
 * @property  {string}            description
 * @property  {ItemCategory}      category
 * @property  {number}            defaultPrice
 * @property  {boolean}           isVisible
 * @property  {Item}              crossReferenceItem
 */
export class Item extends Realm.Object {
  /**
   * Delete all item store joins and item batches associated with this master list.
   *
   * @param  {Realm}  database
   */
  destructor(database) {
    // Clean up item store joins referencing deleted item.
    const itemStoreJoins = database.objects('ItemStoreJoin').filtered('itemId == $0', this.id);
    database.delete('ItemStoreJoin', itemStoreJoins);

    // In case of merge-deletion, ensure only delete batches currently associated with this item.
    this.batches = database.objects('ItemBatch').filtered('item.id == $0', this.id);
    database.delete('ItemBatch', this.batches);
  }

  /**
   * If item is cross-referenced item, return the referenced item, else return this item.
   *
   * @return  {Item}
   */
  get realItem() {
    return this.crossReferenceItem ? this.crossReferenceItem : this;
  }

  /**
   * Get total amount of item.
   *
   * @return  {number}
   */
  get totalQuantity() {
    return getTotal(this.realItem.batches, 'totalQuantity');
  }

  /**
   * Returns an indicator if this item has stock on hand, or not.
   *
   * @return {number}
   */
  get hasStock() {
    return this.totalQuantity > 0;
  }

  /**
   * Get daily usage of item.
   *
   * @return  {number}
   */
  get dailyUsage() {
    return dailyUsage(this);
  }

  /**
   * Get the date the item was added, defined as date of the earliest added batch associated
   * with this item.
   * @return  {Date}
   */
  get addedDate() {
    return this.batches.reduce(
      (acc, { addedDate }) => (acc > addedDate ? addedDate : acc),
      new Date()
    );
  }

  /**
   * Get the batch associated with this item with the earliest expiration date.
   *
   * @return  {ItemBatch}
   */
  get earliestExpiringBatch() {
    // If no batches associated with this item, return null.
    if (this.batches.length === 0) return null;

    let earliestBatch = this.batches.find(batch => batch.totalQuantity > 0);

    // If no batches found with any items, return null.
    if (!earliestBatch) return null;

    this.batches.forEach(batch => {
      if (
        batch.totalQuantity > 0 &&
        batch.expiryDate &&
        (!earliestBatch.expiryDate || batch.expiryDate < earliestBatch.expiryDate)
      ) {
        earliestBatch = batch;
      }
    });

    return earliestBatch;
  }

  /**
   * Get category of item, or empty string if no category exists.
   *
   * @return  {string}
   */
  get categoryName() {
    return this.category ? this.category.name : '';
  }

  /**
   * Get name of department associated with item, or empty string if no department exists.
   *
   * @return  {string}
   */
  get departmentName() {
    return this.department ? this.department.name : '';
  }

  /**
   * Get batches associated with item that have stock.
   *
   * @return  {List}
   */
  get batchesWithStock() {
    return this.batches.filtered('numberOfPacks > 0');
  }

  /**
   * @return {Number} this items monthly usage based on a 30 day month.
   */
  get monthlyUsage() {
    return this.dailyUsage * 30;
  }

  /**
   * Get number of batches associated with item that have stock.
   *
   * @return  {number}
   */
  get totalBatchesInStock() {
    return this.batchesWithStock.length;
  }

  /**
   * Returns a string representing the units for this item.
   * @return {string} the unit for this item, or N/A if none has been assigned.
   */
  get unitString() {
    return this.unit?.units ?? generalStrings.not_available;
  }

  /**
   * Add batch to item.
   *
   * @param  {ItemBatch}  itemBatch
   */
  addBatch(itemBatch) {
    this.batches.push(itemBatch);
  }

  /**
   * Add batch to item if not already added.
   *
   * @param  {ItemBatch}  itemBatch
   */
  addBatchIfUnique(itemBatch) {
    if (this.batches.filtered('id == $0', itemBatch.id).length > 0) return;
    this.addBatch(itemBatch);
  }

  /**
   * Returns an array of all direction expansions related to this
   * item.
   */
  getDirectionExpansions = database =>
    this.directions.sorted('priority').reduce((acc, value) => {
      const expansion = value.getExpansion(database);
      if (expansion) return [...acc, expansion];
      return acc;
    }, []);

  /**
   * Get string representation of item.
   *
   * @returns  {string}
   */
  toString() {
    return `${this.code} - ${this.name}`;
  }

  /**
   * Stock on date
   *
   * @param {Date} date
   * @return  {number}
   */
  geTotalQuantityOnDate(date) {
    if (date >= new Date()) return this.totalQuantity;

    const allMovements = UIDatabase.objects('TransactionBatch')
      .filtered('itemBatch.item.id == $0', this.id)
      .filtered('numberOfPacks > 0')
      .filtered('transaction.confirmDate > $0', date);

    const sumMovements = movements =>
      movements.reduce((sum, { totalQuantity }) => sum + totalQuantity, 0);
    const additions = sumMovements(allMovements.filtered('type == $0', 'stock_in'));
    const reductions = sumMovements(allMovements.filtered('type == $0', 'stock_out'));

    return this.totalQuantity + reductions - additions;
  }
}

Item.schema = {
  name: 'Item',
  primaryKey: 'id',
  properties: {
    id: 'string',
    code: { type: 'string', default: 'placeholderCode' },
    name: { type: 'string', default: 'placeholderName' },
    defaultPackSize: { type: 'double', default: 1 },
    batches: { type: 'list', objectType: 'ItemBatch' },
    department: { type: 'ItemDepartment', optional: true },
    description: { type: 'string', optional: true },
    category: { type: 'ItemCategory', optional: true },
    defaultPrice: { type: 'double', default: 0 },
    isVisible: { type: 'bool', default: false },
    crossReferenceItem: { type: 'Item', optional: true },
    unit: { type: 'Unit', optional: true },
    defaultRestrictedLocationType: { type: 'LocationType', optional: true },
    directions: { type: 'linkingObjects', objectType: 'ItemDirection', property: 'item' },
    dosesPerVial: { type: 'double', default: 0 },
    isVaccine: { type: 'bool', default: false },
  },
};

export default Item;
<commit_msg>Add renaming of dosesPerVial -> doses<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import Realm from 'realm';

import { UIDatabase } from '..';

import { generalStrings } from '../../localization';
import { getTotal } from '../utilities';
import { dailyUsage } from '../../utilities/dailyUsage';

/**
 * An item.
 *
 * @property  {string}            id
 * @property  {string}            code
 * @property  {string}            name
 * @property  {number}            defaultPackSize
 * @property  {List.<ItemBatch>}  batches
 * @property  {ItemDepartment}    department
 * @property  {string}            description
 * @property  {ItemCategory}      category
 * @property  {number}            defaultPrice
 * @property  {boolean}           isVisible
 * @property  {Item}              crossReferenceItem
 */
export class Item extends Realm.Object {
  /**
   * Delete all item store joins and item batches associated with this master list.
   *
   * @param  {Realm}  database
   */
  destructor(database) {
    // Clean up item store joins referencing deleted item.
    const itemStoreJoins = database.objects('ItemStoreJoin').filtered('itemId == $0', this.id);
    database.delete('ItemStoreJoin', itemStoreJoins);

    // In case of merge-deletion, ensure only delete batches currently associated with this item.
    this.batches = database.objects('ItemBatch').filtered('item.id == $0', this.id);
    database.delete('ItemBatch', this.batches);
  }

  /**
   * If item is cross-referenced item, return the referenced item, else return this item.
   *
   * @return  {Item}
   */
  get realItem() {
    return this.crossReferenceItem ? this.crossReferenceItem : this;
  }

  /**
   * Get total amount of item.
   *
   * @return  {number}
   */
  get totalQuantity() {
    return getTotal(this.realItem.batches, 'totalQuantity');
  }

  /**
   * Returns an indicator if this item has stock on hand, or not.
   *
   * @return {number}
   */
  get hasStock() {
    return this.totalQuantity > 0;
  }

  /**
   * Get daily usage of item.
   *
   * @return  {number}
   */
  get dailyUsage() {
    return dailyUsage(this);
  }

  /**
   * Get the date the item was added, defined as date of the earliest added batch associated
   * with this item.
   * @return  {Date}
   */
  get addedDate() {
    return this.batches.reduce(
      (acc, { addedDate }) => (acc > addedDate ? addedDate : acc),
      new Date()
    );
  }

  /**
   * Get the batch associated with this item with the earliest expiration date.
   *
   * @return  {ItemBatch}
   */
  get earliestExpiringBatch() {
    // If no batches associated with this item, return null.
    if (this.batches.length === 0) return null;

    let earliestBatch = this.batches.find(batch => batch.totalQuantity > 0);

    // If no batches found with any items, return null.
    if (!earliestBatch) return null;

    this.batches.forEach(batch => {
      if (
        batch.totalQuantity > 0 &&
        batch.expiryDate &&
        (!earliestBatch.expiryDate || batch.expiryDate < earliestBatch.expiryDate)
      ) {
        earliestBatch = batch;
      }
    });

    return earliestBatch;
  }

  /**
   * Get category of item, or empty string if no category exists.
   *
   * @return  {string}
   */
  get categoryName() {
    return this.category ? this.category.name : '';
  }

  /**
   * Get name of department associated with item, or empty string if no department exists.
   *
   * @return  {string}
   */
  get departmentName() {
    return this.department ? this.department.name : '';
  }

  /**
   * Get batches associated with item that have stock.
   *
   * @return  {List}
   */
  get batchesWithStock() {
    return this.batches.filtered('numberOfPacks > 0');
  }

  /**
   * @return {Number} this items monthly usage based on a 30 day month.
   */
  get monthlyUsage() {
    return this.dailyUsage * 30;
  }

  /**
   * Get number of batches associated with item that have stock.
   *
   * @return  {number}
   */
  get totalBatchesInStock() {
    return this.batchesWithStock.length;
  }

  /**
   * Returns a string representing the units for this item.
   * @return {string} the unit for this item, or N/A if none has been assigned.
   */
  get unitString() {
    return this.unit?.units ?? generalStrings.not_available;
  }

  /**
   * Add batch to item.
   *
   * @param  {ItemBatch}  itemBatch
   */
  addBatch(itemBatch) {
    this.batches.push(itemBatch);
  }

  /**
   * Add batch to item if not already added.
   *
   * @param  {ItemBatch}  itemBatch
   */
  addBatchIfUnique(itemBatch) {
    if (this.batches.filtered('id == $0', itemBatch.id).length > 0) return;
    this.addBatch(itemBatch);
  }

  /**
   * Returns an array of all direction expansions related to this
   * item.
   */
  getDirectionExpansions = database =>
    this.directions.sorted('priority').reduce((acc, value) => {
      const expansion = value.getExpansion(database);
      if (expansion) return [...acc, expansion];
      return acc;
    }, []);

  /**
   * Get string representation of item.
   *
   * @returns  {string}
   */
  toString() {
    return `${this.code} - ${this.name}`;
  }

  /**
   * Stock on date
   *
   * @param {Date} date
   * @return  {number}
   */
  geTotalQuantityOnDate(date) {
    if (date >= new Date()) return this.totalQuantity;

    const allMovements = UIDatabase.objects('TransactionBatch')
      .filtered('itemBatch.item.id == $0', this.id)
      .filtered('numberOfPacks > 0')
      .filtered('transaction.confirmDate > $0', date);

    const sumMovements = movements =>
      movements.reduce((sum, { totalQuantity }) => sum + totalQuantity, 0);
    const additions = sumMovements(allMovements.filtered('type == $0', 'stock_in'));
    const reductions = sumMovements(allMovements.filtered('type == $0', 'stock_out'));

    return this.totalQuantity + reductions - additions;
  }
}

Item.schema = {
  name: 'Item',
  primaryKey: 'id',
  properties: {
    id: 'string',
    code: { type: 'string', default: 'placeholderCode' },
    name: { type: 'string', default: 'placeholderName' },
    defaultPackSize: { type: 'double', default: 1 },
    batches: { type: 'list', objectType: 'ItemBatch' },
    department: { type: 'ItemDepartment', optional: true },
    description: { type: 'string', optional: true },
    category: { type: 'ItemCategory', optional: true },
    defaultPrice: { type: 'double', default: 0 },
    isVisible: { type: 'bool', default: false },
    crossReferenceItem: { type: 'Item', optional: true },
    unit: { type: 'Unit', optional: true },
    defaultRestrictedLocationType: { type: 'LocationType', optional: true },
    directions: { type: 'linkingObjects', objectType: 'ItemDirection', property: 'item' },
    doses: { type: 'double', default: 0 },
    isVaccine: { type: 'bool', default: false },
  },
};

export default Item;
<|endoftext|>


<commit_before>const MAX_STEP = 12
const NEXT_STEPS = [
  [0, 1],
  [0, -1],
  [1, 0],
  [-1, 0],
]

function move(steps) {
  const len = steps.length
  if (len === MAX_STEP + 1) return 1
  const current = steps[len - 1]
  let count = 0
  for (let i = 0; i < NEXT_STEPS.length; i++) {
    const d = NEXT_STEPS[i]
    const next = [current[0] + d[0], current[1] + d[1]]
    if (!steps.find((v) => v[0] === next[0] && v[1] === next[1])) {
      count += move([...steps, next])
    }
  }
  return count
}
<commit_msg>refactor: 添加执行<commit_after>const MAX_STEP = 12
const NEXT_STEPS = [
  [0, 1],
  [0, -1],
  [1, 0],
  [-1, 0],
]

function move(steps) {
  const len = steps.length
  if (len === MAX_STEP + 1) return 1
  const current = steps[len - 1]
  let count = 0
  for (let i = 0; i < NEXT_STEPS.length; i++) {
    const d = NEXT_STEPS[i]
    const next = [current[0] + d[0], current[1] + d[1]]
    if (!steps.find((v) => v[0] === next[0] && v[1] === next[1])) {
      count += move([...steps, next])
    }
  }
  return count
}

move([[0, 0]])<|endoftext|>


<commit_before>function startGame(){
	// set the scene size
	var WIDTH = window.innerWidth,
		HEIGHT = window.innerHeight;

	// set some camera attributes
	var VIEW_ANGLE = 45,
		ASPECT = WIDTH / HEIGHT,
		NEAR = 0.1,
		FAR = 10000;

	// get the DOM element to attach to
	// - assume we've got jQuery to hand
	var $container = $('#container');

	// create a WebGL renderer, camera
	// and a scene
	var renderer = new THREE.WebGLRenderer();
	var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
	var scene = new THREE.Scene();

	// the camera starts at 0,0,0 so pull it back
	camera.position.z = 300;
	camera.position.y = 200;
	camera.rotation.x = 100;

	// start the renderer
	renderer.setSize(WIDTH, HEIGHT);
	// enable shadows on the renderer
	//renderer.shadowMapEnabled = true;

	// attach the render-supplied DOM element
	$container.append(renderer.domElement);

	// create the sphere's material
	var sphereMaterial = new THREE.MeshLambertMaterial(
	{
		color: 0xCC0000
	});

	// set up the sphere vars
	var radius = 50, segments = 16, rings = 16;

	// create a new mesh with sphere geometry -
	// we will cover the sphereMaterial next!
	var sphere = new THREE.Mesh(
		new THREE.SphereGeometry(radius, segments, rings),
		sphereMaterial);

	// create the sphere's material
	var cubeMaterial = new THREE.MeshLambertMaterial(
	{
		color: 0xCC0000
	});

	// set up the cube vars
	var width = 50, height = 50, depth = 100;

	var cube = new THREE.Mesh(
		new THREE.CubeGeometry(width, height, depth),
		cubeMaterial);

	// enable shadows for an object
	//cube.castShadow = true;
	//cube.receiveShadow = true;

	// add the sphere to the scene
	scene.add(cube);

	// sphere geometry
	sphere.geometry

	// it's attributes
	sphere.position.x = 0;
	sphere.rotation.x = 50;
	sphere.scale.y = .5;

	var planeGeo = new THREE.PlaneGeometry(400, 200, 10, 10);
	var planeMat = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
	var plane = new THREE.Mesh(planeGeo, planeMat);
	plane.rotation.x = -Math.PI/2;
	plane.position.y = -25;
	plane.receiveShadow = true;
	scene.add(plane);

	// add the sphere to the scene
	scene.add(sphere);

	// and the camera
	scene.add(camera);

	// create a point light
	var pointLight = new THREE.PointLight( 0xFFFFFF );

	// set its position
	pointLight.position.x = 10;
	pointLight.position.y = 40;
	pointLight.position.z = 130;
	// enable shadows for a light
	//pointLight.castShadow = true;

	// add to the scene
	scene.add(pointLight);

	// model
	var loader = new THREE.OBJMTLLoader();
	loader.addEventListener( 'load', function ( event ) {

		modelObject = event.content;

		modelObject.position.y = - 80;
		scene.add( modelObject );

	});
	loader.load( 'http://localhost/Dodgeball/objData/glMap.obj', 'http://localhost/Dodgeball/objData/glMap.mtl' );

	var controls = new THREE.FirstPersonControls(camera);
	controls.movementSpeed = 100;
	controls.lookSpeed = 0.1;
	//controls.noFly = true;
	var clock = new THREE.Clock();

	// Stop moving around when the window is unfocused
	$(window).bind('focus', function() {
		if (controls) controls.freeze = false;
	});
	$(window).bind('blur', function() {
		if (controls) controls.freeze = true;
	});

	// Draw
	function renderLoop() {
		requestAnimationFrame(renderLoop);

		controls.update(clock.getDelta());

		cube.rotation.x += 0.05;
		cube.rotation.y += 0.05;
		renderer.render(scene, camera);
	}
	renderLoop();
}<commit_msg>Really basic gravity.<commit_after>function startGame(){
	// set the scene size
	var WIDTH = window.innerWidth,
		HEIGHT = window.innerHeight;

	// set some camera attributes
	var VIEW_ANGLE = 45,
		ASPECT = WIDTH / HEIGHT,
		NEAR = 0.1,
		FAR = 10000;

	// get the DOM element to attach to
	// - assume we've got jQuery to hand
	var $container = $('#container');

	// create a WebGL renderer, camera
	// and a scene
	var renderer = new THREE.WebGLRenderer();
	var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
	var scene = new THREE.Scene();

	// the camera starts at 0,0,0 so pull it back
	camera.position.z = 300;
	camera.position.y = 200;
	camera.rotation.x = 100;

	// start the renderer
	renderer.setSize(WIDTH, HEIGHT);
	// enable shadows on the renderer
	//renderer.shadowMapEnabled = true;

	// attach the render-supplied DOM element
	$container.append(renderer.domElement);

	// create the sphere's material
	var sphereMaterial = new THREE.MeshLambertMaterial(
	{
		color: 0xCC0000
	});

	// set up the sphere vars
	var radius = 50, segments = 16, rings = 16;

	// create a new mesh with sphere geometry -
	// we will cover the sphereMaterial next!
	var sphere = new THREE.Mesh(
		new THREE.SphereGeometry(radius, segments, rings),
		sphereMaterial);

	// create the sphere's material
	var cubeMaterial = new THREE.MeshLambertMaterial(
	{
		color: 0xCC0000
	});

	// set up the cube vars
	var width = 50, height = 50, depth = 100;

	var cube = new THREE.Mesh(
		new THREE.CubeGeometry(width, height, depth),
		cubeMaterial);

	// enable shadows for an object
	//cube.castShadow = true;
	//cube.receiveShadow = true;

	// add the sphere to the scene
	scene.add(cube);

	// sphere geometry
	sphere.geometry

	// it's attributes
	sphere.position.x = 0;
	sphere.rotation.x = 50;
	sphere.scale.y = .5;

	var planeGeo = new THREE.PlaneGeometry(400, 200, 10, 10);
	var planeMat = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
	var plane = new THREE.Mesh(planeGeo, planeMat);
	plane.rotation.x = -Math.PI/2;
	plane.position.y = -25;
	plane.receiveShadow = true;
	scene.add(plane);

	// add the sphere to the scene
	scene.add(sphere);

	// and the camera
	scene.add(camera);

	// create a point light
	var pointLight = new THREE.PointLight( 0xFFFFFF );

	// set its position
	pointLight.position.x = 10;
	pointLight.position.y = 40;
	pointLight.position.z = 130;

	// enable shadows for a light
	//pointLight.castShadow = true;

	// add to the scene
	scene.add(pointLight);

	// model
	var loader = new THREE.OBJMTLLoader();
	loader.addEventListener( 'load', function ( event ) {

		modelObject = event.content;

		modelObject.position.y = - 80;
		scene.add( modelObject );

	});
	loader.load( 'http://localhost/Dodgeball/objData/glMap.obj', 'http://localhost/Dodgeball/objData/glMap.mtl' );

	var controls = new THREE.FirstPersonControls(camera);
	controls.movementSpeed = 100;
	controls.lookSpeed = 0.1;
	//controls.noFly = true;
	var clock = new THREE.Clock();

	// Stop moving around when the window is unfocused
	$(window).bind('focus', function() {
		if (controls) controls.freeze = false;
	});
	$(window).bind('blur', function() {
		if (controls) controls.freeze = true;
	});

	// Draw
	function renderLoop() {
		requestAnimationFrame(renderLoop);

		var clockDelta = clock.getDelta();
		controls.update(clockDelta);
		applyGravity(camera, clockDelta);

		cube.rotation.x += 0.05;
		cube.rotation.y += 0.05;
		renderer.render(scene, camera);
	}
	renderLoop();
}

function applyGravity(object, delta){
	var floor = 25;
	if (object.position.y <= floor){
		return;
	}

	var gravityRate = 50;
	object.translateY((-gravityRate) * delta);
}<|endoftext|>


<commit_before>'use babel';

/* @flow */

import { Disposable, CompositeDisposable } from 'atom';
import type { Panel, TextEditor } from 'atom';

import 'rxjs';
import { createStore, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import reducers from './redux/reducers';
import epics from './redux/epics';
import * as actions from './redux/actions';

import Commands from './commands';
import EditorsRegistry from './editor-registry';
import TesterRegistry from './tester-registry';
// import { clearInlineMessages, decorateGutter, setInlineMessages } from './decorate-manager';
import ConsoleOutputView from './views/ConsoleOutputView';
import ResultView from './views/ResultView';
import StatusBarTile from './views/StatusBarTile';
import type { Tester as TesterProvider, Message, Store } from './types';

class Tester {
  commands: Commands;
  subscriptions: CompositeDisposable;
  modalPanel: Panel;
  registryTesters: TesterRegistry;
  registryEditors: EditorsRegistry;
  statusBarTile: Object;
  markers: Array<Object>;
  showInlineError: boolean;
  inlineErrorPosition: string;
  ansiToHtml: boolean;
  showOutputAfterTestRun: boolean;
  showNotifications: boolean;
  messageTimeout: number;
  runningTestersCount: number;
  scrollToBottom: boolean;
  panel: ?ConsoleOutputView;
  resultView: ?ResultView;
  messages:Array<Message>;
  output: string;
  testerStatusBar: Object;
  lastTestEditor: TextEditor;
  deserializeResultView: Function;
  deserializeConsoleOutput: Function;
  store: Store;
  getStore: Function;

  constructor() {
    this.commands = new Commands();
    this.registryEditors = new EditorsRegistry();
    this.registryTesters = new TesterRegistry();
    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(this.commands);
    this.subscriptions.add(this.registryEditors);
    this.subscriptions.add(this.registryTesters);
    this.markers = [];
    this.showInlineError = true;
    this.inlineErrorPosition = 'after';
    this.ansiToHtml = true;
    this.showOutputAfterTestRun = true;
    this.showNotifications = true;
    this.messageTimeout = 5;
    this.runningTestersCount = 0;
    this.scrollToBottom = true;
    this.messages = [];
    this.output = '';
    this.lastTestEditor = null;
    const self = this;

    this.getStore = (initialState) => {
      if (self.store == null) {
        self.store = createStore(
          reducers,
          initialState,
          applyMiddleware(createEpicMiddleware(epics)),
        );
        self.store.subscribe(() => {
          console.log('store updated', self.store.getState());
          // update all views here
        });
      }
      return self.store;
    };
    this.subscriptions.add(atom.config.observe('tester.gutterEnabled', (gutterEnabled) => {
      this.registryEditors.gutterEnabled = gutterEnabled;
    }));
    this.subscriptions.add(atom.config.observe('tester.showInlineError', (showInlineError) => {
      this.showInlineError = showInlineError;
    }));
    this.subscriptions.add(atom.config.observe('tester.inlineErrorPosition', (inlineErrorPosition) => {
      this.inlineErrorPosition = inlineErrorPosition;
    }));
    this.subscriptions.add(atom.config.observe('tester.ansiToHtml', (ansiToHtml) => {
      this.ansiToHtml = ansiToHtml;
    }));
    this.subscriptions.add(atom.config.observe('tester.showOutputAfterTestRun', (showOutputAfterTestRun) => {
      this.showOutputAfterTestRun = showOutputAfterTestRun;
    }));
    this.subscriptions.add(atom.config.observe('tester.messageTimeout', (messageTimeout) => {
      this.messageTimeout = messageTimeout;
    }));
    this.subscriptions.add(atom.config.observe('tester.showNotifications', (showNotifications) => {
      this.showNotifications = showNotifications;
    }));
    this.subscriptions.add(atom.config.observe('tester.scrollToBottom', (scrollToBottom) => {
      this.scrollToBottom = scrollToBottom;
    }));
    this.subscriptions.add(atom.workspace.observeTextEditors(async (/* editor*/) => {
      // await self.updateStatusBar();
    }));
    this.subscriptions.add(atom.workspace.onDidChangeActivePaneItem(async (/* paneItem*/) => {
      // await self.updateStatusBar();
    }));

    this.subscriptions.add(new Disposable(() => {
      atom.workspace.getPaneItems().forEach((item) => {
        if (item instanceof ConsoleOutputView) {
          item.destroy();
        }
      });
    }));

    this.deserializeConsoleOutput = function deserializeConsoleOutput(serializedState :any) {
      console.log('serializedState', serializedState);
      self.panel = new ConsoleOutputView({
        store: self.getStore(),
        ansiToHtml: self.ansiToHtml,
        scrollToBottom: self.scrollToBottom,
      });
      // self.panel = new ConsoleOutputView({
      //   output: self.output,
      //   ansiToHtml: self.ansiToHtml,
      //   scrollToBottom: self.scrollToBottom });
      return self.panel;
    };

    this.subscriptions.add(atom.workspace.addOpener((uri) => {
      if (uri === 'atom://tester-console-output') {
        return self.deserializeConsoleOutput();
      }
    }));

    this.subscriptions.add(new Disposable(() => {
      atom.workspace.getPaneItems().forEach((item) => {
        if (item instanceof ResultView) {
          item.destroy();
        }
      });
    }));

    this.deserializeResultView = function deserializeResultView(serializedState :any) {
      console.log('serializedState', serializedState);
      self.resultView = new ResultView({
        store: self.getStore(),
        ansiToHtml: self.ansiToHtml,
        softWrap: atom.config.get('tester.softWrapDefault'),
      });
      // self.resultView = new ResultView({
      //   messages: self.messages,
      //   ansiToHtml: self.ansiToHtml,
      //   softWrap: atom.config.get('tester.softWrapDefault'),
      //   runningTestersCount: self.runningTestersCount,
      // });
      self.resultView.onTestButtonClick((additionalArgs) => {
        self.registryTesters.test(null, true, additionalArgs);
      });
      return self.resultView;
    };

    this.subscriptions.add(atom.workspace.addOpener((uri) => {
      if (uri === 'atom://tester-result-view') {
        return self.deserializeResultView();
      }
    }));

    const onShouldTestHandler = async () => {
      if (!self.lastTestEditor) {
        self.lastTestEditor = atom.workspace.getActiveTextEditor();
      }
      const activeItem = self.lastTestEditor || atom.workspace.getActivePaneItem();
      const editorTester = self.registryEditors.get(activeItem);

      if (editorTester) {
        // await self.updateStatusBar();
        editorTester.test();
      }
    };
    const onShouldTestProjectHandler = () => {
      self.registryTesters.test(null, true, self.resultView ? self.resultView.getAdditionalArgs() : '');
    };

    this.commands.onShouldTestLast(() => {
      if (self.lastTestEditor) {
        onShouldTestHandler();
      } else {
        onShouldTestProjectHandler();
      }
    });

    this.commands.onShouldTestProject(onShouldTestProjectHandler);

    this.commands.onShouldTest(onShouldTestHandler);

    this.commands.onShouldStop(() => {
      self.registryTesters.stop(atom.workspace.getActiveTextEditor());
    });

    this.commands.onShouldToggleTesterOutput(() => {
      this.togglePanel();
    });
    this.commands.onShouldToggleTesterResultView(() => {
      this.toggleResultView();
    });

    this.commands.onShouldGoToNextTest(() => {
      if (!this.resultView) { return; }
      this.resultView.goToNextTest();
    });
    this.commands.onShouldGoToPreviousTest(() => {
      if (!this.resultView) { return; }
      this.resultView.goToPreviousTest();
    });

    this.registryEditors.observe((editorTester) => {
      editorTester.onShouldTest(() => {
        self.registryTesters.test(editorTester, null, self.resultView ? self.resultView.getAdditionalArgs() : '');
      });
      editorTester.onShouldStop(() => {
        self.registryTesters.stop(editorTester);
      });
    });

    this.registryTesters.onDidUpdateMessages(async ({ editor, messages, output }) => {
      self.getStore().dispatch(actions.updateEditorAction(editor));
      self.getStore().dispatch(actions.updateMessagesAction(messages));
      self.getStore().dispatch(actions.updateOutputAction(output));

      // messages.forEach((message, index) => {
      //   if (!message || typeof message !== 'object') {
      //     messages.splice(index, 1);
      //     console.warn('Tester: Message is not valid. Remove it from globals.', message);
      //   }
      // });
      // this.messages = messages;
      // this.output = output;
      // await self.updateStatusBar();
      // if (this.panel) {
      //   await this.panel.update({ output });
      // }
      // if (this.resultView) {
      //   await this.resultView.update({ messages: this.messages });
      // }
      //
      // if (editor) {
      //   const gutter = self.registryEditors.handleGutter(editor);
      //   if (!gutter) {
      //     return;
      //   }
      //   clearInlineMessages(editor);
      //   decorateGutter(editor, gutter, this.messages);
      //   if (this.showInlineError) {
      //     setInlineMessages(editor, this.messages, this.ansiToHtml, this.inlineErrorPosition);
      //   }
      // }
    });

    this.registryTesters.onDidBeginTesting(async ({ editorTester }) => {
      self.getStore().dispatch(actions.updateEditorAction(editorTester ? editorTester.editor : null));
      self.getStore().dispatch(actions.increaseCounterAction());

      // self.lastTestEditor = editorTester ? editorTester.editor : null;
      // self.runningTestersCount += 1;
      // if (self.resultView) {
      //   await self.resultView.update({ runningTestersCount: self.runningTestersCount });
      // }
      // await self.updateStatusBar();
    });

    this.registryTesters.onDidFinishTesting(async () => {
      self.getStore().dispatch(actions.decreaseCounterAction());
      // self.runningTestersCount -= 1;
      // if (self.resultView) {
      //   await self.resultView.update({ runningTestersCount: self.runningTestersCount });
      // }
      // await self.updateStatusBar();
    });

    this.registryEditors.activate();

    setTimeout(() => {
      // NOTE: Atom triggers this on boot so wait a while
      if (!self.subscriptions.disposed) {
        self.subscriptions.add(atom.project.onDidChangePaths(() => {
          self.registryEditors.handleGutter();
          self.commands.test();
        }));
      }
    }, 100);
  }

  createStatusBar(statusBar : Object) {
    if (!atom.config.get('tester.showStatusBar')) {
      return;
    }
    const onclick = () => {
      const statusBarOnClick = atom.config.get('tester.statusBarOnClick');
      if (statusBarOnClick === 'console' || statusBarOnClick === 'both') {
        this.togglePanel();
      }
      if (statusBarOnClick === 'results' || statusBarOnClick === 'both') {
        this.toggleResultView();
      }
    };
    this.statusBarTile = new StatusBarTile({ store: this.getStore(), onclick });
    // this.statusBarTile = new StatusBarTile({
    //   messages: this.messages,
    //   runningTestersCount: this.runningTestersCount,
    //   onclick,
    // });

    statusBar.addLeftTile({
      item: this.statusBarTile.element,
      priority: -50,
    });
  }
  //
  // async updateStatusBar() {
  //   if (this.statusBarTile) {
  //     await this.statusBarTile.update({
  //       messages: this.messages,
  //       runningTestersCount: this.runningTestersCount,
  //     });
  //   }
  // }

  togglePanel() {
    if (atom.getVersion() < '1.17') {
      return atom.notifications.addWarning('Please update atom to version >=1.17 to use tester dock views.');
    }
    atom.workspace.toggle('atom://tester-console-output');
  }

  toggleResultView() {
    if (atom.getVersion() < '1.17') {
      return atom.notifications.addWarning('Please update atom to version >=1.17 to use tester dock views.');
    }
    atom.workspace.toggle('atom://tester-result-view');
  }

  async dispose() {
    if (this.statusBarTile) {
      await this.statusBarTile.destroy();
    }
    if (this.panel) {
      await this.panel.destroy();
    }
    if (this.resultView) {
      await this.resultView.destroy();
    }
    this.subscriptions.dispose();
  }

  addTester(tester : TesterProvider) {
    this.registryTesters.addTester(tester);
  }

  deleteTester(tester : TesterProvider) {
    this.registryTesters.deleteTester(tester);
  }
}

export default {
  instance: null,
  consumeStatusBar(statusBar : any) {
    this.instance.createStatusBar(statusBar);
  },

  initialize(rawState: any) {
    console.log('rawState', rawState);
    this.instance = new Tester();
    this.deserializeResultView = this.instance.deserializeResultView;
    this.deserializeConsoleOutput = this.instance.deserializeConsoleOutput;
  },

  getInstance(): ?Tester {
    return this.instance;
  },

  consumeTester(tester : Tester) : Disposable {
    const testers = [].concat(tester);
    for (const entry of testers) {
      this.instance.addTester(entry);
    }
    return new Disposable(() => {
      for (const entry of testers) {
        this.instance.deleteTester(entry);
      }
    });
  },

  serialize(){
    if(!this.instance){
      return {};
    }
    return this.instance.getStore();
  }

  deactivate() {
    this.instance.dispose();
  },
};
<commit_msg>fix syntax error<commit_after>'use babel';

/* @flow */

import { Disposable, CompositeDisposable } from 'atom';
import type { Panel, TextEditor } from 'atom';

import 'rxjs';
import { createStore, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import reducers from './redux/reducers';
import epics from './redux/epics';
import * as actions from './redux/actions';

import Commands from './commands';
import EditorsRegistry from './editor-registry';
import TesterRegistry from './tester-registry';
// import { clearInlineMessages, decorateGutter, setInlineMessages } from './decorate-manager';
import ConsoleOutputView from './views/ConsoleOutputView';
import ResultView from './views/ResultView';
import StatusBarTile from './views/StatusBarTile';
import type { Tester as TesterProvider, Message, Store } from './types';

class Tester {
  commands: Commands;
  subscriptions: CompositeDisposable;
  modalPanel: Panel;
  registryTesters: TesterRegistry;
  registryEditors: EditorsRegistry;
  statusBarTile: Object;
  markers: Array<Object>;
  showInlineError: boolean;
  inlineErrorPosition: string;
  ansiToHtml: boolean;
  showOutputAfterTestRun: boolean;
  showNotifications: boolean;
  messageTimeout: number;
  runningTestersCount: number;
  scrollToBottom: boolean;
  panel: ?ConsoleOutputView;
  resultView: ?ResultView;
  messages:Array<Message>;
  output: string;
  testerStatusBar: Object;
  lastTestEditor: TextEditor;
  deserializeResultView: Function;
  deserializeConsoleOutput: Function;
  store: Store;
  getStore: Function;

  constructor() {
    this.commands = new Commands();
    this.registryEditors = new EditorsRegistry();
    this.registryTesters = new TesterRegistry();
    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(this.commands);
    this.subscriptions.add(this.registryEditors);
    this.subscriptions.add(this.registryTesters);
    this.markers = [];
    this.showInlineError = true;
    this.inlineErrorPosition = 'after';
    this.ansiToHtml = true;
    this.showOutputAfterTestRun = true;
    this.showNotifications = true;
    this.messageTimeout = 5;
    this.runningTestersCount = 0;
    this.scrollToBottom = true;
    this.messages = [];
    this.output = '';
    this.lastTestEditor = null;
    const self = this;

    this.getStore = (initialState) => {
      if (self.store == null) {
        self.store = createStore(
          reducers,
          initialState,
          applyMiddleware(createEpicMiddleware(epics)),
        );
        self.store.subscribe(() => {
          console.log('store updated', self.store.getState());
          // update all views here
        });
      }
      return self.store;
    };
    this.subscriptions.add(atom.config.observe('tester.gutterEnabled', (gutterEnabled) => {
      this.registryEditors.gutterEnabled = gutterEnabled;
    }));
    this.subscriptions.add(atom.config.observe('tester.showInlineError', (showInlineError) => {
      this.showInlineError = showInlineError;
    }));
    this.subscriptions.add(atom.config.observe('tester.inlineErrorPosition', (inlineErrorPosition) => {
      this.inlineErrorPosition = inlineErrorPosition;
    }));
    this.subscriptions.add(atom.config.observe('tester.ansiToHtml', (ansiToHtml) => {
      this.ansiToHtml = ansiToHtml;
    }));
    this.subscriptions.add(atom.config.observe('tester.showOutputAfterTestRun', (showOutputAfterTestRun) => {
      this.showOutputAfterTestRun = showOutputAfterTestRun;
    }));
    this.subscriptions.add(atom.config.observe('tester.messageTimeout', (messageTimeout) => {
      this.messageTimeout = messageTimeout;
    }));
    this.subscriptions.add(atom.config.observe('tester.showNotifications', (showNotifications) => {
      this.showNotifications = showNotifications;
    }));
    this.subscriptions.add(atom.config.observe('tester.scrollToBottom', (scrollToBottom) => {
      this.scrollToBottom = scrollToBottom;
    }));
    this.subscriptions.add(atom.workspace.observeTextEditors(async (/* editor*/) => {
      // await self.updateStatusBar();
    }));
    this.subscriptions.add(atom.workspace.onDidChangeActivePaneItem(async (/* paneItem*/) => {
      // await self.updateStatusBar();
    }));

    this.subscriptions.add(new Disposable(() => {
      atom.workspace.getPaneItems().forEach((item) => {
        if (item instanceof ConsoleOutputView) {
          item.destroy();
        }
      });
    }));

    this.deserializeConsoleOutput = function deserializeConsoleOutput(serializedState :any) {
      console.log('serializedState', serializedState);
      self.panel = new ConsoleOutputView({
        store: self.getStore(),
        ansiToHtml: self.ansiToHtml,
        scrollToBottom: self.scrollToBottom,
      });
      // self.panel = new ConsoleOutputView({
      //   output: self.output,
      //   ansiToHtml: self.ansiToHtml,
      //   scrollToBottom: self.scrollToBottom });
      return self.panel;
    };

    this.subscriptions.add(atom.workspace.addOpener((uri) => {
      if (uri === 'atom://tester-console-output') {
        return self.deserializeConsoleOutput();
      }
    }));

    this.subscriptions.add(new Disposable(() => {
      atom.workspace.getPaneItems().forEach((item) => {
        if (item instanceof ResultView) {
          item.destroy();
        }
      });
    }));

    this.deserializeResultView = function deserializeResultView(serializedState :any) {
      console.log('serializedState', serializedState);
      self.resultView = new ResultView({
        store: self.getStore(),
        ansiToHtml: self.ansiToHtml,
        softWrap: atom.config.get('tester.softWrapDefault'),
      });
      // self.resultView = new ResultView({
      //   messages: self.messages,
      //   ansiToHtml: self.ansiToHtml,
      //   softWrap: atom.config.get('tester.softWrapDefault'),
      //   runningTestersCount: self.runningTestersCount,
      // });
      self.resultView.onTestButtonClick((additionalArgs) => {
        self.registryTesters.test(null, true, additionalArgs);
      });
      return self.resultView;
    };

    this.subscriptions.add(atom.workspace.addOpener((uri) => {
      if (uri === 'atom://tester-result-view') {
        return self.deserializeResultView();
      }
    }));

    const onShouldTestHandler = async () => {
      if (!self.lastTestEditor) {
        self.lastTestEditor = atom.workspace.getActiveTextEditor();
      }
      const activeItem = self.lastTestEditor || atom.workspace.getActivePaneItem();
      const editorTester = self.registryEditors.get(activeItem);

      if (editorTester) {
        // await self.updateStatusBar();
        editorTester.test();
      }
    };
    const onShouldTestProjectHandler = () => {
      self.registryTesters.test(null, true, self.resultView ? self.resultView.getAdditionalArgs() : '');
    };

    this.commands.onShouldTestLast(() => {
      if (self.lastTestEditor) {
        onShouldTestHandler();
      } else {
        onShouldTestProjectHandler();
      }
    });

    this.commands.onShouldTestProject(onShouldTestProjectHandler);

    this.commands.onShouldTest(onShouldTestHandler);

    this.commands.onShouldStop(() => {
      self.registryTesters.stop(atom.workspace.getActiveTextEditor());
    });

    this.commands.onShouldToggleTesterOutput(() => {
      this.togglePanel();
    });
    this.commands.onShouldToggleTesterResultView(() => {
      this.toggleResultView();
    });

    this.commands.onShouldGoToNextTest(() => {
      if (!this.resultView) { return; }
      this.resultView.goToNextTest();
    });
    this.commands.onShouldGoToPreviousTest(() => {
      if (!this.resultView) { return; }
      this.resultView.goToPreviousTest();
    });

    this.registryEditors.observe((editorTester) => {
      editorTester.onShouldTest(() => {
        self.registryTesters.test(editorTester, null, self.resultView ? self.resultView.getAdditionalArgs() : '');
      });
      editorTester.onShouldStop(() => {
        self.registryTesters.stop(editorTester);
      });
    });

    this.registryTesters.onDidUpdateMessages(async ({ editor, messages, output }) => {
      self.getStore().dispatch(actions.updateEditorAction(editor));
      self.getStore().dispatch(actions.updateMessagesAction(messages));
      self.getStore().dispatch(actions.updateOutputAction(output));

      // messages.forEach((message, index) => {
      //   if (!message || typeof message !== 'object') {
      //     messages.splice(index, 1);
      //     console.warn('Tester: Message is not valid. Remove it from globals.', message);
      //   }
      // });
      // this.messages = messages;
      // this.output = output;
      // await self.updateStatusBar();
      // if (this.panel) {
      //   await this.panel.update({ output });
      // }
      // if (this.resultView) {
      //   await this.resultView.update({ messages: this.messages });
      // }
      //
      // if (editor) {
      //   const gutter = self.registryEditors.handleGutter(editor);
      //   if (!gutter) {
      //     return;
      //   }
      //   clearInlineMessages(editor);
      //   decorateGutter(editor, gutter, this.messages);
      //   if (this.showInlineError) {
      //     setInlineMessages(editor, this.messages, this.ansiToHtml, this.inlineErrorPosition);
      //   }
      // }
    });

    this.registryTesters.onDidBeginTesting(async ({ editorTester }) => {
      self.getStore().dispatch(actions.updateEditorAction(editorTester ? editorTester.editor : null));
      self.getStore().dispatch(actions.increaseCounterAction());

      // self.lastTestEditor = editorTester ? editorTester.editor : null;
      // self.runningTestersCount += 1;
      // if (self.resultView) {
      //   await self.resultView.update({ runningTestersCount: self.runningTestersCount });
      // }
      // await self.updateStatusBar();
    });

    this.registryTesters.onDidFinishTesting(async () => {
      self.getStore().dispatch(actions.decreaseCounterAction());
      // self.runningTestersCount -= 1;
      // if (self.resultView) {
      //   await self.resultView.update({ runningTestersCount: self.runningTestersCount });
      // }
      // await self.updateStatusBar();
    });

    this.registryEditors.activate();

    setTimeout(() => {
      // NOTE: Atom triggers this on boot so wait a while
      if (!self.subscriptions.disposed) {
        self.subscriptions.add(atom.project.onDidChangePaths(() => {
          self.registryEditors.handleGutter();
          self.commands.test();
        }));
      }
    }, 100);
  }

  createStatusBar(statusBar : Object) {
    if (!atom.config.get('tester.showStatusBar')) {
      return;
    }
    const onclick = () => {
      const statusBarOnClick = atom.config.get('tester.statusBarOnClick');
      if (statusBarOnClick === 'console' || statusBarOnClick === 'both') {
        this.togglePanel();
      }
      if (statusBarOnClick === 'results' || statusBarOnClick === 'both') {
        this.toggleResultView();
      }
    };
    this.statusBarTile = new StatusBarTile({ store: this.getStore(), onclick });
    // this.statusBarTile = new StatusBarTile({
    //   messages: this.messages,
    //   runningTestersCount: this.runningTestersCount,
    //   onclick,
    // });

    statusBar.addLeftTile({
      item: this.statusBarTile.element,
      priority: -50,
    });
  }
  //
  // async updateStatusBar() {
  //   if (this.statusBarTile) {
  //     await this.statusBarTile.update({
  //       messages: this.messages,
  //       runningTestersCount: this.runningTestersCount,
  //     });
  //   }
  // }

  togglePanel() {
    if (atom.getVersion() < '1.17') {
      return atom.notifications.addWarning('Please update atom to version >=1.17 to use tester dock views.');
    }
    atom.workspace.toggle('atom://tester-console-output');
  }

  toggleResultView() {
    if (atom.getVersion() < '1.17') {
      return atom.notifications.addWarning('Please update atom to version >=1.17 to use tester dock views.');
    }
    atom.workspace.toggle('atom://tester-result-view');
  }

  async dispose() {
    if (this.statusBarTile) {
      await this.statusBarTile.destroy();
    }
    if (this.panel) {
      await this.panel.destroy();
    }
    if (this.resultView) {
      await this.resultView.destroy();
    }
    this.subscriptions.dispose();
  }

  addTester(tester : TesterProvider) {
    this.registryTesters.addTester(tester);
  }

  deleteTester(tester : TesterProvider) {
    this.registryTesters.deleteTester(tester);
  }
}

export default {
  instance: null,
  consumeStatusBar(statusBar : any) {
    this.instance.createStatusBar(statusBar);
  },

  initialize(rawState: any) {
    console.log('rawState', rawState);
    this.instance = new Tester();
    this.deserializeResultView = this.instance.deserializeResultView;
    this.deserializeConsoleOutput = this.instance.deserializeConsoleOutput;
  },

  getInstance(): ?Tester {
    return this.instance;
  },

  consumeTester(tester : Tester) : Disposable {
    const testers = [].concat(tester);
    for (const entry of testers) {
      this.instance.addTester(entry);
    }
    return new Disposable(() => {
      for (const entry of testers) {
        this.instance.deleteTester(entry);
      }
    });
  },

  serialize() {
    if (!this.instance) {
      return {};
    }
    return this.instance.getStore();
  },

  deactivate() {
    this.instance.dispose();
  },
};
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');
var utils = require('./to_string_utils');
var textDiff = require('./text_diff');
var virtualDomImplementation = require('../vdom/virtual_dom_implementation');
var isVNode = virtualDomImplementation.isVNode;
var isVText = virtualDomImplementation.isVText;
var isWidget = virtualDomImplementation.isWidget;
var HTMLCommentWidget = require('../template/widgets/html_comment');
var isHook = virtualDomImplementation.isHook;
var vNodeToString = require('./vtree_to_string');

var chars = utils.entities.escaped;

/**
 * Called when a VirtualNode and DOM node align
 *
 * @param  {Object}  vNode VirtualNode
 * @param  {Element} elem  DOM node
 *
 * @return {string}        Diff string
 */
function diffElements(vNode, elem) {
  var output = '';
  // Diff tagnames and save for closing
  var tagDiff = textDiff(vNode.tagName.toLowerCase(), elem.tagName.toLowerCase());
  output += chars.open;
  output += tagDiff;

  // Check declared property values vs DOM values
  // This bypasses properties that are not managed by VirtualNode
  _.each(vNode.properties, function(value, key) {
    if (key === 'attributes') {
      return;
    }
    if (key.toLowerCase() === 'contenteditable' && value.toLowerCase() === 'inherit') {
      return;
    }
    var propValue = value;
    if (isHook(propValue)) {
      if (propValue.value) {
        propValue = propValue.value;
      } else {
        // If this is a hook with no value, ignore as it's functional
        return;
      }
    }
    var propName = utils.propertiesToTransform[key] ? utils.propertiesToTransform[key] : key;

    var domValue = elem[key];
    if (propName === 'href') {
      // the href property displays the fully resolved URL when read, so fall back to attribute value
      domValue = elem.getAttribute('href');
    }

    var vAttr = ' ' + propName + '=' + chars.quote + propValue + chars.quote;
    var eAttr = ' ' + propName + '=' + chars.quote + elem[key] + chars.quote;
    // If the property is a boolean, any non-"false" value of the template is fine
    output += elem[key] === true && propValue.toString() !== 'false' ? vAttr : textDiff(vAttr, eAttr);
  });

  // Check declared attribute values vs DOM values
  // This bypasses attributes that are not managed by VirtualNode
  _.each(vNode.properties.attributes, function(value, key) {
    if (key.toLowerCase() === 'contenteditable' && value.toLowerCase() === 'inherit') {
      return;
    }
    var propValue = value;
    if (isHook(propValue)) {
      propValue = propValue.value;
    }
    var vAttr = ' ' + key + '=' + chars.quote + propValue + chars.quote;
    var eAttr = ' ' + key + '=' + chars.quote + elem.getAttribute(key) + chars.quote;
    output += textDiff(vAttr, eAttr);
  });
  output += chars.close;

  // Iterate over the larger number of children
  var numChildren = Math.max(vNode.children.length, elem.childNodes.length);

  for (var i = 0; i < numChildren; i++) {
    output += recursiveDiff(vNode.children[i], elem.childNodes[i]);
  }
  // For diffing purposes all tags are <tag></tag>, even self-closing tags
  output += chars.open + '/' + tagDiff + chars.close;
  return output;
}

/**
 * Iterates over a VirtualDOM and DOM structure to create a diff string
 *
 * @param  {Object}  vtree VirtualDOM object
 * @param  {Element} elem  DOM object
 *
 * @return {string}        Diff string
 */
function recursiveDiff(vtree, elem) {
  var output = '';
  if (vtree == null && elem != null) {
    // If the VTree ran out but DOM still exists
    output += '' + utils.elementToString(elem, chars) + '';
  } else if (isVNode(vtree)) {
    if (!elem || elem.nodeType !== utils.NODE_TYPES.ELEMENT) {
      // If vtree is a VNode, but elem isn't an Element
      output += '' + vNodeToString(vtree, true, false) + '';
      if (elem) {
        output += '' + utils.elementToString(elem, chars) + '';
      }
    } else {
      // Diff elements and recurse
      output += diffElements(vtree, elem);
    }
  } else if (isVText(vtree)) {
    if (!elem || elem.nodeType !== utils.NODE_TYPES.TEXT) {
      // If vtree is a VText, but elem isn't a textNode
      output += '' + utils.escapeString(vtree.text) + '';
      if (elem) {
        output += '' + utils.elementToString(elem, chars) + '';
      }
    } else {
      output += textDiff(vtree.text, elem.textContent);
    }
  } else if (isWidget(vtree)) {
    // Widgets are the construct that hold childViews
    if (vtree.constructor === HTMLCommentWidget) {
      // HTMLCommentWidget is a special case
      if (!elem || elem.nodeType !== utils.NODE_TYPES.COMMENT) {
        output += '' + utils.getCommentString(utils.escapeString(vtree.text), chars) + '';
        if (elem) {
          output += '' + utils.elementToString(elem, chars) + '';
        }
      } else {
        output += utils.getCommentString(textDiff(vtree.text, elem.textContent), chars);
      }
    } else {
      var widgetName = vtree.view.getDebugName();
      if (typeof vtree.templateToString === 'function') {
        widgetName = vtree.templateToString(true);
      }
      if (vtree.view && vtree.view.el !== elem) {
        // If the view at this position isn't bound to elem, something has gone terribly wrong
        output += '' + widgetName + '';
      } else {
        output += widgetName;
      }
    }
  }
  return output;
}

module.exports = recursiveDiff;
<commit_msg>Making diff_dom_and_vdom resistant to uninitialized child views<commit_after>'use strict';

var _ = require('underscore');
var utils = require('./to_string_utils');
var textDiff = require('./text_diff');
var virtualDomImplementation = require('../vdom/virtual_dom_implementation');
var isVNode = virtualDomImplementation.isVNode;
var isVText = virtualDomImplementation.isVText;
var isWidget = virtualDomImplementation.isWidget;
var HTMLCommentWidget = require('../template/widgets/html_comment');
var isHook = virtualDomImplementation.isHook;
var vNodeToString = require('./vtree_to_string');

var chars = utils.entities.escaped;

/**
 * Called when a VirtualNode and DOM node align
 *
 * @param  {Object}  vNode VirtualNode
 * @param  {Element} elem  DOM node
 *
 * @return {string}        Diff string
 */
function diffElements(vNode, elem) {
  var output = '';
  // Diff tagnames and save for closing
  var tagDiff = textDiff(vNode.tagName.toLowerCase(), elem.tagName.toLowerCase());
  output += chars.open;
  output += tagDiff;

  // Check declared property values vs DOM values
  // This bypasses properties that are not managed by VirtualNode
  _.each(vNode.properties, function(value, key) {
    if (key === 'attributes') {
      return;
    }
    if (key.toLowerCase() === 'contenteditable' && value.toLowerCase() === 'inherit') {
      return;
    }
    var propValue = value;
    if (isHook(propValue)) {
      if (propValue.value) {
        propValue = propValue.value;
      } else {
        // If this is a hook with no value, ignore as it's functional
        return;
      }
    }
    var propName = utils.propertiesToTransform[key] ? utils.propertiesToTransform[key] : key;

    var domValue = elem[key];
    if (propName === 'href') {
      // the href property displays the fully resolved URL when read, so fall back to attribute value
      domValue = elem.getAttribute('href');
    }

    var vAttr = ' ' + propName + '=' + chars.quote + propValue + chars.quote;
    var eAttr = ' ' + propName + '=' + chars.quote + elem[key] + chars.quote;
    // If the property is a boolean, any non-"false" value of the template is fine
    output += elem[key] === true && propValue.toString() !== 'false' ? vAttr : textDiff(vAttr, eAttr);
  });

  // Check declared attribute values vs DOM values
  // This bypasses attributes that are not managed by VirtualNode
  _.each(vNode.properties.attributes, function(value, key) {
    if (key.toLowerCase() === 'contenteditable' && value.toLowerCase() === 'inherit') {
      return;
    }
    var propValue = value;
    if (isHook(propValue)) {
      propValue = propValue.value;
    }
    var vAttr = ' ' + key + '=' + chars.quote + propValue + chars.quote;
    var eAttr = ' ' + key + '=' + chars.quote + elem.getAttribute(key) + chars.quote;
    output += textDiff(vAttr, eAttr);
  });
  output += chars.close;

  // Iterate over the larger number of children
  var numChildren = Math.max(vNode.children.length, elem.childNodes.length);

  for (var i = 0; i < numChildren; i++) {
    output += recursiveDiff(vNode.children[i], elem.childNodes[i]);
  }
  // For diffing purposes all tags are <tag></tag>, even self-closing tags
  output += chars.open + '/' + tagDiff + chars.close;
  return output;
}

/**
 * Iterates over a VirtualDOM and DOM structure to create a diff string
 *
 * @param  {Object}  vtree VirtualDOM object
 * @param  {Element} elem  DOM object
 *
 * @return {string}        Diff string
 */
function recursiveDiff(vtree, elem) {
  var output = '';
  if (vtree == null && elem != null) {
    // If the VTree ran out but DOM still exists
    output += '' + utils.elementToString(elem, chars) + '';
  } else if (isVNode(vtree)) {
    if (!elem || elem.nodeType !== utils.NODE_TYPES.ELEMENT) {
      // If vtree is a VNode, but elem isn't an Element
      output += '' + vNodeToString(vtree, true, false) + '';
      if (elem) {
        output += '' + utils.elementToString(elem, chars) + '';
      }
    } else {
      // Diff elements and recurse
      output += diffElements(vtree, elem);
    }
  } else if (isVText(vtree)) {
    if (!elem || elem.nodeType !== utils.NODE_TYPES.TEXT) {
      // If vtree is a VText, but elem isn't a textNode
      output += '' + utils.escapeString(vtree.text) + '';
      if (elem) {
        output += '' + utils.elementToString(elem, chars) + '';
      }
    } else {
      output += textDiff(vtree.text, elem.textContent);
    }
  } else if (isWidget(vtree)) {
    var widgetName;
    // Widgets are the construct that hold childViews
    if (vtree.constructor === HTMLCommentWidget) {
      // HTMLCommentWidget is a special case
      if (!elem || elem.nodeType !== utils.NODE_TYPES.COMMENT) {
        output += '' + utils.getCommentString(utils.escapeString(vtree.text), chars) + '';
        if (elem) {
          output += '' + utils.elementToString(elem, chars) + '';
        }
      } else {
        output += utils.getCommentString(textDiff(vtree.text, elem.textContent), chars);
      }
    } else if (vtree && vtree.view) {
      widgetName = vtree.view.getDebugName();
      if (typeof vtree.templateToString === 'function') {
        widgetName = vtree.templateToString(true);
      }
      if (vtree.view.el !== elem) {
        // If the view at this position isn't bound to elem, something has gone terribly wrong
        output += '' + widgetName + '';
      } else {
        output += widgetName;
      }
    } else {
      output += '[Uninitialized child view]';
      output += '' + utils.elementToString(elem, chars) + '';
    }
  }
  return output;
}

module.exports = recursiveDiff;
<|endoftext|>


<commit_before>import resolve from "@rollup/plugin-node-resolve";
import babel from "@rollup/plugin-babel";
import rust from "@wasm-tool/rollup-plugin-rust";
import { terser } from "rollup-plugin-terser";

const plugins = [
  babel({
    exclude: "node_modules/**",
    babelHelpers: "bundled",
    presets: ["solid"]
  }),
  resolve({ extensions: [".js", ".jsx"] }),
  rust({ inlineWasm: true })
];

export default {
  input: "src/index.js",
  output: [
    {
      file: "dist/index.js",
      format: "es"
    },
    {
      file: "public/bundle.js",
      format: "iife",
      name: "AsciinemaPlayer"
    },
    {
      file: "public/bundle.min.js",
      format: "iife",
      name: "AsciinemaPlayer",
      plugins: [terser()]
    }
  ],
  plugins
};
<commit_msg>Remove import.meta.url from the output bundles<commit_after>import resolve from "@rollup/plugin-node-resolve";
import babel from "@rollup/plugin-babel";
import rust from "@wasm-tool/rollup-plugin-rust";
import { terser } from "rollup-plugin-terser";

function removeImportMetaUrl() {
  // This plugin replaces import.meta.url with an empty string. Why?
  // wasm-bindgen produces a wasm loading code having reference to
  // import.meta.url, which becomes a dead code given rust plugin inlines the
  // wasm blob, while import.meta.url triggers bundling issues with popular
  // bundlers (or requires plugins).

  return {
    resolveImportMeta(property, {moduleId}) {
      if (property === 'url') { return "''" }
      return null;
    }
  }
}

const plugins = [
  babel({
    exclude: "node_modules/**",
    babelHelpers: "bundled",
    presets: ["solid"]
  }),
  resolve({ extensions: [".js", ".jsx"] }),
  rust({ inlineWasm: true }),
  removeImportMetaUrl()
];

export default {
  input: "src/index.js",
  output: [
    {
      file: "dist/index.js",
      format: "es"
    },
    {
      file: "public/bundle.js",
      format: "iife",
      name: "AsciinemaPlayer"
    },
    {
      file: "public/bundle.min.js",
      format: "iife",
      name: "AsciinemaPlayer",
      plugins: [terser()]
    }
  ],
  plugins
};
<|endoftext|>