<commit_before>'use strict';

/**
 * Determines the response for a stub based on the user-provided response configuration
 * @module
 */

/**
 * Creates the resolver
 * @param {Object} proxy - The protocol-specific proxy implementation
 * @param {Function} postProcess - The protocol-specific post-processor to add default response values
 * @returns {Object}
 */
function create (proxy, postProcess) {
    var injectState = {};

    function inject (request, fn, logger, imposterState) {
        var Q = require('q'),
            helpers = require('../util/helpers'),
            deferred = Q.defer(),
            scope = helpers.clone(request),
            injected = '(' + fn + ')(scope, injectState, logger, deferred.resolve, imposterState);',
            exceptions = require('../util/errors');

        if (request.isDryRun === true) {
            Q.delay(1).then(function () {
                deferred.resolve({});
            });
        }
        else {
            try {
                var response = eval(injected);
                if (helpers.defined(response)) {
                    deferred.resolve(response);
                }
            }
            catch (error) {
                logger.error('injection X=> ' + error);
                logger.error('    full source: ' + JSON.stringify(injected));
                logger.error('    scope: ' + JSON.stringify(scope));
                logger.error('    injectState: ' + JSON.stringify(injectState));
                logger.error('    imposterState: ' + JSON.stringify(imposterState));
                deferred.reject(exceptions.InjectionError('invalid response injection', {
                    source: injected,
                    data: error.message
                }));
            }
        }
        return deferred.promise;
    }

    function buildEquals (request, matchers) {
        var result = {};
        Object.keys(matchers).forEach(function (key) {
            if (typeof request[key] === 'object') {
                result[key] = buildEquals(request[key], matchers[key]);
            }
            else {
                result[key] = request[key];
            }
        });
        return result;
    }

    function predicatesFor (request, matchers) {
        var predicates = [];

        matchers.forEach(function (matcher) {
            var basePredicate = {};

            // Add parameters
            Object.keys(matcher).forEach(function (key) {
                if (key !== 'matches') {
                    basePredicate[key] = matcher[key];
                }
            });

            Object.keys(matcher.matches).forEach(function (fieldName) {
                var helpers = require('../util/helpers'),
                    value = matcher.matches[fieldName],
                    predicate = helpers.clone(basePredicate);

                if (value === true) {
                    predicate.deepEquals = {};
                    predicate.deepEquals[fieldName] = request[fieldName];
                }
                else {
                    predicate.equals = {};
                    predicate.equals[fieldName] = buildEquals(request[fieldName], value);
                }

                predicates.push(predicate);
            });
        });

        return predicates;
    }

    function stubIndexFor (responseConfig, stubs) {
        for (var i = 0; i < stubs.length; i += 1) {
            var stub = stubs[i];
            if (stub.responses.indexOf(responseConfig) >= 0) {
                break;
            }
        }
        return i;
    }

    function indexOfStubToAddResponseTo (responseConfig, request, stubs) {
        var predicates = predicatesFor(request, responseConfig.proxy.predicateGenerators || []),
            stringify = require('json-stable-stringify');

        for (var index = stubIndexFor(responseConfig, stubs) + 1; index < stubs.length; index += 1) {
            if (stringify(predicates) === stringify(stubs[index].predicates)) {
                return index;
            }
        }
        return -1;
    }

    function canAddResponseToExistingStub (responseConfig, request, stubs) {
        return indexOfStubToAddResponseTo(responseConfig, request, stubs) >= 0;
    }

    function newIsResponse (response, addWaitBehavior, addDecorateBehavior) {
        var result = { is: response };
        var addBehaviors = {};

        if (addWaitBehavior && response._proxyResponseTime) { // eslint-disable-line no-underscore-dangle
            addBehaviors.wait = response._proxyResponseTime;  // eslint-disable-line no-underscore-dangle
        }
        if (addDecorateBehavior) {
            addBehaviors.decorate = addDecorateBehavior;
        }

        if (Object.keys(addBehaviors).length) {
            result._behaviors = addBehaviors;
        }
        return result;
    }

    function addNewResponse (responseConfig, request, response, stubs) {
        var stubResponse = newIsResponse(response, responseConfig.proxy.addWaitBehavior, responseConfig.proxy.addDecorateBehavior),
            responseIndex = indexOfStubToAddResponseTo(responseConfig, request, stubs);

        stubs[responseIndex].responses.push(stubResponse);
    }

    function addNewStub (responseConfig, request, response, stubs) {
        var predicates = predicatesFor(request, responseConfig.proxy.predicateGenerators || []),
            stubResponse = newIsResponse(response, responseConfig.proxy.addWaitBehavior, responseConfig.proxy.addDecorateBehavior),
            newStub = { predicates: predicates, responses: [stubResponse] },
            index = responseConfig.proxy.mode === 'proxyAlways' ? stubs.length : stubIndexFor(responseConfig, stubs);

        stubs.splice(index, 0, newStub);
    }

    function recordProxyResponse (responseConfig, request, response, stubs) {
        if (['proxyOnce', 'proxyAlways'].indexOf(responseConfig.proxy.mode) < 0) {
            responseConfig.proxy.mode = 'proxyOnce';
        }

        if (responseConfig.proxy.mode === 'proxyAlways' && canAddResponseToExistingStub(responseConfig, request, stubs)) {
            addNewResponse(responseConfig, request, response, stubs);
        }
        else {
            addNewStub(responseConfig, request, response, stubs);
        }
    }

    function addInjectedHeadersTo (request, headersToInject) {
        Object.keys(headersToInject || {}).forEach(function (key) {
            request.headers[key] = headersToInject[key];
        });
    }

    function proxyAndRecord (responseConfig, request, logger, stubs) {
        var Q = require('q'),
            behaviors = require('./behaviors');

        addInjectedHeadersTo(request, responseConfig.proxy.injectHeaders);

        return proxy.to(responseConfig.proxy.to, request, responseConfig.proxy).then(function (response) {
            // Run behaviors here to persist decorated response
            return Q(behaviors.execute(request, response, responseConfig._behaviors, logger));
        }).then(function (response) {
            recordProxyResponse(responseConfig, request, response, stubs);
            return Q(response);
        });
    }

    function processResponse (responseConfig, request, logger, stubs, imposterState) {
        var Q = require('q'),
            helpers = require('../util/helpers'),
            exceptions = require('../util/errors');

        if (responseConfig.is) {
            // Clone to prevent accidental state changes downstream
            return Q(helpers.clone(responseConfig.is));
        }
        else if (responseConfig.proxy) {
            return proxyAndRecord(responseConfig, request, logger, stubs);
        }
        else if (responseConfig.inject) {
            return inject(request, responseConfig.inject, logger, imposterState).then(Q);
        }
        else {
            return Q.reject(exceptions.ValidationError('unrecognized response type', { source: responseConfig }));
        }
    }

    function hasMultipleTypes (responseConfig) {
        return (responseConfig.is && responseConfig.proxy) ||
               (responseConfig.is && responseConfig.inject) ||
               (responseConfig.proxy && responseConfig.inject);
    }

    /**
     * Resolves a single response
     * @memberOf module:models/responseResolver#
     * @param {Object} responseConfig - The API-provided response configuration
     * @param {Object} request - The protocol-specific request object
     * @param {Object} logger - The logger
     * @param {Object} stubs - The stubs for the imposter
     * @param {Object} imposterState - The current state for the imposter
     * @returns {Object} - Promise resolving to the response
     */
    function resolve (responseConfig, request, logger, stubs, imposterState) {
        var Q = require('q'),
            exceptions = require('../util/errors'),
            helpers = require('../util/helpers'),
            behaviors = require('./behaviors');

        if (hasMultipleTypes(responseConfig)) {
            return Q.reject(exceptions.ValidationError('each response object must have only one response type',
                { source: responseConfig }));
        }

        return processResponse(responseConfig, helpers.clone(request), logger, stubs, imposterState).then(function (response) {
            // We may have already run the behaviors in the proxy call to persist the decorated response
            // in the new stub. If so, we need to ensure we don't re-run it
            if (responseConfig.proxy) {
                return Q(response);
            }
            else {
                return Q(behaviors.execute(request, response, responseConfig._behaviors, logger));
            }
        }).then(function (response) {
            return Q(postProcess(response, request));
        });
    }

    return {
        resolve: resolve
    };
}

module.exports = {
    create: create
};
<commit_msg>Updated xmlpath and jsonpath support for issue #199<commit_after>'use strict';

/**
 * Determines the response for a stub based on the user-provided response configuration
 * @module
 */

/**
 * Creates the resolver
 * @param {Object} proxy - The protocol-specific proxy implementation
 * @param {Function} postProcess - The protocol-specific post-processor to add default response values
 * @returns {Object}
 */
function create (proxy, postProcess) {
    var injectState = {};

    function inject (request, fn, logger, imposterState) {
        var Q = require('q'),
            helpers = require('../util/helpers'),
            deferred = Q.defer(),
            scope = helpers.clone(request),
            injected = '(' + fn + ')(scope, injectState, logger, deferred.resolve, imposterState);',
            exceptions = require('../util/errors');

        if (request.isDryRun === true) {
            Q.delay(1).then(function () {
                deferred.resolve({});
            });
        }
        else {
            try {
                var response = eval(injected);
                if (helpers.defined(response)) {
                    deferred.resolve(response);
                }
            }
            catch (error) {
                logger.error('injection X=> ' + error);
                logger.error('    full source: ' + JSON.stringify(injected));
                logger.error('    scope: ' + JSON.stringify(scope));
                logger.error('    injectState: ' + JSON.stringify(injectState));
                logger.error('    imposterState: ' + JSON.stringify(imposterState));
                deferred.reject(exceptions.InjectionError('invalid response injection', {
                    source: injected,
                    data: error.message
                }));
            }
        }
        return deferred.promise;
    }

    // Function is taken from xpath.js to handle xml namespaces
    function nodeValue (node) {
        if (node.nodeType === node.TEXT_NODE) {
            return node.nodeValue;
        }
        else if (node.nodeType === node.ATTRIBUTE_NODE) {
            return node.value;
        }
        else if (node.firstChild) {
         // Converting to a string allows exists to return true if the node exists,
         // even if there's no data
            return node.firstChild.data + '';
        }
        else {
            return node.data + '';
        }
    }

    function xpathValue (request, value, field, predicate, predicates) {
        var reqBody = (request.body).toString();
        predicate.deepEquals = {};
        if (reqBody !== '') {
            var xpath = require('xpath');
            var dom = require('xmldom').DOMParser;
            var doc = new dom().parseFromString(request.body);
            var savePath = value.xpath.selector;
            var ns = value.xpath.ns;
            if (typeof ns !== 'undefined') {
                var selectFn = xpath.useNamespaces(ns || {}),
                    result = selectFn(savePath, doc),
                    title = result.map(nodeValue);
            }
            else {
                title = xpath.select(savePath, doc);
            }
            if (title.length > 1) {
                for (var i = 0; i < title.length; i += 1) {
                    predicate.deepEquals.body = title[i].toString();
                    predicate.xpath = value.xpath;
                }
                predicate = multiplePathValues(predicate, field, title);
                for (var j = 1; j < title.length; j += 1) {
                    predicates.push(predicate[j - 1]);
                }
            }
            else {
                predicate.deepEquals.body = title.toString();
                predicate.xpath = value.xpath;
            }
        }
        return predicates;
    }

    function multiplePathValues (predicate, field, title) {
        var i, buildPredicate = [], storePredicate = [], finalPredicate = [];
        for (i = 0; i < title.length; i += 1) {
            buildPredicate.push(predicate);
        }

        buildPredicate.forEach(function (storeObject, j) {
            storeObject.deepEquals.body = title[j].toString();
            storePredicate.push(JSON.parse(JSON.stringify(storeObject)));
        });

        if (field === 'jsonpath') {
            storePredicate.forEach(function (jsonpathObject, t) {
                jsonpathObject.jsonpath.selector = (jsonpathObject.jsonpath.selector).replace('*', t);
                predicate.jsonpath = jsonpathObject.jsonpath;
                finalPredicate.push(JSON.parse(JSON.stringify(jsonpathObject)));
            });
            return finalPredicate;
        }
        else {
            storePredicate.forEach(function (xpathObject, t) {
                xpathObject.xpath.selector = xpathObject.xpath.selector + '[' + (t + 1) + ']';
                predicate.xpath = xpathObject.xpath;
                finalPredicate.push(JSON.parse(JSON.stringify(xpathObject)));
            });
            return finalPredicate;
        }
    }

    function jsonpathValue (request, value, field, predicate, predicates) {
        var reqBody = (request.body).toString();
        predicate.deepEquals = {};
        if (reqBody !== '') {
            var parseJson = require('parse-json');
            var jsonPath = require('jsonpath-plus');
            var jsonDoc = parseJson(reqBody);
            var savePath = value.jsonpath.selector;
            var title = jsonPath(savePath, jsonDoc);
            if (title.length > 1) {
                for (var i = 0; i < title.length; i += 1) {
                    predicate.deepEquals.body = title[i].toString();
                    predicate.jsonpath = value.jsonpath;
                }
                predicate = multiplePathValues(predicate, field, title);
                for (var j = 1; j < title.length; j += 1) {
                    predicates.push(predicate[j - 1]);
                }
            }
            else {
                predicate.deepEquals.body = title.toString();
                predicate.jsonpath = value.jsonpath;
            }
        }
        return predicates;
    }

    function buildEquals (request, matchers) {
        var result = {};
        Object.keys(matchers).forEach(function (key) {
            if (typeof request[key] === 'object') {
                result[key] = buildEquals(request[key], matchers[key]);
            }
            else {
                result[key] = request[key];
            }
        });
        return result;
    }

    function predicatesFor (request, matchers) {
        var predicates = [];

        matchers.forEach(function (matcher) {
            var basePredicate = {};

            // Add parameters
            Object.keys(matcher).forEach(function (key) {
                if (key !== 'matches') {
                    basePredicate[key] = matcher[key];
                }
            });

            Object.keys(matcher.matches).forEach(function (fieldName) {
                var helpers = require('../util/helpers'),
                    value = matcher.matches[fieldName],
                    predicate = helpers.clone(basePredicate);

                if (value === true) {
                    predicate.deepEquals = {};
                    predicate.deepEquals[fieldName] = request[fieldName];
                }
                else if ((fieldName === 'body') && (value !== true)) {
                    var fnMap = {
                        xpath: xpathValue,
                        jsonpath: jsonpathValue
                    };
                    Object.keys(value).forEach(function (field) {
                        fnMap[field](request, value, field, predicate, predicates);
                    });
                }
                else {
                    predicate.equals = {};
                    predicate.equals[fieldName] = buildEquals(request[fieldName], value);
                }

                predicates.push(predicate);
            });
        });

        return predicates;
    }

    function stubIndexFor (responseConfig, stubs) {
        for (var i = 0; i < stubs.length; i += 1) {
            var stub = stubs[i];
            if (stub.responses.indexOf(responseConfig) >= 0) {
                break;
            }
        }
        return i;
    }

    function indexOfStubToAddResponseTo (responseConfig, request, stubs) {
        var predicates = predicatesFor(request, responseConfig.proxy.predicateGenerators || []),
            stringify = require('json-stable-stringify');

        for (var index = stubIndexFor(responseConfig, stubs) + 1; index < stubs.length; index += 1) {
            if (stringify(predicates) === stringify(stubs[index].predicates)) {
                return index;
            }
        }
        return -1;
    }

    function canAddResponseToExistingStub (responseConfig, request, stubs) {
        return indexOfStubToAddResponseTo(responseConfig, request, stubs) >= 0;
    }

    function newIsResponse (response, addWaitBehavior, addDecorateBehavior) {
        var result = { is: response };
        var addBehaviors = {};

        if (addWaitBehavior && response._proxyResponseTime) { // eslint-disable-line no-underscore-dangle
            addBehaviors.wait = response._proxyResponseTime;  // eslint-disable-line no-underscore-dangle
        }
        if (addDecorateBehavior) {
            addBehaviors.decorate = addDecorateBehavior;
        }

        if (Object.keys(addBehaviors).length) {
            result._behaviors = addBehaviors;
        }
        return result;
    }

    function addNewResponse (responseConfig, request, response, stubs) {
        var stubResponse = newIsResponse(response, responseConfig.proxy.addWaitBehavior, responseConfig.proxy.addDecorateBehavior),
            responseIndex = indexOfStubToAddResponseTo(responseConfig, request, stubs);

        stubs[responseIndex].responses.push(stubResponse);
    }

    function addNewStub (responseConfig, request, response, stubs) {
        var predicates = predicatesFor(request, responseConfig.proxy.predicateGenerators || []),
            stubResponse = newIsResponse(response, responseConfig.proxy.addWaitBehavior, responseConfig.proxy.addDecorateBehavior),
            newStub = { predicates: predicates, responses: [stubResponse] },
            index = responseConfig.proxy.mode === 'proxyAlways' ? stubs.length : stubIndexFor(responseConfig, stubs);

        stubs.splice(index, 0, newStub);
    }

    function recordProxyResponse (responseConfig, request, response, stubs) {
        if (['proxyOnce', 'proxyAlways'].indexOf(responseConfig.proxy.mode) < 0) {
            responseConfig.proxy.mode = 'proxyOnce';
        }

        if (responseConfig.proxy.mode === 'proxyAlways' && canAddResponseToExistingStub(responseConfig, request, stubs)) {
            addNewResponse(responseConfig, request, response, stubs);
        }
        else {
            addNewStub(responseConfig, request, response, stubs);
        }
    }

    function addInjectedHeadersTo (request, headersToInject) {
        Object.keys(headersToInject || {}).forEach(function (key) {
            request.headers[key] = headersToInject[key];
        });
    }

    function proxyAndRecord (responseConfig, request, logger, stubs) {
        var Q = require('q'),
            behaviors = require('./behaviors');

        addInjectedHeadersTo(request, responseConfig.proxy.injectHeaders);

        return proxy.to(responseConfig.proxy.to, request, responseConfig.proxy).then(function (response) {
            // Run behaviors here to persist decorated response
            return Q(behaviors.execute(request, response, responseConfig._behaviors, logger));
        }).then(function (response) {
            recordProxyResponse(responseConfig, request, response, stubs);
            return Q(response);
        });
    }

    function processResponse (responseConfig, request, logger, stubs, imposterState) {
        var Q = require('q'),
            helpers = require('../util/helpers'),
            exceptions = require('../util/errors');

        if (responseConfig.is) {
            // Clone to prevent accidental state changes downstream
            return Q(helpers.clone(responseConfig.is));
        }
        else if (responseConfig.proxy) {
            return proxyAndRecord(responseConfig, request, logger, stubs);
        }
        else if (responseConfig.inject) {
            return inject(request, responseConfig.inject, logger, imposterState).then(Q);
        }
        else {
            return Q.reject(exceptions.ValidationError('unrecognized response type', { source: responseConfig }));
        }
    }

    function hasMultipleTypes (responseConfig) {
        return (responseConfig.is && responseConfig.proxy) ||
               (responseConfig.is && responseConfig.inject) ||
               (responseConfig.proxy && responseConfig.inject);
    }

    /**
     * Resolves a single response
     * @memberOf module:models/responseResolver#
     * @param {Object} responseConfig - The API-provided response configuration
     * @param {Object} request - The protocol-specific request object
     * @param {Object} logger - The logger
     * @param {Object} stubs - The stubs for the imposter
     * @param {Object} imposterState - The current state for the imposter
     * @returns {Object} - Promise resolving to the response
     */
    function resolve (responseConfig, request, logger, stubs, imposterState) {
        var Q = require('q'),
            exceptions = require('../util/errors'),
            helpers = require('../util/helpers'),
            behaviors = require('./behaviors');

        if (hasMultipleTypes(responseConfig)) {
            return Q.reject(exceptions.ValidationError('each response object must have only one response type',
                { source: responseConfig }));
        }

        return processResponse(responseConfig, helpers.clone(request), logger, stubs, imposterState).then(function (response) {
            // We may have already run the behaviors in the proxy call to persist the decorated response
            // in the new stub. If so, we need to ensure we don't re-run it
            if (responseConfig.proxy) {
                return Q(response);
            }
            else {
                return Q(behaviors.execute(request, response, responseConfig._behaviors, logger));
            }
        }).then(function (response) {
            return Q(postProcess(response, request));
        });
    }

    return {
        resolve: resolve
    };
}

module.exports = {
    create: create
};
<|endoftext|>


<commit_before>angular.module('starter.services')

	.constant('UPDATE_RESULT',
		/**
		 * @ngdoc constant
		 * @name UPDATE_RESULT
		 */
		{
			// TODO Custom Errors로 개선 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
			UPDATED: {
				type: "SUCCESS",
				id: "UPDATED"
			},
			ALREADY: {
				type: "SUCCESS",
				id: "ALREADY"
			},
			NETWORK_ERROR: {
				type: "FAILED",
				id: "NETWORK_ERROR"
			},
			UNKNOWN_ERROR: {
				type: "FAILED",
				id: "UNKNOWN_ERROR"
			}
		})

	.factory('AppUpdater',
		/**
		 * @ngdoc factory
		 * @name AppUpdater
		 * @param {$q} $q
		 * @param {$log} $log
		 * @param {LocalStorage} LocalStorage
		 * @param {RestService} RestService
		 * @param {CategoryUpdater} CategoryUpdater
		 * @param {PostUpdater} PostUpdater
		 * @param {NoticeUpdater} NoticeUpdater
		 * @param {IntroUpdater} IntroUpdater
		 * @param {SettingService} SettingService
		 * @param {UPDATE_RESULT} UPDATE_RESULT
		 */
		function ($q, $log, LocalStorage, RestService, CategoryUpdater, PostUpdater, NoticeUpdater, IntroUpdater, SettingService, UPDATE_RESULT) {
			var HOME_KEY = "HOME_VERSION";
			var POST_KEY = "POST_VERSION";

			var checkUpdate = function () {
				var homeVersion = LocalStorage.get(HOME_KEY);
				var postVersion = LocalStorage.get(POST_KEY);

				// TODO 홈 화면의 버전 확인
				return RestService.getVersion()
					.then(function (response) {
						var currPostVersion = new Date(response.data.content_version * 1000).toJSON();
						$log.debug("로컬 버전 : " + currPostVersion);
						$log.debug("서버 버전 : " + postVersion);

						if (_.isUndefined(postVersion) || currPostVersion != postVersion) {
							$log.info("업데이트가 필요합니다.");
							return currPostVersion;
						} else {
							$log.info("최신으로 업데이트되어 있습니다.");
							return false;
						}
					});
			};

			return {
				getLastUpdate: function () {
					var postVersion = LocalStorage.get(POST_KEY);

					if (_.isUndefined(postVersion)) {
						return undefined;
					} else {
						return new Date(postVersion);
					}
				},

				/**
				 * @returns {Promise}
				 */
				update: function () {
					return checkUpdate()
						.then(function (newestPostVersion) {
							if (newestPostVersion !== false) {
								$log.info("업데이트를 시작합니다.");

								return $q.all([
									// 홈 업데이트
									IntroUpdater.update(),
									// 카테고리 업데이트
									CategoryUpdater.update(),
									// 글 업데이트
									PostUpdater.updateAll(),
									// TODO 개별 update() 호출
									// 공지 업데이트
									NoticeUpdater.updateAll()
									// TODO 설정 확인
								]).then(function () {
									$log.info("업데이트가 완료되었습니다.");
									LocalStorage.set(POST_KEY, newestPostVersion);
									return UPDATE_RESULT.UPDATED;
								});
							}

							return UPDATE_RESULT.ALREADY;
						}).catch(function (err) {
							//TODO err 분석
							$log.warn("업데이트 중 에러가 발생했습니다.", err);
							return UPDATE_RESULT.NETWORK_ERROR;
						});
				}
			};
		});
<commit_msg>[#50] 홈 버전 업데이트 구현<commit_after>angular.module('starter.services')

	.constant('UPDATE_RESULT',
		/**
		 * @ngdoc constant
		 * @name UPDATE_RESULT
		 */
		{
			// TODO Custom Errors로 개선 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
			UPDATED: {
				type: "SUCCESS",
				id: "UPDATED"
			},
			ALREADY: {
				type: "SUCCESS",
				id: "ALREADY"
			},
			NETWORK_ERROR: {
				type: "FAILED",
				id: "NETWORK_ERROR"
			},
			UNKNOWN_ERROR: {
				type: "FAILED",
				id: "UNKNOWN_ERROR"
			}
		})

	.factory('AppUpdater',
		/**
		 * @ngdoc factory
		 * @name AppUpdater
		 * @param {$q} $q
		 * @param {$log} $log
		 * @param {LocalStorage} LocalStorage
		 * @param {RestService} RestService
		 * @param {CategoryUpdater} CategoryUpdater
		 * @param {PostUpdater} PostUpdater
		 * @param {NoticeUpdater} NoticeUpdater
		 * @param {IntroUpdater} IntroUpdater
		 * @param {SettingService} SettingService
		 * @param {UPDATE_RESULT} UPDATE_RESULT
		 */
		function ($q, $log, LocalStorage, RestService, CategoryUpdater, PostUpdater, NoticeUpdater, IntroUpdater, SettingService, UPDATE_RESULT) {
			var HOME_KEY = "HOME_VERSION";
			var POST_KEY = "POST_VERSION";

			return {
				getLastUpdate: function () {
					var postVersion = LocalStorage.get(POST_KEY);

					if (_.isUndefined(postVersion)) {
						return undefined;
					} else {
						return new Date(postVersion);
					}
				},

				/**
				 * @returns {Promise}
				 */
				update: function () {
					return RestService.getVersion()
						.then(function (response) {
							var homeVersion = LocalStorage.get(HOME_KEY);
							var postVersion = LocalStorage.get(POST_KEY);

							var currHomeVersion = new Date(response.data.home_version * 1000).toJSON();
							var currPostVersion = new Date(response.data.content_version * 1000).toJSON();

							$log.debug(`홈 버전 : 로컬(${currHomeVersion}), 서버(${homeVersion})`);
							$log.debug(`컨텐트 버전 : 로컬(${currPostVersion}), 서버(${postVersion})`);

							var updates = [];

							if (_.isUndefined(postVersion) || currPostVersion != postVersion) {
								updates.push(
									CategoryUpdater.update(),
									PostUpdater.updateAll(),
									NoticeUpdater.updateAll()
								);
							}

							if (_.isUndefined(homeVersion) || currHomeVersion != homeVersion) {
								updates.push(
									IntroUpdater.update()
								);
							}

							if (updates.length > 0) {
								$log.info("업데이트를 시작합니다.");

								return $q.all(updates).then(function () {
									$log.info("업데이트가 완료되었습니다.");
									LocalStorage.set(HOME_KEY, currHomeVersion);
									LocalStorage.set(POST_KEY, currPostVersion);
									return UPDATE_RESULT.UPDATED;
								});
							}

							$log.info("이미 최신입니다.");
							return UPDATE_RESULT.ALREADY;
						}).catch(function (err) {
							//TODO err 분석
							$log.warn("업데이트 중 에러가 발생했습니다.", err);
							return UPDATE_RESULT.NETWORK_ERROR;
						});
				}
			};
		});
<|endoftext|>


<commit_before>
$(function(){
    $(document).ready(function() {
        $('#all_question_categories').dataTable();
    } );

    $('#save_question_categories').button().click(function(){
        $('#frm_manage_question_categories').submit();
    });

    $('#frm_manage_question_categories').on('submit',function(event){
        var $form = $(this);
        $.ajax({
            type: $form.attr('method'),
            url: $form.attr('action'),
            data: $form.serialize(),

            success: function(data,status) {
                window.location.href = base_url + 'index.php/survey/question_categories';
            }
        });
        event.preventDefault();
    });

    $('#question_categories_popup_close').button().click(function(){
        $('#question_categories_id').val('');
        $('#question_categories_name').val('');
        $('#question_categories_description').val('');
    });

    $('button[edit_question_categories]').button().click(function(){
        var button_id = this.id;
        var button_id_array = button_id.split('-');
        var question_categories_id = button_id_array[1];
        $.ajax({
            url: base_url + 'index.php/survey/get_question_categories_by_id/'+question_categories_id,

            success: function(data,status) {
                if(data){
                    var msg = jQuery.parseJSON( data );
                    $('#question_categories_name').val(msg[0].name);
                    $('#question_categories_description').val(msg[0].description);
                    $('#question_categories_id').val(msg[0].id);

                    $('#update_question_categories').modal('show');
                }
                //window.location.href = base_url + 'index.php/survey/question_categories';
            }
        });

    });
    $('button[delete_question_categories]').button().click(function(){
        var button_id = this.id;
        var button_id_array = button_id.split('-');
        var question_categories_id = button_id_array[1];

        $.ajax({
            url: base_url + 'index.php/survey/get_question_categories_by_id/'+question_categories_id,

            success: function(data,status) {
                if(data){
                    var msg = jQuery.parseJSON( data );
                    $('#item_name').html(msg[0].name);

                    $( "#dialog-confirm" ).removeClass('hide').dialog({
                        resizable: false,
                        modal: true,
                        title: "

 Delete Department?

",
                        title_html: true,
                        buttons: [
                            {
                                html: "  Delete all items",
                                "class" : "btn btn-danger btn-xs",
                                click: function() {
                                    window.location.href = base_url + 'index.php/survey/delete_question_categories/'+question_categories_id;
                                }
                            }
                            ,
                            {
                                html: "  Cancel",
                                "class" : "btn btn-xs",
                                click: function() {
                                    $( this ).dialog( "close" );
                                }
                            }
                        ]
                    });
                }
                //window.location.href = base_url + 'index.php/survey/question_categories';
            }
        });

    });
});
<commit_msg>implement loader in question category page<commit_after>
$(function(){
    $(document).ready(function() {
        $('#all_question_categories').dataTable();
    } );

    $('#save_question_categories').button().click(function(){
        $('#update_question_categories').modal('hide');
        $body = $("body");
        $body.addClass("loading");
        $('#frm_manage_question_categories').submit();
    });

    $('#frm_manage_question_categories').on('submit',function(event){
        var $form = $(this);
        $.ajax({
            type: $form.attr('method'),
            url: $form.attr('action'),
            data: $form.serialize(),

            success: function(data,status) {
                window.location.href = base_url + 'index.php/survey/question_categories';
            }
        });
        event.preventDefault();
    });

    $('#question_categories_popup_close').button().click(function(){
        $('#question_categories_id').val('');
        $('#question_categories_name').val('');
        $('#question_categories_description').val('');
    });

    $('button[edit_question_categories]').button().click(function(){
        var button_id = this.id;
        var button_id_array = button_id.split('-');
        var question_categories_id = button_id_array[1];
        $.ajax({
            url: base_url + 'index.php/survey/get_question_categories_by_id/'+question_categories_id,

            success: function(data,status) {
                if(data){
                    var msg = jQuery.parseJSON( data );
                    $('#question_categories_name').val(msg[0].name);
                    $('#question_categories_description').val(msg[0].description);
                    $('#question_categories_id').val(msg[0].id);

                    $('#update_question_categories').modal('show');
                }
                //window.location.href = base_url + 'index.php/survey/question_categories';
            }
        });

    });
    $('button[delete_question_categories]').button().click(function(){
        var button_id = this.id;
        var button_id_array = button_id.split('-');
        var question_categories_id = button_id_array[1];

        $.ajax({
            url: base_url + 'index.php/survey/get_question_categories_by_id/'+question_categories_id,

            success: function(data,status) {
                if(data){
                    var msg = jQuery.parseJSON( data );
                    $('#item_name').html(msg[0].name);

                    $( "#dialog-confirm" ).removeClass('hide').dialog({
                        resizable: false,
                        modal: true,
                        title: "

 Delete question category?

",
                        title_html: true,
                        buttons: [
                            {
                                html: "  Delete selected items",
                                "class" : "btn btn-danger btn-xs",
                                click: function() {
                                    $( this ).dialog( "close" );
                                    $body = $("body");
                                    $body.addClass("loading");
                                    window.location.href = base_url + 'index.php/survey/delete_question_categories/'+question_categories_id;
                                }
                            }
                            ,
                            {
                                html: "  Cancel",
                                "class" : "btn btn-xs",
                                click: function() {
                                    $( this ).dialog( "close" );
                                }
                            }
                        ]
                    });
                }
                //window.location.href = base_url + 'index.php/survey/question_categories';
            }
        });

    });
});
<|endoftext|>


<commit_before>/**
 * Created by Jerome on 24-02-17.
 */

var GameServer = require('./GameServer.js').GameServer;
var randomInt = require('./GameServer.js').randomInt;
var GameObject = require('./GameObject.js').GameObject;
var Route = require('./Route.js').Route;

function MovingEntity(){ // Parent class of players and monsters
    this.inFight = false;
    this.targetID = null;
    this.alive = true;
    this.foes = [];
    this.lastFightUpdate = Date.now();
    this.lastDamage = Date.now();
    this.lastWalkUpdate = Date.now();
}

MovingEntity.prototype = Object.create(GameObject.prototype); // Declares the inheritance relationship
MovingEntity.prototype.constructor = MovingEntity;

MovingEntity.prototype.setRoute = function(path,departureTime,latency,action,orientation){
    this.route = new Route(this,path,departureTime,latency,action,orientation);
    this.updateAOIRoutes();
};

MovingEntity.prototype.updateAOIRoutes = function(){
    var AOIs = this.listAdjacentAOIs(true);
    var category = this.category;
    var id = this.id;
    var route = this.route;
    AOIs.forEach(function(aoi){
        GameServer.updateAOIroute(aoi,category,id,route.trim(category));
    });
};

MovingEntity.prototype.setTarget = function(target){
    this.target = target;
    if(target) this.setProperty('targetID',target.id); // only broadcast if non-null
};

MovingEntity.prototype.update = function(){
    if(this.inFight && (Date.now() - this.lastFightUpdate) >= GameServer.fightUpdateDelay) this.updateFight();
    if(this.route && (Date.now() - this.lastWalkUpdate) >= GameServer.walkUpdateDelay) this.updateWalk();
    if(this.constructor.name == 'Monster' && (Date.now() - this.lastPositionCheck) >= GameServer.positionCheckDelay) this.checkPosition();
};

MovingEntity.prototype.updateWalk = function(){
    // Based on the speed of the entity and the time elapsed since it started moving along a path,
    // compute on which tile of the path it should be at this time. If path ended, check what should happen.
    this.lastWalkUpdate = Date.now();
    var previousX = this.x;
    var previousY = this.y;
    var delta = Math.ceil(Math.abs(Date.now() - this.route.departureTime)/this.speed);
    var maxDelta = this.route.path.length-1;
    if(delta > maxDelta) delta = maxDelta;
    this.setAtDelta(delta);
    if(delta == maxDelta){
        if(this.constructor.name == 'Player') {
            GameServer.checkDoor(this);
            GameServer.checkItem(this);
            GameServer.checkAction(this);
            GameServer.checkSave(this);
            console.log(this.name+' moved to '+this.x+', '+this.y);
        }
        this.route = undefined;
    }
    if(this.x != previousX || this.y != previousY) {
        GameServer.moveAtLocation(this,previousX,previousY,this.x,this.y);
        if(this.constructor.name == 'Player') GameServer.checkMonster(this);
    }
};

MovingEntity.prototype.setAtDelta = function(delta){
    // Update the position of an entity by putting at the delta'th tile along it's path (see updateWalk())
    if(!this.route.path) return;
    this.x = this.route.path[delta].x; // no -1 because it's done in updateWalk() aready
    this.y = this.route.path[delta].y;
};

MovingEntity.prototype.startFight = function(target){
    if(!this.alive || !target.alive) return;
    if(!this.target) this.setTarget(target);
    this.addFoe(target);
    this.setProperty('inFight',true);
};

MovingEntity.prototype.damage = function(){
    if(!this.alive || !this.target || !this.target.alive) return;
    if ((Date.now() - this.lastDamage) < GameServer.damageDelay) return;
    this.lastDamage = Date.now();
    var damage = (this.atk * randomInt(5,10)) - (this.target.def*randomInt(1,3));
    damage = (damage <= 0 ? randomInt(1,3) : damage);
    this.target.lastHitter = this;
    var target = this.target;
    var difference = Math.abs(this.target.updateLife(-damage)); // Avoid sending negative numbers for binary protocol
    if(this.constructor.name == 'Player'){
        this.updatePacket.addHP(true,difference); // true = target
        if(!target.alive) GameServer.handleKill(this,target);
    }else if(this.constructor.name == 'Monster'){
        target.updatePacket.addHP(false,difference,this.id); // false = self
    }
};

MovingEntity.prototype.updateLife = function(incr){
    var tmp = this.life;
    this.life += incr;
    if(this.life <= 0) {
        this.life = 0;
        this.die();
    }else if(this.life > this.maxLife){
        this.life = this.maxLife;
    }
    var difference = this.life - tmp;
    if(this.constructor.name == 'Player') this.updatePacket.updateLife(this.life);
    return difference;
};

MovingEntity.prototype.die = function(){
    this.manageFoes();
    if(this.lastHitter) this.setProperty('lastHitter',this.lastHitter.id);
    this.endFight();
    this.setProperty('alive',false);
    if(this.constructor.name == 'Monster'){
        GameServer.respawnCount(this.startX, this.startY, this, this.respawn, GameServer.monsterRespawnDelay);
        setTimeout(GameServer.dropLoot,200,this.lootTable,this.x,this.y);
        if(this.chestArea) this.chestArea.decrement();
    }
};

MovingEntity.prototype.endFight = function(){
    this.setProperty('inFight',false);
    this.setTarget(null);
};

MovingEntity.prototype.manageFoes = function(){
    for(var i = 0; i < this.foes.length; i++){
        var foe = this.foes[i];
        foe.endFight();
        foe.removeFoe(this);
        foe.switchOpponent();
    }
    this.foes = [];
};

MovingEntity.prototype.hasFoe = function(foe) {
    return this.foes.indexOf(foe) > -1;
};

MovingEntity.prototype.addFoe = function(foe){
    var idx = this.foes.indexOf(foe);
    if(idx == -1) this.foes.push(foe);
};

MovingEntity.prototype.removeFoe = function(foe){
    var idx = this.foes.indexOf(foe);
    if (idx >= 0) this.foes.splice( idx, 1 );
};

MovingEntity.prototype.switchOpponent = function(){
    if(this.foes.length){
        setTimeout(function(_entity){
            GameServer.setUpFight(_entity,_entity.foes[0]);
        },300,this);
    }
};

module.exports.MovingEntity = MovingEntity;<commit_msg>Added comments<commit_after>/**
 * Created by Jerome on 24-02-17.
 */

var GameServer = require('./GameServer.js').GameServer;
var randomInt = require('./GameServer.js').randomInt;
var GameObject = require('./GameObject.js').GameObject;
var Route = require('./Route.js').Route;

function MovingEntity(){ // Parent class of players and monsters
    this.inFight = false;
    this.targetID = null;
    this.alive = true;
    this.foes = [];
    this.lastFightUpdate = Date.now();
    this.lastDamage = Date.now();
    this.lastWalkUpdate = Date.now();
}

MovingEntity.prototype = Object.create(GameObject.prototype); // Declares the inheritance relationship
MovingEntity.prototype.constructor = MovingEntity;

MovingEntity.prototype.setRoute = function(path,departureTime,latency,action,orientation){
    this.route = new Route(this,path,departureTime,latency,action,orientation);
    this.updateAOIRoutes();
};

MovingEntity.prototype.updateAOIRoutes = function(){
    var AOIs = this.listAdjacentAOIs(true);
    var category = this.category;
    var id = this.id;
    var route = this.route;
    AOIs.forEach(function(aoi){
        GameServer.updateAOIroute(aoi,category,id,route.trim(category));
    });
};

MovingEntity.prototype.setTarget = function(target){
    this.target = target;
    if(target) this.setProperty('targetID',target.id); // only broadcast if non-null
};

MovingEntity.prototype.update = function(){
    if(this.inFight && (Date.now() - this.lastFightUpdate) >= GameServer.fightUpdateDelay) this.updateFight();
    if(this.route && (Date.now() - this.lastWalkUpdate) >= GameServer.walkUpdateDelay) this.updateWalk();
    if(this.constructor.name == 'Monster' && (Date.now() - this.lastPositionCheck) >= GameServer.positionCheckDelay) this.checkPosition();
};

MovingEntity.prototype.updateWalk = function(){
    // Based on the speed of the entity and the time elapsed since it started moving along a path,
    // compute on which tile of the path it should be at this time. If path ended, check what should happen.
    this.lastWalkUpdate = Date.now();
    var previousX = this.x;
    var previousY = this.y;
    // this.speed is the amount of time need to travel a distance of 1 tile;
    // delta = the number of tiles traveled since departure
    var delta = Math.ceil(Math.abs(Date.now() - this.route.departureTime)/this.speed);
    var maxDelta = this.route.path.length-1;
    if(delta > maxDelta) delta = maxDelta;
    this.setAtDelta(delta);
    if(delta == maxDelta){
        if(this.constructor.name == 'Player') {
            GameServer.checkDoor(this);
            GameServer.checkItem(this);
            GameServer.checkAction(this);
            GameServer.checkSave(this);
            console.log(this.name+' moved to '+this.x+', '+this.y);
        }
        this.route = undefined;
    }
    if(this.x != previousX || this.y != previousY) {
        GameServer.moveAtLocation(this,previousX,previousY,this.x,this.y);
        if(this.constructor.name == 'Player') GameServer.checkMonster(this);
    }
};

MovingEntity.prototype.setAtDelta = function(delta){
    // Update the position of an entity by putting at the delta'th tile along it's path (see updateWalk())
    if(!this.route.path) return;
    this.x = this.route.path[delta].x; // no -1 because it's done in updateWalk() aready
    this.y = this.route.path[delta].y;
};

MovingEntity.prototype.startFight = function(target){
    if(!this.alive || !target.alive) return;
    if(!this.target) this.setTarget(target);
    this.addFoe(target);
    this.setProperty('inFight',true);
};

MovingEntity.prototype.damage = function(){
    if(!this.alive || !this.target || !this.target.alive) return;
    if ((Date.now() - this.lastDamage) < GameServer.damageDelay) return;
    this.lastDamage = Date.now();
    var damage = (this.atk * randomInt(5,10)) - (this.target.def*randomInt(1,3));
    damage = (damage <= 0 ? randomInt(1,3) : damage);
    this.target.lastHitter = this;
    var target = this.target;
    var difference = Math.abs(this.target.updateLife(-damage)); // Avoid sending negative numbers for binary protocol
    if(this.constructor.name == 'Player'){
        this.updatePacket.addHP(true,difference); // true = target
        if(!target.alive) GameServer.handleKill(this,target);
    }else if(this.constructor.name == 'Monster'){
        target.updatePacket.addHP(false,difference,this.id); // false = self
    }
};

MovingEntity.prototype.updateLife = function(incr){
    var tmp = this.life;
    this.life += incr;
    if(this.life <= 0) {
        this.life = 0;
        this.die();
    }else if(this.life > this.maxLife){
        this.life = this.maxLife;
    }
    var difference = this.life - tmp;
    if(this.constructor.name == 'Player') this.updatePacket.updateLife(this.life);
    return difference;
};

MovingEntity.prototype.die = function(){
    this.manageFoes();
    if(this.lastHitter) this.setProperty('lastHitter',this.lastHitter.id);
    this.endFight();
    this.setProperty('alive',false);
    if(this.constructor.name == 'Monster'){
        GameServer.respawnCount(this.startX, this.startY, this, this.respawn, GameServer.monsterRespawnDelay);
        setTimeout(GameServer.dropLoot,200,this.lootTable,this.x,this.y);
        if(this.chestArea) this.chestArea.decrement();
    }
};

MovingEntity.prototype.endFight = function(){
    this.setProperty('inFight',false);
    this.setTarget(null);
};

MovingEntity.prototype.manageFoes = function(){
    for(var i = 0; i < this.foes.length; i++){
        var foe = this.foes[i];
        foe.endFight();
        foe.removeFoe(this);
        foe.switchOpponent();
    }
    this.foes = [];
};

MovingEntity.prototype.hasFoe = function(foe) {
    return this.foes.indexOf(foe) > -1;
};

MovingEntity.prototype.addFoe = function(foe){
    var idx = this.foes.indexOf(foe);
    if(idx == -1) this.foes.push(foe);
};

MovingEntity.prototype.removeFoe = function(foe){
    var idx = this.foes.indexOf(foe);
    if (idx >= 0) this.foes.splice( idx, 1 );
};

MovingEntity.prototype.switchOpponent = function(){
    if(this.foes.length){
        setTimeout(function(_entity){
            GameServer.setUpFight(_entity,_entity.foes[0]);
        },300,this);
    }
};

module.exports.MovingEntity = MovingEntity;<|endoftext|>


<commit_before>'use strict';

formsAngular.provider('routingService', [ '$injector', '$locationProvider', function ($injector, $locationProvider) {

  var config = {
//  fixedRoutes: [] an array in the same format as builtInRoutes that is matched before the generic routes.  Can be omitted
    hashPrefix: '',
    html5Mode: false,
    routing: 'ngroute',    // What sort of routing do we want?  ngroute or uirouter
    prefix: ''        // How do we want to prefix out routes?  If not empty string then first character must be slash (which is added if not)
  };

  var builtInRoutes = [
    {route: '/analyse/:model/:reportSchemaName', state: 'analyse::model::report', templateUrl: 'partials/base-analysis.html'},
    {route: '/analyse/:model',                   state: 'analyse::model',         templateUrl: 'partials/base-analysis.html'},
    {route: '/:model/:id/edit',                  state: 'model::edit',            templateUrl: 'partials/base-edit.html'},
    {route: '/:model/new',                       state: 'model::new',             templateUrl: 'partials/base-edit.html'},
    {route: '/:model',                           state: 'model::list',            templateUrl: 'partials/base-list.html'},
    {route: '/:model/:form/:id/edit',            state: 'model::form::edit',      templateUrl: 'partials/base-edit.html'},       // non default form (different fields etc)
    {route: '/:model/:form/new',                 state: 'model::form::new',       templateUrl: 'partials/base-edit.html'},       // non default form (different fields etc)
    {route: '/:model/:form',                     state: 'model::form::list',      templateUrl: 'partials/base-list.html'}        // list page with links to non default form
  ];

  var _routeProvider, _stateProvider;
  var lastRoute = null,
    lastObject = {};

  function _setUpNgRoutes(routes) {
    angular.forEach(routes, function (routeSpec) {
      _routeProvider.when(config.prefix + routeSpec.route, routeSpec.options || {templateUrl: routeSpec.templateUrl});
    });
  }

  function _setUpUIRoutes(routes) {
    angular.forEach(routes, function (routeSpec) {
      _stateProvider.state(routeSpec.state, routeSpec.options || {
        url: routeSpec.route,
        templateUrl: routeSpec.templateUrl
      });
    });
  }

  function _buildUrl(path) {
    var url = config.html5Mode ? '' : '#';
    url += config.hashPrefix;
    url += config.prefix;
    if (url[0]) { url += '/'; }
    url += (path[0] === '/' ? path.slice(1) : path);
    return url;
  }

  function _buildOperationUrl(prefix, operation, modelName, formName, id) {
      var formString = formName ? ('/' + formName) : '';
      var modelString = prefix + '/' + modelName;
      var urlStr;
      switch (operation) {
          case 'list' :
              urlStr = modelString + formString;
              break;
          case 'edit' :
              urlStr = modelString + formString + '/' + id + '/edit';
              break;
          case 'new' :
              urlStr = modelString + formString + '/new';
              break;
      }
      return urlStr;
  }

  function _pathView(operation, scope, id) {
    var part1Url;
    if (typeof scope.viewName !== 'undefined') {
      part1Url = scope.viewName;
    } else {
      part1Url = scope.modelName;
    }
    return _buildOperationUrl(config.prefix, operation, part1Url, scope.formName, id);
  }

  return {
    start: function (options) {
      angular.extend(config, options);
      if (config.prefix[0] && config.prefix[0] !== '/') { config.prefix = '/' + config.prefix; }
      $locationProvider.html5Mode(config.html5Mode);
      if (config.hashPrefix !== '') {
        $locationProvider.hashPrefix(config.hashPrefix);
      }
      switch (config.routing) {
        case 'ngroute' :
          _routeProvider = $injector.get('$routeProvider');
          if (config.fixedRoutes) { _setUpNgRoutes(config.fixedRoutes); }
          _setUpNgRoutes(builtInRoutes);
          break;
        case 'uirouter' :
          _stateProvider = $injector.get('$stateProvider');
          if (config.fixedRoutes) { _setUpUIRoutes(config.fixedRoutes); }
          setTimeout(function () {
            _setUpUIRoutes(builtInRoutes);
          });
          break;
      }
    },
    $get: function () {
      return {
        router: function () {return config.routing; },
        prefix: function () {return config.prefix; },
        parsePathFunc: function () {
          return function (location) {
            if (location !== lastRoute) {
              lastRoute = location;

              lastObject = {newRecord: false};
              // Get rid of the prefix
              if (config.prefix.length > 0) {
                if (location.indexOf(config.prefix) === 0) {
                  location = location.slice(config.prefix.length);
                }
              }

              var locationSplit = location.split('/');
              var locationParts = locationSplit.length;
              if (locationSplit[1] === 'analyse') {
                lastObject.analyse = true;
                lastObject.modelName = locationSplit[2];
              } else {
                lastObject.modelName = locationSplit[1];
                var lastPart = locationSplit[locationParts - 1];
                if (lastPart === 'new') {
                  lastObject.newRecord = true;
                  locationParts--;
                } else if (lastPart === 'edit') {
                  locationParts = locationParts - 2;
                  lastObject.id = locationSplit[locationParts];
                }
                if (locationParts > 2) {
                  lastObject.formName = locationSplit[2];
                }
              }
            }
            return lastObject;
          };
///**
// * DominicBoettger wrote:
// *
// * Parser for the states provided by ui.router
// */
//'use strict';
//formsAngular.factory('$stateParse', [function () {
//
//  var lastObject = {};
//
//  return function (state) {
//    if (state.current && state.current.name) {
//      lastObject = {newRecord: false};
//      lastObject.modelName = state.params.model;
//      if (state.current.name === 'model::list') {
//        lastObject = {index: true};
//        lastObject.modelName = state.params.model;
//      } else if (state.current.name === 'model::edit') {
//        lastObject.id = state.params.id;
//      } else if (state.current.name === 'model::new') {
//        lastObject.newRecord = true;
//      } else if (state.current.name === 'model::analyse') {
//        lastObject.analyse = true;
//      }
//    }
//    return lastObject;
//  };
//}]);
        },
        buildUrl: _buildUrl,
        buildOperationUrl: function(operation, modelName, formName, id) {
            return _buildOperationUrl(config.prefix, operation, modelName, formName, id);
        },
        pathList: function(scope) {
          if (typeof scope.listPath === 'undefined') {
            return _pathView('list', scope);
          } else {
            return _buildUrl(scope.listPath);
          }
        },
        pathView: _pathView,
        redirectTo: function () {
          return function (operation, scope, location, id) {
//            switch (config.routing) {
//              case 'ngroute' :
                if (location.search()) {
                  location.url(location.path());
                }

              var urlStr = _buildOperationUrl(config.prefix, operation, scope.modelName, scope.formName, id);
              location.path(urlStr);

//                break;
//              case 'uirouter' :
//                var formString = scope.formName ? ('/' + scope.formName) : '';
//                var modelString = config.prefix + '/' + scope.modelName;
//                console.log('form schemas not supported with ui-router');
//                switch (operation) {
//                  case 'list' :
//                    location.path(modelString + formString);
//                    break;
//                  case 'edit' :
//                    location.path(modelString + formString + '/' + id + '/edit');
//                    break;
//                  case 'new' :
//                    location.path(modelString + formString + '/new');
//                    break;
//                }
//                switch (operation) {
//                  case 'list' :
//                    $state.go('model::list', { model: model });
//                    break;
//                  case 'edit' :
//                    location.path('/' + scope.modelName + formString + '/' + id + '/edit');
//                    break;
//                  case 'new' :
//                    location.path('/' + scope.modelName + formString + '/new');
//                    break;
//                }
//                break;
//
//
//                //  edit: $state.go('model::edit', {id: data._id, model: $scope.modelName });
//                //  new:  $state.go('model::new', {model: $scope.modelName});
//                break;
              };
        }
      };
    }
  };
}]);
<commit_msg>FIX url prefix FEATURE: add optional parent state<commit_after>'use strict';

formsAngular.provider('routingService', [ '$injector', '$locationProvider', function ($injector, $locationProvider) {

  var config = {
//  fixedRoutes: [] an array in the same format as builtInRoutes that is matched before the generic routes.  Can be omitted
    hashPrefix: '',
    html5Mode: false,
    routing: 'ngroute',    // What sort of routing do we want?  ngroute or uirouter
    prefix: '',        // How do we want to prefix out routes?  If not empty string then first character must be slash (which is added if not)
    parentState: null
  };

  var builtInRoutes = [
    {route: '/analyse/:model/:reportSchemaName', state: 'analyse::model::report', templateUrl: 'partials/base-analysis.html'},
    {route: '/analyse/:model',                   state: 'analyse::model',         templateUrl: 'partials/base-analysis.html'},
    {route: '/:model/:id/edit',                  state: 'model::edit',            templateUrl: 'partials/base-edit.html'},
    {route: '/:model/new',                       state: 'model::new',             templateUrl: 'partials/base-edit.html'},
    {route: '/:model',                           state: 'model::list',            templateUrl: 'partials/base-list.html'},
    {route: '/:model/:form/:id/edit',            state: 'model::form::edit',      templateUrl: 'partials/base-edit.html'},       // non default form (different fields etc)
    {route: '/:model/:form/new',                 state: 'model::form::new',       templateUrl: 'partials/base-edit.html'},       // non default form (different fields etc)
    {route: '/:model/:form',                     state: 'model::form::list',      templateUrl: 'partials/base-list.html'}        // list page with links to non default form
  ];

  var _routeProvider, _stateProvider;
  var lastRoute = null,
    lastObject = {};

  function _setUpNgRoutes(routes) {
    angular.forEach(routes, function (routeSpec) {
      _routeProvider.when(config.prefix + routeSpec.route, routeSpec.options || {templateUrl: routeSpec.templateUrl});
    });
  }
    function _setUpUIRoutes(routes) {
        angular.forEach(routes, function (routeSpec) {
            var options = routeSpec.options || {
                url: config.prefix + routeSpec.route,
                templateUrl: routeSpec.templateUrl
            };

            if (config.parentState) {
                options.parent = config.parentState;
            }

            _stateProvider.state(routeSpec.state, options);
        });
    }

  function _buildUrl(path) {
    var url = config.html5Mode ? '' : '#';
    url += config.hashPrefix;
    url += config.prefix;
    if (url[0]) { url += '/'; }
    url += (path[0] === '/' ? path.slice(1) : path);
    return url;
  }

  function _buildOperationUrl(prefix, operation, modelName, formName, id) {
      var formString = formName ? ('/' + formName) : '';
      var modelString = prefix + '/' + modelName;
      var urlStr;
      switch (operation) {
          case 'list' :
              urlStr = modelString + formString;
              break;
          case 'edit' :
              urlStr = modelString + formString + '/' + id + '/edit';
              break;
          case 'new' :
              urlStr = modelString + formString + '/new';
              break;
      }
      return urlStr;
  }

  function _pathView(operation, scope, id) {
    var part1Url;
    if (typeof scope.viewName !== 'undefined') {
      part1Url = scope.viewName;
    } else {
      part1Url = scope.modelName;
    }
    return _buildOperationUrl(config.prefix, operation, part1Url, scope.formName, id);
  }

  return {
    start: function (options) {
      angular.extend(config, options);
      if (config.prefix[0] && config.prefix[0] !== '/') { config.prefix = '/' + config.prefix; }
      $locationProvider.html5Mode(config.html5Mode);
      if (config.hashPrefix !== '') {
        $locationProvider.hashPrefix(config.hashPrefix);
      }
      switch (config.routing) {
        case 'ngroute' :
          _routeProvider = $injector.get('$routeProvider');
          if (config.fixedRoutes) { _setUpNgRoutes(config.fixedRoutes); }
          _setUpNgRoutes(builtInRoutes);
          break;
        case 'uirouter' :
          _stateProvider = $injector.get('$stateProvider');
          if (config.fixedRoutes) { _setUpUIRoutes(config.fixedRoutes); }
          setTimeout(function () {
            _setUpUIRoutes(builtInRoutes);
          });
          break;
      }
    },
    $get: function () {
      return {
        router: function () {return config.routing; },
        prefix: function () {return config.prefix; },
        parsePathFunc: function () {
          return function (location) {
            if (location !== lastRoute) {
              lastRoute = location;

              lastObject = {newRecord: false};
              // Get rid of the prefix
              if (config.prefix.length > 0) {
                if (location.indexOf(config.prefix) === 0) {
                  location = location.slice(config.prefix.length);
                }
              }

              var locationSplit = location.split('/');
              var locationParts = locationSplit.length;
              if (locationSplit[1] === 'analyse') {
                lastObject.analyse = true;
                lastObject.modelName = locationSplit[2];
              } else {
                lastObject.modelName = locationSplit[1];
                var lastPart = locationSplit[locationParts - 1];
                if (lastPart === 'new') {
                  lastObject.newRecord = true;
                  locationParts--;
                } else if (lastPart === 'edit') {
                  locationParts = locationParts - 2;
                  lastObject.id = locationSplit[locationParts];
                }
                if (locationParts > 2) {
                  lastObject.formName = locationSplit[2];
                }
              }
            }
            return lastObject;
          };
///**
// * DominicBoettger wrote:
// *
// * Parser for the states provided by ui.router
// */
//'use strict';
//formsAngular.factory('$stateParse', [function () {
//
//  var lastObject = {};
//
//  return function (state) {
//    if (state.current && state.current.name) {
//      lastObject = {newRecord: false};
//      lastObject.modelName = state.params.model;
//      if (state.current.name === 'model::list') {
//        lastObject = {index: true};
//        lastObject.modelName = state.params.model;
//      } else if (state.current.name === 'model::edit') {
//        lastObject.id = state.params.id;
//      } else if (state.current.name === 'model::new') {
//        lastObject.newRecord = true;
//      } else if (state.current.name === 'model::analyse') {
//        lastObject.analyse = true;
//      }
//    }
//    return lastObject;
//  };
//}]);
        },
        buildUrl: _buildUrl,
        buildOperationUrl: function(operation, modelName, formName, id) {
            return _buildOperationUrl(config.prefix, operation, modelName, formName, id);
        },
        pathList: function(scope) {
          if (typeof scope.listPath === 'undefined') {
            return _pathView('list', scope);
          } else {
            return _buildUrl(scope.listPath);
          }
        },
        pathView: _pathView,
        redirectTo: function () {
          return function (operation, scope, location, id) {
//            switch (config.routing) {
//              case 'ngroute' :
                if (location.search()) {
                  location.url(location.path());
                }

              var urlStr = _buildOperationUrl(config.prefix, operation, scope.modelName, scope.formName, id);
              location.path(urlStr);

//                break;
//              case 'uirouter' :
//                var formString = scope.formName ? ('/' + scope.formName) : '';
//                var modelString = config.prefix + '/' + scope.modelName;
//                console.log('form schemas not supported with ui-router');
//                switch (operation) {
//                  case 'list' :
//                    location.path(modelString + formString);
//                    break;
//                  case 'edit' :
//                    location.path(modelString + formString + '/' + id + '/edit');
//                    break;
//                  case 'new' :
//                    location.path(modelString + formString + '/new');
//                    break;
//                }
//                switch (operation) {
//                  case 'list' :
//                    $state.go('model::list', { model: model });
//                    break;
//                  case 'edit' :
//                    location.path('/' + scope.modelName + formString + '/' + id + '/edit');
//                    break;
//                  case 'new' :
//                    location.path('/' + scope.modelName + formString + '/new');
//                    break;
//                }
//                break;
//
//
//                //  edit: $state.go('model::edit', {id: data._id, model: $scope.modelName });
//                //  new:  $state.go('model::new', {model: $scope.modelName});
//                break;
              };
        }
      };
    }
  };
}]);
<|endoftext|>


<commit_before>/* eslint-disable */

const args = require('minimist')(process.argv.slice(2));
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const semver = require('semver');
const { prompt } = require('enquirer');
const execa = require('execa');
const pkg = require('../package.json');

const currentVersion = pkg.version;
const preId =
  args.preid ||
  (semver.prerelease(currentVersion) && semver.prerelease(currentVersion)[0]);
const isDryRun = args.dry;
const skipTests = args.skipTests;
const skipBuild = args.skipBuild;

const pkgPath = path.resolve(__dirname, '../package.json');
const versionIncrements = [
  'patch',
  'minor',
  'major',
  ...(preId ? ['prepatch', 'preminor', 'premajor', 'prerelease'] : []),
];

const inc = (i) => semver.inc(currentVersion, i, preId);
const run = (bin, args, opts = {}) =>
  execa(bin, args, { stdio: 'inherit', ...opts });
const dryRun = (bin, args, opts = {}) =>
  console.log(chalk.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts);
const runIfNotDry = isDryRun ? dryRun : run;
const step = (msg) => console.log(chalk.cyan(msg));

async function main() {
  let targetVersion = args._[0];

  if (!targetVersion) {
    // no explicit version, offer suggestions
    const { release } = await prompt({
      type: 'select',
      name: 'release',
      message: 'Select release type',
      choices: versionIncrements
        .map((i) => `${i} (${inc(i)})`)
        .concat(['custom']),
    });

    if (release === 'custom') {
      targetVersion = (
        await prompt({
          type: 'input',
          name: 'version',
          message: 'Input custom version',
          initial: currentVersion,
        })
      ).version;
    } else {
      targetVersion = release.match(/\((.*)\)/)[1];
    }
  }

  if (!semver.valid(targetVersion)) {
    throw new Error(`invalid target version: ${targetVersion}`);
  }

  const { yes } = await prompt({
    type: 'confirm',
    name: 'yes',
    message: `Releasing v${targetVersion}. Confirm?`,
  });

  if (!yes) {
    return;
  }

  // update all package versions and inter-dependencies
  step('\nUpdating cross dependencies...');
  if (!isDryRun) {
    pkg.version = targetVersion;
    fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
  } else {
    console.log(`(skipped)`);
  }

  // run tests before release
  step('\nRunning tests...');
  if (!skipTests && !isDryRun) {
    await run('npm', ['test']);
  } else {
    console.log(`(skipped)`);
  }

  // build package
  step('\nBuilding package...');
  if (!skipBuild && !isDryRun) {
    await run('npm', ['build', '--release']);
  } else {
    console.log(`(skipped)`);
  }

  // generate changelog
  await run(`npm`, ['run', 'changelog']);

  const { stdout } = await run('git', ['diff'], { stdio: 'pipe' });
  if (stdout) {
    step('\nCommitting changes...');
    await runIfNotDry('git', ['add', '-A']);
    await runIfNotDry('git', ['commit', '-m', `release: v${targetVersion}`]);
  } else {
    console.log('No changes to commit.');
  }

  // push to GitHub
  step('\nPushing to GitHub...');
  await runIfNotDry('git', ['tag', `v${targetVersion}`]);
  await runIfNotDry('git', ['push', 'origin', `refs/tags/v${targetVersion}`]);
  await runIfNotDry('git', ['push']);

  if (isDryRun) {
    console.log(`\nDry run finished - run git diff to see package changes.`);
  }

  console.log();
}

main().catch((err) => {
  console.error(err);
});
<commit_msg>workflow: fix build command<commit_after>/* eslint-disable */

const args = require('minimist')(process.argv.slice(2));
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const semver = require('semver');
const { prompt } = require('enquirer');
const execa = require('execa');
const pkg = require('../package.json');

const currentVersion = pkg.version;
const preId =
  args.preid ||
  (semver.prerelease(currentVersion) && semver.prerelease(currentVersion)[0]);
const isDryRun = args.dry;
const skipTests = args.skipTests;
const skipBuild = args.skipBuild;

const pkgPath = path.resolve(__dirname, '../package.json');
const versionIncrements = [
  'patch',
  'minor',
  'major',
  ...(preId ? ['prepatch', 'preminor', 'premajor', 'prerelease'] : []),
];

const inc = (i) => semver.inc(currentVersion, i, preId);
const run = (bin, args, opts = {}) =>
  execa(bin, args, { stdio: 'inherit', ...opts });
const dryRun = (bin, args, opts = {}) =>
  console.log(chalk.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts);
const runIfNotDry = isDryRun ? dryRun : run;
const step = (msg) => console.log(chalk.cyan(msg));

async function main() {
  let targetVersion = args._[0];

  if (!targetVersion) {
    // no explicit version, offer suggestions
    const { release } = await prompt({
      type: 'select',
      name: 'release',
      message: 'Select release type',
      choices: versionIncrements
        .map((i) => `${i} (${inc(i)})`)
        .concat(['custom']),
    });

    if (release === 'custom') {
      targetVersion = (
        await prompt({
          type: 'input',
          name: 'version',
          message: 'Input custom version',
          initial: currentVersion,
        })
      ).version;
    } else {
      targetVersion = release.match(/\((.*)\)/)[1];
    }
  }

  if (!semver.valid(targetVersion)) {
    throw new Error(`invalid target version: ${targetVersion}`);
  }

  const { yes } = await prompt({
    type: 'confirm',
    name: 'yes',
    message: `Releasing v${targetVersion}. Confirm?`,
  });

  if (!yes) {
    return;
  }

  // update all package versions and inter-dependencies
  step('\nUpdating cross dependencies...');
  if (!isDryRun) {
    pkg.version = targetVersion;
    fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
  } else {
    console.log(`(skipped)`);
  }

  // run tests before release
  step('\nRunning tests...');
  if (!skipTests && !isDryRun) {
    await run('npm', ['test']);
  } else {
    console.log(`(skipped)`);
  }

  // build package
  step('\nBuilding package...');
  if (!skipBuild && !isDryRun) {
    await run('npm', ['run', 'build']);
  } else {
    console.log(`(skipped)`);
  }

  // generate changelog
  await run(`npm`, ['run', 'changelog']);

  const { stdout } = await run('git', ['diff'], { stdio: 'pipe' });
  if (stdout) {
    step('\nCommitting changes...');
    await runIfNotDry('git', ['add', '-A']);
    await runIfNotDry('git', ['commit', '-m', `release: v${targetVersion}`]);
  } else {
    console.log('No changes to commit.');
  }

  // push to GitHub
  step('\nPushing to GitHub...');
  await runIfNotDry('git', ['tag', `v${targetVersion}`]);
  await runIfNotDry('git', ['push', 'origin', `refs/tags/v${targetVersion}`]);
  await runIfNotDry('git', ['push']);

  if (isDryRun) {
    console.log(`\nDry run finished - run git diff to see package changes.`);
  }

  console.log();
}

main().catch((err) => {
  console.error(err);
});
<|endoftext|>


<commit_before>angular.module('enki.user',[])

.controller('userController', function ($scope, $window, $location, User, $state, UserResources) {
  // console.log("ITEM: ", $window.localStorage.getItem('com.fickle'));
  $scope.likedResources = [];
  $scope.dislikedResources = [];
  var user = JSON.parse(window.localStorage.getItem('com.fickle'));
  var username = user.username;

  User.getUser($window.localStorage.getItem('com.fickle'))
  .then(function (user) {
  });

	User.getLikes($window.localStorage.getItem('com.fickle')).then(function(data) {
	 $scope.likedResources = data;
   console.log("LIKES: ", data);
	});

  User.getDislike($window.localStorage.getItem('com.fickle')).then(function(data){
    $scope.dislikedResources = data;
  });

  $scope.logout = function() {
    window.localStorage.setItem('com.fickle', null);
    $state.go('login');
  };

  $scope.onItemDelete = function(resource) {
    console.log("Attempted to Delete");
    var userpref = {
      'username' : username,
      'episodeTitle' : resource[0].title,
      'showName' : resource[1].name
    };
    console.log(userpref);
    UserResources.removeRelationship(userpref)
    .then(function(message){
      console.log("Response Message: ",message);
      if(message === 200){
        alert("You have removed this like/dislke");
      }
    })
    .catch(function (error) {
      console.error(error);
    });
    $scope.likedResources.splice($scope.likedResources.indexOf(resource), 1);
  };
});
<commit_msg>changed the alert to console<commit_after>angular.module('enki.user',[])

.controller('userController', function ($scope, $window, $location, User, $state, UserResources) {
  // console.log("ITEM: ", $window.localStorage.getItem('com.fickle'));
  $scope.likedResources = [];
  $scope.dislikedResources = [];
  var user = JSON.parse(window.localStorage.getItem('com.fickle'));
  var username = user.username;

  User.getUser($window.localStorage.getItem('com.fickle'))
  .then(function (user) {
  });

	User.getLikes($window.localStorage.getItem('com.fickle')).then(function(data) {
	 $scope.likedResources = data;
   console.log("LIKES: ", data);
	});

  User.getDislike($window.localStorage.getItem('com.fickle')).then(function(data){
    $scope.dislikedResources = data;
  });

  $scope.logout = function() {
    window.localStorage.setItem('com.fickle', null);
    $state.go('login');
  };

  $scope.onItemDelete = function(resource) {
    console.log("Attempted to Delete");
    var userpref = {
      'username' : username,
      'episodeTitle' : resource[0].title,
      'showName' : resource[1].name
    };
    console.log(userpref);
    UserResources.removeRelationship(userpref)
    .then(function(message){
      console.log("Response Message: ",message);
      if(message === 200){
        console.log("You have removed this like/dislke");
      }
    })
    .catch(function (error) {
      console.error(error);
    });
    $scope.likedResources.splice($scope.likedResources.indexOf(resource), 1);
  };
});
<|endoftext|>


<commit_before>app.title = '题目列表';
app.links = [];

component.data = function () {
    return {
        tags: [
            {
                text: '按解法',
                data: [
                    { text: '搜索', data: ['暴力', '二分法', 'DFS', 'BFS', '双向BFS', '剪枝'] },
                    { text: '动态规划', data: ['线性', '树形', '背包问题'] }
                ]
            },
            { text: '按年份', data: ['2017', '2016', '2015', '2014'] }
        ],
        selected: [],
        paging: {
            current: 1,
            count: 0
        },
        request: {
            tag: null,
            title: null,
            page: 1
        },
        result: []
    };
}

component.watch = {
    selected: function (value) {
        console.log(value);
        value = value.filter(x => !value.some(y => x != y && y.indexOf(x) >= 0));
        this.request.tag = value.join(', ');
    },
    request: {
        handler: function (value) {
            console.log(value);
            var self = this;
            qv.createView('/api/problem/all', this.request).fetch(x => {
                self.paging.count = x.data.count;
                self.paging.current = x.data.current;
                self.result = x.data.result;
            });
        },
        deep: true
    }
};

component.methods = {
    triggerTag: function (tag) {
        if (this.selected.some(x => x == tag)) {
            var subs = this.selected.filter(x => x.indexOf(tag) >= 0);
            for (var i = 0; i < subs.length; i++) {
                this.selected.remove(subs[i]);
            }
        }
        else {
            this.selected.push(tag);
            if (tag.indexOf(':') >= 0 && tag.lastIndexOf(':') >= 0 && tag.indexOf(':') != tag.lastIndexOf(':')) {
                var parent = tag.substr(0, tag.lastIndexOf(':'));
                if (!this.selected.some(x => x == parent)) {
                    this.selected.push(parent);
                }
            }
        }
    },
    setSearchTitle: function () {
        this.request.title = $('#txtSearchProblemTitle').val();
    },
    toPage: function (p) {
        this.paging.current = p;
        this.request.page = p;
    }
};

component.created = function () {
    qv.createView('/api/problem/all', this.request).fetch(x => {
        this.paging.count = x.data.count;
        this.paging.current = x.data.current;
        this.result = x.data.result;
    });
};
<commit_msg>Move tags into configuration table<commit_after>app.title = '题目列表';
app.links = [];

component.data = function () {
    return {
        tags: [],
        selected: [],
        paging: {
            current: 1,
            count: 0
        },
        request: {
            tag: null,
            title: null,
            page: 1
        },
        result: []
    };
}

component.watch = {
    selected: function (value) {
        console.log(value);
        value = value.filter(x => !value.some(y => x != y && y.indexOf(x) >= 0));
        this.request.tag = value.join(', ');
    },
    request: {
        handler: function (value) {
            console.log(value);
            var self = this;
            qv.createView('/api/problem/all', this.request).fetch(x => {
                self.paging.count = x.data.count;
                self.paging.current = x.data.current;
                self.result = x.data.result;
            });
        },
        deep: true
    }
};

component.methods = {
    triggerTag: function (tag) {
        if (this.selected.some(x => x == tag)) {
            var subs = this.selected.filter(x => x.indexOf(tag) >= 0);
            for (var i = 0; i < subs.length; i++) {
                this.selected.remove(subs[i]);
            }
        }
        else {
            this.selected.push(tag);
            if (tag.indexOf(':') >= 0 && tag.lastIndexOf(':') >= 0 && tag.indexOf(':') != tag.lastIndexOf(':')) {
                var parent = tag.substr(0, tag.lastIndexOf(':'));
                if (!this.selected.some(x => x == parent)) {
                    this.selected.push(parent);
                }
            }
        }
    },
    setSearchTitle: function () {
        this.request.title = $('#txtSearchProblemTitle').val();
    },
    toPage: function (p) {
        this.paging.current = p;
        this.request.page = p;
    }
};

component.created = function () {
    qv.createView('/api/problem/all', this.request).fetch(x => {
        this.paging.count = x.data.count;
        this.paging.current = x.data.current;
        this.result = x.data.result;
    });

    qv.createView('/api/configuration/problemtags').fetch(x => {
        this.tags = JSON.parse(x.data.value);
    });
};
<|endoftext|>


<commit_before>

var tapemerge = function ( compare, a, i, j, b, k, l, c, m ) {

	var n;

	n = m + j - i + l - k;

	for (; m < n; ++m) {
		if ( k >= l || ( i < j && compare( a[i], b[k] ) <= 0 ) ) {
			c[m] = a[i]; ++i;
		}
		else {
			c[m] = b[k]; ++k;
		}
	}

};

exports.tapemerge = tapemerge;
<commit_msg>better variable names for tapemerge<commit_after>

var tapemerge = function ( compare , a , ai , aj , b , bi , bj , c , ci ) {

	var cj ;

	cj = ci + aj - ai + bj - bi ;

	for ( ; ci < cj ; ++ci ) {

		if ( bi >= bj || ( ai < aj && compare( a[ai] , b[bi] ) <= 0 ) ) {

			c[ci] = a[ai] ;
			++ai ;

		}

		else {

			c[ci] = b[bi] ;
			++bi ;

		}
	}

};

exports.tapemerge = tapemerge;
<|endoftext|>