问:
Write config in Zend Framework with APPLICATION_PATH
For an application I'd like to create some kind of setup-steps. In one of the steps the database configuration is written to the application.ini file. This all works, but something very strange happens: All the paths to the directories (library, layout, ...) are changed from paths with APPLICATION_PATH . to full paths. As you can imagine, this isn't very systemfriendly. Any idea how I can prevent that?

I update the application.ini with this code:

```<code># read existing configuration
$config = new Zend_Config_Ini(
    $location,
    null,
    array('skipExtends'        => true,
    'allowModifications' => true));

# add new values
$config->production->doctrine->connection = array();
$config->production->doctrine->connection->host = $data['server'];
$config->production->doctrine->connection->user = $data['username'];
$config->production->doctrine->connection->password = $data['password'];
$config->production->doctrine->connection->database = $data['database'];

# write new configuration
$writer = new Zend_Config_Writer_Ini(
    array(
        'config'   => $config,
    'filename' => $location));
$writer->write();
</code>```

答: This is a long shot - but have you tried running your Zend_Config_Writer_Ini code while the APPLICATION_PATH constant is not defined? It should interpret it as the literal string 'APPLICATION_PATH' and could possibly work.

Body:
For an application I'd like to create some kind of setup-steps. In one of the steps the database configuration is written to the application.ini file. This all works, but something very strange happens: All the paths to the directories (library, layout, ...) are changed from paths with APPLICATION_PATH . to full paths. As you can imagine, this isn't very systemfriendly. Any idea how I can prevent that?

I update the application.ini with this code:

# read existing configuration
$config = new Zend_Config_Ini(
    $location,
    null,
    array('skipExtends'        => true,
    'allowModifications' => true));

# add new values
$config->production->doctrine->connection = array();
$config->production->doctrine->connection->host = $data['server'];
$config->production->doctrine->connection->user = $data['username'];
$config->production->doctrine->connection->password = $data['password'];
$config->production->doctrine->connection->database = $data['database'];

# write new configuration
$writer = new Zend_Config_Writer_Ini(
    array(
        'config'   => $config,
    'filename' => $location));
$writer->write();


来源: stackexchange

问:
ActionController::RoutingError (No route matches [POST] "/users")
I've tested my project with development env and everything works fine but after I upload my project to the host I got this error.

```<code># log
[2020-02-17T14:54:55.319109 #2097106]  INFO -- : [2ac848c8-15f3-47fd-ad77-ede940b1502e] Started POST "/admin/users" for my_server_ip at 2020-02-17 14:54:55 -0500
[2020-02-17T14:54:55.320555 #2097106] FATAL -- : [2ac848c8-15f3-47fd-ad77-ede940b1502e]
[2ac848c8-15f3-47fd-ad77-ede940b1502e] ActionController::RoutingError (No route matches [POST] "/users"):
[2ac848c8-15f3-47fd-ad77-ede940b1502e]
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] rack (2.1.2) lib/rack/method_override.rb:24:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] rack (2.1.2) lib/rack/runtime.rb:24:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] rack (2.1.2) lib/rack/sendfile.rb:113:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:83:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb:97:in `process_request'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:157:in `accept_and_process_next_request'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:110:in `main_loop'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/request_handler.rb:415:in `block (3 levels) in start_threads'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/utils.rb:113:in `block in create_thread_and_abort_on_exception'
</code>```

here are my routes

```<code># config/routes.rb
namespace :admin do
  resources :users
end
</code>```

and here is my form

```<code># app/views/admin/users/index.html.erb
<%= form_with(model: admin_user, local: true) do |form| %>

  # my form inputs

  <%= form.submit class: 'btn btn-dark' %>

<% end %>
</code>```

答:
Output of $ rails routes:

```<code>                           Prefix Verb   URI Pattern                                                                              Controller#Action
                      admin_users GET    /admin/users(.:format)                                                                   admin/users#index
                                  POST   /admin/users(.:format)                                                                   admin/users#create
                   new_admin_user GET    /admin/users/new(.:format)                                                               admin/users#new
                  edit_admin_user GET    /admin/users/:id/edit(.:format)                                                          admin/users#edit
                       admin_user GET    /admin/users/:id(.:format)                                                               admin/users#show
                                  PATCH  /admin/users/:id(.:format)                                                               admin/users#update
                                  PUT    /admin/users/:id(.:format)                                                               admin/users#update
                                  DELETE /admin/users/:id(.:format)                                                               admin/users#destroy
</code>```

If you are trying to route to this from a form you need to use:

```<code><%= form_with(model: [:admin, @user]) do |f| %>
</code>```

See:

Controller Namespaces and routing.

ActionDispatch::Routing::PolymorphicRoutes

ContentLicense: CC BY-SA 4.0

Body:
I've tested my project with development env and everything works fine but after I upload my project to the host I got this error.

# log
[2020-02-17T14:54:55.319109 #2097106]  INFO -- : [2ac848c8-15f3-47fd-ad77-ede940b1502e] Started POST "/admin/users" for my_server_ip at 2020-02-17 14:54:55 -0500
[2020-02-17T14:54:55.320555 #2097106] FATAL -- : [2ac848c8-15f3-47fd-ad77-ede940b1502e]
[2ac848c8-15f3-47fd-ad77-ede940b1502e] ActionController::RoutingError (No route matches [POST] "/users"):
[2ac848c8-15f3-47fd-ad77-ede940b1502e]
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] rack (2.1.2) lib/rack/method_override.rb:24:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] rack (2.1.2) lib/rack/runtime.rb:24:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] rack (2.1.2) lib/rack/sendfile.rb:113:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:83:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb:97:in `process_request'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:157:in `accept_and_process_next_request'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:110:in `main_loop'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/request_handler.rb:415:in `block (3 levels) in start_threads'
[2ac848c8-15f3-47fd-ad77-ede940b1502e] /opt/passenger-5.3.7-2.el7.cloudlinux/src/ruby_supportlib/phusion_passenger/utils.rb:113:in `block in create_thread_and_abort_on_exception'

here are my routes

# config/routes.rb
namespace :admin do
  resources :users
end

and here is my form

# app/views/admin/users/index.html.erb
<%= form_with(model: admin_user, local: true) do |form| %>

  # my form inputs

  <%= form.submit class: 'btn btn-dark' %>

<% end %>

Body:
Output of $ rails routes:

                           Prefix Verb   URI Pattern                                                                              Controller#Action
                      admin_users GET    /admin/users(.:format)                                                                   admin/users#index
                                  POST   /admin/users(.:format)                                                                   admin/users#create
                   new_admin_user GET    /admin/users/new(.:format)                                                               admin/users#new
                  edit_admin_user GET    /admin/users/:id/edit(.:format)                                                          admin/users#edit
                       admin_user GET    /admin/users/:id(.:format)                                                               admin/users#show
                                  PATCH  /admin/users/:id(.:format)                                                               admin/users#update
                                  PUT    /admin/users/:id(.:format)                                                               admin/users#update
                                  DELETE /admin/users/:id(.:format)                                                               admin/users#destroy

If you are trying to route to this from a form you need to use:

<%= form_with(model: [:admin, @user]) do |f| %>

See:

Controller Namespaces and routing.

ActionDispatch::Routing::PolymorphicRoutes


问:
Why does the line marked with //1 print 57 instead of 39?
```<code>class X {
    protected int v = 0;

    public X() {
        v += 10;
    }

    public void proc(X p) {
        System.out.println(43);
    }
}

class Y extends X {
    public Y() {
        v += 5;
    }

    public void proc(X p) {
        System.out.println(57);
    }

    public int getV() {
        return v;
    }
}

class Z extends Y {
    public Z() {
        v += 9;
    }

    public void proc(Z p) {
        System.out.println(39);
    }
}

class Main {
    public static void main(String[] args) {
        X x = new Z();
        Y y = new Z();
        Z z = new Z();
        x.proc(z);// 1
        System.out.println(y.getV());
    }
}
</code>```

From what I can understand,the method proc() is called on an object of type X that "holds" a type Z and at runtime JVM checks the object's type and overrides the method with the proc() method from Y.But the method parameter is of type Z,why doesn't it call the overloaded method from the Z class?

答:
Just to elaborate over Federico answer.
The "x" object is, in fact, a "X" variable that point to a "Z" instance in memory. "Z" instance has only two methods:

```<code>void proc(Z p)
void proc(X p)
</code>```

But the runtime only is aware of the second method that is implemented at "X" class and its overridden by the method implemented in "Y" class.
So, when you call:

```<code>x.proc(z)
</code>```

The runtime only knows about of this second method and call it, executing the overridden one.

Body:
class X {
    protected int v = 0;

    public X() {
        v += 10;
    }

    public void proc(X p) {
        System.out.println(43);
    }
}

class Y extends X {
    public Y() {
        v += 5;
    }

    public void proc(X p) {
        System.out.println(57);
    }

    public int getV() {
        return v;
    }
}

class Z extends Y {
    public Z() {
        v += 9;
    }

    public void proc(Z p) {
        System.out.println(39);
    }
}

class Main {
    public static void main(String[] args) {
        X x = new Z();
        Y y = new Z();
        Z z = new Z();
        x.proc(z);// 1
        System.out.println(y.getV());
    }
}

From what I can understand,the method proc() is called on an object of type X that "holds" a type Z and at runtime JVM checks the object's type and overrides the method with the proc() method from Y.But the method parameter is of type Z,why doesn't it call the overloaded method from the Z class?

Body:
Just to elaborate over Federico answer.
The "x" object is, in fact, a "X" variable that point to a "Z" instance in memory. "Z" instance has only two methods:

void proc(Z p)
void proc(X p)

But the runtime only is aware of the second method that is implemented at "X" class and its overridden by the method implemented in "Y" class.
So, when you call:

x.proc(z)

The runtime only knows about of this second method and call it, executing the overridden one.


问:
Are there a Play, Pause, Rewind, Fast Forward methods in Android?
I am working on an Android application that allows the user to speak into the device. Then i want to save that, and rewind part of it to play it again, maybe fast forward to another part of the audio, pause it, play it, etc. Like a basic tape recorder.

Are there any built APIs or methods or code to allow this? If not, then where do I go from here?

Any help would be greatly appreciated.

答:
//Test Below Cod</p>

```<code>double duration = mediaPlayer.getCurrentTime().toSeconds();
if (e.getKeyCode()==39)
{

    if (duration < mediaPlayer.getTotalDuration().toSeconds()-5)
        duration = duration + 5;
    else
        duration = mediaPlayer.getTotalDuration().toSeconds();
    //...
    mediaPlayer.setStartTime(Duration.seconds(duration));

}else
if (e.getKeyCode()==37)
{
    if (duration > 5)
        duration = duration - 5;
    else
        duration = 0;
    //...
    mediaPlayer.setStartTime(Duration.seconds(duration));
}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
//Test Below Cod

double duration = mediaPlayer.getCurrentTime().toSeconds();
if (e.getKeyCode()==39)
{

    if (duration < mediaPlayer.getTotalDuration().toSeconds()-5)
        duration = duration + 5;
    else
        duration = mediaPlayer.getTotalDuration().toSeconds();
    //...
    mediaPlayer.setStartTime(Duration.seconds(duration));

}else
if (e.getKeyCode()==37)
{
    if (duration > 5)
        duration = duration - 5;
    else
        duration = 0;
    //...
    mediaPlayer.setStartTime(Duration.seconds(duration));
}


问:
Is the following a proper way to write long computations in JavaScript that needs to run on a browser?
I am trying to use async / await to do long computations on JavaScript on a browser.  Should the code be changed or any improvements be done? It seems using promises may make it complicated.  I also have two related questions at the end of the question.

It was doing 60000! (factorial), and the answer is too long to show on screen, so the number of digits of the answer in binary is being shown. (showing the number of digits of the answer in decimal took too long for the conversion).

The iterative version is:

(some note: the computation won't start until 3 seconds later, to show how the UI looks like without the computation).

(function() {
      let startTimeOfProgram = performance.now(),
      timer = 3,
      element = $("#status-display-content"),
      elementTimer = $("#timer");

      setInterval(() => { elementTimer.html((Math.round((performance.now() - startTimeOfProgram) / 10) / 100).toFixed(2)) }, 33);

      function updateState() {
        element.html(timer--).css({ transition: "none" }).css({ opacity: 1 });
        if (timer < 0) timer = 3;

        // need to be next cycle because cannot change
        // transition and have it animated all in the same cycle
        setTimeout(function() {
          element.css({ transition: "opacity 1s" }).css({ opacity: 0 }).on("transitionend", () => { updateState(); element.off("transitionend"); });
        }, 0);
      }

      updateState();

      function binaryLength(n) {
        return n.toString(2).length;
      }

      const occasionalSleeper = (function() {
        let lastSleepingTime = performance.now();

        return function() {
          if (performance.now() - lastSleepingTime > 33) {
            lastSleepingTime = performance.now();
            return new Promise(resolve => setTimeout(resolve, 0));
          } else {
            return Promise.resolve();
          }
        }
      }());

      async function asyncBigIntFactorial(n) {
        let start = performance.now();

        n = BigInt(n);
        if (n <= 1n) return 1n;

        let result = 1n;
        for (let i = 2n; i <= n; i++) {
          await occasionalSleeper();
          result *= i;
        }
        console.log("Time taken", (performance.now() - start) / 1000);
        return result;
      }

      setTimeout(function() {
        let startTimeOfComputation = performance.now();
        asyncBigIntFactorial(60000).then(result => {
          $("#calculation-result")
          .html(`Number of digits of answer in binary: ${binaryLength(result)}<br>Time it took: ${Math.round((performance.now() - startTimeOfComputation) / 10) / 100} seconds`);
        });
      }, 3000);

    }());```
<pre class="snippet-code-css lang-css prettyprint-override"><code>#status-display {
      background-color: #000;
      color: green;
      font: 111px Arial, sans-serif;
      width: 150px;
      height: 150px;
      border-radius: 21%;
      text-align: center;
      line-height: 150px;
    }

    #timer {
      width: 150px;
      text-align: center;
      font: 15px Arial, sans-serif;
    }

    #status-display-content {
      transition: opacity 1s
    }

    #calculation-result {
      margin-left: .3em;
    }
    #left-panel, #calculation-result {
      display: inline-block;
    }</code>```

```
</div>
</div>
</p>

<p>It is also on: http://jsfiddle.net/rxdpbvku/</p>

<p>It can be contrasted with the version with the <code>await occasionalSleeper()</code> commented out, with the UI not responsive during the computation: http://jsfiddle.net/fhL2gqpn/</p>

<p>Basically, it is using an <code>occasionalSleeper()</code> and call <code>await occasionalSleeper()</code> during the computation.</p>

```const occasionalSleeper = (function() {
  let lastSleepingTime = performance.now();

  return function() {
    if (performance.now() - lastSleepingTime > 33) {
      lastSleepingTime = performance.now();
      return new Promise(resolve => setTimeout(resolve, 0));
    } else {
      return Promise.resolve();
    }
  }
}());
```

<p>and the calculation part is:</p>

```async function asyncBigIntFactorial(n) {
  let start = performance.now();

  n = BigInt(n);
  if (n <= 1n) return 1n;

  let result = 1n;
  for (let i = 2n; i <= n; i++) {
    await occasionalSleeper();
    result *= i;
  }
  console.log("Time taken", (performance.now() - start) / 1000);
  return result;
}
```

<p>The recursive version is:</p>

<p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>(function() {
      let startTimeOfProgram = performance.now(),
      timer = 3,
      element = $("#status-display-content"),
      elementTimer = $("#timer");

      setInterval(() => { elementTimer.html((Math.round((performance.now() - startTimeOfProgram) / 10) / 100).toFixed(2)) }, 33);

      function updateState() {
        element.html(timer--).css({ transition: "none" }).css({ opacity: 1 });
        if (timer < 0) timer = 3;

        // need to be next cycle because cannot change
        // transition and have it animated all in the same cycle
        setTimeout(function() {
          element.css({ transition: "opacity 1s" }).css({ opacity: 0 }).on("transitionend", () => { updateState(); element.off("transitionend"); });
        }, 0);
      }

      updateState();

      function binaryLength(n) {
        return n.toString(2).length;
      }

      const occasionalSleeper = (function() {
        let lastSleepingTime = performance.now();

        return function() {
          if (performance.now() - lastSleepingTime > 33) {
            lastSleepingTime = performance.now();
            return new Promise(resolve => setTimeout(resolve, 0));
          } else {
            return Promise.resolve();
          }
        }
      }());

      async function asyncBigIntFactorial(n) {
        let start = performance.now();

        async function factorialHelper(n) {
          n = BigInt(n);
          if (n <= 1n) return 1n;

          await occasionalSleeper();

          let simplerAnswer = factorialHelper(n - 1n);

          return simplerAnswer.then(async function(a) {
            await occasionalSleeper();
            return n * a;
          });
        }

        let result = factorialHelper(n);
        console.log("Time taken", (performance.now() - start) / 1000);
        return result;
      }

      setTimeout(function() {
        let startTimeOfComputation = performance.now();
        asyncBigIntFactorial(60000).then(result => {
          $("#calculation-result")
          .html(`Number of digits of answer in binary: ${binaryLength(result)}<br>Time it took: ${Math.round((performance.now() - startTimeOfComputation) / 10) / 100} seconds`);
        });
      }, 3000);

    }());</code>```

#status-display {
      background-color: #000;
      color: green;
      font: 111px Arial, sans-serif;
      width: 150px;
      height: 150px;
      border-radius: 21%;
      text-align: center;
      line-height: 150px;
    }

    #timer {
      width: 150px;
      text-align: center;
      font: 15px Arial, sans-serif;
    }

    #status-display-content {
      transition: opacity 1s
    }

    #calculation-result {
      margin-left: .3em;
    }

    #left-panel, #calculation-result {
      display: inline-block;
    }```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="left-panel">
<div id="status-display">
    <div id="status-display-content">
    </div>
  </div>

  <div id="timer"></div>
</div>
<div id="calculation-result"></div></code>```

It is also on: http://jsfiddle.net/rxdpbvku/

The recursive version reported finishing almost instantaneously, because at that time only the promise was created.

Some observations:

If inside of:

```<code>          return simplerAnswer.then(async function(a) {
            await occasionalSleeper();
            return n * a;
          });
</code>```

if the await occasionalSleeper() is commented out (or if that function is not an async function), it seems the final unwrapping of the promises will cause it to pause the UI. (I think it is the final unwrapping of 60000 promises).  JSFiddle: http://jsfiddle.net/y0827r16/

Another observation is, if it is a real recursion, calling itself 60,000 times deep will cause a stack overflow. But using async / await, it won't.  Why is that? Is it because it is like a table of resolving or unwrapping promises, so a table of 60,000 entries is not a problem at all.

I also have a question is that if inside any async function, if such occasionalSleeper() is added automatically by the async standard, then won't it make the programmer not have to worry where to add them?

答:
As stated in comments, for long-lasting calculations, you could use Web Workers. That way you can keep your browser interactive, while not having to introduce setTimeout "hops" at regular times.

To make use of web workers as easily as possible, I would suggest using this generic "plugin" code, which I suggested earlier in this answer:

```<code>Function.prototype.callAsWorker = function (...args) {
    return new Promise( (resolve, reject) => {
        const code = `self.onmessage = e => self.postMessage((${this.toString()}).call(...e.data));`,
            blob = new Blob([code], { type: "text/javascript" }),
            worker = new Worker(window.URL.createObjectURL(blob));
        worker.onmessage = e => (resolve(e.data), worker.terminate());
        worker.onerror = e => (reject(e.message), worker.terminate());
        worker.postMessage(args);
    });
}
</code>```

Now you can let a web worker execute any pure function with the following syntax:

```<code>myPureAdditionFunction.callAsWorker(null, 1, 2)
                      .then((sum) => console.log("1+2=" + sum));
</code>```

As said, this takes away the need to inject the execution with something likeoccasionalSleeper().

Your core function can just be:

```<code>function bigIntFactorial(n) {
    n = BigInt(n);
    let result = 1n;
    for (let i = 2n; i <= n; i++) result *= i;
    return result;
}
</code>```

And the call:

```<code>bigIntFactorial.callAsWorker(null, 60000).then(/* handler */);
</code>```

I adapted your snippet to use this method. I also removed the 3 second run-in time, as with a web worker you don't have to worry about the DOM and the paint events.

let startTimeOfProgram = performance.now(),
    timer = 3,
    element = $("#status-display-content"),
    elementTimer = $("#timer");

let stopWatch = setInterval(() => {
    elementTimer.html((Math.round((performance.now() - startTimeOfProgram) / 10) / 100).toFixed(2))
}, 33);

function updateState() {
    element.html(timer--).css({ transition: "none" })
                         .css({ opacity: 1 });
    if (timer < 0) timer = 3;

    // need to be next cycle because cannot change
    // transition and have it animated all in the same cycle
    setTimeout(function() {
        element.css({ transition: "opacity 1s" })
               .css({ opacity: 0 })
               .on("transitionend", () => {
                    if (stopWatch) updateState();
                    element.off("transitionend");
                });
    });
}

updateState();

const binaryLength = n => n.toString(2).length;

Function.prototype.callAsWorker = function (...args) {
    return new Promise( (resolve, reject) => {
        const code = `self.onmessage = e => self.postMessage((${this}).call(...e.data));`,
            blob = new Blob([code], { type: "text/javascript" }),
            worker = new Worker(window.URL.createObjectURL(blob));
        worker.onmessage = e => (resolve(e.data), worker.terminate());
        worker.onerror = e => (reject(e.message), worker.terminate());
        worker.postMessage(args);
    });
}

function bigIntFactorial(n) {
    n = BigInt(n);
    let result = 1n;
    for (let i = 2n; i <= n; i++) result *= i;
    return result;
}

bigIntFactorial.callAsWorker(null, 60000).then(result => {
    clearInterval(stopWatch);
    stopWatch = null;
    $("#calculation-result")
        .html(`Number of digits of answer in binary: ${binaryLength(result)}

               Time it took: ${Math.round((performance.now() - startTimeOfProgram) / 10) / 100} seconds`);
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>#status-display {
    background-color: #000;
    color: green;
    font: 111px Arial, sans-serif;
    width: 150px;
    height: 150px;
    border-radius: 21%;
    text-align: center;
    line-height: 150px;
}

#timer {
  width: 150px;
  text-align: center;
  font: 15px Arial, sans-serif;
}

#status-display-content {
  transition: opacity 1s
}

#calculation-result {
  margin-left: .3em;
}

#left-panel, #calculation-result {
  display: inline-block;
}</code>```

```

Your Questions

Concerning your recursive solution, you wrote:

if the await occasionalSleeper() is commented out (or if that function is not an async function), it seems the final unwrapping of the promises will cause it to pause the UI.

Indeed, that is because you have a long chain of immediately resolving promises, without any setTimeout. Your async callback has no await, so it returns an immediately resolving promise. A promise resolution puts a job in the Promise Job Queue, which is serviced right after the call stack is empty, but still as part of the current task. So the browser's event queue is not serviced while there is something pending in the Promise Job Queue. As a result, such a long chain of resolving promises blocks the UI.

If it is a real recursion, calling itself 60,000 times deep will cause a stack overflow. But using async / await, it won't. Why is that?

This is because you don't really have recursion going on in a way where a current call is waiting for the recursive one to finish. Not here. You have the recursive call of the async happening after an await. This means that the recursive call will return when it processes the await. It returns with a promise, and the current execution context can continue. Only when it reaches the end, the await of the nested call, gets a chance to get the execution back by an event in the Promise Job Queue. And so you see there is not really a stack of function calls here. It is a chain, driven by a FIFO queue... the Promise Job queue.

If inside any async function, if such occasionalSleeper() is added automatically by the async standard, then won't it make the programmer not have to worry where to add them?

That might be a tempting idea, but be aware that EcmaScript is not covering the agent part; it focusses on the core language, which includes promises, async and await, but excludes the exact definition of the (other) event queues. That is covered in other specifications, such as the specifications drafted by the WHATWG.

Altering the meaning of async to include aspects of non-blocking UI go beyond the scope of the language.

Anyway, with Web Workers (not part of core EcmaScript, but specified in the HTML Living Standard), there is a satisfying solution.

Body:
I am trying to use async / await to do long computations on JavaScript on a browser.  Should the code be changed or any improvements be done? It seems using promises may make it complicated.  I also have two related questions at the end of the question.

It was doing 60000! (factorial), and the answer is too long to show on screen, so the number of digits of the answer in binary is being shown. (showing the number of digits of the answer in decimal took too long for the conversion).

The iterative version is:

(some note: the computation won't start until 3 seconds later, to show how the UI looks like without the computation).

(function() {
      let startTimeOfProgram = performance.now(),
      timer = 3,
      element = $("#status-display-content"),
      elementTimer = $("#timer");

      setInterval(() => { elementTimer.html((Math.round((performance.now() - startTimeOfProgram) / 10) / 100).toFixed(2)) }, 33);

      function updateState() {
        element.html(timer--).css({ transition: "none" }).css({ opacity: 1 });
        if (timer < 0) timer = 3;

        // need to be next cycle because cannot change
        // transition and have it animated all in the same cycle
        setTimeout(function() {
          element.css({ transition: "opacity 1s" }).css({ opacity: 0 }).on("transitionend", () => { updateState(); element.off("transitionend"); });
        }, 0);
      }

      updateState();

      function binaryLength(n) {
        return n.toString(2).length;
      }

      const occasionalSleeper = (function() {
        let lastSleepingTime = performance.now();

        return function() {
          if (performance.now() - lastSleepingTime > 33) {
            lastSleepingTime = performance.now();
            return new Promise(resolve => setTimeout(resolve, 0));
          } else {
            return Promise.resolve();
          }
        }
      }());

      async function asyncBigIntFactorial(n) {
        let start = performance.now();

        n = BigInt(n);
        if (n <= 1n) return 1n;

        let result = 1n;
        for (let i = 2n; i <= n; i++) {
          await occasionalSleeper();
          result *= i;
        }
        console.log("Time taken", (performance.now() - start) / 1000);
        return result;
      }

      setTimeout(function() {
        let startTimeOfComputation = performance.now();
        asyncBigIntFactorial(60000).then(result => {
          $("#calculation-result")
          .html(`Number of digits of answer in binary: ${binaryLength(result)}<br>Time it took: ${Math.round((performance.now() - startTimeOfComputation) / 10) / 100} seconds`);
        });
      }, 3000);

    }());

#status-display {
      background-color: #000;
      color: green;
      font: 111px Arial, sans-serif;
      width: 150px;
      height: 150px;
      border-radius: 21%;
      text-align: center;
      line-height: 150px;
    }

    #timer {
      width: 150px;
      text-align: center;
      font: 15px Arial, sans-serif;
    }

    #status-display-content {
      transition: opacity 1s
    }

    #calculation-result {
      margin-left: .3em;
    }
    #left-panel, #calculation-result {
      display: inline-block;
    }

It is also on: http://jsfiddle.net/rxdpbvku/

It can be contrasted with the version with the await occasionalSleeper() commented out, with the UI not responsive during the computation: http://jsfiddle.net/fhL2gqpn/

Basically, it is using an occasionalSleeper() and call await occasionalSleeper() during the computation.

const occasionalSleeper = (function() {
  let lastSleepingTime = performance.now();

  return function() {
    if (performance.now() - lastSleepingTime > 33) {
      lastSleepingTime = performance.now();
      return new Promise(resolve => setTimeout(resolve, 0));
    } else {
      return Promise.resolve();
    }
  }
}());

and the calculation part is:

async function asyncBigIntFactorial(n) {
  let start = performance.now();

  n = BigInt(n);
  if (n <= 1n) return 1n;

  let result = 1n;
  for (let i = 2n; i <= n; i++) {
    await occasionalSleeper();
    result *= i;
  }
  console.log("Time taken", (performance.now() - start) / 1000);
  return result;
}

The recursive version is:

(function() {
      let startTimeOfProgram = performance.now(),
      timer = 3,
      element = $("#status-display-content"),
      elementTimer = $("#timer");

      setInterval(() => { elementTimer.html((Math.round((performance.now() - startTimeOfProgram) / 10) / 100).toFixed(2)) }, 33);

      function updateState() {
        element.html(timer--).css({ transition: "none" }).css({ opacity: 1 });
        if (timer < 0) timer = 3;

        // need to be next cycle because cannot change
        // transition and have it animated all in the same cycle
        setTimeout(function() {
          element.css({ transition: "opacity 1s" }).css({ opacity: 0 }).on("transitionend", () => { updateState(); element.off("transitionend"); });
        }, 0);
      }

      updateState();

      function binaryLength(n) {
        return n.toString(2).length;
      }

      const occasionalSleeper = (function() {
        let lastSleepingTime = performance.now();

        return function() {
          if (performance.now() - lastSleepingTime > 33) {
            lastSleepingTime = performance.now();
            return new Promise(resolve => setTimeout(resolve, 0));
          } else {
            return Promise.resolve();
          }
        }
      }());

      async function asyncBigIntFactorial(n) {
        let start = performance.now();

        async function factorialHelper(n) {
          n = BigInt(n);
          if (n <= 1n) return 1n;

          await occasionalSleeper();

          let simplerAnswer = factorialHelper(n - 1n);

          return simplerAnswer.then(async function(a) {
            await occasionalSleeper();
            return n * a;
          });
        }

        let result = factorialHelper(n);
        console.log("Time taken", (performance.now() - start) / 1000);
        return result;
      }

      setTimeout(function() {
        let startTimeOfComputation = performance.now();
        asyncBigIntFactorial(60000).then(result => {
          $("#calculation-result")
          .html(`Number of digits of answer in binary: ${binaryLength(result)}<br>Time it took: ${Math.round((performance.now() - startTimeOfComputation) / 10) / 100} seconds`);
        });
      }, 3000);

    }());

#status-display {
      background-color: #000;
      color: green;
      font: 111px Arial, sans-serif;
      width: 150px;
      height: 150px;
      border-radius: 21%;
      text-align: center;
      line-height: 150px;
    }

    #timer {
      width: 150px;
      text-align: center;
      font: 15px Arial, sans-serif;
    }

    #status-display-content {
      transition: opacity 1s
    }

    #calculation-result {
      margin-left: .3em;
    }

    #left-panel, #calculation-result {
      display: inline-block;
    }

It is also on: http://jsfiddle.net/rxdpbvku/

The recursive version reported finishing almost instantaneously, because at that time only the promise was created.

Some observations:

If inside of:

          return simplerAnswer.then(async function(a) {
            await occasionalSleeper();
            return n * a;
          });

if the await occasionalSleeper() is commented out (or if that function is not an async function), it seems the final unwrapping of the promises will cause it to pause the UI. (I think it is the final unwrapping of 60000 promises).  JSFiddle: http://jsfiddle.net/y0827r16/

Another observation is, if it is a real recursion, calling itself 60,000 times deep will cause a stack overflow. But using async / await, it won't.  Why is that? Is it because it is like a table of resolving or unwrapping promises, so a table of 60,000 entries is not a problem at all.

I also have a question is that if inside any async function, if such occasionalSleeper() is added automatically by the async standard, then won't it make the programmer not have to worry where to add them?

Body:
As stated in comments, for long-lasting calculations, you could use Web Workers. That way you can keep your browser interactive, while not having to introduce setTimeout "hops" at regular times.

To make use of web workers as easily as possible, I would suggest using this generic "plugin" code, which I suggested earlier in this answer:

Function.prototype.callAsWorker = function (...args) {
    return new Promise( (resolve, reject) => {
        const code = `self.onmessage = e => self.postMessage((${this.toString()}).call(...e.data));`,
            blob = new Blob([code], { type: "text/javascript" }),
            worker = new Worker(window.URL.createObjectURL(blob));
        worker.onmessage = e => (resolve(e.data), worker.terminate());
        worker.onerror = e => (reject(e.message), worker.terminate());
        worker.postMessage(args);
    });
}

Now you can let a web worker execute any pure function with the following syntax:

myPureAdditionFunction.callAsWorker(null, 1, 2)
                      .then((sum) => console.log("1+2=" + sum));

As said, this takes away the need to inject the execution with something likeoccasionalSleeper().

Your core function can just be:

function bigIntFactorial(n) {
    n = BigInt(n);
    let result = 1n;
    for (let i = 2n; i <= n; i++) result *= i;
    return result;
}

And the call:

bigIntFactorial.callAsWorker(null, 60000).then(/* handler */);

I adapted your snippet to use this method. I also removed the 3 second run-in time, as with a web worker you don't have to worry about the DOM and the paint events.

let startTimeOfProgram = performance.now(),
    timer = 3,
    element = $("#status-display-content"),
    elementTimer = $("#timer");

let stopWatch = setInterval(() => {
    elementTimer.html((Math.round((performance.now() - startTimeOfProgram) / 10) / 100).toFixed(2))
}, 33);

function updateState() {
    element.html(timer--).css({ transition: "none" })
                         .css({ opacity: 1 });
    if (timer < 0) timer = 3;

    // need to be next cycle because cannot change
    // transition and have it animated all in the same cycle
    setTimeout(function() {
        element.css({ transition: "opacity 1s" })
               .css({ opacity: 0 })
               .on("transitionend", () => {
                    if (stopWatch) updateState();
                    element.off("transitionend");
                });
    });
}

updateState();

const binaryLength = n => n.toString(2).length;

Function.prototype.callAsWorker = function (...args) {
    return new Promise( (resolve, reject) => {
        const code = `self.onmessage = e => self.postMessage((${this}).call(...e.data));`,
            blob = new Blob([code], { type: "text/javascript" }),
            worker = new Worker(window.URL.createObjectURL(blob));
        worker.onmessage = e => (resolve(e.data), worker.terminate());
        worker.onerror = e => (reject(e.message), worker.terminate());
        worker.postMessage(args);
    });
}

function bigIntFactorial(n) {
    n = BigInt(n);
    let result = 1n;
    for (let i = 2n; i <= n; i++) result *= i;
    return result;
}

bigIntFactorial.callAsWorker(null, 60000).then(result => {
    clearInterval(stopWatch);
    stopWatch = null;
    $("#calculation-result")
        .html(`Number of digits of answer in binary: ${binaryLength(result)}<br>
               Time it took: ${Math.round((performance.now() - startTimeOfProgram) / 10) / 100} seconds`);
});

#status-display {
    background-color: #000;
    color: green;
    font: 111px Arial, sans-serif;
    width: 150px;
    height: 150px;
    border-radius: 21%;
    text-align: center;
    line-height: 150px;
}

#timer {
  width: 150px;
  text-align: center;
  font: 15px Arial, sans-serif;
}

#status-display-content {
  transition: opacity 1s
}

#calculation-result {
  margin-left: .3em;
}

#left-panel, #calculation-result {
  display: inline-block;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="left-panel">
  <div id="status-display">
    <div id="status-display-content">
    </div>
  </div>

  <div id="timer"></div>
</div>
<div id="calculation-result"></div>

Your Questions

Concerning your recursive solution, you wrote:

if the await occasionalSleeper() is commented out (or if that function is not an async function), it seems the final unwrapping of the promises will cause it to pause the UI.

Indeed, that is because you have a long chain of immediately resolving promises, without any setTimeout. Your async callback has no await, so it returns an immediately resolving promise. A promise resolution puts a job in the Promise Job Queue, which is serviced right after the call stack is empty, but still as part of the current task. So the browser's event queue is not serviced while there is something pending in the Promise Job Queue. As a result, such a long chain of resolving promises blocks the UI.

If it is a real recursion, calling itself 60,000 times deep will cause a stack overflow. But using async / await, it won't. Why is that?

This is because you don't really have recursion going on in a way where a current call is waiting for the recursive one to finish. Not here. You have the recursive call of the async happening after an await. This means that the recursive call will return when it processes the await. It returns with a promise, and the current execution context can continue. Only when it reaches the end, the await of the nested call, gets a chance to get the execution back by an event in the Promise Job Queue. And so you see there is not really a stack of function calls here. It is a chain, driven by a FIFO queue... the Promise Job queue.

If inside any async function, if such occasionalSleeper() is added automatically by the async standard, then won't it make the programmer not have to worry where to add them?

That might be a tempting idea, but be aware that EcmaScript is not covering the agent part; it focusses on the core language, which includes promises, async and await, but excludes the exact definition of the (other) event queues. That is covered in other specifications, such as the specifications drafted by the WHATWG.

Altering the meaning of async to include aspects of non-blocking UI go beyond the scope of the language.

Anyway, with Web Workers (not part of core EcmaScript, but specified in the HTML Living Standard), there is a satisfying solution.


问:
How to know the first blank cell in a column in Excel or Google Spreadsheet using only native formulas
Suppose A2,A3,A4 are filled. A5,A6 are empty. A7-10 are filled.

Is there a way to know that A5 is the first blank cell after A2?

For example,

```<code>A1 | =sum(...)
A2 | 3
A3 | 4
A4 | 1
A5 |
A6 | =sum(...)
A7 | 2
A8 | 5
A9 | 7
A10| 10
</code>```

What one formula may we use to replace "..." in order to sum the cells below until the next blank cell? ie. Can a formula on A1 for sum(A2:A4) be re-used on A6 for sum(A7:A10) by just copy-paste?

Here is my story of failed attempts.

So the starting row is easy to get. Just put in A2.
For the end row, Google Spreadsheet doesn't equate "" with empty cell. So sum(A2:index(match("",A2:A))) will not work.

isblank() with an array input will give a single output FALSE regardless of the content. So sum(A2:index(match(TRUE,isblank(A2:A)))) won't work.

What can I do to make it work?

答:
in order to find the first empty cell with MATCH you can do the following

=MATCH("@",ARRAYFORMULA(A2:A&"@"),0)

This is needed because MATCH doesn't work with blank cells, as you found out.

Body:
Suppose A2,A3,A4 are filled. A5,A6 are empty. A7-10 are filled.

Is there a way to know that A5 is the first blank cell after A2?

For example,

A1 | =sum(...)
A2 | 3
A3 | 4
A4 | 1
A5 |
A6 | =sum(...)
A7 | 2
A8 | 5
A9 | 7
A10| 10

What one formula may we use to replace "..." in order to sum the cells below until the next blank cell? ie. Can a formula on A1 for sum(A2:A4) be re-used on A6 for sum(A7:A10) by just copy-paste?

Here is my story of failed attempts.

So the starting row is easy to get. Just put in A2.
For the end row, Google Spreadsheet doesn't equate "" with empty cell. So sum(A2:index(match("",A2:A))) will not work.

isblank() with an array input will give a single output FALSE regardless of the content. So sum(A2:index(match(TRUE,isblank(A2:A)))) won't work.

What can I do to make it work?


问:
What is the difference between gtag implementation and gtm implementations?
I'm new with the new API of google analytics, so I noticed now we also have GTM and as far as I understand is now we can use it to configure events and some other things using GTM tool directly without write any line of code.

GTM is something we don't need for the moment, so I decided to use the gtag.js core to create my implementation.

```<code><script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'UA-XXXXXXXX-1');
</script>
</code>```

And using that script I access the dataLayer array with gtag({object}) So first I tried with this:

```<code>gtag({'event' : 'MyCustomEvent',
'eventCategory' : 'MyCustomCategory',
'eventValue': undefined})
</code>```

But events were not triggered until I modified my code to:

```<code>gtag('event' : 'MyCustomEvent', {
'event_category' : 'MyCustomCategory',
'event_value': undefined})
</code>```

Are gtm and gtag different in the core? I mean, do each dataLayer works different in each implementation? I ask this because the first implementation should work as far as I understood.

https://www.analyticsmania.com/post/google-tag-manager-custom-event-trigger/

答:
Both Tag Manager and gtag.js perform similar functions:

Tag Manager is a tag management system that allows you to quickly and easily update tags on your website or mobile app from a web interface.

gtag.js is the JavaScript framework that is used to add Google tags directly to web pages.

Both solutions are built on the same core Google infrastructure, and are interoperable. You are free to choose the solution that best suits your needs.

Consider Tag Manager if you need:

The ability to deploy and modify both Google and 3rd party tags

The ability to deploy and modify tags for both web and mobile apps

The ability to deploy and modify tags on the fly from a web interface

Collaboration and versioning capabilities

Consider gtag.js if you are unable to use Google Tag Manager, or the following capabilities are important to you:

The ability to install tags directly on your web page, without the ramp-up time of setting up a tag management system

The ability to work with your tags directly in JavaScript without being required to work with a separate interface

https://support.google.com/tagmanager/answer/7582054?hl=en

Body:
I'm new with the new API of google analytics, so I noticed now we also have GTM and as far as I understand is now we can use it to configure events and some other things using GTM tool directly without write any line of code.

GTM is something we don't need for the moment, so I decided to use the gtag.js core to create my implementation.

And using that script I access the dataLayer array with gtag({object}) So first I tried with this:

gtag({'event' : 'MyCustomEvent',
'eventCategory' : 'MyCustomCategory',
'eventValue': undefined})

But events were not triggered until I modified my code to:

gtag('event' : 'MyCustomEvent', {
'event_category' : 'MyCustomCategory',
'event_value': undefined})

Are gtm and gtag different in the core? I mean, do each dataLayer works different in each implementation? I ask this because the first implementation should work as far as I understood.

https://www.analyticsmania.com/post/google-tag-manager-custom-event-trigger/


问:
How to pass the details of an AWS instance to a jenkins job, for the job to ssh and execute in the instance
I am trying to move the execution of automated scripts(Jenkins jobs) in my organization from local server to AWS. I have  a Jenkins job to bring up an ec2 instance from the snapshot.  The instance which I have brought up consists of 5 user profiles, a total of 5 automation  jobs can login to the instance and execute their scripts.

My problem is, the instance I'm bringing up will be terminated once the jobs have been executed(Since we execute those scripts around 3 to 4 times in a month). So each time, I bring up an instance , it will have different IP address, which needs to be passed to the other Jenkins jobs, for the jobs to login into the instance and execute the scripts. My questions is as follows.

How to pass the details of the instance to the jenkins , making the process dynamic?
Are there any other ways , by which this problem can be solved(any solution which you might have implemented at your organisation)?

答:
There are two things that you want to configure in your Jenkins in order to pass parameters to your jobs.

Enable "Trigger build remotely" in the Build Triggers. Read more about it here.

Enable "This project is parameterized" and configure your parameters. Read more about it here.

Now you can start your jobs remotely and pass parameters in your URI like so:

http://server/job/myjob/buildWithParameters?token=TOKEN&PARAMETER=Value

this is also explained in the second link.

Then all thats left to do is add the parameter to your command line args for your script. So if you use Execute Shell build step it would look like this:

python /path/to/file/scripit.py --some_arg ${PARAMETER}


问:
What is the top movie genre using the average rank per movie genre as the metric?
Currently, I am teaching my self SQL and i came across a very interesting question which says:
Based ratings with 10,000 or more votes, what is the top movie genre using the
average rank per movie genre as the metric?
(Note: where a higher value for rank is considered a better movie)

So here are the tables: rating

```<code>+---------+------+--------+--------------+
| movieid | rank | votes  | distribution |
+---------+------+--------+--------------+
| 1672052 | 7.8  |   8111 | 0000001222   |
| 1672111 | 5.3  |  32183 | 0001221000   |
| 1672580 | 4.4  |   1894 | 0011110000   |
| 1672716 | 7.0  |   1255 | 0000001212   |
| 1673647 | 6.5  |    128 | 0000111211   |
| 1673658 | 3.9  |     20 | 22101.10.1   |
| 1673848 | 7.0  | 137748 | 0000012211   |
| 1674388 | 5.5  |  47380 | 0001221000   |
</code>```

Table: movie_directores

```<code>+---------+------------+-------------+
| movieid | directorid | genre       |
+---------+------------+-------------+
| 1672052 |      22397 | Drama       |
| 1672111 |      54934 | Action      |
| 1672580 |     297253 | Comedy      |
| 1672716 |     188926 | Drama       |
| 1672946 |     188940 | Action      |
| 1673647 |     302682 | Drama       |
| 1673658 |     155385 | Comedy      |
| 1673848 |     133605 | Comedy      |
| 1674388 |     115990 | Adventure   |
| 1674737 |     164962 | Drama       |
| 1677011 |     116812 | Comedy      |
| 1677258 |      99002 | Comedy      |
| 1677346 |      22912 | Biography   |

</code>```

what I want is: Based on ratings with 10,000 or more votes, I want to know what is the  top movie genre using the average rank per movie genre as the metric

what I did so far is this:

```<code>SELECT movieid
FROM rating m
JOIN (
SELECT movieid, COUNT(movieid)
FROM rating)
ON m.movieid = r.movieid
count(*)>=10000

</code>```

not sure if the logic is correct . any help?

答:
Consider:</p>

```<code>select md.genre, avg(r.rank) avg_rank
from movies_directores md
inner join rating r on r.movieid = md.movieid
where r.votes > 10000
group by md.genre
order by avg(r.rank) desc
limit 1
</code>```

Body:
Currently, I am teaching my self SQL and i came across a very interesting question which says:
Based ratings with 10,000 or more votes, what is the top movie genre using the
average rank per movie genre as the metric?
(Note: where a higher value for rank is considered a better movie)

So here are the tables: rating

+---------+------+--------+--------------+
| movieid | rank | votes  | distribution |
+---------+------+--------+--------------+
| 1672052 | 7.8  |   8111 | 0000001222   |
| 1672111 | 5.3  |  32183 | 0001221000   |
| 1672580 | 4.4  |   1894 | 0011110000   |
| 1672716 | 7.0  |   1255 | 0000001212   |
| 1673647 | 6.5  |    128 | 0000111211   |
| 1673658 | 3.9  |     20 | 22101.10.1   |
| 1673848 | 7.0  | 137748 | 0000012211   |
| 1674388 | 5.5  |  47380 | 0001221000   |

Table: movie_directores

+---------+------------+-------------+
| movieid | directorid | genre       |
+---------+------------+-------------+
| 1672052 |      22397 | Drama       |
| 1672111 |      54934 | Action      |
| 1672580 |     297253 | Comedy      |
| 1672716 |     188926 | Drama       |
| 1672946 |     188940 | Action      |
| 1673647 |     302682 | Drama       |
| 1673658 |     155385 | Comedy      |
| 1673848 |     133605 | Comedy      |
| 1674388 |     115990 | Adventure   |
| 1674737 |     164962 | Drama       |
| 1677011 |     116812 | Comedy      |
| 1677258 |      99002 | Comedy      |
| 1677346 |      22912 | Biography   |

what I want is: Based on ratings with 10,000 or more votes, I want to know what is the  top movie genre using the average rank per movie genre as the metric

what I did so far is this:

SELECT movieid
FROM rating m
JOIN (
SELECT movieid, COUNT(movieid)
FROM rating)
ON m.movieid = r.movieid
count(*)>=10000

not sure if the logic is correct . any help?

Body:
Consider:

select md.genre, avg(r.rank) avg_rank
from movies_directores md
inner join rating r on r.movieid = md.movieid
where r.votes > 10000
group by md.genre
order by avg(r.rank) desc
limit 1


问:
How to export a CSV file from the MySQL command line
I have a MySQL database containing a single table which is used as a temporary storage point for manipulating and querying data sets and is periodically deleted and replaced with new data. What I would like to be able to do is export the data from the MySQL command line to use for other purposes. I am using the XAMPP Apache server package with phpMyAdmin on Windows 10.

The issue I am having is the INTO OUTFILE syntax I am using returns an error relating to '\n'. Below is an example of the syntax:

```<code>SELECT *
FROM tablename
WHERE work_complete = 'Yes'
INTO OUTFILE 'C:\file path for the file to be exported to\file_name.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY "''"
ESCAPED BY '\'
LINES TERMINATED BY '\n';
</code>```

I have spent some time researching this without any luck, I have even tried using

```<code>LINES TERMINATED BY '\r\n'
</code>```

but the error remained the same

```<code>ERROR: Unknown command '\''.
   ->     LINES TERMINATED BY '\r\n';
</code>```

If anyone could provide any tips that would be greatly appreciated.

答:
Use this

```<code>SELECT *
FROM tablename
#WHERE work_complete = 'Yes'
INTO OUTFILE 'C:\file path for the file to be exported to\file_name.csv'
FIELDS ENCLOSED BY '"'
TERMINATED BY ';'
ESCAPED BY '"'
LINES TERMINATED BY '\r\n';
</code>```

I used some other syntax as you and deleted the OPTIONALLY which mysql doesn't like at that place

Body:
I have a MySQL database containing a single table which is used as a temporary storage point for manipulating and querying data sets and is periodically deleted and replaced with new data. What I would like to be able to do is export the data from the MySQL command line to use for other purposes. I am using the XAMPP Apache server package with phpMyAdmin on Windows 10.

The issue I am having is the INTO OUTFILE syntax I am using returns an error relating to '\n'. Below is an example of the syntax:

SELECT *
FROM tablename
WHERE work_complete = 'Yes'
INTO OUTFILE 'C:\file path for the file to be exported to\file_name.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY "''"
ESCAPED BY '\'
LINES TERMINATED BY '\n';

I have spent some time researching this without any luck, I have even tried using

LINES TERMINATED BY '\r\n'

but the error remained the same

ERROR: Unknown command '\''.
   ->     LINES TERMINATED BY '\r\n';

If anyone could provide any tips that would be greatly appreciated.

Body:
Use this

SELECT *
FROM tablename
#WHERE work_complete = 'Yes'
INTO OUTFILE 'C:\file path for the file to be exported to\file_name.csv'
FIELDS ENCLOSED BY '"'
TERMINATED BY ';'
ESCAPED BY '"'
LINES TERMINATED BY '\r\n';

I used some other syntax as you and deleted the OPTIONALLY which mysql doesn't like at that place


问:
Problem with ArrayList and Stream... I have to stream an ArrayList with elements that have attributes in another ArrayList
I have the Lists  and   ... Now , I have to stream the order list with the products and their names and numbers. I will write a simplified code cause the actual one is pretty long

```<code>ArrayList<Order> order = new ArrayList<>();
order.add(new Order(011, 579, 1 , true);

ArrayList<Product> prod = new ArrayList<>();
prod.add(new Product(9918, "Nvidia Graphic Card", 1299);
</code>```

the goal is to stream the order with the true boolean (which in this case means is confirmed) and with the name and number of the products in those orders....

```<code>order.stream().filter(e-> e.isConfirmed()).forEach((v) -> System.out.println("\n \t "+ v));
</code>```

but this is just the order, I do not know how to get the product inside the same stream... Thanks

答:
Here is one way of doing this, but be warned that it is terrible ineffective solution as for each confirmed order it has to scan products list to find the valid product.
Therefore I would strongly recommend you to consider using another data structure (like Map<Integer, Product> which reduces complexity of finding a product from O(n) to O(log n)) to store products or change the Order class to store Product (or even List<Product>) directly instead of storing the productId.

```<code>public static void main(String[] args) {
    List<Order> orders = new ArrayList<>(List.of(
            new Order(1, 1, 5, false),
            new Order(2, 2, 5, true),
            new Order(3, 3, 7, true),
            new Order(4, 1, 1, true),
            new Order(5, 2, 3, true),
            new Order(6, 3, 5, false)
    ));

    List<Product> products = new ArrayList<>(List.of(
            new Product(1, "Product 1", 1.99),
            new Product(2, "Product 2", 2.99),
            new Product(3, "Product 3", 3.99)
    ));

    String confirmedOrders = orders.stream()
            .filter(Order::isConfirmed)
            .map(order -> products.stream()
                    .filter(product -> product.getId() == order.getProductId())
                    .findFirst()
                    .map(getOrderSummaryString(order))
                    .orElseThrow(() -> new IllegalArgumentException(
                            "Invalid product id (#" + order.getProductId() + ") in order #" + order.getId()))
            )
            .collect(Collectors.joining(System.lineSeparator()));

    System.out.println("Confirmed orders list:" + System.lineSeparator() + confirmedOrders);
}

private static Function<Product, String> getOrderSummaryString(Order order) {
    return product ->
            "\t Order #" + order.getId() + " of " + order.getQuantity() + " * " + product.getName() +
                    " ($" + product.getPrice() + ")," + " $" +
                    String.format("%.2f", product.getPrice() * order.getQuantity());
}
</code>```

Output:

Confirmed orders list:
     Order #2 of 5 * Product 2 ($2.99), $14.95
     Order #3 of 7 * Product 3 ($3.99), $27.93
     Order #4 of 1 * Product 1 ($1.99), $1.99
     Order #5 of 3 * Product 2 ($2.99), $8.97
```

Live demo

Body:
I have the Lists  and   ... Now , I have to stream the order list with the products and their names and numbers. I will write a simplified code cause the actual one is pretty long

ArrayList<Order> order = new ArrayList<>();
order.add(new Order(011, 579, 1 , true);

ArrayList<Product> prod = new ArrayList<>();
prod.add(new Product(9918, "Nvidia Graphic Card", 1299);

the goal is to stream the order with the true boolean (which in this case means is confirmed) and with the name and number of the products in those orders....

order.stream().filter(e-> e.isConfirmed()).forEach((v) -> System.out.println("\n \t "+ v));

but this is just the order, I do not know how to get the product inside the same stream... Thanks

Body:
Here is one way of doing this, but be warned that it is terrible ineffective solution as for each confirmed order it has to scan products list to find the valid product.
Therefore I would strongly recommend you to consider using another data structure (like Map<Integer, Product> which reduces complexity of finding a product from O(n) to O(log n)) to store products or change the Order class to store Product (or even List<Product>) directly instead of storing the productId.

public static void main(String[] args) {
    List<Order> orders = new ArrayList<>(List.of(
            new Order(1, 1, 5, false),
            new Order(2, 2, 5, true),
            new Order(3, 3, 7, true),
            new Order(4, 1, 1, true),
            new Order(5, 2, 3, true),
            new Order(6, 3, 5, false)
    ));

    List<Product> products = new ArrayList<>(List.of(
            new Product(1, "Product 1", 1.99),
            new Product(2, "Product 2", 2.99),
            new Product(3, "Product 3", 3.99)
    ));

    String confirmedOrders = orders.stream()
            .filter(Order::isConfirmed)
            .map(order -> products.stream()
                    .filter(product -> product.getId() == order.getProductId())
                    .findFirst()
                    .map(getOrderSummaryString(order))
                    .orElseThrow(() -> new IllegalArgumentException(
                            "Invalid product id (#" + order.getProductId() + ") in order #" + order.getId()))
            )
            .collect(Collectors.joining(System.lineSeparator()));

    System.out.println("Confirmed orders list:" + System.lineSeparator() + confirmedOrders);
}

private static Function<Product, String> getOrderSummaryString(Order order) {
    return product ->
            "\t Order #" + order.getId() + " of " + order.getQuantity() + " * " + product.getName() +
                    " ($" + product.getPrice() + ")," + " $" +
                    String.format("%.2f", product.getPrice() * order.getQuantity());
}

Output:

Confirmed orders list:
     Order #2 of 5 * Product 2 ($2.99), $14.95
     Order #3 of 7 * Product 3 ($3.99), $27.93
     Order #4 of 1 * Product 1 ($1.99), $1.99
     Order #5 of 3 * Product 2 ($2.99), $8.97

Live demo


问:
Multiple Countries for Android AutocompleteFilter
My app have to provide a Place Autocompleter for Google APIs.
But there should only display locations for selected countries.
For example only addresses in US and in UK.
Here the used code-snipped for the filter:

```<code>AutocompleteFilter autocompleteFilter = new AutocompleteFilter.Builder()
            .setTypeFilter(Place.TYPE_COUNTRY)
            .setCountry("US")
            .build();
</code>```

Is there any solution to set the method setCountry() to multiple counties?
I have tried .setCountrie("US, UK") ... but this don't work.

any idea?

答:
A new method setCountries() has been added to the SDK.

Make sure to update places dependency on gradle to the latest (I'm using 2.2.0 here)

implementation 'com.google.android.libraries.places:places:2.2.0'

Use the new method, here is an example using intent:

Java

Intent intent = new Autocomplete.IntentBuilder(
                AutocompleteActivityMode.OVERLAY, fields)
                .setCountries(Arrays.asList("FR", "IT"))
                .build(this);
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
```

<p><strong>Kotlin</strong></p>

```val intent = Autocomplete.IntentBuilder(
             AutocompleteActivityMode.OVERLAY, fields)
            .setCountries(listOf("FR", "IT"))
            .build(this)
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE)
```

Note: keep in mind autocomplete results to up to five countries according to the documentation

Body:
My app have to provide a Place Autocompleter for Google APIs.
But there should only display locations for selected countries.
For example only addresses in US and in UK.
Here the used code-snipped for the filter:

AutocompleteFilter autocompleteFilter = new AutocompleteFilter.Builder()
            .setTypeFilter(Place.TYPE_COUNTRY)
            .setCountry("US")
            .build();

Is there any solution to set the method setCountry() to multiple counties?
I have tried .setCountrie("US, UK") ... but this don't work.

any idea?

Body:
A new method setCountries() has been added to the SDK.

Make sure to update places dependency on gradle to the latest (I'm using 2.2.0 here)

implementation 'com.google.android.libraries.places:places:2.2.0'

Use the new method, here is an example using intent:

Java

Intent intent = new Autocomplete.IntentBuilder(
                AutocompleteActivityMode.OVERLAY, fields)
                .setCountries(Arrays.asList("FR", "IT"))
                .build(this);
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);

Kotlin

val intent = Autocomplete.IntentBuilder(
             AutocompleteActivityMode.OVERLAY, fields)
            .setCountries(listOf("FR", "IT"))
            .build(this)
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE)

Note: keep in mind autocomplete results to up to five countries according to the documentation


问:
Java functional approach to join identical elements into a single one
I would like to use Streams API to process a call log and calculate the total billing amount for the same phone number. Here's the code that achieves it with a hybrid approach but I would like to use fully functional approach:</p>

```<code>List<CallLog> callLogs = Arrays.stream(S.split("\n"))
                    .map(CallLog::new)
                    .sorted(Comparator.comparingInt(callLog -> callLog.phoneNumber))
                    .collect(Collectors.toList());

            for (int i = 0; i< callLogs.size() -1 ;i++) {
                if (callLogs.get(i).phoneNumber == callLogs.get(i+1).phoneNumber) {
                    callLogs.get(i).billing += callLogs.get(i+1).billing;
                    callLogs.remove(i+1);
                }
            }
</code>```

答:
```<code>Map<Integer, Integer> result = Arrays.stream(S.split("\n"))
                    .map(CallLog::new)
                    .sorted(Comparator.comparingInt(callLog -> callLog.phoneNumber))
                    .collect(Collectors.toMap(
                        c -> c.phoneNumber(),
                        c -> c.billing(),
                        (a, b) -> a+b
                     ));
</code>```

And if you want to have a 'List callLogs' as a result:

```<code>List<CallLog> callLogs = Arrays.stream(S.split("\n"))
                        .map(CallLog::new)
                        .collect(Collectors.toMap(
                            c -> c.phoneNumber(),
                            c -> c.billing(),
                            (a, b) -> a+b
                         ))
                        .entrySet()
                        .stream()
                        .map(entry -> toCallLog(entry.getKey(), entry.getValue()))
                        .sorted(Comparator.comparingInt(callLog -> callLog.phoneNumber))
                        .collect(Collectors.toList())
</code>```

Body:
I would like to use Streams API to process a call log and calculate the total billing amount for the same phone number. Here's the code that achieves it with a hybrid approach but I would like to use fully functional approach:

List<CallLog> callLogs = Arrays.stream(S.split("\n"))
                    .map(CallLog::new)
                    .sorted(Comparator.comparingInt(callLog -> callLog.phoneNumber))
                    .collect(Collectors.toList());

            for (int i = 0; i< callLogs.size() -1 ;i++) {
                if (callLogs.get(i).phoneNumber == callLogs.get(i+1).phoneNumber) {
                    callLogs.get(i).billing += callLogs.get(i+1).billing;
                    callLogs.remove(i+1);
                }
            }

Body:
Map<Integer, Integer> result = Arrays.stream(S.split("\n"))
                    .map(CallLog::new)
                    .sorted(Comparator.comparingInt(callLog -> callLog.phoneNumber))
                    .collect(Collectors.toMap(
                        c -> c.phoneNumber(),
                        c -> c.billing(),
                        (a, b) -> a+b
                     ));

And if you want to have a 'List callLogs' as a result:

List<CallLog> callLogs = Arrays.stream(S.split("\n"))
                        .map(CallLog::new)
                        .collect(Collectors.toMap(
                            c -> c.phoneNumber(),
                            c -> c.billing(),
                            (a, b) -> a+b
                         ))
                        .entrySet()
                        .stream()
                        .map(entry -> toCallLog(entry.getKey(), entry.getValue()))
                        .sorted(Comparator.comparingInt(callLog -> callLog.phoneNumber))
                        .collect(Collectors.toList())


问:
I get an error of a parameter that cannot be nil obj c
this function is the copy of another identical but with different keys. on the other hand it works I can't understand why the app crashes here ..

```<code>    #pragma mark - ChangePin
- (void) doChangePin: (NSString *) pinUser card: (NSString *) pinCard viewController: (UIViewController *) viewController success:(successSDKType)success failure:(failureSDKType)failure{

    self.mcPersonalEnrollmentRequest.mcCardPan = pinCard;

    PRLog(@"Pin Inserito: %@", pinUser);

    SecurityCryptogram *securityCryptogram = [CryptogramManager getSecurityCriptogramWithPan:pinCard pin:pinUser];

    self.mcPersonalEnrollmentRequest.securityCryptogram = securityCryptogram;
    self.mcPersonalEnrollmentRequest.mcIdPublicKey = [[ServiceDataManager getInstance] getIdPublicKey];

    NSDictionary* dtoReq = [self.mcPersonalEnrollmentRequest getDictionary];

    [self.netManager doRequestWithCommand:CMD_STATUS_CHECK dtoReq:dtoReq successCompletion:^(NetworkResponse *successData) {

        NSDictionary *resources = (NSDictionary *)[successData res];

        McCardEnrolled *mcCardEnrolled = [[McCardEnrolled alloc] initWithResDict:resources];
        [[ServiceDataManager getInstance] storeMcCard:mcCardEnrolled];

        McCard *mcCard = [mcCardEnrolled getCard];

        //We have to go on main thread to pop the controller
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.mcCardEnrollmentSuccessCallback(mcCard);
            self.cardEnrollmentViewController.navigationController.navigationBar.translucent = NO;
            [self.cardEnrollmentViewController.navigationController popViewControllerAnimated:YES];

            self.cardEnrollmentViewController = nil;
            self.mcCardEnrollmentSuccessCallback = nil;
            self.mcCardEnrollmentFailureCallback = nil;
            self.mcCardEnrollmentRequest = nil;

        }];

    } failureCompletion:^(Result *failureResult) {

        //Same of success case. We have to go on main thread to pop the controller
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.mcCardEnrollmentFailureCallback(failureResult);
            self.cardEnrollmentViewController.navigationController.navigationBar.translucent = NO;
            [self.cardEnrollmentViewController.navigationController popViewControllerAnimated:YES];

            self.cardEnrollmentViewController = nil;
            self.mcCardEnrollmentSuccessCallback = nil;
            self.mcCardEnrollmentFailureCallback = nil;
            self.mcCardEnrollmentRequest = nil;
        }];

    }];
</code>```

the error is :

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: req)'

the objects or variables that change are as follows:
mcPersonalEnrollmentRequest
CMD_STATUS_CHECK
that I recreated for this function here.

```<code>- (void) doRequestWithCommand:(NSString*)cmd dtoReq:(NSDictionary*)dtoReq successCompletion:(successCompletionType)success failureCompletion:(failureCompletionType)failure{

PRLog(@"NET-MAN> CMD:%@ - Prepare request with dtoReq: %@",cmd,[dtoReq description]);

NetworkRequest *request = [self prepareRequestForCommand:cmd dtoReq:dtoReq];
PRLog(@"NET-REQ> CMD:%@ - [DEBUG] Request created", cmd);

NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];

NSURLSessionDataTask* task = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    PRLog(@"NET-MAN> CMD:%@ - Received response. Error: %@", cmd, [error description]);

    if (!error) {
        // Success
        NSString *errMsg;
        if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

            NSDictionary *jsonResponse = [PRUtility dictionaryFromJsonData:data];
            if(jsonResponse){
                PRLog(@"NET-MAN> CMD:%@ - JSON RESPONSE != nil", cmd);

                NSDictionary* svcResDict = (NSDictionary*)[jsonResponse objectForKey:DTO_RESPONSE_TAG_SVC];
                if(svcResDict && svcResDict != (NSDictionary *)[NSNull null]){

                    PRLog(@"NET-MAN> CMD:%@ - Trying parsing response.",cmd);
                    NetworkResponse* networkResponse = [[NetworkResponse alloc] initWithCmd:cmd andNetworkData:svcResDict];

                    if (networkResponse) {
                        //Happy flow
                        PRLog(@"NET-MAN> CMD:%@ - Response created correctly.",cmd);

                        Result* resultForBadStatusCode = [self errorFromStatusCode:networkResponse.dtoStatus];

                        !resultForBadStatusCode ? success(networkResponse) : failure(resultForBadStatusCode);
                        return;
                    }
                    else{
                        errMsg = @"Error while accessing to networkResponse";
                    }
                }
                else{
                    errMsg = @"SVC field not found";
                }
            }
            else{
                errMsg = @"Cannot parses response into json";
            }
        }  else {
            errMsg = @"Recevied an error [response is not a NSHTTPURLResponse]";
        }

        Result *errorResponse = [[Result alloc] initGenericErrorWithMalformedNetworkResponse:errMsg];

        PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, errMsg);
        failure(errorResponse);

    } else {
        // Fail

        Result *errorNetwork = [self errorNetworkFromCode:error.code];

        PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, error.description);
        failure(errorNetwork);
    }

}];

PRLog(@"NET-MAN: CMD:%@ - Doing request...", request.cmd);
[task resume];
</code>```

}

```<code>- (void) doRequestWithCommand:(NSString*)cmd dtoReq:(NSDictionary*)dtoReq successCompletion:(successCompletionType)success failureCompletion:(failureCompletionType)failure{

    PRLog(@"NET-MAN> CMD:%@ - Prepare request with dtoReq: %@",cmd,[dtoReq description]);

    NetworkRequest *request = [self prepareRequestForCommand:cmd dtoReq:dtoReq];
    PRLog(@"NET-REQ> CMD:%@ - [DEBUG] Request created", cmd);

    NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];

    NSURLSessionDataTask* task = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        PRLog(@"NET-MAN> CMD:%@ - Received response. Error: %@", cmd, [error description]);

        if (!error) {
            // Success
            NSString *errMsg;
            if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

                NSDictionary *jsonResponse = [PRUtility dictionaryFromJsonData:data];
                if(jsonResponse){
                    PRLog(@"NET-MAN> CMD:%@ - JSON RESPONSE != nil", cmd);

                    NSDictionary* svcResDict = (NSDictionary*)[jsonResponse objectForKey:DTO_RESPONSE_TAG_SVC];
                    if(svcResDict && svcResDict != (NSDictionary *)[NSNull null]){

                        PRLog(@"NET-MAN> CMD:%@ - Trying parsing response.",cmd);
                        NetworkResponse* networkResponse = [[NetworkResponse alloc] initWithCmd:cmd andNetworkData:svcResDict];

                        if (networkResponse) {
                            //Happy flow
                            PRLog(@"NET-MAN> CMD:%@ - Response created correctly.",cmd);

                            Result* resultForBadStatusCode = [self errorFromStatusCode:networkResponse.dtoStatus];

                            !resultForBadStatusCode ? success(networkResponse) : failure(resultForBadStatusCode);
                            return;
                        }
                        else{
                            errMsg = @"Error while accessing to networkResponse";
                        }
                    }
                    else{
                        errMsg = @"SVC field not found";
                    }
                }
                else{
                    errMsg = @"Cannot parses response into json";
                }
            }  else {
                errMsg = @"Recevied an error [response is not a NSHTTPURLResponse]";
            }

            Result *errorResponse = [[Result alloc] initGenericErrorWithMalformedNetworkResponse:errMsg];

            PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, errMsg);
            failure(errorResponse);

        } else {
            // Fail

            Result *errorNetwork = [self errorNetworkFromCode:error.code];

            PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, error.description);
            failure(errorNetwork);
        }

    }];

    PRLog(@"NET-MAN: CMD:%@ - Doing request...", request.cmd);
    [task resume];

}

    - (NetworkRequest*) prepareRequestForCommand:(NSString*)cmd dtoReq:(NSDictionary*)dtoReq{
    NSMutableDictionary* dtoAppRequest = [[NSMutableDictionary alloc] init];
    [dtoAppRequest setObject:cmd
                      forKey:CMD_TAG];
    [dtoAppRequest setObject:dtoReq forKey:REQ_TAG];

    NetworkRequest *request = [[NetworkRequest alloc] initWithDtoAppRequest:dtoAppRequest
                                                             jSessionClient:self.userConfig.jSessionClient
                                                                     userId:self.userConfig.userId
                                                                 fiscalCode:self.userConfig.fiscalCode];

    [request completeRequestObject];

    return request;
}
</code>```

答:
This is the line that generates nil, and nil cannot be inserted in NSMutableDictionary,

```<code>NSDictionary* dtoReq = [self.mcPersonalEnrollmentRequest getDictionary];
</code>```

Just add validation for this parameter with some handling and all will be ok.

Body:
this function is the copy of another identical but with different keys. on the other hand it works I can't understand why the app crashes here ..

    #pragma mark - ChangePin
- (void) doChangePin: (NSString *) pinUser card: (NSString *) pinCard viewController: (UIViewController *) viewController success:(successSDKType)success failure:(failureSDKType)failure{

    self.mcPersonalEnrollmentRequest.mcCardPan = pinCard;

    PRLog(@"Pin Inserito: %@", pinUser);

    SecurityCryptogram *securityCryptogram = [CryptogramManager getSecurityCriptogramWithPan:pinCard pin:pinUser];

    self.mcPersonalEnrollmentRequest.securityCryptogram = securityCryptogram;
    self.mcPersonalEnrollmentRequest.mcIdPublicKey = [[ServiceDataManager getInstance] getIdPublicKey];

    NSDictionary* dtoReq = [self.mcPersonalEnrollmentRequest getDictionary];

    [self.netManager doRequestWithCommand:CMD_STATUS_CHECK dtoReq:dtoReq successCompletion:^(NetworkResponse *successData) {

        NSDictionary *resources = (NSDictionary *)[successData res];

        McCardEnrolled *mcCardEnrolled = [[McCardEnrolled alloc] initWithResDict:resources];
        [[ServiceDataManager getInstance] storeMcCard:mcCardEnrolled];

        McCard *mcCard = [mcCardEnrolled getCard];

        //We have to go on main thread to pop the controller
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.mcCardEnrollmentSuccessCallback(mcCard);
            self.cardEnrollmentViewController.navigationController.navigationBar.translucent = NO;
            [self.cardEnrollmentViewController.navigationController popViewControllerAnimated:YES];

            self.cardEnrollmentViewController = nil;
            self.mcCardEnrollmentSuccessCallback = nil;
            self.mcCardEnrollmentFailureCallback = nil;
            self.mcCardEnrollmentRequest = nil;

        }];

    } failureCompletion:^(Result *failureResult) {

        //Same of success case. We have to go on main thread to pop the controller
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.mcCardEnrollmentFailureCallback(failureResult);
            self.cardEnrollmentViewController.navigationController.navigationBar.translucent = NO;
            [self.cardEnrollmentViewController.navigationController popViewControllerAnimated:YES];

            self.cardEnrollmentViewController = nil;
            self.mcCardEnrollmentSuccessCallback = nil;
            self.mcCardEnrollmentFailureCallback = nil;
            self.mcCardEnrollmentRequest = nil;
        }];

    }];

the error is :

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: req)'

the objects or variables that change are as follows:
mcPersonalEnrollmentRequest
CMD_STATUS_CHECK
that I recreated for this function here.

- (void) doRequestWithCommand:(NSString*)cmd dtoReq:(NSDictionary*)dtoReq successCompletion:(successCompletionType)success failureCompletion:(failureCompletionType)failure{

PRLog(@"NET-MAN> CMD:%@ - Prepare request with dtoReq: %@",cmd,[dtoReq description]);

NetworkRequest *request = [self prepareRequestForCommand:cmd dtoReq:dtoReq];
PRLog(@"NET-REQ> CMD:%@ - [DEBUG] Request created", cmd);

NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];

NSURLSessionDataTask* task = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    PRLog(@"NET-MAN> CMD:%@ - Received response. Error: %@", cmd, [error description]);

    if (!error) {
        // Success
        NSString *errMsg;
        if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

            NSDictionary *jsonResponse = [PRUtility dictionaryFromJsonData:data];
            if(jsonResponse){
                PRLog(@"NET-MAN> CMD:%@ - JSON RESPONSE != nil", cmd);

                NSDictionary* svcResDict = (NSDictionary*)[jsonResponse objectForKey:DTO_RESPONSE_TAG_SVC];
                if(svcResDict && svcResDict != (NSDictionary *)[NSNull null]){

                    PRLog(@"NET-MAN> CMD:%@ - Trying parsing response.",cmd);
                    NetworkResponse* networkResponse = [[NetworkResponse alloc] initWithCmd:cmd andNetworkData:svcResDict];

                    if (networkResponse) {
                        //Happy flow
                        PRLog(@"NET-MAN> CMD:%@ - Response created correctly.",cmd);

                        Result* resultForBadStatusCode = [self errorFromStatusCode:networkResponse.dtoStatus];

                        !resultForBadStatusCode ? success(networkResponse) : failure(resultForBadStatusCode);
                        return;
                    }
                    else{
                        errMsg = @"Error while accessing to networkResponse";
                    }
                }
                else{
                    errMsg = @"SVC field not found";
                }
            }
            else{
                errMsg = @"Cannot parses response into json";
            }
        }  else {
            errMsg = @"Recevied an error [response is not a NSHTTPURLResponse]";
        }

        Result *errorResponse = [[Result alloc] initGenericErrorWithMalformedNetworkResponse:errMsg];

        PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, errMsg);
        failure(errorResponse);

    } else {
        // Fail

        Result *errorNetwork = [self errorNetworkFromCode:error.code];

        PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, error.description);
        failure(errorNetwork);
    }

}];

PRLog(@"NET-MAN: CMD:%@ - Doing request...", request.cmd);
[task resume];

}

- (void) doRequestWithCommand:(NSString*)cmd dtoReq:(NSDictionary*)dtoReq successCompletion:(successCompletionType)success failureCompletion:(failureCompletionType)failure{

    PRLog(@"NET-MAN> CMD:%@ - Prepare request with dtoReq: %@",cmd,[dtoReq description]);

    NetworkRequest *request = [self prepareRequestForCommand:cmd dtoReq:dtoReq];
    PRLog(@"NET-REQ> CMD:%@ - [DEBUG] Request created", cmd);

    NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];

    NSURLSessionDataTask* task = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        PRLog(@"NET-MAN> CMD:%@ - Received response. Error: %@", cmd, [error description]);

        if (!error) {
            // Success
            NSString *errMsg;
            if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

                NSDictionary *jsonResponse = [PRUtility dictionaryFromJsonData:data];
                if(jsonResponse){
                    PRLog(@"NET-MAN> CMD:%@ - JSON RESPONSE != nil", cmd);

                    NSDictionary* svcResDict = (NSDictionary*)[jsonResponse objectForKey:DTO_RESPONSE_TAG_SVC];
                    if(svcResDict && svcResDict != (NSDictionary *)[NSNull null]){

                        PRLog(@"NET-MAN> CMD:%@ - Trying parsing response.",cmd);
                        NetworkResponse* networkResponse = [[NetworkResponse alloc] initWithCmd:cmd andNetworkData:svcResDict];

                        if (networkResponse) {
                            //Happy flow
                            PRLog(@"NET-MAN> CMD:%@ - Response created correctly.",cmd);

                            Result* resultForBadStatusCode = [self errorFromStatusCode:networkResponse.dtoStatus];

                            !resultForBadStatusCode ? success(networkResponse) : failure(resultForBadStatusCode);
                            return;
                        }
                        else{
                            errMsg = @"Error while accessing to networkResponse";
                        }
                    }
                    else{
                        errMsg = @"SVC field not found";
                    }
                }
                else{
                    errMsg = @"Cannot parses response into json";
                }
            }  else {
                errMsg = @"Recevied an error [response is not a NSHTTPURLResponse]";
            }

            Result *errorResponse = [[Result alloc] initGenericErrorWithMalformedNetworkResponse:errMsg];

            PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, errMsg);
            failure(errorResponse);

        } else {
            // Fail

            Result *errorNetwork = [self errorNetworkFromCode:error.code];

            PRLog(@"NET-MAN: CMD:%@ - ERR: %@", cmd, error.description);
            failure(errorNetwork);
        }

    }];

    PRLog(@"NET-MAN: CMD:%@ - Doing request...", request.cmd);
    [task resume];

}

    - (NetworkRequest*) prepareRequestForCommand:(NSString*)cmd dtoReq:(NSDictionary*)dtoReq{
    NSMutableDictionary* dtoAppRequest = [[NSMutableDictionary alloc] init];
    [dtoAppRequest setObject:cmd
                      forKey:CMD_TAG];
    [dtoAppRequest setObject:dtoReq forKey:REQ_TAG];

    NetworkRequest *request = [[NetworkRequest alloc] initWithDtoAppRequest:dtoAppRequest
                                                             jSessionClient:self.userConfig.jSessionClient
                                                                     userId:self.userConfig.userId
                                                                 fiscalCode:self.userConfig.fiscalCode];

    [request completeRequestObject];

    return request;
}

Body:
This is the line that generates nil, and nil cannot be inserted in NSMutableDictionary,

NSDictionary* dtoReq = [self.mcPersonalEnrollmentRequest getDictionary];

Just add validation for this parameter with some handling and all will be ok.


问:
Rescale a vector of integers
Assume that I have a vector, V, of positive integers. If the sum of the integers are larger than a positive integer N, I want to rescale the integers in V so that the sum is <= N. The elements in V must remain above zero. The length of V is guaranteed to be <= N.

Is there an algorithm to perform this rescaling in linear time?

This is not homework, BTW :). I need to rescale a map from symbols to symbol frequencies to use range encoding.

Some quick thinking and googling has not given a solution to the problem.

EDIT:

Ok, the question was somewhat unclear. "Rescale" means "normalize". That is, transform the integers in V, for example by multiplying them by a constant, to smaller positive integers so the criterion of sum(V) <= N is fulfilled. The better the ratios between the integers are preserved, the better the compression will be.

The problem is open-ended in that way, the method does not need to find the optimal (in, say, a least squares fit sense) way to preserve the ratios, but a "good" one. Setting the entire vector to 1, as suggested, is not acceptable (unless forced). "Good" enough would for example be finding the smallest divisor (defined below) that fulfills the sum criterion.

The following naive algorithm does not work.

Find the current sum(V), Sv

divisor := int(ceil(Sv/N))

Divide each integer in V by divisor, rounding down, but not to less than 1.

This fails on v = [1,1,1,10] with N = 5.

```<code>divisor = ceil(13 / 5) = 3.
V := [1,1,1, max(1, floor(10/3)) = 3]
Sv is now 6 > 5.
</code>```

In this case, the correct normalization is [1,1,1,2]

One algorithm that would work is to do a binary search for divisor (defined above) until the smallest divisor in [1,N] fulfilling the sum criterion is found. Starting with the ceil(Sv/N) guess. This is however, not linear in number of operations, but proportional to len(V)*log(len(V)).

I am starting to think that it is impossible to do well, in linear time, in the general case. I might resort to some sort of heuristic.

答:
How about this:

Find the current sum(V), Sv

divisor := int(ceil(Sv/(N - |V| + 1))

Divide each integer in V by divisor, rounding up

On v = [1,1,1,10] with N = 5:

divisor = ceil(13 / 2) = 7.
V := [1,1,1, ceil(10/7)) = 2]

Title: Rescale a vector of integers

Body:
Assume that I have a vector, V, of positive integers. If the sum of the integers are larger than a positive integer N, I want to rescale the integers in V so that the sum is <= N. The elements in V must remain above zero. The length of V is guaranteed to be <= N.

Is there an algorithm to perform this rescaling in linear time?

This is not homework, BTW :). I need to rescale a map from symbols to symbol frequencies to use range encoding.

Some quick thinking and googling has not given a solution to the problem.

EDIT:

Ok, the question was somewhat unclear. "Rescale" means "normalize". That is, transform the integers in V, for example by multiplying them by a constant, to smaller positive integers so the criterion of sum(V) <= N is fulfilled. The better the ratios between the integers are preserved, the better the compression will be.

The problem is open-ended in that way, the method does not need to find the optimal (in, say, a least squares fit sense) way to preserve the ratios, but a "good" one. Setting the entire vector to 1, as suggested, is not acceptable (unless forced). "Good" enough would for example be finding the smallest divisor (defined below) that fulfills the sum criterion.

The following naive algorithm does not work.

Find the current sum(V), Sv

divisor := int(ceil(Sv/N))

Divide each integer in V by divisor, rounding down, but not to less than 1.

This fails on v = [1,1,1,10] with N = 5.

divisor = ceil(13 / 5) = 3.
V := [1,1,1, max(1, floor(10/3)) = 3]
Sv is now 6 > 5.

In this case, the correct normalization is [1,1,1,2]

One algorithm that would work is to do a binary search for divisor (defined above) until the smallest divisor in [1,N] fulfilling the sum criterion is found. Starting with the ceil(Sv/N) guess. This is however, not linear in number of operations, but proportional to len(V)*log(len(V)).

I am starting to think that it is impossible to do well, in linear time, in the general case. I might resort to some sort of heuristic.