<commit_before>// MISC java things we'll need in a few lines
var SimpleDateFormat        = Java.type("java.text.SimpleDateFormat");
var OracleCallableStatement = Java.type("oracle.jdbc.OracleCallableStatement");
var OracleTypes             = Java.type("oracle.jdbc.OracleTypes");
var BigDecimal              = Java.type("java.math.BigDecimal");
var CopyOption              = Java.type("java.nio.file.StandardCopyOption");
var Charset                 = Java.type("java.nio.charset.Charset")
var BufferedReader          = Java.type("java.io.BufferedReader")
function ApexImport()  {
    this.CmdName = "apximp";

    this.sql = {
    // various SQL we'll need later
          wsID :    "begin apex_application_install.SET_WORKSPACE_ID(   P_WORKSPACE_ID   =>  :workspaceID ); end;",
          appID:    "begin apex_application_install.SET_APPLICATION_ID(   P_APPLICATION_ID   =>  :appID); end;",
          offset :  "begin apex_application_install.SET_OFFSET(   P_OFFSET   =>  :offset ); end;",
          schema :  "begin apex_application_install.SET_SCHEMA(   P_SCHEMA   =>  :schema ); end;",
          appName:  "begin apex_application_install.SET_APPLICATION_NAME(   P_APPLICATION_NAME   =>  :appName  ); end;",
          appAlias: "begin     apex_application_install.SET_APPLICATION_ALIAS(   P_APPLICATION_ALIAS   =>  :appAlias); end;",
          proxy:       "begin     apex_application_install.SET_PROXY(   P_PROXY   =>  :proxy  ); end;",
          supportObjs: "begin     apex_application_install.SET_AUTO_INSTALL_SUP_OBJ(   P_AUTO_INSTALL_SUP_OBJ   =>  :supportingObjects); end;",
          appFiles:    "begin     apex_application_install.SET_STATIC_APP_FILE_PREFIX(   P_FILE_PREFIX   =>  :appFilePrefix  ); end;",
          themeFiles:  "begin     apex_application_install.SET_STATIC_THEME_FILE_PREFIX(   P_THEME_NUMBER   =>  :themeNumber ,P_FILE_PREFIX    =>  :themeFilePrefix );  end;",
          pluginFiles: "begin     apex_application_install.SET_STATIC_PLUGIN_FILE_PREFIX(   P_PLUGIN_TYPE   =>  :pluginType  ,P_PLUGIN_NAME   =>  :pluginName  ,  P_FILE_PREFIX   =>  :pluginFilePrefix); end;",
          appImagePrefix: "begin     apex_application_install.SET_IMAGE_PREFIX(   P_IMAGE_PREFIX   =>  :imgPrefix ); end;",
          details :"select apex_application_install.get_application_id \"Application ID\", " +
                   " apex_application_install.get_workspace_id \"Workspace ID\", " +
                   " apex_application_install.get_offset  \"Offset\", " +
                   " apex_application_install.get_schema   \"Parsing Schema\", " +
                   " apex_application_install.get_application_name \"Application Name\", " +
                   " apex_application_install.get_application_alias \"Application Alias\", " +
                   " apex_application_install.get_image_prefix \"Image Prefix\", " +
                   " apex_application_install.get_proxy  \"Proxy\", " +
                   " apex_application_install.get_static_app_file_prefix \"App File Prefix\" " +
            " from dual"
    };

    // hold all command line options
    this.options={};

    //
    // Get the cmd line args
    //
    this.setVarsFromArgs = function(args){
            if ( args!=null && args.length == 0){ this.usage();return false;}
            for (var i = 0; i < args.length; i++) {
                this.debug('Param:' + args[i])
                if ( args[i].equalsIgnoreCase(this.CmdName)) {
                    // just skip it.
                  } else if (args[i].equalsIgnoreCase("-file")) {
                      this.options.fileName = args[++i];
                } else if (args[i].equalsIgnoreCase("-workspaceid")) {
                    this.options.workspaceID = args[++i];
                } else if (args[i].equalsIgnoreCase("-applicationid")) {
                    this.options.appID = args[++i];
                } else if (args[i].equalsIgnoreCase("-debug")) {
                    this.options.gDebug = true;
                } else if (args[i].equalsIgnoreCase("-offset")) {
                    this.options.offset = args[++i];
                } else if (args[i].equalsIgnoreCase("-schema")) {
                    this.options.schema = args[++i];
                } else if (args[i].equalsIgnoreCase("-name")) {
                    this.options.appName = args[++i];
                } else if (args[i].equalsIgnoreCase("-alias")) {
                    this.options.appAlias = args[++i];
                } else if (args[i].equalsIgnoreCase("-imagePrefix")) {
                    this.options.imgPrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-appFilePrefix")) {
                    this.options.appFilePrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-themeFilePrefix")) {
                    this.options.themeNumber = args[++i];
                    this.options.themeFilePrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-pluginFilePrefix")) {
                    this.options.pluginType = args[++i];
                    this.options.pluginName = args[++i];
                    this.options.pluginFilePrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-proxy")) {
                    this.options.proxy = args[++i];
                } else if (args[i].equalsIgnoreCase("-installSupportingObjects")) {
                    this.options.supportingObjects = true;
                } else {
                    this.usage();
                    ctx.write("\nUnknown Option :" + args[i] + "\n")
                    return false; // return false to signal not to continue
                }
            }
            if ( ! this.options.fileName ){
                ctx.write("\nNO FILE SPECIFIED TO IMPORT\n");
                this.usage();
                ctx.write("\n")
              return false;
            }
            return true; // all is good all args processed
    }

    this.usage = function(){
            ctx.write("\nUsage "+this.CmdName+" -file [file name] [options]  \n");
            ctx.write("   -file                       APEX Export file to import. ONLY REQUIRED OPTION. \n");
            ctx.write("   -workspaceid                Workspace ID to import application into \n");
            ctx.write("   -applicationid              New Application ID or AUTO for a new generated ID \n");
            ctx.write("   -offset                     Specify the offset to be using during import \n");
            ctx.write("   -schema                     Change the PARSE_AS schema of the application \n");
            ctx.write("   -name                       Change the name of the application \n");
            ctx.write("   -alias                      Change the alias of the application \n");
            ctx.write("   -imagePrefix                Change the image prefix used in the application \n");
            ctx.write("   -appFilePrefix              Change the Application Static file prefix used in the application \n");
            ctx.write("   -themeFilePrefix            Change the Theme file prefix used in the application \n");
            ctx.write("         Example: -themeFilePrefix number prefix \n");
            ctx.write("   -pluginFilePrefix           Change the Plugin file prefix used in the application \n");
            ctx.write("         Example: -pluginFilePrefix type name prefix \n");
            ctx.write("   -proxy                      Change the proxy used by the application \n");
            ctx.write("   -installSupportingObjects   Specify to install supporting objects \n");
            ctx.write("   -debug                      Print debug messages \n");
            ctx.write("  \n");
            ctx.write("    Application Example: \n");
            ctx.write("       "+this.CmdName+"  -applicationid 31500 \n");
            ctx.write("       "+this.CmdName+"  -applicationid AUTO \n");
            ctx.write("    Offset  Example: \n");
            ctx.write("       "+this.CmdName+" -offset -123 \n");
            ctx.write("    Schema Example:\n");
            ctx.write("       "+this.CmdName+"  -schema KLRICE \n");
            ctx.write("    Application Name:\n");
            ctx.write("       "+this.CmdName+" -name MyApp\n");
            ctx.write(" \n");
            ctx.write(" SQLcl Scripting Example:\n");
            ctx.write(" \n");
            ctx.write("    script  \n");
            ctx.write("       var a = new ApexImpport();\n");
            ctx.write("       var myoptions = ['-applicationid','123'];\n");
            ctx.write("       a.run(myoptions);\n");
            ctx.write("   /\n");
    }

    this.debug=function (str){
        if ( this.options.gDebug ) { ctx.write("\n>>>"+str+"\n"); out.flush();}
    }

    this.printOptions = function(args){
      var ret = util.executeReturnList(this.sql.details,this.options);
      this.debug('Tried>>' + this.sql.details);
      this.debug('Got>>' + ret);
      ctx.write("** Importing with the following options **\n")
      if ( ret && ret.length == 1) {
          var it = ret[0].keySet().iterator();
          while(it.hasNext()){
            var key = it.next();
            var value = ret[0].get(key);
            if ( value ){
              ctx.write(key + "\t:" + value + "\n");
            }
          }
        }
      ctx.write("****\n")
    }
//
// main method
//
    this.run = function(args){
        // get the user once as it's used a few times/places
        var userName = util.executeReturnOneCol('select user from dual' )

        // process the args and place into the options
        if ( ! this.setVarsFromArgs(args) ) {
            return;
        }
        // debug of what was passed
        this.debug("\nRunning with Flags set:\n\t" + JSON.stringify(this.options) + "\n");
            if ( this.options.workspaceID ) {
              util.execute(this.sql.wsID,this.options);
            } else {
              // get the default workspace ( lowest WorkSpace ID with this schema assigned )
              var bind = {};
              bind.workspaceID = util.executeReturnOneCol('select min(workspace_id) wsID  from  apex_workspace_schemas where schema = user' )
              util.execute(this.sql.wsID,bind);
              var  name = util.executeReturnOneCol('select workspace_name from  apex_workspace_schemas where WORKSPACE_ID = :workspaceID' , bind)
              this.options.wsID = bind.wsID;

              ctx.write('*** USING DEFAULT WORKSPACE *** \n');
              ctx.write('*** '+name+' *** \n');

            }
            if (this.options.appID ){
              util.execute(this.sql.appID,this.options);
            }
            if ( this.options.offset ){
              util.execute(this.sql.offset,this.options);
            }
            if ( this.options.schema) {
              util.execute(this.sql.schema,this.options);
            }
            if ( this.options.appName ){
              util.execute(this.sql.appName,this.options);
            }
            if ( this.options.appAlias ){
              util.execute(this.sql.appAlias,this.options);
            }
            if ( this.options.imgPrefix ){
              util.execute(this.sql.appImagePrefix,this.options);
            }
            if( this.options.appFilePrefix ){
              util.execute(this.sql.appFiles,this.options);
            }
            if ( this.options.themeNumber &&
                 this.options.themeFilePrefix ) {
                   util.execute(this.sql.themeFiles,this.options);
                 }

            if ( this.options.pluginType &&
                 this.options.pluginName &&
                 this.options.pluginFilePrefix ) {
                   util.execute(this.sql.pluginFiles,this.options);
                 }
            if ( this.options.proxy ) {
              util.execute(this.sql.proxy,this.options);
            }
            if ( this.options.supportingObjects) {
              util.execute(this.sql.supportObjs,this.options);
            }
        this.printOptions();
        ctx.write('\n')
        out.flush();
        sqlcl.setStmt("prompt running...@" + this.options.fileName);
        sqlcl.run();
        sqlcl.setStmt("@" + this.options.fileName);
        sqlcl.run();
        ctx.write("\n")
    }

};

//
//  Now to install the Command into SQLcl
//
// SQLCL's Command Registry
var CommandRegistry = Java.type("oracle.dbtools.raptor.newscriptrunner.CommandRegistry");

// CommandListener for creating any new command
var CommandListener =  Java.type("oracle.dbtools.raptor.newscriptrunner.CommandListener")

// Broke the .js out from the Java.extend to be easier to read
var cmd = {};

// Called to attempt to handle any command
cmd.handle = function (conn,ctx,cmd) {
  if ( cmd.getSql().trim().startsWith("apximp") ) {
    // split the arguments
    args = cmd.getSql().trim().split(/\s+/);

    // is the first arg a number
    var ai = new ApexImport();
    ai.run(args);
    return true;
  }
   return false;
}

// fired before ANY command
cmd.begin = function (conn,ctx,cmd) {
}

// fired after ANY Command
cmd.end = function (conn,ctx,cmd) {
}

// Actual Extend of the Java CommandListener

var APEXImportCommand = Java.extend(CommandListener, {
        handleEvent:    cmd.handle ,
        beginEvent:     cmd.begin  ,
        endEvent:       cmd.end
});

// Registering the new Command
CommandRegistry.addForAllStmtsListener(APEXImportCommand.class);

/*
script
var a = new ApexImport();
var myoptions = ["-file","f102.sql","-offset","123","-name","Kris","-alias","rice","-installSupportingObjects" ];
a.run(myoptions);
/

*/
<commit_msg>-applicationid AUTO fixed<commit_after>// MISC java things we'll need in a few lines
var SimpleDateFormat        = Java.type("java.text.SimpleDateFormat");
var OracleCallableStatement = Java.type("oracle.jdbc.OracleCallableStatement");
var OracleTypes             = Java.type("oracle.jdbc.OracleTypes");
var BigDecimal              = Java.type("java.math.BigDecimal");
var CopyOption              = Java.type("java.nio.file.StandardCopyOption");
var Charset                 = Java.type("java.nio.charset.Charset")
var BufferedReader          = Java.type("java.io.BufferedReader")
function ApexImport()  {
    this.CmdName = "apximp";

    this.sql = {
    // various SQL we'll need later
          wsID :    "begin apex_application_install.SET_WORKSPACE_ID(   P_WORKSPACE_ID   =>  :workspaceID ); end;",
          appID:    "begin apex_application_install.SET_APPLICATION_ID(   P_APPLICATION_ID   =>  :appID); end;",
          appGenID : "begin apex_application_install.GENERATE_APPLICATION_ID(); end;",
          offset :  "begin apex_application_install.SET_OFFSET(   P_OFFSET   =>  :offset ); end;",
          schema :  "begin apex_application_install.SET_SCHEMA(   P_SCHEMA   =>  :schema ); end;",
          appName:  "begin apex_application_install.SET_APPLICATION_NAME(   P_APPLICATION_NAME   =>  :appName  ); end;",
          appAlias: "begin     apex_application_install.SET_APPLICATION_ALIAS(   P_APPLICATION_ALIAS   =>  :appAlias); end;",
          proxy:       "begin     apex_application_install.SET_PROXY(   P_PROXY   =>  :proxy  ); end;",
          supportObjs: "begin     apex_application_install.SET_AUTO_INSTALL_SUP_OBJ(   P_AUTO_INSTALL_SUP_OBJ   =>  :supportingObjects); end;",
          appFiles:    "begin     apex_application_install.SET_STATIC_APP_FILE_PREFIX(   P_FILE_PREFIX   =>  :appFilePrefix  ); end;",
          themeFiles:  "begin     apex_application_install.SET_STATIC_THEME_FILE_PREFIX(   P_THEME_NUMBER   =>  :themeNumber ,P_FILE_PREFIX    =>  :themeFilePrefix );  end;",
          pluginFiles: "begin     apex_application_install.SET_STATIC_PLUGIN_FILE_PREFIX(   P_PLUGIN_TYPE   =>  :pluginType  ,P_PLUGIN_NAME   =>  :pluginName  ,  P_FILE_PREFIX   =>  :pluginFilePrefix); end;",
          appImagePrefix: "begin     apex_application_install.SET_IMAGE_PREFIX(   P_IMAGE_PREFIX   =>  :imgPrefix ); end;",
          details :"select apex_application_install.get_application_id \"Application ID\", " +
                   " apex_application_install.get_workspace_id \"Workspace ID\", " +
                   " apex_application_install.get_offset  \"Offset\", " +
                   " apex_application_install.get_schema   \"Parsing Schema\", " +
                   " apex_application_install.get_application_name \"Application Name\", " +
                   " apex_application_install.get_application_alias \"Application Alias\", " +
                   " apex_application_install.get_image_prefix \"Image Prefix\", " +
                   " apex_application_install.get_proxy  \"Proxy\", " +
                   " apex_application_install.get_static_app_file_prefix \"App File Prefix\" " +
            " from dual"
    };

    // hold all command line options
    this.options={};

    //
    // Get the cmd line args
    //
    this.setVarsFromArgs = function(args){
            if ( args!=null && args.length == 0){ this.usage();return false;}
            for (var i = 0; i < args.length; i++) {
                this.debug('Param:' + args[i])
                if ( args[i].equalsIgnoreCase(this.CmdName)) {
                    // just skip it.
                  } else if (args[i].equalsIgnoreCase("-file")) {
                      this.options.fileName = args[++i];
                } else if (args[i].equalsIgnoreCase("-workspaceid")) {
                    this.options.workspaceID = args[++i];
                } else if (args[i].equalsIgnoreCase("-applicationid")) {
                    this.options.appID = args[++i];
                } else if (args[i].equalsIgnoreCase("-debug")) {
                    this.options.gDebug = true;
                } else if (args[i].equalsIgnoreCase("-offset")) {
                    this.options.offset = args[++i];
                } else if (args[i].equalsIgnoreCase("-schema")) {
                    this.options.schema = args[++i];
                } else if (args[i].equalsIgnoreCase("-name")) {
                    this.options.appName = args[++i];
                } else if (args[i].equalsIgnoreCase("-alias")) {
                    this.options.appAlias = args[++i];
                } else if (args[i].equalsIgnoreCase("-imagePrefix")) {
                    this.options.imgPrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-appFilePrefix")) {
                    this.options.appFilePrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-themeFilePrefix")) {
                    this.options.themeNumber = args[++i];
                    this.options.themeFilePrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-pluginFilePrefix")) {
                    this.options.pluginType = args[++i];
                    this.options.pluginName = args[++i];
                    this.options.pluginFilePrefix = args[++i];
                } else if (args[i].equalsIgnoreCase("-proxy")) {
                    this.options.proxy = args[++i];
                } else if (args[i].equalsIgnoreCase("-installSupportingObjects")) {
                    this.options.supportingObjects = true;
                } else {
                    this.usage();
                    ctx.write("\nUnknown Option :" + args[i] + "\n")
                    return false; // return false to signal not to continue
                }
            }
            if ( ! this.options.fileName ){
                ctx.write("\nNO FILE SPECIFIED TO IMPORT\n");
                this.usage();
                ctx.write("\n")
              return false;
            }
            return true; // all is good all args processed
    }

    this.usage = function(){
            ctx.write("\nUsage "+this.CmdName+" -file [file name] [options]  \n");
            ctx.write("   -file                       APEX Export file to import. ONLY REQUIRED OPTION. \n");
            ctx.write("   -workspaceid                Workspace ID to import application into \n");
            ctx.write("   -applicationid              New Application ID or AUTO for a new generated ID \n");
            ctx.write("   -offset                     Specify the offset to be using during import \n");
            ctx.write("   -schema                     Change the PARSE_AS schema of the application \n");
            ctx.write("   -name                       Change the name of the application \n");
            ctx.write("   -alias                      Change the alias of the application \n");
            ctx.write("   -imagePrefix                Change the image prefix used in the application \n");
            ctx.write("   -appFilePrefix              Change the Application Static file prefix used in the application \n");
            ctx.write("   -themeFilePrefix            Change the Theme file prefix used in the application \n");
            ctx.write("         Example: -themeFilePrefix number prefix \n");
            ctx.write("   -pluginFilePrefix           Change the Plugin file prefix used in the application \n");
            ctx.write("         Example: -pluginFilePrefix type name prefix \n");
            ctx.write("   -proxy                      Change the proxy used by the application \n");
            ctx.write("   -installSupportingObjects   Specify to install supporting objects \n");
            ctx.write("   -debug                      Print debug messages \n");
            ctx.write("  \n");
            ctx.write("    Application Example: \n");
            ctx.write("       "+this.CmdName+"  -applicationid 31500 \n");
            ctx.write("       "+this.CmdName+"  -applicationid AUTO \n");
            ctx.write("    Offset  Example: \n");
            ctx.write("       "+this.CmdName+" -offset -123 \n");
            ctx.write("    Schema Example:\n");
            ctx.write("       "+this.CmdName+"  -schema KLRICE \n");
            ctx.write("    Application Name:\n");
            ctx.write("       "+this.CmdName+" -name MyApp\n");
            ctx.write(" \n");
            ctx.write(" SQLcl Scripting Example:\n");
            ctx.write(" \n");
            ctx.write("    script  \n");
            ctx.write("       var a = new ApexImpport();\n");
            ctx.write("       var myoptions = ['-applicationid','123'];\n");
            ctx.write("       a.run(myoptions);\n");
            ctx.write("   /\n");
    }

    this.debug=function (str){
        if ( this.options.gDebug ) { ctx.write("\n>>>"+str+"\n"); out.flush();}
    }

    this.printOptions = function(args){
      var ret = util.executeReturnList(this.sql.details,this.options);
      this.debug('Tried>>' + this.sql.details);
      this.debug('Got>>' + ret);
      ctx.write("** Importing with the following options **\n")
      if ( ret && ret.length == 1) {
          var it = ret[0].keySet().iterator();
          while(it.hasNext()){
            var key = it.next();
            var value = ret[0].get(key);
            if ( value ){
              ctx.write(key + "\t:" + value + "\n");
            }
          }
        }
      ctx.write("****\n")
    }
//
// main method
//
    this.run = function(args){
        // get the user once as it's used a few times/places
        var userName = util.executeReturnOneCol('select user from dual' )

        // process the args and place into the options
        if ( ! this.setVarsFromArgs(args) ) {
            return;
        }
        // debug of what was passed
        this.debug("\nRunning with Flags set:\n\t" + JSON.stringify(this.options) + "\n");
            if ( this.options.workspaceID ) {
              util.execute(this.sql.wsID,this.options);
            } else {
              // get the default workspace ( lowest WorkSpace ID with this schema assigned )
              var bind = {};
              bind.workspaceID = util.executeReturnOneCol('select min(workspace_id) wsID  from  apex_workspace_schemas where schema = user' )
              util.execute(this.sql.wsID,bind);
              var  name = util.executeReturnOneCol('select workspace_name from  apex_workspace_schemas where WORKSPACE_ID = :workspaceID' , bind)
              this.options.wsID = bind.wsID;

              ctx.write('*** USING DEFAULT WORKSPACE *** \n');
              ctx.write('*** '+name+' *** \n');

            }
            if (this.options.appID ){
              if (this.options.appID.equals('AUTO') ) {
                util.execute(this.sql.appGenID,this.options);
              } else {
                util.execute(this.sql.appID,this.options);
              }
            }
            if ( this.options.offset ){
              util.execute(this.sql.offset,this.options);
            }
            if ( this.options.schema) {
              util.execute(this.sql.schema,this.options);
            }
            if ( this.options.appName ){
              util.execute(this.sql.appName,this.options);
            }
            if ( this.options.appAlias ){
              util.execute(this.sql.appAlias,this.options);
            }
            if ( this.options.imgPrefix ){
              util.execute(this.sql.appImagePrefix,this.options);
            }
            if( this.options.appFilePrefix ){
              util.execute(this.sql.appFiles,this.options);
            }
            if ( this.options.themeNumber &&
                 this.options.themeFilePrefix ) {
                   util.execute(this.sql.themeFiles,this.options);
                 }

            if ( this.options.pluginType &&
                 this.options.pluginName &&
                 this.options.pluginFilePrefix ) {
                   util.execute(this.sql.pluginFiles,this.options);
                 }
            if ( this.options.proxy ) {
              util.execute(this.sql.proxy,this.options);
            }
            if ( this.options.supportingObjects) {
              util.execute(this.sql.supportObjs,this.options);
            }
        this.printOptions();
        ctx.write('\n')
        out.flush();
        sqlcl.setStmt("prompt running...@" + this.options.fileName);
        sqlcl.run();
        sqlcl.setStmt("@" + this.options.fileName);
        sqlcl.run();
        ctx.write("\n")
    }

};

//
//  Now to install the Command into SQLcl
//
// SQLCL's Command Registry
var CommandRegistry = Java.type("oracle.dbtools.raptor.newscriptrunner.CommandRegistry");

// CommandListener for creating any new command
var CommandListener =  Java.type("oracle.dbtools.raptor.newscriptrunner.CommandListener")

// Broke the .js out from the Java.extend to be easier to read
var cmd = {};

// Called to attempt to handle any command
cmd.handle = function (conn,ctx,cmd) {
  if ( cmd.getSql().trim().startsWith("apximp") ) {
    // split the arguments
    args = cmd.getSql().trim().split(/\s+/);

    // is the first arg a number
    var ai = new ApexImport();
    ai.run(args);
    return true;
  }
   return false;
}

// fired before ANY command
cmd.begin = function (conn,ctx,cmd) {
}

// fired after ANY Command
cmd.end = function (conn,ctx,cmd) {
}

// Actual Extend of the Java CommandListener

var APEXImportCommand = Java.extend(CommandListener, {
        handleEvent:    cmd.handle ,
        beginEvent:     cmd.begin  ,
        endEvent:       cmd.end
});

// Registering the new Command
CommandRegistry.addForAllStmtsListener(APEXImportCommand.class);

/*
script
var a = new ApexImport();
var myoptions = ["-expWorkspace","-replace"];
a.run(myoptions);
/

*/
<|endoftext|>


<commit_before>module.exports = function (opts) {
    if (!opts) opts = {};
    if (opts.bark === undefined) opts.bark = 1;
    if (opts.leaves === undefined) opts.leaves = 2;
    if (opts.random == undefined) opts.random = function() { return Math.random(); };
    if (!opts.height) opts.height = opts.random() * 16 + 4;
    if (opts.base === undefined) opts.base = opts.height / 3;
    if (opts.radius === undefined) opts.radius = opts.base;
    if (opts.treeType === undefined) opts.treeType = 'subspace';
    if (opts.position === undefined) throw "voxel-trees requires position option";
    if (opts.setBlock === undefined) throw "voxel-trees requires setBlock option";

    var set = opts.setBlock;

    var generators = {
    subspace: function() {
        var around = [
        [ 0, 1 ], [ 0, -1 ],
        [ 1, 1 ], [ 1, 0 ], [ 1, -1 ],
        [ -1, 1 ], [ -1, 0 ], [ -1, -1 ]
        ];
        for (var y = 0; y < opts.height - 1; y++) {
            var pos = [opts.position.x, opts.position.y, opts.position.z];
            pos[1] += y
            if (set(pos, opts.bark)) break;
            if (y < opts.base) continue;
            around.forEach(function (offset) {
                if (opts.random() > 0.5) return;
                var x = offset[0]
                var z = offset[1]
                pos[0] += x;
                pos[2] += z;
                set(pos, opts.leaves);
                pos[0] -= x;
                pos[2] -= z;
            });
        }
    },

    guybrush: function() {
        var sphere = function(x,y,z, r) {
            return x*x + y*y + z*z <= r*r;
        }
        for (var y = 0; y < opts.height - 1; y++) {
            var pos = [opts.position.x, opts.position.y, opts.position.z];
            pos[1] += y;
            if (set(pos, opts.bark)) break;
        }
        var radius = opts.radius;
        for (var xstep = -radius; xstep <= radius; xstep++) {
            for (var ystep = -radius; ystep <= radius; ystep++) {
                for (var zstep = -radius; zstep <= radius; zstep++) {
                    if (sphere(xstep,ystep,zstep, radius)) {
                        var leafpos = [
                            pos[0] + xstep,
                            pos[1] + ystep,
                            pos[2] + zstep
                        ]
                        set(leafpos, opts.leaves);
                    }
                }
            }
        }
    },

    fractal: function() {
        function drawAxiom(axiom, angle, unitsize, units) {
            var posstack = [];

            var penangle = 0;
            var pos = [opts.position.x, opts.position.y, opts.position.z];
            pos[1] += unitsize * 30;
            function moveForward() {
                var ryaw = penangle * Math.PI/180;
                for (var i = 0; i < units; i++) {
                    pos[1] += unitsize * Math.cos(ryaw);
                    pos[2] += unitsize * Math.sin(ryaw);
                    set(pos,opts.leaves);
                }
            }

            function setPoint() {
                set(pos, opts.bark);
            }
            function setMaterial(value) {
                mindex = value;
            }
            function yaw(angle) {
                penangle += angle;
            }
            function pitch(angle) {
                //turtle.pitch += angle;
            }
            function roll(angle) {
                //turtle.roll += angle;
            }
            function PushState() {
                //penstack.push(turtle);
                posstack.push(pos);
            }
            function PopState() {
              //  turtle = penstack.pop();
                pos = posstack.pop();
            }

            //F  - move forward one unit with the pen down
            //G  - move forward one unit with the pen up
            //#  - Changes draw medium.

            // +  - yaw the turtle right by angle parameter
            // -  - yaw the turtle left by angle parameter
            // &  - pitch the turtle down by angle parameter
            // ^  - pitch the turtle up by angle parameter
            // /  - roll the turtle to the right by angle parameter
            // *  - roll the turtle to the left by angle parameter
            // [  - save in stack current state info
            // ]  - recover from stack state info
            for (var i = 0; i < axiom.length; i++) {
                var c = axiom.charAt(i);
                switch(c) {
                    case 'F':
                        moveForward();
                        setPoint();
                        break;
                    case '+':
                        yaw(+angle);
                        break;
                    case '-':
                        yaw(-angle);
                        break;
                    case '&':
                        pitch(+angle);
                        break;
                    case '^':
                        pitch(-angle);
                        break;
                    case '/':
                        roll(+angle);
                        break;
                    case '*':
                        roll(-angle);
                        break;
                    case 'G':
                        moveForward();
                        break;
                    case '[':
                        PushState();
                        break;
                    case ']':
                        PopState();
                        break;
                    case '0':
                        setMaterial(0);
                        break;
                    case '1':
                        setMaterial(1);
                        break;
                    case '2':
                        setMaterial(2);
                        break;
                    case '3':
                        setMaterial(3);
                        break;

                }
            }
        }

        var axiom = "FX";
        var rules = [ ["X", "X+YF+"], ["Y", "-FX-Y"]];
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        drawAxiom(axiom, 90, 1, 5);
    }
    };

    if (!generators[opts.treeType]) throw 'voxel-trees invalid treeType: ' + opts.treeType;

    generators[opts.treeType]();
};

function regexRules(rules) {
    var regexrule = '';
    rules.forEach(function (rule) {
        if (regexrule != '') {
            regexrule = regexrule+ '|' ;
        }
        regexrule = regexrule+rule[0];
    });
    return new RegExp(regexrule, "g");
}

function applyRules(axiom, rules) {
    function matchRule(match)
    {
        for (var i=0;i<rules.length;i++)
        {
            if (rules[i][0] == match) return rules[i][1];
        }
        return '';
    }
    return axiom.replace(regexRules(rules), matchRule);
}
<commit_msg>Throw new Error, not string<commit_after>module.exports = function (opts) {
    if (!opts) opts = {};
    if (opts.bark === undefined) opts.bark = 1;
    if (opts.leaves === undefined) opts.leaves = 2;
    if (opts.random == undefined) opts.random = function() { return Math.random(); };
    if (!opts.height) opts.height = opts.random() * 16 + 4;
    if (opts.base === undefined) opts.base = opts.height / 3;
    if (opts.radius === undefined) opts.radius = opts.base;
    if (opts.treeType === undefined) opts.treeType = 'subspace';
    if (opts.position === undefined) throw new Error('voxel-trees requires position option');
    if (opts.setBlock === undefined) throw new Error('voxel-trees requires setBlock option');

    var set = opts.setBlock;

    var generators = {
    subspace: function() {
        var around = [
        [ 0, 1 ], [ 0, -1 ],
        [ 1, 1 ], [ 1, 0 ], [ 1, -1 ],
        [ -1, 1 ], [ -1, 0 ], [ -1, -1 ]
        ];
        for (var y = 0; y < opts.height - 1; y++) {
            var pos = [opts.position.x, opts.position.y, opts.position.z];
            pos[1] += y
            if (set(pos, opts.bark)) break;
            if (y < opts.base) continue;
            around.forEach(function (offset) {
                if (opts.random() > 0.5) return;
                var x = offset[0]
                var z = offset[1]
                pos[0] += x;
                pos[2] += z;
                set(pos, opts.leaves);
                pos[0] -= x;
                pos[2] -= z;
            });
        }
    },

    guybrush: function() {
        var sphere = function(x,y,z, r) {
            return x*x + y*y + z*z <= r*r;
        }
        for (var y = 0; y < opts.height - 1; y++) {
            var pos = [opts.position.x, opts.position.y, opts.position.z];
            pos[1] += y;
            if (set(pos, opts.bark)) break;
        }
        var radius = opts.radius;
        for (var xstep = -radius; xstep <= radius; xstep++) {
            for (var ystep = -radius; ystep <= radius; ystep++) {
                for (var zstep = -radius; zstep <= radius; zstep++) {
                    if (sphere(xstep,ystep,zstep, radius)) {
                        var leafpos = [
                            pos[0] + xstep,
                            pos[1] + ystep,
                            pos[2] + zstep
                        ]
                        set(leafpos, opts.leaves);
                    }
                }
            }
        }
    },

    fractal: function() {
        function drawAxiom(axiom, angle, unitsize, units) {
            var posstack = [];

            var penangle = 0;
            var pos = [opts.position.x, opts.position.y, opts.position.z];
            pos[1] += unitsize * 30;
            function moveForward() {
                var ryaw = penangle * Math.PI/180;
                for (var i = 0; i < units; i++) {
                    pos[1] += unitsize * Math.cos(ryaw);
                    pos[2] += unitsize * Math.sin(ryaw);
                    set(pos,opts.leaves);
                }
            }

            function setPoint() {
                set(pos, opts.bark);
            }
            function setMaterial(value) {
                mindex = value;
            }
            function yaw(angle) {
                penangle += angle;
            }
            function pitch(angle) {
                //turtle.pitch += angle;
            }
            function roll(angle) {
                //turtle.roll += angle;
            }
            function PushState() {
                //penstack.push(turtle);
                posstack.push(pos);
            }
            function PopState() {
              //  turtle = penstack.pop();
                pos = posstack.pop();
            }

            //F  - move forward one unit with the pen down
            //G  - move forward one unit with the pen up
            //#  - Changes draw medium.

            // +  - yaw the turtle right by angle parameter
            // -  - yaw the turtle left by angle parameter
            // &  - pitch the turtle down by angle parameter
            // ^  - pitch the turtle up by angle parameter
            // /  - roll the turtle to the right by angle parameter
            // *  - roll the turtle to the left by angle parameter
            // [  - save in stack current state info
            // ]  - recover from stack state info
            for (var i = 0; i < axiom.length; i++) {
                var c = axiom.charAt(i);
                switch(c) {
                    case 'F':
                        moveForward();
                        setPoint();
                        break;
                    case '+':
                        yaw(+angle);
                        break;
                    case '-':
                        yaw(-angle);
                        break;
                    case '&':
                        pitch(+angle);
                        break;
                    case '^':
                        pitch(-angle);
                        break;
                    case '/':
                        roll(+angle);
                        break;
                    case '*':
                        roll(-angle);
                        break;
                    case 'G':
                        moveForward();
                        break;
                    case '[':
                        PushState();
                        break;
                    case ']':
                        PopState();
                        break;
                    case '0':
                        setMaterial(0);
                        break;
                    case '1':
                        setMaterial(1);
                        break;
                    case '2':
                        setMaterial(2);
                        break;
                    case '3':
                        setMaterial(3);
                        break;

                }
            }
        }

        var axiom = "FX";
        var rules = [ ["X", "X+YF+"], ["Y", "-FX-Y"]];
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        axiom = applyRules(axiom,rules);
        drawAxiom(axiom, 90, 1, 5);
    }
    };

    if (!generators[opts.treeType]) throw new Error('voxel-trees invalid treeType: ' + opts.treeType);

    generators[opts.treeType]();
};

function regexRules(rules) {
    var regexrule = '';
    rules.forEach(function (rule) {
        if (regexrule != '') {
            regexrule = regexrule+ '|' ;
        }
        regexrule = regexrule+rule[0];
    });
    return new RegExp(regexrule, "g");
}

function applyRules(axiom, rules) {
    function matchRule(match)
    {
        for (var i=0;i<rules.length;i++)
        {
            if (rules[i][0] == match) return rules[i][1];
        }
        return '';
    }
    return axiom.replace(regexRules(rules), matchRule);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 by Arena of Titans Contributors.
 *
 * This file is part of Arena of Titans.
 *
 * Arena of Titans is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Arena of Titans is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
 */

import Config from './configuration';

const PRELOAD_DELAY = 1000;
const PRELOAD_CHUNK_SIZE = 5;

export class AssetSource {
    static version = Config.version;

    static forAnimation(data) {
        return `/${this.version}/assets/game/animation/${ImageName.forAnimation(data)}.png`;
    }

    static forBackground(kind) {
        switch (kind) {
            case 'board':
                return `/${this.version}/assets/game/backgrounds/board.png`;
            case 'board-outline':
                return `/${this.version}/assets/game/backgrounds/board-outline.png`;
            case 'create-game':
                return `/${this.version}/assets/game/backgrounds/game-creation.jpg`;
            case 'heroes-selection':
                return `/${this.version}/assets/game/backgrounds/heroes-selection.png`;
            default:
                throw new Error(`No such background: ${kind}`);
        }
    }

    static forCard(card) {
        return `/${this.version}/assets/game/cards/movement/${ImageName.forCard(card)}.png`;
    }

    static forChestHero(hero) {
        return `/${this.version}/assets/game/heroes/${hero}-chest.png`;
    }

    static forCircledHero(hero) {
        return `/${this.version}/assets/game/heroes/${hero}-circle.png`;
    }

    static forGame(kind) {
        switch (kind) {
            case 'logo':
                return `/${this.version}/assets/game/aot-logo.png`;
            default:
                throw new Error(`No such image for game: ${kind}`);
        }
    }

    static forHero(hero) {
        return `/${this.version}/assets/game/heroes/${hero}.png`;
    }

    static forHeroPower(hero) {
        return `/${this.version}/assets/game/cards/powers/${hero}.png`;
    }

    static forMiscImage(kind) {
        switch (kind) {
            case 'clippy':
                return `/${this.version}/assets/game/misc/clippy.svg`;
            case 'arrow-left':
                return `/${this.version}/assets/game/misc/arrow-left.png`;
            case 'arrow-right':
                return `/${this.version}/assets/game/misc/arrow-right.png`;
            case 'favicon':
                return `/${this.version}/assets/favicon.png`;
            case 'favicon-notify':
                return `/${this.version}/assets/favicon-notify.png`;
            default:
                throw new Error(`No such misc image: ${kind}`);
        }
    }

    static forGlobalImage(kind) {
        switch (kind) {
            case 'french-flag':
                return `/${this.version}/assets/components/french.png`;
            case 'english-flag':
                return `/${this.version}/assets/components/english.png`;
            case 'gear':
                return `/${this.version}/assets/components/gear.png`;
            default:
                throw new Error(`No such global image: ${kind}`);
        }
    }

    static forSound(kind, format) {
        switch (kind) {
            case 'your-turn':
                return `/${this.version}/assets/sounds/game/your-turn-sound.${format}`;
            case 'your-turn-voice':
                return `/${this.version}/assets/sounds/game/your-turn-voice.${format}`;
            case 'game-over':
                return `/${this.version}/assets/sounds/game/game-over.${format}`;
            default:
                throw new Error(`No such sound: ${kind}`);
        }
    }

    static forPower(power) {
        return `/${this.version}/assets/game/cards/powers/${ImageName.forTrump(power)}.png`;
    }

    static forTrump(trump) {
        return `/${this.version}/assets/game/cards/trumps/${ImageName.forTrump(trump)}.png`;
    }

    static preloadImages(kind) {
        if (!(kind in Config.images)) {
            throw new Error(`No such kind of images to preload: ${kind}`);
        }
        // Don't try to preload images when testing the application.
        if (window.jasmine) {
            return;
        }
        let imagesToPreload = Config.images[kind];
        let imagesChunkToPreload = [];
        let startIndex = 0;
        while (startIndex < imagesToPreload.length) {
            let chunk = imagesToPreload.slice(startIndex, startIndex + PRELOAD_CHUNK_SIZE);
            imagesChunkToPreload.push(chunk);
            startIndex += PRELOAD_CHUNK_SIZE;
        }

        let timeout = 0;
        for (let chunk of imagesChunkToPreload) {
            setTimeout(() => {
                this._preloadImages(chunk);
            }, timeout);
            timeout += PRELOAD_DELAY;
        }
    }

    static _preloadImages(images) {
        for (let src of images) {
            let img = new Image();
            img.src = `//${location.host}/${this.version}/${src}`;
        }
    }
}

export class ImageClass {
    static forCard(card) {
        return `sprite-movement-${ImageName.forCard(card)}`;
    }
}

export class ImageName {
    static forAnimation(data) {
        let name = data.name.toLowerCase();
        let color = data.color.toLocaleLowerCase();

        return `${name}-${color}`;
    }

    static forCard(card) {
        let name = card.name.toLowerCase();
        let color = card.color.toLocaleLowerCase();

        return `${name}-${color}`;
    }

    static forTrump(trump) {
        let trumpName = trump.name.replace(' ', '-').toLowerCase();
        return `${trumpName}`;
    }
}
<commit_msg>ref(assets): use trump color if specified to load trump image<commit_after>/*
 * Copyright (C) 2017 by Arena of Titans Contributors.
 *
 * This file is part of Arena of Titans.
 *
 * Arena of Titans is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Arena of Titans is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
 */

import Config from './configuration';

const PRELOAD_DELAY = 1000;
const PRELOAD_CHUNK_SIZE = 5;

export class AssetSource {
    static version = Config.version;

    static forAnimation(data) {
        return `/${this.version}/assets/game/animation/${ImageName.forAnimation(data)}.png`;
    }

    static forBackground(kind) {
        switch (kind) {
            case 'board':
                return `/${this.version}/assets/game/backgrounds/board.png`;
            case 'board-outline':
                return `/${this.version}/assets/game/backgrounds/board-outline.png`;
            case 'create-game':
                return `/${this.version}/assets/game/backgrounds/game-creation.jpg`;
            case 'heroes-selection':
                return `/${this.version}/assets/game/backgrounds/heroes-selection.png`;
            default:
                throw new Error(`No such background: ${kind}`);
        }
    }

    static forCard(card) {
        return `/${this.version}/assets/game/cards/movement/${ImageName.forCard(card)}.png`;
    }

    static forChestHero(hero) {
        return `/${this.version}/assets/game/heroes/${hero}-chest.png`;
    }

    static forCircledHero(hero) {
        return `/${this.version}/assets/game/heroes/${hero}-circle.png`;
    }

    static forGame(kind) {
        switch (kind) {
            case 'logo':
                return `/${this.version}/assets/game/aot-logo.png`;
            default:
                throw new Error(`No such image for game: ${kind}`);
        }
    }

    static forHero(hero) {
        return `/${this.version}/assets/game/heroes/${hero}.png`;
    }

    static forHeroPower(hero) {
        return `/${this.version}/assets/game/cards/powers/${hero}.png`;
    }

    static forMiscImage(kind) {
        switch (kind) {
            case 'clippy':
                return `/${this.version}/assets/game/misc/clippy.svg`;
            case 'arrow-left':
                return `/${this.version}/assets/game/misc/arrow-left.png`;
            case 'arrow-right':
                return `/${this.version}/assets/game/misc/arrow-right.png`;
            case 'favicon':
                return `/${this.version}/assets/favicon.png`;
            case 'favicon-notify':
                return `/${this.version}/assets/favicon-notify.png`;
            default:
                throw new Error(`No such misc image: ${kind}`);
        }
    }

    static forGlobalImage(kind) {
        switch (kind) {
            case 'french-flag':
                return `/${this.version}/assets/components/french.png`;
            case 'english-flag':
                return `/${this.version}/assets/components/english.png`;
            case 'gear':
                return `/${this.version}/assets/components/gear.png`;
            default:
                throw new Error(`No such global image: ${kind}`);
        }
    }

    static forSound(kind, format) {
        switch (kind) {
            case 'your-turn':
                return `/${this.version}/assets/sounds/game/your-turn-sound.${format}`;
            case 'your-turn-voice':
                return `/${this.version}/assets/sounds/game/your-turn-voice.${format}`;
            case 'game-over':
                return `/${this.version}/assets/sounds/game/game-over.${format}`;
            default:
                throw new Error(`No such sound: ${kind}`);
        }
    }

    static forPower(power) {
        return `/${this.version}/assets/game/cards/powers/${ImageName.forTrump(power)}.png`;
    }

    static forTrump(trump) {
        return `/${this.version}/assets/game/cards/trumps/${ImageName.forTrump(trump)}.png`;
    }

    static preloadImages(kind) {
        if (!(kind in Config.images)) {
            throw new Error(`No such kind of images to preload: ${kind}`);
        }
        // Don't try to preload images when testing the application.
        if (window.jasmine) {
            return;
        }
        let imagesToPreload = Config.images[kind];
        let imagesChunkToPreload = [];
        let startIndex = 0;
        while (startIndex < imagesToPreload.length) {
            let chunk = imagesToPreload.slice(startIndex, startIndex + PRELOAD_CHUNK_SIZE);
            imagesChunkToPreload.push(chunk);
            startIndex += PRELOAD_CHUNK_SIZE;
        }

        let timeout = 0;
        for (let chunk of imagesChunkToPreload) {
            setTimeout(() => {
                this._preloadImages(chunk);
            }, timeout);
            timeout += PRELOAD_DELAY;
        }
    }

    static _preloadImages(images) {
        for (let src of images) {
            let img = new Image();
            img.src = `//${location.host}/${this.version}/${src}`;
        }
    }
}

export class ImageClass {
    static forCard(card) {
        return `sprite-movement-${ImageName.forCard(card)}`;
    }
}

export class ImageName {
    static forAnimation(data) {
        let name = data.name.toLowerCase();
        let color = data.color.toLocaleLowerCase();

        return `${name}-${color}`;
    }

    static forCard(card) {
        let name = card.name.toLowerCase();
        let color = card.color.toLocaleLowerCase();

        return `${name}-${color}`;
    }

    static forTrump(trump) {
        let trumpName = trump.name.replace(' ', '-').toLowerCase();
        if (trump.color === null) {
            return trumpName;
        }

        let trumpColor = trump.color.toLowerCase();
        return `${trumpName}-${trumpColor}`;
    }
}
<|endoftext|>


<commit_before>(function () {
	'use strict';

	const CURRENT_DATE = new Date();

	function Area(_name, _code) {
			this.name = _name;
			this.code = _code;
	}

	function MSP
	(_ID, _constit, _region, _firstName, _lastName, _DOB, _photoURL) {
			this.ID = _ID;
			this.constit = _constit;
			this.region = _region;
			this.firstName = _firstName;
			this.lastName = _lastName;
			this.DOB = _DOB;
			this.photoURL = _photoURL;
	}

	const getDataFromAPIs = new Promise((resolve, reject) => {
		const APIroot = 'https://data.parliament.scot/api/';
		const membersAPI = APIroot + 'members';
		const constituencyElectionsAPI = APIroot + 'MemberElectionConstituencyStatuses';
		const regionalElectionsAPI = APIroot + 'MemberElectionregionStatuses';
		const regionsAPI = APIroot + 'regions';
		const constituenciesAPI = APIroot + 'constituencies';

		const get = (url) => {
			return new Promise((resolve, reject) => {
				fetch(url, {
						method: 'get'
					})
					.then(function (response) {
						return response.json();
					})
					.then(function (data) {
						resolve(data);
					});
			});
		};

		Promise.all([
		get(membersAPI),
		get(constituencyElectionsAPI),
		get(regionalElectionsAPI),
		get(constituenciesAPI),
		get(regionsAPI)
		]).then((dataArr) => {

		let returnData = {
		'basicMSPData': dataArr[0],
		'constitResults':  dataArr[1],
		'regResults': dataArr[2],
		'constits': dataArr[3],
		'regions': dataArr[4],
		}

		resolve(returnData);

		});
	});

	const getCurrentMSPsFromElectionResults =
		(constitResults, regResults, constituencies, regions) => {

			let r = [];
			let results;

			for (let isLoopingRegions = 0; isLoopingRegions < 2; isLoopingRegions++) {
				if (isLoopingRegions) {
					results = regResults;
				} else {
					results = constitResults;
				}

				results.forEach((electionResult) => {

					let startDate = null;
					let endDate = null;
					startDate = getSPDateFromStr(electionResult.ValidFromDate);
					if (electionResult.ValidUntilDate != null) {
						endDate = getSPDateFromStr(electionResult.ValidUntilDate);
					}

					if ((CURRENT_DATE >= startDate &&
							CURRENT_DATE <= endDate) ||
						(CURRENT_DATE >= startDate &&
							endDate == null)) {

						let newMSP = new MSP(electionResult.PersonID);

						if (isLoopingRegions) {

							let region = regions.find((reg) => {
								return reg.ID == electionResult.RegionID;
							});
							newMSP.region = new Area(region.Name, region.RegionCode);

						} else {

							let constit = constituencies.find((c) => {
								return c.ID == electionResult.ConstituencyID;
							});
							newMSP.constit = new Area(constit.Name, constit.ConstituencyCode);

							let region = regions.find((reg) => {
								return reg.ID == constit.RegionID;
							});
							newMSP.region = new Area(region.Name, region.RegionCode);

						}
						r.push(newMSP);
					}
				});
			}
			return r;
		};

	const addMSPData = (mspList, basicMSPData) => {

		mspList.forEach((m) => {

			let mspDataObj = basicMSPData.find((dataElem) => {
				return dataElem.PersonID === m.ID;
			});

			let fullName = mspDataObj.ParliamentaryName.split(',');
			m.firstName = fullName[1];
			m.lastName = fullName[0];

			if (!mspDataObj.BirthDateIsProtected) {
				m.DOB = getSPDateFromStr(mspDataObj.BirthDate);
			}

			m.photoURL = mspDataObj.PhotoURL;

		});
	};

	//Processes an SP formatted date string into a JS date object
	const getSPDateFromStr = (dateStr) => {
		let T = dateStr.indexOf('T');
		dateStr = dateStr.substring(0, T);
		dateStr = dateStr.replace(/\s+/g, '');
		let dateArr = dateStr.split('-');
		let year = dateArr[0],
			month = dateArr[1],
			day = dateArr[2];
		return new Date(year, (month - 1), day);
	};

	/******************************************************************/

	const colsClass = 'cols';
	const cellClass = 'cols--cell';
	const txtBoxClass = 'txtbox';
	const portraitBoxClass = 'portrait-box';
	const portraitImgClass = 'portrait-img';
	const smallImgPath = '/img/portraits/';
	const main = document.getElementsByTagName('main')[0];

	//Code for building the HTML elements
	const E = (tag, attrs = {}, text = '', ...children) => {
		const e = document.createElement(tag);
		if (attrs) {
			for (let key in attrs) {
				e.setAttribute(key, attrs[key]);
			}
		}
		if (text) {
			e.appendChild(document.createTextNode(text));
		}
		for (let i = 0; i < children.length; i++) {
			e.appendChild(children[i]);
		}
		return e;
	};

	const setupMSPComponentsInView = (mspList) => {

		mspList.forEach((m) => {

			let location;
			if (m.constit) {
				location = m.constit.name + ', ' + m.region.name;
			} else {
				location = m.region.name;
			}

			let birthDate = '(Birth date not given)';
			if (m.DOB) {
				let d = m.DOB;
				birthDate = d.getDate() +
					'/' + (d.getMonth() + 1) +
					'/' + d.getFullYear();
			}

			let imgSRC = m.photoURL;
			let imgAlt = m.firstName + ' portrait';

			if (imgSRC) {

				let imgID = imgSRC.substring(imgSRC.lastIndexOf('/') + 1);
				imgID = imgID.replace(/\s+/g, '');
				imgSRC = smallImgPath + imgID + '.jpg';

			} else {
				imgSRC = '#';
			}

			let MSPComponent = E('div', {
					'class': colsClass
				}, '',
				E('div', {
						'class': cellClass
					}, '',
					E('div', {
							'class': portraitBoxClass
						}, '',
						E('img', {
							'class': portraitImgClass,
							'src': imgSRC,
							'alt': imgAlt
						})),
					E('div', {
							'class': txtBoxClass
						}, '',
						E('p', {}, m.firstName + ' ' + m.lastName),
						E('p', {}, birthDate),
						E('p', {}, location)
					)));

			main.appendChild(MSPComponent);

		});

	};

	/******************************************************************/

	getDataFromAPIs.then((d) => {

		let mspList = getCurrentMSPsFromElectionResults(
			d.constitResults, d.regResults, d.constits, d.regions);

		addMSPData(mspList, d.basicMSPData);

		setupMSPComponentsInView(mspList);

	});

}());<commit_msg>Some more small tweaks<commit_after>(function () {
	'use strict';

	/* GLOBALS & UTILS */

	const CURRENT_DATE = new Date();

	function Area(_name, _code) {
			this.name = _name;
			this.code = _code;
	}

	function MSP
	(_ID, _constit, _region, _firstName, _lastName, _DOB, _photoURL) {
			this.constit = _constit;
			this.region = _region;
			this.firstName = _firstName;
			this.lastName = _lastName;
			this.DOB = _DOB;
			this.photoURL = _photoURL;
	}

	const getSPDateFromStr = (dateStr) => {
		let T = dateStr.indexOf('T');
		dateStr = dateStr.substring(0, T);
		dateStr = dateStr.replace(/\s+/g, '');
		let dateArr = dateStr.split('-');
		let year = dateArr[0],
			month = dateArr[1],
			day = dateArr[2];
		return new Date(year, (month - 1), day);
	};

/******************************************************************/
/* API */

	const getDataFromAPIs = new Promise((resolve, reject) => {
		const APIroot = 'https://data.parliament.scot/api/';
		const membersAPI = APIroot + 'members';
		const constituencyElectionsAPI = APIroot + 'MemberElectionConstituencyStatuses';
		const regionalElectionsAPI = APIroot + 'MemberElectionregionStatuses';
		const regionsAPI = APIroot + 'regions';
		const constituenciesAPI = APIroot + 'constituencies';

		const get = (url) => {
			return new Promise((resolve, reject) => {
				fetch(url, {
						method: 'get'
					})
					.then(function (response) {
						return response.json();
					})
					.then(function (data) {
						resolve(data);
					});
			});
		};

		Promise.all([
		get(membersAPI),
		get(constituencyElectionsAPI),
		get(regionalElectionsAPI),
		get(constituenciesAPI),
		get(regionsAPI)
		]).then((dataArr) => {

		let returnData = {
		'basicMSPData': dataArr[0],
		'constitResults':  dataArr[1],
		'regResults': dataArr[2],
		'constits': dataArr[3],
		'regions': dataArr[4],
		}

		resolve(returnData);

		});
	});

	/******************************************************************/
	/* DATA PROCESSING */

	//Builds a Map of MSPs using their PersonIDs
	const getMSPMap =
	(constitResults, regResults, constituencies, regions) => {

			let r = new Map();
			let results;

			for (let isLoopingRegions = 0; isLoopingRegions < 2; isLoopingRegions++) {
				if (isLoopingRegions) {
					results = regResults;
				} else {
					results = constitResults;
				}

				results.forEach((electionResult) => {

					let startDate = null;
					let endDate = null;
					startDate = getSPDateFromStr(electionResult.ValidFromDate);
					if (electionResult.ValidUntilDate != null) {
						endDate = getSPDateFromStr(electionResult.ValidUntilDate);
					}

					if ((CURRENT_DATE >= startDate &&
							CURRENT_DATE <= endDate) ||
						(CURRENT_DATE >= startDate &&
							endDate == null)) {

						let newMSP = new MSP();

						if (isLoopingRegions) {

							let region = regions.find((reg) => {
								return reg.ID == electionResult.RegionID;
							});
							newMSP.region = new Area(region.Name, region.RegionCode);

						} else {

							let constit = constituencies.find((c) => {
								return c.ID == electionResult.ConstituencyID;
							});
							newMSP.constit = new Area(constit.Name, constit.ConstituencyCode);

							let region = regions.find((reg) => {
								return reg.ID == constit.RegionID;
							});
							newMSP.region = new Area(region.Name, region.RegionCode);

						}
						r.set(electionResult.PersonID, newMSP);
					}
				});
			}
			return r;
		};

	const addMSPData = (mspMap, basicMSPData) => {
	console.log(mspMap);

		mspMap.forEach((val, key, map) => {

			let mspDataObj = basicMSPData.find((dataElem) => {
				return dataElem.PersonID === key;
			});

			let fullName = mspDataObj.ParliamentaryName.split(',');
			val.firstName = fullName[1];
			val.lastName = fullName[0];

			if (!mspDataObj.BirthDateIsProtected) {
				val.DOB = getSPDateFromStr(mspDataObj.BirthDate);
			}

			val.photoURL = mspDataObj.PhotoURL;

		});
	};

/******************************************************************/
/* VIEW */

	const setView = (mspMap) => {
		const colsClass = 'cols';
		const cellClass = 'cols--cell';
		const txtBoxClass = 'txtbox';
		const portraitBoxClass = 'portrait-box';
		const portraitImgClass = 'portrait-img';
		const smallImgPath = '/img/portraits/';
		const main = document.getElementsByTagName('main')[0];

		const E = (tag, attrs = {}, text = '', ...children) => {
			const e = document.createElement(tag);
			if (attrs) {
				for (let key in attrs) {
					e.setAttribute(key, attrs[key]);
				}
			}
			if (text) {
				e.appendChild(document.createTextNode(text));
			}
			for (let i = 0; i < children.length; i++) {
				e.appendChild(children[i]);
			}
			return e;
		};

		mspMap.forEach((m) => {
			let location;
			if (m.constit) {
				location = m.constit.name + ', ' + m.region.name;
			} else {
				location = m.region.name;
			}

			let birthDate = '(Birth date not given)';
			if (m.DOB) {
				let d = m.DOB;
				birthDate = d.getDate() +
					'/' + (d.getMonth() + 1) +
					'/' + d.getFullYear();
			}

			let imgSRC = m.photoURL;
			let imgAlt = m.firstName + ' portrait';
			if (imgSRC) {
				let imgID = imgSRC.substring(imgSRC.lastIndexOf('/') + 1);
				imgID = imgID.replace(/\s+/g, '');
				imgSRC = smallImgPath + imgID + '.jpg';
			} else {
				imgSRC = '#';
			}

			let MSPComponent = E('div', {
					'class': colsClass
				}, '',
				E('div', {
						'class': cellClass
					}, '',
					E('div', {
							'class': portraitBoxClass
						}, '',
						E('img', {
							'class': portraitImgClass,
							'src': imgSRC,
							'alt': imgAlt
						})),
					E('div', {
							'class': txtBoxClass
						}, '',
						E('p', {}, m.firstName + ' ' + m.lastName),
						E('p', {}, birthDate),
						E('p', {}, location)
					)));

			main.appendChild(MSPComponent);
		});
	}

	/******************************************************************/
  /* MAIN */

	getDataFromAPIs.then((d) => {

		let mspMap = getMSPMap(
			d.constitResults, d.regResults, d.constits, d.regions);

		addMSPData(mspMap, d.basicMSPData);

		setView(mspMap);

	});

}());<|endoftext|>


<commit_before>var http = require('http');
var Busboy = require('busboy');
var _ = require('lodash');
var Spreadsheet = require('edit-google-spreadsheet');

//environment variables
var env = process.env;
var port = env.PORT || 5000;

var mailgunDomain = env.MAILGUN_DOMAIN;
var mailgun = require('mailgun-js')({
  apiKey: env.MAILGUN_API_KEY,
  domain: mailgunDomain,
});

var inboundMessageEndpoint = env.ENDPOINT_SECRET;

var gDriveEmail = env.GDRIVE_EMAIL;
var gDriveFileId = env.GDRIVE_FILEID;
var gDriveKey = env.GDRIVE_KEY;

//main flow
function messagePosted(message){
  var parsedMessage = parseMessage(message);
  var parsedMessageWithLinks = uploadAttachments(parsedMessage);
  appendToGoogleSpreadsheet(parsedMessageWithLinks);
  confirmReceipt(parsedMessageWithLinks);
}

//setup an http server to parse posts to inboundMessageEndpoint
//and foroward them to messagePosted function above
var server = http.createServer(function(req, res) {
  message = {};
  if (req.method === 'POST' && req.url === '/' + inboundMessageEndpoint) {
    var busboy = new Busboy({headers: req.headers});
    busboy.on('field', function(fieldName, val) {
      message[fieldName] = val;
    });
    busboy.on('finish', function() {
      res.writeHead(200, {Connection: 'close'});
      res.end('got it.');
      messagePosted(message);
    });
    req.pipe(busboy);
  }
});

server.listen(port, function() {
  console.log('listening. port = ' + port);
});

//parse the posted message into the fields the rest of the app works with
function messagePosted(message){
  var sender = message.sender;
  var category = message.recipient.replace('@' + mailgunDomain, '');

  var subject = message.subject;
  //split subject into (<amount>:) <description>
  var subjectSplit = message.indexOf(':');
  var description = subject;
  var amount = null;
  if(subjectSplit !== -1){
    amount = subject.slice(0, subjectSplit);
    description = subject.slice(subjectSplit);
  }

  return {
    sender:      sender,
    category:    category,
    description: description,
    amount:      amount,
  }
}

//Upload attachments to s3 and replace them with a link to the file
//note that this approach requires the entire attachment to be in RAM
//that should be fine since emails max out at 25mb and we have 512mb on the
//heroku server
//note that this message edits and returns the input parameter
function uploadAttachments(parsedMessage){
  var parsedMessageWithLinks = parsedMessage;
}

//append fields from message to google spreadsheet
function appendToGoogleSpreadsheet(message){
  function onSpreadsheetLogin(spreadsheet){
    spreadsheet.receive(withErr('receive',
      _.curry(onSpreadsheetReceive)(_, spreadsheet))
    );
  }
  function onSpreadsheetReceive(spreadsheet, rows, info){
    appendRowToSpreadsheet(spreadsheet, info.nextRow);
  }
  function appendRowToSpreadsheet(spreadsheet, rowNum){
    var row = {};
    row[rowNum] = {
      1:moment().format('DD/MM/YY hh:mm a'),
      2:message.sender,
      3:message.category,
      4:message.amount,
      5:message.description,
    };
    spreadsheet.add(row);
    spreadsheet.send(withErr('send', _.noop));
  }
  Spreadsheet.load({
    debug:true,
    spreadsheetId: gDriveFileId,
    worksheetName: 'Sheet1',
    oauth:{
      email: gDriveEmail,
      key: gDriveKey,
    },
  }, withErr('login', onSpreadsheetLogin));

  //wrap a function in another function that logs errors passed in the first
  //argument
  function withErr(opname, fn){
    return function(){
      args = _.toArray(arguments);

      var error = args.pop();
      if(error){
        logError(message.sender, opname + ' failed: ' + error);
        throw error;
      }

      fn.apply(null, args);
    }
  }
}

//email sender a confirmation of what was done
function confirmReceipt(message){

}

//notify user with email 'to' of error described by message
function logError(to, message){
  console.log('Error:', to, message);
  var data = {
    from: 'Expensa Bot <expensa-bot@' + mailgunDomain + '>',
    to: to,
    subject: 'expenas encountered an unexpected error, try your request again.',
    text: message,
  };

  mailgun.messages().send(data, function (error, body) {
    if(error){
      console.log('error sending error to',to, error);
    }
  });
}

mailgun.messages().send(message, function(error, data){
  if(error){
    console.log(error);
  }

});
//UTILITIES---------------------------------------------------------------------
<commit_msg>implement email receipts<commit_after>var http = require('http');
var Busboy = require('busboy');
var _ = require('lodash');
var Spreadsheet = require('edit-google-spreadsheet');

//environment variables
var env = process.env;
var port = env.PORT || 5000;

var mailgunDomain = env.MAILGUN_DOMAIN;
var mailgun = require('mailgun-js')({
  apiKey: env.MAILGUN_API_KEY,
  domain: mailgunDomain,
});

var inboundMessageEndpoint = env.ENDPOINT_SECRET;

var gDriveEmail = env.GDRIVE_EMAIL;
var gDriveFileId = env.GDRIVE_FILEID;
var gDriveKey = env.GDRIVE_KEY;

//main flow
function messagePosted(message){
  var parsedMessage = parseMessage(message);
  var parsedMessageWithLinks = uploadAttachments(parsedMessage);
  appendToGoogleSpreadsheet(parsedMessageWithLinks);
  confirmReceipt(parsedMessageWithLinks);
}

//setup an http server to parse posts to inboundMessageEndpoint
//and foroward them to messagePosted function above
var server = http.createServer(function(req, res) {
  message = {};
  if (req.method === 'POST' && req.url === '/' + inboundMessageEndpoint) {
    var busboy = new Busboy({headers: req.headers});
    busboy.on('field', function(fieldName, val) {
      message[fieldName] = val;
    });
    busboy.on('finish', function() {
      res.writeHead(200, {Connection: 'close'});
      res.end('got it.');
      messagePosted(message);
    });
    req.pipe(busboy);
  }
});

server.listen(port, function() {
  console.log('listening. port = ' + port);
});

//parse the posted message into the fields the rest of the app works with
function messagePosted(message){
  var sender = message.sender;
  var category = message.recipient.replace('@' + mailgunDomain, '');

  var subject = message.subject;
  //split subject into (<amount>:) <description>
  var subjectSplit = message.indexOf(':');
  var description = subject;
  var amount = null;
  if(subjectSplit !== -1){
    amount = subject.slice(0, subjectSplit);
    description = subject.slice(subjectSplit);
  }

  return {
    timestamp:   moment().format('DD/MM/YY hh:mm a')
    sender:      sender,
    category:    category,
    description: description,
    amount:      amount,
  }
}

//Upload attachments to s3 and replace them with a link to the file
//note that this approach requires the entire attachment to be in RAM
//that should be fine since emails max out at 25mb and we have 512mb on the
//heroku server
//note that this message edits and returns the input parameter
function uploadAttachments(parsedMessage){
  var parsedMessageWithLinks = parsedMessage;
}

//append fields from message to google spreadsheet
function appendToGoogleSpreadsheet(message){
  function onSpreadsheetLogin(spreadsheet){
    spreadsheet.receive(withErr('receive',
      _.curry(onSpreadsheetReceive)(_, spreadsheet))
    );
  }
  function onSpreadsheetReceive(spreadsheet, rows, info){
    appendRowToSpreadsheet(spreadsheet, info.nextRow);
  }
  function appendRowToSpreadsheet(spreadsheet, rowNum){
    var row = {};
    row[rowNum] = {
      1:message.timestamp,
      2:message.sender,
      3:message.category,
      4:message.amount,
      5:message.description,
    };
    spreadsheet.add(row);
    spreadsheet.send(withErr('send', _.noop));
  }
  Spreadsheet.load({
    debug:true,
    spreadsheetId: gDriveFileId,
    worksheetName: 'Sheet1',
    oauth:{
      email: gDriveEmail,
      key: gDriveKey,
    },
  }, withErr('login', onSpreadsheetLogin));

  //wrap a function in another function that logs errors passed in the first
  //argument
  function withErr(opname, fn){
    return function(){
      args = _.toArray(arguments);

      var error = args.pop();
      if(error){
        logError(message.sender, opname + ' failed: ' + error);
        throw error;
      }

      fn.apply(null, args);
    }
  }
}

//email sender a confirmation of what was done
function confirmReceipt(message){
  var fields = JSON.stringify(message, null, '    ');
  var receipt = 'The following message has been processed:\n' + fields + '\n';
  reciept    += '--Expensa Bot';
  sendmail({
    to: message.sender,
    subject: 'Message Processed on ' + fields.timestamp,
    text: receipt,
  });
}

//notify user with email 'to' of error described by message
function logError(to, message){
  console.log('Error:', to, message);
  sendMail({
    to: to,
    subject: 'expensa encountered an unexpected error, try your request again.',
    text: message,
  });
}
//UTILITIES---------------------------------------------------------------------
function sendMail(email){
  email.from = 'Expensa Bot <expensa-bot@' + mailgunDomain + '>';
  mailgun.messages().send(email, function (error, body) {
    if(error){
      console.log('error sending mail:',email.to, error);
    }
  });
}
<|endoftext|>


<commit_before>/**
 * Autonomous flight with the Flow deck
 * Implementation of (https://github.com/bitcraze/crazyflie-lib-python/blob/master/examples/flowsequenceSync.py)
 */

const { Crazyradio, utils } = require('../dist/index');
// How high drone should be (in meters)
const hoverDistance = 0.4;
// How fast drone should move (in m/s)
const speed = 0.5;

// Because you can only use `await` within an async function...
main();
async function main() {

	const radio = new Crazyradio();

	try {

		await radio.init();

		radio.on('console line', console.log);
		radio.on('error', err => {
			console.log('Radio error!', err);
		});

		const drones = await radio.findDrones();
		console.log(`Nearby drones: ${drones}`);

		if (drones.length < 1) {
			throw 'Could not find any drones!';
		}

		const drone = await radio.connect(drones[0]);

		// What to do if we exit the program via Ctrl + c
		process.on('SIGINT', async () => {
			await drone.commander.stopSetpoint();
			process.exit();
		});

		const toc = await drone.parameters.getTOC();
		const resetKalman = toc.getItem('kalman', 'resetEstimation');

		console.log('******************************');
		console.log('Resetting Position Estimation...')
		console.log('******************************');

		drone.parameters.set(resetKalman, '1');
		await utils.wait(100);
		drone.parameters.set(resetKalman, '0');
		await utils.wait(2000);

		console.log('******************************');
		console.log('Done! All clear for takeoff.')
		console.log('******************************');

		for (let i = 0; i <= 1; i += 0.1) {
			await drone.commander.hoverSetpoint({
				zDistance: (i / 1) * hoverDistance
			});
			await utils.wait(100);
		}
		await utils.wait(2000);

		await drone.commander.hoverSetpoint({
			velocityX: speed,
			yawRate: 36 * 2
		});
		await utils.wait(5000);

		await drone.commander.hoverSetpoint({
			velocityX: speed,
			yawRate: -36 * 2
		});
		await utils.wait(5000);

		await drone.commander.hoverSetpoint({
			velocityX: 0,
			yawRate: 0
		});
		await utils.wait(2000);

		for (let i = 0; i <= 1; i += 0.1) {
			await drone.commander.hoverSetpoint({
				zDistance: hoverDistance - ((i / 1) * hoverDistance)
			});
			await utils.wait(100);
		}

		await drone.commander.stopSetpoint();

	} catch (err) {
		console.log('Uh oh!', err);
		await radio.close();
	}
}
<commit_msg>Disconnect after flow sequence example<commit_after>/**
 * Autonomous flight with the Flow deck
 * Implementation of (https://github.com/bitcraze/crazyflie-lib-python/blob/master/examples/flowsequenceSync.py)
 */

const { Crazyradio, utils } = require('../dist/index');
// How high drone should be (in meters)
const hoverDistance = 0.4;
// How fast drone should move (in m/s)
const speed = 0.5;

// Because you can only use `await` within an async function...
main();
async function main() {

	const radio = new Crazyradio();

	try {

		await radio.init();

		radio.on('console line', console.log);
		radio.on('error', err => {
			console.log('Radio error!', err);
		});

		const drones = await radio.findDrones();
		console.log(`Nearby drones: ${drones}`);

		if (drones.length < 1) {
			throw 'Could not find any drones!';
		}

		const drone = await radio.connect(drones[0]);

		// What to do if we exit the program via Ctrl + c
		process.on('SIGINT', async () => {
			await drone.commander.stopSetpoint();
			process.exit();
		});

		const toc = await drone.parameters.getTOC();
		const resetKalman = toc.getItem('kalman', 'resetEstimation');

		console.log('******************************');
		console.log('Resetting Position Estimation...')
		console.log('******************************');

		drone.parameters.set(resetKalman, '1');
		await utils.wait(100);
		drone.parameters.set(resetKalman, '0');
		await utils.wait(2000);

		console.log('******************************');
		console.log('Done! All clear for takeoff.')
		console.log('******************************');

		for (let i = 0; i <= 1; i += 0.1) {
			await drone.commander.hoverSetpoint({
				zDistance: (i / 1) * hoverDistance
			});
			await utils.wait(100);
		}
		await utils.wait(2000);

		await drone.commander.hoverSetpoint({
			velocityX: speed,
			yawRate: 36 * 2
		});
		await utils.wait(5000);

		await drone.commander.hoverSetpoint({
			velocityX: speed,
			yawRate: -36 * 2
		});
		await utils.wait(5000);

		await drone.commander.hoverSetpoint({
			velocityX: 0,
			yawRate: 0
		});
		await utils.wait(2000);

		for (let i = 0; i <= 1; i += 0.1) {
			await drone.commander.hoverSetpoint({
				zDistance: hoverDistance - ((i / 1) * hoverDistance)
			});
			await utils.wait(100);
		}

		await drone.commander.stopSetpoint();
		await radio.close();

	} catch (err) {
		console.log('Uh oh!', err);
		await radio.close();
	}
}
<|endoftext|>


<commit_before>'use strict';
var path = require('path'),
	fs = require('fs'),
	merge = require('merge'),
	postcss = require('postcss'),
	userOptions = null,
	criticalActive = false,
	numberOfLinesInOriginalCss = 0,
	numberOfSameChecks = 0,
	numberOfSelectorSearches = 0,
	defaults = {
		'start': 'critical:start',
		'end': 'critical:end',
		'suffix': '-critical'
	};

function CriticalSplit(newOptions) {
	newOptions = newOptions || {};

	return function(originalCss, result) {
		if (applyUserOptions(newOptions)) {
			performTransform(originalCss, result);
		};
	};
}

function performTransform(originalCss, result) {
	var criticalCss = postcss.root(),
		absolutePath = originalCss.source.input.file,
		cwd = process.cwd(),
		relativePath = path.relative(cwd, absolutePath),
		nonCriticalFilename = path.basename(relativePath),
		relativeDirectory = path.dirname(relativePath),
		criticalFilename = createCriticalFilename(nonCriticalFilename);

	getAllCriticals(originalCss, criticalCss);

	// console.log('numberOfLinesInOriginalCss:', numberOfLinesInOriginalCss);
	// console.log('numberOfSameChecks:', numberOfSameChecks);
	// console.log('numberOfSelectorSearches:', numberOfSelectorSearches);

	fs.writeFileSync(path.join(relativeDirectory, nonCriticalFilename), originalCss.toResult());

	if (criticalCss.nodes.length > 0) {
		fs.writeFileSync(path.join(relativeDirectory, criticalFilename), criticalCss.toResult());
	}
}

function applyUserOptions(newOptions) {
	var errorMessage ='',
		result = true;

	userOptions = merge(defaults, newOptions);

	if (userOptions.start === userOptions.end) {
		errorMessage += '\n\n';
		errorMessage += 'ERROR :: PostCSS Plugin: Critical Split\n';
		errorMessage += '.Critical CSS start and end tag must not be the same. \n';
		errorMessage += 'Please adapt your options. \n\n';
		errorMessage += '------ Current Options ----- \n\n';
		errorMessage += JSON.stringify(userOptions, null, 2) + '\n\n';
		errorMessage += '---------- End -------------\n';

		console.error(errorMessage);
		result = false;
	}

	return result;
}

function createCriticalFilename(filename) {
	var position = filename.lastIndexOf('.css'),
		result = '';

	result = filename.substring(0, position);
	result += userOptions.suffix;
	result += '.css';

	return result;
}

function clearLevel(level) {
	level.walk(function(nestedRule) {
		nestedRule.remove();
	});
}

function getAllCriticals(originalCss, criticalCss) {
	var currentLevel = null;

	originalCss.walk(function(line) {
		var temp = null;

		numberOfLinesInOriginalCss++;

		if (line.type === 'comment' && line.text === userOptions.start) {
			criticalActive = true;
			// line.remove(); // remove unnecessary comment
		} else if (line.type === 'comment' && line.text === userOptions.end) {
			criticalActive = false
			currentLevel = null;
			// line.remove(); // remove unnecessary comment
		} else if (criticalActive === true && (line.type === 'decl' || line.type === 'comment')) {
			appendDeclaration(criticalCss, line);
			line.remove();
		}
	});
}

function appendDeclaration(criticalCss, line) {
	var parents = getParents(line),
		currentLevel = prepareSelectors(criticalCss, parents);

	currentLevel.append(line);
	currentLevel.raws.semicolon = true; // enforce last rule semicolon; just in case of some weird last-line comments...
}

function prepareSelectors(criticalCss, selectorLevels) {
	var currentLevel = null;

	currentLevel = findSelector(criticalCss, selectorLevels);

	if (currentLevel === null) {
		currentLevel = createSelectorLevels(criticalCss, selectorLevels);
	}

	return currentLevel;
}

function createSelectorLevels(criticalCss, selectorLevels) {
	var i = null,
		currentLevel = null,
		temp = null;

	numberOfSelectorSearches++;

	currentLevel = criticalCss;

	for (i = 0; i < selectorLevels.length; i++) {
		temp = selectorLevels[i];
		currentLevel.append(temp);
		currentLevel = temp;
		temp = null;
	}

	return currentLevel;
}

function findSelector(criticalCss, selectorLevels) {
	var result = null,
		currentLevel = null,
		temp = null,
		i = null;

	currentLevel = criticalCss;

	for (i = 0; i < selectorLevels.length; i++) {
		temp = selectorLevels[i];
		currentLevel = currentLevel.last;

		if (typeof currentLevel === 'undefined' || areTheSame(temp, currentLevel) === false) {
			currentLevel = null;
			break;
		}
	}

	result = currentLevel;

	return result;
}

function areTheSame(a, b) {
	var tempA = null,
		tempB = null,
		result = false;

	numberOfSameChecks++;

	if (a.type === b.type) {
		tempA = a.clone().removeAll()
		tempB = b.clone().removeAll();

		if (tempA.toString() === tempB.toString()) {
			result =  true;
		}
	}

	return result;
}

function getParents(line) {
	 var parents = [],
		currentParent = null,
		temp = null;

	currentParent = line.parent;

	while (typeof currentParent !== 'undefined' && currentParent.type !== 'root') {
		temp = currentParent.clone();
		clearLevel(temp);
		parents.push(temp);
		temp = null;
		currentParent = currentParent.parent;
	}

	parents = parents.reverse();

	return parents;
}

module.exports = postcss.plugin('postcss-critical-split', CriticalSplit);
<commit_msg>brought back the critical-block-tag, renamed the pattern option; this now now longer works. Sorry about the breaking change but for the sake of cleanliness, this was required.<commit_after>'use strict';
var path = require('path'),
	fs = require('fs'),
	merge = require('merge'),
	postcss = require('postcss'),
	userOptions = null,
	criticalActive = false,
	numberOfLinesInOriginalCss = 0,
	numberOfSameChecks = 0,
	numberOfSelectorSearches = 0,
	defaults = {
		'startTag': 'critical:start',
		'endTag': 'critical:end',
		'blockTag': 'critical',
		'suffix': '-critical'
	};

function CriticalSplit(newOptions) {
	newOptions = newOptions || {};

	return function(originalCss, result) {
		if (applyUserOptions(newOptions)) {
			performTransform(originalCss, result);
		};
	};
}

function performTransform(originalCss, result) {
	var criticalCss = postcss.root(),
		absolutePath = originalCss.source.input.file,
		cwd = process.cwd(),
		relativePath = path.relative(cwd, absolutePath),
		nonCriticalFilename = path.basename(relativePath),
		relativeDirectory = path.dirname(relativePath),
		criticalFilename = createCriticalFilename(nonCriticalFilename);

	getAllCriticals(originalCss, criticalCss);

	cleanUp(originalCss);
	cleanUp(criticalCss);

	// console.log('numberOfLinesInOriginalCss:', numberOfLinesInOriginalCss);
	// console.log('numberOfSameChecks:', numberOfSameChecks);
	// console.log('numberOfSelectorSearches:', numberOfSelectorSearches);

	fs.writeFileSync(path.join(relativeDirectory, nonCriticalFilename), originalCss.toResult());

	if (criticalCss.nodes.length > 0) {
		fs.writeFileSync(path.join(relativeDirectory, criticalFilename), criticalCss.toResult());
	}
}

function cleanUp(cssRoot) {

	var handleBlock = function(block) {
		if (block.nodes.length === 0) {
			block.remove();
		}
	};

	cssRoot.walkRules(handleBlock);
	cssRoot.walkAtRules(handleBlock);
}

function applyUserOptions(newOptions) {
	var errorMessage ='',
		result = true;

	userOptions = merge(defaults, newOptions);

	if (userOptions.startTag === userOptions.endTag) {
		errorMessage += '\n\n';
		errorMessage += 'ERROR :: PostCSS Plugin: Critical Split\n';
		errorMessage += '.Critical CSS start and end tag must not be the same. \n';
		errorMessage += 'Please adapt your options. \n\n';
		errorMessage += '------ Current Options ----- \n\n';
		errorMessage += JSON.stringify(userOptions, null, 2) + '\n\n';
		errorMessage += '---------- End -------------\n';

		console.error(errorMessage);
		result = false;
	}

	return result;
}

function createCriticalFilename(filename) {
	var position = filename.lastIndexOf('.css'),
		result = '';

	result = filename.substring(0, position);
	result += userOptions.suffix;
	result += '.css';

	return result;
}

function clearLevel(level) {
	level.walk(function(nestedRule) {
		nestedRule.remove();
	});
}

function getAllCriticals(originalCss, criticalCss) {
	var currentLevel = null;

	originalCss.walk(function(line) {
		var temp = null;

		numberOfLinesInOriginalCss++;

		if (line.type === 'comment' && line.text === userOptions.blockTag) {
			appendFullBlock(criticalCss,line);
			line.remove(); // remove tagging comment
		} else if (line.type === 'comment' && line.text === userOptions.startTag) {
			criticalActive = true;
			line.remove(); // remove tagging comment
		} else if (line.type === 'comment' && line.text === userOptions.endTag) {
			criticalActive = false
			currentLevel = null;
			line.remove(); // remove tagging comment
		} else if (criticalActive === true && (line.type === 'decl' || line.type === 'comment')) {
			appendDeclaration(criticalCss, line);
			line.remove(); // remove line from originalCss as it is now alive in criticalCss
		}
	});
}

function getBlockFromTriggerTag(line) {
	var result = null;

	if (line.parent.type !== 'root') {
		result = line.parent;
	}

	return result;
}

function appendFullBlock(criticalCss, line) {
	var currentLevel = null,
		parents = null,
		block =  getBlockFromTriggerTag(line);

	if (block !== null) {
		parents = getParents(line);
		currentLevel = prepareSelectors(criticalCss, parents);

		if (currentLevel.type === 'rule') {
			block.walk(function(line) {
				if (!(line.type === 'comment' && line.text === userOptions.blockTag)){
					// we don't want to add the blockTag comment back; skip that
					currentLevel.append(line);
					line.remove();
				}
			});
		}
	}
}

function appendDeclaration(criticalCss, line) {
	var parents = getParents(line),
		currentLevel = prepareSelectors(criticalCss, parents);

	currentLevel.append(line);
	currentLevel.raws.semicolon = true; // enforce last rule semicolon; just in case of some weird last-line comments...
}

function prepareSelectors(criticalCss, selectorLevels) {
	var currentLevel = null;

	currentLevel = findSelector(criticalCss, selectorLevels);

	if (currentLevel === null) {
		currentLevel = createSelectorLevels(criticalCss, selectorLevels);
	}

	return currentLevel;
}

function createSelectorLevels(criticalCss, selectorLevels) {
	var i = null,
		currentLevel = null,
		temp = null;

	numberOfSelectorSearches++;

	currentLevel = criticalCss;

	for (i = 0; i < selectorLevels.length; i++) {
		temp = selectorLevels[i];
		currentLevel.append(temp);
		currentLevel = temp;
		temp = null;
	}

	return currentLevel;
}

function findSelector(criticalCss, selectorLevels) {
	var result = null,
		currentLevel = null,
		temp = null,
		i = null;

	currentLevel = criticalCss;

	for (i = 0; i < selectorLevels.length; i++) {
		temp = selectorLevels[i];
		currentLevel = currentLevel.last;

		if (typeof currentLevel === 'undefined' || areTheSame(temp, currentLevel) === false) {
			currentLevel = null;
			break;
		}
	}

	result = currentLevel;

	return result;
}

function areTheSame(a, b) {
	var tempA = null,
		tempB = null,
		result = false;

	numberOfSameChecks++;

	if (a.type === b.type) {
		tempA = a.clone().removeAll()
		tempB = b.clone().removeAll();

		if (tempA.toString() === tempB.toString()) {
			result =  true;
		}
	}

	return result;
}

function getParents(line) {
	 var parents = [],
		currentParent = null,
		temp = null;

	currentParent = line.parent;

	while (typeof currentParent !== 'undefined' && currentParent.type !== 'root') {
		temp = currentParent.clone();
		clearLevel(temp);
		parents.push(temp);
		temp = null;
		currentParent = currentParent.parent;
	}

	parents = parents.reverse();

	return parents;
}

module.exports = postcss.plugin('postcss-critical-split', CriticalSplit);
<|endoftext|>