<commit_before>'use strict';

/* Services */

<%= angularAppName %>.factory('Register', ['$resource',
    function ($resource) {
        return $resource('app/rest/register', {}, {
        });
    }]);

<%= angularAppName %>.factory('Activate', ['$resource',
    function ($resource) {
        return $resource('app/rest/activate', {}, {
            'get': { method: 'GET', params: {}, isArray: false}
        });
    }]);

<%= angularAppName %>.factory('Account', ['$resource',
    function ($resource) {
        return $resource('app/rest/account', {}, {
        });
    }]);

<%= angularAppName %>.factory('Password', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/change_password', {}, {
        });
    }]);

<%= angularAppName %>.factory('Sessions', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/sessions/:series', {}, {
            'get': { method: 'GET', isArray: true}
        });
    }]);

<%= angularAppName %>.factory('MetricsService', ['$resource',
    function ($resource) {
        return $resource('metrics/metrics', {}, {
            'get': { method: 'GET'}
        });
    }]);

<%= angularAppName %>.factory('ThreadDumpService', ['$http',
    function ($http) {
        return {
            dump: function() {
                var promise = $http.get('dump').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

<%= angularAppName %>.factory('HealthCheckService', ['$rootScope', '$http',
    function ($rootScope, $http) {
        return {
            check: function() {
                var promise = $http.get('health').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

<%= angularAppName %>.factory('LogsService', ['$resource',
    function ($resource) {
        return $resource('app/rest/logs', {}, {
            'findAll': { method: 'GET', isArray: true},
            'changeLevel':  { method: 'PUT'}
        });
    }]);

<%= angularAppName %>.factory('AuditsService', ['$http',
    function ($http) {
        return {
            findAll: function() {
                var promise = $http.get('app/rest/audits/all').then(function (response) {
                    return response.data;
                });
                return promise;
            },
            findByDates: function(fromDate, toDate) {
                var promise = $http.get('app/rest/audits/byDates', {params: {fromDate: fromDate, toDate: toDate}}).then(function (response) {
                    return response.data;
                });
                return promise;
            }
        }
    }]);

<%= angularAppName %>.factory('Session', [
    function () {
        this.create = function (login, firstName, lastName, email, userRoles) {
            this.login = login;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
            this.userRoles = userRoles;
        };
        this.invalidate = function () {
            this.login = null;
            this.firstName = null;
            this.lastName = null;
            this.email = null;
            this.userRoles = null;
        };
        return this;
    }]);

<%= angularAppName %>.constant('USER_ROLES', {
        all: '*',
        admin: 'ROLE_ADMIN',
        user: 'ROLE_USER'
    });

<%= angularAppName %>.factory('AuthenticationSharedService', ['$rootScope', '$http', 'authService', 'Session', 'Account',<% if (authenticationType == 'token') { %> 'Base64Service', 'AccessToken', <% } %>
    function ($rootScope, $http, authService, Session, Account<% if (authenticationType == 'token') { %>, Base64Service, AccessToken<% } %>) {
        return {
            login: function (param) {<% if (authenticationType == 'cookie') { %>
                var data ="j_username=" + param.username +"&j_password=" + param.password +"&_spring_security_remember_me=" + param.rememberMe +"&submit=Login";
                $http.post('app/authentication', data, {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded"
                    },
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    Account.get(function(data) {
                        Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                        $rootScope.account = Session;
                        authService.loginConfirmed(data);
                    });
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticationError = true;
                    Session.invalidate();
                });<% } %><% if (authenticationType == 'token') { %>
                var data = "username=" + param.username + "&password=" + param.password + "&grant_type=password&scope=read%20write&client_secret=mySecretOAuthSecret&client_id=<%= baseName%>";
                $http.post('oauth/token', data, {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded",
                        "Accept": "application/json",
                        "Authorization": "Basic " + Base64Service.encode("jhipsterapp" + ':' + "mySecretOAuthSecret")
                    },
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    httpHeaders.common['Authorization'] = 'Bearer ' + data.access_token;
                    AccessToken.set(data);

                    Account.get(function(data) {
                        Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                        $rootScope.account = Session;
                        authService.loginConfirmed(data);
                    });
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticationError = true;
                    Session.invalidate();
                });<% } %>
            },
            valid: function (authorizedRoles) {<% if (authenticationType == 'token') { %>
                httpHeaders.common['Authorization'] = 'Bearer ' + AccessToken.get();<% } %>

                $http.get('protected/transparent.gif', {
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    if (!Session.login<% if (authenticationType == 'token') { %> || AccessToken.get() != undefined<% } %>) {<% if (authenticationType == 'token') { %>
                        if (AccessToken.get() == undefined || AccessToken.expired()) {
                            $rootScope.authenticated = false
                            return;
                        }<% } %>
                        Account.get(function(data) {
                            Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                            $rootScope.account = Session;

                            if (!$rootScope.isAuthorized(authorizedRoles)) {
                                event.preventDefault();
                                // user is not allowed
                                $rootScope.$broadcast("event:auth-notAuthorized");
                            }

                            $rootScope.authenticated = true;
                        });
                    }
                    $rootScope.authenticated = !!Session.login;
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticated = false;
                });
            },
            isAuthorized: function (authorizedRoles) {
                if (!angular.isArray(authorizedRoles)) {
                    if (authorizedRoles == '*') {
                        return true;
                    }

                    authorizedRoles = [authorizedRoles];
                }

                var isAuthorized = false;
                angular.forEach(authorizedRoles, function(authorizedRole) {
                    var authorized = (!!Session.login &&
                        Session.userRoles.indexOf(authorizedRole) !== -1);

                    if (authorized || authorizedRole == '*') {
                        isAuthorized = true;
                    }
                });

                return isAuthorized;
            },
            logout: function () {
                $rootScope.authenticationError = false;
                $rootScope.authenticated = false;
                $rootScope.account = null;<% if (authenticationType == 'token') { %>
                AccessToken.remove();<% } %>

                $http.get('app/logout');
                Session.invalidate();<% if (authenticationType == 'token') { %>
                httpHeaders.common['Authorization'] = null;<% } %>
                authService.loginCancelled();
            }
        };
    }]);
<commit_msg>Bug fix #341<commit_after>'use strict';

/* Services */

<%= angularAppName %>.factory('Register', ['$resource',
    function ($resource) {
        return $resource('app/rest/register', {}, {
        });
    }]);

<%= angularAppName %>.factory('Activate', ['$resource',
    function ($resource) {
        return $resource('app/rest/activate', {}, {
            'get': { method: 'GET', params: {}, isArray: false}
        });
    }]);

<%= angularAppName %>.factory('Account', ['$resource',
    function ($resource) {
        return $resource('app/rest/account', {}, {
        });
    }]);

<%= angularAppName %>.factory('Password', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/change_password', {}, {
        });
    }]);

<%= angularAppName %>.factory('Sessions', ['$resource',
    function ($resource) {
        return $resource('app/rest/account/sessions/:series', {}, {
            'get': { method: 'GET', isArray: true}
        });
    }]);

<%= angularAppName %>.factory('MetricsService', ['$resource',
    function ($resource) {
        return $resource('metrics/metrics', {}, {
            'get': { method: 'GET'}
        });
    }]);

<%= angularAppName %>.factory('ThreadDumpService', ['$http',
    function ($http) {
        return {
            dump: function() {
                var promise = $http.get('dump').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

<%= angularAppName %>.factory('HealthCheckService', ['$rootScope', '$http',
    function ($rootScope, $http) {
        return {
            check: function() {
                var promise = $http.get('health').then(function(response){
                    return response.data;
                });
                return promise;
            }
        };
    }]);

<%= angularAppName %>.factory('LogsService', ['$resource',
    function ($resource) {
        return $resource('app/rest/logs', {}, {
            'findAll': { method: 'GET', isArray: true},
            'changeLevel':  { method: 'PUT'}
        });
    }]);

<%= angularAppName %>.factory('AuditsService', ['$http',
    function ($http) {
        return {
            findAll: function() {
                var promise = $http.get('app/rest/audits/all').then(function (response) {
                    return response.data;
                });
                return promise;
            },
            findByDates: function(fromDate, toDate) {
                var promise = $http.get('app/rest/audits/byDates', {params: {fromDate: fromDate, toDate: toDate}}).then(function (response) {
                    return response.data;
                });
                return promise;
            }
        }
    }]);

<%= angularAppName %>.factory('Session', [
    function () {
        this.create = function (login, firstName, lastName, email, userRoles) {
            this.login = login;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
            this.userRoles = userRoles;
        };
        this.invalidate = function () {
            this.login = null;
            this.firstName = null;
            this.lastName = null;
            this.email = null;
            this.userRoles = null;
        };
        return this;
    }]);

<%= angularAppName %>.constant('USER_ROLES', {
        all: '*',
        admin: 'ROLE_ADMIN',
        user: 'ROLE_USER'
    });

<%= angularAppName %>.factory('AuthenticationSharedService', ['$rootScope', '$http', 'authService', 'Session', 'Account',<% if (authenticationType == 'token') { %> 'Base64Service', 'AccessToken', <% } %>
    function ($rootScope, $http, authService, Session, Account<% if (authenticationType == 'token') { %>, Base64Service, AccessToken<% } %>) {
        return {
            login: function (param) {<% if (authenticationType == 'cookie') { %>
                var data ="j_username=" + param.username +"&j_password=" + param.password +"&_spring_security_remember_me=" + param.rememberMe +"&submit=Login";
                $http.post('app/authentication', data, {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded"
                    },
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    Account.get(function(data) {
                        Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                        $rootScope.account = Session;
                        authService.loginConfirmed(data);
                    });
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticationError = true;
                    Session.invalidate();
                });<% } %><% if (authenticationType == 'token') { %>
                var data = "username=" + param.username + "&password=" + param.password + "&grant_type=password&scope=read%20write&client_secret=mySecretOAuthSecret&client_id=<%= baseName%>app";
                $http.post('oauth/token', data, {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded",
                        "Accept": "application/json",
                        "Authorization": "Basic " + Base64Service.encode("<%= baseName%>app" + ':' + "mySecretOAuthSecret")
                    },
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    httpHeaders.common['Authorization'] = 'Bearer ' + data.access_token;
                    AccessToken.set(data);

                    Account.get(function(data) {
                        Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                        $rootScope.account = Session;
                        authService.loginConfirmed(data);
                    });
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticationError = true;
                    Session.invalidate();
                });<% } %>
            },
            valid: function (authorizedRoles) {<% if (authenticationType == 'token') { %>
                httpHeaders.common['Authorization'] = 'Bearer ' + AccessToken.get();<% } %>

                $http.get('protected/transparent.gif', {
                    ignoreAuthModule: 'ignoreAuthModule'
                }).success(function (data, status, headers, config) {
                    if (!Session.login<% if (authenticationType == 'token') { %> || AccessToken.get() != undefined<% } %>) {<% if (authenticationType == 'token') { %>
                        if (AccessToken.get() == undefined || AccessToken.expired()) {
                            $rootScope.authenticated = false
                            return;
                        }<% } %>
                        Account.get(function(data) {
                            Session.create(data.login, data.firstName, data.lastName, data.email, data.roles);
                            $rootScope.account = Session;

                            if (!$rootScope.isAuthorized(authorizedRoles)) {
                                event.preventDefault();
                                // user is not allowed
                                $rootScope.$broadcast("event:auth-notAuthorized");
                            }

                            $rootScope.authenticated = true;
                        });
                    }
                    $rootScope.authenticated = !!Session.login;
                }).error(function (data, status, headers, config) {
                    $rootScope.authenticated = false;
                });
            },
            isAuthorized: function (authorizedRoles) {
                if (!angular.isArray(authorizedRoles)) {
                    if (authorizedRoles == '*') {
                        return true;
                    }

                    authorizedRoles = [authorizedRoles];
                }

                var isAuthorized = false;
                angular.forEach(authorizedRoles, function(authorizedRole) {
                    var authorized = (!!Session.login &&
                        Session.userRoles.indexOf(authorizedRole) !== -1);

                    if (authorized || authorizedRole == '*') {
                        isAuthorized = true;
                    }
                });

                return isAuthorized;
            },
            logout: function () {
                $rootScope.authenticationError = false;
                $rootScope.authenticated = false;
                $rootScope.account = null;<% if (authenticationType == 'token') { %>
                AccessToken.remove();<% } %>

                $http.get('app/logout');
                Session.invalidate();<% if (authenticationType == 'token') { %>
                httpHeaders.common['Authorization'] = null;<% } %>
                authService.loginCancelled();
            }
        };
    }]);
<|endoftext|>


<commit_before>/*
    blockly_runner:
        Blockly (translated into JavaScript) code runner, with highlighting and
        value reporting features.
*/

function initBlocklyRunner(context, messageCallback) {
   init(context, [], [], [], false, {});

   function init(context, interpreters, isRunning, toStop, stopPrograms, runner) {
      runner.hasActions = false;
      runner.nbActions = 0;
      runner.scratchMode = context.blocklyHelper ? context.blocklyHelper.scratchMode : false;
      runner.delayFactory = new DelayFactory();
      runner.resetDone = false;

      // Iteration limits
      runner.maxIter = 400000;
      runner.maxIterWithoutAction = 500;

      // Counts the call stack depth to know when to reset it
      runner.stackCount = 0;

      // During step-by-step mode
      runner.stepInProgress = false;
      runner.stepMode = false;
      runner.nextCallBack = null;

      // First highlightBlock of this run
      runner.firstHighlight = true;

      runner.strings = languageStrings;

      runner.valueToString = function(value) {
         if(interpreters.length == 0) {
            return value.toString(); // We "need" an interpreter to access ARRAY prototype
         }
         var itp = interpreters[0];
         if(itp.isa(value, itp.ARRAY)) {
            var strs = [];
            for(var i = 0; i < value.properties.length; i++) {
               strs[i] = runner.valueToString(value.properties[i]);
            }
            return '['+strs.join(', ')+']';
         } else if(value && value.toString) {
            return value.toString();
         } else {
            return "" + value;
         }
      };

      runner.reportBlockValue = function(id, value, varName) {
         // Show a popup displaying the value of a block in step-by-step mode
         if(context.display && runner.stepMode) {
            var displayStr = runner.valueToString(value);
            if(value && value.type == 'boolean') {
               displayStr = value.data ? runner.strings.valueTrue : runner.strings.valueFalse;
            }
            if(varName) {
               varName = varName.toString();
               // Get the original variable name
               for(var dbIdx in Blockly.JavaScript.variableDB_.db_) {
                  if(Blockly.JavaScript.variableDB_.db_[dbIdx] == varName) {
                     varName = dbIdx.substring(0, dbIdx.length - 9);
                     // Get the variable name with the right case
                     for(var i=0; i<context.blocklyHelper.workspace.variableList.length; i++) {
                        var varNameCase = context.blocklyHelper.workspace.variableList[i];
                        if(varName.toLowerCase() == varNameCase.toLowerCase()) {
                           varName = varNameCase;
                           break;
                        }
                     }
                     break;
                  }
               }
               displayStr = varName + ' = ' + displayStr;
            }
            context.blocklyHelper.workspace.reportValue(id, displayStr);
         }
         return value;
      };

      runner.waitDelay = function(callback, value, delay) {
         if (delay > 0) {
            runner.stackCount = 0;
            runner.delayFactory.createTimeout("wait" + context.curRobot + "_" + Math.random(), function() {
                  runner.noDelay(callback, value);
               },
               delay
            );
         } else {
            runner.noDelay(callback, value);
         }
      };

      runner.waitEvent = function(callback, target, eventName, func) {
         runner.stackCount = 0;
         var listenerFunc = null;
         listenerFunc = function(e) {
            target.removeEventListener(eventName, listenerFunc);
            runner.noDelay(callback, func(e));
         };
         target.addEventListener(eventName, listenerFunc);
      };

      runner.waitCallback = function(callback) {
         // Returns a callback to be called once we can continue the execution
         runner.stackCount = 0;
         return function(value) {
            runner.noDelay(callback, value);
         }
      };

      runner.noDelay = function(callback, value) {
         var primitive = undefined;
         if (value !== undefined) {
            if(typeof value.length != 'undefined') {
               // It's an array, create a primitive out of it
               primitive = interpreters[context.curRobot].nativeToPseudo(value);
            } else {
               primitive = value;
            }
         }
         if (runner.stackCount > 100) {
            // In case of an infinite loop, add some delay to slow down a bit
            var delay = context.allowInfiniteLoop ? 20 : 0;

            runner.stackCount = 0;
            runner.stackResetting = true;
            runner.delayFactory.createTimeout("wait_" + Math.random(), function() {
               runner.stackResetting = false;
               callback(primitive);
               runner.runSyncBlock();
            }, delay);
         } else {
            runner.stackCount += 1;
            callback(primitive);
            runner.runSyncBlock();
         }
      };

      runner.initInterpreter = function(interpreter, scope) {
         // Wrapper for async functions
         var createAsync = function(func) {
            return function() {
               var args = [];
               for(var i=0; i < arguments.length-1; i++) {
                  // TODO :: Maybe JS-Interpreter has a better way of knowing?
                  if(typeof arguments[i] != 'undefined' && arguments[i].isObject) {
                     args.push(interpreter.pseudoToNative(arguments[i]));
                  } else {
                     args.push(arguments[i]);
                  }
               }
               args.push(arguments[arguments.length-1]);
               func.apply(func, args);
               };
         };

         var makeHandler = function(runner, handler) {
            // For commands belonging to the "actions" category, we count the
            // number of actions to put a limit on steps without actions
            return function () {
               runner.nbActions += 1;
               handler.apply(this, arguments);
            };
         };

         for (var objectName in context.customBlocks) {
            for (var category in context.customBlocks[objectName]) {
               for (var iBlock in context.customBlocks[objectName][category]) {
                  var blockInfo = context.customBlocks[objectName][category][iBlock];
                  var code = context.strings.code[blockInfo.name];
                  if (typeof(code) == "undefined") {
                     code = blockInfo.name;
                  }

                  if(category == 'actions') {
                     runner.hasActions = true;
                     var handler = makeHandler(runner, blockInfo.handler);
                  } else {
                     var handler = blockInfo.handler;
                  }

                  interpreter.setProperty(scope, code, interpreter.createAsyncFunction(createAsync(handler)));
               }
            }
         }

         var makeNative = function(func) {
            return function() {
               var value = func.apply(func, arguments);
               var primitive = undefined;
               if (value != undefined) {
                  if(typeof value.length != 'undefined') {
                     // It's an array, create a primitive out of it
                     primitive = interpreters[context.curRobot].nativeToPseudo(value);
                  } else {
                     primitive = value;
                  }
               }
               return primitive;
            };
         }

         if(Blockly.JavaScript.externalFunctions) {
            for(var name in Blockly.JavaScript.externalFunctions) {
               interpreter.setProperty(scope, name, interpreter.createNativeFunction(makeNative(Blockly.JavaScript.externalFunctions[name])));
            }
         }

         /*for (var objectName in context.generators) {
            for (var iGen = 0; iGen < context.generators[objectName].length; iGen++) {
               var generator = context.generators[objectName][iGen];
               interpreter.setProperty(scope, objectName + "_" + generator.labelEn, interpreter.createAsyncFunction(generator.fct));
            }
         }*/
         interpreter.setProperty(scope, "program_end", interpreter.createAsyncFunction(createAsync(context.program_end)));

         function highlightBlock(id, callback) {
            id = id ? id.toString() : '';

            if (context.display) {
               try {
                  if(!runner.scratchMode) {
                     context.blocklyHelper.workspace.traceOn(true);
                     context.blocklyHelper.workspace.highlightBlock(id);
                     highlightPause = true;
                  } else {
                     context.blocklyHelper.glowBlock(id);
                     highlightPause = true;
                  }
               } catch(e) {}
            }

            // We always execute directly the first highlightBlock
            if(runner.firstHighlight || !runner.stepMode) {
               runner.firstHighlight = false;
               callback();
               runner.runSyncBlock();
            } else {
               // Interrupt here for step mode, allows to stop before each
               // instruction
               runner.nextCallback = callback;
               runner.stepInProgress = false;
            }
         }

         // Add an API function for highlighting blocks.
         interpreter.setProperty(scope, 'highlightBlock', interpreter.createAsyncFunction(createAsync(highlightBlock)));

         // Add an API function to report a value.
         interpreter.setProperty(scope, 'reportBlockValue', interpreter.createNativeFunction(runner.reportBlockValue));

      };

      runner.stop = function() {
         for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
            if (isRunning[iInterpreter]) {
               toStop[iInterpreter] = true;
               isRunning[iInterpreter] = false;
            }
         }

         if(runner.scratchMode) {
            Blockly.DropDownDiv.hide();
            context.blocklyHelper.glowBlock(null);
         }

         runner.nbActions = 0;
         runner.stepInProgress = false;
         runner.stepMode = false;
         runner.firstHighlight = true;
      };

      runner.runSyncBlock = function() {
         runner.resetDone = false;
         runner.stepInProgress = true;
         // Handle the callback from last highlightBlock
         if(runner.nextCallback) {
            runner.nextCallback();
            runner.nextCallback = null;
         }

         try {
            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               context.curRobot = iInterpreter;
               if (context.infos.checkEndEveryTurn) {
                  context.infos.checkEndCondition(context, false);
               }
               var interpreter = interpreters[iInterpreter];
               while(!context.programEnded[iInterpreter]) {
                  if(!context.allowInfiniteLoop &&
                        (context.curSteps[iInterpreter].total >= runner.maxIter || context.curSteps[iInterpreter].withoutAction >= runner.maxIterWithoutAction)) {
                     break;
                  }
                  if (!interpreter.step() || toStop[iInterpreter]) {
                     isRunning[iInterpreter] = false;
                     break;
                  }
                  if (interpreter.paused_) {
                     break;
                  }
                  context.curSteps[iInterpreter].total++;
                  if(context.curSteps[iInterpreter].lastNbMoves != runner.nbActions) {
                     context.curSteps[iInterpreter].lastNbMoves = runner.nbActions;
                     context.curSteps[iInterpreter].withoutAction = 0;
                  } else {
                     context.curSteps[iInterpreter].withoutAction++;
                  }
               }

               if (!context.programEnded[iInterpreter] && !context.allowInfiniteLoop) {
                  if (context.curSteps[iInterpreter].total >= runner.maxIter) {
                     isRunning[iInterpreter] = false;
                     throw context.blocklyHelper.strings.tooManyIterations;
                  } else if(context.curSteps[iInterpreter].withoutAction >= runner.maxIterWithoutAction) {
                     isRunning[iInterpreter] = false;
                     throw context.blocklyHelper.strings.tooManyIterationsWithoutAction;
                  }
               }
            }
         } catch (e) {
            context.onExecutionEnd && context.onExecutionEnd();
            runner.stepInProgress = false;

            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               isRunning[iInterpreter] = false;
               context.programEnded[iInterpreter] = true;
            }

            var message = e.message || e.toString();

            // Translate "Unknown identifier" message
            if(message.substring(0, 20) == "Unknown identifier: ") {
               var varName = message.substring(20);
               // Get original variable name if possible
               for(var dbIdx in Blockly.JavaScript.variableDB_.db_) {
                  if(Blockly.JavaScript.variableDB_.db_[dbIdx] == varName) {
                     varName = dbIdx.substring(0, dbIdx.length - 9);
                     break;
                  }
               }
               message = runner.strings.uninitializedVar + ' ' + varName;
            }

            if(message.indexOf('undefined') != -1) {
               console.error(e)
               message += '. ' + runner.strings.undefinedMsg;
            }

            if ((context.nbTestCases != undefined) && (context.nbTestCases > 1)) {
               if (context.success) {
                  message = context.messagePrefixSuccess + message;
               } else {
                  message = context.messagePrefixFailure + message;
               }
            }
            if (context.success) {
               message = "" + message + "";
               if (context.linkBack) {
                  //message += "
Retour à la liste des questions";
               }
            }
            runner.delayFactory.destroyAll();
            if(window.quickAlgoInterface) {
               window.quickAlgoInterface.setPlayPause(false);
            }
            setTimeout(function() { messageCallback(message); }, 0);
         }
      };

      runner.initCodes = function(codes) {
         runner.delayFactory.destroyAll();
         interpreters = [];
         runner.nbActions = 0;
         runner.stepInProgress = false;
         runner.stepMode = false;
         runner.firstHighlight = true;
         runner.stackCount = 0;
         context.programEnded = [];
         context.curSteps = [];
         runner.reset();
         for (var iInterpreter = 0; iInterpreter < codes.length; iInterpreter++) {
            context.curSteps[iInterpreter] = {
               total: 0,
               withoutAction: 0,
               lastNbMoves: 0
            };
            context.programEnded[iInterpreter] = false;
            interpreters.push(new Interpreter(codes[iInterpreter], runner.initInterpreter));
            isRunning[iInterpreter] = true;
            toStop[iInterpreter] = false;
         }
         runner.maxIter = 400000;
         if (context.infos.maxIter != undefined) {
            runner.maxIter = context.infos.maxIter;
         }
         if(runner.hasActions) {
            runner.maxIterWithoutAction = 500;
            if (context.infos.maxIterWithoutAction != undefined) {
               runner.maxIterWithoutAction = context.infos.maxIterWithoutAction;
            }
         } else {
            // If there's no actions in the current task, "disable" the limit
            runner.maxIterWithoutAction = runner.maxIter;
         }
      };

      runner.runCodes = function(codes) {
         runner.initCodes(codes);
         runner.runSyncBlock();
      };

      runner.run = function () {
         runner.stepMode = false;
         if(!runner.stepInProgress) {
            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               interpreters[iInterpreter].paused_ = false;
            }
            runner.runSyncBlock();
         }
      };

      runner.step = function () {
         runner.stepMode = true;
         if(!runner.stepInProgress) {
            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               interpreters[iInterpreter].paused_ = false;
            }
            runner.runSyncBlock();
         }
      };

      runner.nbRunning = function() {
         var nbRunning = 0;
         for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
            if (isRunning[iInterpreter]) {
               nbRunning++;
            }
         }
         return nbRunning;
      };

      runner.isRunning = function () {
         return this.nbRunning() > 0;
      };

      runner.reset = function() {
         if(runner.resetDone) { return; }
         context.reset();
         runner.stop();
         runner.resetDone = true;
      };

      context.runner = runner;
      context.callCallback = runner.noDelay;
      context.programEnded = [];
   }
}
<commit_msg>quickAlgo: Fix blockly runner noDelay<commit_after>/*
    blockly_runner:
        Blockly (translated into JavaScript) code runner, with highlighting and
        value reporting features.
*/

function initBlocklyRunner(context, messageCallback) {
   init(context, [], [], [], false, {});

   function init(context, interpreters, isRunning, toStop, stopPrograms, runner) {
      runner.hasActions = false;
      runner.nbActions = 0;
      runner.scratchMode = context.blocklyHelper ? context.blocklyHelper.scratchMode : false;
      runner.delayFactory = new DelayFactory();
      runner.resetDone = false;

      // Iteration limits
      runner.maxIter = 400000;
      runner.maxIterWithoutAction = 500;

      // Counts the call stack depth to know when to reset it
      runner.stackCount = 0;

      // During step-by-step mode
      runner.stepInProgress = false;
      runner.stepMode = false;
      runner.nextCallBack = null;

      // First highlightBlock of this run
      runner.firstHighlight = true;

      runner.strings = languageStrings;

      runner.valueToString = function(value) {
         if(interpreters.length == 0) {
            return value.toString(); // We "need" an interpreter to access ARRAY prototype
         }
         var itp = interpreters[0];
         if(itp.isa(value, itp.ARRAY)) {
            var strs = [];
            for(var i = 0; i < value.properties.length; i++) {
               strs[i] = runner.valueToString(value.properties[i]);
            }
            return '['+strs.join(', ')+']';
         } else if(value && value.toString) {
            return value.toString();
         } else {
            return "" + value;
         }
      };

      runner.reportBlockValue = function(id, value, varName) {
         // Show a popup displaying the value of a block in step-by-step mode
         if(context.display && runner.stepMode) {
            var displayStr = runner.valueToString(value);
            if(value && value.type == 'boolean') {
               displayStr = value.data ? runner.strings.valueTrue : runner.strings.valueFalse;
            }
            if(varName) {
               varName = varName.toString();
               // Get the original variable name
               for(var dbIdx in Blockly.JavaScript.variableDB_.db_) {
                  if(Blockly.JavaScript.variableDB_.db_[dbIdx] == varName) {
                     varName = dbIdx.substring(0, dbIdx.length - 9);
                     // Get the variable name with the right case
                     for(var i=0; i<context.blocklyHelper.workspace.variableList.length; i++) {
                        var varNameCase = context.blocklyHelper.workspace.variableList[i];
                        if(varName.toLowerCase() == varNameCase.toLowerCase()) {
                           varName = varNameCase;
                           break;
                        }
                     }
                     break;
                  }
               }
               displayStr = varName + ' = ' + displayStr;
            }
            context.blocklyHelper.workspace.reportValue(id, displayStr);
         }
         return value;
      };

      runner.waitDelay = function(callback, value, delay) {
         if (delay > 0) {
            runner.stackCount = 0;
            runner.delayFactory.createTimeout("wait" + context.curRobot + "_" + Math.random(), function() {
                  runner.noDelay(callback, value);
               },
               delay
            );
         } else {
            runner.noDelay(callback, value);
         }
      };

      runner.waitEvent = function(callback, target, eventName, func) {
         runner.stackCount = 0;
         var listenerFunc = null;
         listenerFunc = function(e) {
            target.removeEventListener(eventName, listenerFunc);
            runner.noDelay(callback, func(e));
         };
         target.addEventListener(eventName, listenerFunc);
      };

      runner.waitCallback = function(callback) {
         // Returns a callback to be called once we can continue the execution
         runner.stackCount = 0;
         return function(value) {
            runner.noDelay(callback, value);
         }
      };

      runner.noDelay = function(callback, value) {
         var primitive = undefined;
         if (value !== undefined) {
            if(value && typeof value.length != 'undefined') {
               // It's an array, create a primitive out of it
               primitive = interpreters[context.curRobot].nativeToPseudo(value);
            } else {
               primitive = value;
            }
         }
         if (runner.stackCount > 100) {
            // In case of an infinite loop, add some delay to slow down a bit
            var delay = context.allowInfiniteLoop ? 20 : 0;

            runner.stackCount = 0;
            runner.stackResetting = true;
            runner.delayFactory.createTimeout("wait_" + Math.random(), function() {
               runner.stackResetting = false;
               callback(primitive);
               runner.runSyncBlock();
            }, delay);
         } else {
            runner.stackCount += 1;
            callback(primitive);
            runner.runSyncBlock();
         }
      };

      runner.initInterpreter = function(interpreter, scope) {
         // Wrapper for async functions
         var createAsync = function(func) {
            return function() {
               var args = [];
               for(var i=0; i < arguments.length-1; i++) {
                  // TODO :: Maybe JS-Interpreter has a better way of knowing?
                  if(typeof arguments[i] != 'undefined' && arguments[i].isObject) {
                     args.push(interpreter.pseudoToNative(arguments[i]));
                  } else {
                     args.push(arguments[i]);
                  }
               }
               args.push(arguments[arguments.length-1]);
               func.apply(func, args);
               };
         };

         var makeHandler = function(runner, handler) {
            // For commands belonging to the "actions" category, we count the
            // number of actions to put a limit on steps without actions
            return function () {
               runner.nbActions += 1;
               handler.apply(this, arguments);
            };
         };

         for (var objectName in context.customBlocks) {
            for (var category in context.customBlocks[objectName]) {
               for (var iBlock in context.customBlocks[objectName][category]) {
                  var blockInfo = context.customBlocks[objectName][category][iBlock];
                  var code = context.strings.code[blockInfo.name];
                  if (typeof(code) == "undefined") {
                     code = blockInfo.name;
                  }

                  if(category == 'actions') {
                     runner.hasActions = true;
                     var handler = makeHandler(runner, blockInfo.handler);
                  } else {
                     var handler = blockInfo.handler;
                  }

                  interpreter.setProperty(scope, code, interpreter.createAsyncFunction(createAsync(handler)));
               }
            }
         }

         var makeNative = function(func) {
            return function() {
               var value = func.apply(func, arguments);
               var primitive = undefined;
               if (value != undefined) {
                  if(typeof value.length != 'undefined') {
                     // It's an array, create a primitive out of it
                     primitive = interpreters[context.curRobot].nativeToPseudo(value);
                  } else {
                     primitive = value;
                  }
               }
               return primitive;
            };
         }

         if(Blockly.JavaScript.externalFunctions) {
            for(var name in Blockly.JavaScript.externalFunctions) {
               interpreter.setProperty(scope, name, interpreter.createNativeFunction(makeNative(Blockly.JavaScript.externalFunctions[name])));
            }
         }

         /*for (var objectName in context.generators) {
            for (var iGen = 0; iGen < context.generators[objectName].length; iGen++) {
               var generator = context.generators[objectName][iGen];
               interpreter.setProperty(scope, objectName + "_" + generator.labelEn, interpreter.createAsyncFunction(generator.fct));
            }
         }*/
         interpreter.setProperty(scope, "program_end", interpreter.createAsyncFunction(createAsync(context.program_end)));

         function highlightBlock(id, callback) {
            id = id ? id.toString() : '';

            if (context.display) {
               try {
                  if(!runner.scratchMode) {
                     context.blocklyHelper.workspace.traceOn(true);
                     context.blocklyHelper.workspace.highlightBlock(id);
                     highlightPause = true;
                  } else {
                     context.blocklyHelper.glowBlock(id);
                     highlightPause = true;
                  }
               } catch(e) {}
            }

            // We always execute directly the first highlightBlock
            if(runner.firstHighlight || !runner.stepMode) {
               runner.firstHighlight = false;
               callback();
               runner.runSyncBlock();
            } else {
               // Interrupt here for step mode, allows to stop before each
               // instruction
               runner.nextCallback = callback;
               runner.stepInProgress = false;
            }
         }

         // Add an API function for highlighting blocks.
         interpreter.setProperty(scope, 'highlightBlock', interpreter.createAsyncFunction(createAsync(highlightBlock)));

         // Add an API function to report a value.
         interpreter.setProperty(scope, 'reportBlockValue', interpreter.createNativeFunction(runner.reportBlockValue));

      };

      runner.stop = function() {
         for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
            if (isRunning[iInterpreter]) {
               toStop[iInterpreter] = true;
               isRunning[iInterpreter] = false;
            }
         }

         if(runner.scratchMode) {
            Blockly.DropDownDiv.hide();
            context.blocklyHelper.glowBlock(null);
         }

         runner.nbActions = 0;
         runner.stepInProgress = false;
         runner.stepMode = false;
         runner.firstHighlight = true;
      };

      runner.runSyncBlock = function() {
         runner.resetDone = false;
         runner.stepInProgress = true;
         // Handle the callback from last highlightBlock
         if(runner.nextCallback) {
            runner.nextCallback();
            runner.nextCallback = null;
         }

         try {
            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               context.curRobot = iInterpreter;
               if (context.infos.checkEndEveryTurn) {
                  context.infos.checkEndCondition(context, false);
               }
               var interpreter = interpreters[iInterpreter];
               while(!context.programEnded[iInterpreter]) {
                  if(!context.allowInfiniteLoop &&
                        (context.curSteps[iInterpreter].total >= runner.maxIter || context.curSteps[iInterpreter].withoutAction >= runner.maxIterWithoutAction)) {
                     break;
                  }
                  if (!interpreter.step() || toStop[iInterpreter]) {
                     isRunning[iInterpreter] = false;
                     break;
                  }
                  if (interpreter.paused_) {
                     break;
                  }
                  context.curSteps[iInterpreter].total++;
                  if(context.curSteps[iInterpreter].lastNbMoves != runner.nbActions) {
                     context.curSteps[iInterpreter].lastNbMoves = runner.nbActions;
                     context.curSteps[iInterpreter].withoutAction = 0;
                  } else {
                     context.curSteps[iInterpreter].withoutAction++;
                  }
               }

               if (!context.programEnded[iInterpreter] && !context.allowInfiniteLoop) {
                  if (context.curSteps[iInterpreter].total >= runner.maxIter) {
                     isRunning[iInterpreter] = false;
                     throw context.blocklyHelper.strings.tooManyIterations;
                  } else if(context.curSteps[iInterpreter].withoutAction >= runner.maxIterWithoutAction) {
                     isRunning[iInterpreter] = false;
                     throw context.blocklyHelper.strings.tooManyIterationsWithoutAction;
                  }
               }
            }
         } catch (e) {
            context.onExecutionEnd && context.onExecutionEnd();
            runner.stepInProgress = false;

            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               isRunning[iInterpreter] = false;
               context.programEnded[iInterpreter] = true;
            }

            var message = e.message || e.toString();

            // Translate "Unknown identifier" message
            if(message.substring(0, 20) == "Unknown identifier: ") {
               var varName = message.substring(20);
               // Get original variable name if possible
               for(var dbIdx in Blockly.JavaScript.variableDB_.db_) {
                  if(Blockly.JavaScript.variableDB_.db_[dbIdx] == varName) {
                     varName = dbIdx.substring(0, dbIdx.length - 9);
                     break;
                  }
               }
               message = runner.strings.uninitializedVar + ' ' + varName;
            }

            if(message.indexOf('undefined') != -1) {
               console.error(e)
               message += '. ' + runner.strings.undefinedMsg;
            }

            if ((context.nbTestCases != undefined) && (context.nbTestCases > 1)) {
               if (context.success) {
                  message = context.messagePrefixSuccess + message;
               } else {
                  message = context.messagePrefixFailure + message;
               }
            }
            if (context.success) {
               message = "" + message + "";
               if (context.linkBack) {
                  //message += "
Retour à la liste des questions";
               }
            }
            runner.delayFactory.destroyAll();
            if(window.quickAlgoInterface) {
               window.quickAlgoInterface.setPlayPause(false);
            }
            setTimeout(function() { messageCallback(message); }, 0);
         }
      };

      runner.initCodes = function(codes) {
         runner.delayFactory.destroyAll();
         interpreters = [];
         runner.nbActions = 0;
         runner.stepInProgress = false;
         runner.stepMode = false;
         runner.firstHighlight = true;
         runner.stackCount = 0;
         context.programEnded = [];
         context.curSteps = [];
         runner.reset();
         for (var iInterpreter = 0; iInterpreter < codes.length; iInterpreter++) {
            context.curSteps[iInterpreter] = {
               total: 0,
               withoutAction: 0,
               lastNbMoves: 0
            };
            context.programEnded[iInterpreter] = false;
            interpreters.push(new Interpreter(codes[iInterpreter], runner.initInterpreter));
            isRunning[iInterpreter] = true;
            toStop[iInterpreter] = false;
         }
         runner.maxIter = 400000;
         if (context.infos.maxIter != undefined) {
            runner.maxIter = context.infos.maxIter;
         }
         if(runner.hasActions) {
            runner.maxIterWithoutAction = 500;
            if (context.infos.maxIterWithoutAction != undefined) {
               runner.maxIterWithoutAction = context.infos.maxIterWithoutAction;
            }
         } else {
            // If there's no actions in the current task, "disable" the limit
            runner.maxIterWithoutAction = runner.maxIter;
         }
      };

      runner.runCodes = function(codes) {
         runner.initCodes(codes);
         runner.runSyncBlock();
      };

      runner.run = function () {
         runner.stepMode = false;
         if(!runner.stepInProgress) {
            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               interpreters[iInterpreter].paused_ = false;
            }
            runner.runSyncBlock();
         }
      };

      runner.step = function () {
         runner.stepMode = true;
         if(!runner.stepInProgress) {
            for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
               interpreters[iInterpreter].paused_ = false;
            }
            runner.runSyncBlock();
         }
      };

      runner.nbRunning = function() {
         var nbRunning = 0;
         for (var iInterpreter = 0; iInterpreter < interpreters.length; iInterpreter++) {
            if (isRunning[iInterpreter]) {
               nbRunning++;
            }
         }
         return nbRunning;
      };

      runner.isRunning = function () {
         return this.nbRunning() > 0;
      };

      runner.reset = function() {
         if(runner.resetDone) { return; }
         context.reset();
         runner.stop();
         runner.resetDone = true;
      };

      context.runner = runner;
      context.callCallback = runner.noDelay;
      context.programEnded = [];
   }
}
<|endoftext|>


<commit_before>
// changed to be usable as an es6 module, ASR

/*! sprintf-js v1.0.3 | Copyright (c) 2007-present, Alexandru Marasteanu <hello@alexei.ro> | BSD-3-Clause */

    var re = {
        not_string: /[^s]/,
        not_bool: /[^t]/,
        not_type: /[^T]/,
        not_primitive: /[^v]/,
        number: /[diefg]/,
        numeric_arg: /bcdiefguxX/,
        json: /[j]/,
        not_json: /[^j]/,
        text: /^[^\x25]+/,
        modulo: /^\x25{2}/,
        placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,
        key: /^([a-z_][a-z_\d]*)/i,
        key_access: /^\.([a-z_][a-z_\d]*)/i,
        index_access: /^\[(\d+)\]/,
        sign: /^[\+\-]/
    }

    function sprintf() {
        var key = arguments[0], cache = sprintf.cache
        if (!(cache[key] && cache.hasOwnProperty(key))) {
            cache[key] = sprintf.parse(key)
        }
        return sprintf.format.call(null, cache[key], arguments)
    }

    sprintf.format = function(parse_tree, argv) {
        var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ''
        for (i = 0; i < tree_length; i++) {
            node_type = get_type(parse_tree[i])
            if (node_type === 'string') {
                output[output.length] = parse_tree[i]
            }
            else if (node_type === 'array') {
                match = parse_tree[i] // convenience purposes only
                if (match[2]) { // keyword argument
                    arg = argv[cursor]
                    for (k = 0; k < match[2].length; k++) {
                        if (!arg.hasOwnProperty(match[2][k])) {
                            throw new Error(sprintf('[sprintf] property "%s" does not exist', match[2][k]))
                        }
                        arg = arg[match[2][k]]
                    }
                }
                else if (match[1]) { // positional argument (explicit)
                    arg = argv[match[1]]
                }
                else { // positional argument (implicit)
                    arg = argv[cursor++]
                }

                if (re.not_type.test(match[8]) && re.not_primitive.test(match[8]) && get_type(arg) == 'function') {
                    arg = arg()
                }

                if (re.numeric_arg.test(match[8]) && (get_type(arg) != 'number' && isNaN(arg))) {
                    throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg)))
                }

                if (re.number.test(match[8])) {
                    is_positive = arg >= 0
                }

                switch (match[8]) {
                    case 'b':
                        arg = parseInt(arg, 10).toString(2)
                    break
                    case 'c':
                        arg = String.fromCharCode(parseInt(arg, 10))
                    break
                    case 'd':
                    case 'i':
                        arg = parseInt(arg, 10)
                    break
                    case 'j':
                        arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0)
                    break
                    case 'e':
                        arg = match[7] ? parseFloat(arg).toExponential(match[7]) : parseFloat(arg).toExponential()
                    break
                    case 'f':
                        arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)
                    break
                    case 'g':
                        arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg)
                    break
                    case 'o':
                        arg = arg.toString(8)
                    break
                    case 's':
                        arg = String(arg)
                        arg = (match[7] ? arg.substring(0, match[7]) : arg)
                    break
                    case 't':
                        arg = String(!!arg)
                        arg = (match[7] ? arg.substring(0, match[7]) : arg)
                    break
                    case 'T':
                        arg = get_type(arg)
                        arg = (match[7] ? arg.substring(0, match[7]) : arg)
                    break
                    case 'u':
                        arg = parseInt(arg, 10) >>> 0
                    break
                    case 'v':
                        arg = arg.valueOf()
                        arg = (match[7] ? arg.substring(0, match[7]) : arg)
                    break
                    case 'x':
                        arg = parseInt(arg, 10).toString(16)
                    break
                    case 'X':
                        arg = parseInt(arg, 10).toString(16).toUpperCase()
                    break
                }
                if (re.json.test(match[8])) {
                    output[output.length] = arg
                }
                else {
                    if (re.number.test(match[8]) && (!is_positive || match[3])) {
                        sign = is_positive ? '+' : '-'
                        arg = arg.toString().replace(re.sign, '')
                    }
                    else {
                        sign = ''
                    }
                    pad_character = match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '
                    pad_length = match[6] - (sign + arg).length
                    pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : '') : ''
                    output[output.length] = match[5] ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)
                }
            }
        }
        return output.join('')
    }

    sprintf.cache = {}

    sprintf.parse = function(fmt) {
        var _fmt = fmt, match = [], parse_tree = [], arg_names = 0
        while (_fmt) {
            if ((match = re.text.exec(_fmt)) !== null) {
                parse_tree[parse_tree.length] = match[0]
            }
            else if ((match = re.modulo.exec(_fmt)) !== null) {
                parse_tree[parse_tree.length] = '%'
            }
            else if ((match = re.placeholder.exec(_fmt)) !== null) {
                if (match[2]) {
                    arg_names |= 1
                    var field_list = [], replacement_field = match[2], field_match = []
                    if ((field_match = re.key.exec(replacement_field)) !== null) {
                        field_list[field_list.length] = field_match[1]
                        while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
                            if ((field_match = re.key_access.exec(replacement_field)) !== null) {
                                field_list[field_list.length] = field_match[1]
                            }
                            else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
                                field_list[field_list.length] = field_match[1]
                            }
                            else {
                                throw new SyntaxError("[sprintf] failed to parse named argument key")
                            }
                        }
                    }
                    else {
                        throw new SyntaxError("[sprintf] failed to parse named argument key")
                    }
                    match[2] = field_list
                }
                else {
                    arg_names |= 2
                }
                if (arg_names === 3) {
                    throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported")
                }
                parse_tree[parse_tree.length] = match
            }
            else {
                throw new SyntaxError("[sprintf] unexpected placeholder")
            }
            _fmt = _fmt.substring(match[0].length)
        }
        return parse_tree
    }

    var vsprintf = function(fmt, argv, _argv) {
        _argv = (argv || []).slice(0)
        _argv.splice(0, 0, fmt)
        return sprintf.apply(null, _argv)
    }

    /**
     * helpers
     */
    function get_type(variable) {
        if (typeof variable === 'number') {
            return 'number'
        }
        else if (typeof variable === 'string') {
            return 'string'
        }
        else {
            return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()
        }
    }

    var preformattedPadding = {
        '0': ['', '0', '00', '000', '0000', '00000', '000000', '0000000'],
        ' ': ['', ' ', '  ', '   ', '    ', '     ', '      ', '       '],
        '_': ['', '_', '__', '___', '____', '_____', '______', '_______'],
    }
    function str_repeat(input, multiplier) {
        if (multiplier >= 0 && multiplier <= 7 && preformattedPadding[input]) {
            return preformattedPadding[input][multiplier]
        }
        return Array(multiplier + 1).join(input)
    }

export {
    sprintf,
    vsprintf
};
<commit_msg>updated sprintf to 1.1.1<commit_after>
// changed to be usable as an es6 module, ASR

/*! sprintf-js v1.1.1 | Copyright (c) 2007-present, Alexandru Marasteanu <hello@alexei.ro> | BSD-3-Clause */
var re = {
    not_string: /[^s]/,
    not_bool: /[^t]/,
    not_type: /[^T]/,
    not_primitive: /[^v]/,
    number: /[diefg]/,
    numeric_arg: /[bcdiefguxX]/,
    json: /[j]/,
    not_json: /[^j]/,
    text: /^[^\x25]+/,
    modulo: /^\x25{2}/,
    placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,
    key: /^([a-z_][a-z_\d]*)/i,
    key_access: /^\.([a-z_][a-z_\d]*)/i,
    index_access: /^\[(\d+)\]/,
    sign: /^[\+\-]/
}

function sprintf(key) {
    // `arguments` is not an array, but should be fine for this call
    return sprintf_format(sprintf_parse(key), arguments)
}

function vsprintf(fmt, argv) {
    return sprintf.apply(null, [fmt].concat(argv || []))
}

function sprintf_format(parse_tree, argv) {
    var cursor = 1, tree_length = parse_tree.length, arg, output = '', i, k, ph, pad, pad_character, pad_length, is_positive, sign
    for (i = 0; i < tree_length; i++) {
        if (typeof parse_tree[i] === 'string') {
            output += parse_tree[i]
        }
        else if (typeof parse_tree[i] === 'object') {
            ph = parse_tree[i] // convenience purposes only
            if (ph.keys) { // keyword argument
                arg = argv[cursor]
                for (k = 0; k < ph.keys.length; k++) {
                    if (!arg.hasOwnProperty(ph.keys[k])) {
                        throw new Error(sprintf('[sprintf] property "%s" does not exist', ph.keys[k]))
                    }
                    arg = arg[ph.keys[k]]
                }
            }
            else if (ph.param_no) { // positional argument (explicit)
                arg = argv[ph.param_no]
            }
            else { // positional argument (implicit)
                arg = argv[cursor++]
            }

            if (re.not_type.test(ph.type) && re.not_primitive.test(ph.type) && arg instanceof Function) {
                arg = arg()
            }

            if (re.numeric_arg.test(ph.type) && (typeof arg !== 'number' && isNaN(arg))) {
                throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg))
            }

            if (re.number.test(ph.type)) {
                is_positive = arg >= 0
            }

            switch (ph.type) {
                case 'b':
                    arg = parseInt(arg, 10).toString(2)
                    break
                case 'c':
                    arg = String.fromCharCode(parseInt(arg, 10))
                    break
                case 'd':
                case 'i':
                    arg = parseInt(arg, 10)
                    break
                case 'j':
                    arg = JSON.stringify(arg, null, ph.width ? parseInt(ph.width) : 0)
                    break
                case 'e':
                    arg = ph.precision ? parseFloat(arg).toExponential(ph.precision) : parseFloat(arg).toExponential()
                    break
                case 'f':
                    arg = ph.precision ? parseFloat(arg).toFixed(ph.precision) : parseFloat(arg)
                    break
                case 'g':
                    arg = ph.precision ? String(Number(arg.toPrecision(ph.precision))) : parseFloat(arg)
                    break
                case 'o':
                    arg = (parseInt(arg, 10) >>> 0).toString(8)
                    break
                case 's':
                    arg = String(arg)
                    arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
                    break
                case 't':
                    arg = String(!!arg)
                    arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
                    break
                case 'T':
                    arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase()
                    arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
                    break
                case 'u':
                    arg = parseInt(arg, 10) >>> 0
                    break
                case 'v':
                    arg = arg.valueOf()
                    arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
                    break
                case 'x':
                    arg = (parseInt(arg, 10) >>> 0).toString(16)
                    break
                case 'X':
                    arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase()
                    break
            }
            if (re.json.test(ph.type)) {
                output += arg
            }
            else {
                if (re.number.test(ph.type) && (!is_positive || ph.sign)) {
                    sign = is_positive ? '+' : '-'
                    arg = arg.toString().replace(re.sign, '')
                }
                else {
                    sign = ''
                }
                pad_character = ph.pad_char ? ph.pad_char === '0' ? '0' : ph.pad_char.charAt(1) : ' '
                pad_length = ph.width - (sign + arg).length
                pad = ph.width ? (pad_length > 0 ? pad_character.repeat(pad_length) : '') : ''
                output += ph.align ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)
            }
        }
    }
    return output
}

var sprintf_cache = Object.create(null)

function sprintf_parse(fmt) {
    if (sprintf_cache[fmt]) {
        return sprintf_cache[fmt]
    }

    var _fmt = fmt, match, parse_tree = [], arg_names = 0
    while (_fmt) {
        if ((match = re.text.exec(_fmt)) !== null) {
            parse_tree.push(match[0])
        }
        else if ((match = re.modulo.exec(_fmt)) !== null) {
            parse_tree.push('%')
        }
        else if ((match = re.placeholder.exec(_fmt)) !== null) {
            if (match[2]) {
                arg_names |= 1
                var field_list = [], replacement_field = match[2], field_match = []
                if ((field_match = re.key.exec(replacement_field)) !== null) {
                    field_list.push(field_match[1])
                    while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
                        if ((field_match = re.key_access.exec(replacement_field)) !== null) {
                            field_list.push(field_match[1])
                        }
                        else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
                            field_list.push(field_match[1])
                        }
                        else {
                            throw new SyntaxError('[sprintf] failed to parse named argument key')
                        }
                    }
                }
                else {
                    throw new SyntaxError('[sprintf] failed to parse named argument key')
                }
                match[2] = field_list
            }
            else {
                arg_names |= 2
            }
            if (arg_names === 3) {
                throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported')
            }

            parse_tree.push(
                {
                    placeholder: match[0],
                    param_no:    match[1],
                    keys:        match[2],
                    sign:        match[3],
                    pad_char:    match[4],
                    align:       match[5],
                    width:       match[6],
                    precision:   match[7],
                    type:        match[8]
                }
            )
        }
        else {
            throw new SyntaxError('[sprintf] unexpected placeholder')
        }
        _fmt = _fmt.substring(match[0].length)
    }
    return sprintf_cache[fmt] = parse_tree
}

export {
    sprintf,
    vsprintf
};
<|endoftext|>


<commit_before><commit_msg>Bot can be in private channel.<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env node
"use strict";

const fs = require("fs-extra");
const request = require("request");
const Menu = require("terminal-menu");
const moment = require("moment");
const Configstore = require("configstore");
const pkg = require("./package.json");
const path = require("path");

const conf = new Configstore(pkg.name, {
  dir: fs.realpathSync(__dirname),
  weeklyfocus: "Do good things this week",
  monthlyfocus: "Do good things this month",
  yearlyfocus: "Do good things this year"
});
const _ = require("lodash");
const chalk = require("chalk");

require("yargs")
  .command({
    command: "new [type] [goal]",
    aliases: ["n"],
    desc: "Set a new goal",
    example: "$0 n w 'work out 3 times'",
    builder: yargs => yargs.default("type", "w"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
      }
      newGoal(type, argv.goal);
    }
  })
  .command({
    command: "complete [type] [goal]",
    aliases: ["c"],
    desc: "mark a goal as completed",
    example: "$0 c w ",
    builder: yargs => yargs.default("type", "w"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
      }
      if (argv.goal) {
        completeGoal(type, argv.goal);
      } else {
        menu(type);
      }
    }
  })
  .command({
    command: "ls [type]",
    aliases: ["list"],
    usage: `$0 ls  <w, m, y, o, c, a>`,
    description: `list goals of a type`,
    builder: yargs => yargs.default("type", "a"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
        case "all":
        case "a":
          type = "all";
          break;
      }
      console.log(ls(type));
    }
  })
  .command({
    command: "clear [type]",
    aliases: ["clr"],
    usage: `$0 clear  <w, m, y, o, c, a>`,
    description: `clear goals of a type`,
    builder: yargs => yargs.default("type", "a"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
        case "all":
        case "a":
          type = "all";
          break;
      }
      clear(type);
    }
  })
  .command({
    command: "config <key> [value]",
    aliases: ["cfg"],
    usage: `$0 config <key> [value]`,
    describe: "Set up the personal goals configuration",
    handler: argv => {
      if (argv.value === "clear") {
        conf.delete(argv.key);
      } else if (argv.key === "clear") {
        conf.clear();
      } else if (argv.key === "ls" || argv.key === "get") {
        console.log(conf.all);
      } else {
        conf.set(argv.key, argv.value);
        console.log("Successfully updated");
        console.log(`${chalk.bold(argv.key)}: ${conf.get(argv.key)}`);
      }
    }
  })
  .group("weekly (w)", "Types")
  .group("monthly (m)", "Types")
  .group("other (o)", "Types")
  .group("completed (c)", "Types")
  .group("all (a)", "Types")
  .example("ls", "$0 ls")
  .example("ls", "$0 ls complete")
  .example("ls", "$0 list all")
  .example("new", `$0 new w 'work out 3 times' `)
  .example("new", `$0 n m 'lose 5 pounds'`)
  .example("complete", "$0 c other")
  .example("complete", `$0 complete week 'work out 3 times'`)
  .example("config", "$0 cfg dir '/user/me/projects/personal-goals'")
  .example("config", `$0 config weeklyfocus 'get outside more'`)
  .example(
    "complete",
    "$0 config monthlyfocus 'punch as many nazis as possible'"
  )
  .example("config", `$0 cfg yearlyfocus 'destroy all nazis'`)
  .example("clear", "$0 clear all")
  .example("clear", `$0 clear weekly`)
  .help().argv;

writeMD();

function newGoal(type, goal) {
  const date = moment().format("MMMDYYYYHHmm");
  const file = getFileName(type, goal);
  const completedfile = getFileName("completed/" + type + "/" + date, goal);
  fs.ensureDirSync(conf.get("dir") + "/" + type);
  fs.stat(completedfile, (err, cstat) => {
    if (err == null) {
      console.log("Moving goal from completed to " + type);
      fs.moveSync(completedfile, file);
      console.log(ls(type));
    } else if (err.code == "ENOENT") {
      fs.stat(file, (err, stat) => {
        if (err == null) {
          console.log("Goal already exists");
        } else if (err.code == "ENOENT") {
          // File does not exist
          fs.closeSync(fs.openSync(file, "w"));
          console.log(ls("all"));
        } else {
          console.log("Some other error: ", err.code);
        }
      });
    }
  });
  writeMD();
}

function completeGoal(type, goal) {
  const date = moment().format("MMMDYYYYHHmm");
  const dir = conf.get("dir") + "/completed/" + type + "/" + date;
  fs.ensureDirSync(dir);
  fs.ensureDirSync(path.join(conf.get("dir"), type));
  fs.moveSync(
    getFileName(type, goal),
    getFileName("completed/" + type + "/" + date, goal)
  );
  console.log(ls("all"));
  writeMD();
}

function getFileName(type, goal) {
  if (goal.length) {
    return (
      conf.get("dir") + "/" + type + "/" + goal.replace(/[ /.//]/g, "_") + ".md"
    );
  }

  return conf.get("dir") + "/" + type;
}

function prettyName(file) {
  let lastSlash = file.lastIndexOf("/") + 1;
  let fileExt = file.lastIndexOf(".");
  lastSlash = lastSlash === -1 ? 0 : lastSlash;
  fileExt = fileExt === -1 ? 20 : fileExt;
  const goal = file.substring(lastSlash, fileExt);
  const ret = goal.replace(/_/g, " ").replace(/(\w)(\w*)/g, (_, i, r) => {
    return i.toUpperCase() + (r != null ? r : "");
  });
  return ret;
}

function menu(type) {
  const dir = getFileName(type, "");
  fs.ensureDirSync(dir);
  const files = fs.readdirSync(dir);
  const menu = Menu({ bg: "black", fg: "white" });

  menu.reset();
  menu.write("Which " + prettyName(type) + " Goal Did You Complete?\n");
  menu.write("-------------------------------------\n");
  files.map(item => menu.add(prettyName(item)));
  menu.add("None");

  menu.on("select", label => {
    menu.close();
    if (label === "None") {
      process.exit(0);
    }
    completeGoal(type, label);
  });
  process.stdin.pipe(menu.createStream()).pipe(process.stdout);

  process.stdin.setRawMode(true);
  menu.on("close", () => {
    process.stdin.setRawMode(false);
    process.stdin.end();
  });
}

function clear(type) {
  if (type === "all") {
    fs.removeSync(path.join(conf.get("dir"), "weekly"));
    fs.removeSync(path.join(conf.get("dir"), "monthly"));
    fs.removeSync(path.join(conf.get("dir"), "yearly"));
    fs.removeSync(path.join(conf.get("dir"), "other"));
    fs.removeSync(path.join(conf.get("dir"), "completed"));
  } else {
    fs.removeSync(path.join(conf.get("dir"), type));
  }
}

function ls(type) {
  let res = "";
  if (type === "all") {
    res += ls("weekly");
    res += ls("monthly");
    res += ls("yearly");
    res += ls("other");
  } else {
    const dir = conf.get("dir") + "/" + type;
    fs.ensureDir(dir);
    const title = prettyName(type) + " Tasks";
    res += "\n" + chalk.bold.underline(title) + "\n";
    res += print(type);
    if (type !== "completed") {
      res += print("completed/" + type);
    }
  }
  return res;
}

function print(type, opts = {}) {
  const dir = conf.get("dir") + "/" + type;
  fs.ensureDirSync(dir);
  let res = "";
  const files = fs.readdirSync(dir);
  if (!files.length) {
    fs.removeSync(dir);
  }
  files.map(item => {
    const stats = fs.statSync(dir + "/" + item);
    if (stats.isDirectory()) {
      if (item.match(/\w{3}\d{9,10}/g)) {
        if (moment(item, "MMMDYYYYHHmm").diff(moment(), "day") < -7) {
          /*fs.moveSync(
            path.join(dir, item),
            path.join(
              conf.get("dir"),
              "past",
              path
                .dirname(type)
                .split(path.delimiter)
                .pop()
            )
          );*/
          console.log(path.dirname(dir));
        }
        opts.date = item;
      } else {
        res += "\n" + chalk.underline(item) + "\n";
      }
      res += print(type + "/" + item, opts);
    } else if (stats.isFile()) {
      if (!opts.hasOwnProperty("date")) {
        res += prettyName(item) + "\n";
      } else {
        res += `${chalk.green(prettyName(item))} ${chalk.gray(
          "- " + moment(opts.date, "MMMDYYYYHHmm").fromNow()
        )}\n`;
      }
    }
  });
  return res;
}

function writeMD() {
  fs.truncate(conf.get("dir") + "/README.md", 0, () => {
    fs.writeFile(conf.get("dir") + "/README.md", genMD(), err => {
      if (err) {
        return console.log("Error writing file: " + err);
      }
    });
  });
}

function genMD() {
  const date = moment().day(0);
  const res = `
Personal Goals
==============
Personal goals made open source for accessibility across computers I use, transparency, accountability, and versioning. Learn more about it [here](http://una.im/personal-goals-guide).

# Overarching Goals for ${date.format("YYYY")}:
### This year's focus: ${conf.get("yearlyfocus")}

${MDprint("yearly")}${MDprint("completed/yearly")}

# Weekly Goals ${date.format("MMM Do, YYYY")}:
### This week's focus: ${conf.get("weeklyfocus")}

${MDprint("weekly")}${MDprint("completed/weekly")}

# Monthly Goals ${date.format("MMMM YYYY")}:
### This month's focus: ${conf.get("monthlyfocus")}

${MDprint("monthly")}${MDprint("completed/monthly")}

# Other Goals:

${MDprint("other")}${MDprint("completed/other")}`;
  return res;
}

function MDprint(type, opts = {}) {
  const dir = conf.get("dir") + "/" + type;
  fs.ensureDirSync(dir);
  let res = "";
  const path = getFileName(type, "");
  const files = fs.readdirSync(path);
  if (!files.length) {
    fs.removeSync(path);
  }
  files.map(item => {
    if (!item.startsWith(".")) {
      const stats = fs.statSync(path + "/" + item);
      if (stats.isDirectory()) {
        if (item.match(/\w{3}\d{5,6}/g)) {
          opts.date = item;
        } else {
          res += `\n***${item}***\n`;
        }
        res += MDprint(type + "/" + item, opts);
      } else if (stats.isFile()) {
        if (!opts.hasOwnProperty("date")) {
          res += `* [ ] ${prettyName(item)}\n`;
        } else {
          res += `* [x] ${prettyName(item)} _- ${moment(
            opts.date,
            "MMMDYYYYHHmm"
          ).format("MMMM Do YYYY")}_\n`;
        }
      }
    }
  });
  return res;
}
<commit_msg>uses path.join instead of manual joining<commit_after>#!/usr/bin/env node
"use strict";

const fs = require("fs-extra");
const request = require("request");
const Menu = require("terminal-menu");
const moment = require("moment");
const Configstore = require("configstore");
const pkg = require("./package.json");
const path = require("path");

const conf = new Configstore(pkg.name, {
  dir: fs.realpathSync(__dirname),
  weeklyfocus: "Do good things this week",
  monthlyfocus: "Do good things this month",
  yearlyfocus: "Do good things this year"
});
const _ = require("lodash");
const chalk = require("chalk");

require("yargs")
  .command({
    command: "new [type] [goal]",
    aliases: ["n"],
    desc: "Set a new goal",
    example: "$0 n w 'work out 3 times'",
    builder: yargs => yargs.default("type", "w"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
      }
      newGoal(type, argv.goal);
    }
  })
  .command({
    command: "complete [type] [goal]",
    aliases: ["c"],
    desc: "mark a goal as completed",
    example: "$0 c w ",
    builder: yargs => yargs.default("type", "w"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
      }
      if (argv.goal) {
        completeGoal(type, argv.goal);
      } else {
        menu(type);
      }
    }
  })
  .command({
    command: "ls [type]",
    aliases: ["list"],
    usage: `$0 ls  <w, m, y, o, c, a>`,
    description: `list goals of a type`,
    builder: yargs => yargs.default("type", "a"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
        case "all":
        case "a":
          type = "all";
          break;
      }
      console.log(ls(type));
    }
  })
  .command({
    command: "clear [type]",
    aliases: ["clr"],
    usage: `$0 clear  <w, m, y, o, c, a>`,
    description: `clear goals of a type`,
    builder: yargs => yargs.default("type", "a"),
    handler: argv => {
      let type;
      switch (argv.type) {
        case "weekly":
        case "week":
        case "w":
          type = "weekly";
          break;
        case "monthly":
        case "month":
        case "m":
          type = "monthly";
          break;
        case "yearly":
        case "year":
        case "y":
          type = "yearly";
          break;
        case "other":
        case "o":
          type = "other";
          break;
        case "all":
        case "a":
          type = "all";
          break;
      }
      clear(type);
    }
  })
  .command({
    command: "config <key> [value]",
    aliases: ["cfg"],
    usage: `$0 config <key> [value]`,
    describe: "Set up the personal goals configuration",
    handler: argv => {
      if (argv.value === "clear") {
        conf.delete(argv.key);
      } else if (argv.key === "clear") {
        conf.clear();
      } else if (argv.key === "ls" || argv.key === "get") {
        console.log(conf.all);
      } else {
        conf.set(argv.key, argv.value);
        console.log("Successfully updated");
        console.log(`${chalk.bold(argv.key)}: ${conf.get(argv.key)}`);
      }
    }
  })
  .group("weekly (w)", "Types")
  .group("monthly (m)", "Types")
  .group("other (o)", "Types")
  .group("completed (c)", "Types")
  .group("all (a)", "Types")
  .example("ls", "$0 ls")
  .example("ls", "$0 ls complete")
  .example("ls", "$0 list all")
  .example("new", `$0 new w 'work out 3 times' `)
  .example("new", `$0 n m 'lose 5 pounds'`)
  .example("complete", "$0 c other")
  .example("complete", `$0 complete week 'work out 3 times'`)
  .example("config", "$0 cfg dir '/user/me/projects/personal-goals'")
  .example("config", `$0 config weeklyfocus 'get outside more'`)
  .example(
    "complete",
    "$0 config monthlyfocus 'punch as many nazis as possible'"
  )
  .example("config", `$0 cfg yearlyfocus 'destroy all nazis'`)
  .example("clear", "$0 clear all")
  .example("clear", `$0 clear weekly`)
  .help().argv;

writeMD();

function newGoal(type, goal) {
  const date = moment().format("MMMDYYYYHHmm");
  const file = getFileName(type, goal);
  const completedfile = getFileName(path.join("completed", type, date), goal);
  fs.ensureDirSync(path.join(conf.get("dir"), type));
  fs.stat(completedfile, (err, cstat) => {
    if (err == null) {
      console.log("Moving goal from completed to " + type);
      fs.moveSync(completedfile, file);
      console.log(ls(type));
    } else if (err.code == "ENOENT") {
      fs.stat(file, (err, stat) => {
        if (err == null) {
          console.log("Goal already exists");
        } else if (err.code == "ENOENT") {
          // File does not exist
          fs.closeSync(fs.openSync(file, "w"));
          console.log(ls("all"));
        } else {
          console.log("Some other error: ", err.code);
        }
      });
    }
  });
  writeMD();
}

function completeGoal(type, goal) {
  const date = moment().format("MMMDYYYYHHmm");
  const dir = conf.get("dir") + "/completed/" + type + "/" + date;
  fs.ensureDirSync(dir);
  fs.ensureDirSync(path.join(conf.get("dir"), type));
  fs.moveSync(
    getFileName(type, goal),
    getFileName(path.join("completed/", type, date), goal)
  );
  console.log(ls("all"));
  writeMD();
}

function getFileName(type, goal) {
  if (goal.length) {
    return path.join(
      conf.get("dir"),
      type,
      goal.replace(/[ ]/g, "_").replace(/[//]/g,"-")+".md"
    );
  }

  return path.join(conf.get("dir"), type);
}

function prettyName(file) {
  const goal = path.basename(file, path.extname(file));
  const ret = goal.replace(/_/g, " ").replace(/(\w)(\w*)/g, (_, i, r) => {
    return i.toUpperCase() + (r != null ? r : "");
  });
  return ret;
}

function menu(type) {
  const dir = getFileName(type, "");
  fs.ensureDirSync(dir);
  const files = fs.readdirSync(dir);
  const menu = Menu({ bg: "black", fg: "white" });

  menu.reset();
  menu.write("Which " + prettyName(type) + " Goal Did You Complete?\n");
  menu.write("-------------------------------------\n");
  files.map(item => menu.add(prettyName(item)));
  menu.add("None");

  menu.on("select", label => {
    menu.close();
    if (label === "None") {
      process.exit(0);
    }
    completeGoal(type, label);
  });
  process.stdin.pipe(menu.createStream()).pipe(process.stdout);

  process.stdin.setRawMode(true);
  menu.on("close", () => {
    process.stdin.setRawMode(false);
    process.stdin.end();
  });
}

function clear(type) {
  if (type === "all") {
    fs.removeSync(path.join(conf.get("dir"), "weekly"));
    fs.removeSync(path.join(conf.get("dir"), "monthly"));
    fs.removeSync(path.join(conf.get("dir"), "yearly"));
    fs.removeSync(path.join(conf.get("dir"), "other"));
    fs.removeSync(path.join(conf.get("dir"), "completed"));
  } else {
    fs.removeSync(path.join(conf.get("dir"), type));
  }
}

function ls(type) {
  let res = "";
  if (type === "all") {
    res += ls("weekly");
    res += ls("monthly");
    res += ls("yearly");
    res += ls("other");
  } else {
    const dir = conf.get("dir") + "/" + type;
    fs.ensureDir(dir);
    const title = prettyName(type) + " Tasks";
    res += "\n" + chalk.bold.underline(title) + "\n";
    res += print(type);
    if (type !== "completed") {
      res += print("completed/" + type);
    }
  }
  return res;
}

function print(type, opts = {}) {
  const dir = conf.get("dir") + "/" + type;
  fs.ensureDirSync(dir);
  let res = "";
  const files = fs.readdirSync(dir);
  if (!files.length) {
    fs.removeSync(dir);
  }
  files.map(item => {
    const stats = fs.statSync(dir + "/" + item);
    if (stats.isDirectory()) {
      if (item.match(/\w{3}\d{9,10}/g)) {
        if (moment(item, "MMMDYYYYHHmm").diff(moment(), "day") < -7) {
          /*fs.moveSync(
            path.join(dir, item),
            path.join(
              conf.get("dir"),
              "past",
              path
                .dirname(type)
                .split(path.delimiter)
                .pop()
            )
          );*/
          console.log(path.dirname(dir));
        }
        opts.date = item;
      } else {
        res += "\n" + chalk.underline(item) + "\n";
      }
      res += print(type + "/" + item, opts);
    } else if (stats.isFile()) {
      if (!opts.hasOwnProperty("date")) {
        if (!item.startsWith(".")) {
          res += prettyName(item) + "\n";
        }
      } else {
        res += `${chalk.green(prettyName(item))} ${chalk.gray(
          "- " + moment(opts.date, "MMMDYYYYHHmm").fromNow()
        )}\n`;
      }
    }
  });
  return res;
}

function writeMD() {
  fs.truncate(conf.get("dir") + "/README.md", 0, () => {
    fs.writeFile(conf.get("dir") + "/README.md", genMD(), err => {
      if (err) {
        return console.log("Error writing file: " + err);
      }
    });
  });
}

function genMD() {
  const date = moment().day(0);
  const res = `
Personal Goals
==============
Personal goals made open source for accessibility across computers I use, transparency, accountability, and versioning. Learn more about it [here](http://una.im/personal-goals-guide).

# Overarching Goals for ${date.format("YYYY")}:
### This year's focus: ${conf.get("yearlyfocus")}

${MDprint("yearly")}${MDprint("completed/yearly")}

# Weekly Goals ${date.format("MMM Do, YYYY")}:
### This week's focus: ${conf.get("weeklyfocus")}

${MDprint("weekly")}${MDprint("completed/weekly")}

# Monthly Goals ${date.format("MMMM YYYY")}:
### This month's focus: ${conf.get("monthlyfocus")}

${MDprint("monthly")}${MDprint("completed/monthly")}

# Other Goals:

${MDprint("other")}${MDprint("completed/other")}`;
  return res;
}

function MDprint(type, opts = {}) {
  const dir = conf.get("dir") + "/" + type;
  fs.ensureDirSync(dir);
  let res = "";
  const path = getFileName(type, "");
  const files = fs.readdirSync(path);
  if (!files.length) {
    fs.removeSync(path);
  }
  files.map(item => {
    if (!item.startsWith(".")) {
      const stats = fs.statSync(path + "/" + item);
      if (stats.isDirectory()) {
        if (item.match(/\w{3}\d{5,6}/g)) {
          opts.date = item;
        } else {
          res += `\n***${item}***\n`;
        }
        res += MDprint(type + "/" + item, opts);
      } else if (stats.isFile()) {
        if (!opts.hasOwnProperty("date")) {
          res += `* [ ] ${prettyName(item)}\n`;
        } else {
          res += `* [x] ${prettyName(item)} _- ${moment(
            opts.date,
            "MMMDYYYYHHmm"
          ).format("MMMM Do YYYY")}_\n`;
        }
      }
    }
  });
  return res;
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var Console = require("./console")
  , arg, options = {
      workDir: process.cwd()
    , consolePath: "/roil/"
    , port: 8913
    , debug: false
    }
  , args = process.argv.slice(2)
  , http = require("http")
  , server = http.createServer()
  , c = new Console()
  , helpMessage =
    [ "Usage: roil [options]"
    , "Options:"
    , "  -v, --version"
    , "    print version and exit"
    , ""
    , "  -p <port>, --port <port>"
    , "    port to listen, 8913 by default"
    , ""
    , "  -d <path>, --work-dir <path>"
    , "    document root for this HTTP server, cwd is used by default"
    , ""
    , "  -c <path>, --console-path <path>"
    , "    use a specific path for console, `/roil/' by default"
    , "    mostly you don't have to worry 'cuz \"roil\" is a strange name"
    , ""
    , "  -h, --help"
    , "    print this and exit"
    ].join("\n")

while (arg = args.shift()) {
  switch (arg) {
    case "-d":
    case "--work-dir":
      options.workDir = args.shift()
      break;
    case "-p":
    case "--port":
      options.port = parseInt(args.shift(), 10)
      break;
    case "-c":
    case "--console-path":
      options.consolePath = args.shift()
      break;
    case "--debug":
      options.debug = true
      break;
    case "-v":
    case "--version":
      console.log("roil v0.1.0")
      process.exit()
    case "-h":
    case "--help":
      console.log(helpMessage)
      process.exit(1)
    default:
      throw new Error("Unknown argument: " + arg)
  }
}

c.attach(server, options)
server.listen(options.port)

console.log(
  "Roil server started on http://localhost:"
+ options.port
+ options.consolePath
)
console.log(
  "Document root is"
, options.workDir
)

if (options.debug) {
  console.log(options)
  var context = require("repl").start().context
  context.c = c
  context.s = server
  c._socketListener.on("connection", function(client) {
    client.on("message", function(msg) {
      console.log(msg)
    })
  })
  process.on("uncaughtException", function(e) {
    console.log(e.stack || e.message)
  })
}
<commit_msg>-b to launch browsers<commit_after>#!/usr/bin/env node
var Console = require("./console")
  , arg, options = {
      workDir: process.cwd()
    , consolePath: "/roil/"
    , port: 8913
    , debug: false
    , browserBins: []
    }
  , args = process.argv.slice(2)
  , http = require("http")
  , exec = require("child_process").exec
  , server = http.createServer()
  , c = new Console()
  , helpMessage =
    [ "Usage: roil [options]"
    , "Options:"
    , "  -v, --version"
    , "    print version and exit"
    , ""
    , "  -p <port>, --port <port>"
    , "    port to listen, 8913 by default"
    , ""
    , "  -b <bin>, --launch-browser <bin>"
    , "    launch browser(s) to open console path"
    , ""
    , "  -d <path>, --work-dir <path>"
    , "    document root for this HTTP server, cwd is used by default"
    , ""
    , "  -c <path>, --console-path <path>"
    , "    use a specific path for console, `/roil/' by default"
    , "    mostly you don't have to worry 'cuz \"roil\" is a strange name"
    , ""
    , "  -h, --help"
    , "    print this and exit"
    ].join("\n")

while (arg = args.shift()) {
  switch (arg) {
    case "-d":
    case "--work-dir":
      options.workDir = args.shift()
      break;
    case "-p":
    case "--port":
      options.port = parseInt(args.shift(), 10)
      break;
    case "-c":
    case "--console-path":
      options.consolePath = args.shift()
      break;
    case "-b":
    case "--launch-browser":
      options.browserBins.push(args.shift())
      break;
    case "--debug":
      options.debug = true
      break;
    case "-v":
    case "--version":
      console.log("roil v0.1.0")
      process.exit()
    case "-h":
    case "--help":
      console.log(helpMessage)
      process.exit(1)
    default:
      console.log("Unknown argument:", arg)
      process.exit(1)
  }
}

c.attach(server, options)
server.listen(options.port)

var consolePath = "http://localhost:" + options.port + options.consolePath

options.browserBins.forEach(function(bin) {
  exec(bin + " " + consolePath, function(err) {
    if (err) console.error(err.message)
    else console.log("Lauched browser", bin)
  })
})

console.log(
  "Roil server started on"
, consolePath
)
console.log(
  "Document root is"
, options.workDir
)

if (options.debug) {
  console.log(options)
  var context = require("repl").start().context
  context.c = c
  context.s = server
  c._socketListener.on("connection", function(client) {
    client.on("message", function(msg) {
      console.log(msg)
    })
  })
  process.on("uncaughtException", function(e) {
    console.log(e.stack || e.message)
  })
}
<|endoftext|>