问:
How to mix two types of navigation in react native
I'm working on an application using React Native. I would like to have a bottom navigation on my application (5.x). After this done, I also would like to let user to navigate on other users profile view.
But, I don't want that this new screen appear on the bottom navigation. I don't know how to do that. Does I need to mix stack navigation and bottom navigation ? How to do that ? </p>

答:
As the react-navigation docs says, it's not a good usage to do nesting navigation, but you can do that in version 5.x of react-navigation, as the others answers says.
Bu if you want to, you can use react-navigation 4.x to do it better, like mixing stack-navigatior with bottom-navigator, as the below pic shows.
Follow the code to do it:

```<code>yarn add react-navigation
</code>```

if you are running a bare react-native project, run this code below

```<code>yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
</code>```

if you are running an expo project, run this:

```<code>expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
</code>```

And then, to finish up the dependencies installations, run:

```<code>yarn add react-navigation-tabs
</code>```

You can keep reading the docs of version 4.x to finish some other details.
The pic below show the structure to nest navigators.

Giving a better explanation, this code will first open the route(screen) name SignIn, and if the prop SignedIn is true, then Dashboard route will open.
Of course is always better to use the newest stable version, as it is 5.x, and follow the doc's tips and advices.
Hope this helps.

Body:
As the react-navigation docs says, it's not a good usage to do nesting navigation, but you can do that in version 5.x of react-navigation, as the others answers says.
Bu if you want to, you can use react-navigation 4.x to do it better, like mixing stack-navigatior with bottom-navigator, as the below pic shows.
Follow the code to do it:

yarn add react-navigation

if you are running a bare react-native project, run this code below

yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

if you are running an expo project, run this:

expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

And then, to finish up the dependencies installations, run:

yarn add react-navigation-tabs

You can keep reading the docs of version 4.x to finish some other details.
The pic below show the structure to nest navigators.

Giving a better explanation, this code will first open the route(screen) name SignIn, and if the prop SignedIn is true, then Dashboard route will open.
Of course is always better to use the newest stable version, as it is 5.x, and follow the doc's tips and advices.
Hope this helps.


来源: stackexchange

问:
Request is missing required authentication credential. Expected OAuth 2 access token
we are trying to add Google Sign option to our project. We have successfully added this option to the site and to the ios application. But encountered difficulties adding to the android application. Using "Configure project" option in this page https://developers.google.com/identity/sign-in/android/start-integrating I specify SHA1 of Andrid debug key (Gradle -> android -> signingReport) and package name (com.my.app). This form gives us WEB type client ID. I downloaded credentials.json and put it in the app folder of the project. I also found an android type client ID with specified SHA1 hash in the Google API Console, but I don't understand where to use it (if we use android type oauth client, we get an error "signInResult:failed code=10", so we should use web type client, and without such android client in the API console we get 12500 error and no token).

Next we added a sample code to get token and pass it to our backend server according to this document https://developers.google.com/identity/sign-in/android/backend-auth.

```<code>private void enterGoogle() {
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .requestIdToken("12345-OurWebTypeClient.apps.googleusercontent.com").build();
        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
        try {
            GoogleSignInAccount account = completedTask.getResult(ApiException.class);

            String accessToken = account.getIdToken();
            authWithGoogleToken(accessToken);

        } catch (ApiException e) {
            // The ApiException status code indicates the detailed failure reason.
            // Please refer to the GoogleSignInStatusCodes class reference for more information.
            Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());

        }
    }

    private void authWithGoogleToken(String accessToken) {
        if (accessToken == null)
            Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
        else
            RetrofitFactory.getInstance().authGoogle(accessToken)
                .enqueue(new retrofit2.Callback<JsonObject>() {
                    @Override
                    public void onResponse(retrofit2.Call<JsonObject> call, retrofit2.Response<JsonObject> response) {
                        try {
                            if (response.isSuccessful() && response.body() != null) {
                                if (!response.body().has("error")) {

                                    Toast.makeText(MainActivity.this, "Success!", Toast.LENGTH_SHORT).show();
                                } else {
                                    Toast.makeText(MainActivity.this, response.body().get("error").getAsString(), Toast.LENGTH_SHORT).show();
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(retrofit2.Call<JsonObject> call, Throwable t) {
                        Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                    }
                });
    }
</code>```

using this code, we get long token which starts from "eyJ". If we change a code little bit to use alternative methods:

```<code>.requestServerAuthCode("12345-OurWebTypeClient.apps.googleusercontent.com").build();
</code>```

and

```<code>String accessToken = completedTask.getResult().getServerAuthCode();
</code>```

we get short token which starts from "4/0". We do not know what a difference between these 2 types of tokens from 2 methods of getting tokens, but on backend server we get one error for both types of tokens:

```<code>{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}
</code>```

We do not have such error for token from iOS SDK for example. Please help to find out what is wrong with implementation of Google Sign In in the Android app?

答:
we solved it using this workaround</p>

```<code>GoogleSignInAccount account = completedTask.getResult(ApiException.class);
            AsyncTask.execute(() -> {
                try {
                    String accessToken = GoogleAuthUtil.getToken(context, account.getAccount(), "oauth2:" + Scopes.PLUS_LOGIN);
                    runOnUiThread(() -> {
                        authWithGoogleToken(accessToken);
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            String accessToken = account.getIdToken();
            authWithGoogleToken(accessToken);
</code>```

ContentLicense: CC BY-SA 4.0

Body:
we are trying to add Google Sign option to our project. We have successfully added this option to the site and to the ios application. But encountered difficulties adding to the android application. Using "Configure project" option in this page https://developers.google.com/identity/sign-in/android/start-integrating I specify SHA1 of Andrid debug key (Gradle -> android -> signingReport) and package name (com.my.app). This form gives us WEB type client ID. I downloaded credentials.json and put it in the app folder of the project. I also found an android type client ID with specified SHA1 hash in the Google API Console, but I don't understand where to use it (if we use android type oauth client, we get an error "signInResult:failed code=10", so we should use web type client, and without such android client in the API console we get 12500 error and no token).

Next we added a sample code to get token and pass it to our backend server according to this document https://developers.google.com/identity/sign-in/android/backend-auth.

private void enterGoogle() {
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .requestIdToken("12345-OurWebTypeClient.apps.googleusercontent.com").build();
        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
        try {
            GoogleSignInAccount account = completedTask.getResult(ApiException.class);

            String accessToken = account.getIdToken();
            authWithGoogleToken(accessToken);

        } catch (ApiException e) {
            // The ApiException status code indicates the detailed failure reason.
            // Please refer to the GoogleSignInStatusCodes class reference for more information.
            Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());

        }
    }

    private void authWithGoogleToken(String accessToken) {
        if (accessToken == null)
            Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
        else
            RetrofitFactory.getInstance().authGoogle(accessToken)
                .enqueue(new retrofit2.Callback<JsonObject>() {
                    @Override
                    public void onResponse(retrofit2.Call<JsonObject> call, retrofit2.Response<JsonObject> response) {
                        try {
                            if (response.isSuccessful() && response.body() != null) {
                                if (!response.body().has("error")) {

                                    Toast.makeText(MainActivity.this, "Success!", Toast.LENGTH_SHORT).show();
                                } else {
                                    Toast.makeText(MainActivity.this, response.body().get("error").getAsString(), Toast.LENGTH_SHORT).show();
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(retrofit2.Call<JsonObject> call, Throwable t) {
                        Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                    }
                });
    }

using this code, we get long token which starts from "eyJ". If we change a code little bit to use alternative methods:

.requestServerAuthCode("12345-OurWebTypeClient.apps.googleusercontent.com").build();

and

String accessToken = completedTask.getResult().getServerAuthCode();

we get short token which starts from "4/0". We do not know what a difference between these 2 types of tokens from 2 methods of getting tokens, but on backend server we get one error for both types of tokens:

{
  "error": {
    "code": 401,
    "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}

We do not have such error for token from iOS SDK for example. Please help to find out what is wrong with implementation of Google Sign In in the Android app?

Body:
we solved it using this workaround

GoogleSignInAccount account = completedTask.getResult(ApiException.class);
            AsyncTask.execute(() -> {
                try {
                    String accessToken = GoogleAuthUtil.getToken(context, account.getAccount(), "oauth2:" + Scopes.PLUS_LOGIN);
                    runOnUiThread(() -> {
                        authWithGoogleToken(accessToken);
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            String accessToken = account.getIdToken();
            authWithGoogleToken(accessToken);


问:
WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 3221225477
I'm new to Robot Framewerk and I am using it with RIDE and I followed some tutorials and that went well till today.

Yesterday everything worked fine and I changed nothing after yesterday. Now I am getting this error when I execute my tests in RIDE:

```<code>WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 3221225477
</code>```

I'm trying to test on Chrome. Check screenshot for other versions of selenium etc.

Using:

```<code>Chrome Versie 83.0.4103.61 (Officiële build) (64-bits)
ChromeDriver 83.0.4103.39
</code>```

Environment:

答:
This error message...

```<code>WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 3221225477
</code>```

...implies that the ChromeDriver unexpectedly exited.

Status code: 3221225477

As per the documentation in Program exit codes Status Code 3221225477 implies Access violation which indicates that the executed program has terminated abnormally or crashed.

As you are using ChromeDriver / Chrome combination there can be numerous reason for this error. A couple of them are as follows:

Due to incorrect ChromeDriver path.

You can find a detailed discussion in WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 127

Due to ChromeDriver / Chrome version mismatch.

You can find a detailed discussion in WebDriverException: Message: Service /content/chromedriver unexpectedly exited. Status code was: -6 with ChromeDriver Google Colab and Selenium

Body:
I'm new to Robot Framewerk and I am using it with RIDE and I followed some tutorials and that went well till today.

Yesterday everything worked fine and I changed nothing after yesterday. Now I am getting this error when I execute my tests in RIDE:

WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 3221225477

I'm trying to test on Chrome. Check screenshot for other versions of selenium etc.

Using:

Chrome Versie 83.0.4103.61 (Officiële build) (64-bits)
ChromeDriver 83.0.4103.39

Environment:

Body:
This error message...

WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 3221225477

...implies that the ChromeDriver unexpectedly exited.

Status code: 3221225477

As per the documentation in Program exit codes Status Code 3221225477 implies Access violation which indicates that the executed program has terminated abnormally or crashed.

As you are using ChromeDriver / Chrome combination there can be numerous reason for this error. A couple of them are as follows:

Due to incorrect ChromeDriver path.

You can find a detailed discussion in WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 127

Due to ChromeDriver / Chrome version mismatch.

You can find a detailed discussion in WebDriverException: Message: Service /content/chromedriver unexpectedly exited. Status code was: -6 with ChromeDriver Google Colab and Selenium


问:
How to fix pgAdmin 4 not importing my csv file?
I have a csv file on my computer that I am trying to import into a postgres DB using pgAdmin 4. I am using the import tool, am able to find the correct csv file in the import/export dialog box, and when I click "Ok" I get a message saying "Import/Export job has been created" and then nothing.

Is there a solution to this? Or is there an alternative way to load the csv file into my tables?

答: I'm having the same issue "Import/Export job created". I thought maybe its a MAC issue. Anyway, my work-around on the COPY is put the file in the applications folder, it's the only folder postgreSQL is able to read (at least in my case) without being a superuser.


问:
Can I make a path like that
Hello guys I a class like that:

```<code>@Path("infected")

public class Resource{

     @GET
    @Path("city/{infected}")
    public Response selectInfectadosCiudad(@PathParam("infected") String nombre){
    ...}
}
</code>```

But when I try to go to .../infected/city/123 for example it gives me a 404, so I suppose that you can't call city/{infected} I mean you cant use city/ before the Pathparam am I correct?

答:
Can you try to add '/' before the path

```<code>@Path("/infected")

public class Resource{

@GET
@Path("/city/{infected}")
public Response selectInfectadosCiudad(@PathParam("infected") String nombre){
...}
}
</code>```

I'm not sure if this will work or not but try it

Title: Can I make a path like that

Body:
Hello guys I a class like that:

@Path("infected")

public class Resource{

     @GET
    @Path("city/{infected}")
    public Response selectInfectadosCiudad(@PathParam("infected") String nombre){
    ...}
}

But when I try to go to .../infected/city/123 for example it gives me a 404, so I suppose that you can't call city/{infected} I mean you cant use city/ before the Pathparam am I correct?

Body:
Can you try to add '/' before the path

@Path("/infected")

public class Resource{

@GET
@Path("/city/{infected}")
public Response selectInfectadosCiudad(@PathParam("infected") String nombre){
...}
}

I'm not sure if this will work or not but try it


问:
CSS: border-color command causing strange shadow when element viewed on mobile device
something strange is happening in my css.

I'm working on a custom view for the Quantity Box on a WooCommerce product page. It renders fine on Chrome Developer tools for both mobile/desktop but when I look on my actual phone I get a strange shadow near the top border above the quantity number.

This is my code

#smntcswcb{
        height:35px;
        width:60px;
        padding: 8px 18px 8px 18px !important;
        border:2px solid !important;
        border-radius: 0px !important;
        color:#333 !important;
        font-size: 15px !important;
        border-color: #e5e5e5 !important;
}
```

<p>When I remove the border color line it goes away, but I would like to keep the gray border without the shadow. Please help.</p>

<p>Edit: </p>

<p>Here is the HTML code for the elements</p>

<pre class="lang-html prettyprint-override"><code><div class="quantity">
    <label class="screen-reader-text" for="smntcswcb">Quantity </label>
    <input class="minus" type="button" value="-">
    <input type="number" id="smntcswcb" step="1" min="1" name="quantity" value="1" title="Qty" class="input-text qty text" inputmode="numeric">
    <input class="plus" type="button" value="+">
</div>
</code>```

Here is the CSS code for class="minus"

.minus{
    background: none;
    text-align: center;
    width:48px !important;
    height:35px;
    padding: 2px 0px 0px 0px !important;
    background-color: #fff !important;
    border:2px solid transparent !important;
    border-radius: 0px !important;
    border-color: #e5e5e5 !important;
    color:#333 !important;
    margin-right: -4px;
    color:#000 !important;
    font-size: 24px !important;
    font-weight:900 !important;
    position: relative;
}
```

<p>Here is the CSS code for the class "plus"</p>

<pre class="lang-css prettyprint-override"><code>.plus{
    height:35px !important;
    width:48px !important;
    padding: 2px 0px 0px 0px !important;
    background-color: #fff !important;
    border:2px solid transparent !important;
    border-radius: 0px !important;
    border-color: #e5e5e5 !important;
    color:#333 !important;
    margin-left: -4px;
    font-size: 24px !important;
    font-weight:900 !important;
}
</code>```

Here is the code for the parent class "quantity". I am using flex to make the items on the same height

.single_variation_wrap .quantity{
    display: flex;
}
```

答:
It must be that your phone's OS UI engine renders the component according to its standards and it ends up adding that shadow, try to force disable the shadow. See last 3 lines of the css selectors:</p>

```<code>#smntcswcb{
    height:35px;
    width:60px;
    padding: 8px 18px 8px 18px !important;
    border:2px solid !important;
    border-radius: 0px !important;
    color:#333 !important;
    font-size: 15px !important;
    border-color: #e5e5e5 !important;

    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;

}
</code>```

Body:
something strange is happening in my css.

I'm working on a custom view for the Quantity Box on a WooCommerce product page. It renders fine on Chrome Developer tools for both mobile/desktop but when I look on my actual phone I get a strange shadow near the top border above the quantity number.

This is my code

#smntcswcb{
        height:35px;
        width:60px;
        padding: 8px 18px 8px 18px !important;
        border:2px solid !important;
        border-radius: 0px !important;
        color:#333 !important;
        font-size: 15px !important;
        border-color: #e5e5e5 !important;
}

When I remove the border color line it goes away, but I would like to keep the gray border without the shadow. Please help.

Edit:

Here is the HTML code for the elements

    Quantity
    <input class="minus" type="button" value="-">
    <input type="number" id="smntcswcb" step="1" min="1" name="quantity" value="1" title="Qty" class="input-text qty text" inputmode="numeric">
    <input class="plus" type="button" value="+">

Here is the CSS code for class="minus"

.minus{
    background: none;
    text-align: center;
    width:48px !important;
    height:35px;
    padding: 2px 0px 0px 0px !important;
    background-color: #fff !important;
    border:2px solid transparent !important;
    border-radius: 0px !important;
    border-color: #e5e5e5 !important;
    color:#333 !important;
    margin-right: -4px;
    color:#000 !important;
    font-size: 24px !important;
    font-weight:900 !important;
    position: relative;
}

Here is the CSS code for the class "plus"

.plus{
    height:35px !important;
    width:48px !important;
    padding: 2px 0px 0px 0px !important;
    background-color: #fff !important;
    border:2px solid transparent !important;
    border-radius: 0px !important;
    border-color: #e5e5e5 !important;
    color:#333 !important;
    margin-left: -4px;
    font-size: 24px !important;
    font-weight:900 !important;
}

Here is the code for the parent class "quantity". I am using flex to make the items on the same height

.single_variation_wrap .quantity{
    display: flex;
}

Body:
It must be that your phone's OS UI engine renders the component according to its standards and it ends up adding that shadow, try to force disable the shadow. See last 3 lines of the css selectors:

#smntcswcb{
    height:35px;
    width:60px;
    padding: 8px 18px 8px 18px !important;
    border:2px solid !important;
    border-radius: 0px !important;
    color:#333 !important;
    font-size: 15px !important;
    border-color: #e5e5e5 !important;

    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;

}


问:
How to get Highcharts XAxis to Display in 2 Minute Intervals
I am somewhat new to Highcharts and I am trying to pull off something that I am sure can be done but I cant figure it out.

I have posted my jsfiddle here: https://jsfiddle.net/dfeagin/1hn6c9ad/7/
Here is what the data looks like in my categories section for that axis:

```<code>categories: ['1/20/2020 9:22:02 PM', '1/20/2020 9:22:03 PM', '1/20/2020 9:22:04 PM', '1/20/2020 9:22:08 PM', '1/20/2020 9:22:09 PM', '1/20/2020 9:22:10 PM', '1/20/2020 9:22:12 PM', '1/20/2020 9:22:14 PM', '1/20/2020 9:22:15 PM', '1/20/2020 9:22:16 PM', '1/20/2020 9:22:18 PM', '1/20/2020 9:22:19 PM'.....]
</code>```

On the XAxis, which represents  minutes, there are a total of 46 minutes between the start to end time frame. I want to show two minute increments and just show the minute number vs. a date/time stamp:
0 2 4 6 8 10 ..... 42 44 46

How can I get it to do that? The data will have differing numbers of data points between those two minute increments but I want the 2 min intervals to be consistent.

Another note: I am generating the data that I feed to Highcharts in a .net web application so if it helps the situation I can send in a series of minute numbers vs. time/date stamps. So I could be sending over:

```<code>categories: ['0', '0', '0', '1', '1', '2', '2', '2', '2', '2', '2', '2', '3', ... '43', '43', '43', '44', '44', '45', '45', '45', '45', '45', '45', '45', '46', '46']

</code>```

答:
I think you would be better setting the chart up as spline rather than each series, with a datetime x-axis and putting data into the series as an array of date/value x/y pairs.

This way you can have more control over the xAxis ticks in this case setting tick interval to 2 minutes, and is more flexible in general.

Use a custom formatter to manipulate the tick value.

https://jsfiddle.net/gazx45oy/

Chart type:

```<code>chart: {
  type: 'spline',
</code>```

xAxis settings:

```<code>xAxis: [{
type: 'datetime',
startOnTick: true,
minPadding: 0,
tickInterval: 120000,
labels: {
    formatter: function () {
        return (this.value - this.axis.min) / 60000;
    },
</code>```

Series data:

```<code>var vesselSteamTemp = [
[Date.UTC(2020,20,1,9,22,2), 119],
</code>```

Body:
I am somewhat new to Highcharts and I am trying to pull off something that I am sure can be done but I cant figure it out.

I have posted my jsfiddle here: https://jsfiddle.net/dfeagin/1hn6c9ad/7/
Here is what the data looks like in my categories section for that axis:

categories: ['1/20/2020 9:22:02 PM', '1/20/2020 9:22:03 PM', '1/20/2020 9:22:04 PM', '1/20/2020 9:22:08 PM', '1/20/2020 9:22:09 PM', '1/20/2020 9:22:10 PM', '1/20/2020 9:22:12 PM', '1/20/2020 9:22:14 PM', '1/20/2020 9:22:15 PM', '1/20/2020 9:22:16 PM', '1/20/2020 9:22:18 PM', '1/20/2020 9:22:19 PM'.....]

On the XAxis, which represents  minutes, there are a total of 46 minutes between the start to end time frame. I want to show two minute increments and just show the minute number vs. a date/time stamp:
0 2 4 6 8 10 ..... 42 44 46

How can I get it to do that? The data will have differing numbers of data points between those two minute increments but I want the 2 min intervals to be consistent.

Another note: I am generating the data that I feed to Highcharts in a .net web application so if it helps the situation I can send in a series of minute numbers vs. time/date stamps. So I could be sending over:

categories: ['0', '0', '0', '1', '1', '2', '2', '2', '2', '2', '2', '2', '3', ... '43', '43', '43', '44', '44', '45', '45', '45', '45', '45', '45', '45', '46', '46']

Body:
I think you would be better setting the chart up as spline rather than each series, with a datetime x-axis and putting data into the series as an array of date/value x/y pairs.

This way you can have more control over the xAxis ticks in this case setting tick interval to 2 minutes, and is more flexible in general.

Use a custom formatter to manipulate the tick value.

https://jsfiddle.net/gazx45oy/

Chart type:

chart: {
  type: 'spline',

xAxis settings:

xAxis: [{
type: 'datetime',
startOnTick: true,
minPadding: 0,
tickInterval: 120000,
labels: {
    formatter: function () {
        return (this.value - this.axis.min) / 60000;
    },

Series data:

var vesselSteamTemp = [
[Date.UTC(2020,20,1,9,22,2), 119],


问:
What is an elegant way to replace the marked text of a beautifulsoup tag with a child tag containing the same text
So I have these tags like below, in some cases containing other tags (spans in these case)

Test1###yrdy
,

Test2###qweqwe
,

Test3 ###qweqeqwe
,

Test4 ### sfsfsdfds
,

Test5### 121212
```
</div>
</div>
</p>

<p>I am trying to figure out a way to replace what comes after ### and the ### with a span contatining the replaced text<br>
I am looking at the .replace_with() method but that will replace the tag entirely</p>

<p>using the above against .string is not going to work as my strings are</p>

```Test1###yrdy
Test2###qweqwe
None
Test4 ### sfsfsdfds
Test5### 121212
```

<p>So line 3 will be missed.  I also tried changing .contents
 for p in paragraphs:   </p>

```print(p.contents)
for content in p.contents:
    if "###" in content:
        content=content.replace("###",''+'###'+'')
print (p.contents)
```

<p>The above did not have any effect on the tree</p>

<p>The desired result (the text will be enclosed in its own span with some styling):</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override"><code><p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{218}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="font-weight:bold">Test1<span>###yrdy</span></span></p>,
 <p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{220}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test2<span>###qweqwe</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{22}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="color:red">Test3</span> <span>###qweqeqwe</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{17}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test4 <span>### sfsfsdfds</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{19}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test5<span>### 121212</span></p></code>```

答:
```<code>txt = '''<p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{218}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="font-weight:bold">Test1###yrdy</span></p>,
 <p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{220}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test2###qweqwe</p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{22}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="color:red">Test3</span> ###qweqeqwe</p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{17}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test4 ### sfsfsdfds</p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{19}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test5### 121212</p>'''

soup = BeautifulSoup(txt, 'html.parser')

r = re.compile(r'(.*?)(###.*)')

for tag in soup.find_all(lambda tag: any('###' in c for c in tag.contents)):
    # find content index:
    for idx, c in enumerate(tag.contents):
        if '###' in c:
            break
    tag.contents[idx] = BeautifulSoup(r.sub(r'\1<span>\2</span>', tag.contents[idx]), 'html.parser')

print(soup)
</code>```

Prints:

```<code><p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{218}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="font-weight:bold">Test1<span>###yrdy</span></span></p>,
 <p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{220}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test2<span>###qweqwe</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{22}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="color:red">Test3</span> <span>###qweqeqwe</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{17}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test4 <span>### sfsfsdfds</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{19}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test5<span>### 121212</span></p>
</code>```

Body:
So I have these tags like below, in some cases containing other tags (spans in these case)

Test1###yrdy
,

Test2###qweqwe
,

Test3 ###qweqeqwe
,

Test4 ### sfsfsdfds
,

Test5### 121212

I am trying to figure out a way to replace what comes after ### and the ### with a span contatining the replaced text

I am looking at the .replace_with() method but that will replace the tag entirely

using the above against .string is not going to work as my strings are

Test1###yrdy
Test2###qweqwe
None
Test4 ### sfsfsdfds
Test5### 121212

So line 3 will be missed.  I also tried changing .contents
 for p in paragraphs:

print(p.contents)
for content in p.contents:
    if "###" in content:
        content=content.replace("###",''+'###'+'')
print (p.contents)

The above did not have any effect on the tree

The desired result (the text will be enclosed in its own span with some styling):

Test1###yrdy
,

Test2###qweqwe
,

Test3 ###qweqeqwe
,

Test4 ### sfsfsdfds
,

Test5### 121212

Body:
txt = '''<p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{218}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="font-weight:bold">Test1###yrdy</span></p>,
 <p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{220}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test2###qweqwe</p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{22}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="color:red">Test3</span> ###qweqeqwe</p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{17}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test4 ### sfsfsdfds</p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{19}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test5### 121212</p>'''

soup = BeautifulSoup(txt, 'html.parser')

r = re.compile(r'(.*?)(###.*)')

for tag in soup.find_all(lambda tag: any('###' in c for c in tag.contents)):
    # find content index:
    for idx, c in enumerate(tag.contents):
        if '###' in c:
            break
    tag.contents[idx] = BeautifulSoup(r.sub(r'\1<span>\2</span>', tag.contents[idx]), 'html.parser')

print(soup)

Prints:

<p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{218}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="font-weight:bold">Test1<span>###yrdy</span></span></p>,
 <p id="p:{659babcd-9de3-0e7a-27ba-7fa0325a40f7}{220}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test2<span>###qweqwe</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{22}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt"><span style="color:red">Test3</span> <span>###qweqeqwe</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{17}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test4 <span>### sfsfsdfds</span></p>,
 <p id="p:{d59b11dc-654f-0d5c-0ee2-f66181a6fa4b}{19}" lang="en-US" style="font-size:10.5pt;margin-top:0pt;margin-bottom:0pt">Test5<span>### 121212</span></p>


问:
How to subscribe data using DolphinDB Python API?
I want to subscribe data from DolphinDB, and I have run these codes in DolphinDB:

```<code>share streamTable(10000:0,`time`sym`price`id, [TIMESTAMP,SYMBOL,DOUBLE,INT]) as trades
setStreamTableFilterColumn(trades, `sym)
insert into trades values(take(now(), 10), rand(`ab`cd`ef`gh`ij, 10), rand(1000,10)/10.0, 1..10)
</code>```

And thes codes in Python:

```<code>import dolphindb as ddb
import numpy as np
s = ddb.session()
s.enableStreaming(8000)

def handler(lst):
    print(lst)

s.subscribe("localhost",8848,handler,"trades","action",0,False,np.array(['ab']))
</code>```

And I encountered this error:

```<code>ERROR in subscribeInternal err: The feature of publish is not enabled.
Retry subscribe in 1 second
ERROR in subscribeInternal err: The feature of publish is not enabled.
Retry subscribe in 1 second
ERROR in subscribeInternal err: The feature of publish is not enabled.
Retry subscribe in 1 second
</code>```

So how to enable the feature of publish?

答:
The python code looks good. However

1) You might double check if you have set parameter maxPubConnection such as the follows. In order to enable publishing, this parameter has to be set on the server side.
    maxPubConnection=256

2) For robust subscription,  it is recommended using ip address such as "127.0.0.1" instead of "localhost".

Body:
I want to subscribe data from DolphinDB, and I have run these codes in DolphinDB:

share streamTable(10000:0,`time`sym`price`id, [TIMESTAMP,SYMBOL,DOUBLE,INT]) as trades
setStreamTableFilterColumn(trades, `sym)
insert into trades values(take(now(), 10), rand(`ab`cd`ef`gh`ij, 10), rand(1000,10)/10.0, 1..10)

And thes codes in Python:

import dolphindb as ddb
import numpy as np
s = ddb.session()
s.enableStreaming(8000)

def handler(lst):
    print(lst)

s.subscribe("localhost",8848,handler,"trades","action",0,False,np.array(['ab']))

And I encountered this error:

ERROR in subscribeInternal err: The feature of publish is not enabled.
Retry subscribe in 1 second
ERROR in subscribeInternal err: The feature of publish is not enabled.
Retry subscribe in 1 second
ERROR in subscribeInternal err: The feature of publish is not enabled.
Retry subscribe in 1 second

So how to enable the feature of publish?


问:
How to list latest timestamps files from partial duplicate name
I have more than 10k  files like as given in below example. I would like to filter out partial duplicate i.e 123456 is common in all listed files which are consider to be duplicate and out of these duplicate files I need file of latest time stamps

```<code>   123456_20200425-012034.xml
   123456_20200424-120102.xml
   123456_20200425-121102.xml
   234567_20200323-112232.xml
   123456_20200423-111102.xml --- consider that this file is having latest
                                  timestamps out of all above duplicate file
</code>```

How to do it using bash ?

Also output should have files which are not duplicate. It means out of 10K files few files are not duplicate those files should include in output.

Output is require like (latest timestamps files)

```<code>123456_20200423-111102.xml
234567_20200323-112232.xml
</code>```

答:
Because we can assume that globs are sorted alphanumerically, we can use a wildcard to iterate over the files and build a set of results:

#!/bin/bash

# change INPUTDIR to your input directory
INPUTDIR=.
seen=
store=()

for file in "$INPUTDIR"/* ; do
    if [[ "$seen" != *"${file%_*}"* ]] ; then
        store+=( "$file" )
        seen="$seen ${file%_*}"
    fi
done

# results
echo "${store[@]}"
```

Explanation:

Iterate over all files in a directory.

Get the filename before the first underscore (i.e. 123456). If we've haven't it before (i.e. "$seen" != *"${file%_*}"*), add it to our list of files to store. If we have seen it before, skip the file.

Print the results.

Body:
I have more than 10k  files like as given in below example. I would like to filter out partial duplicate i.e 123456 is common in all listed files which are consider to be duplicate and out of these duplicate files I need file of latest time stamps

   123456_20200425-012034.xml
   123456_20200424-120102.xml
   123456_20200425-121102.xml
   234567_20200323-112232.xml
   123456_20200423-111102.xml --- consider that this file is having latest
                                  timestamps out of all above duplicate file

How to do it using bash ?

Also output should have files which are not duplicate. It means out of 10K files few files are not duplicate those files should include in output.

Output is require like (latest timestamps files)

123456_20200423-111102.xml
234567_20200323-112232.xml

Body:
Because we can assume that globs are sorted alphanumerically, we can use a wildcard to iterate over the files and build a set of results:

#!/bin/bash

# change INPUTDIR to your input directory
INPUTDIR=.
seen=
store=()

for file in "$INPUTDIR"/* ; do
    if [[ "$seen" != *"${file%_*}"* ]] ; then
        store+=( "$file" )
        seen="$seen ${file%_*}"
    fi
done

# results
echo "${store[@]}"

Explanation:

Iterate over all files in a directory.

Get the filename before the first underscore (i.e. 123456). If we've haven't it before (i.e. "$seen" != *"${file%_*}"*), add it to our list of files to store. If we have seen it before, skip the file.

Print the results.


问:
TypeError: join() argument must be str or bytes, not 'TextIOWrapper
I have features and a target variable which I am wanting to generate a Decision Tree. However, the code is throwing an error. Since the 'out file' did not generate an error, I figured there wouldn't be an error for the 'Source.from_file' either, but there is one.</p>

```<code>import os
from graphviz import Source
from sklearn.tree import export_graphviz
f = open("C:/Users/julia/Desktop/iris_tree.dot", 'w')
export_graphviz(
        tree_clf,
        out_file=f,
        feature_names=sample2[0:2],
        class_names=sample2[5],
        rounded=True,
        filled=True
    )
Source.from_file(f)
</code>```

答:
As noted in the docs, from_file accepts a string path, not a file object:

filename – Filename for loading/saving the source.

Just pass the path in:

```<code>import os
from graphviz import Source
from sklearn.tree import export_graphviz
path = "C:/Users/julia/Desktop/iris_tree.dot"
f = open(path, 'w')
export_graphviz(
        tree_clf,
        out_file=f,
        feature_names=sample2[0:2],
        class_names=sample2[5],
        rounded=True,
        filled=True
    )
Source.from_file(path)
</code>```

Body:
I have features and a target variable which I am wanting to generate a Decision Tree. However, the code is throwing an error. Since the 'out file' did not generate an error, I figured there wouldn't be an error for the 'Source.from_file' either, but there is one.

import os
from graphviz import Source
from sklearn.tree import export_graphviz
f = open("C:/Users/julia/Desktop/iris_tree.dot", 'w')
export_graphviz(
        tree_clf,
        out_file=f,
        feature_names=sample2[0:2],
        class_names=sample2[5],
        rounded=True,
        filled=True
    )
Source.from_file(f)

Body:
As noted in the docs, from_file accepts a string path, not a file object:

filename – Filename for loading/saving the source.

Just pass the path in:

import os
from graphviz import Source
from sklearn.tree import export_graphviz
path = "C:/Users/julia/Desktop/iris_tree.dot"
f = open(path, 'w')
export_graphviz(
        tree_clf,
        out_file=f,
        feature_names=sample2[0:2],
        class_names=sample2[5],
        rounded=True,
        filled=True
    )
Source.from_file(path)


问:
Selenium file_detector unable to find file to upload to selenium grid
Using selenium webdriver 3.12 and running a file upload tests on saucelabs(a selenium grid) as Win 10 chrome 66. I've tried to implement file detector and send keys into my code so that the system can take the file off my local machine and use it in saucelabs, but am running into the error:

```<code>Selenium::WebDriver::Error::ExpectedError:
       invalid argument: File not found : /Users/john.doe/Work/project/spec/support/apps/files/suggested_content/valid_sc.csv
         (Session info: chrome=66.0.3359.117)
         (Driver info: chromedriver=2.38.551601 (edb21f07fc70e9027c746edd3201443e011a61ed),platform=Windows NT 10.0.10586 x86_64)
</code>```

The way I've implemented this is adding file detector as part of my spec helper, then requiring the spec helper at the top of my spec file, then using sendkeys to send the path for the file upload. Similar to Saucelabs best practices here

A snippet from inside my spec helper... I've instantiated the driver and added the code for file detector(this is slightly tweaked from sauce's and rubydoc's use since it is using current session driver instead of just driver):

```<code>       Capybara::Selenium::Driver.new(app,
                                       browser: :remote,
                                       url: url,
                                       desired_capabilities: capabilities)
        end

Capybara.current_session.driver.browser.file_detector = lambda do |args|
            str = args.first.to_s
            str if File.exist?(str)
          end
</code>```

and what is getting called to upload the file:

```<code>    def add_file(file_name = 'valid_sc.csv')
      path = './spec/support/apps/files/suggested_content/'
      expose_file_upload
      page.find('input[id*=content--add-file')
          .send_keys(File.expand_path(path + file_name))
    end
</code>```

The file is most certainly at that path and works just fine when I run the test locally.  what am I missing here?

答:
I stumbled upon this thread for another error, but found the context on this question useful. Adding it here in case anyone's stuck on this:

```<code>NoMethodError:
           undefined method `file_detector=' for #<Selenium::WebDriver::Chrome::Driver:0x00007ff8edf60020>
</code>```

My version setup looked like:

ChromeDriver 83.0.4103.39

selenium-webdriver 3.14

To fix this:

I followed Thomas's recommendation to put driver.browser.file_detector inside the driver registration used for the remote driver as shown in his answer

I upgraded selenium-webdriver gem from 3.14 to 3.142.7

Body:
Using selenium webdriver 3.12 and running a file upload tests on saucelabs(a selenium grid) as Win 10 chrome 66. I've tried to implement file detector and send keys into my code so that the system can take the file off my local machine and use it in saucelabs, but am running into the error:

Selenium::WebDriver::Error::ExpectedError:
       invalid argument: File not found : /Users/john.doe/Work/project/spec/support/apps/files/suggested_content/valid_sc.csv
         (Session info: chrome=66.0.3359.117)
         (Driver info: chromedriver=2.38.551601 (edb21f07fc70e9027c746edd3201443e011a61ed),platform=Windows NT 10.0.10586 x86_64)

The way I've implemented this is adding file detector as part of my spec helper, then requiring the spec helper at the top of my spec file, then using sendkeys to send the path for the file upload. Similar to Saucelabs best practices here

A snippet from inside my spec helper... I've instantiated the driver and added the code for file detector(this is slightly tweaked from sauce's and rubydoc's use since it is using current session driver instead of just driver):

       Capybara::Selenium::Driver.new(app,
                                       browser: :remote,
                                       url: url,
                                       desired_capabilities: capabilities)
        end

Capybara.current_session.driver.browser.file_detector = lambda do |args|
            str = args.first.to_s
            str if File.exist?(str)
          end

and what is getting called to upload the file:

    def add_file(file_name = 'valid_sc.csv')
      path = './spec/support/apps/files/suggested_content/'
      expose_file_upload
      page.find('input[id*=content--add-file')
          .send_keys(File.expand_path(path + file_name))
    end

The file is most certainly at that path and works just fine when I run the test locally.  what am I missing here?

Body:
I stumbled upon this thread for another error, but found the context on this question useful. Adding it here in case anyone's stuck on this:

NoMethodError:
           undefined method `file_detector=' for #<Selenium::WebDriver::Chrome::Driver:0x00007ff8edf60020>

My version setup looked like:

ChromeDriver 83.0.4103.39

selenium-webdriver 3.14

To fix this:

I followed Thomas's recommendation to put driver.browser.file_detector inside the driver registration used for the remote driver as shown in his answer

I upgraded selenium-webdriver gem from 3.14 to 3.142.7


问:
Network profiling in VS2019 Community
Has the network profiler been removed?

In previous versions you could select the network profiler but in 2019 I cannot find it.  I want to be able to view the network requests my code is making:

答:
I could not find it either. But if it helps and you need to see the traffic and the calls for debugging purposes you could use Fiddler

Fiddler was a free and pretty advanced tool used to profile the network calls from your computer, I used fiddler before Network profile tool was available in VS 2015.

So now that is gone I am back  using fiddler and I don't need VS Network traffic tool anymore

Title: Network profiling in VS2019 Community


问:
Agora Unity - PushAudioFrame
I'm Using Agor SDK 2.9.2.2 within Unity Platform, to integrate a web broadcasting live.

I tryed to use the pushAudioFrame feature in order to  :

Grab a float [] from an audioListener

Send it as byte[] into an AudioFrame,

Whichever way I try SDK receives zero data, or unity just crashes, i'm sure issues in my code are multiple, but couldnt find any successfull example on the web, just ONE unanswered post from a chinese guy, and  I'm not allowed from europe to participate thread...

Actually following code is used:

// Before Joining Channel

mRtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_MUSIC_STANDARD,AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_EDUCATION);
mRtcEngine.SetExternalAudioSource(true, 16000, 1);

// On Audio Filter Read

```<code>`
virtual public void OnAudioFilterRead(float[] data, int channels)
        {
            if (GrabSceneAudio)
            {
                Int16[] intData = new Int16[data.Length];
                //converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]

                Byte[] bytesData = new Byte[data.Length * 2];
                //bytesData array is twice the size of
                //dataSource array because a float converted in Int16 is 2 bytes.

                var rescaleFactor = 32767; //to convert float to Int16

                for (int i = 0; i < data.Length; i++)
                {
                    intData[i] = (short)(data[i] * rescaleFactor);
                    Byte[] byteArr = new Byte[2];
                    byteArr = BitConverter.GetBytes(intData[i]);
                    byteArr.CopyTo(bytesData, i * 2);
                }
                _externalAudioFrameBuffer = bytesData;

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

// Finally push Audioframe to SDK

```<code>`
virtual protected void PushExternalAudioFrame()
        {
            _externalAudioFrame = new AudioFrame();

            _externalAudioFrame.type = AUDIO_FRAME_TYPE.FRAME_TYPE_PCM16;
            _externalAudioFrame.samples = 256;
            _externalAudioFrame.bytesPerSample = 2;
            _externalAudioFrame.samplesPerSec = 16000;
            _externalAudioFrame.channels = 1;
            _externalAudioFrame.buffer = _externalAudioFrameBuffer;

            if (mRtcEngine != null)
            {
                int a = mRtcEngine.PushAudioFrame(_externalAudioFrame);
            }
        }
`
</code>```

答:
Hi I added some changes to your posted code and tested it in the demo application. You may give it a try.

https://gist.github.com/icywind/8d1d6ad9831402bea8e5852933eb4eb9

or here:

```<code>using UnityEngine;
using UnityEngine.UI;

using agora_gaming_rtc;
using agora_utilities;
using System;
using System.Collections;

// this is an example of using Agora Unity SDK
// It demonstrates:
// How to enable video
// How to join/leave channel
//
public class TestHelloUnityVideo
{

    // instance of agora engine
    private IRtcEngine mRtcEngine;
    AudioSource audioSource;
    MonoBehaviour monoProxy;

    public int AudioChannels = 1;

    // load agora engine
    public void loadEngine(string appId)
    {
        // start sdk
        Debug.Log("initializeEngine");

        if (mRtcEngine != null)
        {
            Debug.Log("Engine exists. Please unload it first!");
            return;
        }

        // init engine
        mRtcEngine = IRtcEngine.GetEngine(appId);

        // enable log
        mRtcEngine.SetLogFilter(LOG_FILTER.DEBUG | LOG_FILTER.INFO | LOG_FILTER.WARNING | LOG_FILTER.ERROR | LOG_FILTER.CRITICAL);
    }

    public void join(string channel)
    {
        Debug.Log("calling join (channel = " + channel + ")");

        if (mRtcEngine == null)
            return;

        // set callbacks (optional)
        mRtcEngine.OnJoinChannelSuccess = onJoinChannelSuccess;
        mRtcEngine.OnUserJoined = onUserJoined;
        mRtcEngine.OnUserOffline = onUserOffline;

        // enable video
        mRtcEngine.EnableVideo();
        // allow camera output callback
        mRtcEngine.EnableVideoObserver();

        /// BEFORE JOINING CHANNEL

        // mRtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_MUSIC_HIGH_QUALITY, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING);

        mRtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_MUSIC_STANDARD, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_EDUCATION);
        mRtcEngine.SetExternalAudioSource(true, SAMPLE_RATE, AudioChannels);

        // join channel
        mRtcEngine.JoinChannel(channel, null, 0);

        // Optional: if a data stream is required, here is a good place to create it
        int streamID = mRtcEngine.CreateDataStream(true, true);
        Debug.Log("initializeEngine done, data stream id = " + streamID);
    }

    public bool GrabSceneAudio = true;

    //// OnAudioListenerRender
    virtual public void OnAudioFilterRead(float[] data, int channels)
    {
        if (GrabSceneAudio)
        {
            short[] intData = new short[data.Length];
            //converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]

            byte[] bytesData = new byte[data.Length * 2];
            //bytesData array is twice the size of
            //dataSource array because a float converted in Int16 is 2 bytes.

            var rescaleFactor = 32767; //to convert float to Int16

            for (int i = 0; i < data.Length; i++)
            {
                float sample = data[i];
                if (sample > 1) sample = 1;
                else if (sample < -1) sample = -1;

                intData[i] = (short)(sample * rescaleFactor);
                byte[] byteArr = new byte[2];
                byteArr = BitConverter.GetBytes(intData[i]);
                byteArr.CopyTo(bytesData, i * 2);
            }

            PushExternalAudioFrame(bytesData, channels);
        }
    }

    const int SAMPLE_RATE = 44100;
    /// FINALLY PUSH FRAME INTO STREAM
    // _externalAudioFrameBuffer.Length = samples * channels * bytesPerSample
    IEnumerator CoAudioRender()
    {
        int channels = audioSource.clip.channels;
        float[] samples = new float[audioSource.clip.samples * channels];
        audioSource.clip.GetData(samples, 0);
        GrabSceneAudio = true;
        int SourceDataIndex = channels * audioSource.timeSamples;
        //int SourceDataIndex = channels * (audioSource.clip.samples - 120000);
        Debug.LogWarning("CoAudioRender started. Found audio samples = " +
            samples.Length + " channels = " + audioSource.clip.channels);

        while (audioSource != null && audioSource.isActiveAndEnabled && audioSource.isPlaying)
        {
            int readSamples = (int)(SAMPLE_RATE * Time.deltaTime); // SamplesRate * elapsedTime => number of samples to read
            int delta = channels * readSamples;
            float[] copySample = new float[delta];
            if (readSamples + SourceDataIndex / channels <= audioSource.clip.samples)
            {
                Array.Copy(samples, SourceDataIndex, copySample, 0, delta);
            }
            else // wrap
            {
                int cur2EndCnt = samples.Length - SourceDataIndex;
                int wrap2HeadCnt = delta - cur2EndCnt;
                Array.Copy(samples, SourceDataIndex, copySample, 0, cur2EndCnt);
                Array.Copy(samples, 0, copySample, cur2EndCnt, wrap2HeadCnt);
            }
            SourceDataIndex = (SourceDataIndex + delta) % samples.Length;

            OnAudioFilterRead(copySample, channels);
            yield return new WaitForEndOfFrame();
        }
        GrabSceneAudio = false;
        Debug.LogWarning("Done Audio Render coroutine...");
    }

    virtual protected void PushExternalAudioFrame(byte[] _externalAudioFrameBuffer, int channels)
    {
        AudioFrame _externalAudioFrame = new AudioFrame();

        int bytesPerSample = 2;

        _externalAudioFrame.type = AUDIO_FRAME_TYPE.FRAME_TYPE_PCM16;
        _externalAudioFrame.samples = _externalAudioFrameBuffer.Length / (channels * bytesPerSample);
        _externalAudioFrame.bytesPerSample = bytesPerSample;
        _externalAudioFrame.samplesPerSec = SAMPLE_RATE;
        _externalAudioFrame.channels = channels;
        _externalAudioFrame.buffer = _externalAudioFrameBuffer;

        if (mRtcEngine != null)
        {
            int a = mRtcEngine.PushAudioFrame(_externalAudioFrame);
        }
    }

    public string getSdkVersion()
    {
        string ver = IRtcEngine.GetSdkVersion();
        if (ver == "2.9.1.45")
        {
            ver = "2.9.2";  // A conversion for the current internal version#
        }
        else
        {
            if (ver == "2.9.1.46")
            {
                ver = "2.9.2.2";  // A conversion for the current internal version#
            }
        }
        return ver;
    }

    public void leave()
    {
        Debug.Log("calling leave");

        if (mRtcEngine == null)
            return;

        // leave channel
        mRtcEngine.LeaveChannel();
        // deregister video frame observers in native-c code
        mRtcEngine.DisableVideoObserver();
    }

    // unload agora engine
    public void unloadEngine()
    {
        Debug.Log("calling unloadEngine");

        // delete
        if (mRtcEngine != null)
        {
            IRtcEngine.Destroy();  // Place this call in ApplicationQuit
            mRtcEngine = null;
        }
    }

    public void EnableVideo(bool pauseVideo)
    {
        if (mRtcEngine != null)
        {
            if (!pauseVideo)
            {
                mRtcEngine.EnableVideo();
            }
            else
            {
                mRtcEngine.DisableVideo();
            }
        }
    }

    // accessing GameObject in Scnene1
    // set video transform delegate for statically created GameObject
    public void onSceneHelloVideoLoaded()
    {
        // Attach the SDK Script VideoSurface for video rendering
        GameObject quad = GameObject.Find("Quad");
        if (ReferenceEquals(quad, null))
        {
            Debug.Log("BBBB: failed to find Quad");
            return;
        }
        else
        {
            quad.AddComponent<VideoSurface>();
        }

        GameObject cube = GameObject.Find("Cube");
        if (ReferenceEquals(cube, null))
        {
            Debug.Log("BBBB: failed to find Cube");
            return;
        }
        else
        {
            cube.AddComponent<VideoSurface>();
        }

        GameObject game = GameObject.Find("GameController");
        if (game != null)
        {
            monoProxy = game.GetComponent<MonoBehaviour>();
            audioSource = game.GetComponent<AudioSource>();
            monoProxy.StartCoroutine(CoAudioRender());
        }
    }

    // implement engine callbacks
    private void onJoinChannelSuccess(string channelName, uint uid, int elapsed)
    {
        Debug.Log("JoinChannelSuccessHandler: uid = " + uid);
        GameObject textVersionGameObject = GameObject.Find("VersionText");
        textVersionGameObject.GetComponent<Text>().text = "SDK Version : " + getSdkVersion();
    }

    // When a remote user joined, this delegate will be called. Typically
    // create a GameObject to render video on it
    private void onUserJoined(uint uid, int elapsed)
    {
        Debug.Log("onUserJoined: uid = " + uid + " elapsed = " + elapsed);
        // this is called in main thread

        // find a game object to render video stream from 'uid'
        GameObject go = GameObject.Find(uid.ToString());
        if (!ReferenceEquals(go, null))
        {
            return; // reuse
        }

        // create a GameObject and assign to this new user
        VideoSurface videoSurface = makeImageSurface(uid.ToString());
        if (!ReferenceEquals(videoSurface, null))
        {
            // configure videoSurface
            videoSurface.SetForUser(uid);
            videoSurface.SetEnable(true);
            videoSurface.SetVideoSurfaceType(AgoraVideoSurfaceType.RawImage);
            videoSurface.SetGameFps(30);
        }
    }

    public VideoSurface makePlaneSurface(string goName)
    {
        GameObject go = GameObject.CreatePrimitive(PrimitiveType.Plane);

        if (go == null)
        {
            return null;
        }
        go.name = goName;
        // set up transform
        go.transform.Rotate(-90.0f, 0.0f, 0.0f);
        float yPos = UnityEngine.Random.Range(3.0f, 5.0f);
        float xPos = UnityEngine.Random.Range(-2.0f, 2.0f);
        go.transform.position = new Vector3(xPos, yPos, 0f);
        go.transform.localScale = new Vector3(0.25f, 0.5f, .5f);

        // configure videoSurface
        VideoSurface videoSurface = go.AddComponent<VideoSurface>();
        return videoSurface;
    }

    private const float Offset = 100;
    public VideoSurface makeImageSurface(string goName)
    {
        GameObject go = new GameObject();

        if (go == null)
        {
            return null;
        }

        go.name = goName;

        // to be renderered onto
        go.AddComponent<RawImage>();

        // make the object draggable
        go.AddComponent<UIElementDragger>();
        GameObject canvas = GameObject.Find("Canvas");
        if (canvas != null)
        {
            go.transform.parent = canvas.transform;
        }
        // set up transform
        go.transform.Rotate(0f, 0.0f, 180.0f);
        float xPos = UnityEngine.Random.Range(Offset - Screen.width / 2f, Screen.width / 2f - Offset);
        float yPos = UnityEngine.Random.Range(Offset, Screen.height / 2f - Offset);
        go.transform.localPosition = new Vector3(xPos, yPos, 0f);
        go.transform.localScale = new Vector3(3f, 4f, 1f);

        // configure videoSurface
        VideoSurface videoSurface = go.AddComponent<VideoSurface>();
        return videoSurface;
    }
    // When remote user is offline, this delegate will be called. Typically
    // delete the GameObject for this user
    private void onUserOffline(uint uid, USER_OFFLINE_REASON reason)
    {
        // remove video stream
        Debug.Log("onUserOffline: uid = " + uid + " reason = " + reason);
        // this is called in main thread
        GameObject go = GameObject.Find(uid.ToString());
        if (!ReferenceEquals(go, null))
        {
            GameObject.Destroy(go);
        }
    }
}
</code>```

Title: Agora Unity - PushAudioFrame

Body:
I'm Using Agor SDK 2.9.2.2 within Unity Platform, to integrate a web broadcasting live.

I tryed to use the pushAudioFrame feature in order to  :

Grab a float [] from an audioListener

Send it as byte[] into an AudioFrame,

Whichever way I try SDK receives zero data, or unity just crashes, i'm sure issues in my code are multiple, but couldnt find any successfull example on the web, just ONE unanswered post from a chinese guy, and  I'm not allowed from europe to participate thread...

Actually following code is used:

// Before Joining Channel

mRtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_MUSIC_STANDARD,AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_EDUCATION);
mRtcEngine.SetExternalAudioSource(true, 16000, 1);

// On Audio Filter Read

`
virtual public void OnAudioFilterRead(float[] data, int channels)
        {
            if (GrabSceneAudio)
            {
                Int16[] intData = new Int16[data.Length];
                //converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]

                Byte[] bytesData = new Byte[data.Length * 2];
                //bytesData array is twice the size of
                //dataSource array because a float converted in Int16 is 2 bytes.

                var rescaleFactor = 32767; //to convert float to Int16

                for (int i = 0; i < data.Length; i++)
                {
                    intData[i] = (short)(data[i] * rescaleFactor);
                    Byte[] byteArr = new Byte[2];
                    byteArr = BitConverter.GetBytes(intData[i]);
                    byteArr.CopyTo(bytesData, i * 2);
                }
                _externalAudioFrameBuffer = bytesData;

                PushExternalAudioFrame();
            }
        }
`

// Finally push Audioframe to SDK

`
virtual protected void PushExternalAudioFrame()
        {
            _externalAudioFrame = new AudioFrame();

            _externalAudioFrame.type = AUDIO_FRAME_TYPE.FRAME_TYPE_PCM16;
            _externalAudioFrame.samples = 256;
            _externalAudioFrame.bytesPerSample = 2;
            _externalAudioFrame.samplesPerSec = 16000;
            _externalAudioFrame.channels = 1;
            _externalAudioFrame.buffer = _externalAudioFrameBuffer;

            if (mRtcEngine != null)
            {
                int a = mRtcEngine.PushAudioFrame(_externalAudioFrame);
            }
        }
`

Body:
Hi I added some changes to your posted code and tested it in the demo application. You may give it a try.

https://gist.github.com/icywind/8d1d6ad9831402bea8e5852933eb4eb9

or here:

using UnityEngine;
using UnityEngine.UI;

using agora_gaming_rtc;
using agora_utilities;
using System;
using System.Collections;

// this is an example of using Agora Unity SDK
// It demonstrates:
// How to enable video
// How to join/leave channel
//
public class TestHelloUnityVideo
{

    // instance of agora engine
    private IRtcEngine mRtcEngine;
    AudioSource audioSource;
    MonoBehaviour monoProxy;

    public int AudioChannels = 1;

    // load agora engine
    public void loadEngine(string appId)
    {
        // start sdk
        Debug.Log("initializeEngine");

        if (mRtcEngine != null)
        {
            Debug.Log("Engine exists. Please unload it first!");
            return;
        }

        // init engine
        mRtcEngine = IRtcEngine.GetEngine(appId);

        // enable log
        mRtcEngine.SetLogFilter(LOG_FILTER.DEBUG | LOG_FILTER.INFO | LOG_FILTER.WARNING | LOG_FILTER.ERROR | LOG_FILTER.CRITICAL);
    }

    public void join(string channel)
    {
        Debug.Log("calling join (channel = " + channel + ")");

        if (mRtcEngine == null)
            return;

        // set callbacks (optional)
        mRtcEngine.OnJoinChannelSuccess = onJoinChannelSuccess;
        mRtcEngine.OnUserJoined = onUserJoined;
        mRtcEngine.OnUserOffline = onUserOffline;

        // enable video
        mRtcEngine.EnableVideo();
        // allow camera output callback
        mRtcEngine.EnableVideoObserver();

        /// BEFORE JOINING CHANNEL

        // mRtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_MUSIC_HIGH_QUALITY, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING);

        mRtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_MUSIC_STANDARD, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_EDUCATION);
        mRtcEngine.SetExternalAudioSource(true, SAMPLE_RATE, AudioChannels);

        // join channel
        mRtcEngine.JoinChannel(channel, null, 0);

        // Optional: if a data stream is required, here is a good place to create it
        int streamID = mRtcEngine.CreateDataStream(true, true);
        Debug.Log("initializeEngine done, data stream id = " + streamID);
    }

    public bool GrabSceneAudio = true;

    //// OnAudioListenerRender
    virtual public void OnAudioFilterRead(float[] data, int channels)
    {
        if (GrabSceneAudio)
        {
            short[] intData = new short[data.Length];
            //converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]

            byte[] bytesData = new byte[data.Length * 2];
            //bytesData array is twice the size of
            //dataSource array because a float converted in Int16 is 2 bytes.

            var rescaleFactor = 32767; //to convert float to Int16

            for (int i = 0; i < data.Length; i++)
            {
                float sample = data[i];
                if (sample > 1) sample = 1;
                else if (sample < -1) sample = -1;

                intData[i] = (short)(sample * rescaleFactor);
                byte[] byteArr = new byte[2];
                byteArr = BitConverter.GetBytes(intData[i]);
                byteArr.CopyTo(bytesData, i * 2);
            }

            PushExternalAudioFrame(bytesData, channels);
        }
    }

    const int SAMPLE_RATE = 44100;
    /// FINALLY PUSH FRAME INTO STREAM
    // _externalAudioFrameBuffer.Length = samples * channels * bytesPerSample
    IEnumerator CoAudioRender()
    {
        int channels = audioSource.clip.channels;
        float[] samples = new float[audioSource.clip.samples * channels];
        audioSource.clip.GetData(samples, 0);
        GrabSceneAudio = true;
        int SourceDataIndex = channels * audioSource.timeSamples;
        //int SourceDataIndex = channels * (audioSource.clip.samples - 120000);
        Debug.LogWarning("CoAudioRender started. Found audio samples = " +
            samples.Length + " channels = " + audioSource.clip.channels);

        while (audioSource != null && audioSource.isActiveAndEnabled && audioSource.isPlaying)
        {
            int readSamples = (int)(SAMPLE_RATE * Time.deltaTime); // SamplesRate * elapsedTime => number of samples to read
            int delta = channels * readSamples;
            float[] copySample = new float[delta];
            if (readSamples + SourceDataIndex / channels <= audioSource.clip.samples)
            {
                Array.Copy(samples, SourceDataIndex, copySample, 0, delta);
            }
            else // wrap
            {
                int cur2EndCnt = samples.Length - SourceDataIndex;
                int wrap2HeadCnt = delta - cur2EndCnt;
                Array.Copy(samples, SourceDataIndex, copySample, 0, cur2EndCnt);
                Array.Copy(samples, 0, copySample, cur2EndCnt, wrap2HeadCnt);
            }
            SourceDataIndex = (SourceDataIndex + delta) % samples.Length;

            OnAudioFilterRead(copySample, channels);
            yield return new WaitForEndOfFrame();
        }
        GrabSceneAudio = false;
        Debug.LogWarning("Done Audio Render coroutine...");
    }

    virtual protected void PushExternalAudioFrame(byte[] _externalAudioFrameBuffer, int channels)
    {
        AudioFrame _externalAudioFrame = new AudioFrame();

        int bytesPerSample = 2;

        _externalAudioFrame.type = AUDIO_FRAME_TYPE.FRAME_TYPE_PCM16;
        _externalAudioFrame.samples = _externalAudioFrameBuffer.Length / (channels * bytesPerSample);
        _externalAudioFrame.bytesPerSample = bytesPerSample;
        _externalAudioFrame.samplesPerSec = SAMPLE_RATE;
        _externalAudioFrame.channels = channels;
        _externalAudioFrame.buffer = _externalAudioFrameBuffer;

        if (mRtcEngine != null)
        {
            int a = mRtcEngine.PushAudioFrame(_externalAudioFrame);
        }
    }

    public string getSdkVersion()
    {
        string ver = IRtcEngine.GetSdkVersion();
        if (ver == "2.9.1.45")
        {
            ver = "2.9.2";  // A conversion for the current internal version#
        }
        else
        {
            if (ver == "2.9.1.46")
            {
                ver = "2.9.2.2";  // A conversion for the current internal version#
            }
        }
        return ver;
    }

    public void leave()
    {
        Debug.Log("calling leave");

        if (mRtcEngine == null)
            return;

        // leave channel
        mRtcEngine.LeaveChannel();
        // deregister video frame observers in native-c code
        mRtcEngine.DisableVideoObserver();
    }

    // unload agora engine
    public void unloadEngine()
    {
        Debug.Log("calling unloadEngine");

        // delete
        if (mRtcEngine != null)
        {
            IRtcEngine.Destroy();  // Place this call in ApplicationQuit
            mRtcEngine = null;
        }
    }

    public void EnableVideo(bool pauseVideo)
    {
        if (mRtcEngine != null)
        {
            if (!pauseVideo)
            {
                mRtcEngine.EnableVideo();
            }
            else
            {
                mRtcEngine.DisableVideo();
            }
        }
    }

    // accessing GameObject in Scnene1
    // set video transform delegate for statically created GameObject
    public void onSceneHelloVideoLoaded()
    {
        // Attach the SDK Script VideoSurface for video rendering
        GameObject quad = GameObject.Find("Quad");
        if (ReferenceEquals(quad, null))
        {
            Debug.Log("BBBB: failed to find Quad");
            return;
        }
        else
        {
            quad.AddComponent<VideoSurface>();
        }

        GameObject cube = GameObject.Find("Cube");
        if (ReferenceEquals(cube, null))
        {
            Debug.Log("BBBB: failed to find Cube");
            return;
        }
        else
        {
            cube.AddComponent<VideoSurface>();
        }

        GameObject game = GameObject.Find("GameController");
        if (game != null)
        {
            monoProxy = game.GetComponent<MonoBehaviour>();
            audioSource = game.GetComponent<AudioSource>();
            monoProxy.StartCoroutine(CoAudioRender());
        }
    }

    // implement engine callbacks
    private void onJoinChannelSuccess(string channelName, uint uid, int elapsed)
    {
        Debug.Log("JoinChannelSuccessHandler: uid = " + uid);
        GameObject textVersionGameObject = GameObject.Find("VersionText");
        textVersionGameObject.GetComponent<Text>().text = "SDK Version : " + getSdkVersion();
    }

    // When a remote user joined, this delegate will be called. Typically
    // create a GameObject to render video on it
    private void onUserJoined(uint uid, int elapsed)
    {
        Debug.Log("onUserJoined: uid = " + uid + " elapsed = " + elapsed);
        // this is called in main thread

        // find a game object to render video stream from 'uid'
        GameObject go = GameObject.Find(uid.ToString());
        if (!ReferenceEquals(go, null))
        {
            return; // reuse
        }

        // create a GameObject and assign to this new user
        VideoSurface videoSurface = makeImageSurface(uid.ToString());
        if (!ReferenceEquals(videoSurface, null))
        {
            // configure videoSurface
            videoSurface.SetForUser(uid);
            videoSurface.SetEnable(true);
            videoSurface.SetVideoSurfaceType(AgoraVideoSurfaceType.RawImage);
            videoSurface.SetGameFps(30);
        }
    }

    public VideoSurface makePlaneSurface(string goName)
    {
        GameObject go = GameObject.CreatePrimitive(PrimitiveType.Plane);

        if (go == null)
        {
            return null;
        }
        go.name = goName;
        // set up transform
        go.transform.Rotate(-90.0f, 0.0f, 0.0f);
        float yPos = UnityEngine.Random.Range(3.0f, 5.0f);
        float xPos = UnityEngine.Random.Range(-2.0f, 2.0f);
        go.transform.position = new Vector3(xPos, yPos, 0f);
        go.transform.localScale = new Vector3(0.25f, 0.5f, .5f);

        // configure videoSurface
        VideoSurface videoSurface = go.AddComponent<VideoSurface>();
        return videoSurface;
    }

    private const float Offset = 100;
    public VideoSurface makeImageSurface(string goName)
    {
        GameObject go = new GameObject();

        if (go == null)
        {
            return null;
        }

        go.name = goName;

        // to be renderered onto
        go.AddComponent<RawImage>();

        // make the object draggable
        go.AddComponent<UIElementDragger>();
        GameObject canvas = GameObject.Find("Canvas");
        if (canvas != null)
        {
            go.transform.parent = canvas.transform;
        }
        // set up transform
        go.transform.Rotate(0f, 0.0f, 180.0f);
        float xPos = UnityEngine.Random.Range(Offset - Screen.width / 2f, Screen.width / 2f - Offset);
        float yPos = UnityEngine.Random.Range(Offset, Screen.height / 2f - Offset);
        go.transform.localPosition = new Vector3(xPos, yPos, 0f);
        go.transform.localScale = new Vector3(3f, 4f, 1f);

        // configure videoSurface
        VideoSurface videoSurface = go.AddComponent<VideoSurface>();
        return videoSurface;
    }
    // When remote user is offline, this delegate will be called. Typically
    // delete the GameObject for this user
    private void onUserOffline(uint uid, USER_OFFLINE_REASON reason)
    {
        // remove video stream
        Debug.Log("onUserOffline: uid = " + uid + " reason = " + reason);
        // this is called in main thread
        GameObject go = GameObject.Find(uid.ToString());
        if (!ReferenceEquals(go, null))
        {
            GameObject.Destroy(go);
        }
    }
}


问:
Create target directory outside project directory with sbt
The structure of my project is:

```<code>└───current-working-dir
    ├───my-project
        ├───src
</code>```

When I run sbt compile in current-working-dir where .sbt file looks like:

```<code>lazy val root = (project in file("my-project"))
  .settings(
    name := "my-project",
    settings,
    libraryDependencies ++= commonDependencies
  )
</code>```

then it generates target in the project directory:

```<code>└───current-working-dir
    ├───my-project
        ├───src
        ├───target
</code>```

Is it possible to make sbt to create target outside the project directory? For instance:

```<code>└───current-working-dir
    ├───my-project
        ├───src
    ├───target
</code>```

or

```<code>└───current-working-dir
    ├───my-project
        ├───src
    ├───my-project-compilation
        ├───target
</code>```

答:
target setting controls where files are generated. Here is an example how to change it

```<code>target := baseDirectory.value / "my-project-compilation" / "target"
</code>```

Body:
The structure of my project is:

└───current-working-dir
    ├───my-project
        ├───src

When I run sbt compile in current-working-dir where .sbt file looks like:

lazy val root = (project in file("my-project"))
  .settings(
    name := "my-project",
    settings,
    libraryDependencies ++= commonDependencies
  )

then it generates target in the project directory:

└───current-working-dir
    ├───my-project
        ├───src
        ├───target

Is it possible to make sbt to create target outside the project directory? For instance:

└───current-working-dir
    ├───my-project
        ├───src
    ├───target

or

└───current-working-dir
    ├───my-project
        ├───src
    ├───my-project-compilation
        ├───target

Body:
target setting controls where files are generated. Here is an example how to change it

target := baseDirectory.value / "my-project-compilation" / "target"


问:
Potentially long loop and declaring variables inside
I've recently written a dynamic program that calculates the similarity (modified edit distance) between two sequences of DNA strands (can be lengthy).

My code is like (not actual code since its an assignment):

```<code>while(!file.eof){
   string line;
   int sizeY, sizeX;

   //get first strand
   getline(db, line)

   //second strand
   getline(db, line)

   double ** ary = new double[sizeY];
   //loop to initialize array

   for(i to sizeY)
   {
      for(i to sizex)
      {
            pair<string,string> p,d;
            p.first = "A";
            p.second = "T";
            d.first = "G";
            d.second = "C";
            //do some comparisons
      }
   }
}
</code>```

The code above will take approximately 40 minutes to complete on a file with ~2400 lines.
If I move the pair p,d and assignments outside the nested for-loop and run the exact same file, it will complete in about ~1 minute.

I've read in other threads that the performance is pretty much the same. I've also compiled it with -O2.

Why is the code above so much slower?

答:
Generic answer:
  It would appear you're using gcc (that is to say g++); you can always do g++ -S [stuff] to see what G++ is doing to your code (assuming you can read assembly well enough to get by).

Specific answer:
  I'm surprised the difference is 40 times, but in your code, every time you finish a loop, it has to call create_new_pair twice (and I would have thought it would have had to do a little bit of cleanup to "free" the old pair, but given that its on the stack, I guess that's not as hard as I would have thought, or at least I'm not seeing it... reading code from Gcc used to be a lot easier than reading C++ code is at the moment)

ContentLicense: CC BY-SA 3.0

Body:
I've recently written a dynamic program that calculates the similarity (modified edit distance) between two sequences of DNA strands (can be lengthy).

My code is like (not actual code since its an assignment):

while(!file.eof){
   string line;
   int sizeY, sizeX;

   //get first strand
   getline(db, line)

   //second strand
   getline(db, line)

   double ** ary = new double[sizeY];
   //loop to initialize array

   for(i to sizeY)
   {
      for(i to sizex)
      {
            pair<string,string> p,d;
            p.first = "A";
            p.second = "T";
            d.first = "G";
            d.second = "C";
            //do some comparisons
      }
   }
}

The code above will take approximately 40 minutes to complete on a file with ~2400 lines.
If I move the pair p,d and assignments outside the nested for-loop and run the exact same file, it will complete in about ~1 minute.

I've read in other threads that the performance is pretty much the same. I've also compiled it with -O2.

Why is the code above so much slower?


问:
Errors when using DialogFlow "restore agent" API
We have suddenly started experiencing an error when using the DialogFlow "restore agent" API. The call is failing with the error:

400 com.google.apps.framework.request.BadRequestException: Invalid
  agent zip. Missing required json file agent.json

Oddly, it only seems to happen for newly created DialogFlow agents, but not for older/existing ones.  We are using this API so that we can programmatically create a custom agent using our own intents/entities.  This code has been working for about the past two years, with no changes on our side.  We are using the official DialogFlow client library for Python. We have been on version 0.2.0, and I tried updating to the latest (0.8.0) but there was no change.

I tried changing our code to include the agent.json file (by using the "export agent" API and getting the agent.json file from there).  In that case, I no longer get the above error and the restore appears to succeed. However, the agent then seems to be corrupt in some way.  When trying to click on any intent -- or various other operations in the DialogFlow console -- I get the error:

Failed to get Training Phrases Errorid=xxx

(where xxx seems to be a UUID that changes each time)

Trying to export the agent in that state also displays an error:

Error downloading agent

Occasionally, even including the agent.json as above, the restore will still fail but return the error:

500 Internal error encountered.

I appreciate any ideas on how we can get this working again. Thanks!

答:
Easy way to fix is to export one of the existing agents and copy it's agent.json and package.json into your current directory before uploading.

agent.json is now required by dialogflow.


问:
ref no longer reactive within a reactive array object
The following code works fine. When we change the language the text gets updated correctly thanks to the ref:

const mainNavigationLinks = computed(() => [
  { label: context.root.$t('navigationMenu.home') },
  { label: context.root.$t('navigationMenu.tickets') },
])

return {
  mainNavigationLinks,
}
```

<p>But what we would really like is to have the <code>mainNavigationLinks</code> as a <code>reactive</code> object, so we can add and remove items from the array and have Vue update the components accordingly with the correct translations by using the <code>ref</code> within the <code>array</code>. According to the Vue docs this should be possible</p>

<p>However, when we try the code below we see that the label is no longer reactive:</p>

<pre class="lang-js prettyprint-override"><code>const mainNavigation = reactive([
  { label: context.root.$t('navigationMenu.home') },
  { label: context.root.$t('navigationMenu.tickets') },
])

const mainNavigationLinks = computed(() => mainNavigation)
</code>```

What are we missing here to be able to add items to the array and still have it reactive? Thank you for your help.

答:
It seems like what you want is to have the array be reactive, but the items within the array be computed properties.

```<code>const mainNavigation = reactive([
  { label: computed(() => context.root.$t('navigationMenu.home')) },
  { label: computed(() => context.root.$t('navigationMenu.tickets')) },
])
</code>```

Alternatively, you might be able to get away with not using computed at all here, as long as each label property refers to a function that you have to call:

```<code>const mainNavigation = reactive([
  { label: () => context.root.$t('navigationMenu.home') },
  { label: () => context.root.$t('navigationMenu.tickets') },
])
</code>```

That's the main idea: each label needs to be evaluated at the time it is used, which is why it must be either a computed property (you benefit from caching) or a function. Your code doesn't work because you are getting the label translations immediately when you constructed the array.

Body:
The following code works fine. When we change the language the text gets updated correctly thanks to the ref:

const mainNavigationLinks = computed(() => [
  { label: context.root.$t('navigationMenu.home') },
  { label: context.root.$t('navigationMenu.tickets') },
])

return {
  mainNavigationLinks,
}

But what we would really like is to have the mainNavigationLinks as a reactive object, so we can add and remove items from the array and have Vue update the components accordingly with the correct translations by using the ref within the array. According to the Vue docs this should be possible

However, when we try the code below we see that the label is no longer reactive:

const mainNavigation = reactive([
  { label: context.root.$t('navigationMenu.home') },
  { label: context.root.$t('navigationMenu.tickets') },
])

const mainNavigationLinks = computed(() => mainNavigation)

What are we missing here to be able to add items to the array and still have it reactive? Thank you for your help.

Body:
It seems like what you want is to have the array be reactive, but the items within the array be computed properties.

const mainNavigation = reactive([
  { label: computed(() => context.root.$t('navigationMenu.home')) },
  { label: computed(() => context.root.$t('navigationMenu.tickets')) },
])

Alternatively, you might be able to get away with not using computed at all here, as long as each label property refers to a function that you have to call:

const mainNavigation = reactive([
  { label: () => context.root.$t('navigationMenu.home') },
  { label: () => context.root.$t('navigationMenu.tickets') },
])

That's the main idea: each label needs to be evaluated at the time it is used, which is why it must be either a computed property (you benefit from caching) or a function. Your code doesn't work because you are getting the label translations immediately when you constructed the array.


问:
Cannot load fixtures when testing Django
I hope not to make a fool of myself by re-asking this question, but I just can't figure out why my fixtures are not loaded when running test. I am using python 2.7.5 and Django 1.5.3.

I can load my fixtures with python manage.py testserver test_winning_answers, with a location of survey/fixtures/test_winning_answers.json.

```<code>Creating test database for alias 'default'...
Installed 13 object(s) from 1 fixture(s)
Validating models...

0 errors found
</code>```

My test class is doing the correct import:

```<code>from django.test import TestCase
class QuestionWinningAnswersTest(TestCase):

    fixtures = ['test_winning_answers.json']
    ...
</code>```

But when trying to run the test command, it cannot find them:

```<code>python manage.py test survey.QuestionWinningAnswersTest -v3
...
Checking '/django/mysite/survey/fixtures' for fixtures...
...
No json fixture 'initial_data' in '/django/mysite/survey/fixtures'.
...
Installed 0 object(s) from 0 fixture(s)
...
</code>```

I suspect I am missing something obvious, but cannot quite figure it out... any suggestion would be appreciated. Thanks!

答: In my case, the app was missing from INSTALLED_APPS configuration for Django to find the fixture file.</p>

Body:
I hope not to make a fool of myself by re-asking this question, but I just can't figure out why my fixtures are not loaded when running test. I am using python 2.7.5 and Django 1.5.3.

I can load my fixtures with python manage.py testserver test_winning_answers, with a location of survey/fixtures/test_winning_answers.json.

Creating test database for alias 'default'...
Installed 13 object(s) from 1 fixture(s)
Validating models...

0 errors found

My test class is doing the correct import:

from django.test import TestCase
class QuestionWinningAnswersTest(TestCase):

    fixtures = ['test_winning_answers.json']
    ...

But when trying to run the test command, it cannot find them:

python manage.py test survey.QuestionWinningAnswersTest -v3
...
Checking '/django/mysite/survey/fixtures' for fixtures...
...
No json fixture 'initial_data' in '/django/mysite/survey/fixtures'.
...
Installed 0 object(s) from 0 fixture(s)
...

I suspect I am missing something obvious, but cannot quite figure it out... any suggestion would be appreciated. Thanks!


问:
Canary vs. A/B release strategy
I was going through the different types of release strategy and was confused between the Canary and A/B strategy. Both of them seems to be similar.

Everywhere I read on Canary is "Allows to test deployment by releasing the new version to a small group of them." and on A/B is "An A/B testing strategy targets a specific group of customers."

Then where the differences lie between them and what are the use cases of both?

References: https://azure.microsoft.com/en-in/overview/kubernetes-deployment-strategy/

答:
A/B test's purpose is usually to see users' response (In a way, how much they like it) to a new UI, feature, etc. But you know that the new version works. So, you actually send randomly both versions of the application to all of them. It can be 50-50, 80-20, 90-10, anything. Sometimes the functionality is not even relevant. You might want to see which version attracts more clients and stuff like that.

Canary is more focused on how well works the new feature. Or if it actually works. It usually will be 90-10, 80-20, A >> B. Never 50-50, because if it goes wrong, you don't want half of your users to have a bad experience. So you are not positive if the new version is going to work as expected.

The most important difference (and this is what almost no one talks about) is that a canary testing has session affinity. So it doesn't send both versions to all users, but randomly sends some users to the new version, and keeps them on the same version.

Title: Canary vs. A/B release strategy