问:
Google apps script stopped after just one iteration
I have a little function in google app script that have to do some things in a for loop, i.e.I have 3 rows with some values and for each row I have to update a sheet, but unfortunately I don't understand why but after just one loop the program stopped! And there are no return statements.

this is the code:

```<code>function movimentiRicorrenti(){

  tempoInizioScript = new Date();

  var rigaInizio = 2

  Logger.log("Data e ora script movimenti ricorrenti: " + Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy HH:mm"))

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ricorrenti")

  var ultimaRiga = sheet.getLastRow();  // ultima riga con i dati

  Logger.log("ultima riga " +ultimaRiga);

  var dataMovimento = Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy");

  var dataRangeMovimento;

  var datiMovimento;

  var today = new Date();

  //----------  parte dalla prima riga fino all'ultima del foglio, verifica che il movimento non sia scaduto, verifica se in data odierna andrà eseguito ed esegue eventualmente l'update

for (i=rigaInizio; i<=ultimaRiga; i++){

     dataRangeMovimento = sheet.getRange(i, 1, 1, 9)
     datiMovimento = dataRangeMovimento.getValues();

     Logger.log(convertiMovR(datiMovimento[0][0],datiMovimento[0][1],datiMovimento[0][2],datiMovimento[0][3],datiMovimento[0][4],datiMovimento[0][5],datiMovimento[0][6],datiMovimento[0][7],datiMovimento[0][8]));

}
}
</code>```

other 2 functions

```<code> function convertiMovR(cr, cat, conto, importo, ricorrenza, giornoM, giornoS, giornoA, scadenza){

    today = new Date();
    if (typeof importo != "number"){
       return false;
    }
    if (scadenza >= today){
       if (ricorrenza == "mensile" && today.getDate() == giornoM){
         aggiornaBil(cr,cat,conto,importo,"movimento ricorrente ogni mese il giorno " + giornoM);
         return true;
       }
       if (ricorrenza == "annuale"){
         if (today.getMonth()+1 == giornoA.getMonth()+1 && today.getDate() == giornoA.getDate() + 1 && today.getYear() == giornoA.getYear()){
           aggiornaBil(cr,cat,conto,importo,"movimento ricorrente ogni anno il giorno "+ Utilities.formatDate(new Date(giornoA), "GMT+0200", "dd/MM/yyyy"));
           return true;
         }
       }
       if (ricorrenza == "giornaliera"){
          aggiornaBil(cr,cat,conto,importo,"movimento ricorrente giornaliero");
          return true;
       }
       if (ricorrenza == "settimanale"){
         var giornoSett = 7;
           switch(giornoS)  {
              case "domenica":
                  giornoSett = 0;
                  break;
              case "lunedì":
                  giornoSett = 1;
                  break;
              case "martedì":
                  giornoSett = 2;
                  break;
              case "mercoledì":
                  giornoSett = 3;
                  break;
              case "giovedì":
                  giornoSett = 4;
                  break;
              case "venerdì":
                  giornoSett = 5;
                  break;
              case "sabato":
                  giornoSett = 6;
                  break;
           }
           if (giornoSett == 7){
                var corpo = "Verificare il movimento ricorrente alla riga " + i + " inserire un giorno della settimana dal lunedì alla domenica";
                MailApp.sendEmail("xxxxxx@gmail.com", "Errore movimenti ricorrenti", corpo, {name: "Bilancio Gianluca", htmlBody: corpo})
                Logger.log("Script movimenti ricorrenti eseguito in data/ora " + Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy hh:mm") + " con errori! Mail inviata a xxxxxx@gmail.com")
           }

         if (new Date().getDay() == giornoSett){

             var nScript = sheet.getRange(i, 10).getValue();
             nScript = nScript + 1;
             sheet.getRange(i, 10).setValue(nScript);

             aggiornaBil(cr,cat,conto,importo,"movimento ricorrente ogni settimana di " + giornoS);
             return true;
         }
       }
    }
}

function aggiornaBil(CostoRicavo, Categoria, Conto, Importo, Descrizione){

  var dataMovimento = Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy");

    if (CostoRicavo == "costo"){
      var rigaAgg = rigaAggiornamentoCosti(Conto);
      if (rigaAgg == 0){
        var corpo = "Il movimento inserito in data <b>" +
            Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy")+
            "</b> relativo a <b>" + Conto +
            "</b> non ha corrispondenze in bilancio. Si prega di controllare il foglio di lavoro. Log di sistema:" + Logger.getLog() ;
          MailApp.sendEmail("xxxxxx@gmail.com", "Errore corrispondenza in bilancio", corpo, {name: "Bilancio Gianluca", htmlBody: corpo})

          // uscita dalla sub
          Logger.log("Conto non corrispondente!! Mail inviata a xxxxxx@gmail.com")
          return;
      }

      var foglioBilancio = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("bilancio")
      var rangeDaAggiornare = foglioBilancio.getRange(rigaAgg, colonnaCostiBilancio + 1)
      var importoDaAggiornare = rangeDaAggiornare.getValue();
      var importoAggiornato = importoDaAggiornare + Importo;
      Logger.log("Importo da aggiornare:" + cambiaSeparatore(importoDaAggiornare) + " - Importo aggiornato: " + cambiaSeparatore(arrotondaEuro(importoAggiornato)));
      rangeDaAggiornare.setValue(importoAggiornato);

   }
   if (CostoRicavo == "ricavo"){
      var rigaAgg = rigaAggiornamentoRicavi(Conto);
      if (rigaAgg == 0){
        var corpo = "Il movimento inserito in data <b>" +
            Utilities.formatDate(new Date(dataMovimento), "GMT+0200", "dd/MM/yyyy")+
            "</b> relativo a <b>" + Conto +
            "</b> non ha corrispondenze in bilancio. Si prega di controllare il foglio di lavoro. Log di sistema:" + Logger.getLog() ;
          MailApp.sendEmail("xxxxxx@gmail.com", "Errore corrispondenza in bilancio", corpo, {name: "Bilancio Gianluca", htmlBody: corpo})

          // uscita dalla sub
          Logger.log("Conto non corrispondente!! Mail inviata a xxxxxx@gmail.com")
          return;
      }

      var foglioBilancio = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("bilancio")
      var rangeDaAggiornare = foglioBilancio.getRange(rigaAgg, colonnaRicaviBilancio + 1)
      var importoDaAggiornare = rangeDaAggiornare.getValue();
      var importoAggiornato = importoDaAggiornare + Importo;
      Logger.log("Importo da aggiornare:" + cambiaSeparatore(importoDaAggiornare) + " - Importo aggiornato: " + cambiaSeparatore(arrotondaEuro(importoAggiornato)));
      rangeDaAggiornare.setValue(importoAggiornato);
   }

   var arrayMovimento = [[dataMovimento, CostoRicavo, Categoria, Conto, cambiaSeparatore(Importo), Descrizione]]

   Logger.log(arrayMovimento);

   var foglioMovimenti = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("movimenti")

   foglioMovimenti.insertRowAfter(1);

   foglioMovimenti.getRange(2, 1, 1, 6).setValues(arrayMovimento);

   foglioMovimenti.getRange(3,8,1,1).copyTo(foglioMovimenti.getRange(2,8,1,1))

   foglioBilancio = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("verifica")
   rangeDaAggiornare = foglioBilancio.getRange(1, 5)
   importoDaAggiornare = rangeDaAggiornare.getValue();
   importoAggiornato = importoDaAggiornare + Importo;
   rangeDaAggiornare.setValue(importoAggiornato);

   Logger.log("Aggiornamento completato!");
}
</code>```

log:

```<code>[20-02-17 23:07:22:486 CET] Data e ora script movimenti ricorrenti: 18/02/2020 00:07
[20-02-17 23:07:22:757 CET] ultima riga 4
[20-02-17 23:07:23:206 CET] cellulare riga n. 63
[20-02-17 23:07:23:211 CET] Importo da aggiornare:-29 - Importo aggiornato: -31
[20-02-17 23:07:23:212 CET] [[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]
[20-02-17 23:07:24:067 CET] Aggiornamento completato!
[20-02-17 23:07:24:067 CET] true
</code>```

and stopped.. but there are other 2 rows..

results after put  Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"before/after")  convertiMovR

```<code>Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"before")
Logger.log(convertiMovR(datiMovimento[0][0],datiMovimento[0][1],datiMovimento[0][2],datiMovimento[0][3],datiMovimento[0][4],datiMovimento[0][5],datiMovimento[0][6],datiMovimento[0][7],datiMovimento[0][8]));
Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"after")
</code>```

[20-02-17 23:18:41:155 PST] Data e ora script movimenti ricorrenti: 18/02/2020 09:18

[20-02-17 23:18:41:422 PST] ultima riga 4

[20-02-17 23:18:41:580 PST] r:2.0,u4.0,before

[20-02-17 23:18:41:858 PST] cellulare riga n. 63

[20-02-17 23:18:41:863 PST] Importo da aggiornare:-31 - Importo aggiornato: -33

[20-02-17 23:18:41:865 PST] [[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]

[20-02-17 23:18:42:537 PST] Aggiornamento completato!

[20-02-17 23:18:42:538 PST] true

[20-02-17 23:18:42:538 PST] r:2.0,u4.0,after

but.. maybe i've understand... the for.. next loop doesn't wait that convertiMovR is finished

i try to put

```<code> Logger.log("value of i before call convertiMovR " + i)
 Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"before")
 Logger.log(convertiMovR(datiMovimento[0][0],datiMovimento[0][1],datiMovimento[0][2],datiMovimento[0][3],datiMovimento[0][4],datiMovimento[0][5],datiMovimento[0][6],datiMovimento[0][7],datiMovimento[0][8]));
 Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"after")
 Logger.log("value of i after call convertiMovR " + i)
</code>```

and the result is

```<code>[20-02-18 08:39:32:396 CET] Data e ora script movimenti ricorrenti: 18/02/2020 09:39
[20-02-18 08:39:32:678 CET] ultima riga 4
[20-02-18 08:39:32:807 CET] value of i before call convertiMovR 2
[20-02-18 08:39:32:808 CET] r:2.0,u4.0,before
[20-02-18 08:39:33:057 CET] cellulare riga n. 63
[20-02-18 08:39:33:061 CET] Importo da aggiornare:-41 - Importo aggiornato: -43
[20-02-18 08:39:33:062 CET] [[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]
[20-02-18 08:39:33:706 CET] Aggiornamento completato!
[20-02-18 08:39:33:707 CET] true
[20-02-18 08:39:33:707 CET] r:2.0,u4.0,after
[20-02-18 08:39:33:708 CET] value of i after call convertiMovR 60
</code>```

i guess i have to change the for .. next with other loop maybe do..loop or there is any statement that can 'wait' execution of convertiMovR ? ..

transcript

```<code>[20-02-17 23:39:32:386 PST] Avvio dell'esecuzione
[20-02-17 23:39:32:395 PST] Utilities.formatDate([Mon Feb 17 23:39:32 PST 2020, GMT+0200, dd/MM/yyyy HH:mm]) [0 secondi]
[20-02-17 23:39:32:396 PST] Logger.log([Data e ora script movimenti ricorrenti: 18/02/2020 09:39, []]) [0 secondi]
[20-02-17 23:39:32:398 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:32:573 PST] SpreadsheetApp.Spreadsheet.getSheetByName([ricorrenti]) [0,175 secondi]
[20-02-17 23:39:32:678 PST] SpreadsheetApp.Sheet.getLastRow() [0,103 secondi]
[20-02-17 23:39:32:679 PST] Logger.log([ultima riga 4, []]) [0 secondi]
[20-02-17 23:39:32:679 PST] Utilities.formatDate([Mon Feb 17 23:39:32 PST 2020, GMT+0200, dd/MM/yyyy]) [0 secondi]
[20-02-17 23:39:32:680 PST] SpreadsheetApp.Sheet.getRange([2, 1, 1, 9]) [0 secondi]
[20-02-17 23:39:32:807 PST] SpreadsheetApp.Range.getValues() [0,127 secondi]
[20-02-17 23:39:32:808 PST] Logger.log([value of i before call convertiMovR 2, []]) [0 secondi]
[20-02-17 23:39:32:808 PST] Logger.log([r:%s,u%s,%s, [2.0, 4.0, before]]) [0 secondi]
[20-02-17 23:39:32:808 PST] Utilities.formatDate([Sun Feb 16 15:00:00 PST 2020, GMT+0200, dd/MM/yyyy]) [0 secondi]
[20-02-17 23:39:32:809 PST] Utilities.formatDate([Mon Feb 17 23:39:32 PST 2020, GMT+0200, dd/MM/yyyy]) [0 secondi]
[20-02-17 23:39:32:809 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:32:810 PST] SpreadsheetApp.Spreadsheet.getSheetByName([bilancio]) [0 secondi]
[20-02-17 23:39:32:910 PST] SpreadsheetApp.Sheet.getLastRow() [0,1 secondi]
[20-02-17 23:39:32:911 PST] SpreadsheetApp.Sheet.getRange([3, 1, 130, 1]) [0 secondi]
[20-02-17 23:39:33:056 PST] SpreadsheetApp.Range.getValues() [0,145 secondi]
[20-02-17 23:39:33:058 PST] Logger.log([cellulare riga n. 63, []]) [0 secondi]
[20-02-17 23:39:33:059 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:33:059 PST] SpreadsheetApp.Spreadsheet.getSheetByName([bilancio]) [0 secondi]
[20-02-17 23:39:33:060 PST] SpreadsheetApp.Sheet.getRange([63, 2]) [0 secondi]
[20-02-17 23:39:33:060 PST] SpreadsheetApp.Range.getValue() [0 secondi]
[20-02-17 23:39:33:062 PST] Logger.log([Importo da aggiornare:-41 - Importo aggiornato: -43, []]) [0 secondi]
[20-02-17 23:39:33:062 PST] SpreadsheetApp.Range.setValue([-43.0]) [0 secondi]
[20-02-17 23:39:33:063 PST] Logger.log([[[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]], []]) [0 secondi]
[20-02-17 23:39:33:064 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:33:064 PST] SpreadsheetApp.Spreadsheet.getSheetByName([movimenti]) [0 secondi]
[20-02-17 23:39:33:225 PST] SpreadsheetApp.Sheet.insertRowAfter([1]) [0,16 secondi]
[20-02-17 23:39:33:226 PST] SpreadsheetApp.Sheet.getRange([2, 1, 1, 6]) [0 secondi]
[20-02-17 23:39:33:431 PST] SpreadsheetApp.Range.setValues([[[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]]) [0,205 secondi]
[20-02-17 23:39:33:432 PST] SpreadsheetApp.Sheet.getRange([3, 8, 1, 1]) [0 secondi]
[20-02-17 23:39:33:432 PST] SpreadsheetApp.Sheet.getRange([2, 8, 1, 1]) [0 secondi]
[20-02-17 23:39:33:433 PST] SpreadsheetApp.Range.copyTo([Range]) [0 secondi]
[20-02-17 23:39:33:433 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:33:434 PST] SpreadsheetApp.Spreadsheet.getSheetByName([verifica]) [0 secondi]
[20-02-17 23:39:33:434 PST] SpreadsheetApp.Sheet.getRange([1, 5]) [0 secondi]
[20-02-17 23:39:33:705 PST] SpreadsheetApp.Range.getValue() [0,27 secondi]
[20-02-17 23:39:33:706 PST] SpreadsheetApp.Range.setValue([-41.0]) [0 secondi]
[20-02-17 23:39:33:707 PST] Logger.log([Aggiornamento completato!, []]) [0 secondi]
[20-02-17 23:39:33:707 PST] Logger.log([true, []]) [0 secondi]
[20-02-17 23:39:33:708 PST] Logger.log([r:%s,u%s,%s, [2.0, 4.0, after]]) [0 secondi]
[20-02-17 23:39:33:709 PST] Logger.log([value of i after call convertiMovR 60, []]) [0 secondi]
[20-02-17 23:39:33:994 PST] Esecuzione riuscita [1,315 secondi di esecuzione totale]
</code>```

答:
Issue:

Modifying i outside the loop.

Solution:

Restrict i to the  block scope using let

Snippet:

```<code>for (let i=rigaInizio; i<=ultimaRiga; i++){
</code>```

References:

let

Body:
I have a little function in google app script that have to do some things in a for loop, i.e.I have 3 rows with some values and for each row I have to update a sheet, but unfortunately I don't understand why but after just one loop the program stopped! And there are no return statements.

this is the code:

function movimentiRicorrenti(){

  tempoInizioScript = new Date();

  var rigaInizio = 2

  Logger.log("Data e ora script movimenti ricorrenti: " + Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy HH:mm"))

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ricorrenti")

  var ultimaRiga = sheet.getLastRow();  // ultima riga con i dati

  Logger.log("ultima riga " +ultimaRiga);

  var dataMovimento = Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy");

  var dataRangeMovimento;

  var datiMovimento;

  var today = new Date();

  //----------  parte dalla prima riga fino all'ultima del foglio, verifica che il movimento non sia scaduto, verifica se in data odierna andrà eseguito ed esegue eventualmente l'update

for (i=rigaInizio; i<=ultimaRiga; i++){

     dataRangeMovimento = sheet.getRange(i, 1, 1, 9)
     datiMovimento = dataRangeMovimento.getValues();

     Logger.log(convertiMovR(datiMovimento[0][0],datiMovimento[0][1],datiMovimento[0][2],datiMovimento[0][3],datiMovimento[0][4],datiMovimento[0][5],datiMovimento[0][6],datiMovimento[0][7],datiMovimento[0][8]));

}
}

other 2 functions

 function convertiMovR(cr, cat, conto, importo, ricorrenza, giornoM, giornoS, giornoA, scadenza){

    today = new Date();
    if (typeof importo != "number"){
       return false;
    }
    if (scadenza >= today){
       if (ricorrenza == "mensile" && today.getDate() == giornoM){
         aggiornaBil(cr,cat,conto,importo,"movimento ricorrente ogni mese il giorno " + giornoM);
         return true;
       }
       if (ricorrenza == "annuale"){
         if (today.getMonth()+1 == giornoA.getMonth()+1 && today.getDate() == giornoA.getDate() + 1 && today.getYear() == giornoA.getYear()){
           aggiornaBil(cr,cat,conto,importo,"movimento ricorrente ogni anno il giorno "+ Utilities.formatDate(new Date(giornoA), "GMT+0200", "dd/MM/yyyy"));
           return true;
         }
       }
       if (ricorrenza == "giornaliera"){
          aggiornaBil(cr,cat,conto,importo,"movimento ricorrente giornaliero");
          return true;
       }
       if (ricorrenza == "settimanale"){
         var giornoSett = 7;
           switch(giornoS)  {
              case "domenica":
                  giornoSett = 0;
                  break;
              case "lunedì":
                  giornoSett = 1;
                  break;
              case "martedì":
                  giornoSett = 2;
                  break;
              case "mercoledì":
                  giornoSett = 3;
                  break;
              case "giovedì":
                  giornoSett = 4;
                  break;
              case "venerdì":
                  giornoSett = 5;
                  break;
              case "sabato":
                  giornoSett = 6;
                  break;
           }
           if (giornoSett == 7){
                var corpo = "Verificare il movimento ricorrente alla riga " + i + " inserire un giorno della settimana dal lunedì alla domenica";
                MailApp.sendEmail("xxxxxx@gmail.com", "Errore movimenti ricorrenti", corpo, {name: "Bilancio Gianluca", htmlBody: corpo})
                Logger.log("Script movimenti ricorrenti eseguito in data/ora " + Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy hh:mm") + " con errori! Mail inviata a xxxxxx@gmail.com")
           }

         if (new Date().getDay() == giornoSett){

             var nScript = sheet.getRange(i, 10).getValue();
             nScript = nScript + 1;
             sheet.getRange(i, 10).setValue(nScript);

             aggiornaBil(cr,cat,conto,importo,"movimento ricorrente ogni settimana di " + giornoS);
             return true;
         }
       }
    }
}

function aggiornaBil(CostoRicavo, Categoria, Conto, Importo, Descrizione){

  var dataMovimento = Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy");

    if (CostoRicavo == "costo"){
      var rigaAgg = rigaAggiornamentoCosti(Conto);
      if (rigaAgg == 0){
        var corpo = "Il movimento inserito in data " +
            Utilities.formatDate(new Date(), "GMT+0200", "dd/MM/yyyy")+
            " relativo a " + Conto +
            " non ha corrispondenze in bilancio. Si prega di controllare il foglio di lavoro. Log di sistema:" + Logger.getLog() ;
          MailApp.sendEmail("xxxxxx@gmail.com", "Errore corrispondenza in bilancio", corpo, {name: "Bilancio Gianluca", htmlBody: corpo})

          // uscita dalla sub
          Logger.log("Conto non corrispondente!! Mail inviata a xxxxxx@gmail.com")
          return;
      }

      var foglioBilancio = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("bilancio")
      var rangeDaAggiornare = foglioBilancio.getRange(rigaAgg, colonnaCostiBilancio + 1)
      var importoDaAggiornare = rangeDaAggiornare.getValue();
      var importoAggiornato = importoDaAggiornare + Importo;
      Logger.log("Importo da aggiornare:" + cambiaSeparatore(importoDaAggiornare) + " - Importo aggiornato: " + cambiaSeparatore(arrotondaEuro(importoAggiornato)));
      rangeDaAggiornare.setValue(importoAggiornato);

   }
   if (CostoRicavo == "ricavo"){
      var rigaAgg = rigaAggiornamentoRicavi(Conto);
      if (rigaAgg == 0){
        var corpo = "Il movimento inserito in data " +
            Utilities.formatDate(new Date(dataMovimento), "GMT+0200", "dd/MM/yyyy")+
            " relativo a " + Conto +
            " non ha corrispondenze in bilancio. Si prega di controllare il foglio di lavoro. Log di sistema:" + Logger.getLog() ;
          MailApp.sendEmail("xxxxxx@gmail.com", "Errore corrispondenza in bilancio", corpo, {name: "Bilancio Gianluca", htmlBody: corpo})

          // uscita dalla sub
          Logger.log("Conto non corrispondente!! Mail inviata a xxxxxx@gmail.com")
          return;
      }

      var foglioBilancio = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("bilancio")
      var rangeDaAggiornare = foglioBilancio.getRange(rigaAgg, colonnaRicaviBilancio + 1)
      var importoDaAggiornare = rangeDaAggiornare.getValue();
      var importoAggiornato = importoDaAggiornare + Importo;
      Logger.log("Importo da aggiornare:" + cambiaSeparatore(importoDaAggiornare) + " - Importo aggiornato: " + cambiaSeparatore(arrotondaEuro(importoAggiornato)));
      rangeDaAggiornare.setValue(importoAggiornato);
   }

   var arrayMovimento = [[dataMovimento, CostoRicavo, Categoria, Conto, cambiaSeparatore(Importo), Descrizione]]

   Logger.log(arrayMovimento);

   var foglioMovimenti = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("movimenti")

   foglioMovimenti.insertRowAfter(1);

   foglioMovimenti.getRange(2, 1, 1, 6).setValues(arrayMovimento);

   foglioMovimenti.getRange(3,8,1,1).copyTo(foglioMovimenti.getRange(2,8,1,1))

   foglioBilancio = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("verifica")
   rangeDaAggiornare = foglioBilancio.getRange(1, 5)
   importoDaAggiornare = rangeDaAggiornare.getValue();
   importoAggiornato = importoDaAggiornare + Importo;
   rangeDaAggiornare.setValue(importoAggiornato);

   Logger.log("Aggiornamento completato!");
}

log:

[20-02-17 23:07:22:486 CET] Data e ora script movimenti ricorrenti: 18/02/2020 00:07
[20-02-17 23:07:22:757 CET] ultima riga 4
[20-02-17 23:07:23:206 CET] cellulare riga n. 63
[20-02-17 23:07:23:211 CET] Importo da aggiornare:-29 - Importo aggiornato: -31
[20-02-17 23:07:23:212 CET] [[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]
[20-02-17 23:07:24:067 CET] Aggiornamento completato!
[20-02-17 23:07:24:067 CET] true

and stopped.. but there are other 2 rows..

results after put  Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"before/after")  convertiMovR

Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"before")
Logger.log(convertiMovR(datiMovimento[0][0],datiMovimento[0][1],datiMovimento[0][2],datiMovimento[0][3],datiMovimento[0][4],datiMovimento[0][5],datiMovimento[0][6],datiMovimento[0][7],datiMovimento[0][8]));
Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"after")

[20-02-17 23:18:41:155 PST] Data e ora script movimenti ricorrenti: 18/02/2020 09:18

[20-02-17 23:18:41:422 PST] ultima riga 4

[20-02-17 23:18:41:580 PST] r:2.0,u4.0,before

[20-02-17 23:18:41:858 PST] cellulare riga n. 63

[20-02-17 23:18:41:863 PST] Importo da aggiornare:-31 - Importo aggiornato: -33

[20-02-17 23:18:41:865 PST] [[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]

[20-02-17 23:18:42:537 PST] Aggiornamento completato!

[20-02-17 23:18:42:538 PST] true

[20-02-17 23:18:42:538 PST] r:2.0,u4.0,after

but.. maybe i've understand... the for.. next loop doesn't wait that convertiMovR is finished

i try to put

 Logger.log("value of i before call convertiMovR " + i)
 Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"before")
 Logger.log(convertiMovR(datiMovimento[0][0],datiMovimento[0][1],datiMovimento[0][2],datiMovimento[0][3],datiMovimento[0][4],datiMovimento[0][5],datiMovimento[0][6],datiMovimento[0][7],datiMovimento[0][8]));
 Logger.log("r:%s,u%s,%s",rigaInizio,ultimaRiga,"after")
 Logger.log("value of i after call convertiMovR " + i)

and the result is

[20-02-18 08:39:32:396 CET] Data e ora script movimenti ricorrenti: 18/02/2020 09:39
[20-02-18 08:39:32:678 CET] ultima riga 4
[20-02-18 08:39:32:807 CET] value of i before call convertiMovR 2
[20-02-18 08:39:32:808 CET] r:2.0,u4.0,before
[20-02-18 08:39:33:057 CET] cellulare riga n. 63
[20-02-18 08:39:33:061 CET] Importo da aggiornare:-41 - Importo aggiornato: -43
[20-02-18 08:39:33:062 CET] [[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]
[20-02-18 08:39:33:706 CET] Aggiornamento completato!
[20-02-18 08:39:33:707 CET] true
[20-02-18 08:39:33:707 CET] r:2.0,u4.0,after
[20-02-18 08:39:33:708 CET] value of i after call convertiMovR 60

i guess i have to change the for .. next with other loop maybe do..loop or there is any statement that can 'wait' execution of convertiMovR ? ..

transcript

[20-02-17 23:39:32:386 PST] Avvio dell'esecuzione
[20-02-17 23:39:32:395 PST] Utilities.formatDate([Mon Feb 17 23:39:32 PST 2020, GMT+0200, dd/MM/yyyy HH:mm]) [0 secondi]
[20-02-17 23:39:32:396 PST] Logger.log([Data e ora script movimenti ricorrenti: 18/02/2020 09:39, []]) [0 secondi]
[20-02-17 23:39:32:398 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:32:573 PST] SpreadsheetApp.Spreadsheet.getSheetByName([ricorrenti]) [0,175 secondi]
[20-02-17 23:39:32:678 PST] SpreadsheetApp.Sheet.getLastRow() [0,103 secondi]
[20-02-17 23:39:32:679 PST] Logger.log([ultima riga 4, []]) [0 secondi]
[20-02-17 23:39:32:679 PST] Utilities.formatDate([Mon Feb 17 23:39:32 PST 2020, GMT+0200, dd/MM/yyyy]) [0 secondi]
[20-02-17 23:39:32:680 PST] SpreadsheetApp.Sheet.getRange([2, 1, 1, 9]) [0 secondi]
[20-02-17 23:39:32:807 PST] SpreadsheetApp.Range.getValues() [0,127 secondi]
[20-02-17 23:39:32:808 PST] Logger.log([value of i before call convertiMovR 2, []]) [0 secondi]
[20-02-17 23:39:32:808 PST] Logger.log([r:%s,u%s,%s, [2.0, 4.0, before]]) [0 secondi]
[20-02-17 23:39:32:808 PST] Utilities.formatDate([Sun Feb 16 15:00:00 PST 2020, GMT+0200, dd/MM/yyyy]) [0 secondi]
[20-02-17 23:39:32:809 PST] Utilities.formatDate([Mon Feb 17 23:39:32 PST 2020, GMT+0200, dd/MM/yyyy]) [0 secondi]
[20-02-17 23:39:32:809 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:32:810 PST] SpreadsheetApp.Spreadsheet.getSheetByName([bilancio]) [0 secondi]
[20-02-17 23:39:32:910 PST] SpreadsheetApp.Sheet.getLastRow() [0,1 secondi]
[20-02-17 23:39:32:911 PST] SpreadsheetApp.Sheet.getRange([3, 1, 130, 1]) [0 secondi]
[20-02-17 23:39:33:056 PST] SpreadsheetApp.Range.getValues() [0,145 secondi]
[20-02-17 23:39:33:058 PST] Logger.log([cellulare riga n. 63, []]) [0 secondi]
[20-02-17 23:39:33:059 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:33:059 PST] SpreadsheetApp.Spreadsheet.getSheetByName([bilancio]) [0 secondi]
[20-02-17 23:39:33:060 PST] SpreadsheetApp.Sheet.getRange([63, 2]) [0 secondi]
[20-02-17 23:39:33:060 PST] SpreadsheetApp.Range.getValue() [0 secondi]
[20-02-17 23:39:33:062 PST] Logger.log([Importo da aggiornare:-41 - Importo aggiornato: -43, []]) [0 secondi]
[20-02-17 23:39:33:062 PST] SpreadsheetApp.Range.setValue([-43.0]) [0 secondi]
[20-02-17 23:39:33:063 PST] Logger.log([[[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]], []]) [0 secondi]
[20-02-17 23:39:33:064 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:33:064 PST] SpreadsheetApp.Spreadsheet.getSheetByName([movimenti]) [0 secondi]
[20-02-17 23:39:33:225 PST] SpreadsheetApp.Sheet.insertRowAfter([1]) [0,16 secondi]
[20-02-17 23:39:33:226 PST] SpreadsheetApp.Sheet.getRange([2, 1, 1, 6]) [0 secondi]
[20-02-17 23:39:33:431 PST] SpreadsheetApp.Range.setValues([[[18/02/2020, costo, comunicazioni, cellulare, -2, movimento ricorrente ogni anno il giorno 17/02/2020]]]) [0,205 secondi]
[20-02-17 23:39:33:432 PST] SpreadsheetApp.Sheet.getRange([3, 8, 1, 1]) [0 secondi]
[20-02-17 23:39:33:432 PST] SpreadsheetApp.Sheet.getRange([2, 8, 1, 1]) [0 secondi]
[20-02-17 23:39:33:433 PST] SpreadsheetApp.Range.copyTo([Range]) [0 secondi]
[20-02-17 23:39:33:433 PST] SpreadsheetApp.getActiveSpreadsheet() [0 secondi]
[20-02-17 23:39:33:434 PST] SpreadsheetApp.Spreadsheet.getSheetByName([verifica]) [0 secondi]
[20-02-17 23:39:33:434 PST] SpreadsheetApp.Sheet.getRange([1, 5]) [0 secondi]
[20-02-17 23:39:33:705 PST] SpreadsheetApp.Range.getValue() [0,27 secondi]
[20-02-17 23:39:33:706 PST] SpreadsheetApp.Range.setValue([-41.0]) [0 secondi]
[20-02-17 23:39:33:707 PST] Logger.log([Aggiornamento completato!, []]) [0 secondi]
[20-02-17 23:39:33:707 PST] Logger.log([true, []]) [0 secondi]
[20-02-17 23:39:33:708 PST] Logger.log([r:%s,u%s,%s, [2.0, 4.0, after]]) [0 secondi]
[20-02-17 23:39:33:709 PST] Logger.log([value of i after call convertiMovR 60, []]) [0 secondi]
[20-02-17 23:39:33:994 PST] Esecuzione riuscita [1,315 secondi di esecuzione totale]

Body:
Issue:

Modifying i outside the loop.

Solution:

Restrict i to the  block scope using let

Snippet:

for (let i=rigaInizio; i<=ultimaRiga; i++){

References:

let


来源: stackexchange

问:
RealmSwift: No such module 'RealmSwift'
I configured RealmSwift 1.0.0 Latest Using Docs into the Xcode project. After installation i created a class file and getting module error - like: No such module 'RealmSwift' in class file.

1.

2.

3.

4.

After adding the Realm Plugin, i created a class and get the module error below.

Please help me to solve this error.

答: For me there first was an error like 'could not build Objective-C module 'RealmSwift'' which I could fix by deleting the Derived Data Folder, Pods Folder, Podfile.lock and the .xcworkspace and after that there was the error saying 'No such module 'RealmSwift'' which only disappeared when I first tried to build the project. Now everything works fine for me!</p>

ContentLicense: CC BY-SA 3.0

Title: RealmSwift: No such module 'RealmSwift'

ContentLicense: CC BY-SA 4.0


问:
Error SQL0204 - Not found HTTPCLOB in SYSTOOOLS type *N
I am trying to use HTTPCLOB function to issue a POST request to a web service, but when I run the program I get the error as in the title, no matter my efforts to match the fields' type of my SQL statement to those of the function.
Here D-specifications:

```<code>D url             s           1024a   varying
D httpHeader      s           1024a   varying inz
D requestMsg      s          32000a   varying inz
D resHttpHeader   s          32000a   varying inz
D resMsg          s          32000a   varying inz
</code>```

This is the SQL statement:

```<code>url = 'https://labelservice.gls-italy.com/AddParcel';
requestMsg = 'XMLInfoParcel: ' + xmlData;
httpHeader = 'Content-Type: application/x-www-form-urlencoded;'
           + ' Content-Length: ' + %char(%len(requestMsg))
           ;
exec sql
  select cast(responseMsg as clob(2G))
  //   , cast(responseHttpHeader as varchar(512))
  into :resMsg
  // , :resHttpHeader
  from table(systoools.HTTPCLOB(
          URL => cast(:url
                 as varchar(2048)),
          HTTPMETHOD => 'POST',
          HTTPHEADER => cast(:httpHeader
                 as clob(10K)),
          REQUESTMSG => cast(:requestMsg
                 as clob(2G))
             )
       ) as httpRequest
;
</code>```

where xmlData is an xml-variabile with some content in it.
I assume there might be other errors because this is my first try using this function.
Anyway, as for the IBM documentation here
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqudfhttpclob.htm
variables' types match.
What am I doing wrong?

答: So, the first error was a typo, then when the function is used as a table in the from clause the verbose version should be used instead.</p>

Body:
I am trying to use HTTPCLOB function to issue a POST request to a web service, but when I run the program I get the error as in the title, no matter my efforts to match the fields' type of my SQL statement to those of the function.
Here D-specifications:

D url             s           1024a   varying
D httpHeader      s           1024a   varying inz
D requestMsg      s          32000a   varying inz
D resHttpHeader   s          32000a   varying inz
D resMsg          s          32000a   varying inz

This is the SQL statement:

url = 'https://labelservice.gls-italy.com/AddParcel';
requestMsg = 'XMLInfoParcel: ' + xmlData;
httpHeader = 'Content-Type: application/x-www-form-urlencoded;'
           + ' Content-Length: ' + %char(%len(requestMsg))
           ;
exec sql
  select cast(responseMsg as clob(2G))
  //   , cast(responseHttpHeader as varchar(512))
  into :resMsg
  // , :resHttpHeader
  from table(systoools.HTTPCLOB(
          URL => cast(:url
                 as varchar(2048)),
          HTTPMETHOD => 'POST',
          HTTPHEADER => cast(:httpHeader
                 as clob(10K)),
          REQUESTMSG => cast(:requestMsg
                 as clob(2G))
             )
       ) as httpRequest
;

where xmlData is an xml-variabile with some content in it.
I assume there might be other errors because this is my first try using this function.
Anyway, as for the IBM documentation here
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqudfhttpclob.htm
variables' types match.
What am I doing wrong?


问:
Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)
I'm trying to use the Promise.allSettled API with TypeScript. Code here:

server.test.ts:

it('should partial success if QPS > 50', async () => {
  const requests: any[] = [];
  for (let i = 0; i < 51; i++) {
    requests.push(rp('http://localhost:3000/place'));
  }
  await Promise.allSettled(requests);
  // ...
});
```
<p>But TSC throws an error:</p>
<blockquote>
<p>Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)</p>
</blockquote>
<p>I already added these values to the <code>lib</code> option in <code>tsconfig.json</code>:</p>
<p><code>tsconfig.json</code>:</p>
```{
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "lib": [
      "ES2015",
      "ES2016",
      "ES2017",
      "ES2018",
      "ES2019",
      "ES2020",
      "ESNext"
    ]
   // ...
}
```

TypeScript version: "typescript": "^3.7.3"

So, how can I solve this? I know I can use an alternative module, but I am curious about working with TypeScript natively.

答:
The types for Promise.allSettled() were only merged in January, and will apparently be released in TypeScript 3.8.

As an interim solution, you can declare a mock-ish type for the function yourself:

```<code>declare interface PromiseConstructor {
    allSettled(promises: Array<Promise<any>>): Promise<Array<{status: 'fulfilled' | 'rejected', value?: any, reason?: any}>>;
}
</code>```

Body:
I'm trying to use the Promise.allSettled API with TypeScript. Code here:

server.test.ts:

it('should partial success if QPS > 50', async () => {
  const requests: any[] = [];
  for (let i = 0; i < 51; i++) {
    requests.push(rp('http://localhost:3000/place'));
  }
  await Promise.allSettled(requests);
  // ...
});

But TSC throws an error:

Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)

I already added these values to the lib option in tsconfig.json:

tsconfig.json:

{
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "lib": [
      "ES2015",
      "ES2016",
      "ES2017",
      "ES2018",
      "ES2019",
      "ES2020",
      "ESNext"
    ]
   // ...
}

TypeScript version: "typescript": "^3.7.3"

So, how can I solve this? I know I can use an alternative module, but I am curious about working with TypeScript natively.

Body:
The types for Promise.allSettled() were only merged in January, and will apparently be released in TypeScript 3.8.

As an interim solution, you can declare a mock-ish type for the function yourself:

declare interface PromiseConstructor {
    allSettled(promises: Array<Promise<any>>): Promise<Array<{status: 'fulfilled' | 'rejected', value?: any, reason?: any}>>;
}


答:
It's ES2020 and at Stage 4, so not available everywhere without a polyfill. It got typed and merged into TS. Try installing the latest @types/node package and see if that pulls it in.

Update: Looks like it will be adding es2020.promise to the libs, when it does land.

Update: npm i typescript@3.8.0-beta woot woot!

Title: Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)


问:
How to define textAppearence value in android layout
In my layout, I am using falling for predefined values for android:textAppearence. But, there are, as I found, at least 2 ways to define  them, which yields a very different result (like, different font size and alpha and weight value):

android:textAppearance:="@style/TextAppearance.MaterialComponents.Caption". This @style/... values are defined in (in my case) in a file
~/.gradle/caches/transforms-2/files-2.1/11ab83d2971a1126be493aa33fdd0f6e/material-1.1.0/res/values. This, for example, is defined as:

```<code><style name="TextAppearance.MaterialComponents.Caption" parent="TextAppearance.AppCompat.Caption">
  <item name="fontFamily">sans-serif</item>
  <item name="android:fontFamily">sans-serif</item>
  <item name="android:textStyle">normal</item>
  <item name="android:textAllCaps">false</item>
  <item name="android:textSize">12sp</item>
  <item name="android:letterSpacing">0.0333333333</item>
</style>
</code>```

android:textAppearance="@android:style/TextAppearance.Material.Menu". This is defined in
/home/rudra/.Android/Sdk/platforms/android-29/data/res/values/styles_material.xml. This is defined as:

```<code><style name="TextAppearance.Material.Menu">
    <item name="textSize">@dimen/text_size_menu_material</item>
    <item name="fontFamily">@string/font_family_menu_material</item>
</style>
</code>```

The main problem to me is, I am not sure which one to use for more consistent user experience. I am sure, the file for case 2 will not be shipped with my app, but maybe the user will have styles_material for his android-xx. But by realizing how values have changed with material-1.0.0 and 1.1.0, I am a bit sKeptic to depend on these values, but I am not sure.

On the other hand, this is a considerable work to redefine textAppearance for all possible scenarios.

So, I am looking for suggestions on how to define the textAppearence, and among case 1 and case 2, which should I use for more consistent result across devices

答:
Looking at TextView.java, there don't appear to be any attributes that are defined by android:textAppearance that are not able to be set on a TextView directly. So there doesn't appear to be any technical reason that one needs to use them over defining attributes in styles directly, at least in one's ability to configure how a TextView looks.

This means that you can avoid using it in your layouts as well as your styles without any adverse effects, provided that you override all the associated attributes. The base theme defines many different standard android:textAppearances for the various widgets, so you should check that all the widgets are properly overridden.

Based on my experience, android:textAppearance is most useful if you wish your app to appear to integrate into the rest of the device. So if you need big text, you can use android:textAppearance="?android:attr/textAppearanceLarge" and now your text is large! No need to know how many sp that means for the given device/screen size/etc..

However if your app is highly styled and you'd otherwise be overriding all the text sizes anyhow, the value-add of android:textAppearance diminishes. You can certainly use it as referenced in the posts above, but if that doesn't fit into your styling system, then feel free to omit it. It's just another tool to help you get a good-looking app across all devices.

I would also recommend making extra-sure that you try your app across a variety of devices if you choose not to use it, just to make sure that you didn't neglect to override a default android:textAppearance.

Body:
In my layout, I am using falling for predefined values for android:textAppearence. But, there are, as I found, at least 2 ways to define  them, which yields a very different result (like, different font size and alpha and weight value):

android:textAppearance:="@style/TextAppearance.MaterialComponents.Caption". This @style/... values are defined in (in my case) in a file
~/.gradle/caches/transforms-2/files-2.1/11ab83d2971a1126be493aa33fdd0f6e/material-1.1.0/res/values. This, for example, is defined as:

android:textAppearance="@android:style/TextAppearance.Material.Menu". This is defined in
/home/rudra/.Android/Sdk/platforms/android-29/data/res/values/styles_material.xml. This is defined as:

The main problem to me is, I am not sure which one to use for more consistent user experience. I am sure, the file for case 2 will not be shipped with my app, but maybe the user will have styles_material for his android-xx. But by realizing how values have changed with material-1.0.0 and 1.1.0, I am a bit sKeptic to depend on these values, but I am not sure.

On the other hand, this is a considerable work to redefine textAppearance for all possible scenarios.

So, I am looking for suggestions on how to define the textAppearence, and among case 1 and case 2, which should I use for more consistent result across devices


问:
Implementing K-medoids in Pyspark
I can not find a library to use PAM (K-medoids) in Pyspark.

I have found this in Scala :
https://gist.github.com/erikerlandson/c3c35f0b1aae737fc884

And this issue in Spark which was resolved in 2016 :
https://issues.apache.org/jira/browse/SPARK-4510

https://github.com/apache/spark/pull/3382

But it seems not to be working and this is not included in the mllib documentation :
http://spark.apache.org/docs/2.0.0/api/python/pyspark.mllib.html#module-pyspark.mllib.clustering

Does anyone knows any library for PAM in Pyspark ?

Thank you

答:
I actually had a go at this the other day for fun. Can't say much about performance as I'm quite new to spark. But here is KMedoids with K++ seeding:

```<code># (c) 2020 Jonathan Kelsey
# This code is licensed under MIT license
from pyspark.sql import functions as F
import pyspark
import numpy as np
import sys

def seed_kernel(data_broadcast, data_id_value, centeroids, k, metric):
    data = data_broadcast.value
    point = data_id_value[1]
    min_distance = sys.maxsize
    for j in range(len(centeroids)):
        distance = metric(point, data[centeroids[j]])
        min_distance = min(min_distance, distance)
    return min_distance

def seed_clusters(data_broadcast, data_frame, k, metric):
    data = data_broadcast.value
    centeroids = list(np.random.choice(data.shape[0], 1, replace=False))
    for i in range(k - 1):
        print("clusterSeed", i)
        distances = []
        mK = data_frame.rdd.map(lambda data_id_value: seed_kernel(data_broadcast, data_id_value, centeroids, k, metric))
        mK_collect = mK.collect()
        distances = np.array(mK_collect)
        next_centeroid = np.argmax(distances)
        centeroids.append(next_centeroid)
    print("centeroids", centeroids)
    return centeroids

def nearest_centeroid_kernel(data_id_value, centeroid_id_values, metric):
    _, data_value = data_id_value
    data_np = np.asarray(data_value)
    distances = []
    for _, centeroid_value in centeroid_id_values:
        centeroid_np = np.asarray(centeroid_value)
        distance = metric(data_np, centeroid_np)
        distances.append(distance)
    distances = np.asarray(distances)
    closest_centeroid = np.argmin(distances)
    return int(closest_centeroid)

def optimise_cluster_membership_spark(data, data_frame, n, metric, intital_cluster_indices=None):
    data_shape = data.shape
    data_rdd = data_frame.rdd
    data_length = data_shape[0]
    if intital_cluster_indices is None:
        index = np.random.choice(data_length, n, replace=False)
    else:
        index = intital_cluster_indices
    list_index = [int(i) for i in list(index)]
    centeroid_id_values = [(i,data[index[i]]) for i in range(len(index))]
    data_rdd = data_rdd.filter(lambda data_id_value: int(data_id_value["id"]) not in list_index)
    associated_cluster_points = data_rdd.map(lambda data_id_value: (data_id_value[0],nearest_centeroid_kernel(data_id_value, centeroid_id_values, metric)))
    clusters = associated_cluster_points.toDF(["id", "bestC"]).groupBy("bestC").agg(F.collect_list("id").alias("cluster"))
    return index, clusters

def cost_kernel(data_broadcast, test_centeroid, cluster_data, metric):
    data = data_broadcast.value
    cluster = np.asarray(cluster_data)
    cluster_length = cluster.shape[0]
    feature_length = data.shape[1]
    test_centeroid_column = np.zeros(shape=(cluster_length, feature_length), dtype=data.dtype)
    new_cluster_column = np.zeros(shape=(cluster_length, feature_length), dtype=data.dtype)
    for i in range(0, cluster_length):
        new_cluster_column[i] = data[cluster[i]]
        test_centeroid_column[i] = data[int(test_centeroid)]
    pairwise_distance =  metric(new_cluster_column, test_centeroid_column)# (np.absolute(new_cluster_column-test_centeroid_column).sum(axis=1))# metric(new_cluster_column, test_centeroid_column)
    cost = np.sum(pairwise_distance)
    return float(cost) #new_cluster_column.shape[1]

def optimise_centroid_selection_spark(data_broadcast, data_frame, centeroids, clusters_frames, metric):
    data = data_broadcast.value
    new_centeroid_ids = []
    total_cost = 0
    for cluster_idx in range(len(centeroids)):
        old_centeroid = centeroids[cluster_idx]
        cluster_frame = clusters_frames.filter(clusters_frames.bestC == cluster_idx).select(F.explode(clusters_frames.cluster))
        cluster_data = cluster_frame.collect()
        if cluster_data:
            cluster_data = [cluster_data[i].col for i in range(len(cluster_data))]
        else:
            cluster_data = []
        cost_data = cluster_frame.rdd.map(lambda point_id: (point_id[0], cost_kernel(data_broadcast, point_id[0], cluster_data, metric)))
        cost = cost_data.map(lambda point_id_cost: point_id_cost[1]).sum()
        total_cost = total_cost + cost
        point_result = cost_data.sortBy(lambda point_id_cost: point_id_cost[1]).take(1)
        if (point_result):
            best_point = point_result[0][0]
        else:
            best_point = old_centeroid
        new_centeroid_ids.append(best_point)
    return (new_centeroid_ids, total_cost)

def validate_metric(metric):
    if (metric == "euclidean" or metric == "hamming"):
        return True
    if isinstance(metric, dict) == False:
        return "Metric is not a dictionary. And not a known string 'euclidean' or 'hamming'"
    metric_keys = metric.keys()
    if "point" not in metric_keys or "vector" not in metric_keys:
        return "Metric does not contain a member function for 'point' and/or 'point'."
    if callable(metric["point"]) == False or callable(metric["vector"]) == False:
        return "Metric.point and/or Metric.vector are not callable functions."
    if (metric["point"].__code__.co_argcount != 2 and metric["vector"].__code__.co_argcount != 2):
        return "Metric.point and/or Metric.vector do not both have 2 arguments."
    return True

# pre-defined metrics

#vector metrics
def hamming_vector(stack1, stack2):
    return (stack1 != stack2).sum(axis=1)
def euclidean_vector(stack1, stack2):
    #return (np.absolute(stack2-stack1)).sum(axis=1)
    return np.sqrt(((stack2-stack1)**2).sum(axis=1))

# point metrics
def hamming_point(p1, p2):
    return np.sum((p1 != p2))
def euclidean_point(p1, p2):
    return np.sqrt(np.sum((p1 - p2)**2))

def fit(sc, data, n_clusters = 2, metric = "euclidean", seeding = "heuristic"):
    metric_valid = validate_metric(metric)
    if metric_valid == True:
        if metric == "euclidean":
            point_metric = euclidean_point
            vector_metric = euclidean_vector
        elif metric == "hamming":
            point_metric = hamming_point
            vector_metric = hamming_vector
        else:
            point_metric = metric["point"]
            vector_metric = metric["vector"]
    else:
        print(metric_valid)
        return

    data_np = np.asarray(data)
    data_broadcast = sc.broadcast(data_np)
    seeds = None
    data_frame  = sc.parallelize(data).zipWithIndex().map(lambda xy: (xy[1],xy[0])).toDF(["id", "vector"]).cache()
    if (seeding == "heuristic"):
        seeds = list(seed_clusters(data_broadcast, data_frame, n_clusters, point_metric))
    last_centeroids, last_clusters = optimise_cluster_membership_spark(data_np, data_frame, n_clusters, point_metric, seeds)
    last_cost = float('inf')
    iteration = 0
    escape = False
    while not escape:
        iteration = iteration + 1
        current_centeroids, current_cost = optimise_centroid_selection_spark(data_broadcast, data_frame, last_centeroids, last_clusters, vector_metric)
        current_centeroids, current_clusters = optimise_cluster_membership_spark(data_np, data_frame, n_clusters, point_metric, current_centeroids)
        print((current_cost<last_cost, current_cost, last_cost, current_cost - last_cost))
        if (current_cost<last_cost):
            print(("iteration",iteration,"cost improving...", current_cost, last_cost, current_centeroids))
            last_cost = current_cost
            last_centeroids = current_centeroids
            last_clusters = current_clusters
        else:
            print(("iteration",iteration,"cost got worse or did not improve", current_cost, last_cost))
            escape = True
    bc = last_clusters.sort("bestC", ascending=True).collect()
    unpacked_clusters = [bc[i].cluster for i in range(len(bc))]
    return (last_centeroids, unpacked_clusters)
</code>```

I used some sample data from pyclustering as a sanity check:

```<code>from pyclustering.cluster import cluster_visualizer
from pyclustering.utils import read_sample
from pyclustering.samples.definitions import FCPS_SAMPLES
from pyclustering.samples.definitions import SIMPLE_SAMPLES
sample = read_sample(FCPS_SAMPLES.SAMPLE_GOLF_BALL)
bestCentroids, bestClusters = fit(sc, sample, 9)
visualizer = cluster_visualizer()
visualizer.append_clusters(bestClusters, sample)
visualizer.show()
</code>```

Title: Implementing K-medoids in Pyspark

Body:
I actually had a go at this the other day for fun. Can't say much about performance as I'm quite new to spark. But here is KMedoids with K++ seeding:

# (c) 2020 Jonathan Kelsey
# This code is licensed under MIT license
from pyspark.sql import functions as F
import pyspark
import numpy as np
import sys

def seed_kernel(data_broadcast, data_id_value, centeroids, k, metric):
    data = data_broadcast.value
    point = data_id_value[1]
    min_distance = sys.maxsize
    for j in range(len(centeroids)):
        distance = metric(point, data[centeroids[j]])
        min_distance = min(min_distance, distance)
    return min_distance

def seed_clusters(data_broadcast, data_frame, k, metric):
    data = data_broadcast.value
    centeroids = list(np.random.choice(data.shape[0], 1, replace=False))
    for i in range(k - 1):
        print("clusterSeed", i)
        distances = []
        mK = data_frame.rdd.map(lambda data_id_value: seed_kernel(data_broadcast, data_id_value, centeroids, k, metric))
        mK_collect = mK.collect()
        distances = np.array(mK_collect)
        next_centeroid = np.argmax(distances)
        centeroids.append(next_centeroid)
    print("centeroids", centeroids)
    return centeroids

def nearest_centeroid_kernel(data_id_value, centeroid_id_values, metric):
    _, data_value = data_id_value
    data_np = np.asarray(data_value)
    distances = []
    for _, centeroid_value in centeroid_id_values:
        centeroid_np = np.asarray(centeroid_value)
        distance = metric(data_np, centeroid_np)
        distances.append(distance)
    distances = np.asarray(distances)
    closest_centeroid = np.argmin(distances)
    return int(closest_centeroid)

def optimise_cluster_membership_spark(data, data_frame, n, metric, intital_cluster_indices=None):
    data_shape = data.shape
    data_rdd = data_frame.rdd
    data_length = data_shape[0]
    if intital_cluster_indices is None:
        index = np.random.choice(data_length, n, replace=False)
    else:
        index = intital_cluster_indices
    list_index = [int(i) for i in list(index)]
    centeroid_id_values = [(i,data[index[i]]) for i in range(len(index))]
    data_rdd = data_rdd.filter(lambda data_id_value: int(data_id_value["id"]) not in list_index)
    associated_cluster_points = data_rdd.map(lambda data_id_value: (data_id_value[0],nearest_centeroid_kernel(data_id_value, centeroid_id_values, metric)))
    clusters = associated_cluster_points.toDF(["id", "bestC"]).groupBy("bestC").agg(F.collect_list("id").alias("cluster"))
    return index, clusters

def cost_kernel(data_broadcast, test_centeroid, cluster_data, metric):
    data = data_broadcast.value
    cluster = np.asarray(cluster_data)
    cluster_length = cluster.shape[0]
    feature_length = data.shape[1]
    test_centeroid_column = np.zeros(shape=(cluster_length, feature_length), dtype=data.dtype)
    new_cluster_column = np.zeros(shape=(cluster_length, feature_length), dtype=data.dtype)
    for i in range(0, cluster_length):
        new_cluster_column[i] = data[cluster[i]]
        test_centeroid_column[i] = data[int(test_centeroid)]
    pairwise_distance =  metric(new_cluster_column, test_centeroid_column)# (np.absolute(new_cluster_column-test_centeroid_column).sum(axis=1))# metric(new_cluster_column, test_centeroid_column)
    cost = np.sum(pairwise_distance)
    return float(cost) #new_cluster_column.shape[1]

def optimise_centroid_selection_spark(data_broadcast, data_frame, centeroids, clusters_frames, metric):
    data = data_broadcast.value
    new_centeroid_ids = []
    total_cost = 0
    for cluster_idx in range(len(centeroids)):
        old_centeroid = centeroids[cluster_idx]
        cluster_frame = clusters_frames.filter(clusters_frames.bestC == cluster_idx).select(F.explode(clusters_frames.cluster))
        cluster_data = cluster_frame.collect()
        if cluster_data:
            cluster_data = [cluster_data[i].col for i in range(len(cluster_data))]
        else:
            cluster_data = []
        cost_data = cluster_frame.rdd.map(lambda point_id: (point_id[0], cost_kernel(data_broadcast, point_id[0], cluster_data, metric)))
        cost = cost_data.map(lambda point_id_cost: point_id_cost[1]).sum()
        total_cost = total_cost + cost
        point_result = cost_data.sortBy(lambda point_id_cost: point_id_cost[1]).take(1)
        if (point_result):
            best_point = point_result[0][0]
        else:
            best_point = old_centeroid
        new_centeroid_ids.append(best_point)
    return (new_centeroid_ids, total_cost)

def validate_metric(metric):
    if (metric == "euclidean" or metric == "hamming"):
        return True
    if isinstance(metric, dict) == False:
        return "Metric is not a dictionary. And not a known string 'euclidean' or 'hamming'"
    metric_keys = metric.keys()
    if "point" not in metric_keys or "vector" not in metric_keys:
        return "Metric does not contain a member function for 'point' and/or 'point'."
    if callable(metric["point"]) == False or callable(metric["vector"]) == False:
        return "Metric.point and/or Metric.vector are not callable functions."
    if (metric["point"].__code__.co_argcount != 2 and metric["vector"].__code__.co_argcount != 2):
        return "Metric.point and/or Metric.vector do not both have 2 arguments."
    return True

# pre-defined metrics

#vector metrics
def hamming_vector(stack1, stack2):
    return (stack1 != stack2).sum(axis=1)
def euclidean_vector(stack1, stack2):
    #return (np.absolute(stack2-stack1)).sum(axis=1)
    return np.sqrt(((stack2-stack1)**2).sum(axis=1))

# point metrics
def hamming_point(p1, p2):
    return np.sum((p1 != p2))
def euclidean_point(p1, p2):
    return np.sqrt(np.sum((p1 - p2)**2))

def fit(sc, data, n_clusters = 2, metric = "euclidean", seeding = "heuristic"):
    metric_valid = validate_metric(metric)
    if metric_valid == True:
        if metric == "euclidean":
            point_metric = euclidean_point
            vector_metric = euclidean_vector
        elif metric == "hamming":
            point_metric = hamming_point
            vector_metric = hamming_vector
        else:
            point_metric = metric["point"]
            vector_metric = metric["vector"]
    else:
        print(metric_valid)
        return

    data_np = np.asarray(data)
    data_broadcast = sc.broadcast(data_np)
    seeds = None
    data_frame  = sc.parallelize(data).zipWithIndex().map(lambda xy: (xy[1],xy[0])).toDF(["id", "vector"]).cache()
    if (seeding == "heuristic"):
        seeds = list(seed_clusters(data_broadcast, data_frame, n_clusters, point_metric))
    last_centeroids, last_clusters = optimise_cluster_membership_spark(data_np, data_frame, n_clusters, point_metric, seeds)
    last_cost = float('inf')
    iteration = 0
    escape = False
    while not escape:
        iteration = iteration + 1
        current_centeroids, current_cost = optimise_centroid_selection_spark(data_broadcast, data_frame, last_centeroids, last_clusters, vector_metric)
        current_centeroids, current_clusters = optimise_cluster_membership_spark(data_np, data_frame, n_clusters, point_metric, current_centeroids)
        print((current_cost<last_cost, current_cost, last_cost, current_cost - last_cost))
        if (current_cost<last_cost):
            print(("iteration",iteration,"cost improving...", current_cost, last_cost, current_centeroids))
            last_cost = current_cost
            last_centeroids = current_centeroids
            last_clusters = current_clusters
        else:
            print(("iteration",iteration,"cost got worse or did not improve", current_cost, last_cost))
            escape = True
    bc = last_clusters.sort("bestC", ascending=True).collect()
    unpacked_clusters = [bc[i].cluster for i in range(len(bc))]
    return (last_centeroids, unpacked_clusters)

I used some sample data from pyclustering as a sanity check:

from pyclustering.cluster import cluster_visualizer
from pyclustering.utils import read_sample
from pyclustering.samples.definitions import FCPS_SAMPLES
from pyclustering.samples.definitions import SIMPLE_SAMPLES
sample = read_sample(FCPS_SAMPLES.SAMPLE_GOLF_BALL)
bestCentroids, bestClusters = fit(sc, sample, 9)
visualizer = cluster_visualizer()
visualizer.append_clusters(bestClusters, sample)
visualizer.show()


问:
ReactJS: Why does pushing values to state in an object removes data?
I have set up a couple of input fields where the value goes into an object input, and I'm trying to store it into a new object with other data, but the value is disappearing.

On my handleSubmit function, I have setNewData(mediaArray) where it just sets the mediaArray into a new state - which it happens to be working correctly, but if I wrap the mediaArray into an object: setNewData({mediaArray}), it erases the data. Why does it do that?

I'm ultimately trying to do this: setNewData({...setSomeOtherInfo, mediaArray}) so I can have this:

```<code>newData = {
  info: '',
  description: '',
  mediaArray: [
    {
      input1: '',
      input2: '',
    },
    {
      input1: '',
      input2: '',
    },
    {
      input1: '',
      input2: '',
    },
  ]
}
</code>```

Component:

```<code>const Screen = props => {

  const [someOtherInfo, setSomeOtherInfo] = useState({
    info: '',
    description: ''
  });
  const [mediaArray, setMediaArray] = useState([]);
  const [newData, setNewData] = useState(null);
  const [input, setInput] = useState({
    input1: '',
    input2: ''
  });

  const handleInput1 = (index, value) => {
    mediaArray[index] = {
      ...mediaArray[index],
      ['input1']: value,
    };
  };

  const handleInput2 = (index, value) => {
    mediaArray[index] = {
      ...mediaArray[index],
      ['input2']: value,
    };
  };

  const handleSubmit = () => {
    setNewData(mediaArray);
  };

  useEffect(() => {

  }, [newData]);

  return (
    <View>
      <TextInput onChangeText={e => handleInput1(index, e)} value={input.input1} />
      <TextInput onChangeText={e => handleInput2(index, e)} value={input.input2} />
    </View>
  );
};

export default Screen;
</code>```

答:
You are doing it quite wrong.

You should not create so many states, if they are linked together. You can create a single state and update multiple values.

You cant setState with mutated data. You have to clone it before set again. Use destructure to clone

The sample is given below:

```<code>const Screen = props => {
  const [mediaArray, setMediaArray] = useState([]);
  const [newData, setNewData] = useState(null);
  const [input, setInput] = useState({
    input1: "",
    input2: ""
  });

  const handleSubmit = (name, value) => {
    mediaArray[index] = {
      ...mediaArray[index],
      [name]: value
    };
    setMediaArray(mediaArray);
  };

  return (
    <View>
      <TextInput
        onChangeText={e => handleSubmit.bind(null, 'input1')(index, e)}
        value={input.input1}
      />
      <TextInput
        onChangeText={e => handleSubmit.bind(null, 'input2')(index, e)}
        value={input.input2}
      />
    </View>
  );
};

export default Screen;
</code>```

If you have such complex logic. Create a reducer(use reducer) to make it simple.

Body:
I have set up a couple of input fields where the value goes into an object input, and I'm trying to store it into a new object with other data, but the value is disappearing.

On my handleSubmit function, I have setNewData(mediaArray) where it just sets the mediaArray into a new state - which it happens to be working correctly, but if I wrap the mediaArray into an object: setNewData({mediaArray}), it erases the data. Why does it do that?

I'm ultimately trying to do this: setNewData({...setSomeOtherInfo, mediaArray}) so I can have this:

newData = {
  info: '',
  description: '',
  mediaArray: [
    {
      input1: '',
      input2: '',
    },
    {
      input1: '',
      input2: '',
    },
    {
      input1: '',
      input2: '',
    },
  ]
}

Component:

const Screen = props => {

  const [someOtherInfo, setSomeOtherInfo] = useState({
    info: '',
    description: ''
  });
  const [mediaArray, setMediaArray] = useState([]);
  const [newData, setNewData] = useState(null);
  const [input, setInput] = useState({
    input1: '',
    input2: ''
  });

  const handleInput1 = (index, value) => {
    mediaArray[index] = {
      ...mediaArray[index],
      ['input1']: value,
    };
  };

  const handleInput2 = (index, value) => {
    mediaArray[index] = {
      ...mediaArray[index],
      ['input2']: value,
    };
  };

  const handleSubmit = () => {
    setNewData(mediaArray);
  };

  useEffect(() => {

  }, [newData]);

  return (
    <View>
      <TextInput onChangeText={e => handleInput1(index, e)} value={input.input1} />
      <TextInput onChangeText={e => handleInput2(index, e)} value={input.input2} />
    </View>
  );
};

export default Screen;

Body:
You are doing it quite wrong.

You should not create so many states, if they are linked together. You can create a single state and update multiple values.

You cant setState with mutated data. You have to clone it before set again. Use destructure to clone

The sample is given below:

const Screen = props => {
  const [mediaArray, setMediaArray] = useState([]);
  const [newData, setNewData] = useState(null);
  const [input, setInput] = useState({
    input1: "",
    input2: ""
  });

  const handleSubmit = (name, value) => {
    mediaArray[index] = {
      ...mediaArray[index],
      [name]: value
    };
    setMediaArray(mediaArray);
  };

  return (
    <View>
      <TextInput
        onChangeText={e => handleSubmit.bind(null, 'input1')(index, e)}
        value={input.input1}
      />
      <TextInput
        onChangeText={e => handleSubmit.bind(null, 'input2')(index, e)}
        value={input.input2}
      />
    </View>
  );
};

export default Screen;

If you have such complex logic. Create a reducer(use reducer) to make it simple.


问:
How to filter/compare 2 arrays of objects by single property with lodash?
I have the following arrays of objects?

let arr1 = [{
  id: 1,
  props: []
}, {
  id: 2,
  props: []
}, {
  id: 3,
  props: []
}]

let arr2 = [{
  id: 1,
  props: ['a', 'b']
}, {
  id: 3,
  props: []
}]
```

<p>I need to somehow compare these 2 arrays and return a new array that contains only objects which IDs are not in both of the original arrays. So in the case above it should contain only the object with ID 2, since it's only in arr1.</p>

<p>I tried to use</p>

```let arr3 = _.differenceWith(arr1, arr2, _.isEqual)
```

<p>And it works as long as props array in objects are similar and I don't change it (I'm changing it only in the second array).</p>

<p>I also tried this:</p>

```let arr3 = _.filter(arr1, o => o.id === _.find(arr2, obj2 => o.id === obj2.id))
```

But that didn't work at all.

Any ideas?

答:
Use reduce and Object.values will simplify.

let arr1 = [
  {
    id: 1,
    props: []
  },
  {
    id: 2,
    props: []
  },
  {
    id: 3,
    props: []
  }
];

let arr2 = [
  {
    id: 1,
    props: ["a", "b"]
  },
  {
    id: 3,
    props: []
  }
];

const updated = Object.values(
  [...arr1, ...arr2].reduce(
    (acc, curr) =>
      Object.assign(acc, { [curr.id]: curr.id in acc ? "" : { ...curr } }),
    {}
  )
).filter(x => x);

console.log(updated);```

Body:
I have the following arrays of objects?

let arr1 = [{
  id: 1,
  props: []
}, {
  id: 2,
  props: []
}, {
  id: 3,
  props: []
}]

let arr2 = [{
  id: 1,
  props: ['a', 'b']
}, {
  id: 3,
  props: []
}]

I need to somehow compare these 2 arrays and return a new array that contains only objects which IDs are not in both of the original arrays. So in the case above it should contain only the object with ID 2, since it's only in arr1.

I tried to use

let arr3 = _.differenceWith(arr1, arr2, _.isEqual)

And it works as long as props array in objects are similar and I don't change it (I'm changing it only in the second array).

I also tried this:

let arr3 = _.filter(arr1, o => o.id === _.find(arr2, obj2 => o.id === obj2.id))

But that didn't work at all.

Any ideas?


问:
Enabling Amazon S3 bucket versioning
I'm trying to enable bucket versioning using the .net amazon sdk. I was wondering if anyone could shed some light on it.</p>

答: There's a specific method that can be called to enabled this in the SDK.</p>

Title: Enabling Amazon S3 bucket versioning


问:
Angular 5 and Service Worker: How to exclude a particular path from ngsw-config.json
I have ngsw-config.json (taken from the docs):

    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }]
    }
```

<p>On my site there is a link to the RSS feed <code>/api/rss</code>, which should open in a new browser tab without loading Angular app. How can I exclude it from a list of resources whose request is redirected to <code>index.html</code>?</p>

<p><strong>UPD</strong>: I tried but not working the following config (see <code>!/api/rss</code>):</p>

<pre class="lang-js prettyprint-override"><code>    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "patterns": ["!/api/rss"],
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html",
            "!/api/rss"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }]
    }
</code>```

答:
you can disable service worker for specific request, via headers or query string.

More Detail;

Go github issue please

Body:
I have ngsw-config.json (taken from the docs):

    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }]
    }

On my site there is a link to the RSS feed /api/rss, which should open in a new browser tab without loading Angular app. How can I exclude it from a list of resources whose request is redirected to index.html?

UPD: I tried but not working the following config (see !/api/rss):

    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "patterns": ["!/api/rss"],
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html",
            "!/api/rss"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }]
    }


问:
Why doesn't Tensorflow have if conditions?
Recently I was implementing a custom loss function in Tensorflow and I realized, Tensorflow doesn't have if conditions. I feel like if conditions are such an inherent programming feature why would Tensorflow developers not have such a fundamental feature in such a big project?</p>

答:
TensorFlow is not thought to be eagerly executed as python is. So the framework provides extra functions to kind o simulate eager functionalities.

Some examples are:

tf.cond(condition, true_fn, flase_fn): In case the condition is false it will execute the false_fn, otherwise the true_fn

```<code>z = tf.multiply(a, b)
result = tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y))
</code>```

tf.while

```<code>i = tf.constant(0)
c = lambda i: tf.less(i, 10)
b = lambda i: tf.add(i, 1)
r = tf.while_loop(c, b, [i])
</code>```

Source: https://www.tensorflow.org/api_docs/python/

Body:
TensorFlow is not thought to be eagerly executed as python is. So the framework provides extra functions to kind o simulate eager functionalities.

Some examples are:

tf.cond(condition, true_fn, flase_fn): In case the condition is false it will execute the false_fn, otherwise the true_fn

z = tf.multiply(a, b)
result = tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y))

tf.while

i = tf.constant(0)
c = lambda i: tf.less(i, 10)
b = lambda i: tf.add(i, 1)
r = tf.while_loop(c, b, [i])

Source: https://www.tensorflow.org/api_docs/python/


问:
TextInput cursor jump to right end when the input is empty
Cursor in the TextInput is jumping to the right end when the field is empty.

```<code><TextInput
    autoCorrect={ false }
    keyboardType="number-pad"
    autoCapitalize="none"
    placeholder="Inactivity time in seconds"
    onChangeText={ (value) => this.setState({ inactivityTime: value }) }
    value={ this.state.inactivityTime }
    style={ commons.pinInput } />
</code>```

This issue only happens when the value prop of the TextInput is set to the state.

答:
this is the exact problem i was facing, its a bug in React native textInput when the input is empty , the cursor jumps to the right . It was only happening when i used textAlign center.

So i had to go through the process of actually editing the design and assigning the placeholder and text to be centered in the left :

```<code><TextInput
textAlign="left"
/>
</code>```

Hope this fix helps. actually upvoting question too , so that. ican get a real fix for the answer.

Body:
Cursor in the TextInput is jumping to the right end when the field is empty.

<TextInput
    autoCorrect={ false }
    keyboardType="number-pad"
    autoCapitalize="none"
    placeholder="Inactivity time in seconds"
    onChangeText={ (value) => this.setState({ inactivityTime: value }) }
    value={ this.state.inactivityTime }
    style={ commons.pinInput } />

This issue only happens when the value prop of the TextInput is set to the state.

Body:
this is the exact problem i was facing, its a bug in React native textInput when the input is empty , the cursor jumps to the right . It was only happening when i used textAlign center.

So i had to go through the process of actually editing the design and assigning the placeholder and text to be centered in the left :

<TextInput
textAlign="left"
/>

Hope this fix helps. actually upvoting question too , so that. ican get a real fix for the answer.


问:
How often false signals are triggered in a condition variable?
I don’t understand why std::condition_variable has more standard guarantees than this code:</p>

```<code>class condition_variable {
public:
  void notify_one() {}
  void notify_all() {}
  void wait(unique_lock<mutex> &lock) {
    lock.unlock();
    this_thread::sleep_for(15ms);
    lock.lock();
  }
  void wait(unique_lock<mutex> &lock,
            const function<bool()> &pred) {
    while (!pred()) wait(lock);
  }
};
</code>```

答:
The simplest implementation for std::condition_variable::wait() would just correspond to busy waiting:

```<code>template<typename Predicate>
void wait(std::unique_lock<std::mutex>& lck, Predicate pred) {
   while (!pred()) {
      lck.unlock();
      lck.lock();
   }
}
</code>```

For this reason, spurious wakeups can occur.

Your implementation puts the thread to sleep between the release and the acquisition of the lock on the mutex:

```<code>void wait(unique_lock<mutex> &lock) {
   lock.unlock();
   this_thread::sleep_for(15ms); // <--
   lock.lock();
}
</code>```

Finding the right sleeping period may be difficult, though. The lower it is, the more it resembles busy waiting, and therefore the more CPU cycles are wasted. The higher it is, the fewer CPU cycles are wasted, but the worse is the responsiveness.

How often spurious wakeups occur on your implementation depends on the election of the sleeping period.

Body:
I don’t understand why std::condition_variable has more standard guarantees than this code:

class condition_variable {
public:
  void notify_one() {}
  void notify_all() {}
  void wait(unique_lock<mutex> &lock) {
    lock.unlock();
    this_thread::sleep_for(15ms);
    lock.lock();
  }
  void wait(unique_lock<mutex> &lock,
            const function<bool()> &pred) {
    while (!pred()) wait(lock);
  }
};

Body:
The simplest implementation for std::condition_variable::wait() would just correspond to busy waiting:

template<typename Predicate>
void wait(std::unique_lock<std::mutex>& lck, Predicate pred) {
   while (!pred()) {
      lck.unlock();
      lck.lock();
   }
}

For this reason, spurious wakeups can occur.

Your implementation puts the thread to sleep between the release and the acquisition of the lock on the mutex:

void wait(unique_lock<mutex> &lock) {
   lock.unlock();
   this_thread::sleep_for(15ms); // <--
   lock.lock();
}

Finding the right sleeping period may be difficult, though. The lower it is, the more it resembles busy waiting, and therefore the more CPU cycles are wasted. The higher it is, the fewer CPU cycles are wasted, but the worse is the responsiveness.

How often spurious wakeups occur on your implementation depends on the election of the sleeping period.


问:
TFS 2010 Upgrade Path to Azure DevOps Services - Circumvent or Not Circumvent?
I am preparing an upgrade of an on-premises TFS 2010 instance to the cloud-based Azure DevOps Services, using Microsoft's Data Migration Tool for Azure DevOps Migration to facilitate the collection database move to Azure DevOps Services. There are however a few key points or caveats to highlight relating to this proposed upgrade and these are listed below.

It will be an "In Place Upgrade", meaning we intend to use the existing "on-premises" hardware throughout the process.

Our TFS 2010 instance is hosted on a Windows Server 2008 R2 Enterprise server.

The Data Tier is implemented on a Microsoft SQL Server 2008 R2 instance.

Now, the Data Migration Guide recommends that to migrate to Azure DevOps Services, we first need to complete an upgrade from TFS 2010 to TFS 2013, as per the attached Upgrade path map. TFS 2013 however is not compatible with SQL Server 2008 R2 and requires SQL Server 2012 (Express, Standard, Enterprise).

On the other hand, TFS 2012 supports SQL Server 2008 R2 and can also then be upgraded directly to Azure DevOps Services, according to the Data Migration Tool's Recommended Upgrade Path. This, I believe will avoid the need to upgrade our current instance of SQL Server from SQL 2008 R2 to SQL Server 2012 (to upgrade to TFS 2013), in order to finally achieve our objective of upgrading to Azure DevOps Services.

Can anyone foresee any issues with this approach, or should we just bite the bullet and complete that SQL 2008 to SQL 2012 upgrade as suggested in the guide?

答:
Please check this documentation:

The data migration tool for Azure DevOps supports the two latest
  releases of Azure DevOps Server at a given time. Releases include
  updates and major releases. Currently the following versions of Azure
  DevOps Server are supported for import:

Azure DevOps Server 2019.1.1

Azure DevOps Server 2019 Update 1

As @Daniel Mann mentioned above, the picture you posted showed the upgrade path from old versions TFS to Azure DevOps Server 2019 (Azure DevOps Server was previously named TFS), not Azure DevOps Service.

In summary, both hardware and software you use need to be upgrade. To migrate to Azure DevOps Service, you have to upgrade to TFS 2012.3/TFS 2013.5, and then upgrade to Azure DevOps Server 2019.1 (TFS 2019.1), after that, migrate to Azure DevOps Service.


问:
convert php string to json object
I have a string in database that actualy is an json object. How can i convert it to see as object/array instead string?
this is string </p>

```<code>[{"id_piesa":"8","cantitate_piesa":"12","garantie_piesa":false},{"id_piesa":"30","cantitate_piesa":1,"garantie_piesa":true}]
</code>```

答:
You can use json_decode() php function.

```<code>$json_string = '[{"id_piesa":"8","cantitate_piesa":"12","garantie_piesa":false},{"id_piesa":"30","cantitate_piesa":1,"garantie_piesa":true}]';
$array = json_decode( $json_string , TRUE);

print_r( $array);
</code>```

Output:

```<code>Array
(
    [0] => Array
        (
            [id_piesa] => 8
            [cantitate_piesa] => 12
            [garantie_piesa] =>
        )

    [1] => Array
        (
            [id_piesa] => 30
            [cantitate_piesa] => 1
            [garantie_piesa] => 1
        )

)
</code>```

if you add TRUE as second argument the returned objects will be converted into associative arrays.

Here you can find the complete documentation.

Title: convert php string to json object

Body:
I have a string in database that actualy is an json object. How can i convert it to see as object/array instead string?
this is string

[{"id_piesa":"8","cantitate_piesa":"12","garantie_piesa":false},{"id_piesa":"30","cantitate_piesa":1,"garantie_piesa":true}]

Body:
You can use json_decode() php function.

$json_string = '[{"id_piesa":"8","cantitate_piesa":"12","garantie_piesa":false},{"id_piesa":"30","cantitate_piesa":1,"garantie_piesa":true}]';
$array = json_decode( $json_string , TRUE);

print_r( $array);

Output:

Array
(
    [0] => Array
        (
            [id_piesa] => 8
            [cantitate_piesa] => 12
            [garantie_piesa] =>
        )

    [1] => Array
        (
            [id_piesa] => 30
            [cantitate_piesa] => 1
            [garantie_piesa] => 1
        )

)

if you add TRUE as second argument the returned objects will be converted into associative arrays.

Here you can find the complete documentation.


问:
Handling paper documentation
After every new program written a lot of paper documentation remains.

Apart from the usual scribble notes from the programmers there usually is a nice heap of papers containing physical model explanations, calculations and so on (equations, tables, graphs, little pictures describing variables ...)

We usually do numerically intensive calculations in console applications, which are not released to the public (remain in the house, only results go out). Before each project is finished all those papers have to be packed somehow with the application, so that one day, when someone will be reusing parts of it, has some idea what is what in there.
So far, we've been using the 'dirty' solution of just scanning all of it, and packing it up on the disc with the application.

So I was wondering ... for all science guys here in a similar situation ... how do you handle project documentation which is needed, but not released to the public ?
(the one that does, goes to the dtp laddies, and they make it nice and shiny - not our problem anymore :)

答:
Here is some of the thoughts... Not so practical though :)

We can make it part of our Check-in notes. This may help the developers going to maintain the application.

Update the requirement document/Low level design document with these items

ContentLicense: CC BY-SA 2.5

Title: Handling paper documentation

OwnerDisplayName: renil


问:
Facebook Check IsFan is not working, please help

```<code>    <script type="text/javascript">
        window.fbAsyncInit = function() {
            FB.init({appId: '197724456937488', status: true, cookie: true, xfbml: true});

            // this will fire when any of the like widgets are "liked" by the user
FB.Event.subscribe('edge.create', function(response) {

         document.getElementById('likepost').style.display = "";
             document.getElementById('falsebox').style.display = "none";
              document.getElementById('fb').style.display = "";

});

FB.Event.subscribe('edge.remove', function(response) {
    console.log('This was UNliked from this page: ' + window.location);
});
        };
        (function() {
            var e = document.createElement('script');
            e.type = 'text/javascript';
            e.src = document.location.protocol +
                '//connect.facebook.net/en_US/all.js';
            e.async = true;
            document.getElementById('fb-root').appendChild(e);
        }());

    </script>

    <div id="fb" style="display:none">
    <fb:like-box href="<?php echo $detail['Post_FB'] ;?>" width="292" height="100" show_faces="false" stream="false" header="false"></fb:like-box>
    </div>
    <div id="link" style="display:none">
    <fb:like href="http://design-pro.co.cc/appleworld/post.php?id=<?php echo $id?>" send="false" width="450" show_faces="true" font=""></fb:like>
    </div>
</code>```

答:
Use this as your starting point for reference:  http://developers.facebook.com/docs/reference/javascript/FB.init/

First thing to notice is how FB.init() call is wrapped in:

```<code>window.fbAsyncInit = function() {
  ...
};
</code>```

You are already setting 'status' to true in your init call, so you should be able to subscribe to an event which will return the status value, which tells you the user's login status.

Check out:  http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/

Your FB.Event.subscribe(...) call should also be inside the same window.fbAsyncInit() call.

Once you verify that user is logged in, you can check for fan status.  You still have to use the old REST API, since Facebook hasn't ported this over to Graph API:  http://developers.facebook.com/docs/reference/rest/pages.isFan/

Please note: We are in the process of
  deprecating the REST API, and will be
  adding equivalent support to the Graph
  API for this method. You should
  continue to use this method until we
  announce support in the Graph API.

Hope this points you in the right direction.

This tutorial might also help: http://thinkdiff.net/facebook/graph-api-javascript-base-facebook-connect-tutorial/

Body:
    <fb:like-box href="<?php echo $detail['Post_FB'] ;?>" width="292" height="100" show_faces="false" stream="false" header="false"></fb:like-box>

    <fb:like href="http://design-pro.co.cc/appleworld/post.php?id=<?php echo $id?>" send="false" width="450" show_faces="true" font=""></fb:like>

Body:
Use this as your starting point for reference:  http://developers.facebook.com/docs/reference/javascript/FB.init/

First thing to notice is how FB.init() call is wrapped in:

window.fbAsyncInit = function() {
  ...
};

You are already setting 'status' to true in your init call, so you should be able to subscribe to an event which will return the status value, which tells you the user's login status.

Check out:  http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/

Your FB.Event.subscribe(...) call should also be inside the same window.fbAsyncInit() call.

Once you verify that user is logged in, you can check for fan status.  You still have to use the old REST API, since Facebook hasn't ported this over to Graph API:  http://developers.facebook.com/docs/reference/rest/pages.isFan/

Please note: We are in the process of
  deprecating the REST API, and will be
  adding equivalent support to the Graph
  API for this method. You should
  continue to use this method until we
  announce support in the Graph API.

Hope this points you in the right direction.

This tutorial might also help: http://thinkdiff.net/facebook/graph-api-javascript-base-facebook-connect-tutorial/


答:
```<code>$str = '[{"id_piesa":"8","cantitate_piesa":"12","garantie_piesa":false},{"id_piesa":"30","cantitate_piesa":1,"garantie_piesa":true}]';
$jsonArr = json_decode( $str ,true);
var_dump($jsonArr);
</code>```

Title: convert php string to json object


问:
animate an element to fullscreen with css
How do I animate a  to expand to fit the screen upon clicking. I do not want to give a position in the initial state. Div should be able to be used dynamically within the screen.

```<code>.box {
  width: 80px;
  height: 80px;
  background: red;
  cursor: pointer;
  transition: 1s ease-in-out;
}

.fullscreen {
  width: 100vw;
  height: 100vh;
  position: absolute;
  top:0;
  left:0;
  background: red;
  transition: 1s ease-in-out;
}
</code>```

Codepen demo of my code

答:
In order to animate the left and top you'll need an initial value, which you don't have. You can add them upon click and then set the new values by changing the class.

Note that I added the new values in the style so we also need to add !important to the class rule so it will override the inline style.

function expand(){
  // get the element
  var box = document.getElementsByClassName("box")[0];

  // set top and left properties
  box.style.setProperty("left", box.offsetLeft + "px");
  box.style.setProperty("top", box.offsetTop + "px");
  box.style.setProperty("position", "absolute");

  // now change the class for the animation will work
  box.className = "fullscreen";
}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.box {
  width: 80px;
  height: 80px;
  background: red;
  cursor: pointer;
  transition: 1s ease-in-out;
  margin: 0 auto;
  margin-top: 100px;
}

.fullscreen {
  width: 100vw;
  height: 100vh;
  position: absolute;
  top: 0 !important;
  left: 0 !important;
  background: red;
  transition: 1s ease-in-out;
}</code>```

```

Body:
How do I animate a  to expand to fit the screen upon clicking. I do not want to give a position in the initial state. Div should be able to be used dynamically within the screen.

.box {
  width: 80px;
  height: 80px;
  background: red;
  cursor: pointer;
  transition: 1s ease-in-out;
}

.fullscreen {
  width: 100vw;
  height: 100vh;
  position: absolute;
  top:0;
  left:0;
  background: red;
  transition: 1s ease-in-out;
}

Codepen demo of my code

Body:
In order to animate the left and top you'll need an initial value, which you don't have. You can add them upon click and then set the new values by changing the class.

Note that I added the new values in the style so we also need to add !important to the class rule so it will override the inline style.

function expand(){
  // get the element
  var box = document.getElementsByClassName("box")[0];

  // set top and left properties
  box.style.setProperty("left", box.offsetLeft + "px");
  box.style.setProperty("top", box.offsetTop + "px");
  box.style.setProperty("position", "absolute");

  // now change the class for the animation will work
  box.className = "fullscreen";
}

.box {
  width: 80px;
  height: 80px;
  background: red;
  cursor: pointer;
  transition: 1s ease-in-out;
  margin: 0 auto;
  margin-top: 100px;
}

.fullscreen {
  width: 100vw;
  height: 100vh;
  position: absolute;
  top: 0 !important;
  left: 0 !important;
  background: red;
  transition: 1s ease-in-out;
}

<div class="box" onClick="expand()"></div>


问:
Unable to clean recently used items in windows 10
The batch command  del /s /f /q %userprofile%\Recent\*.*  doesn't seem to be working. While  del /s /f /q %USERPROFILE%\appdata\local\temp\*.*  is working fine.

```<code>C:\Users\zzzzz\Recent>del /s /f /q %userprofile%\Recent\*.*
Could Not Find C:\Users\zzzzz\Recent\*.*
</code>```

The path does exist and I can manually cleanup the directory but the same is not working through given command. The command is run as an administrator too but same error.

答:
below %userprofile% is not a regular folder. The real content is here:

```<code>%AppData%\Microsoft\Windows\Recent\
</code>```

where it doesn't have the typical "link" overlay:

Body:
The batch command  del /s /f /q %userprofile%\Recent\*.*  doesn't seem to be working. While  del /s /f /q %USERPROFILE%\appdata\local\temp\*.*  is working fine.

C:\Users\zzzzz\Recent>del /s /f /q %userprofile%\Recent\*.*
Could Not Find C:\Users\zzzzz\Recent\*.*

The path does exist and I can manually cleanup the directory but the same is not working through given command. The command is run as an administrator too but same error.

Body:
below %userprofile% is not a regular folder. The real content is here:

%AppData%\Microsoft\Windows\Recent\

where it doesn't have the typical "link" overlay:


问:
How to reset the port for Java.exe process
I am currently setting BluePrism resourcepc service in my VM and it always shows the status 'Offline'. After the deep analysis, we found that BluePrism using 8181 port which is already being used by the process java.exe.

Hence if i kill the java.exe process through task manager, issue is resolved and everything is working fine however if i restart the VM, then the java process accessing port 8181.

Can someone help me how to change the port for java process?

答:
The BluePrism root folder a program called automate.exe which you can use to set all kinds of preferences for BluePrism. Try to set the port with this:

```<code> automate.exe /resourcepc /port "new port" /public
</code>```

So as an example:

```<code> automate.exe /resourcepc /port 1234 /public
</code>```

Body:
The BluePrism root folder a program called automate.exe which you can use to set all kinds of preferences for BluePrism. Try to set the port with this:

 automate.exe /resourcepc /port "new port" /public

So as an example:

 automate.exe /resourcepc /port 1234 /public