问:
iOS can't play uploaded audio: JS MediaRecorder -> Blob -> Django Server -> AWS s3 -> JS decodeAudioData --> "EncodingError: Decoding Failed"
Answer: shouldn't set content/mime type browser side with JS, should use native browser mimeType then convert server side (I used PyDub).

Question:
I am using Javascript MediaRecorder, Django, AWS s3 and Javascript Web Audio API to record audio files for users to share voice notes with one another. I've seen disbursed answers online about how to record and upload audio data and the issues with Safari/iOS but thought this could be a thread to bring it together and confront some of these issues.

Javascript:

```<code>mediaRecorder = new MediaRecorder(stream);

mediaRecorder.onstop = function (e) {
    var blob = new Blob(
        chunks,
        {
            type:"audio/mp3",
        }
    );
    var formdata = new FormData();
    formdata.append('recording', blob)
    var resp = await fetch(url, { // Your POST endpoint
        method: 'POST',
        mode: 'same-origin',
        headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRFToken': csrf_token,
        },
        body: formdata,
    })
}
</code>```

Django:

```<code>for k,file in request.FILES.items():
    sub_path = "recordings/audio.mp3"
    meta_data = {"ContentType":"audio/mp3"}
    s3.upload_fileobj(file, S3_BUCKET_NAME, sub_path,ExtraArgs=meta_data)
    ###then some code to save the s3 URL to my database for future retrieval
</code>```

Javascript:

```<code>var audio_context = new AudioContext();

document.addEventListener("#play-audio","click", function(e) {
    var url = "https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/audio.mp3"
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    request.onload = function () {
        audio_context.decodeAudioData(request.response, function (buffer) {
            playSound(buffer)
        });
    }
    request.send();
})
</code>```

Results in:
"EncodingError: Decoding Failed"

Note however that using the w3 schools demo mp3 url does play the recording:
https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/t-rex-roar.mp3

Specs:
PC (used to upload recoding): Windows 11, Chrome Version 98.0.4758.81 (Official Build) (64-bit)
Django: Version: 3.1.7
Mobile (used to play recording): iPhone X, iOS (Version 14.7.1)
Problematic url:  https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/audio.mp3
Working url: https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/t-rex-roar.mp3

(This is my first post so please forgive me if I haven't asked this question in the ideal way :) )

答:
When you upload the recorded Blob you set the type to 'audio/mp3'. But unless you use a custom library which patches the MediaRecorder the mimeType of the recording will be whatever the browser likes best.

As of now it's 'audio/opus' in Firefox and 'audio/webm' in Chrome.

If you define your Blob like this it should work.

```<code>var blob = new Blob(
    chunks,
    {
        type: mediaRecorder.mimeType
    }
);
</code>```

You would also have to change your server side code to not use 'audio/mp3' anymore.

Body:
Answer: shouldn't set content/mime type browser side with JS, should use native browser mimeType then convert server side (I used PyDub).

Question:
I am using Javascript MediaRecorder, Django, AWS s3 and Javascript Web Audio API to record audio files for users to share voice notes with one another. I've seen disbursed answers online about how to record and upload audio data and the issues with Safari/iOS but thought this could be a thread to bring it together and confront some of these issues.

Javascript:

mediaRecorder = new MediaRecorder(stream);

mediaRecorder.onstop = function (e) {
    var blob = new Blob(
        chunks,
        {
            type:"audio/mp3",
        }
    );
    var formdata = new FormData();
    formdata.append('recording', blob)
    var resp = await fetch(url, { // Your POST endpoint
        method: 'POST',
        mode: 'same-origin',
        headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRFToken': csrf_token,
        },
        body: formdata,
    })
}

Django:

for k,file in request.FILES.items():
    sub_path = "recordings/audio.mp3"
    meta_data = {"ContentType":"audio/mp3"}
    s3.upload_fileobj(file, S3_BUCKET_NAME, sub_path,ExtraArgs=meta_data)
    ###then some code to save the s3 URL to my database for future retrieval

Javascript:

var audio_context = new AudioContext();

document.addEventListener("#play-audio","click", function(e) {
    var url = "https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/audio.mp3"
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    request.onload = function () {
        audio_context.decodeAudioData(request.response, function (buffer) {
            playSound(buffer)
        });
    }
    request.send();
})

Results in:
"EncodingError: Decoding Failed"

Note however that using the w3 schools demo mp3 url does play the recording:
https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/t-rex-roar.mp3

Specs:
PC (used to upload recoding): Windows 11, Chrome Version 98.0.4758.81 (Official Build) (64-bit)
Django: Version: 3.1.7
Mobile (used to play recording): iPhone X, iOS (Version 14.7.1)
Problematic url:  https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/audio.mp3
Working url: https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/t-rex-roar.mp3

(This is my first post so please forgive me if I haven't asked this question in the ideal way :) )

Body:
When you upload the recorded Blob you set the type to 'audio/mp3'. But unless you use a custom library which patches the MediaRecorder the mimeType of the recording will be whatever the browser likes best.

As of now it's 'audio/opus' in Firefox and 'audio/webm' in Chrome.

If you define your Blob like this it should work.

var blob = new Blob(
    chunks,
    {
        type: mediaRecorder.mimeType
    }
);

You would also have to change your server side code to not use 'audio/mp3' anymore.


来源: stackexchange

问:
How can I get a document URL suitable for use by the .NET Sharepoint API?
I'm editing an Excel document hosted on Sharepoint that has a url like this:

https://{mysite}.sharepoint.com/:x:/g/personal/{name}/ETxQX66YJ...XOmOv1SYLDA?rtime=mqEhNZwV10g

I want to be able to read this programmatically using code like this:

```<code>Using clientContext = New ClientContext("https://{mysite}.sharepoint.com/")
  clientContext.Credentials = ...

  Dim file = clientContext.Web.GetFileByServerRelativeUrl("/:x:/g/personal/{name}/ETxQX66YJ...XOmOv1SYLDA?rtime=mqEhNZwV10g")

  Dim data = file.OpenBinaryStream()
  clientContext.Load(file)
  clientContext.ExecuteQuery()
  ...
End Using
</code>```

The connection works fine, but the ExecuteQuery fails with:

Microsoft.SharePoint.Client.ServerException: 'The file or folder name contains characters that are not permitted.  Please use a different name.'

I assume this is because of the colons in the relative url, and that there is another url endpoint that I'm supposed to use to access this file, but I can't figure out what it is.

What is that correct format or else how can I determine what it is?

答:
You can try using GetFileByUrl (new) instead of GetFileByServerRelativeUrl, to get a file from the shareable link like yours. It should resolve such links.

clientContext.Web.GetFileByUrl("https://{mysite}.sharepoint.com/:x:/g/personal/{name}/ETxQX66YJ...XOmOv1SYLDA?rtime=mqEhNZwV10g")
```

ContentLicense: CC BY-SA 4.0

Body:
I'm editing an Excel document hosted on Sharepoint that has a url like this:

https://{mysite}.sharepoint.com/:x:/g/personal/{name}/ETxQX66YJ...XOmOv1SYLDA?rtime=mqEhNZwV10g

I want to be able to read this programmatically using code like this:

Using clientContext = New ClientContext("https://{mysite}.sharepoint.com/")
  clientContext.Credentials = ...

  Dim file = clientContext.Web.GetFileByServerRelativeUrl("/:x:/g/personal/{name}/ETxQX66YJ...XOmOv1SYLDA?rtime=mqEhNZwV10g")

  Dim data = file.OpenBinaryStream()
  clientContext.Load(file)
  clientContext.ExecuteQuery()
  ...
End Using

The connection works fine, but the ExecuteQuery fails with:

Microsoft.SharePoint.Client.ServerException: 'The file or folder name contains characters that are not permitted.  Please use a different name.'

I assume this is because of the colons in the relative url, and that there is another url endpoint that I'm supposed to use to access this file, but I can't figure out what it is.

What is that correct format or else how can I determine what it is?


问:
Dealing with PHP 8.1 warning for undefined array key
We are upgrading to PHP 8.1. A new feature is that an undefined array key throws a warning.

Unfortunately this interferes with the ability to easily use associative arrays such as $_SESSION variables. I understand the virtues of predefining variables, and am not looking for a discussion on those virtues. The idea of the associative array is that you can add things easily to the session and everything not so assigned is evaluated as null. But now it also throws a warning; something has to be done to deal with that.

Here is an example of some code:

```<code>$_SESSION['is_condition'] = true;
</code>```

In another place in the code, the following occurs

```<code>if ($_SESSION['is_condition']) ...
</code>```

If this occurs in a context where the 'is_condition' session variable has not been defined, the desired result of evaluating its value as null is what we want. But now something else has to be done to deal with the possibility that it is undefined.

There are several approaches to dealing with this:

Pre-define all session variables having the value of null. Seems like it is not the spirit of associative arrays. Now every script has to invoke a lengthy set of code.

Use the null coalesce operator whenever the value of an associative array element is required. This is an ugly requirement to place many, many additional operators throughout the code base.

Alter our custom error handling functions to ignore the undefined array key error. A very bad idea to suppress warnings, and adds overhead.

None of these approaches is very desirable.

A theoretical way to solve this would be an array initialization statement that assigns all possible associative keys to null. I don't know of any such thing.

My question is whether there is some other approach that I am missing, such as a parameter that suppresses this specific warning only.

答:
My suggestion would be to write an abstraction over the session mechanism that deals with this problem. I'd opt for a class, but even a simple function could work:

function getValueFromSession(string $key, mixed $defaultValue = null) : mixed
{
   return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
}
```

This has the added benefit of allowing you to change your underlying session storage (e.g. to Redis) without having to change every single instance of session value access.

Body:
We are upgrading to PHP 8.1. A new feature is that an undefined array key throws a warning.

Unfortunately this interferes with the ability to easily use associative arrays such as $_SESSION variables. I understand the virtues of predefining variables, and am not looking for a discussion on those virtues. The idea of the associative array is that you can add things easily to the session and everything not so assigned is evaluated as null. But now it also throws a warning; something has to be done to deal with that.

Here is an example of some code:

$_SESSION['is_condition'] = true;

In another place in the code, the following occurs

if ($_SESSION['is_condition']) ...

If this occurs in a context where the 'is_condition' session variable has not been defined, the desired result of evaluating its value as null is what we want. But now something else has to be done to deal with the possibility that it is undefined.

There are several approaches to dealing with this:

Pre-define all session variables having the value of null. Seems like it is not the spirit of associative arrays. Now every script has to invoke a lengthy set of code.

Use the null coalesce operator whenever the value of an associative array element is required. This is an ugly requirement to place many, many additional operators throughout the code base.

Alter our custom error handling functions to ignore the undefined array key error. A very bad idea to suppress warnings, and adds overhead.

None of these approaches is very desirable.

A theoretical way to solve this would be an array initialization statement that assigns all possible associative keys to null. I don't know of any such thing.

My question is whether there is some other approach that I am missing, such as a parameter that suppresses this specific warning only.

Body:
My suggestion would be to write an abstraction over the session mechanism that deals with this problem. I'd opt for a class, but even a simple function could work:

function getValueFromSession(string $key, mixed $defaultValue = null) : mixed
{
   return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
}

This has the added benefit of allowing you to change your underlying session storage (e.g. to Redis) without having to change every single instance of session value access.


问:
JavaFX Spinner - How to align the text inside the spinner if the arrows are on left and right?
So I have this Spinner which is used for pagination. Its style class looks like below:

```<code>Spinner<Integer> spinner = new Spinner<>(1,20,1);
spinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
</code>```

So now the spinner appears with arrows on the left and right sides of the number. However, the text is aligned to the left of the spinner always. Say even if I have some width for the spinner (ex. 200px or something) the number displayed in the spinner is always next to the left arrow. I would like to know how to set it to the center of the Spinner.

This is what I tried in CSS:

```<code>.spinner > .text-field
{
    -fx-text-alignment: center;
}

.spinner
{
    -fx-text-alignment: center;
}

.spinner > text
{
    -fx-text-alignment: center;
}
</code>```

Nothing worked.

答:
You need

```<code>.spinner > .text-field
{
    -fx-alignment: center;
}
</code>```

The -fx-text-alignment property determines how multi-line text is aligned (i.e. the alignment of one line of text relative to another line). To align overall content, use -fx-alignment.

Body:
So I have this Spinner which is used for pagination. Its style class looks like below:

Spinner<Integer> spinner = new Spinner<>(1,20,1);
spinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);

So now the spinner appears with arrows on the left and right sides of the number. However, the text is aligned to the left of the spinner always. Say even if I have some width for the spinner (ex. 200px or something) the number displayed in the spinner is always next to the left arrow. I would like to know how to set it to the center of the Spinner.

This is what I tried in CSS:

.spinner > .text-field
{
    -fx-text-alignment: center;
}

.spinner
{
    -fx-text-alignment: center;
}

.spinner > text
{
    -fx-text-alignment: center;
}

Nothing worked.

Body:
You need

.spinner > .text-field
{
    -fx-alignment: center;
}

The -fx-text-alignment property determines how multi-line text is aligned (i.e. the alignment of one line of text relative to another line). To align overall content, use -fx-alignment.


问:
YII2 - In test, send email nowhere
I have a test and live environment.  In test, I don't ever want to send the mailer mails.  I have the mailer setup as a component in web.php like this

```<code>    'mailer' => [
        'class' => 'nickcv\mandrill\Mailer',
        'apikey' => 'xxxxxxxxxxxxxxxxxxxx',
        'useMandrillTemplates' => true,
        'templateLanguage' => nickcv\mandrill\Mailer::LANGUAGE_HANDLEBARS,
    ],
</code>```

Is there a way to set up the mailer component so it sends nowhere?

Thanks in advance.

答:
Actually, I think it would be nice to receive somewhere your test emails for debugging and QA.

Personally, in dev environment, I would recommend setting up and configuring mailhog

```<code>'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'viewPath' => '@common/mail',
            'transport' => [
                'class' => 'Swift_SmtpTransport',
                'host' => 'localhost',
                'port' => '1025',
            ],
        ],
</code>```

It is straightforward to install following the steps described here: https://github.com/mailhog/MailHog

You can then go to http://localhost:8025 and see your inbox

Title: YII2 - In test, send email nowhere

Body:
I have a test and live environment.  In test, I don't ever want to send the mailer mails.  I have the mailer setup as a component in web.php like this

    'mailer' => [
        'class' => 'nickcv\mandrill\Mailer',
        'apikey' => 'xxxxxxxxxxxxxxxxxxxx',
        'useMandrillTemplates' => true,
        'templateLanguage' => nickcv\mandrill\Mailer::LANGUAGE_HANDLEBARS,
    ],

Is there a way to set up the mailer component so it sends nowhere?

Thanks in advance.

Body:
Actually, I think it would be nice to receive somewhere your test emails for debugging and QA.

Personally, in dev environment, I would recommend setting up and configuring mailhog

'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'viewPath' => '@common/mail',
            'transport' => [
                'class' => 'Swift_SmtpTransport',
                'host' => 'localhost',
                'port' => '1025',
            ],
        ],

It is straightforward to install following the steps described here: https://github.com/mailhog/MailHog

You can then go to http://localhost:8025 and see your inbox


问:
jq: nesting objects according to two keys
Here my documents:

{
   "name":"name1",
   "oid1":"oid1-1",
   "oid2":"oid2-1"
}{
   "name":"name2",
   "oid1":"oid1-2",
   "oid2":"oid2-2"
}
```
<p>By other side:</p>
<pre class="lang-json prettyprint-override"><code>{
  "id": "id1",
  "info": "info1",
  "oid1":"oid1-1",
  "oid2":"oid2-1"
}
{
  "id": "id2",
  "info": "info2",
  "oid1":"oid1-1",
  "oid2":"oid2-1"
}
{
  "id": "id3",
  "info": "info3",
  "oid1":"oid1-2",
  "oid2":"oid2-2"
}
</code>```

I need to nest just above documents into first ones:

{
   "name":"name1",
   "oid1":"oid1-1",
   "oid2":"oid2-1",
   "ids":[
      {
         "id":"id1",
         "info":"info1"
      },
      {
         "id":"id2",
         "info":"info2"
      }
   ]
}{
   "name":"name2",
   "oid1":"oid1-2",
   "oid2":"oid2-2",
   "ids":[
      {
         "id":"id3",
         "info":"info3"
      }
   ]
}
```

So, I need to nest into first documents, which ones parent.oid1 == nest.oid1 && parent.oid2 == nest.oid2.

I've not been to get anything reasonable.

Any ideas?

答:
If "my documents" is stored in a file called mine.json and the "other side" is the contents of a file others.json, then --slurpfile the others and add them based on a select:

jq --slurpfile others others.json '
  . as $mine
  | . + {ids: ($others | map(
    select(.oid1 == $mine.oid1 and .oid2 == $mine.oid2)
    | {id, info}
  ))}
' mine.json
```
<pre class="lang-json prettyprint-override"><code>{
  "name": "name1",
  "oid1": "oid1-1",
  "oid2": "oid2-1",
  "ids": [
    {
      "id": "id1",
      "info": "info1"
    },
    {
      "id": "id2",
      "info": "info2"
    }
  ]
}
{
  "name": "name2",
  "oid1": "oid1-2",
  "oid2": "oid2-2",
  "ids": [
    {
      "id": "id3",
      "info": "info3"
    }
  ]
}
</code>```

Demo (using an object with fields mine and others instead of files)

Body:
Here my documents:

{
   "name":"name1",
   "oid1":"oid1-1",
   "oid2":"oid2-1"
}{
   "name":"name2",
   "oid1":"oid1-2",
   "oid2":"oid2-2"
}

By other side:

{
  "id": "id1",
  "info": "info1",
  "oid1":"oid1-1",
  "oid2":"oid2-1"
}
{
  "id": "id2",
  "info": "info2",
  "oid1":"oid1-1",
  "oid2":"oid2-1"
}
{
  "id": "id3",
  "info": "info3",
  "oid1":"oid1-2",
  "oid2":"oid2-2"
}

I need to nest just above documents into first ones:

{
   "name":"name1",
   "oid1":"oid1-1",
   "oid2":"oid2-1",
   "ids":[
      {
         "id":"id1",
         "info":"info1"
      },
      {
         "id":"id2",
         "info":"info2"
      }
   ]
}{
   "name":"name2",
   "oid1":"oid1-2",
   "oid2":"oid2-2",
   "ids":[
      {
         "id":"id3",
         "info":"info3"
      }
   ]
}

So, I need to nest into first documents, which ones parent.oid1 == nest.oid1 && parent.oid2 == nest.oid2.

I've not been to get anything reasonable.

Any ideas?

Body:
If "my documents" is stored in a file called mine.json and the "other side" is the contents of a file others.json, then --slurpfile the others and add them based on a select:

jq --slurpfile others others.json '
  . as $mine
  | . + {ids: ($others | map(
    select(.oid1 == $mine.oid1 and .oid2 == $mine.oid2)
    | {id, info}
  ))}
' mine.json

{
  "name": "name1",
  "oid1": "oid1-1",
  "oid2": "oid2-1",
  "ids": [
    {
      "id": "id1",
      "info": "info1"
    },
    {
      "id": "id2",
      "info": "info2"
    }
  ]
}
{
  "name": "name2",
  "oid1": "oid1-2",
  "oid2": "oid2-2",
  "ids": [
    {
      "id": "id3",
      "info": "info3"
    }
  ]
}

Demo (using an object with fields mine and others instead of files)


问:
Having trouble identifying matching characters in two strings
I am able to iterate through two given strings of the same length.

I am supposed to output a green emoji if the letters in guess_word are are also contained and in the correct position of the secret_word. If a letter in the guess_word is in the secret_word but it's in the wrong position, then I should have an output of a yellow emoji.

This is where my issue is. The yellow emoji is not showing up in my output, only the green and white boxes. I have a picture below of what it should look like in the output.

I have to stick to two different functions because this is what my homework is asking me to do.

```<code>def contains_char(any_length: str, single_character: str) -> bool:
    """Loop iterates through each character in string to find matching character."""
    assert len(single_character) == 1
    if single_character in any_length:
        return True
    else:
        return False

def emojified(guess_word: str, secret_word: str) -> str:
    """A way to match letters to its corresponding emoji color output. """
    assert len(guess_word) == len(secret_word)
    WHITE_BOX: str = "\U00002B1C"
    GREEN_BOX: str = "\U0001F7E9"
    YELLOW_BOX: str = "\U0001F7E8"
    emoji_color: str = ""
    i: int = 0
    while i < len(secret_word):
        i += 1
        if guess_word[0] in secret_word[0]:
            emoji_color += GREEN_BOX
            i += 1
        else:
            emoji_color += WHITE_BOX
            i += 1
        if contains_char is True:
            emoji_color += YELLOW_BOX
        else:
            emoji_color += WHITE_BOX
    return emoji_color
</code>```

Output:

答:
Without changing too much, here's how I would write your while-loop:</p>
```<code>while i < len(secret_word):
    guess_char = guess_word[i]
    secret_char = secret_word[i]

    current_emoji = WHITE_BOX # By default, we display a white box for this position

    if contains_char(secret_word, guess_char):
        current_emoji = YELLOW_BOX # guess_char is in secret_word. guess_char may even be in the correct position, but we don't care about that yet.

    if guess_char == secret_char:
        current_emoji = GREEN_BOX # guess_char is in the correct position.

    emoji_color += current_emoji
    i += 1
return emoji_color
</code>```

Body:
I am able to iterate through two given strings of the same length.

I am supposed to output a green emoji if the letters in guess_word are are also contained and in the correct position of the secret_word. If a letter in the guess_word is in the secret_word but it's in the wrong position, then I should have an output of a yellow emoji.

This is where my issue is. The yellow emoji is not showing up in my output, only the green and white boxes. I have a picture below of what it should look like in the output.

I have to stick to two different functions because this is what my homework is asking me to do.

def contains_char(any_length: str, single_character: str) -> bool:
    """Loop iterates through each character in string to find matching character."""
    assert len(single_character) == 1
    if single_character in any_length:
        return True
    else:
        return False

def emojified(guess_word: str, secret_word: str) -> str:
    """A way to match letters to its corresponding emoji color output. """
    assert len(guess_word) == len(secret_word)
    WHITE_BOX: str = "\U00002B1C"
    GREEN_BOX: str = "\U0001F7E9"
    YELLOW_BOX: str = "\U0001F7E8"
    emoji_color: str = ""
    i: int = 0
    while i < len(secret_word):
        i += 1
        if guess_word[0] in secret_word[0]:
            emoji_color += GREEN_BOX
            i += 1
        else:
            emoji_color += WHITE_BOX
            i += 1
        if contains_char is True:
            emoji_color += YELLOW_BOX
        else:
            emoji_color += WHITE_BOX
    return emoji_color

Output:

Body:
Without changing too much, here's how I would write your while-loop:

while i < len(secret_word):
    guess_char = guess_word[i]
    secret_char = secret_word[i]

    current_emoji = WHITE_BOX # By default, we display a white box for this position

    if contains_char(secret_word, guess_char):
        current_emoji = YELLOW_BOX # guess_char is in secret_word. guess_char may even be in the correct position, but we don't care about that yet.

    if guess_char == secret_char:
        current_emoji = GREEN_BOX # guess_char is in the correct position.

    emoji_color += current_emoji
    i += 1
return emoji_color


问:
what to use to get data from the gridpanel?
What is the difference between itemdblclick and rowdblclick?  Both of these methods seem to work well for gridpanel. Which is preferable for getting data from a row?</p>

答:
As you mention itemdblclick this seems to be the classic framework.

```<code>itemdblclick ( grid, record, item, index, e, eOpts )
rowdblclick ( grid, record, element, rowIndex, e, eOpts )
</code>```

itemdblclick and rowdblclick are fired from different sources, but otherwise both are equally good to use. For both you receive the record, which holds the data and you receive an index, if you need it.

For me it is more about, what you want to tell another programmer, what you are listening for. And that's where you can differ between cell and row.

The record will be the same for both.

Body:
As you mention itemdblclick this seems to be the classic framework.

itemdblclick ( grid, record, item, index, e, eOpts )
rowdblclick ( grid, record, element, rowIndex, e, eOpts )

itemdblclick and rowdblclick are fired from different sources, but otherwise both are equally good to use. For both you receive the record, which holds the data and you receive an index, if you need it.

For me it is more about, what you want to tell another programmer, what you are listening for. And that's where you can differ between cell and row.

The record will be the same for both.


问:
how to create custom intersected container from 2 distinct container types
Using the following containers:

```<code>std::vector<std::pair<std::string, int>> keyVals = {
    {"A", 1}, {"B", 2},  {"C", 3}
};

std::vector<std::string> keys = {
    "A", "B", "C"
};
</code>```

I need to construct a sorted output container

std::set<std::tuple<std::string, int, int>>

using the std::set_intersection between keyVals and keys.

These types use a common field (in my case a string) this is also used for pre-sorting these vectors via the default std::less - however no need in the above example as they are already sorted.

I need help to create a sorted container C that is not just a simple copy of elements from A to the output over the intersection range.

Instead I need to be able to construct each output element C - in my case a std::tuple<std::string, int, int> (where the first entry in the tuple is the common link string field and the other 2 int are some global fields.

To illustrate the problem I created a coliru live demo where I commented out the broken code - I don't know how to invoke a custom constructor for each iteration - please help.

```<code>#include <vector>
#include <variant>
#include <memory>
#include <iostream>
#include <algorithm>

// Helper to get Lambda with multiple signatures in place
// template deduction guide is a C++17 feature!
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
// this line is necessary for c++17 - not required for c++20
template<class... Ts> overload(Ts...) -> overload<Ts...>;

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
    for (auto& el : vec) {
        os << el.first << ' ';
    }
    return os;
}

// if c++17 is not available, you have to write a functor/function
// with both signatures
int main()
{
    std::vector<std::pair<std::string, int>> keyVals = {
        {"A", 1}, {"B", 2},  {"C", 3}
    };

    std::vector<std::string> keys = {
        "A", "B", "C"
    };

    // std::set_intersection results can only be of the first iterator type
    std::vector<std::pair<std::string, int>> intersection;

    // this works
    std::set_intersection(
        keyVals.begin(), keyVals.end(),
        keys.begin(), keys.end(),
        std::back_inserter(intersection),
        overload {
            [](const std::pair<std::string, int>& lhs, const std::string& rhs) {
                return lhs.first < rhs;
            },
            [](const std::string& lhs, const std::pair<std::string, int>& rhs) {
                return lhs < rhs.first;
            }
        }
    );

    std::cout << intersection << std::endl;

#if 0
    // std::set_intersection results can only be of the first iterator type
    std::vector<std::tuple<std::string, int, int>> broken_intersection;

    // this does not work as no match for 'operator=' *__result = *__first1;
    std::set_intersection(
        keyVals.begin(), keyVals.end(),
        keys.begin(), keys.end(),
        std::back_inserter(broken_intersection),  // help here - I need to be able to
        overload {
            [](const std::pair<std::string, int>& lhs, const std::string& rhs) {
                return lhs.first < rhs;
            },
            [](const std::string& lhs, const std::pair<std::string, int>& rhs) {
                return lhs < rhs.first;
            }
        }
    );

    std::cout << broken_intersection << std::endl;
#endif
}
</code>```

答:
The problem is, as already noted, the different types of the data.

All input and output containers habe a different type.

And with that, 2 main operations in std::set_difference need to be expressed.

The comparison of the dereferenced input iterators of different type

The assignment of a rvalue from the dereferenced input to the dereferenced output iterator.

Problem 1 can be easily solved with a Functor, for which we will create 2 function call operators with the 2 needed signatures. This will allow for comparison in both directions.

Starting with C++14 you may also use a generic Lambda:

```<code>auto cmp = [](auto lhs, auto rhs) { return lhs.mCommonField < rhs.mCommonField; };
</code>```

But then you need some common fields in both vectors.

The same approach would be possible with a Functor having a templated call operator:

```<code>struct Comparator
{
    template<typename T, typename U>
    bool operator()(T const& lhs, U const& rhs) const {
        return lhs.commonField < rhs.commonField;
    }
};
</code>```

Also here you need a common field. And they must have the same name. Maybe this will not fit here.

Or, we could create a wrapper for a Common Field:

```<code>struct Common {
    std::string const& commonField;
    Common(StructA const& sa) : commonField{sa.commonField} {};
    Common(StructB const& sb) : commonField{sb.commonField} {};
};
</code>```

Here the common field must just be of the same type.

Many possibilities

For problem 2 we need a small wrapper. Either for the first input iterator or the output iterator. The wrapper needs to have iterator functionality and a dereferencing operator that returns a Tuple, so that we can assign this Tuple to the resulting vector of Tuples.

So we will create a very small custom iterator, with only the minimumm functions needed by std::set_intersection

Construction

Dereferencing

Pre Incrementing

Comparison for not equal

Within the iterator we will use a simple pointer to a Pair as the real iterator. The constructor can get a pointer to the Pairs in the first vector with the std::vector data function. That is very convenient.

The dereferencing operator does the trick. It will not return a Pair, but construct a Tuple and return that. So, this is the conversion from the Pair to a Tuple.

Putting this altogether may lead to one of many potential solutions:

```<code>#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <tuple>
#include <utility>

using Key = std::string;
using Value = int;
using Keys = std::vector<Key>;
using Pair = std::pair<Key, Value>;
using KeyVals = std::vector<Pair>;
using Tuple = std::tuple<Key, Value, Value>;
using Tuples = std::vector<Tuple>;

std::ostream& operator<<(std::ostream& os, const Tuples& t) {
    for (auto& el : t)  os << std::get<0>(el) << ' ';
    return os;
}

struct Iterator {
    using iterator_category = std::output_iterator_tag;
    using difference_type = std::ptrdiff_t;
    using value_type = Tuple;
    using pointer = Tuple*;
    using reference = Tuple&;

    Pair* iter; // The internal iterator. Just a pointer
    Iterator(Pair* kv) { iter = kv; }

    Tuple operator *() const { return Tuple{ iter->first,0,0}; }
    Iterator operator ++() { ++iter; return *this; }
    bool operator !=(const Iterator& other) { return iter != other.iter; }
};

struct Comp {
    bool operator ()(const Tuple& lhs, const std::string& rhs) { return std::get<0>(lhs) < rhs; }
    bool operator ()(const std::string& lhs, const Tuple& rhs) { return lhs < std::get<0>(rhs) ; }
};
int main()
{
    KeyVals keyVals = { {"A", 1}, {"B", 2},  {"C", 3} };
    Keys keys = { "A", "B", "C" };

    // Resulting vector
    Tuples tupleResult{};

    // Create Iterators to KeyVals
    Iterator begin(keyVals.data());
    Iterator end(keyVals.data() + keyVals.size());

    // Do the intersection
    std::set_intersection(begin, end, keys.begin(), keys.end(), std::back_inserter(tupleResult), Comp());

    // Show result
    std::cout << tupleResult << '\n';
}
</code>```

Looks a little bit clumsy

On a 2nd thought, you could convert both input vectors to the needed output type using std::transform. But this will cost additional space and time.

Anyway, please see the next potential solution:

```<code>#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <utility>
#include <tuple>

using Key = std::string;
using Value = int;
using Keys = std::vector<Key>;
using Pair = std::pair<Key, Value>;
using KeyVals = std::vector<Pair>;
using Tuple = std::tuple<Key, Value, Value>;
using Tuples = std::vector<Tuple>;

std::ostream& operator<<(std::ostream& os, const Tuples& t) {
    for (auto& el : t)  os << std::get<0>(el) << ' ';
    return os;
}

int main()
{
    KeyVals keyVals = { {"A", 1}, {"B", 2},  {"C", 3} };

    Keys keys = { "A", "B", "C" };

    // Convert to same type
    Tuples tupleKeyVals{}, tupleKeys{};

    std::transform(keyVals.begin(), keyVals.end(), std::back_inserter(tupleKeyVals), [](const Pair& p) { return Tuple{ p.first, p.second, 0 }; });
    std::transform(keys.begin(), keys.end(), std::back_inserter(tupleKeys), [](const std::string& s) { return Tuple{ s, 0, 0 }; });

    // Resulting vector
    Tuples tupleResult{};

    // Build intersection based on first tuple element
    std::set_intersection(tupleKeyVals.begin(), tupleKeyVals.end(), tupleKeys.begin(), tupleKeys.end(), std::back_inserter(tupleResult),
        [](const Tuple& t1, const Tuple& t2) { return std::get<0>(t1) < std::get<0>(t2); });

    std::cout << tupleResult << '\n';
}
</code>```

This looks a little bit cleaner. But disadvantage is much more memory consumption and longer operation time.

Last but not least, we could implement an own set_intersetcion  function, which is quite simple.

```<code>#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <utility>
#include <tuple>

using Key = std::string;
using Value = int;
using Keys = std::vector<Key>;
using Pair = std::pair<Key, Value>;
using KeyVals = std::vector<Pair>;
using Tuple = std::tuple<Key, Value, Value>;
using Tuples = std::vector<Tuple>;

std::ostream& operator<<(std::ostream& os, const Tuples& t) {
    for (auto& el : t)  os << std::get<0>(el) << ' ';
    return os;
}

// Specialized intersection function
Tuples set_intersection(KeyVals& kv, Keys& k) {
    Tuples result{};
    KeyVals::iterator iterKeyVal = kv.begin();
    Keys::iterator iterKey = k.begin();

    while (iterKeyVal != kv.end() and iterKey != k.end()) {
        if (iterKeyVal->first < *iterKey)
            ++iterKeyVal;
        else {
            if (not(*iterKey < iterKeyVal->first))
                result.emplace_back(Tuple{ (iterKeyVal++)->first ,0,0 });
            ++iterKey;
        }
    }
    return result;
}

int main()
{
    // Input
    KeyVals keyVals = { {"A", 1}, {"B", 2},  {"C", 3} };
    Keys keys = { "A", "B", "C" };

    // Resulting vector
    Tuples tupleResult = set_intersection(keyVals, keys);

    // Show result
    std::cout << tupleResult << '\n';
}
</code>```

But in the end you need to decide based on other requirements or constraints.

Body:
Using the following containers:

std::vector<std::pair<std::string, int>> keyVals = {
    {"A", 1}, {"B", 2},  {"C", 3}
};

std::vector<std::string> keys = {
    "A", "B", "C"
};

I need to construct a sorted output container

std::set<std::tuple<std::string, int, int>>

using the std::set_intersection between keyVals and keys.

These types use a common field (in my case a string) this is also used for pre-sorting these vectors via the default std::less - however no need in the above example as they are already sorted.

I need help to create a sorted container C that is not just a simple copy of elements from A to the output over the intersection range.

Instead I need to be able to construct each output element C - in my case a std::tuple<std::string, int, int> (where the first entry in the tuple is the common link string field and the other 2 int are some global fields.

To illustrate the problem I created a coliru live demo where I commented out the broken code - I don't know how to invoke a custom constructor for each iteration - please help.

#include <vector>
#include <variant>
#include <memory>
#include <iostream>
#include <algorithm>

// Helper to get Lambda with multiple signatures in place
// template deduction guide is a C++17 feature!
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
// this line is necessary for c++17 - not required for c++20
template<class... Ts> overload(Ts...) -> overload<Ts...>;

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
    for (auto& el : vec) {
        os << el.first << ' ';
    }
    return os;
}

// if c++17 is not available, you have to write a functor/function
// with both signatures
int main()
{
    std::vector<std::pair<std::string, int>> keyVals = {
        {"A", 1}, {"B", 2},  {"C", 3}
    };

    std::vector<std::string> keys = {
        "A", "B", "C"
    };

    // std::set_intersection results can only be of the first iterator type
    std::vector<std::pair<std::string, int>> intersection;

    // this works
    std::set_intersection(
        keyVals.begin(), keyVals.end(),
        keys.begin(), keys.end(),
        std::back_inserter(intersection),
        overload {
            [](const std::pair<std::string, int>& lhs, const std::string& rhs) {
                return lhs.first < rhs;
            },
            [](const std::string& lhs, const std::pair<std::string, int>& rhs) {
                return lhs < rhs.first;
            }
        }
    );

    std::cout << intersection << std::endl;

#if 0
    // std::set_intersection results can only be of the first iterator type
    std::vector<std::tuple<std::string, int, int>> broken_intersection;

    // this does not work as no match for 'operator=' *__result = *__first1;
    std::set_intersection(
        keyVals.begin(), keyVals.end(),
        keys.begin(), keys.end(),
        std::back_inserter(broken_intersection),  // help here - I need to be able to
        overload {
            [](const std::pair<std::string, int>& lhs, const std::string& rhs) {
                return lhs.first < rhs;
            },
            [](const std::string& lhs, const std::pair<std::string, int>& rhs) {
                return lhs < rhs.first;
            }
        }
    );

    std::cout << broken_intersection << std::endl;
#endif
}

Body:
The problem is, as already noted, the different types of the data.

All input and output containers habe a different type.

And with that, 2 main operations in std::set_difference need to be expressed.

The comparison of the dereferenced input iterators of different type

The assignment of a rvalue from the dereferenced input to the dereferenced output iterator.

Problem 1 can be easily solved with a Functor, for which we will create 2 function call operators with the 2 needed signatures. This will allow for comparison in both directions.

Starting with C++14 you may also use a generic Lambda:

auto cmp = [](auto lhs, auto rhs) { return lhs.mCommonField < rhs.mCommonField; };

But then you need some common fields in both vectors.

The same approach would be possible with a Functor having a templated call operator:

struct Comparator
{
    template<typename T, typename U>
    bool operator()(T const& lhs, U const& rhs) const {
        return lhs.commonField < rhs.commonField;
    }
};

Also here you need a common field. And they must have the same name. Maybe this will not fit here.

Or, we could create a wrapper for a Common Field:

struct Common {
    std::string const& commonField;
    Common(StructA const& sa) : commonField{sa.commonField} {};
    Common(StructB const& sb) : commonField{sb.commonField} {};
};

Here the common field must just be of the same type.

Many possibilities

For problem 2 we need a small wrapper. Either for the first input iterator or the output iterator. The wrapper needs to have iterator functionality and a dereferencing operator that returns a Tuple, so that we can assign this Tuple to the resulting vector of Tuples.

So we will create a very small custom iterator, with only the minimumm functions needed by std::set_intersection

Construction

Dereferencing

Pre Incrementing

Comparison for not equal

Within the iterator we will use a simple pointer to a Pair as the real iterator. The constructor can get a pointer to the Pairs in the first vector with the std::vector data function. That is very convenient.

The dereferencing operator does the trick. It will not return a Pair, but construct a Tuple and return that. So, this is the conversion from the Pair to a Tuple.

Putting this altogether may lead to one of many potential solutions:

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <tuple>
#include <utility>

using Key = std::string;
using Value = int;
using Keys = std::vector<Key>;
using Pair = std::pair<Key, Value>;
using KeyVals = std::vector<Pair>;
using Tuple = std::tuple<Key, Value, Value>;
using Tuples = std::vector<Tuple>;

std::ostream& operator<<(std::ostream& os, const Tuples& t) {
    for (auto& el : t)  os << std::get<0>(el) << ' ';
    return os;
}

struct Iterator {
    using iterator_category = std::output_iterator_tag;
    using difference_type = std::ptrdiff_t;
    using value_type = Tuple;
    using pointer = Tuple*;
    using reference = Tuple&;

    Pair* iter; // The internal iterator. Just a pointer
    Iterator(Pair* kv) { iter = kv; }

    Tuple operator *() const { return Tuple{ iter->first,0,0}; }
    Iterator operator ++() { ++iter; return *this; }
    bool operator !=(const Iterator& other) { return iter != other.iter; }
};

struct Comp {
    bool operator ()(const Tuple& lhs, const std::string& rhs) { return std::get<0>(lhs) < rhs; }
    bool operator ()(const std::string& lhs, const Tuple& rhs) { return lhs < std::get<0>(rhs) ; }
};
int main()
{
    KeyVals keyVals = { {"A", 1}, {"B", 2},  {"C", 3} };
    Keys keys = { "A", "B", "C" };

    // Resulting vector
    Tuples tupleResult{};

    // Create Iterators to KeyVals
    Iterator begin(keyVals.data());
    Iterator end(keyVals.data() + keyVals.size());

    // Do the intersection
    std::set_intersection(begin, end, keys.begin(), keys.end(), std::back_inserter(tupleResult), Comp());

    // Show result
    std::cout << tupleResult << '\n';
}

Looks a little bit clumsy

On a 2nd thought, you could convert both input vectors to the needed output type using std::transform. But this will cost additional space and time.

Anyway, please see the next potential solution:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <utility>
#include <tuple>

using Key = std::string;
using Value = int;
using Keys = std::vector<Key>;
using Pair = std::pair<Key, Value>;
using KeyVals = std::vector<Pair>;
using Tuple = std::tuple<Key, Value, Value>;
using Tuples = std::vector<Tuple>;

std::ostream& operator<<(std::ostream& os, const Tuples& t) {
    for (auto& el : t)  os << std::get<0>(el) << ' ';
    return os;
}

int main()
{
    KeyVals keyVals = { {"A", 1}, {"B", 2},  {"C", 3} };

    Keys keys = { "A", "B", "C" };

    // Convert to same type
    Tuples tupleKeyVals{}, tupleKeys{};

    std::transform(keyVals.begin(), keyVals.end(), std::back_inserter(tupleKeyVals), [](const Pair& p) { return Tuple{ p.first, p.second, 0 }; });
    std::transform(keys.begin(), keys.end(), std::back_inserter(tupleKeys), [](const std::string& s) { return Tuple{ s, 0, 0 }; });

    // Resulting vector
    Tuples tupleResult{};

    // Build intersection based on first tuple element
    std::set_intersection(tupleKeyVals.begin(), tupleKeyVals.end(), tupleKeys.begin(), tupleKeys.end(), std::back_inserter(tupleResult),
        [](const Tuple& t1, const Tuple& t2) { return std::get<0>(t1) < std::get<0>(t2); });

    std::cout << tupleResult << '\n';
}

This looks a little bit cleaner. But disadvantage is much more memory consumption and longer operation time.

Last but not least, we could implement an own set_intersetcion  function, which is quite simple.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <utility>
#include <tuple>

using Key = std::string;
using Value = int;
using Keys = std::vector<Key>;
using Pair = std::pair<Key, Value>;
using KeyVals = std::vector<Pair>;
using Tuple = std::tuple<Key, Value, Value>;
using Tuples = std::vector<Tuple>;

std::ostream& operator<<(std::ostream& os, const Tuples& t) {
    for (auto& el : t)  os << std::get<0>(el) << ' ';
    return os;
}

// Specialized intersection function
Tuples set_intersection(KeyVals& kv, Keys& k) {
    Tuples result{};
    KeyVals::iterator iterKeyVal = kv.begin();
    Keys::iterator iterKey = k.begin();

    while (iterKeyVal != kv.end() and iterKey != k.end()) {
        if (iterKeyVal->first < *iterKey)
            ++iterKeyVal;
        else {
            if (not(*iterKey < iterKeyVal->first))
                result.emplace_back(Tuple{ (iterKeyVal++)->first ,0,0 });
            ++iterKey;
        }
    }
    return result;
}

int main()
{
    // Input
    KeyVals keyVals = { {"A", 1}, {"B", 2},  {"C", 3} };
    Keys keys = { "A", "B", "C" };

    // Resulting vector
    Tuples tupleResult = set_intersection(keyVals, keys);

    // Show result
    std::cout << tupleResult << '\n';
}

But in the end you need to decide based on other requirements or constraints.


问:
How to properly use Hilt with ViewModel using @HiltViewModel?
I have a problem with Hilt and ViewModel. I'm getting RunTimeException:

```<code>MainViewModel> has no zero argument constructor
</code>```

I spent hours to find what is wrong...

Here are sources from my code:

AppModule:

```<code>@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun provideCurrencyApi(): CurrencyApi = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(CurrencyApi::class.java)

    @Singleton
    @Provides
    fun provideMainRepository(api: CurrencyApi): MainRepository = DefaultMainRepository(api)

    @Singleton
    @Provides
    fun provideDispatchers(): DispatcherProvider = object : DispatcherProvider {
        override val main: CoroutineDispatcher
            get() = Dispatchers.Main
        override val io: CoroutineDispatcher
            get() = Dispatchers.IO
        override val default: CoroutineDispatcher
            get() = Dispatchers.Default
        override val unconfined: CoroutineDispatcher
            get() = Dispatchers.Unconfined
    }
}
</code>```

MainActivity:

```<code>@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private val viewModel: MainViewModel by viewModels()
</code>```

MainViewModel:

```<code>@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: MainRepository,
    private val dispatchers: DispatcherProvider
) : ViewModel() {
</code>```

MainRepository

```<code>class DefaultMainRepository @Inject constructor(
    private val api: CurrencyApi
) : MainRepository {
</code>```

Hee are Gradle dependencies:

```<code>dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.9.0'

    implementation "androidx.activity:activity-ktx:1.4.0"

    implementation 'com.google.dagger:hilt-android:2.40.5'
    kapt 'com.google.dagger:hilt-compiler:2.40.5'
    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
    kapt'androidx.hilt:hilt-compiler:1.0.0'

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.4.0'

    androidTestImplementation  'com.google.dagger:hilt-android-testing:2.40.5'
    kaptAndroidTest 'com.google.dagger:hilt-compiler:2.40.5'
    testImplementation 'com.google.dagger:hilt-android-testing:2.40.5'
    kaptTest 'com.google.dagger:hilt-compiler:2.40.5'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
</code>```

Application:

```<code>@HiltAndroidApp
class CurrencyApplication: Application()
</code>```

Manifest:

```<code>    <application
        android:name=".CurrencyApplication"
</code>```

Im trying to find solution everywhere like here: possible reason

I will be grateful for any help

答:
first of all, check anotationProcessor for hilt to be able generate correct binding, so go to app.gradle and check these dependency existence:</p>
```<code>dependencies {

    implementation 'com.google.dagger:hilt-android:2.30-alpha'
    kapt 'com.google.dagger:hilt-android-compiler:2.30-alpha'

    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
    kapt'androidx.hilt:hilt-compiler:1.0.0-alpha02'

...
}
</code>```

Body:
I have a problem with Hilt and ViewModel. I'm getting RunTimeException:

MainViewModel> has no zero argument constructor

I spent hours to find what is wrong...

Here are sources from my code:

AppModule:

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun provideCurrencyApi(): CurrencyApi = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(CurrencyApi::class.java)

    @Singleton
    @Provides
    fun provideMainRepository(api: CurrencyApi): MainRepository = DefaultMainRepository(api)

    @Singleton
    @Provides
    fun provideDispatchers(): DispatcherProvider = object : DispatcherProvider {
        override val main: CoroutineDispatcher
            get() = Dispatchers.Main
        override val io: CoroutineDispatcher
            get() = Dispatchers.IO
        override val default: CoroutineDispatcher
            get() = Dispatchers.Default
        override val unconfined: CoroutineDispatcher
            get() = Dispatchers.Unconfined
    }
}

MainActivity:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private val viewModel: MainViewModel by viewModels()

MainViewModel:

@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: MainRepository,
    private val dispatchers: DispatcherProvider
) : ViewModel() {

MainRepository

class DefaultMainRepository @Inject constructor(
    private val api: CurrencyApi
) : MainRepository {

Hee are Gradle dependencies:

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.9.0'

    implementation "androidx.activity:activity-ktx:1.4.0"

    implementation 'com.google.dagger:hilt-android:2.40.5'
    kapt 'com.google.dagger:hilt-compiler:2.40.5'
    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
    kapt'androidx.hilt:hilt-compiler:1.0.0'

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.4.0'

    androidTestImplementation  'com.google.dagger:hilt-android-testing:2.40.5'
    kaptAndroidTest 'com.google.dagger:hilt-compiler:2.40.5'
    testImplementation 'com.google.dagger:hilt-android-testing:2.40.5'
    kaptTest 'com.google.dagger:hilt-compiler:2.40.5'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

Application:

@HiltAndroidApp
class CurrencyApplication: Application()

Manifest:

    <application
        android:name=".CurrencyApplication"

Im trying to find solution everywhere like here: possible reason

I will be grateful for any help

Body:
first of all, check anotationProcessor for hilt to be able generate correct binding, so go to app.gradle and check these dependency existence:

dependencies {

    implementation 'com.google.dagger:hilt-android:2.30-alpha'
    kapt 'com.google.dagger:hilt-android-compiler:2.30-alpha'

    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
    kapt'androidx.hilt:hilt-compiler:1.0.0-alpha02'

...
}


问:
Snakemake on SLURM: retry attempt counter does not change
I have a workflow rule with varying time requirements for a slurm cluster. I decorated the workflow as per documentation to increase the slurm time limit for resubmitted jobs (my cluster config.yaml has the arg restart-times: 3), look for resources.time:

example_1:

```<code>rule run_toolx:
    ...
    resources:
        cpus=config["smk_params"]["threads"] * config["smk_params"]["thread_factor"],
        mem_mb=4000,
        time=lambda wildcards, attempt: ( 3 * ( attempt ** 2 ))
    threads:
        config["smk_params"]["threads"] * config["smk_params"]["thread_factor"]
    log:
        "logs/{sample}_toolX.log"
    shell:
        """
        echo "Queueing toolX job with a timelimit of {resources.time} minutes."
        toolX --threads {threads} | tee {log} 2> {log}
        """
</code>```

When I review my snakemake log file for the echo, I find three job submissions with the line: "Queueing toolX job with a timelimit of 3 minutes.". I expected a time limit increase of 3, 12, 27 minutes. This is backed by the slurm logs where each submitted job requests only "00:03:00" computing time on the nodes. When the job hits this timelimit, the slurm manager interrupts it as expected:

output_1:

```<code>       JobID    JobName  Partition  AllocCPUS      State    Elapsed  Timelimit ExitCode
------------ ---------- ---------- ---------- ---------- ---------- ---------- --------
4983483      snakejob.+     normal          6    TIMEOUT   00:03:15   00:03:00      0:0
4983483.bat+      batch                     6  CANCELLED   00:03:16                0:15
4983904      snakejob.+     normal          6    TIMEOUT   00:03:03   00:03:00      0:0
4983904.bat+      batch                     6  CANCELLED   00:03:04                0:15
4984740      snakejob.+     normal          6    TIMEOUT   00:03:03   00:03:00      0:0
4984740.bat+      batch                     6  CANCELLED   00:03:04                0:15
</code>```

Apparently, either my lambda function does not work or the variable attempt is not a counter.

Thanks for sharing a thought.

Edit_1:

with config["smk_params"]["threads"]=2 and config["smk_params"]["thread_factor"]=3 , so the math for resources.cpus works

This tutorial uses the same notation as my in example above.

The attempt parameter was introduced with [4.1.0] - 2017-09-26. I am using snakemake 6.15.1.

I am using the slurm job submission scripts from Snakemake-Profiles.

some tutorials and posts use 'int(attempt)', this does not solve above problem

Edit_2: Reproducable Example for succesful attempt usage

reprex_1:

```<code>shell.executable("bash")

localrules: all

rule all:
    input:
        "success.txt"

rule run_toolX:
    output:
        "success.txt",
    resources:
        cpus=1,
        mem_mb=100,
        time=lambda wildcards, input, threads, attempt: ( 3 * ( attempt ** 2 ))
    shell:
        """
        echo "Queueing run_quast with a timelimit of {resources.time} minutes."
        sleep 4m
        echo "Queueing run_quast with a timelimit of {resources.time} minutes." > {output}
        """
</code>```

yielding:

output_2:

```<code>4985470      snakejob.+     normal          1    TIMEOUT   00:03:16   00:03:00      0:0
4985470.bat+      batch                     1  CANCELLED   00:03:17                0:15
4985477      snakejob.+     normal          1  COMPLETED   00:04:08   00:12:00      0:0
4985477.bat+      batch                     1  COMPLETED   00:04:08                 0:0
</code>```

Experience: I first tried it with a one-minute setup, which was working to my suprise, and then tested the exact same lambda function as in my complex rule resulting in the error. The same slurm profile was used for both examples.

It's quirky.

Edit_3: testing all variations of the notation

my reprex works with or without, respectively:

int(attempt)

int( lambda ... )

lambda wildcards, input, threads, attempt: ...

lambda wildcards, attempt: ...

Edit_4: embedding the reprex in the complex workflow

I am converging with reprex_1 to the setup/environment of the non-functional rule:

reprex_1 works within complex workflow with all rule only pulling reprex_1 rule output

with all rule only pulling example_1 rule output and the resources of example_1 the counter is broken

Next culprit to test: example_1 is a grouped rule. Maybe rule grouping disables the attempt counter.

答:
It is a bug and I have raised an issue:

Retry counter attempt is dysfunctional for grouped rules

That was painful.

Body:
I have a workflow rule with varying time requirements for a slurm cluster. I decorated the workflow as per documentation to increase the slurm time limit for resubmitted jobs (my cluster config.yaml has the arg restart-times: 3), look for resources.time:

example_1:

rule run_toolx:
    ...
    resources:
        cpus=config["smk_params"]["threads"] * config["smk_params"]["thread_factor"],
        mem_mb=4000,
        time=lambda wildcards, attempt: ( 3 * ( attempt ** 2 ))
    threads:
        config["smk_params"]["threads"] * config["smk_params"]["thread_factor"]
    log:
        "logs/{sample}_toolX.log"
    shell:
        """
        echo "Queueing toolX job with a timelimit of {resources.time} minutes."
        toolX --threads {threads} | tee {log} 2> {log}
        """

When I review my snakemake log file for the echo, I find three job submissions with the line: "Queueing toolX job with a timelimit of 3 minutes.". I expected a time limit increase of 3, 12, 27 minutes. This is backed by the slurm logs where each submitted job requests only "00:03:00" computing time on the nodes. When the job hits this timelimit, the slurm manager interrupts it as expected:

output_1:

       JobID    JobName  Partition  AllocCPUS      State    Elapsed  Timelimit ExitCode
------------ ---------- ---------- ---------- ---------- ---------- ---------- --------
4983483      snakejob.+     normal          6    TIMEOUT   00:03:15   00:03:00      0:0
4983483.bat+      batch                     6  CANCELLED   00:03:16                0:15
4983904      snakejob.+     normal          6    TIMEOUT   00:03:03   00:03:00      0:0
4983904.bat+      batch                     6  CANCELLED   00:03:04                0:15
4984740      snakejob.+     normal          6    TIMEOUT   00:03:03   00:03:00      0:0
4984740.bat+      batch                     6  CANCELLED   00:03:04                0:15

Apparently, either my lambda function does not work or the variable attempt is not a counter.

Thanks for sharing a thought.

Edit_1:

with config["smk_params"]["threads"]=2 and config["smk_params"]["thread_factor"]=3 , so the math for resources.cpus works

This tutorial uses the same notation as my in example above.

The attempt parameter was introduced with [4.1.0] - 2017-09-26. I am using snakemake 6.15.1.

I am using the slurm job submission scripts from Snakemake-Profiles.

some tutorials and posts use 'int(attempt)', this does not solve above problem

Edit_2: Reproducable Example for succesful attempt usage

reprex_1:

shell.executable("bash")

localrules: all

rule all:
    input:
        "success.txt"

rule run_toolX:
    output:
        "success.txt",
    resources:
        cpus=1,
        mem_mb=100,
        time=lambda wildcards, input, threads, attempt: ( 3 * ( attempt ** 2 ))
    shell:
        """
        echo "Queueing run_quast with a timelimit of {resources.time} minutes."
        sleep 4m
        echo "Queueing run_quast with a timelimit of {resources.time} minutes." > {output}
        """

yielding:

output_2:

4985470      snakejob.+     normal          1    TIMEOUT   00:03:16   00:03:00      0:0
4985470.bat+      batch                     1  CANCELLED   00:03:17                0:15
4985477      snakejob.+     normal          1  COMPLETED   00:04:08   00:12:00      0:0
4985477.bat+      batch                     1  COMPLETED   00:04:08                 0:0

Experience: I first tried it with a one-minute setup, which was working to my suprise, and then tested the exact same lambda function as in my complex rule resulting in the error. The same slurm profile was used for both examples.

It's quirky.

Edit_3: testing all variations of the notation

my reprex works with or without, respectively:

int(attempt)

int( lambda ... )

lambda wildcards, input, threads, attempt: ...

lambda wildcards, attempt: ...

Edit_4: embedding the reprex in the complex workflow

I am converging with reprex_1 to the setup/environment of the non-functional rule:

reprex_1 works within complex workflow with all rule only pulling reprex_1 rule output

with all rule only pulling example_1 rule output and the resources of example_1 the counter is broken

Next culprit to test: example_1 is a grouped rule. Maybe rule grouping disables the attempt counter.


问:
MS Word filename from bookmarks with VBA
Assuming I have:

a word template including macro: custom_template.dotm;

two bookmarks in this template: 'first_name" and "last_name".

I would like that on "Save" event, in the dialog box, the application proposes to user, instead of "document1", and only if relative bookmarks exist, the filename "Document of first_name second_name.docx".

Can anybody explain me how to achieve this with VBA?

Thanks.

=== UPDATE ===

Now I've this code, working well when I execute it.
I would like it runs automatically when user clicks on "save document".

```<code>Sub Demo()
Dim sFlNm As String
With ActiveDocument
  sFlNm = "Document of " & .Bookmarks("first_name").Range.Text & " " & .Bookmarks("last_name").Range.Text
End With
With Dialogs(wdDialogFileSaveAs)
  .Name = sFlNm
  .Show
End With
End Sub
</code>```

答:
For a macro to run at the client's end, you would have to send a macro-enabled template or document. Many people who are running anti-virus software will get a warning of a possible Word virus. Then the user will have to manually enable the macros. Are they going to bother?

Making it run automatically with a Save command may have unintended consequences. You'll have to check whether the bookmarks have actually been filled, and using the Save command while you're revising the document can save it with a new file name. But you asked, so here's how: rename the macro as FileSave. Then when you choose Ctrl + S or File>Save in Word, the dialog will automatically pop up:

```<code>Sub FileSave()
    Dim sFlNm As String
    With ActiveDocument
      sFlNm = "Document of " & .Bookmarks("first_name").Range.Text & " " & .Bookmarks("last_name").Range.Text
    End With
    With Dialogs(wdDialogFileSaveAs)
      .Name = sFlNm
      .Show
    End With
End Sub
</code>```

In Word, to create a macro that runs automatically when you choose a Word command, follow these steps:

Choose Developer>Macros.

Change the Macros in dropdown to Word commands.

Choose the command name you want to re-purpose.

Change the Macros in dropdown back to the macro-enabled document or template that you're developing.

Click on the Create button. A new macro is created in the VBE with the correct command name. Fill in the macro with whatever you want the macro to do.

Body:
Assuming I have:

a word template including macro: custom_template.dotm;

two bookmarks in this template: 'first_name" and "last_name".

I would like that on "Save" event, in the dialog box, the application proposes to user, instead of "document1", and only if relative bookmarks exist, the filename "Document of first_name second_name.docx".

Can anybody explain me how to achieve this with VBA?

Thanks.

=== UPDATE ===

Now I've this code, working well when I execute it.
I would like it runs automatically when user clicks on "save document".

Sub Demo()
Dim sFlNm As String
With ActiveDocument
  sFlNm = "Document of " & .Bookmarks("first_name").Range.Text & " " & .Bookmarks("last_name").Range.Text
End With
With Dialogs(wdDialogFileSaveAs)
  .Name = sFlNm
  .Show
End With
End Sub

Body:
For a macro to run at the client's end, you would have to send a macro-enabled template or document. Many people who are running anti-virus software will get a warning of a possible Word virus. Then the user will have to manually enable the macros. Are they going to bother?

Making it run automatically with a Save command may have unintended consequences. You'll have to check whether the bookmarks have actually been filled, and using the Save command while you're revising the document can save it with a new file name. But you asked, so here's how: rename the macro as FileSave. Then when you choose Ctrl + S or File>Save in Word, the dialog will automatically pop up:

Sub FileSave()
    Dim sFlNm As String
    With ActiveDocument
      sFlNm = "Document of " & .Bookmarks("first_name").Range.Text & " " & .Bookmarks("last_name").Range.Text
    End With
    With Dialogs(wdDialogFileSaveAs)
      .Name = sFlNm
      .Show
    End With
End Sub

In Word, to create a macro that runs automatically when you choose a Word command, follow these steps:

Choose Developer>Macros.

Change the Macros in dropdown to Word commands.

Choose the command name you want to re-purpose.

Change the Macros in dropdown back to the macro-enabled document or template that you're developing.

Click on the Create button. A new macro is created in the VBE with the correct command name. Fill in the macro with whatever you want the macro to do.


问:
Shifting minimum values using Python
The code calculates the minimum value at each row and picks the next minimum by scanning the nearby element on the same and the next row. Instead, I want the code to start with minimum value of the first row and then progress by scanning the nearby elements. I don't want it to calculate the minimum value for each row. The outputs are attached.

```<code>import numpy as np
from scipy.ndimage import minimum_filter as mf

Pe = np.random.rand(5,5)

b = np.zeros((Pe.shape[0], 2))

#the footprint of the window, i.e., we do not consider the value itself or value in the row above
ft = np.asarray([[0, 0, 0],
                 [1, 0, 1],
                 [1, 1, 1]])
#applying scipy's minimum filter
#mode defines what should be considered as values at the edges
#setting the edges to INF
Pe_min = mf(Pe, footprint=ft, mode="constant", cval=np.inf)

#finding rowwise index of minimum value
idx = Pe.argmin(axis=1)

#retrieving minimum values and filtered values
b[:, 0] = np.take_along_axis(Pe, idx[None].T, 1).T[0]
b[:, 1] = np.take_along_axis(Pe_min, idx[None].T, 1).T[0]

print(b)
</code>```

Present Output:

Desired Output:

答:
You can solve this using a simple while loop: for a given current location, each step of the loop iterates over the neighborhood to find the smallest value amongst all the valid next locations and then update/write it.

Since this can be pretty inefficient in pure Numpy, you can use Numba so the code can be executed efficiently. Here is the implementation:

import numpy as np
import numba as nb

Pe = np.random.rand(5,5)
# array([[0.58268917, 0.99645225, 0.06229945, 0.5741654 , 0.41407074],
#        [0.4933553 , 0.93253261, 0.1485588 , 0.00133828, 0.09301049],
#        [0.49055436, 0.53794993, 0.81358814, 0.25031136, 0.76174586],
#        [0.69885908, 0.90878292, 0.25387689, 0.25735301, 0.63913838],
#        [0.33781117, 0.99406778, 0.49133067, 0.95026241, 0.14237322]])

@nb.njit('int_[:,:](float64[:,::1])', boundscheck=True)
def minValues(arr):
    n, m = arr.shape
    assert n >= 1 and m >= 2
    res = []
    i, j = 0, np.argmin(arr[0,:])
    res.append((i, j))
    iPrev = jPrev = -1
    while iPrev < n-1:
        cases = [(i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1)]
        minVal = np.inf
        iMin = jMin = -1
        # Find the best candidate (smalest value)
        for (i2, j2) in cases:
            if i2 == iPrev and j2 == jPrev: # No cycles
                continue
            if i2 < 0 or i2 >= n or j2 < 0 or j2 >= m: # No out-of-bounds
                continue
            if arr[i2, j2] < minVal:
                iMin, jMin = i2, j2
                minVal = arr[i2, j2]
        assert not np.isinf(minVal)
        # Store it and update the values
        res.append((iMin, jMin))
        iPrev, jPrev = i, j
        i, j = iMin, jMin
    return np.array(res)

minValues(Pe)
# array([[0, 2],
#        [1, 3],
#        [1, 4],
#        [2, 3],
#        [3, 2],
#        [3, 3],
#        [4, 4],
#        [4, 3]], dtype=int32)
```

The algorithm is relatively fast as it succeeds to find the result of a path of length 141_855 in a Pe array of shape (100_000, 1_000) in only 15 ms on my machine (although it can be optimized). The same code using only CPython (ie. without the Numba JIT) takes 591 ms.

Title: Shifting minimum values using Python

Body:
The code calculates the minimum value at each row and picks the next minimum by scanning the nearby element on the same and the next row. Instead, I want the code to start with minimum value of the first row and then progress by scanning the nearby elements. I don't want it to calculate the minimum value for each row. The outputs are attached.

import numpy as np
from scipy.ndimage import minimum_filter as mf

Pe = np.random.rand(5,5)

b = np.zeros((Pe.shape[0], 2))

#the footprint of the window, i.e., we do not consider the value itself or value in the row above
ft = np.asarray([[0, 0, 0],
                 [1, 0, 1],
                 [1, 1, 1]])
#applying scipy's minimum filter
#mode defines what should be considered as values at the edges
#setting the edges to INF
Pe_min = mf(Pe, footprint=ft, mode="constant", cval=np.inf)

#finding rowwise index of minimum value
idx = Pe.argmin(axis=1)

#retrieving minimum values and filtered values
b[:, 0] = np.take_along_axis(Pe, idx[None].T, 1).T[0]
b[:, 1] = np.take_along_axis(Pe_min, idx[None].T, 1).T[0]

print(b)

Present Output:

Desired Output:

Body:
You can solve this using a simple while loop: for a given current location, each step of the loop iterates over the neighborhood to find the smallest value amongst all the valid next locations and then update/write it.

Since this can be pretty inefficient in pure Numpy, you can use Numba so the code can be executed efficiently. Here is the implementation:

import numpy as np
import numba as nb

Pe = np.random.rand(5,5)
# array([[0.58268917, 0.99645225, 0.06229945, 0.5741654 , 0.41407074],
#        [0.4933553 , 0.93253261, 0.1485588 , 0.00133828, 0.09301049],
#        [0.49055436, 0.53794993, 0.81358814, 0.25031136, 0.76174586],
#        [0.69885908, 0.90878292, 0.25387689, 0.25735301, 0.63913838],
#        [0.33781117, 0.99406778, 0.49133067, 0.95026241, 0.14237322]])

@nb.njit('int_[:,:](float64[:,::1])', boundscheck=True)
def minValues(arr):
    n, m = arr.shape
    assert n >= 1 and m >= 2
    res = []
    i, j = 0, np.argmin(arr[0,:])
    res.append((i, j))
    iPrev = jPrev = -1
    while iPrev < n-1:
        cases = [(i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1)]
        minVal = np.inf
        iMin = jMin = -1
        # Find the best candidate (smalest value)
        for (i2, j2) in cases:
            if i2 == iPrev and j2 == jPrev: # No cycles
                continue
            if i2 < 0 or i2 >= n or j2 < 0 or j2 >= m: # No out-of-bounds
                continue
            if arr[i2, j2] < minVal:
                iMin, jMin = i2, j2
                minVal = arr[i2, j2]
        assert not np.isinf(minVal)
        # Store it and update the values
        res.append((iMin, jMin))
        iPrev, jPrev = i, j
        i, j = iMin, jMin
    return np.array(res)

minValues(Pe)
# array([[0, 2],
#        [1, 3],
#        [1, 4],
#        [2, 3],
#        [3, 2],
#        [3, 3],
#        [4, 4],
#        [4, 3]], dtype=int32)

The algorithm is relatively fast as it succeeds to find the result of a path of length 141_855 in a Pe array of shape (100_000, 1_000) in only 15 ms on my machine (although it can be optimized). The same code using only CPython (ie. without the Numba JIT) takes 591 ms.


问:
How to add two elements of arrays with each others and have a new array with a new shape?
I have the following two numpy arrays 'a' and 'b':

a = np.array([[1, -1], [1, 0], [1, 1]]) with a shape = (3, 2)

b = np.array([[1, 1], [2, 2]]) with shape = (2, 2)

I want to add each element of the 'b' array with each element of the 'a' array so that I have as an output the following 'c' array

c = np.array([[2, 0], [2, 1], [2, 2], [3, 1], [3, 2], [3, 3]])
with a shape = (6, 2)

Is the any function that can do it? Thanks

答:
That's the simplest calculation I could come up with:

c = np.array([a + b[0,:], a + b[1,:]]).reshape(6, 2)
```


问:
expoappauth.getAuth:encountered exception when trying to start auth request null
I am trying to do a react-natvie-app with google-service,
this is my code:

useAuth.js

```<code>import * as Google from "expo-google-app-auth";

const AuthContext=createContext({});

 const config={
  androidClientId:"551241887947-trikk6eg7jvilk8cjrpp1maq10cb11gr.apps.googleusercontent.com",
  scopes:["profile","email"],
  permissions:["public_profile","email","gender","location"],
}

export const AuthProvider = ({children}) => {

    const signInWithGoogle = async () =>{
         Google.logInAsync(config).then(async (logInResult) =>{
         if(logInResult.type === "success"){
           //login..
         }
       }).catch((error)=>{
        console.log("Api call error");
        alert(error.message);
     })
    }

  return (
    <AuthContext.Provider value={{
          user:null,
          signInWithGoogle,
      }}
    >
        {children}
     </AuthContext.Provider>
  );
};

export default function useAuth(){
    return useContext(AuthContext);
}
</code>```

here is my

LoginScreen.js

```<code>import React from 'react';
import useAuth from '../hooks/useAuth';

const LoginScreen = () => {
  const {signInWithGoogle}=useAuth();
  return (
    <View>
      <Text>login to the app</Text>
      <Button title="login" onPress={signInWithGoogle}/>
    </View>
  );
};

export default LoginScreen;
</code>```

when I press the button I get this exception

I am using a firestore.
in my firebase project I add the two fingerprint SHA-1
and SHA-256
I googled it and I didn’t  found any solution for this
problem.
thanks for the assitance!

答:
I found a solution for this problem,In order to resolve you need to work with real android phone,and that's because the emulator is reason behind it.and it didn't work
properly.</p>

Body:
I am trying to do a react-natvie-app with google-service,
this is my code:

useAuth.js

import * as Google from "expo-google-app-auth";

const AuthContext=createContext({});

 const config={
  androidClientId:"551241887947-trikk6eg7jvilk8cjrpp1maq10cb11gr.apps.googleusercontent.com",
  scopes:["profile","email"],
  permissions:["public_profile","email","gender","location"],
}

export const AuthProvider = ({children}) => {

    const signInWithGoogle = async () =>{
         Google.logInAsync(config).then(async (logInResult) =>{
         if(logInResult.type === "success"){
           //login..
         }
       }).catch((error)=>{
        console.log("Api call error");
        alert(error.message);
     })
    }

  return (
    <AuthContext.Provider value={{
          user:null,
          signInWithGoogle,
      }}
    >
        {children}
     </AuthContext.Provider>
  );
};

export default function useAuth(){
    return useContext(AuthContext);
}

here is my

LoginScreen.js

import React from 'react';
import useAuth from '../hooks/useAuth';

const LoginScreen = () => {
  const {signInWithGoogle}=useAuth();
  return (
    <View>
      <Text>login to the app</Text>
      <Button title="login" onPress={signInWithGoogle}/>
    </View>
  );
};

export default LoginScreen;

when I press the button I get this exception

I am using a firestore.
in my firebase project I add the two fingerprint SHA-1
and SHA-256
I googled it and I didn’t  found any solution for this
problem.
thanks for the assitance!


问:
Why I cannot run npm run dev on a centos7?
I have a problem installing my app on a new server, I come from centos6 to centos7.

When I am installing a Laravel app that works perfectly on centos6 it goes right except when I run npm run dev

```<code>[root@v6-a10 worknow4.0]# npm run dev

> dev
> npm run development

> development
> cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js

node:events:306
      throw er; // Unhandled 'error' event
      ^

Error: spawn node_modules/webpack/bin/webpack.js EACCES
    at Process.ChildProcess._handle.onexit (node:internal/child_process:269:19)
    at onErrorNT (node:internal/child_process:467:16)
    at processTicksAndRejections (node:internal/process/task_queues:80:21)
Emitted 'error' event on ChildProcess instance at:
    at Process.ChildProcess._handle.onexit (node:internal/child_process:275:12)
    at onErrorNT (node:internal/child_process:467:16)
    at processTicksAndRejections (node:internal/process/task_queues:80:21) {
  errno: -13,
  code: 'EACCES',
  syscall: 'spawn node_modules/webpack/bin/webpack.js',
  path: 'node_modules/webpack/bin/webpack.js',
  spawnargs: [
    '--progress',
    '--hide-modules',
    '--config=node_modules/laravel-mix/setup/webpack.config.js'
  ]
}
npm ERR! code 1
npm ERR! path /home/admin/domains/worknow-cursos.com/public_html/worknow4.0
npm ERR! command failed
npm ERR! command sh -c cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-07T19_56_43_919Z-debug.log
npm ERR! code 1
npm ERR! path /home/admin/domains/worknow-cursos.com/public_html/worknow4.0
npm ERR! command failed
npm ERR! command sh -c npm run development

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-07T19_56_44_006Z-debug.log
</code>```

I have been searching for an answer for hours but nothing works.

I tried to delete node_modules and package-lock and reinstall, but also didn't work.

答:
Ok the problem might be permission as dimitri says. I just go to node_modules/webpack/bin/webpack.js and change the permission to 777

I dont know if this is recomended but at least works

Body:
I have a problem installing my app on a new server, I come from centos6 to centos7.

When I am installing a Laravel app that works perfectly on centos6 it goes right except when I run npm run dev

[root@v6-a10 worknow4.0]# npm run dev

> dev
> npm run development

> development
> cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js

node:events:306
      throw er; // Unhandled 'error' event
      ^

Error: spawn node_modules/webpack/bin/webpack.js EACCES
    at Process.ChildProcess._handle.onexit (node:internal/child_process:269:19)
    at onErrorNT (node:internal/child_process:467:16)
    at processTicksAndRejections (node:internal/process/task_queues:80:21)
Emitted 'error' event on ChildProcess instance at:
    at Process.ChildProcess._handle.onexit (node:internal/child_process:275:12)
    at onErrorNT (node:internal/child_process:467:16)
    at processTicksAndRejections (node:internal/process/task_queues:80:21) {
  errno: -13,
  code: 'EACCES',
  syscall: 'spawn node_modules/webpack/bin/webpack.js',
  path: 'node_modules/webpack/bin/webpack.js',
  spawnargs: [
    '--progress',
    '--hide-modules',
    '--config=node_modules/laravel-mix/setup/webpack.config.js'
  ]
}
npm ERR! code 1
npm ERR! path /home/admin/domains/worknow-cursos.com/public_html/worknow4.0
npm ERR! command failed
npm ERR! command sh -c cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-07T19_56_43_919Z-debug.log
npm ERR! code 1
npm ERR! path /home/admin/domains/worknow-cursos.com/public_html/worknow4.0
npm ERR! command failed
npm ERR! command sh -c npm run development

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-07T19_56_44_006Z-debug.log

I have been searching for an answer for hours but nothing works.

I tried to delete node_modules and package-lock and reinstall, but also didn't work.


问:
XSLT count element value and create new element with the value
I have the following source XML:

```<code><ITEMS>
   <ITEM>
      <CODE>34155</CODE>
      <VARIANTS>
         <NAME>A</NAME>
         <STOCK>12</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>B</NAME>
         <STOCK>0</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>C</NAME>
         <STOCK>50</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>D</NAME>
         <STOCK>3</STOCK>
      </VARIANTS>
   </ITEM>
</ITEMS>
</code>```

I would like to loop trough all <VARIANTS> elements count <STOCK> child value and create new <TOTALSTOCK> value under the parent element <ITEM>.

```<code><ITEMS>
   <ITEM>
      <TOTALSTOCK>65</TOTALSTOCK>
      <CODE>34155</CODE>
      <VARIANTS>
         <NAME>A</NAME>
         <STOCK>12</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>B</NAME>
         <STOCK>0</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>C</NAME>
         <STOCK>50</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>D</NAME>
         <STOCK>3</STOCK>
      </VARIANTS>
   </ITEM>
</ITEMS>
</code>```

Is such a mathematical operation possible with XSLT?

答:
Please try the following XSLT.

Input XML

```<code><ITEMS>
    <ITEM>
        <CODE>34155</CODE>
        <VARIANTS>
            <NAME>A</NAME>
            <STOCK>12</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>B</NAME>
            <STOCK>0</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>C</NAME>
            <STOCK>50</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>D</NAME>
            <STOCK>3</STOCK>
        </VARIANTS>
    </ITEM>
    <ITEM>
        <CODE>34770</CODE>
        <VARIANTS>
            <NAME>A</NAME>
            <STOCK>120</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>C</NAME>
            <STOCK>180</STOCK>
        </VARIANTS>
    </ITEM>
</ITEMS>
</code>```

XSLT

```<code><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/ITEMS">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ITEM">
        <xsl:copy>
            <TOTALSTOCK>
                <xsl:value-of select="sum(./VARIANTS/STOCK)"/>
            </TOTALSTOCK>
            <xsl:copy-of select="*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
</code>```

Output XML

```<code><ITEMS>
  <ITEM>
    <TOTALSTOCK>65</TOTALSTOCK>
    <CODE>34155</CODE>
    <VARIANTS>
      <NAME>A</NAME>
      <STOCK>12</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>B</NAME>
      <STOCK>0</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>C</NAME>
      <STOCK>50</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>D</NAME>
      <STOCK>3</STOCK>
    </VARIANTS>
  </ITEM>
  <ITEM>
    <TOTALSTOCK>300</TOTALSTOCK>
    <CODE>34770</CODE>
    <VARIANTS>
      <NAME>A</NAME>
      <STOCK>120</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>C</NAME>
      <STOCK>180</STOCK>
    </VARIANTS>
  </ITEM>
</ITEMS>
</code>```

Body:
I have the following source XML:

<ITEMS>
   <ITEM>
      34155
      <VARIANTS>
         <NAME>A</NAME>
         <STOCK>12</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>B</NAME>
         <STOCK>0</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>C</NAME>
         <STOCK>50</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>D</NAME>
         <STOCK>3</STOCK>
      </VARIANTS>
   </ITEM>
</ITEMS>

I would like to loop trough all <VARIANTS> elements count <STOCK> child value and create new <TOTALSTOCK> value under the parent element <ITEM>.

<ITEMS>
   <ITEM>
      <TOTALSTOCK>65</TOTALSTOCK>
      34155
      <VARIANTS>
         <NAME>A</NAME>
         <STOCK>12</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>B</NAME>
         <STOCK>0</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>C</NAME>
         <STOCK>50</STOCK>
      </VARIANTS>
      <VARIANTS>
         <NAME>D</NAME>
         <STOCK>3</STOCK>
      </VARIANTS>
   </ITEM>
</ITEMS>

Is such a mathematical operation possible with XSLT?

Body:
Please try the following XSLT.

Input XML

<ITEMS>
    <ITEM>
        <CODE>34155</CODE>
        <VARIANTS>
            <NAME>A</NAME>
            <STOCK>12</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>B</NAME>
            <STOCK>0</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>C</NAME>
            <STOCK>50</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>D</NAME>
            <STOCK>3</STOCK>
        </VARIANTS>
    </ITEM>
    <ITEM>
        <CODE>34770</CODE>
        <VARIANTS>
            <NAME>A</NAME>
            <STOCK>120</STOCK>
        </VARIANTS>
        <VARIANTS>
            <NAME>C</NAME>
            <STOCK>180</STOCK>
        </VARIANTS>
    </ITEM>
</ITEMS>

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/ITEMS">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ITEM">
        <xsl:copy>
            <TOTALSTOCK>
                <xsl:value-of select="sum(./VARIANTS/STOCK)"/>
            </TOTALSTOCK>
            <xsl:copy-of select="*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output XML

<ITEMS>
  <ITEM>
    <TOTALSTOCK>65</TOTALSTOCK>
    <CODE>34155</CODE>
    <VARIANTS>
      <NAME>A</NAME>
      <STOCK>12</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>B</NAME>
      <STOCK>0</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>C</NAME>
      <STOCK>50</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>D</NAME>
      <STOCK>3</STOCK>
    </VARIANTS>
  </ITEM>
  <ITEM>
    <TOTALSTOCK>300</TOTALSTOCK>
    <CODE>34770</CODE>
    <VARIANTS>
      <NAME>A</NAME>
      <STOCK>120</STOCK>
    </VARIANTS>
    <VARIANTS>
      <NAME>C</NAME>
      <STOCK>180</STOCK>
    </VARIANTS>
  </ITEM>
</ITEMS>


问:
How can I swap internal IP address between two GCP VMs?
I have a running VM1 (internal IP is: xxx.xxx.0.7). I will create another new VM2 and I want to change the IP of VM1 to any other IP and set the IP of VM2 to "xxx.xxx.0.7". OS of both VM is windows server.

I have found some way to change the IP of a running VM. But I am not sure if that works. Is there any straightforward way to do this?

Thanks in advance!

答:
You can assign a static internal IP address when the instance is created and not once the VM is running.

To accomplish your goal of creating a new instance using an existing internal IP address:

Backup the existing virtual machine (create an image, snaphot, etc.)

Promote the internal ephemeral IP address.

Delete the virtual machine.

Create a new virtual machine specifying the static internal IP address.

Recreate the original virtual machine from the image or snapshot.

References:

Reserving a static internal IP address

Promote an in-use ephemeral internal IP address to a static
address

Create a VM instance with a specific internal IP address


问:
How would i check if the value in the table is equal to the _G variable string?
How would i check the table to see if the value in the table matches the _G.User = "" variable?

```<code>_G.Name = "Bod"
------------------------------------------------------------
local CorrectUsers = {
  "Username1",
  "Username2",
  "Username3",
  "Username4",
  "Username5",
}
------------------------------------------------------------
for i,v in pairs(CorrectUsers, _G.User) do
 if table.find(CorrectUsers, _G.User) then
  print("Correct User")
 else
  print("Incorrect User")
 end
end
</code>```

https://replit.com/@BloodThirstyy/SimpleMultiStepWhitelist

答:
```<code>for i,v in pairs(CorrectUsers, _G.User) do
 if table.find(CorrectUsers, _G.User) then
</code>```

pairs only takes one argument. There is no table.find in Lua's table library.

In your snippet _G.User is undefined. _G.Name is unused.

Also usually there is no need to access globals through _G. Just write User.

To find something in a table you traverse over the table and compare each element with the value you are looking for.

So for a table like

```<code>local CorrectUsers = {
  "Bob",
  "John",
  "Susan",
  "Daniel",
  "Zoe",
}
</code>```

You'd simply do

```<code>for i, v in ipairs(CorrectUsers) do
  if v == "Daniel" then
    print("found Daniel")
  end
end
</code>```

Alternatively you can build a look up table:

```<code>local isCorrectUser = {
  Bob = true,
  Jane = true,
  John = true,
}
</code>```

And then

```<code>if isCorrectUser.Jane then
  print("found Jane")
end
</code>```

As building such look up tables can become tedious you can simply create one from your user list.

```<code>local isCorrectUser = {}
for i, v in ipairs(CorrectUsers) do
  isCorrectUser[v] = true
end
</code>```

Using a lookup table becomes useful if you are checking values very frequently as you will not have to traverse over the table very time.

Body:
How would i check the table to see if the value in the table matches the _G.User = "" variable?

_G.Name = "Bod"
------------------------------------------------------------
local CorrectUsers = {
  "Username1",
  "Username2",
  "Username3",
  "Username4",
  "Username5",
}
------------------------------------------------------------
for i,v in pairs(CorrectUsers, _G.User) do
 if table.find(CorrectUsers, _G.User) then
  print("Correct User")
 else
  print("Incorrect User")
 end
end

https://replit.com/@BloodThirstyy/SimpleMultiStepWhitelist

Body:
for i,v in pairs(CorrectUsers, _G.User) do
 if table.find(CorrectUsers, _G.User) then

pairs only takes one argument. There is no table.find in Lua's table library.

In your snippet _G.User is undefined. _G.Name is unused.

Also usually there is no need to access globals through _G. Just write User.

To find something in a table you traverse over the table and compare each element with the value you are looking for.

So for a table like

local CorrectUsers = {
  "Bob",
  "John",
  "Susan",
  "Daniel",
  "Zoe",
}

You'd simply do

for i, v in ipairs(CorrectUsers) do
  if v == "Daniel" then
    print("found Daniel")
  end
end

Alternatively you can build a look up table:

local isCorrectUser = {
  Bob = true,
  Jane = true,
  John = true,
}

And then

if isCorrectUser.Jane then
  print("found Jane")
end

As building such look up tables can become tedious you can simply create one from your user list.

local isCorrectUser = {}
for i, v in ipairs(CorrectUsers) do
  isCorrectUser[v] = true
end

Using a lookup table becomes useful if you are checking values very frequently as you will not have to traverse over the table very time.


问:
SCP to create a security group with no tag or with specific tag
I want to create an SCP (service control policy) that should allow creating a security group if no tags are present. If a tag is created, it should have a specific value. For example, if 'bu' is a tag, the value should always be 'finance' only. How this can be done. I have done this bit:

```<code>{
  "Sid": "SGBu",
  "Effect": "Deny",
  "Action": [
    "ec2:CreateSecurityGroup"
  ],
  "Resource": [
    "arn:aws:ec2:*:*:security-group/*"
  ],
  "Condition": {
    "ForAnyValue:Null": {
      "aws:RequestTag/bu": "false"
    }
  }
}
</code>```

How can I add an OR condition along with this so that the value has to be 'finance' if 'bu' tag is added?

Thank you

答:
The best approach is to combine SCP with Tag Policies.

In this way, SCP are used to enforce tagging at resource creation and Tag Policy is used to standarize values of determined tags.

With Tag Policies you can define a list of values allowed for certain tags, enforce it for the services you select and also is case-sensitive (SCP is not case-sensitive on condition keys).

For your scenario the Tag policy could be:

Tag key: bu

Values: finance

Resource types to enforce: ec2:securitygroup

Body:
I want to create an SCP (service control policy) that should allow creating a security group if no tags are present. If a tag is created, it should have a specific value. For example, if 'bu' is a tag, the value should always be 'finance' only. How this can be done. I have done this bit:

{
  "Sid": "SGBu",
  "Effect": "Deny",
  "Action": [
    "ec2:CreateSecurityGroup"
  ],
  "Resource": [
    "arn:aws:ec2:*:*:security-group/*"
  ],
  "Condition": {
    "ForAnyValue:Null": {
      "aws:RequestTag/bu": "false"
    }
  }
}

How can I add an OR condition along with this so that the value has to be 'finance' if 'bu' tag is added?

Thank you