问:
Getting to specific lines of a text file using ANSI functions
in trying to create a function in c which can get to a specific line in a CSV file (similar to getline()). I'm only allowed to use the ANSI 89/99 standard. Here is what i have wrote so far:

```<code>char * getline(FILE * fi,size_t line_length,size_t line_number)
{

size_t i;
char * aux_string;
char * p;
if (fi==NULL)
    return NULL;

if ((aux_string = malloc(line_length*sizeof(char)))==NULL)
    return NULL;

i=0;
while(fgets(aux_string,line_length,fi)!=NULL||feof(fi)!=0)
 {

    if (i==line_number)
    {

        if ((p=strchr(aux_string,'\n'))!=NULL)
        {
            *p='\0';
        }

        return aux_string;
    }
    i++;

 }
return NULL;
}
</code>```

This works fairly ok for a single call to getline(). However, if the function is called like in the example below:

```<code>puts(getline(file_a,MAX_LENGTH,0));
puts(getline(file_a,MAX_LENGTH,0));
</code>```

It outputs the line in the file immediately below, as well as the desired line.
How can I avoid this? What could be causing this? Thanks.

答:
FILE* remembers position inside the file where you ended. So the second time you call fread the file has already read the first line, so you start reading from the second line. You need to fseek(fi, 0, SEEK_SET) rewind the file to the beginning.

```<code>char * getline(FILE * fi,size_t line_length,size_t line_number)
{
    if (fseek(fi, 0, SEEK_SET) != 0) {
          // handle error
     }
     // rest of your function
</code>```

Notes:

rewind is equivalent to fseek(.., 0, SEEK_SET), but offers no error handling (weii, except ferror that is).

puts(getline(file_a,MAX_LENGTH,0)); leaks memory allocated inside getline. You should char *pnt = getline(...); puts(pnt); free(pnt) always remember to pick out the trash.

The feof(fi)!=0 condition from inside the while loop looks redundant. If the file has no more lines, the fgets will tell you about it.

I would advise to rename the function to some mygetline or such, not to confuse others. The function getline is already a POSIX function that's been around for very long.

Body:
in trying to create a function in c which can get to a specific line in a CSV file (similar to getline()). I'm only allowed to use the ANSI 89/99 standard. Here is what i have wrote so far:

char * getline(FILE * fi,size_t line_length,size_t line_number)
{

size_t i;
char * aux_string;
char * p;
if (fi==NULL)
    return NULL;

if ((aux_string = malloc(line_length*sizeof(char)))==NULL)
    return NULL;

i=0;
while(fgets(aux_string,line_length,fi)!=NULL||feof(fi)!=0)
 {

    if (i==line_number)
    {

        if ((p=strchr(aux_string,'\n'))!=NULL)
        {
            *p='\0';
        }

        return aux_string;
    }
    i++;

 }
return NULL;
}

This works fairly ok for a single call to getline(). However, if the function is called like in the example below:

puts(getline(file_a,MAX_LENGTH,0));
puts(getline(file_a,MAX_LENGTH,0));

It outputs the line in the file immediately below, as well as the desired line.
How can I avoid this? What could be causing this? Thanks.

Body:
FILE* remembers position inside the file where you ended. So the second time you call fread the file has already read the first line, so you start reading from the second line. You need to fseek(fi, 0, SEEK_SET) rewind the file to the beginning.

char * getline(FILE * fi,size_t line_length,size_t line_number)
{
    if (fseek(fi, 0, SEEK_SET) != 0) {
          // handle error
     }
     // rest of your function

Notes:

rewind is equivalent to fseek(.., 0, SEEK_SET), but offers no error handling (weii, except ferror that is).

puts(getline(file_a,MAX_LENGTH,0)); leaks memory allocated inside getline. You should char *pnt = getline(...); puts(pnt); free(pnt) always remember to pick out the trash.

The feof(fi)!=0 condition from inside the while loop looks redundant. If the file has no more lines, the fgets will tell you about it.

I would advise to rename the function to some mygetline or such, not to confuse others. The function getline is already a POSIX function that's been around for very long.


来源: stackexchange

问:
Android: Long press of button to save sound (Soundboard)
I have put together a basic soundboard using Android Studio. Please be warned; I am new to Android app development.

I have a series of buttons that I have managed to get to play some .mp3 sounds that I have placed in the Raw folder and mentioned in my MainActivity.java file.

Albeit, I would like the ability to be able to long press on the buttons to save the associated sound to the storage of the phone.

Does anybody have any idea how I could go about this please?

Many thanks, Billy.

```<code>import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaPlayer;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    MediaPlayer mysound1;
    MediaPlayer mysound2;
    MediaPlayer mysound3;
    MediaPlayer mysound4;
    MediaPlayer mysound5;
    MediaPlayer mysound6;
    MediaPlayer mysound7;
    MediaPlayer mysound8;
    MediaPlayer mysound9;
    MediaPlayer mysound10;
    MediaPlayer mysound11;
    MediaPlayer mysound12;
    MediaPlayer mysound13;
    MediaPlayer mysound14;
    MediaPlayer mysound15;
    MediaPlayer mysound16;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mysound1 = MediaPlayer.create(this, R.raw.nickingbentcoppers);
        mysound2 = MediaPlayer.create(this, R.raw.bentcoppers);
        mysound3 = MediaPlayer.create(this, R.raw.bentcoppers2);
        mysound4 = MediaPlayer.create(this, R.raw.bentcoppers3);
        mysound5 = MediaPlayer.create(this, R.raw.twentyfirstcentury);
        mysound6 = MediaPlayer.create(this, R.raw.imdoingmine);
        mysound7 = MediaPlayer.create(this, R.raw.illgoafterhim);
        mysound8 = MediaPlayer.create(this, R.raw.iamcalm);
        mysound9 = MediaPlayer.create(this, R.raw.likethebattle);
        mysound10 = MediaPlayer.create(this, R.raw.thatsright);
        mysound11 = MediaPlayer.create(this, R.raw.seenenough);
        mysound12 = MediaPlayer.create(this, R.raw.jesusmary);
        mysound13 = MediaPlayer.create(this, R.raw.changepage);
        mysound14 = MediaPlayer.create(this, R.raw.opendialog);
        mysound15 = MediaPlayer.create(this, R.raw.yes);
        mysound16 = MediaPlayer.create(this, R.raw.no);

    }

    public void sound1(View view) {
        mysound1.start();
    }

    public void sound2(View view) {
        mysound2.start();
    }

    public void sound3(View view) {
        mysound3.start();
    }

    public void sound4(View view) {
        mysound4.start();
    }

    public void sound5(View view) {
        mysound5.start();
    }

    public void sound6(View view) {
        mysound6.start();
    }

    public void sound7(View view) {
        mysound7.start();
    }

    public void sound8(View view) {
        mysound8.start();
    }

    public void sound9(View view) {
        mysound9.start();
    }

    public void sound10(View view) {
        mysound10.start();
    }

    public void sound11(View view) {
        mysound11.start();
    }

    public void sound12(View view) {
        mysound12.start();
    }

    public void sound13(View view) {
        mysound13.start();
    }

    public void sound14(View view) {
        mysound14.start();
    }

    public void sound15(View view) {
        mysound15.start();
    }

    public void sound16(View view) {
        mysound16.start();
    }

    @Override
    public void onBackPressed() {

        mysound14.start();

        new AlertDialog.Builder(this)

                .setMessage("Are you sure you want to exit, feller?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        mysound15.start();

                        ActivityCompat.finishAffinity(MainActivity.this);

                        System.exit(0);
                    }
                })

                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        mysound16.start();
                    }
                })

                .show();

    }

    public void gotopage1(View v) {

        mysound13.start();
        finish();

        Intent myIntent = new Intent(getBaseContext(), MainActivity.class);
        startActivity(myIntent);

    }

    public void gotopage2(View v) {

        mysound13.start();

        Intent myIntent = new Intent(getBaseContext(), SecondActivity.class);
        startActivity(myIntent);

    }

}```

```

答:
I have tried to apply what you have posted, but I have probably gone wrong somewhere.

I have been trying to save the sound file to internal storage (as I don't have External Memory). When I long press on the button, the message I have put in pops up to say that the file has saved (so far to the directory of the app), but I don't think that it actually saves there at all.

Can you take a look at my code please and see where I have gone wrong. Thanks for helping this noob out, I do really appreciate people's help!

''''@Override

```<code>protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_second);

    Button a;

    a = findViewById(R.id.button11);

    a.setOnLongClickListener(new View.OnLongClickListener() {
        public boolean onLongClick(View arg0) {

            String path = getFilesDir().getAbsolutePath();

            try {
                copyRAWtoPhone(R.raw.nickingbentcoppers, path);
            } catch (IOException e) {
                e.printStackTrace();
            }

            Toast.makeText(SecondActivity.this, "Saved to " + getFilesDir(), Toast.LENGTH_SHORT).show();

            return true;
                               }

        private void copyRAWtoPhone(int nickingbentcoppers, String path) throws IOException {

            InputStream in = getResources().openRawResource(nickingbentcoppers);
            FileOutputStream out = new FileOutputStream(path);
            byte[] buff = new byte[1024];
            int read = 0;
            try {
                while ((read = in.read(buff)) > 0) {
                    out.write(buff, 0, read);
                }
            } finally {
                in.close();
                out.close();
            }

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

ContentLicense: CC BY-SA 4.0

Body:
I have put together a basic soundboard using Android Studio. Please be warned; I am new to Android app development.

I have a series of buttons that I have managed to get to play some .mp3 sounds that I have placed in the Raw folder and mentioned in my MainActivity.java file.

Albeit, I would like the ability to be able to long press on the buttons to save the associated sound to the storage of the phone.

Does anybody have any idea how I could go about this please?

Many thanks, Billy.

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaPlayer;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    MediaPlayer mysound1;
    MediaPlayer mysound2;
    MediaPlayer mysound3;
    MediaPlayer mysound4;
    MediaPlayer mysound5;
    MediaPlayer mysound6;
    MediaPlayer mysound7;
    MediaPlayer mysound8;
    MediaPlayer mysound9;
    MediaPlayer mysound10;
    MediaPlayer mysound11;
    MediaPlayer mysound12;
    MediaPlayer mysound13;
    MediaPlayer mysound14;
    MediaPlayer mysound15;
    MediaPlayer mysound16;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mysound1 = MediaPlayer.create(this, R.raw.nickingbentcoppers);
        mysound2 = MediaPlayer.create(this, R.raw.bentcoppers);
        mysound3 = MediaPlayer.create(this, R.raw.bentcoppers2);
        mysound4 = MediaPlayer.create(this, R.raw.bentcoppers3);
        mysound5 = MediaPlayer.create(this, R.raw.twentyfirstcentury);
        mysound6 = MediaPlayer.create(this, R.raw.imdoingmine);
        mysound7 = MediaPlayer.create(this, R.raw.illgoafterhim);
        mysound8 = MediaPlayer.create(this, R.raw.iamcalm);
        mysound9 = MediaPlayer.create(this, R.raw.likethebattle);
        mysound10 = MediaPlayer.create(this, R.raw.thatsright);
        mysound11 = MediaPlayer.create(this, R.raw.seenenough);
        mysound12 = MediaPlayer.create(this, R.raw.jesusmary);
        mysound13 = MediaPlayer.create(this, R.raw.changepage);
        mysound14 = MediaPlayer.create(this, R.raw.opendialog);
        mysound15 = MediaPlayer.create(this, R.raw.yes);
        mysound16 = MediaPlayer.create(this, R.raw.no);

    }

    public void sound1(View view) {
        mysound1.start();
    }

    public void sound2(View view) {
        mysound2.start();
    }

    public void sound3(View view) {
        mysound3.start();
    }

    public void sound4(View view) {
        mysound4.start();
    }

    public void sound5(View view) {
        mysound5.start();
    }

    public void sound6(View view) {
        mysound6.start();
    }

    public void sound7(View view) {
        mysound7.start();
    }

    public void sound8(View view) {
        mysound8.start();
    }

    public void sound9(View view) {
        mysound9.start();
    }

    public void sound10(View view) {
        mysound10.start();
    }

    public void sound11(View view) {
        mysound11.start();
    }

    public void sound12(View view) {
        mysound12.start();
    }

    public void sound13(View view) {
        mysound13.start();
    }

    public void sound14(View view) {
        mysound14.start();
    }

    public void sound15(View view) {
        mysound15.start();
    }

    public void sound16(View view) {
        mysound16.start();
    }

    @Override
    public void onBackPressed() {

        mysound14.start();

        new AlertDialog.Builder(this)

                .setMessage("Are you sure you want to exit, feller?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        mysound15.start();

                        ActivityCompat.finishAffinity(MainActivity.this);

                        System.exit(0);
                    }
                })

                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        mysound16.start();
                    }
                })

                .show();

    }

    public void gotopage1(View v) {

        mysound13.start();
        finish();

        Intent myIntent = new Intent(getBaseContext(), MainActivity.class);
        startActivity(myIntent);

    }

    public void gotopage2(View v) {

        mysound13.start();

        Intent myIntent = new Intent(getBaseContext(), SecondActivity.class);
        startActivity(myIntent);

    }

}```

Body:
I have tried to apply what you have posted, but I have probably gone wrong somewhere.

I have been trying to save the sound file to internal storage (as I don't have External Memory). When I long press on the button, the message I have put in pops up to say that the file has saved (so far to the directory of the app), but I don't think that it actually saves there at all.

Can you take a look at my code please and see where I have gone wrong. Thanks for helping this noob out, I do really appreciate people's help!

''''@Override

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_second);

    Button a;

    a = findViewById(R.id.button11);

    a.setOnLongClickListener(new View.OnLongClickListener() {
        public boolean onLongClick(View arg0) {

            String path = getFilesDir().getAbsolutePath();

            try {
                copyRAWtoPhone(R.raw.nickingbentcoppers, path);
            } catch (IOException e) {
                e.printStackTrace();
            }

            Toast.makeText(SecondActivity.this, "Saved to " + getFilesDir(), Toast.LENGTH_SHORT).show();

            return true;
                               }

        private void copyRAWtoPhone(int nickingbentcoppers, String path) throws IOException {

            InputStream in = getResources().openRawResource(nickingbentcoppers);
            FileOutputStream out = new FileOutputStream(path);
            byte[] buff = new byte[1024];
            int read = 0;
            try {
                while ((read = in.read(buff)) > 0) {
                    out.write(buff, 0, read);
                }
            } finally {
                in.close();
                out.close();
            }

        }
    }); ''''


问:
How to get a data from an URL
An API like http://www.yourWebService.com/PIP.jsp?request=aaa&param=2

Lets consider the above API gives an JSON value. I use the below coding to get that JSON:

```<code>NSURL *url =[NSURL URLWithString:@"http://www.yourWebService.com/PIP.jsp?request=aaa&param=2"];

NSString *resultedString=[[NSString alloc] initWithContentsOfURL:url];
</code>```

It returns the JSON to the resultedString variable. It is somewhat small amount of Data.
If that API has large amount of data like in 100's of KB's then whether this coding will work fine, or It will crash?

答:
Many APIs like this generally limit the responses - for example, the twitter API will not return more than 1500 results.

http://dev.twitter.com/doc/get/search

ContentLicense: CC BY-SA 3.0

Title: How to get a data from an URL

Body:
An API like http://www.yourWebService.com/PIP.jsp?request=aaa&param=2

Lets consider the above API gives an JSON value. I use the below coding to get that JSON:

NSURL *url =[NSURL URLWithString:@"http://www.yourWebService.com/PIP.jsp?request=aaa&param=2"];

NSString *resultedString=[[NSString alloc] initWithContentsOfURL:url];

It returns the JSON to the resultedString variable. It is somewhat small amount of Data.
If that API has large amount of data like in 100's of KB's then whether this coding will work fine, or It will crash?

OwnerDisplayName: shelman


问:
How can i use forEach for Json Array in javascript
Hi Everyove i have a json array GelenDeger is like

```<code>>GelenDeger
{Localizations: null, Languages: null, AgencyModels: null, GetCitiesModel: {…}, GetCountyModel: null, …}
AgencyAddress: null
GetCitiesModel: {IL_KOD: "35", IL_AD: null, ULKE_KOD: null}
GetCountyModel: null
HtmlResult: ""
M_ACENTE: (4) [{…}, {…}, {…}, {…}]
countryCode: 1234
</code>```

and I can get when I click the button

GelenDeger.M_ACENTE[0].ADRES_TEXT

and

GelenDeger.M_ACENTE[0].ACENTE_AD

but I need a loop and without having to use indexes like [0] or [1] or [2] but I don't know how can to do this. Can you help me on this. Thanks.

My js code :

```<code>function jsFiltreleme(GelenDeger) {
                    $("#myDiv").append(
                        "<div style='border-style:ridge;'>adress : <strong>" + GelenDeger.M_ACENTE[0].ADRES_TEXT + "</strong><br>" +
                        "name : <strong>" + GelenDeger.M_ACENTE[0].ACENTE_AD+ "</strong></div>"
                    );
                }
</code>```

My html code :

```<code><li class="none buttonBox">
    <input id="register" type="submit" value="Search">
</li>
<div id="myDiv"></div>
</code>```

BTW my JSON array can be changeable like M_ACENTE: (10) [{…}, {…}, {…}, {…}]

答: simply make function and pass parameter or argument what you say to like or you can use ES6 function so simply type function parameter name and after that give '=>' then give '.' and what object you stored in your array give name and append your little handy dandy tag thats it not that complicated</p>

Body:
Hi Everyove i have a json array GelenDeger is like

>GelenDeger
{Localizations: null, Languages: null, AgencyModels: null, GetCitiesModel: {…}, GetCountyModel: null, …}
AgencyAddress: null
GetCitiesModel: {IL_KOD: "35", IL_AD: null, ULKE_KOD: null}
GetCountyModel: null
HtmlResult: ""
M_ACENTE: (4) [{…}, {…}, {…}, {…}]
countryCode: 1234

and I can get when I click the button

GelenDeger.M_ACENTE[0].ADRES_TEXT

and

GelenDeger.M_ACENTE[0].ACENTE_AD

but I need a loop and without having to use indexes like [0] or [1] or [2] but I don't know how can to do this. Can you help me on this. Thanks.

My js code :

function jsFiltreleme(GelenDeger) {
                    $("#myDiv").append(
                        "
adress : " + GelenDeger.M_ACENTE[0].ADRES_TEXT + "
" +
                        "name : " + GelenDeger.M_ACENTE[0].ACENTE_AD+ "
"
                    );
                }

My html code :

    <input id="register" type="submit" value="Search">

BTW my JSON array can be changeable like M_ACENTE: (10) [{…}, {…}, {…}, {…}]


问:
Copying a range from one sheet to a specific range in another sheet
The data from the form response sheet "EFS" needs to be copied into the "QE" sheet. The range for the destination sheet does not start in Column A Row1, instead, it should start in Column C of row 3. As this is an active form when a new entry is made that entry needs to be copied to the last row on the destination sheet "QE"  This is what I have so far. I am getting an error,

The number of rows in the data does not match the number of rows in the range. The data has 26751 but the range has 20. (line 15, file "QETaskList")

I've tried to change the range but I get other errors.

```<code>function CopyGradesToQETaskList() {

var sss = SpreadsheetApp.openById("1PK-nMvqIoXaL1nrYPRIWr72I5IQ3wd9sjeztMtR9J1M");
var ss = sss.getSheetByName('EFS');

var lastRowSource = ss.getLastRow();
var source = sss.getRange("A2:p2" + lastRowSource);
values = source.getValues();

var TargetSource = SpreadsheetApp.getActiveSpreadsheet();
var TargetSheet = TargetSource.getSheetByName('QE');
var last_row = TargetSheet.getLastRow();
TargetSheet.insertRowAfter(last_row)
var tsRange = TargetSheet.getRange("C2:R2"+last_row);
tsRange.setValues(values);

}
</code>```

答:
Try this:</p>

```<code>function CopyGradesToQETaskList() {
  var ss=SpreadsheetApp.openById("SSID");
  var sh=ss.getSheetByName('EFS');
  var src=sh.getRange(sh.getLastRow(),1,1,16);
  var vA=src.getValues();
  var tss=SpreadsheetApp.getActive();
  var tsh=tss.getSheetByName('QE');
  var trg=tsh.getRange(tsh.getLastRow()+1,3,1,16);
  trg.setValues(vA);
}
</code>```

Body:
The data from the form response sheet "EFS" needs to be copied into the "QE" sheet. The range for the destination sheet does not start in Column A Row1, instead, it should start in Column C of row 3. As this is an active form when a new entry is made that entry needs to be copied to the last row on the destination sheet "QE"  This is what I have so far. I am getting an error,

The number of rows in the data does not match the number of rows in the range. The data has 26751 but the range has 20. (line 15, file "QETaskList")

I've tried to change the range but I get other errors.

function CopyGradesToQETaskList() {

var sss = SpreadsheetApp.openById("1PK-nMvqIoXaL1nrYPRIWr72I5IQ3wd9sjeztMtR9J1M");
var ss = sss.getSheetByName('EFS');

var lastRowSource = ss.getLastRow();
var source = sss.getRange("A2:p2" + lastRowSource);
values = source.getValues();

var TargetSource = SpreadsheetApp.getActiveSpreadsheet();
var TargetSheet = TargetSource.getSheetByName('QE');
var last_row = TargetSheet.getLastRow();
TargetSheet.insertRowAfter(last_row)
var tsRange = TargetSheet.getRange("C2:R2"+last_row);
tsRange.setValues(values);

}

Body:
Try this:

function CopyGradesToQETaskList() {
  var ss=SpreadsheetApp.openById("SSID");
  var sh=ss.getSheetByName('EFS');
  var src=sh.getRange(sh.getLastRow(),1,1,16);
  var vA=src.getValues();
  var tss=SpreadsheetApp.getActive();
  var tsh=tss.getSheetByName('QE');
  var trg=tsh.getRange(tsh.getLastRow()+1,3,1,16);
  trg.setValues(vA);
}


问:
Observability: can we filter by tags then aggregate on prometheus or any metrics backend server
For example, I call Redis server with following command:

```<code>SET key "value"
</code>```

After running, I want to track those 2 information at the same time:

statistic of all write operators (so tag should be SET)

statistic of all specific operators (so tag should be SET and key)

So I will create views for tracking metrics. There are 2 ways I can think:

Single view with tag "SET" and key. and later hopefully I can filter by "SET" or by "SET" and by key. (1)

Creating 2 views. First view only has tag "SET" and second view will have tags "SET" and key. So each view for each query. (2)

I prefer (1) because it is more elegant and I don't need to create too many views. My question is: If I do on (1), can it works on metric backend server ? (i.e: Prometheus). Or metric backend server doesn't support filter by tag and aggregation, so I must create separate views ?

Thanks

答:
Prometheus enables you to browse metrics by a specific tag and aggregate them.

I recommend Prometheus documentation on aggregation and on tags (which in Prometheus are called 'labels').

If you are asking about 'views' in something like Grafana, then they are easily configurable and you can set the filtering with variables for example.

Body:
For example, I call Redis server with following command:

SET key "value"

After running, I want to track those 2 information at the same time:

statistic of all write operators (so tag should be SET)

statistic of all specific operators (so tag should be SET and key)

So I will create views for tracking metrics. There are 2 ways I can think:

Single view with tag "SET" and key. and later hopefully I can filter by "SET" or by "SET" and by key. (1)

Creating 2 views. First view only has tag "SET" and second view will have tags "SET" and key. So each view for each query. (2)

I prefer (1) because it is more elegant and I don't need to create too many views. My question is: If I do on (1), can it works on metric backend server ? (i.e: Prometheus). Or metric backend server doesn't support filter by tag and aggregation, so I must create separate views ?

Thanks


问:
worst case complexity improvement of Quick sort without converting it to mergsort
Can the worst case time complexity of quick sort be changed from O(n2) to O(nlogn) by modifying it (without converting it to mergsort)?

答:
Normally, worst case is avoided by switching to heapsort if the number of recursions or partition splits becomes too large, since heapsort is also in place.

https://en.wikipedia.org/wiki/Introsort

The other way to avoid worst case behavior is to use median of medians, although it's slower.

https://en.wikipedia.org/wiki/Median_of_medians

As mentioned in the article, it can be a hybrid quicksort that switches to median of medians when the level of recursion becomes excessive.

https://en.wikipedia.org/wiki/Introselect


问:
Evaluate postfix using a stack in C++
```<code>#include <iostream>
#include <sstream>
#include <stack>
#include <limits>
#include <string>
using namespace std;

int main()
{
    string input;
    cout << "Enter a postfix expression: " << endl;
    getline(cin, input);

    int operand1, operand2, result,number;
    stack<char>operation;

    stringstream temp;

    int i=0;
    while (i < input.length())
    {
        if (isdigit(input[i]))
        {
            operation.push(input[i]);
        }
        else
        {
            operand2 = operation.top();
            temp << operation.top();
            operation.pop();

            operand1 = operation.top();
            temp << operation.top();
            operation.pop();

            switch(operand1,operand2)
            {
                case '+': result=operand1 + operand2;
                break;

                case '-': result=operand1 - operand2;
                break;

                case '*': result=operand1 * operand2;
                break;

                case '/': result=operand1 / operand2;
                break;
            }
            operation.push(result);
        }
        i++;
    }
    cout << "The result is: "<<temp.str()<<endl;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    return 0;
}
</code>```

I've changed the code and managed to obtain the "pop" value, but the operation didn't work.

答:
Update response to code changes

I can confirm you changed the code, but not in a good way.

The code mostly has all the flaws it already had, and a few more.

What good is that you now combine the operands into a stringstream?

You now switch on (operand1,operand2)...

both are uninitialized

(operand1,operand2) means basically (operand2) in this context (sequence operator)

your branch labels are ... operators (+-/*)

you now print a final result which is the concatenation of all digits in the input (if you ever reach the end of the program without crashing)?

Among the things that were wrong before, and should still be fixed

the mental model of a stack calculator.

numbers (integers) are the operands (so 9, 100, 39829 are valid operands)

+-/* are the operators (operators operate on the operands)

the stack is an operand stack, not an operator stack (operators do not have to be remembered, because they are evaluated immediately)

numbers consist of 1 or more digits (0123456789) in a row; so you'd need to read several characters before you can 'push' a number on the operand stack

the operators +-/* take 2 operands, so any operation on a stack of size<2 is an error (you need to check that or the program will crash while trying to access memory that doesn't exist or contains rubbish).

That should be enough to get you started.

Two things I do think are positive:

You program compiles. +1 for you actually using a compiler there :)

You took the repeated operation.push(result) out of the switch so it isn't duplicated anymore. +1 for coding style ...

I hope you can gather from this that the code isn't very good (to put it mildly), and I really think some basic exercises are in order:
 1. write a simple for loop that prints numbers 1 to 10 to the console
 1. write a simple while loop that prints words entered by the user
 1. use a simple loop to print all numbers between 1 and 50 that are multiples of 7
 1. use a switch statement to print "yes" whenever the user enters one of the letters a, b, k, or z
 2. make a simple loop that only prints the input character for every character that follows the identical (so 'abccdefgghijkllmabcdd' would become 'cgld')
 1. use the same loop but this time print every word that immediately follows the identical word (so "no, no, you should not pop, pop, but push, pop" becomes "no pop")

That should give you a feel for how things really work, without the guesswork or the 'magic factor'.

Oh, and don't forget, I implemented the whole thing for you below. I don't suggest you blindly copy it (it will be rather obvious to your teacher :)) but it is there for you to take a peek if you want to know, what I mean with all my words above :)

You are pushing loose digits, not parsed numbers

In line 31 you pop a possibly empty stack (resulting in segfault unless you use the debug-mode STL flags on your compiler)

Just for fun:

```<code>#include <iostream>
#include <stack>
#include <vector>
#include <limits>
#include <string>
#include <stdexcept>
#include <iterator>
#include <fstream>

using namespace std;

    template <class T>
        static void dumpstack(std::stack<T> s/*byval!*/)
    {
        std::vector<T> vec;

        while (!s.empty())
        {
            vec.push_back(s.top());
            s.pop();
        }

        std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));
    }

    class calc
    {
        private:
            std::stack<int> _stack;
            int _accum;
            bool _pending;

            void store(/*store accumulator if pending*/)
            {
                if (_pending)
                {
                    _stack.push(_accum);
                    _pending = false;
                    _accum = 0;
                }
            }

        public:
            calc() : _accum(0), _pending(false)
            {
            }

            void handle(char ch)
            {
                switch (ch)
                {
                    case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
                        _pending = true;
                        _accum *= 10;
                        _accum += ch-'0';
                        break;
                    case '+': case '-': case '/': case '*':
                        {
                            store();
                            if (_stack.size()<2)
                                throw std::runtime_error("stack underflow");

                            int op2 = _stack.top(); _stack.pop();
                            int op1 = _stack.top(); _stack.pop();
                            switch (ch)
                            {
                                case '+': _stack.push(op1 + op2); break;
                                case '-': _stack.push(op1 - op2); break;
                                case '/': _stack.push(op1 / op2); break;
                                case '*': _stack.push(op1 * op2); break;
                            }

                            // feedback to console:
                            std::cout << std::endl << "(evaluated: " << op1 << " " << ch << " " << op2 << " == " << _stack.top() << ")" << std::endl;
                            dump();
                        }
                        break;
                    default:
                        store(); // todo: notify of ignored characters in input?
                }
            }

            void dump() const
            {
                dumpstack(_stack);
            }
    };

    int main()
    {
        cout << "Enter postfix expressions: " << endl;
        calc instance;

        try
        {
            while (std::cin.good())
            {
                char ch = std::cin.get();
                instance.handle(ch);
            }
            std::cout << "Final result: ";
            instance.dump();

            return 0;
        } catch(const std::exception& e)
        {
            std::cerr << "E: " << e.what() << std::endl;
            return 255;
        }

    }
</code>```

Test output: (note that you can continue with the remaining, partially evaluted, stack after pressing carriage return)

```<code>Enter postfix expressions:
1 2 3 +4 * - / 1333 *

(evaluated: 2 + 3 == 5)
1 5
(evaluated: 5 * 4 == 20)
1 20
(evaluated: 1 - 20 == -19)
-19 E: stack underflow
</code>```

Title: Evaluate postfix using a stack in C++

Body:
#include <iostream>
#include <sstream>
#include <stack>
#include <limits>
#include <string>
using namespace std;

int main()
{
    string input;
    cout << "Enter a postfix expression: " << endl;
    getline(cin, input);

    int operand1, operand2, result,number;
    stack<char>operation;

    stringstream temp;

    int i=0;
    while (i < input.length())
    {
        if (isdigit(input[i]))
        {
            operation.push(input[i]);
        }
        else
        {
            operand2 = operation.top();
            temp << operation.top();
            operation.pop();

            operand1 = operation.top();
            temp << operation.top();
            operation.pop();

            switch(operand1,operand2)
            {
                case '+': result=operand1 + operand2;
                break;

                case '-': result=operand1 - operand2;
                break;

                case '*': result=operand1 * operand2;
                break;

                case '/': result=operand1 / operand2;
                break;
            }
            operation.push(result);
        }
        i++;
    }
    cout << "The result is: "<<temp.str()<<endl;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    return 0;
}

I've changed the code and managed to obtain the "pop" value, but the operation didn't work.

Body:
Update response to code changes

I can confirm you changed the code, but not in a good way.

The code mostly has all the flaws it already had, and a few more.

What good is that you now combine the operands into a stringstream?

You now switch on (operand1,operand2)...

both are uninitialized

(operand1,operand2) means basically (operand2) in this context (sequence operator)

your branch labels are ... operators (+-/*)

you now print a final result which is the concatenation of all digits in the input (if you ever reach the end of the program without crashing)?

Among the things that were wrong before, and should still be fixed

the mental model of a stack calculator.

numbers (integers) are the operands (so 9, 100, 39829 are valid operands)

+-/* are the operators (operators operate on the operands)

the stack is an operand stack, not an operator stack (operators do not have to be remembered, because they are evaluated immediately)

numbers consist of 1 or more digits (0123456789) in a row; so you'd need to read several characters before you can 'push' a number on the operand stack

the operators +-/* take 2 operands, so any operation on a stack of size<2 is an error (you need to check that or the program will crash while trying to access memory that doesn't exist or contains rubbish).

That should be enough to get you started.

Two things I do think are positive:

You program compiles. +1 for you actually using a compiler there :)

You took the repeated operation.push(result) out of the switch so it isn't duplicated anymore. +1 for coding style ...

I hope you can gather from this that the code isn't very good (to put it mildly), and I really think some basic exercises are in order:
 1. write a simple for loop that prints numbers 1 to 10 to the console
 1. write a simple while loop that prints words entered by the user
 1. use a simple loop to print all numbers between 1 and 50 that are multiples of 7
 1. use a switch statement to print "yes" whenever the user enters one of the letters a, b, k, or z
 2. make a simple loop that only prints the input character for every character that follows the identical (so 'abccdefgghijkllmabcdd' would become 'cgld')
 1. use the same loop but this time print every word that immediately follows the identical word (so "no, no, you should not pop, pop, but push, pop" becomes "no pop")

That should give you a feel for how things really work, without the guesswork or the 'magic factor'.

Oh, and don't forget, I implemented the whole thing for you below. I don't suggest you blindly copy it (it will be rather obvious to your teacher :)) but it is there for you to take a peek if you want to know, what I mean with all my words above :)

You are pushing loose digits, not parsed numbers

In line 31 you pop a possibly empty stack (resulting in segfault unless you use the debug-mode STL flags on your compiler)

Just for fun:

#include <iostream>
#include <stack>
#include <vector>
#include <limits>
#include <string>
#include <stdexcept>
#include <iterator>
#include <fstream>

using namespace std;

    template <class T>
        static void dumpstack(std::stack<T> s/*byval!*/)
    {
        std::vector<T> vec;

        while (!s.empty())
        {
            vec.push_back(s.top());
            s.pop();
        }

        std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));
    }

    class calc
    {
        private:
            std::stack<int> _stack;
            int _accum;
            bool _pending;

            void store(/*store accumulator if pending*/)
            {
                if (_pending)
                {
                    _stack.push(_accum);
                    _pending = false;
                    _accum = 0;
                }
            }

        public:
            calc() : _accum(0), _pending(false)
            {
            }

            void handle(char ch)
            {
                switch (ch)
                {
                    case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
                        _pending = true;
                        _accum *= 10;
                        _accum += ch-'0';
                        break;
                    case '+': case '-': case '/': case '*':
                        {
                            store();
                            if (_stack.size()<2)
                                throw std::runtime_error("stack underflow");

                            int op2 = _stack.top(); _stack.pop();
                            int op1 = _stack.top(); _stack.pop();
                            switch (ch)
                            {
                                case '+': _stack.push(op1 + op2); break;
                                case '-': _stack.push(op1 - op2); break;
                                case '/': _stack.push(op1 / op2); break;
                                case '*': _stack.push(op1 * op2); break;
                            }

                            // feedback to console:
                            std::cout << std::endl << "(evaluated: " << op1 << " " << ch << " " << op2 << " == " << _stack.top() << ")" << std::endl;
                            dump();
                        }
                        break;
                    default:
                        store(); // todo: notify of ignored characters in input?
                }
            }

            void dump() const
            {
                dumpstack(_stack);
            }
    };

    int main()
    {
        cout << "Enter postfix expressions: " << endl;
        calc instance;

        try
        {
            while (std::cin.good())
            {
                char ch = std::cin.get();
                instance.handle(ch);
            }
            std::cout << "Final result: ";
            instance.dump();

            return 0;
        } catch(const std::exception& e)
        {
            std::cerr << "E: " << e.what() << std::endl;
            return 255;
        }

    }

Test output: (note that you can continue with the remaining, partially evaluted, stack after pressing carriage return)

Enter postfix expressions:
1 2 3 +4 * - / 1333 *

(evaluated: 2 + 3 == 5)
1 5
(evaluated: 5 * 4 == 20)
1 20
(evaluated: 1 - 20 == -19)
-19 E: stack underflow


问:
How to change the OS on an existing Service Fabric cluster?
I'm trying to change my VMSS from:

```<code>    "imageReference": {
      "publisher": "MicrosoftWindowsServer",
      "offer": "WindowsServer",
      "sku": "2016-Datacenter-with-Containers",
      "version": "latest"
    }
</code>```

To:

```<code>    "imageReference": {
      "publisher": "MicrosoftWindowsServer",
      "offer": "WindowsServerSemiAnnual",
      "sku": "Datacenter-Core-1803-with-Containers-smalldisk",
      "version": "latest"
    }
</code>```

The first thing I tried was:

Update-AzureRmVmss -ResourceGroupName "DevServiceFabric" -VMScaleSetName "HTTP" -ImageReferenceSku Datacenter-Core-1803-with-Containers-smalldisk -ImageReferenceOffer WindowsServerSemiAnnual

Which gives me the error:

Update-AzureRmVmss : Changing property 'imageReference.offer' is not allowed.
  ErrorCode: PropertyChangeNotAllowed

This is confirmed in the docs; you can only set the offer when the scaleset is created.

Next I tried Add-AzureRmServiceFabricNodeType to add a new node type, thinking I could just delete the old one after.  However, this command doesn't seem to allow you to set the OS image.  You can only set the VM SKU (In other words, all VMs on your cluster have to have the same OS).

Is there a way to change this without deleting the entire cluster and starting from scratch?

答:
Edit If you can stay within the current publisher+offer, you can switch the OS very easily by simply changing the SKU. See the answer by Mike.

If you really need to change the offer, you can do this:

Upgrade the size and operating system of the primary node type VMs.

Be aware that you need to consider a lot of things like your availablility level.  The cluster will also be unavailable from the outside for a time.

Shortened drastically:

add a second scale set with your desired OS to the primary node type

disable the old scale set, then remove it

switch over the load balancer

# Variables.
$groupname = "sfupgradetestgroup"
$clusterloc="southcentralus"
$subscriptionID="<your subscription ID>"

# sign in to your Azure account and select your subscription
Login-AzAccount -SubscriptionId $subscriptionID

# Create a new resource group for your deployment and give it a name and a location.
New-AzResourceGroup -Name $groupname -Location $clusterloc

# Deploy the two node type cluster.
New-AzResourceGroupDeployment -ResourceGroupName $groupname -TemplateParameterFile "C:\temp\cluster\Deploy-2NodeTypes-2ScaleSets.parameters.json" `
    -TemplateFile "C:\temp\cluster\Deploy-2NodeTypes-2ScaleSets.json" -Verbose

# Connect to the cluster and check the cluster health.
$ClusterName= "sfupgradetest.southcentralus.cloudapp.azure.com:19000"
$thumb="F361720F4BD5449F6F083DDE99DC51A86985B25B"

Connect-ServiceFabricCluster -ConnectionEndpoint $ClusterName -KeepAliveIntervalInSec 10 `
    -X509Credential `
    -ServerCertThumbprint $thumb  `
    -FindType FindByThumbprint `
    -FindValue $thumb `
    -StoreLocation CurrentUser `
    -StoreName My

Get-ServiceFabricClusterHealth

# Deploy a new scale set into the primary node type.  Create a new load balancer and public IP address for the new scale set.
New-AzResourceGroupDeployment -ResourceGroupName $groupname -TemplateParameterFile "C:\temp\cluster\Deploy-2NodeTypes-3ScaleSets.parameters.json" `
    -TemplateFile "C:\temp\cluster\Deploy-2NodeTypes-3ScaleSets.json" -Verbose

# Check the cluster health again. All 15 nodes should be healthy.
Get-ServiceFabricClusterHealth

# Disable the nodes in the original scale set.
$nodeNames = @("_NTvm1_0","_NTvm1_1","_NTvm1_2","_NTvm1_3","_NTvm1_4")

Write-Host "Disabling nodes..."
foreach($name in $nodeNames){
    Disable-ServiceFabricNode -NodeName $name -Intent RemoveNode -Force
}

Write-Host "Checking node status..."
foreach($name in $nodeNames){

    $state = Get-ServiceFabricNode -NodeName $name

    $loopTimeout = 50

    do{
        Start-Sleep 5
        $loopTimeout -= 1
        $state = Get-ServiceFabricNode -NodeName $name
        Write-Host "$name state: " $state.NodeDeactivationInfo.Status
    }

    while (($state.NodeDeactivationInfo.Status -ne "Completed") -and ($loopTimeout -ne 0))

    if ($state.NodeStatus -ne [System.Fabric.Query.NodeStatus]::Disabled)
    {
        Write-Error "$name node deactivation failed with state" $state.NodeStatus
        exit
    }
}

# Remove the scale set
$scaleSetName="NTvm1"
Remove-AzVmss -ResourceGroupName $groupname -VMScaleSetName $scaleSetName -Force
Write-Host "Removed scale set $scaleSetName"

$lbname="LB-sfupgradetest-NTvm1"
$oldPublicIpName="PublicIP-LB-FE-0"
$newPublicIpName="PublicIP-LB-FE-2"

# Store DNS settings of public IP address related to old Primary NodeType into variable
$oldprimaryPublicIP = Get-AzPublicIpAddress -Name $oldPublicIpName  -ResourceGroupName $groupname

$primaryDNSName = $oldprimaryPublicIP.DnsSettings.DomainNameLabel

$primaryDNSFqdn = $oldprimaryPublicIP.DnsSettings.Fqdn

# Remove Load Balancer related to old Primary NodeType. This will cause a brief period of downtime for the cluster
Remove-AzLoadBalancer -Name $lbname -ResourceGroupName $groupname -Force

# Remove the old public IP
Remove-AzPublicIpAddress -Name $oldPublicIpName -ResourceGroupName $groupname -Force

# Replace DNS settings of Public IP address related to new Primary Node Type with DNS settings of Public IP address related to old Primary Node Type
$PublicIP = Get-AzPublicIpAddress -Name $newPublicIpName  -ResourceGroupName $groupname
$PublicIP.DnsSettings.DomainNameLabel = $primaryDNSName
$PublicIP.DnsSettings.Fqdn = $primaryDNSFqdn
Set-AzPublicIpAddress -PublicIpAddress $PublicIP

# Check the cluster health
Get-ServiceFabricClusterHealth

# Remove node state for the deleted nodes.
foreach($name in $nodeNames){
    # Remove the node from the cluster
    Remove-ServiceFabricNodeState -NodeName $name -TimeoutSec 300 -Force
    Write-Host "Removed node state for node $name"
}

```

Body:
I'm trying to change my VMSS from:

    "imageReference": {
      "publisher": "MicrosoftWindowsServer",
      "offer": "WindowsServer",
      "sku": "2016-Datacenter-with-Containers",
      "version": "latest"
    }

To:

    "imageReference": {
      "publisher": "MicrosoftWindowsServer",
      "offer": "WindowsServerSemiAnnual",
      "sku": "Datacenter-Core-1803-with-Containers-smalldisk",
      "version": "latest"
    }

The first thing I tried was:

Update-AzureRmVmss -ResourceGroupName "DevServiceFabric" -VMScaleSetName "HTTP" -ImageReferenceSku Datacenter-Core-1803-with-Containers-smalldisk -ImageReferenceOffer WindowsServerSemiAnnual

Which gives me the error:

Update-AzureRmVmss : Changing property 'imageReference.offer' is not allowed.
  ErrorCode: PropertyChangeNotAllowed

This is confirmed in the docs; you can only set the offer when the scaleset is created.

Next I tried Add-AzureRmServiceFabricNodeType to add a new node type, thinking I could just delete the old one after.  However, this command doesn't seem to allow you to set the OS image.  You can only set the VM SKU (In other words, all VMs on your cluster have to have the same OS).

Is there a way to change this without deleting the entire cluster and starting from scratch?


问:
Problem with: TypeError: Cannot read property 'map' of undefined
I was goin through some tutorial, and i got into an issue with The error 'cannot read property 'map' of undefined'.Please help me with the following code.

TypeError: Cannot read property 'map' of undefined
TodoItems.render
C:/Users/hp/Desktop/todo_list/src/TodoItems.js:10

```<code> 7 |
   8 |    render(){
   9 |        var todoEntries = this.props.entries;
> 10 |        var listItems = todoEntries.map(this.createTasks);
     | ^  11 |
  12 |        return (
  13 |            <ul className="theList">
View compiled
▶ 23 stack frames were collapsed.

import React, { Component } from "react";

class TodoItems extends Component{
    createTasks(item) {
        return <li key={item.key}>{item.text}</li>
    }

    render(){
        var todoEntries = this.props.entries;
        var listItems = todoEntries.map(this.createTasks);

        return (
            <ul className="theList">
                {listItems}
            </ul>
        );
    }
}

export default TodoItems;

and the TodoList file code is:
render() {
        return (
            <div className="todoListMain">
            <div className="header">
                <form onSubmit={this.addItem}>
                    <input ref={(a) => this._inputElement = a}
                         placeholder="enter task">
                    </input>
                    <button type="submit">add</button>
                </form>
            </div>
            <TodoItems entries={this.state.items}/>
        </div>
        );
    }
}

export default TodoList;
</code>```

答:
You're trying to pass this.state.items as entries, but it seems that it's not an array but undefined.

You could just make it an array by default by doing something like the following -

```<code>class MyComponent extends Component {
  state = {
    items: []
  }
}
</code>```

Body:
I was goin through some tutorial, and i got into an issue with The error 'cannot read property 'map' of undefined'.Please help me with the following code.

TypeError: Cannot read property 'map' of undefined
TodoItems.render
C:/Users/hp/Desktop/todo_list/src/TodoItems.js:10

 7 |
   8 |    render(){
   9 |        var todoEntries = this.props.entries;
> 10 |        var listItems = todoEntries.map(this.createTasks);
     | ^  11 |
  12 |        return (
  13 |

View compiled
▶ 23 stack frames were collapsed.

import React, { Component } from "react";

class TodoItems extends Component{
    createTasks(item) {
        return
{item.text}

    }

    render(){
        var todoEntries = this.props.entries;
        var listItems = todoEntries.map(this.createTasks);

        return (

                {listItems}

        );
    }
}

export default TodoItems;

and the TodoList file code is:
render() {
        return (

                <form onSubmit={this.addItem}>
                    <input ref={(a) => this._inputElement = a}
                         placeholder="enter task">
                    </input>
                    <button type="submit">add</button>
                </form>

            <TodoItems entries={this.state.items}/>

        );
    }
}

export default TodoList;

Body:
You're trying to pass this.state.items as entries, but it seems that it's not an array but undefined.

You could just make it an array by default by doing something like the following -

class MyComponent extends Component {
  state = {
    items: []
  }
}


问:
Why after continue; execution further function code is executed?
I have a functions like:

```<code>public function checkItems(int $id, array $items)
{
    $this->validateItems($id, $items);

    foreach($items as $item) {
        ...// further code
    }

    return $items;
}

private function validateItems(int $id, array $items)
{
    foreach ($items as $item) {
        if (!is_int($item->itemId)) {
            continue;
        }
    }
}
</code>```

The thing is that when I write this if:

```<code>if (!is_int($item->itemId)) {
    continue;
}
</code>```

inside the function checkItems() (not moved to another one) it works perfectly, because ..//further code doesn't get executed if the item is wrong. It basically returns $items if the information is not valid.

But when I move my validation into an another function, despite continue statements, at the end it loops again and the further code is executed.

Could someone tell me how to properly solve this with a validation move to another function?

答:
continue only works in the loop it is used in - the foreach ($items as $item)

if you want to use it in the validated function you either need to pass back some kind of array of valid options - or use validate in the for loop of ...// further code

something like:

```<code>public function checkItems(int $id, array $items)
{
    foreach($items as $item) {
        if ($this->validateItems($id, $item) {
            ...// further code
        }
    }

    return $items;
}

private function validateItems(int $id, array $item)
{
    //$id is never used?
    if (!is_int($item->itemId)) {
        return false;
    }
    return true;
}
</code>```

Body:
I have a functions like:

public function checkItems(int $id, array $items)
{
    $this->validateItems($id, $items);

    foreach($items as $item) {
        ...// further code
    }

    return $items;
}

private function validateItems(int $id, array $items)
{
    foreach ($items as $item) {
        if (!is_int($item->itemId)) {
            continue;
        }
    }
}

The thing is that when I write this if:

if (!is_int($item->itemId)) {
    continue;
}

inside the function checkItems() (not moved to another one) it works perfectly, because ..//further code doesn't get executed if the item is wrong. It basically returns $items if the information is not valid.

But when I move my validation into an another function, despite continue statements, at the end it loops again and the further code is executed.

Could someone tell me how to properly solve this with a validation move to another function?

Body:
continue only works in the loop it is used in - the foreach ($items as $item)

if you want to use it in the validated function you either need to pass back some kind of array of valid options - or use validate in the for loop of ...// further code

something like:

public function checkItems(int $id, array $items)
{
    foreach($items as $item) {
        if ($this->validateItems($id, $item) {
            ...// further code
        }
    }

    return $items;
}

private function validateItems(int $id, array $item)
{
    //$id is never used?
    if (!is_int($item->itemId)) {
        return false;
    }
    return true;
}


问:
display files and dir in linux as graphic mode
how to display the directories and files in graphic way

I forget the command in linux but some linux command can displayed from root directories the recursive directories like this

root

```<code>|
</code>```

sbin  etc   var ...

```<code>|   |     |

dir dir dir dir ........

|   |   |   |
|   |   |   |
</code>```

答: I would recommend that you use the tree program. It's distributed along with the popular GNU/Linux distros and is much more durable than a shell pipeline.</p>

Body:
how to display the directories and files in graphic way

I forget the command in linux but some linux command can displayed from root directories the recursive directories like this

root

|

sbin  etc   var ...

|   |     |

dir dir dir dir ........

|   |   |   |
|   |   |   |


问:
How in the JQ UI Datepicker to show always the date in the input field
I implemented in my app a JQ Datepicker calendar on its default version, but I cannot understand how to show in the input field always the date the today date to be precise. Now when I open the page where is the datepicker, the input field is blank until I select the date I need.
What I would like to see is that the date is always visible on the input filed if that possible.

My Datepicker:

```<code>//Date Picker
  $("*[data-behavior~=shipping-date-input]").datepicker({
    onSelect: function() {
      digest = cargoflux.generateUUID();
      cargoflux.resetCalculatedFields();

      clearTimeout(timeOut);
      timeOut = setTimeout(function() {
        if (cargoflux.validInput()) {
          cargoflux.resetCalculatedFields();
          cargoflux.getAvailableCarrierProducts();
        }
      }, 1500);
    },
    showOtherMonths: true,
    selectOtherMonths: true,
    changeMonth: true,
    changeYear: true,
    altField: "#recorded-at-alt",
    dateFormat: "yy-mm-dd",
    minDate: "-1Y",
    maxDate: "+1Y"

  });
</code>```

Screenshot of what I mean as you see the input is blank in his initial state:

答:
To populate the value of the text field, you can use $.datepicker.formatDate( format, date, options ) feature. here is an example:

$(function() {
  var dtFt = "yy-mm-dd";
  $("#datepicker").datepicker({
    onSelect: function() {
      /*digest = cargoflux.generateUUID();
      cargoflux.resetCalculatedFields();

      clearTimeout(timeOut);
      timeOut = setTimeout(function() {
        if (cargoflux.validInput()) {
          cargoflux.resetCalculatedFields();
          cargoflux.getAvailableCarrierProducts();
        }
      }, 1500);
      */
    },
    showOtherMonths: true,
    selectOtherMonths: true,
    changeMonth: true,
    changeYear: true,
    //altField: "#recorded-at-alt",
    dateFormat: dtFt,
    minDate: "-1Y",
    maxDate: "+1Y"
  }).val($.datepicker.formatDate(dtFt, new Date()));
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<p>Date: <input type="text" id="datepicker"></p></code>```

As you can see, we populate the text field value, $("#datepicker").val();.

Hope that helps.

Body:
I implemented in my app a JQ Datepicker calendar on its default version, but I cannot understand how to show in the input field always the date the today date to be precise. Now when I open the page where is the datepicker, the input field is blank until I select the date I need.
What I would like to see is that the date is always visible on the input filed if that possible.

My Datepicker:

//Date Picker
  $("*[data-behavior~=shipping-date-input]").datepicker({
    onSelect: function() {
      digest = cargoflux.generateUUID();
      cargoflux.resetCalculatedFields();

      clearTimeout(timeOut);
      timeOut = setTimeout(function() {
        if (cargoflux.validInput()) {
          cargoflux.resetCalculatedFields();
          cargoflux.getAvailableCarrierProducts();
        }
      }, 1500);
    },
    showOtherMonths: true,
    selectOtherMonths: true,
    changeMonth: true,
    changeYear: true,
    altField: "#recorded-at-alt",
    dateFormat: "yy-mm-dd",
    minDate: "-1Y",
    maxDate: "+1Y"

  });

Screenshot of what I mean as you see the input is blank in his initial state:

Body:
To populate the value of the text field, you can use $.datepicker.formatDate( format, date, options ) feature. here is an example:

$(function() {
  var dtFt = "yy-mm-dd";
  $("#datepicker").datepicker({
    onSelect: function() {
      /*digest = cargoflux.generateUUID();
      cargoflux.resetCalculatedFields();

      clearTimeout(timeOut);
      timeOut = setTimeout(function() {
        if (cargoflux.validInput()) {
          cargoflux.resetCalculatedFields();
          cargoflux.getAvailableCarrierProducts();
        }
      }, 1500);
      */
    },
    showOtherMonths: true,
    selectOtherMonths: true,
    changeMonth: true,
    changeYear: true,
    //altField: "#recorded-at-alt",
    dateFormat: dtFt,
    minDate: "-1Y",
    maxDate: "+1Y"
  }).val($.datepicker.formatDate(dtFt, new Date()));
});

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<p>Date: <input type="text" id="datepicker"></p>

As you can see, we populate the text field value, $("#datepicker").val();.

Hope that helps.


问:
Django Datetime.strptime displays unwanted time
I am trying to inject a date into my django html template.

I have the string "2019-05-26" and I am trying to convert it to datetime format for django to display as "May 26, 2019" on the webpage. The problem is that it displays "May 26, 2019 Midnight" instead of just "May 26 2019". It adds the "Midnight" because of a trailing 00:00 that is added on from the function, How do I remove the trailing "midnight"?

```<code>timestamp = transaction["timestamp"]
data = (timestamp[:10]) if len(timestamp) > 10 else timestamp
print(data)
data2 = datetime.strptime(data, '%Y-%m-%d')
</code>```

print("timestamp:", transaction["timestamp"])

timestamp: 2019-05-26T20:55:44.993368+00:00

答:
```<code>data = datetime.strptime("2019-05-26", '%Y-%m-%d')
print(data)
</code>```

Body:
I am trying to inject a date into my django html template.

I have the string "2019-05-26" and I am trying to convert it to datetime format for django to display as "May 26, 2019" on the webpage. The problem is that it displays "May 26, 2019 Midnight" instead of just "May 26 2019". It adds the "Midnight" because of a trailing 00:00 that is added on from the function, How do I remove the trailing "midnight"?

timestamp = transaction["timestamp"]
data = (timestamp[:10]) if len(timestamp) > 10 else timestamp
print(data)
data2 = datetime.strptime(data, '%Y-%m-%d')

print("timestamp:", transaction["timestamp"])

timestamp: 2019-05-26T20:55:44.993368+00:00


问:
Scrapy xpath is not working perfectly, return empty data
I am trying to scrape the book title price and author from vitalsource.com.

I successfully extracted the title, author and ISBN information but I can't get the price from the webpage.

I don't understand why I can't get the data since they are all on the same webpage.

I googled and tried many hours and now it's 4:43 am here, I am tired and despair, please help me.

please check the image for more detail. The xpath is working fine in the blue area, but not working in the red area

```<code>import scrapy
from VitalSource.items import VitalsourceItem
from scrapy.spiders import SitemapSpider

class VsSpider(scrapy.Spider):
    name = 'VS'
    allowed_domains = ['VitalSource.com']
    start_urls = ['https://www.vitalsource.com/products/cengage-unlimited-1st-edition-instant-access-1-cengage-unlimited-v9780357700006']

    def parse(self, response):
        item = VitalsourceItem()
        item['Ebook_Title'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/h1/text()').extract()[1].strip()
        item['Ebook_Author'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/p/text()').extract()[0].strip()
        item['Ebook_ISBN'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/ul/li[2]/h2/text()').extract()[0].strip()
        item['Ebook_Price'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/div/span[1]/span[3]/span[2]/text()')
        print(item)
        return item
</code>```

Result Information:

```<code>{
 'Ebook_Author': 'by: Cengage Unlimited',
 'Ebook_ISBN': 'Print ISBN: \n 9780357700037, 0357700031',
 'Ebook_Price': [],
 'Ebook_Title': 'Cengage Unlimited, 1st Edition [Instant Access], 1 term (4 months)'
}
</code>```

答:
I am not sure if you want to strictly use xpath, but I will post how it's done both with xpath and css selector:

css:

```<code>response.css('.u-pull-sixth--right+ span::text').get().strip()
</code>```

xpath:

```<code>response.xpath('/html[1]/body[1]/div[2]/main[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/span[1]').xpath('//span[@class]//span[2]/text()').get().strip()
</code>```

Result:

```<code>{'Ebook_Price': '119.99'}
</code>```

Body:
I am trying to scrape the book title price and author from vitalsource.com.

I successfully extracted the title, author and ISBN information but I can't get the price from the webpage.

I don't understand why I can't get the data since they are all on the same webpage.

I googled and tried many hours and now it's 4:43 am here, I am tired and despair, please help me.

please check the image for more detail. The xpath is working fine in the blue area, but not working in the red area

import scrapy
from VitalSource.items import VitalsourceItem
from scrapy.spiders import SitemapSpider

class VsSpider(scrapy.Spider):
    name = 'VS'
    allowed_domains = ['VitalSource.com']
    start_urls = ['https://www.vitalsource.com/products/cengage-unlimited-1st-edition-instant-access-1-cengage-unlimited-v9780357700006']

    def parse(self, response):
        item = VitalsourceItem()
        item['Ebook_Title'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/h1/text()').extract()[1].strip()
        item['Ebook_Author'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/p/text()').extract()[0].strip()
        item['Ebook_ISBN'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/ul/li[2]/h2/text()').extract()[0].strip()
        item['Ebook_Price'] = response.xpath('//*[@id="content"]/div[1]/div[1]/div[1]/div/div[2]/div/span[1]/span[3]/span[2]/text()')
        print(item)
        return item

Result Information:

{
 'Ebook_Author': 'by: Cengage Unlimited',
 'Ebook_ISBN': 'Print ISBN: \n 9780357700037, 0357700031',
 'Ebook_Price': [],
 'Ebook_Title': 'Cengage Unlimited, 1st Edition [Instant Access], 1 term (4 months)'
}

Body:
I am not sure if you want to strictly use xpath, but I will post how it's done both with xpath and css selector:

css:

response.css('.u-pull-sixth--right+ span::text').get().strip()

xpath:

response.xpath('/html[1]/body[1]/div[2]/main[1]/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/span[1]').xpath('//span[@class]//span[2]/text()').get().strip()

Result:

{'Ebook_Price': '119.99'}


问:
How to create a grade table data from excel data to html display?
I need to create a data table of score, in with it with show score of participant, taking data from excel to html display with an ID input and only show individual participant score with the correct ID. Any Idea for starter, or any site that provide a online form of sure kind.
Like this</p>

答: Is it static data or does it change programatically? For static files I've had success converting to CSV and using this tool to output JSON which I use to generate the HTML.</p>


答:
datetime.strptime() returns a datetime object. You just need the date, so call the date() method.

```<code>data2 = datetime.strptime(data, '%Y-%m-%d').date()
</code>```

Title: Django Datetime.strptime displays unwanted time

Body:
datetime.strptime() returns a datetime object. You just need the date, so call the date() method.

data2 = datetime.strptime(data, '%Y-%m-%d').date()


问:
How can I restrict users from accessing other pages by url?
There are 3 users logged in, and each one has their own profile page.
How can I restrict others from accessing other profile pages by url? </p>

答:
Before outputting the contents of the profile page, check if the id of the currently logged in user is the same as the id of the owner of the page.

If it does not match show a "permission denied" page instead of the profile.


问:
Spring RestController response mixed with PrometheusMeterRegistry error message
Env: Springboot-2.0.7.RELEASE (embedded tomcat-8.5.35), JDK-1.8.0_181, micrometer-registry-prometheus-1.0.8

Desc: using @Timed on controller method and WebMvcMetricsFilter with custom WebMvcTagsProvider.

Demo project: https://github.com/kenix/resp-mix

If PrometheusMeterRegistry already created a meter with a set of tags, it won't create another meter with same name and a set of different tags. It throws IllegalArgumentException with the aforementioned reason. This happens after the normal processing of request, which is successful (response now has the converted JSON). The exception isn't caught in spring's WebMvcMetricsFilter (i.e. catch the exception in its catch-clause. BTW, ControllerAdvice doesn't help), but is caught by tomcat's StandardHostValve, which renders his own error message (it cannot know where this exception is from) into response too. This leads to an illegal JSON as the rendered result.

Question 1: should WebMvcMetricsFilter catch and handle this Exception thrown by PrometheusMeterRegistry and not throw it further up?

Question 2: have seen that exception in filter chain before hitting the actual processing is handled as expected. What about exception after a successful actual processing? Any references?

To trigger this case:

curl -i localhost:8080/hi/foo/there

curl -i localhost:8080/hi/blah/there

答:
Question 1: No, WebMvcTagsProvider handles HTTP Exceptions.
Question 2: Try using ControllerAdvice and catch the IllegalArgumentException there. </p>


问:
Calculate value using previously-calculated value (from the same column) and value from another column in a Pandas Dataframe
After hours trying to learn how to do this, I'm reaching out to the community.

I'm starting with the following:

```<code>                perf
date
2018-06-01  0.012923
2018-06-02  0.039364
2018-06-03  0.042805
2018-06-04 -0.033214
2018-06-05 -0.021745
</code>```

Need to calculate a cumulative percentage change on a new column but need to ensure the calculation uses 100 as the starting value. So I prepend a single row with the 100:

```<code>                perf  pct_change
date
2018-05-31       NaN       100.0
2018-06-01  0.012923         NaN
2018-06-02  0.039364         NaN
2018-06-03  0.042805         NaN
2018-06-04 -0.033214         NaN
</code>```

What I need to get is this:

```<code>                perf  pct_change
date
2018-05-31       NaN       100.0
2018-06-01  0.012923    101.2923
2018-06-02  0.039364 105.2795701
2018-06-03  0.042805 109.7860621
2018-06-04 -0.033214 106.1396278
</code>```

The formula being something like pct_change = previous_days_pct_change * ( 1 + perf )

I tried a few different approaches including a for ... in loop with no success.

```<code># INCOMPLETE/DOES NOT WORK (adding for illustration purposes only)
for index, row in performance.iterrows():
    curr = performance.loc[index, 'perf']
    pidx = index + pd.DateOffset(-1)
    prev = performance.iloc[[pidx], 'pct_change']
    performance.loc[index, 'pct_change'] = prev * ( 1 + curr )
</code>```

I also tried:

```<code>performance['pct_change'] = performance['pct_change'].shift() * ( 1 + performance['perf'] )
</code>```

Which yields:

```<code>                perf  pct_change
date
2018-05-31       NaN         NaN
2018-06-01  0.012923  101.292251
2018-06-02  0.039364         NaN
2018-06-03  0.042805         NaN
2018-06-04 -0.033214         NaN
</code>```

But that only gives me the one value.

I suspect there is already a much simpler way to do what I'm trying to do but I'm just not finding it. Any help would be appreciated. Very easy to do in a spreadsheet but I want to learn how to do this in Pandas.

Thank you

答:
Using cumprod:

```<code>df['pct_change'] = (df['perf']+1).cumprod() * 100
</code>```

achieves what you actually want:

```<code>pct_change_0 = (perf_0 + 1) * 100
pct_change_1 = pct_change_0 * (perf_1 + 1) = (perf_0 + 1) * (perf_1 + 1) *  100
pct_change_2 = pct_change_1 * (perf_2 + 1) = (perf_0 + 1) * (perf_1 + 1) * (perf_2 + 1) * 100
...
</code>```

So you are actually computing the cumulative product of perf values (or to be more accurate perf + 1 values).

Body:
After hours trying to learn how to do this, I'm reaching out to the community.

I'm starting with the following:

                perf
date
2018-06-01  0.012923
2018-06-02  0.039364
2018-06-03  0.042805
2018-06-04 -0.033214
2018-06-05 -0.021745

Need to calculate a cumulative percentage change on a new column but need to ensure the calculation uses 100 as the starting value. So I prepend a single row with the 100:

                perf  pct_change
date
2018-05-31       NaN       100.0
2018-06-01  0.012923         NaN
2018-06-02  0.039364         NaN
2018-06-03  0.042805         NaN
2018-06-04 -0.033214         NaN

What I need to get is this:

                perf  pct_change
date
2018-05-31       NaN       100.0
2018-06-01  0.012923    101.2923
2018-06-02  0.039364 105.2795701
2018-06-03  0.042805 109.7860621
2018-06-04 -0.033214 106.1396278

The formula being something like pct_change = previous_days_pct_change * ( 1 + perf )

I tried a few different approaches including a for ... in loop with no success.

# INCOMPLETE/DOES NOT WORK (adding for illustration purposes only)
for index, row in performance.iterrows():
    curr = performance.loc[index, 'perf']
    pidx = index + pd.DateOffset(-1)
    prev = performance.iloc[[pidx], 'pct_change']
    performance.loc[index, 'pct_change'] = prev * ( 1 + curr )

I also tried:

performance['pct_change'] = performance['pct_change'].shift() * ( 1 + performance['perf'] )

Which yields:

                perf  pct_change
date
2018-05-31       NaN         NaN
2018-06-01  0.012923  101.292251
2018-06-02  0.039364         NaN
2018-06-03  0.042805         NaN
2018-06-04 -0.033214         NaN

But that only gives me the one value.

I suspect there is already a much simpler way to do what I'm trying to do but I'm just not finding it. Any help would be appreciated. Very easy to do in a spreadsheet but I want to learn how to do this in Pandas.

Thank you

Body:
Using cumprod:

df['pct_change'] = (df['perf']+1).cumprod() * 100

achieves what you actually want:

pct_change_0 = (perf_0 + 1) * 100
pct_change_1 = pct_change_0 * (perf_1 + 1) = (perf_0 + 1) * (perf_1 + 1) *  100
pct_change_2 = pct_change_1 * (perf_2 + 1) = (perf_0 + 1) * (perf_1 + 1) * (perf_2 + 1) * 100
...

So you are actually computing the cumulative product of perf values (or to be more accurate perf + 1 values).


问:
How to get an access token from vKontakte (VK) via OAuth2?
I'm trying to get an access token from vKontakte (russian social network) via their OAuth2 API.
This is how I make the call:

```<code>https://oauth.vk.com/authorize?client_id=12345&scope=wall,offline&redirect_uri=https://www.example.com/oauth/vk.php&display=page&v=5.24&response_type=token
</code>```

I'm receiving an access token but if I try to post a message with it, I'm receiving this error:

```<code>//error: Permission to perform this action is denied for non-standalone applications: you should request token using blank.html page.
</code>```

My app is a standalone application - why do I receive the error?

答: That's exactly what it says it is - you cannot use implicit flow for non-standalone application. Instead, you should use authorization code flow, which is more secure for client applications.</p>

Body:
I'm trying to get an access token from vKontakte (russian social network) via their OAuth2 API.
This is how I make the call:

https://oauth.vk.com/authorize?client_id=12345&scope=wall,offline&redirect_uri=https://www.example.com/oauth/vk.php&display=page&v=5.24&response_type=token

I'm receiving an access token but if I try to post a message with it, I'm receiving this error:

//error: Permission to perform this action is denied for non-standalone applications: you should request token using blank.html page.

My app is a standalone application - why do I receive the error?


问:
Index when using OR in query
What is the best way to create index when I have a query like this?

```<code>... WHERE (user_1 = '$user_id' OR user_2 = '$user_id') ...
</code>```

I know that only one index can be used in a query so I can't create two indexes, one for user_1 and one for user_2.

Also could solution for this type of query be used for this query?

```<code>WHERE ((user_1 = '$user_id' AND user_2 = '$friend_id') OR (user_1 = '$friend_id' AND user_2 = '$user_id'))
</code>```

答:
MySQL has a hard time with OR conditions. In theory, there's an index merge optimization that @duskwuff mentions, but in practice, it doesn't kick in when you think it should. Besides, it doesn't give as performance as a single index when it does.

The solution most people use to work around this is to split up the query:

```<code>SELECT ... WHERE user_1 = ?
UNION
SELECT ... WHERE user_2 = ?
</code>```

That way each query will be able to use its own choice for index, without relying on the unreliable index merge feature.

Your second query is optimizable more simply. It's just a tuple comparison. It can be written this way:

```<code>WHERE (user_1, user_2) IN (('$user_id', '$friend_id'), ('$friend_id', '$user_id'))
</code>```

In old versions of MySQL, tuple comparisons would not use an index, but since 5.7.3, it will (see https://dev.mysql.com/doc/refman/5.7/en/row-constructor-optimization.html).

P.S.: Don't interpolate application code variables directly into your SQL expressions. Use query parameters instead.

Title: Index when using OR in query

Body:
What is the best way to create index when I have a query like this?

... WHERE (user_1 = '$user_id' OR user_2 = '$user_id') ...

I know that only one index can be used in a query so I can't create two indexes, one for user_1 and one for user_2.

Also could solution for this type of query be used for this query?

WHERE ((user_1 = '$user_id' AND user_2 = '$friend_id') OR (user_1 = '$friend_id' AND user_2 = '$user_id'))

Body:
MySQL has a hard time with OR conditions. In theory, there's an index merge optimization that @duskwuff mentions, but in practice, it doesn't kick in when you think it should. Besides, it doesn't give as performance as a single index when it does.

The solution most people use to work around this is to split up the query:

SELECT ... WHERE user_1 = ?
UNION
SELECT ... WHERE user_2 = ?

That way each query will be able to use its own choice for index, without relying on the unreliable index merge feature.

Your second query is optimizable more simply. It's just a tuple comparison. It can be written this way:

WHERE (user_1, user_2) IN (('$user_id', '$friend_id'), ('$friend_id', '$user_id'))

In old versions of MySQL, tuple comparisons would not use an index, but since 5.7.3, it will (see https://dev.mysql.com/doc/refman/5.7/en/row-constructor-optimization.html).

P.S.: Don't interpolate application code variables directly into your SQL expressions. Use query parameters instead.


问:
Getting started with SSL
After reading articles about SSL online (a while ago, sources forgotten) - I've come to the conclusion that half of SSL related articles are full of . While the other half seem to suggest that SSL is a must if you're selling stuff on your site.

My question is, after trying to find this out on Google, is How do you actually use SSL, like how do you put it on your site?

I'm not sure why, but I was always under the impression that to make SSL work with your website you just pay for an SSL Certificate and just enter your website's details on your SSL providers site and it just get sets up somehow by the SSL service?

Is there any programming involved?

答:
SSL can work without involving any Certification Authority. So CA are not mandatory.
Of course if you don't use CA your user needs a way to get your certificate off-line (to be sure that no MiTM will be performed on your first connection to the your site).
Otherwise the user can accept the certificate sent back by your web server on the first connection (but this is susceptible to MiTM on the first connection ).

Also, CA doesn't do anything except giving a third-part trust upon your certificate, all implementations issues are up to you.

Title: Getting started with SSL


问:
Can I specify the model (e.g. "video") in the Google Cloud Speech-to-Text api when using the gcloud tool?
Google's speech-to-text service has several possible models to use for transcribing speech to text (standard, video, phone call, etc). Google provides documentation here on using these models when sending requests to their speech-to-text api from Python or via curl. But I am using gcloud ml speech recognize to make requests to that API, and want to be able to specify the model to use. I've read pages and pages of documentation to figure this out, but no luck yet.

My command-line script:

```<code>gcloud ml speech recognize test.wav --language-code=EN --useEnhanced=true
</code>```

I've also tried --model=video instead of --useEnhanced=true.

Google's response:

```<code>ERROR: (gcloud.ml.speech.recognize) unrecognized arguments: --useEnhanced=true

To search the help text of gcloud commands, run:
  gcloud help -- SEARCH_TERMS
</code>```

Please help! Thanks :)

答:
I wasn't able to get it working with the gcloud tool but I was able to do it "manually" with cURL. Follow the docs here: https://cloud.google.com/speech-to-text/docs/quickstart-protocol. Make sure to create a service account with the proper role, download the resulting private key, and run export GOOGLE_APPLICATION_CREDENTIALS=path-to-credentials.json. Then create a JSON file with your request. Mine looked like this:

{
    "config": {
        "languageCode": "en-US",
        "useEnhanced": true,
        "model": "video"
    },
    "audio": {
        "uri": "gs://bucket/audio.flac"
    }
  }
```

Then just execute the cURL command the docs suggest for the recognize endpoint (taking care to change the file name to the JSON you created) and you should be good to go.

Here are the docs for the recognize endpoint: https://cloud.google.com/speech-to-text/docs/reference/rest/v1/speech/recognize. You can click-through to the RecognitionConfig and RecognitionAudio objects to see what you can include in your JSON file.

Body:
Google's speech-to-text service has several possible models to use for transcribing speech to text (standard, video, phone call, etc). Google provides documentation here on using these models when sending requests to their speech-to-text api from Python or via curl. But I am using gcloud ml speech recognize to make requests to that API, and want to be able to specify the model to use. I've read pages and pages of documentation to figure this out, but no luck yet.

My command-line script:

gcloud ml speech recognize test.wav --language-code=EN --useEnhanced=true

I've also tried --model=video instead of --useEnhanced=true.

Google's response:

ERROR: (gcloud.ml.speech.recognize) unrecognized arguments: --useEnhanced=true

To search the help text of gcloud commands, run:
  gcloud help -- SEARCH_TERMS

Please help! Thanks :)

Body:
I wasn't able to get it working with the gcloud tool but I was able to do it "manually" with cURL. Follow the docs here: https://cloud.google.com/speech-to-text/docs/quickstart-protocol. Make sure to create a service account with the proper role, download the resulting private key, and run export GOOGLE_APPLICATION_CREDENTIALS=path-to-credentials.json. Then create a JSON file with your request. Mine looked like this:

{
    "config": {
        "languageCode": "en-US",
        "useEnhanced": true,
        "model": "video"
    },
    "audio": {
        "uri": "gs://bucket/audio.flac"
    }
  }

Then just execute the cURL command the docs suggest for the recognize endpoint (taking care to change the file name to the JSON you created) and you should be good to go.

Here are the docs for the recognize endpoint: https://cloud.google.com/speech-to-text/docs/reference/rest/v1/speech/recognize. You can click-through to the RecognitionConfig and RecognitionAudio objects to see what you can include in your JSON file.


问:
Use Firebase Functions to create JOINs in Firestore queries
According to this answer, Firestore references cannot be used for JOIN-like queries, i.e. for retrieving the referencing document and the referenced document in one database round-trip. This can be a performance issue, since network latency costs apply for each database round-trip.

Network latency is only a problem if you are not close to the datacenter, which means that if you do the join server-side, i.e. in the Google datacenter where Firestore runs, then it should not be a problem.

Can we use Firebase Functions to implement this functionality in a generic manner? I'm thinking of a service, implemented in Firebase Functions, which sits between the client and the database. Most queries are just passed to the database (where, orderBy, limit etc. must still be possible), but there should be an additional populate: true query parameter. If this parameter is present and set to true, then the referenced documents are returned as well.

Maybe it will also be necessary to indicate which documents should be populated.

答:
Sure, sounds like you could give it a try.  You can still expect to pay for all documents read by whatever queries you use, even if you don't return that many to the client.

If you really have a lot of joins to perform, it's typically better to pre-compute the joins in another collection, and have the client query that instead.  Then you have the advantage of the client having a local cache the helps both speed and cost.

But there's nothing stopping you from implementing a function that does this, if that's what you need.


问:
holding movement and dashing by tapping shift
im trying to get my character to dash the direction its currently moving when i tap shift. right now i have to hold shift then tap the direction i want to dash.

ive tried switching up the order, and ive tried changing the code to use a double tap to dash. with no luck so far

```<code>public class Dash : MonoBehaviour
{

private Rigidbody rb;

public float dashSpeed;
private float dashTime;
public float startDashTime;
private int direction;

void Update()
{
    //dash
    if (direction == 0)
    {
        if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.A))
        {
            direction = 1;
        }
        else if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.D))
        {
            direction = 2;
        }
        else if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.W))
        {
            direction = 3;
        }
        else if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.S))
        {
            direction = 4;
        }
</code>```

I want the character to dash to the left. I want to be able to hold down the "A" key to strafe in that direction and tap "Shift" to do a short dash.

if i hold "A" i strafe in the direction but "Shift" does nothing. if i hold "Shift" then tap "A" the character does the dash i expect.

答:
Instead of:

```<code>if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.A))
</code>```

Try:

```<code>if (Input.GetKeyDown(KeyCode.LeftShift) && Input.GetKey(KeyCode.A))
</code>```

Input.GetKeyDown olnly returns true in the first frame the key is pushed, while Input.GetKey returns true every frame you are holding the key

Body:
im trying to get my character to dash the direction its currently moving when i tap shift. right now i have to hold shift then tap the direction i want to dash.

ive tried switching up the order, and ive tried changing the code to use a double tap to dash. with no luck so far

public class Dash : MonoBehaviour
{

private Rigidbody rb;

public float dashSpeed;
private float dashTime;
public float startDashTime;
private int direction;

void Update()
{
    //dash
    if (direction == 0)
    {
        if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.A))
        {
            direction = 1;
        }
        else if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.D))
        {
            direction = 2;
        }
        else if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.W))
        {
            direction = 3;
        }
        else if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.S))
        {
            direction = 4;
        }

I want the character to dash to the left. I want to be able to hold down the "A" key to strafe in that direction and tap "Shift" to do a short dash.

if i hold "A" i strafe in the direction but "Shift" does nothing. if i hold "Shift" then tap "A" the character does the dash i expect.

Body:
Instead of:

if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.A))

Try:

if (Input.GetKeyDown(KeyCode.LeftShift) && Input.GetKey(KeyCode.A))

Input.GetKeyDown olnly returns true in the first frame the key is pushed, while Input.GetKey returns true every frame you are holding the key


问:
Error trying to share CKRecord in Default Zone CloudKit
I'm trying to use the shared Database in CloudKit.

As soon as I try to share a CKRecord, I get the error "Shares cannot exist in the default zone".
I guess it's just a minor error on my side but, I have no clue for what I should look out for.

That's the error I get:

Shares cannot exist in the default zone

Can't share records in the default zone

答:
The docs say:

Sharing is only supported in zones with the
  CKRecordZoneCapabilitySharing capability. The default zone does not
  support sharing.

This means, you have to define your custom zone that allows sharing records.