问:
Forward chaining in prolog with rules about lists
In previous question, we built a simple forward chaining in Prolog together with the user slago, and solved some problems about it.
Code for forward chaining:

```<code>:- op(1100, xfx, if).
:- op(1000, xfy, or).
:- op(900, xfy, and).

forward(Facts) :-
    fixed_point(nil, [true], Facts).                % Start with the base with only true

fixed_point(Base, Base, Base) :- !.                 % Reached a fixpoint
fixed_point(_, Base, Facts) :-                      % Base =/= Facts => not a fixpoint
    setof(Fact, derived(Fact, Base), NewFacts),     % Derive new facts
    ord_union(NewFacts, Base, NewBase),             % Add new facts to base
    fixed_point(Base, NewBase, Facts).              % Repeat with new base

derived(Fact, Base) :-
    rule(Fact if Condition),                        % Match a rule
    satisfy(Base, Condition).                       % Verify if condition is satisfied given base

satisfy(Base, G and Gs) :-                          % Condition is a conjunction
    !,
    member(G, Base),
    satisfy(Base, Gs).
satisfy(Base, G or Gs) :-                           % Condition is a disjunction
    !,
    (   member(G, Base)
    ;   satisfy(Base, Gs) ).
satisfy(_, callp(X)) :-                             % Condition is a callable fact
    !,
    call(X).
satisfy(Base, Condition) :-                         % Condition is an atomic proposition
    member(Condition, Base).
</code>```

Simple knowledge base to test it:

```<code>rule(eats_flies(fritz) if true).
rule(croaks(fritz)     if true).
rule(eats_flies(frotz) if true).
rule(croaks(frotz)     if true).
rule(sings(tweety)     if true).
rule(chips(tweety)     if true).
rule(has_wings(tweety) if true).
rule(croaks(krogr)    if true).
rule(chips(kroger)     if true).
rule(canary(X)         if and(sings(X),chips(X),has_wings(X))).
rule(frog(X)           if and(croaks(X),eats_flies(X))).
rule(green(X)          if frog(X)).
rule(yellow(X)         if canary(X)).
rule(node(a) if true).
rule(node(b) if true).
rule(node(c) if true).
rule(node(d) if true).
rule(node(e) if true).
rule(connected(a,b) if true).
rule(connected(b,c) if true).
rule(connected(c,d) if true).
rule(connected(d,e) if true).
rule(funny(c,d) if true).
rule(wonderful(X,Y) if or(nice(X,Y),funny(X,Y))).
rule(connected(X,Z) if and(connected(X,Y),connected(Y,Z))).
rule(path([Node|[]]) if node(Node)).
rule(path([Node, NextNode|Nodes]) if and(connected(Node, NextNode),path([NextNode|Nodes]))).
rule(int(1) if true).
rule(int(0) if true).
rule(int(2) if true).
rule(iszero(X) if and(int(X), callp(X = 0))).

rule(has_at_least_n([_|Tail], 0) if true).
rule(has_at_least_n([X|Tail], N) if and(node(X), callp(NewN is N-1), has_at_least_n(Tail, NewN))).
rule(has_at_least_n([X|Tail], N) if and(has_at_least_n(Tail, N))).
</code>```

Now I would like to solve a problem with the last rules about lists. I would like to be able to count the elements of a list. So I would like to be able to say, for example, that the list:

```<code>[a,b,c,d,e]
</code>```

has at least 5 nodes,
and a list like:

```<code>[a,x,y,c,d]
</code>```

has not 5 nodes

with the rule I built, the forward loops itself by finding every time a fact like:

```<code>has_at_least_n([_|_], 0)
</code>```

since every time it can unify that _ with anything.

Any tips on how should I handle this case? How can I have rules on lists avoiding infinite loops?

Still my forward is not able to find any other rule different from the dummy one with the has_at_least_n([_|_], 0).

EDIT:

Using gtrace for debugging, I found out that, if the and or the or have more than two facts inside the brackets, it is not recognized as satisfy(Base, G and Gs) /  satisfy(Base, G or Gs), but only satisfy(Base, Condition), and of course the member(Condition, Base) is false since and(..., ..., ..., ...) is not in Base.

When there are just two facts, instead, I see in the debugger that they have a different representation : fact1 and fact2
And this matches the rule.

答:
As I suggested before, a possible solution is as follows:

```<code>:- op(1100, xfx, if).
:- op(1000, xfy, or).
:- op(900, xfy, and).

forward(Steps, FinalBase) :-
    forward_iteration(Steps, nil, [true], FinalBase).                 % Current base is [true]

forward_iteration(Steps, PreviousBase, CurrentBase, FinalBase) :-
    (   ( Steps = 0                                                   % Reached max iterations
        ; PreviousBase = CurrentBase )                                % Reached a fixed point
    ->  FinalBase = CurrentBase
    ;   setof(Fact, derived(Fact, CurrentBase), NewFacts),            % Derive new facts
        ord_union(NewFacts, CurrentBase, NewBase),                    % Add new facts into current base
        succ(Steps0, Steps),
        forward_iteration(Steps0, CurrentBase, NewBase, FinalBase) ). % Repeat with new base

derived(Fact, Base) :-
    rule(Fact if Condition),                                          % Match a rule
    satisfy(Base, Condition).                                         % Condition holds in current base

satisfy(Base, G and Gs) :-                                            % Condition is a conjunction
    !,
    member(G, Base),
    satisfy(Base, Gs).

satisfy(Base, G or Gs) :-                                            % Condition is a disjunction
    !,
    (   member(G, Base)
    ;   satisfy(Base, Gs) ).

satisfy(_Base, call(Fact)) :-                                        % Condition is a callable fact
    !,
    call(Fact).

satisfy(Base, Condition) :-                                          % Condition is an atomic proposition
    member(Condition, Base).
</code>```

Note that and is a binary operator, not an arbitrary arity functor! So, for example, we can define len/2 as:

```<code>rule(item(X) if call(member(X, [a,b,c]))).
rule(len([], 0) if true).
rule(len([H|T], N) if len(T,M) and item(H) and call(succ(M,N))).
</code>```

Running examples:

```<code>?- forward(1, FinalBase), maplist(writeln, FinalBase).
true
item(a)
item(b)
item(c)
len([],0)
FinalBase = [true, item(a), item(b), item(c), len([], 0)].

?- forward(2, FinalBase), maplist(writeln, FinalBase).
true
item(a)
item(b)
item(c)
len([],0)
len([a],1)
len([b],1)
len([c],1)
FinalBase = [true, item(a), item(b), item(c), len([], 0), len([a], 1), len([b], 1), len([...], 1)].

?- forward(3, FinalBase), maplist(writeln, FinalBase).
true
item(a)
item(b)
item(c)
len([],0)
len([a],1)
len([a,a],2)
len([a,b],2)
len([a,c],2)
len([b],1)
len([b,a],2)
len([b,b],2)
len([b,c],2)
len([c],1)
len([c,a],2)
len([c,b],2)
len([c,c],2)
FinalBase = [true, item(a), item(b), item(c), len([], 0), len([a], 1), len([a|...], 2), len([...|...], 2), len(..., ...)|...].
</code>```

Body:
In previous question, we built a simple forward chaining in Prolog together with the user slago, and solved some problems about it.
Code for forward chaining:

:- op(1100, xfx, if).
:- op(1000, xfy, or).
:- op(900, xfy, and).

forward(Facts) :-
    fixed_point(nil, [true], Facts).                % Start with the base with only true

fixed_point(Base, Base, Base) :- !.                 % Reached a fixpoint
fixed_point(_, Base, Facts) :-                      % Base =/= Facts => not a fixpoint
    setof(Fact, derived(Fact, Base), NewFacts),     % Derive new facts
    ord_union(NewFacts, Base, NewBase),             % Add new facts to base
    fixed_point(Base, NewBase, Facts).              % Repeat with new base

derived(Fact, Base) :-
    rule(Fact if Condition),                        % Match a rule
    satisfy(Base, Condition).                       % Verify if condition is satisfied given base

satisfy(Base, G and Gs) :-                          % Condition is a conjunction
    !,
    member(G, Base),
    satisfy(Base, Gs).
satisfy(Base, G or Gs) :-                           % Condition is a disjunction
    !,
    (   member(G, Base)
    ;   satisfy(Base, Gs) ).
satisfy(_, callp(X)) :-                             % Condition is a callable fact
    !,
    call(X).
satisfy(Base, Condition) :-                         % Condition is an atomic proposition
    member(Condition, Base).

Simple knowledge base to test it:

rule(eats_flies(fritz) if true).
rule(croaks(fritz)     if true).
rule(eats_flies(frotz) if true).
rule(croaks(frotz)     if true).
rule(sings(tweety)     if true).
rule(chips(tweety)     if true).
rule(has_wings(tweety) if true).
rule(croaks(krogr)    if true).
rule(chips(kroger)     if true).
rule(canary(X)         if and(sings(X),chips(X),has_wings(X))).
rule(frog(X)           if and(croaks(X),eats_flies(X))).
rule(green(X)          if frog(X)).
rule(yellow(X)         if canary(X)).
rule(node(a) if true).
rule(node(b) if true).
rule(node(c) if true).
rule(node(d) if true).
rule(node(e) if true).
rule(connected(a,b) if true).
rule(connected(b,c) if true).
rule(connected(c,d) if true).
rule(connected(d,e) if true).
rule(funny(c,d) if true).
rule(wonderful(X,Y) if or(nice(X,Y),funny(X,Y))).
rule(connected(X,Z) if and(connected(X,Y),connected(Y,Z))).
rule(path([Node|[]]) if node(Node)).
rule(path([Node, NextNode|Nodes]) if and(connected(Node, NextNode),path([NextNode|Nodes]))).
rule(int(1) if true).
rule(int(0) if true).
rule(int(2) if true).
rule(iszero(X) if and(int(X), callp(X = 0))).

rule(has_at_least_n([_|Tail], 0) if true).
rule(has_at_least_n([X|Tail], N) if and(node(X), callp(NewN is N-1), has_at_least_n(Tail, NewN))).
rule(has_at_least_n([X|Tail], N) if and(has_at_least_n(Tail, N))).

Now I would like to solve a problem with the last rules about lists. I would like to be able to count the elements of a list. So I would like to be able to say, for example, that the list:

[a,b,c,d,e]

has at least 5 nodes,
and a list like:

[a,x,y,c,d]

has not 5 nodes

with the rule I built, the forward loops itself by finding every time a fact like:

has_at_least_n([_|_], 0)

since every time it can unify that _ with anything.

Any tips on how should I handle this case? How can I have rules on lists avoiding infinite loops?

Still my forward is not able to find any other rule different from the dummy one with the has_at_least_n([_|_], 0).

EDIT:

Using gtrace for debugging, I found out that, if the and or the or have more than two facts inside the brackets, it is not recognized as satisfy(Base, G and Gs) /  satisfy(Base, G or Gs), but only satisfy(Base, Condition), and of course the member(Condition, Base) is false since and(..., ..., ..., ...) is not in Base.

When there are just two facts, instead, I see in the debugger that they have a different representation : fact1 and fact2
And this matches the rule.

Body:
As I suggested before, a possible solution is as follows:

:- op(1100, xfx, if).
:- op(1000, xfy, or).
:- op(900, xfy, and).

forward(Steps, FinalBase) :-
    forward_iteration(Steps, nil, [true], FinalBase).                 % Current base is [true]

forward_iteration(Steps, PreviousBase, CurrentBase, FinalBase) :-
    (   ( Steps = 0                                                   % Reached max iterations
        ; PreviousBase = CurrentBase )                                % Reached a fixed point
    ->  FinalBase = CurrentBase
    ;   setof(Fact, derived(Fact, CurrentBase), NewFacts),            % Derive new facts
        ord_union(NewFacts, CurrentBase, NewBase),                    % Add new facts into current base
        succ(Steps0, Steps),
        forward_iteration(Steps0, CurrentBase, NewBase, FinalBase) ). % Repeat with new base

derived(Fact, Base) :-
    rule(Fact if Condition),                                          % Match a rule
    satisfy(Base, Condition).                                         % Condition holds in current base

satisfy(Base, G and Gs) :-                                            % Condition is a conjunction
    !,
    member(G, Base),
    satisfy(Base, Gs).

satisfy(Base, G or Gs) :-                                            % Condition is a disjunction
    !,
    (   member(G, Base)
    ;   satisfy(Base, Gs) ).

satisfy(_Base, call(Fact)) :-                                        % Condition is a callable fact
    !,
    call(Fact).

satisfy(Base, Condition) :-                                          % Condition is an atomic proposition
    member(Condition, Base).

Note that and is a binary operator, not an arbitrary arity functor! So, for example, we can define len/2 as:

rule(item(X) if call(member(X, [a,b,c]))).
rule(len([], 0) if true).
rule(len([H|T], N) if len(T,M) and item(H) and call(succ(M,N))).

Running examples:

?- forward(1, FinalBase), maplist(writeln, FinalBase).
true
item(a)
item(b)
item(c)
len([],0)
FinalBase = [true, item(a), item(b), item(c), len([], 0)].

?- forward(2, FinalBase), maplist(writeln, FinalBase).
true
item(a)
item(b)
item(c)
len([],0)
len([a],1)
len([b],1)
len([c],1)
FinalBase = [true, item(a), item(b), item(c), len([], 0), len([a], 1), len([b], 1), len([...], 1)].

?- forward(3, FinalBase), maplist(writeln, FinalBase).
true
item(a)
item(b)
item(c)
len([],0)
len([a],1)
len([a,a],2)
len([a,b],2)
len([a,c],2)
len([b],1)
len([b,a],2)
len([b,b],2)
len([b,c],2)
len([c],1)
len([c,a],2)
len([c,b],2)
len([c,c],2)
FinalBase = [true, item(a), item(b), item(c), len([], 0), len([a], 1), len([a|...], 2), len([...|...], 2), len(..., ...)|...].


来源: stackexchange

问:
DigitalOcean API + cloud-config - install Node v14
I want to invoke Digital Ocean create droplet API to create a droplet with NodeJS v14 installed immediately. I invoked the API, get the IP, log in with SSH, but nothing is installed. Not sure what I am doing wrong or how to even debug it.

My API request:

```<code>curl --location --request POST 'https://api.digitalocean.com/v2/droplets' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data-raw '{
  "names": [
    "test"
  ],
  "region": "nyc3",
  "size": "s-1vcpu-1gb",
  "image": "ubuntu-21-10-x64",
  "ssh_keys": [
    "my-key-fingerprint"
  ],
  "backups": false,
  "ipv6": true,
  "user_data": "#cloud-config\n\npackage_update: true\npackage_upgrade: false\npackage_reboot_if_required: false\n\nruncmd:\n  - '\''curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash'\''\n  - '\''source .bashrc'\''\n  - '\''nvm install v14.19.0'\''",
  "private_networking": null,
  "volumes": null,
  "tags": [
    "test"
  ]
}'
</code>```

If I enter the 3 following thing manually in the ssh shell then it installs the Node just fine:

```<code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
source .bashrc
nvm install v14.19.0
</code>```

答:
You should check the Droplet's logs to determine what happened:

more /var/log/cloud-init-output.log
```
<p>For your script:</p>
```  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

=> Downloading nvm from git to '/.nvm'

=> Compressing and cleaning up git repository

=> Profile not found. Tried ~/.bashrc, ~/.bash_profile, ~/.zshrc, and ~/.profile.
=> Create one of them and run this script again
   OR
=> Append the following lines to the correct file yourself:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm

=> Close and reopen your terminal to start using nvm or run the following to use it now:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
/var/lib/cloud/instance/scripts/runcmd: 3: source: not found
/var/lib/cloud/instance/scripts/runcmd: 4: nvm: not found
2022-02-13 17:57:03,777 - cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)
2022-02-13 17:57:03,778 - util.py[WARNING]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_scripts_user.py'>) failed
```

ContentLicense: CC BY-SA 4.0

Body:
I want to invoke Digital Ocean create droplet API to create a droplet with NodeJS v14 installed immediately. I invoked the API, get the IP, log in with SSH, but nothing is installed. Not sure what I am doing wrong or how to even debug it.

My API request:

curl --location --request POST 'https://api.digitalocean.com/v2/droplets' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data-raw '{
  "names": [
    "test"
  ],
  "region": "nyc3",
  "size": "s-1vcpu-1gb",
  "image": "ubuntu-21-10-x64",
  "ssh_keys": [
    "my-key-fingerprint"
  ],
  "backups": false,
  "ipv6": true,
  "user_data": "#cloud-config\n\npackage_update: true\npackage_upgrade: false\npackage_reboot_if_required: false\n\nruncmd:\n  - '\''curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash'\''\n  - '\''source .bashrc'\''\n  - '\''nvm install v14.19.0'\''",
  "private_networking": null,
  "volumes": null,
  "tags": [
    "test"
  ]
}'

If I enter the 3 following thing manually in the ssh shell then it installs the Node just fine:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
source .bashrc
nvm install v14.19.0

Body:
You should check the Droplet's logs to determine what happened:

more /var/log/cloud-init-output.log

For your script:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

=> Downloading nvm from git to '/.nvm'

=> Compressing and cleaning up git repository

=> Profile not found. Tried ~/.bashrc, ~/.bash_profile, ~/.zshrc, and ~/.profile.
=> Create one of them and run this script again
   OR
=> Append the following lines to the correct file yourself:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm

=> Close and reopen your terminal to start using nvm or run the following to use it now:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
/var/lib/cloud/instance/scripts/runcmd: 3: source: not found
/var/lib/cloud/instance/scripts/runcmd: 4: nvm: not found
2022-02-13 17:57:03,777 - cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)
2022-02-13 17:57:03,778 - util.py[WARNING]: Running module scripts-user (<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_scripts_user.py'>) failed


问:
Twilio REST API sequential Dialling
I really can't figure out why my code isn't working because Twilio's debugger isnt giving me errors so I don't know what to do...I am trying to make Sequential dialing in REST api using Twilio so it should keep calling numbers in order until one person picks up..Below is my code I have written so far. I am using sessions to keep track of the calls.

File Name:dial.php

```<code><?php
session_start();

    require 'Services/Twilio.php';
    $version = "2010-04-01";

$arr = array('4167641123','6478604321','9058553456');

    $sid = '....';
    $token = '...';
    $from = '....';
    $to = '416.....';
    $callback = 'www.site.com/dial.php';

    $client = new Services_Twilio($sid, $token, $version);

    //if this is our very first call then CallStatus should be empty so it means we can use the emptiness of this variable
    //to trigger our very first call
    if (!(isset($_REQUEST['CallStatus'])))
    {
    try {
        $call = $client->account->calls->create(
            $from,
            $arr[0],
            'http://demo.twilio.com/welcome/voice/',
            array('Timeout' => 1,
                  'StatusCallback' => $callback)
            );
            var_dump($call);
        } catch (Exception $e) {
            var_dump($e);
        }
}
// if the CallStatus variable is not empty then the else statement will execute
else
{
//if this part of code runs for the first time, it means this is our 2nd call because the 1st person did not pick up
//this means the second number in the array will be called
//each time this statement runs it adds a 1 to the index of the array but if the last index number called was the final and
//last number in the array, then this statement wont run and instead session at the bottom if statement will be initialized to 0
//so that if this script is ran again it will start off from the first number in the array
if (!($_SESSION['X']>=count($arr)-1) && isset($_REQUEST['CallStatus']) && ($_REQUEST['CallStatus']=='failed'|| $_REQUEST['CallStatus']=='no-answer' || $_REQUEST['CallStatus']=='busy'))
{

$_SESSION['X']=$_SESSION['X']+1;

    try {
        $call = $client->account->calls->create(
            $from,
            $arr[SESSION['X']],
            'http://demo.twilio.com/welcome/voice/',
            array('Timeout' => 1,
                  'StatusCallback' => $callback)
            );
            var_dump($call);
        } catch (Exception $e) {
            var_dump($e);
        }
}
//initializes the session to 0 because if we have reached to this else statement,
//then it means the if statement above did not run and we have already called the last person
//in the phone number array so we are at an end and we must close the program
//by leaving session at 0 for the next trial to run properly
else
{

$_SESSION['X']=0;

}

}
</code>```

I have this other file same, sequential diallnig written using php and twilio's Dial verb, the Dial verb's parameters allow it to pass the array index but in my case I don't know how to pass the array index parameter....any ideas?

```<code><?php

// Set the numbers to call
$numbers = array("<number to call 1>", "<number to call 2>", "<number to call n>");
$number_index = isset($_REQUEST['number_index']) ? $_REQUEST['number_index'] : "0";
$DialCallStatus = isset($_REQUEST['DialCallStatus']) ? $_REQUEST['DialCallStatus'] : "";

header("content-type: text/xml");

// Check the status of the call and
// that there is a valid number to call

if($DialCallStatus!="completed" && $number_index<count($numbers)){
?>
    <Response>
    <Dial action="attempt_call.php?number_index=<?php echo $number_index+1 ?>">
        <Number url="screen_for_machine.php">
        <?php echo $numbers[$number_index] ?>
        </Number>
    </Dial>
    </Response>
<?php
} else {
?>
    <Response>
        <Hangup/>
    </Response>
<?php
}
?>
</code>```

答:
Your code has syntax errors and such.

For example SESSION['X']=0; is not doing what you might have thought it is doing. If that's a session variable, it should be written as $_SESSION['X']=0;.

To spot these issues, enable error reporting to the highest level, then log errors to a file and then watch that file. It will give you some hints.

See Error Handling and Logging Docs.

ContentLicense: CC BY-SA 3.0

Title: Twilio REST API sequential Dialling

Body:
I really can't figure out why my code isn't working because Twilio's debugger isnt giving me errors so I don't know what to do...I am trying to make Sequential dialing in REST api using Twilio so it should keep calling numbers in order until one person picks up..Below is my code I have written so far. I am using sessions to keep track of the calls.

File Name:dial.php

<?php
session_start();

    require 'Services/Twilio.php';
    $version = "2010-04-01";

$arr = array('4167641123','6478604321','9058553456');

    $sid = '....';
    $token = '...';
    $from = '....';
    $to = '416.....';
    $callback = 'www.site.com/dial.php';

    $client = new Services_Twilio($sid, $token, $version);

    //if this is our very first call then CallStatus should be empty so it means we can use the emptiness of this variable
    //to trigger our very first call
    if (!(isset($_REQUEST['CallStatus'])))
    {
    try {
        $call = $client->account->calls->create(
            $from,
            $arr[0],
            'http://demo.twilio.com/welcome/voice/',
            array('Timeout' => 1,
                  'StatusCallback' => $callback)
            );
            var_dump($call);
        } catch (Exception $e) {
            var_dump($e);
        }
}
// if the CallStatus variable is not empty then the else statement will execute
else
{
//if this part of code runs for the first time, it means this is our 2nd call because the 1st person did not pick up
//this means the second number in the array will be called
//each time this statement runs it adds a 1 to the index of the array but if the last index number called was the final and
//last number in the array, then this statement wont run and instead session at the bottom if statement will be initialized to 0
//so that if this script is ran again it will start off from the first number in the array
if (!($_SESSION['X']>=count($arr)-1) && isset($_REQUEST['CallStatus']) && ($_REQUEST['CallStatus']=='failed'|| $_REQUEST['CallStatus']=='no-answer' || $_REQUEST['CallStatus']=='busy'))
{

$_SESSION['X']=$_SESSION['X']+1;

    try {
        $call = $client->account->calls->create(
            $from,
            $arr[SESSION['X']],
            'http://demo.twilio.com/welcome/voice/',
            array('Timeout' => 1,
                  'StatusCallback' => $callback)
            );
            var_dump($call);
        } catch (Exception $e) {
            var_dump($e);
        }
}
//initializes the session to 0 because if we have reached to this else statement,
//then it means the if statement above did not run and we have already called the last person
//in the phone number array so we are at an end and we must close the program
//by leaving session at 0 for the next trial to run properly
else
{

$_SESSION['X']=0;

}

}

I have this other file same, sequential diallnig written using php and twilio's Dial verb, the Dial verb's parameters allow it to pass the array index but in my case I don't know how to pass the array index parameter....any ideas?

<?php

// Set the numbers to call
$numbers = array("<number to call 1>", "<number to call 2>", "<number to call n>");
$number_index = isset($_REQUEST['number_index']) ? $_REQUEST['number_index'] : "0";
$DialCallStatus = isset($_REQUEST['DialCallStatus']) ? $_REQUEST['DialCallStatus'] : "";

header("content-type: text/xml");

// Check the status of the call and
// that there is a valid number to call

if($DialCallStatus!="completed" && $number_index<count($numbers)){
?>
    <Response>
    <Dial action="attempt_call.php?number_index=<?php echo $number_index+1 ?>">
        <Number url="screen_for_machine.php">
        <?php echo $numbers[$number_index] ?>
        </Number>
    </Dial>
    </Response>
<?php
} else {
?>
    <Response>
        <Hangup/>
    </Response>
<?php
}
?>


问:
Drag and drop files to QTableWidget
I'm trying to drag and drop files into a table-widget, but the path will not appear when I drop the files. When I test by using print() the path appears, but the path will not appear in the table. I am not sure why this is happening, I would greatly appreciate some help.

Main code:

```<code>import os
import shutil
import sys

import pandas as pd
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import *

from vituix_converter_UI import (Ui_MainWindow)

def no_file_selected():
    msg = QMessageBox()
    msg.setIcon(QMessageBox.Warning)
    msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
    msg.setText("No File Was Selected!")
    msg.setWindowTitle("Warning!")
    retval = msg.exec_()

def process_completed():
    msg = QMessageBox()
    msg.setIcon(QMessageBox.Information)
    msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
    msg.setText("Files are converted.")
    msg.setWindowTitle("Completed!")
    retval = msg.exec_()

class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)

        self.pushButton_hats.clicked.connect(self.hats_conversion)
        self.pushButton_sams.clicked.connect(self.sams_conversion)

        self.tableWidget.setAcceptDrops(True)
        self.tableWidget.viewport().installEventFilter(self)
        types = ['text/uri-list']
        types.extend(self.tableWidget.mimeTypes())
        self.tableWidget.mimeTypes = lambda: types
        self.tableWidget.setRowCount(0)

        self.tableWidget.dropEvent(self.eventFilter())

    def hats_conversion(self):

        hats_file = QtWidgets.QFileDialog.getOpenFileName(self, "Select HATS File", "", 'txt (*.txt)')[0]

        if hats_file == '':
            no_file_selected()
        else:

            hats_data = pd.read_csv(hats_file, sep="\t", skiprows=3, header=None, on_bad_lines='skip')

            txt_name = []

            for i in range(1, 148, 2):
                txt_name.append(hats_data.loc[0, i])

            hats_data = hats_data.drop([0, 1])
            hats_data = hats_data.reset_index(drop=True)
            # Select folder to save data output
            save_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select HATS Save Folder")
            # iteration variable for lists in following for loop
            i = 1
            # iterate over all text names, allocate corresponding data, and then save as txt
            for j in range(0, len(txt_name)):
                test_df_1 = hats_data[0].values.tolist()
                test_df_2 = hats_data[i].values.tolist()
                test_df_3 = hats_data[i + 1].values.tolist()

                export_df = pd.DataFrame(
                    {'0': test_df_1,
                     '1': test_df_2,
                     '2': test_df_3
                     })

                save_file = save_folder + '/' + txt_name[j] + '.txt'
                export_df.to_csv(save_file, sep='\t', index=False, na_rep='NaN', header=False)
                i = i + 2

            process_completed()

    def sams_conversion(self):

        sams_file = QtWidgets.QFileDialog.getExistingDirectory(self, "Select SAMS Folder")

        if sams_file == '':
            no_file_selected()
        else:
            output_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select/Create Save Folder")

            if output_folder == '':
                no_file_selected()

            else:

                file_names = []
                for x in os.listdir(sams_file):
                    if x.endswith(".txt"):
                        file_names.append(x)

                for i in range(len(file_names)):
                    newPath = shutil.copy(os.path.join(sams_file, file_names[i]), output_folder)

                    sams_data = pd.read_csv(newPath, sep="\t", skiprows=5, header=None, on_bad_lines='skip')

                    sams_data.to_csv(newPath, sep='\t', index=False, na_rep='NaN', header=False)

                process_completed()

    def eventFilter(self, source, event):
        if event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                self.addFile(url.toLocalFile())

            return True
        return super().eventFilter(source, event)

    def addFile(self, filepath):
        row = self.tableWidget.rowCount()
        self.tableWidget.insertRow(row)
        item = QtWidgets.QTableWidgetItem(filepath)
        self.tableWidget.setItem(row, 0, item)
        self.tableWidget.resizeColumnToContents(0)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
    win = MyMainWindow()
    win.show()
    sys.exit(app.exec_())
</code>```

UI code:

```<code># -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'vituix converter.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(400, 500)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(400, 500))
        MainWindow.setMaximumSize(QtCore.QSize(400, 500))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Icon/Vituix_Converter_Icon_R1.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
        self.tableWidget.setSizePolicy(sizePolicy)
        self.tableWidget.setMinimumSize(QtCore.QSize(0, 350))
        self.tableWidget.setDragEnabled(False)
        self.tableWidget.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
        self.tableWidget.setDefaultDropAction(QtCore.Qt.LinkAction)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.verticalLayout.addWidget(self.tableWidget, 0, QtCore.Qt.AlignVCenter)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.gridLayout.setVerticalSpacing(6)
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton_hats = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_hats.setMinimumSize(QtCore.QSize(0, 55))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(True)
        font.setWeight(75)
        self.pushButton_hats.setFont(font)
        self.pushButton_hats.setObjectName("pushButton_hats")
        self.gridLayout.addWidget(self.pushButton_hats, 0, 0, 1, 1)
        self.pushButton_sams = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_sams.setMinimumSize(QtCore.QSize(0, 55))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(True)
        font.setWeight(75)
        self.pushButton_sams.setFont(font)
        self.pushButton_sams.setObjectName("pushButton_sams")
        self.gridLayout.addWidget(self.pushButton_sams, 0, 1, 1, 1, QtCore.Qt.AlignVCenter)
        self.verticalLayout.addLayout(self.gridLayout)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Vituix Converter"))
        self.pushButton_hats.setText(_translate("MainWindow", "Vituix HATS"))
        self.pushButton_sams.setText(_translate("MainWindow", "Vituix SAMS"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
</code>```

答:
In order to do this using an event-filter, you need to handle the drag-enter, drag-move and drag-drop events, and accept the events when the mime-data contains urls. The following changes to your example should work as expected:</p>
```<code>class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        ...
        self.tableWidget.setAcceptDrops(True)
        self.tableWidget.viewport().installEventFilter(self)
        self.tableWidget.setRowCount(0)
        self.tableWidget.setColumnCount(1)

    def eventFilter(self, source, event):
        if (source is self.tableWidget.viewport() and
            (event.type() == QtCore.QEvent.DragEnter or
             event.type() == QtCore.QEvent.DragMove or
             event.type() == QtCore.QEvent.Drop) and
            event.mimeData().hasUrls()):
            if event.type() == QtCore.QEvent.Drop:
                for url in event.mimeData().urls():
                    if url.isLocalFile():
                        self.addFile(url.path())
            event.accept()
            return True
        return super().eventFilter(source, event)
</code>```

Title: Drag and drop files to QTableWidget

Body:
I'm trying to drag and drop files into a table-widget, but the path will not appear when I drop the files. When I test by using print() the path appears, but the path will not appear in the table. I am not sure why this is happening, I would greatly appreciate some help.

Main code:

import os
import shutil
import sys

import pandas as pd
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import *

from vituix_converter_UI import (Ui_MainWindow)

def no_file_selected():
    msg = QMessageBox()
    msg.setIcon(QMessageBox.Warning)
    msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
    msg.setText("No File Was Selected!")
    msg.setWindowTitle("Warning!")
    retval = msg.exec_()

def process_completed():
    msg = QMessageBox()
    msg.setIcon(QMessageBox.Information)
    msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
    msg.setText("Files are converted.")
    msg.setWindowTitle("Completed!")
    retval = msg.exec_()

class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)

        self.pushButton_hats.clicked.connect(self.hats_conversion)
        self.pushButton_sams.clicked.connect(self.sams_conversion)

        self.tableWidget.setAcceptDrops(True)
        self.tableWidget.viewport().installEventFilter(self)
        types = ['text/uri-list']
        types.extend(self.tableWidget.mimeTypes())
        self.tableWidget.mimeTypes = lambda: types
        self.tableWidget.setRowCount(0)

        self.tableWidget.dropEvent(self.eventFilter())

    def hats_conversion(self):

        hats_file = QtWidgets.QFileDialog.getOpenFileName(self, "Select HATS File", "", 'txt (*.txt)')[0]

        if hats_file == '':
            no_file_selected()
        else:

            hats_data = pd.read_csv(hats_file, sep="\t", skiprows=3, header=None, on_bad_lines='skip')

            txt_name = []

            for i in range(1, 148, 2):
                txt_name.append(hats_data.loc[0, i])

            hats_data = hats_data.drop([0, 1])
            hats_data = hats_data.reset_index(drop=True)
            # Select folder to save data output
            save_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select HATS Save Folder")
            # iteration variable for lists in following for loop
            i = 1
            # iterate over all text names, allocate corresponding data, and then save as txt
            for j in range(0, len(txt_name)):
                test_df_1 = hats_data[0].values.tolist()
                test_df_2 = hats_data[i].values.tolist()
                test_df_3 = hats_data[i + 1].values.tolist()

                export_df = pd.DataFrame(
                    {'0': test_df_1,
                     '1': test_df_2,
                     '2': test_df_3
                     })

                save_file = save_folder + '/' + txt_name[j] + '.txt'
                export_df.to_csv(save_file, sep='\t', index=False, na_rep='NaN', header=False)
                i = i + 2

            process_completed()

    def sams_conversion(self):

        sams_file = QtWidgets.QFileDialog.getExistingDirectory(self, "Select SAMS Folder")

        if sams_file == '':
            no_file_selected()
        else:
            output_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select/Create Save Folder")

            if output_folder == '':
                no_file_selected()

            else:

                file_names = []
                for x in os.listdir(sams_file):
                    if x.endswith(".txt"):
                        file_names.append(x)

                for i in range(len(file_names)):
                    newPath = shutil.copy(os.path.join(sams_file, file_names[i]), output_folder)

                    sams_data = pd.read_csv(newPath, sep="\t", skiprows=5, header=None, on_bad_lines='skip')

                    sams_data.to_csv(newPath, sep='\t', index=False, na_rep='NaN', header=False)

                process_completed()

    def eventFilter(self, source, event):
        if event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                self.addFile(url.toLocalFile())

            return True
        return super().eventFilter(source, event)

    def addFile(self, filepath):
        row = self.tableWidget.rowCount()
        self.tableWidget.insertRow(row)
        item = QtWidgets.QTableWidgetItem(filepath)
        self.tableWidget.setItem(row, 0, item)
        self.tableWidget.resizeColumnToContents(0)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
    win = MyMainWindow()
    win.show()
    sys.exit(app.exec_())

UI code:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'vituix converter.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(400, 500)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(400, 500))
        MainWindow.setMaximumSize(QtCore.QSize(400, 500))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Icon/Vituix_Converter_Icon_R1.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
        self.tableWidget.setSizePolicy(sizePolicy)
        self.tableWidget.setMinimumSize(QtCore.QSize(0, 350))
        self.tableWidget.setDragEnabled(False)
        self.tableWidget.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
        self.tableWidget.setDefaultDropAction(QtCore.Qt.LinkAction)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.verticalLayout.addWidget(self.tableWidget, 0, QtCore.Qt.AlignVCenter)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.gridLayout.setVerticalSpacing(6)
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton_hats = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_hats.setMinimumSize(QtCore.QSize(0, 55))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(True)
        font.setWeight(75)
        self.pushButton_hats.setFont(font)
        self.pushButton_hats.setObjectName("pushButton_hats")
        self.gridLayout.addWidget(self.pushButton_hats, 0, 0, 1, 1)
        self.pushButton_sams = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_sams.setMinimumSize(QtCore.QSize(0, 55))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(True)
        font.setWeight(75)
        self.pushButton_sams.setFont(font)
        self.pushButton_sams.setObjectName("pushButton_sams")
        self.gridLayout.addWidget(self.pushButton_sams, 0, 1, 1, 1, QtCore.Qt.AlignVCenter)
        self.verticalLayout.addLayout(self.gridLayout)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Vituix Converter"))
        self.pushButton_hats.setText(_translate("MainWindow", "Vituix HATS"))
        self.pushButton_sams.setText(_translate("MainWindow", "Vituix SAMS"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Body:
In order to do this using an event-filter, you need to handle the drag-enter, drag-move and drag-drop events, and accept the events when the mime-data contains urls. The following changes to your example should work as expected:

class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        ...
        self.tableWidget.setAcceptDrops(True)
        self.tableWidget.viewport().installEventFilter(self)
        self.tableWidget.setRowCount(0)
        self.tableWidget.setColumnCount(1)

    def eventFilter(self, source, event):
        if (source is self.tableWidget.viewport() and
            (event.type() == QtCore.QEvent.DragEnter or
             event.type() == QtCore.QEvent.DragMove or
             event.type() == QtCore.QEvent.Drop) and
            event.mimeData().hasUrls()):
            if event.type() == QtCore.QEvent.Drop:
                for url in event.mimeData().urls():
                    if url.isLocalFile():
                        self.addFile(url.path())
            event.accept()
            return True
        return super().eventFilter(source, event)


问:
Unity - how to get collision angle on trigger enter?
I'm trying to build a brick-breaker game, and I want to aim the ball according to where the ball hit the paddle.
For example if the ball hit paddle's right edge, it should go to the right (and up).
Assuming the paddle has a box (or capsule) collider and the ball has a sphere collider, how can I do this?
Thanks for any help!

And I want to get the pad's velocity as well. The code below returns 0, any ideas why?

```<code>function OnTriggerEnter(other:Collider)
{
    if(other.rigidbody){
    V_pad=other.rigidbody.velocity;
    //Here it returns (0,0,0) , also tried other.attachedRigidbody
    }

    if(other.name=="Pad"){
    rigidbody.velocity =
Vector3(rigidbody.velocity.x, Mathf.Abs(rigidbody.velocity.y + V_pad),0);
//this part executes but with V_pad.y=0
    }
}
</code>```

答:
You need to unCheck the  Is Trigger setting in the collider and use OnCollision instead of OnTrigger. In the OnCollision you can use something like this to calculate the output direction.

var direction = Vector3.Reflect(lastFrameVelocity.normalized, collision.contacts[0].normal);

Body:
I'm trying to build a brick-breaker game, and I want to aim the ball according to where the ball hit the paddle.
For example if the ball hit paddle's right edge, it should go to the right (and up).
Assuming the paddle has a box (or capsule) collider and the ball has a sphere collider, how can I do this?
Thanks for any help!

And I want to get the pad's velocity as well. The code below returns 0, any ideas why?

function OnTriggerEnter(other:Collider)
{
    if(other.rigidbody){
    V_pad=other.rigidbody.velocity;
    //Here it returns (0,0,0) , also tried other.attachedRigidbody
    }

    if(other.name=="Pad"){
    rigidbody.velocity =
Vector3(rigidbody.velocity.x, Mathf.Abs(rigidbody.velocity.y + V_pad),0);
//this part executes but with V_pad.y=0
    }
}


问:
How do I sort array by numbers and also prevent it from increasing more then 15 length and take only the biggest numbers?
here is my code for now:

```<code>router.get('/questions/best', function(req,res,next){
  Question.find({}).exec(function(err,results){
    if (err){return next(err)}
    let top15 = [];
    for(let i = 0; i< results.length; i++){
      let dislikestouse = results[i].dislikes[0]
      let ratio  = 0
      if(dislikestouse > 0){
        ratio = results[i].likes[0]/dislikestouse
      }
      else{
        ratio = results[i].likes[0]/1
      }

    }
    res.render('content', { whichOne: 5, user: req.user, questions: top15 });
  })
});
</code>```

results is every question in the database, and top15 is supposed to be only the ones displayed since they have the highest ratio and rendered into the template.
I tried using if statements to prevent it dividing by 0 since it results in an error.

how do I sort every result by finding if it is bigger then any of the items in top15 and then placing it in the right place if it is? I use pure JavaScript.
to access the numbers of a result's dislikes and likes search for the first item since it where I store the length, like a typical likes array is: [2,'username1', 'username2'].
here is the scheme for a question:

```<code>const Question = mongoose.model(
  "Question",
  new Schema({
    title: { type: String, required: true },
    text: { type: String },
    authorUsername: { type: String, required: true },
    dateCreated: {},
    answers: { type: Array, required: true },
    likes: { type: Array, required: true },
    dislikes: { type: Array, required: true },
    tag: { type: String, required: true },
    views: {type: Array, required:true},
  })
);
</code>```

here is an example of a question:

```<code>_id:620935985f6865b4e85c333d
title:"How do i make a lemon?"
text:"yeet"
authorUsername:"SweetWhite"
dateCreated:2022-02-13T16:45:12.598+00:00
answers:
Array
likes:
Array
0:1
1:"SweetWhite"
dislikes:
Array
0:0
tag:
"Social"
views:
Array
0:1
1:"SweetWhite"
__v:0
</code>```

Thanks!

答:
You could use Array methods:

sort: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

slice: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Here is snippet i tried for your problem:

function sortQuestions(results) {
  const questionsWithRatio = results.map((result) => ({
    ...result,
    ratio: result.likes[0] / Math.max(result.dislikes[0], 1),
  }));
  // console.log(questionsWithRatio);
  const top15 = questionsWithRatio
    .sort((a, b) => b.ratio - a.ratio)
    .slice(0, 15);
  console.log(top15);
}
```

Body:
here is my code for now:

router.get('/questions/best', function(req,res,next){
  Question.find({}).exec(function(err,results){
    if (err){return next(err)}
    let top15 = [];
    for(let i = 0; i< results.length; i++){
      let dislikestouse = results[i].dislikes[0]
      let ratio  = 0
      if(dislikestouse > 0){
        ratio = results[i].likes[0]/dislikestouse
      }
      else{
        ratio = results[i].likes[0]/1
      }

    }
    res.render('content', { whichOne: 5, user: req.user, questions: top15 });
  })
});

results is every question in the database, and top15 is supposed to be only the ones displayed since they have the highest ratio and rendered into the template.
I tried using if statements to prevent it dividing by 0 since it results in an error.

how do I sort every result by finding if it is bigger then any of the items in top15 and then placing it in the right place if it is? I use pure JavaScript.
to access the numbers of a result's dislikes and likes search for the first item since it where I store the length, like a typical likes array is: [2,'username1', 'username2'].
here is the scheme for a question:

const Question = mongoose.model(
  "Question",
  new Schema({
    title: { type: String, required: true },
    text: { type: String },
    authorUsername: { type: String, required: true },
    dateCreated: {},
    answers: { type: Array, required: true },
    likes: { type: Array, required: true },
    dislikes: { type: Array, required: true },
    tag: { type: String, required: true },
    views: {type: Array, required:true},
  })
);

here is an example of a question:

_id:620935985f6865b4e85c333d
title:"How do i make a lemon?"
text:"yeet"
authorUsername:"SweetWhite"
dateCreated:2022-02-13T16:45:12.598+00:00
answers:
Array
likes:
Array
0:1
1:"SweetWhite"
dislikes:
Array
0:0
tag:
"Social"
views:
Array
0:1
1:"SweetWhite"
__v:0

Thanks!


问:
How to retain the first observation in every 30 days in the dataset for each ID?
I have a dataset in which I need to keep the first incidence in the database and remove what happens in 30 days window after and redo the process again. Here is a demonstration

I want to keep all the rows with arrows and exclude the other ones.

Any help would be really appreciated.

Thanks

Body:
# Example data
set.seed(2022)
n <- 20
df <- data.frame(
  dt = rep(as.Date('2010-06-01'), n) + cumsum(sample(1:20, n, TRUE))
)

df
#>            dt
#> 1  2010-06-05
#> 2  2010-06-24
#> 3  2010-07-08
#> 4  2010-07-19
#> 5  2010-07-23
#> 6  2010-07-29
#> 7  2010-08-12
#> 8  2010-08-21
#> 9  2010-09-04
#> 10 2010-09-11
#> 11 2010-09-29
#> 12 2010-10-15
#> 13 2010-10-20
#> 14 2010-10-21
#> 15 2010-11-09
#> 16 2010-11-10
#> 17 2010-11-12
#> 18 2010-11-19
#> 19 2010-12-01
#> 20 2010-12-16

library(dplyr, warn.conflicts = FALSE)
library(purrr)

cutoff <- 25

df %>%
  # if date is < cutoff days of first date, maintain the same group
  # else create a new group
  group_by(g = accumulate(dt, ~ if (.y - .x < cutoff) .x else .y)) %>%
  # for each group select the first row
  slice_head(n = 1) %>%
  # ungroup and remove grouping variable
  ungroup() %>%
  select(-g)
#> # A tibble: 7 × 1
#>   dt
#>   <date>
#> 1 2010-06-05
#> 2 2010-07-08
#> 3 2010-08-12
#> 4 2010-09-11
#> 5 2010-10-15
#> 6 2010-11-09
#> 7 2010-12-16

Created on 2022-02-13 by the reprex package (v2.0.1)

Or, using data.table::rowid

library(dplyr, warn.conflicts = FALSE)
library(purrr)
library(data.table, warn.conflicts = FALSE)

cutoff <- 25

df %>%
  filter(rowid(accumulate(dt, ~ if (.y - .x < cutoff) .x else .y)) == 1)
#>           dt
#> 1 2010-06-05
#> 2 2010-07-08
#> 3 2010-08-12
#> 4 2010-09-11
#> 5 2010-10-15
#> 6 2010-11-09
#> 7 2010-12-16

Created on 2022-02-13 by the reprex package (v2.0.1)


答:
The table has no columns: setItemData() will be ignored if no valid row and column are given:

```<code>    def addFile(self, filepath):
        if not self.tableWidget.columnCount():
            self.tableWidget.setColumnCount(1)
        # ...
</code>```

Note that you must always check the event type in an event filter before accessing the event functions, otherwise you'll get an error or even a crash:

```<code>    def eventFilter(self, source, event):
        if event.type() == event.Drop and event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                self.addFile(url.toLocalFile())
            return True
        return super().eventFilter(source, event)
</code>```

Also, remove the following line, which is completely wrong:

```<code>        self.tableWidget.dropEvent(self.eventFilter())
</code>```

Title: Drag and drop files to QTableWidget

Body:
The table has no columns: setItemData() will be ignored if no valid row and column are given:

    def addFile(self, filepath):
        if not self.tableWidget.columnCount():
            self.tableWidget.setColumnCount(1)
        # ...

Note that you must always check the event type in an event filter before accessing the event functions, otherwise you'll get an error or even a crash:

    def eventFilter(self, source, event):
        if event.type() == event.Drop and event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                self.addFile(url.toLocalFile())
            return True
        return super().eventFilter(source, event)

Also, remove the following line, which is completely wrong:

        self.tableWidget.dropEvent(self.eventFilter())


问:
Select all values in Row "B" and "C" and move 1 step up
My Intention:

I wanna select all values in Rows "B" and "C" and move these 1 and 2 steps up.

The Example for what I have:

A
B
C

AA

Two

AA

Three

Two

AA

Three

Two

Three

X

yy

CC

The Example for what I would: If in Column-A find "X" should YY and CC delet

A
B
C

AA
Two
Three

AA
Two
Three

AA
Two
Three

My Code:

```<code>Sub test()

ActiveSheet.Select
Range("B:B").Select Shift:=xlUp, CopyOrigin:=xlFormatFromLeftOrAbove
Range("C:C").Select Shift:=xlUp, CopyOrigin:=xlFormatFromLeftOrAbove

End Sub
</code>```

I would be happy if somebody help me

答:
select all cells (A1:C5) and start the following macro

```<code>Sub FillCells()
Dim rngCell As Range

Do Until Application.WorksheetFunction.CountBlank(Selection) = 0

  For Each rngCell In Selection

  If rngCell.Value = "" Then

   rngCell.Value = rngCell.Offset(1, 0).Value

  End If

  Next rngCell

Loop

End Sub
</code>```

Best regards
Bernd

Body:
My Intention:

I wanna select all values in Rows "B" and "C" and move these 1 and 2 steps up.

The Example for what I have:

A
B
C

AA

Two

AA

Three

Two

AA

Three

Two

Three

X

yy

CC

The Example for what I would: If in Column-A find "X" should YY and CC delet

A
B
C

AA
Two
Three

AA
Two
Three

AA
Two
Three

My Code:

Sub test()

ActiveSheet.Select
Range("B:B").Select Shift:=xlUp, CopyOrigin:=xlFormatFromLeftOrAbove
Range("C:C").Select Shift:=xlUp, CopyOrigin:=xlFormatFromLeftOrAbove

End Sub

I would be happy if somebody help me

Body:
select all cells (A1:C5) and start the following macro

Sub FillCells()
Dim rngCell As Range

Do Until Application.WorksheetFunction.CountBlank(Selection) = 0

  For Each rngCell In Selection

  If rngCell.Value = "" Then

   rngCell.Value = rngCell.Offset(1, 0).Value

  End If

  Next rngCell

Loop

End Sub

Best regards
Bernd


问:
identifying Duplicates and flag the duplicate
Suppose if i have list input_list=["Name","Age","Address","nAme","Father","NAME","AGE"]

I have "name" multiple times but while checking I don't want it to be case sensitive.
if there is duplicate add 1 , 2 etc.

I am trying to remove Duplicates i want to add NaMe, Name1,NAME2
but order should be same

can you please help me achieve this output.

I want output final_list=["Name","Age","Address","nAme1","Father","NAME2","AGE1"]

答:
Here's one way to do it.

Make a set of lowercased entries from that list

lowered_set = {word.lower() for word in input_list}
```
<ol start="2">
<li>Make a dict with that set as keys</li>
</ol>
<pre class="lang-py prettyprint-override"><code>occurrences = {word: 0 for word in lowered_set}
</code>```

Walk the input_list, append count if the word was used already, and increment the count:

output_list = []
for word in input_list:
    lowered = word.lower()
    previous = occurrences[lowered]
    occurrences[lowered] += 1
    if previous:
        output_list.append(f"{word}{previous}")
    else:
        output_list.append(word)
```

There's surely a better way, though

Body:
Here's one way to do it.

Make a set of lowercased entries from that list

lowered_set = {word.lower() for word in input_list}

Make a dict with that set as keys

occurrences = {word: 0 for word in lowered_set}

Walk the input_list, append count if the word was used already, and increment the count:

output_list = []
for word in input_list:
    lowered = word.lower()
    previous = occurrences[lowered]
    occurrences[lowered] += 1
    if previous:
        output_list.append(f"{word}{previous}")
    else:
        output_list.append(word)

There's surely a better way, though


问:
"await" in Widget build FLUTTER
I've been stuck for several hours with a problem on flutter. If you can help me that would be really nice.

I need to put "await" in my Widget build(BuildContext context){} but it's impossible to put "async".
How to do ?

When i test void _myAsyncMethod()async{} :

答:
If your are using stateful widget you can instantiate firebase auth in initstate() method.

class testFirless extends StatefulWidget {
  var currentuseid = "";

  testFirless({Key? key}) : super(key: key);

  @override
  _testFirlessState createState() => _testFirlessState();
}
class _testFirlessState extends State<testFirless> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  // ------------------------------------>heree
  @override
  Future<void> initState() async {
    FirebaseAuth auth = FirebaseAuth.instance;

    var user = await auth.currentUser;
    if (user == null) {
      widget.currentuseid = user!.uid;
    } else {
      print('User is signed in!');
    }
  }
}
```
<ol start="2">
<li>FutureBuilder</li>
</ol>
<pre class="lang-dart prettyprint-override"><code>class fbuilder extends StatelessWidget {
  const fbauth({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    FirebaseAuth auth = FirebaseAuth.instance;

// --------------->
    return Container(child: FutureBuilder(
      builder: (BuildContext ctx, AsyncSnapshot<User> snapshot) {
        if (ConnectionState.done == snapshot.connectionState) {
          return Text(snapshot.data.userId.toString());
        } else {
          return CircularProgressIndicator();
        }
      },
      future: auth.currentUser(),
    ));
  }
}
</code>```

in stateless or stateful widget

String currentuseid="";
        class fbauth extends StatelessWidget {
          const fbauth({Key? key}) : super(key: key);

          @override
          Widget build(BuildContext context) {

       FirebaseAuth auth = FirebaseAuth.instance;
 //   ------------------------>
            auth.currentUser().then((user) {
              if (user == null) {
                currentuseid = user!.uid;
              } else {
                print('User is signed in!');
              }
              // other logic after the user retrieval
            });

            return Container();
          }
}

Nb: Instead of instantiating firebase auth in every widget .you must instantiate in `void main` method
```

Title: "await" in Widget build FLUTTER

Body:
If your are using stateful widget you can instantiate firebase auth in initstate() method.

class testFirless extends StatefulWidget {
  var currentuseid = "";

  testFirless({Key? key}) : super(key: key);

  @override
  _testFirlessState createState() => _testFirlessState();
}
class _testFirlessState extends State<testFirless> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  // ------------------------------------>heree
  @override
  Future<void> initState() async {
    FirebaseAuth auth = FirebaseAuth.instance;

    var user = await auth.currentUser;
    if (user == null) {
      widget.currentuseid = user!.uid;
    } else {
      print('User is signed in!');
    }
  }
}

FutureBuilder

class fbuilder extends StatelessWidget {
  const fbauth({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    FirebaseAuth auth = FirebaseAuth.instance;

// --------------->
    return Container(child: FutureBuilder(
      builder: (BuildContext ctx, AsyncSnapshot<User> snapshot) {
        if (ConnectionState.done == snapshot.connectionState) {
          return Text(snapshot.data.userId.toString());
        } else {
          return CircularProgressIndicator();
        }
      },
      future: auth.currentUser(),
    ));
  }
}

in stateless or stateful widget

String currentuseid="";
        class fbauth extends StatelessWidget {
          const fbauth({Key? key}) : super(key: key);

          @override
          Widget build(BuildContext context) {

       FirebaseAuth auth = FirebaseAuth.instance;
 //   ------------------------>
            auth.currentUser().then((user) {
              if (user == null) {
                currentuseid = user!.uid;
              } else {
                print('User is signed in!');
              }
              // other logic after the user retrieval
            });

            return Container();
          }
}

Nb: Instead of instantiating firebase auth in every widget .you must instantiate in `void main` method


问:
Using C# SharpADBClient to output device info to textbox duplicates text on device connection
So I'm using SharpADBClient library to communicate to an android device via C# application. I'm able to query the data from the device and the first time the device is connected it displays the correct data.
I'm also open to any refactoring tips as I'm a novice. Thank You.

Outputted Data to textbox(statusHome) 1st Connection

```<code>Device Name: Fire TV Stick 2
Fire Stick TV 2 is connected to this PC
ADB Version: 32
ADB Running Version: Version 1.0.32 of the adb daemon is running.
ADB Server Status: The adb daemon is not running.
ADB Default Server Port: 5037
ADB Default Port: 5555
ADB Default Encoding: ISO-8859-1
Device Serial: G070L81782241RAK
Device State: Online
Device Model: AFTT
Product Name: full_tank
Product Features:
Device USB Port:
Transport ID:
Device Message:
Connection Endpoint: 127.0.0.1:5555
Connection Serialization: InterNetwork:16:{21,179,127,0,0,1,0,0,0,0,0,0,0,0}
Connection Type: System.Net.IPEndPoint
Connection Serialization: 4
</code>```

If I disconnect the device and reconnect it, it displays duplicated textbox(statusHome):

```<code>Device Name: Fire TV Stick 2
Device Name: Fire TV Stick 2
Fire Stick TV 2 is connected to this PC
Fire Stick TV 2 is connected to this PC
ADB Version: 32
ADB Version: 32
ADB Running Version: Version 1.0.32 of the adb daemon is running.
ADB Running Version: Version 1.0.32 of the adb daemon is running.
ADB Server Status: The adb daemon is not running.
ADB Server Status: The adb daemon is not running.
ADB Default Server Port: 5037
ADB Default Server Port: 5037
ADB Default Port: 5555
ADB Default Port: 5555
ADB Default Encoding: ISO-8859-1
ADB Default Encoding: ISO-8859-1
Device Serial: G070L81782241RAK
Device Serial: G070L81782241RAK
Device State: Online
Device State: Online
Device Model: AFTT
Device Model: AFTT
Product Name: full_tank
Product Name: full_tank
Product Features:
Product Features:
Device USB Port:
Device USB Port:
Transport ID:
Transport ID:
Device Message:
Device Message:
Connection Endpoint: 127.0.0.1:5555
Connection Endpoint: 127.0.0.1:5555
Connection Serialization: InterNetwork:16:{21,179,127,0,0,1,0,0,0,0,0,0,0,0}
Connection Serialization: InterNetwork:16:{21,179,127,0,0,1,0,0,0,0,0,0,0,0}
Connection Type: System.Net.IPEndPoint
Connection Type: System.Net.IPEndPoint
Connection Serialization: 4
Connection Serialization: 4
</code>```

If I disconnect it a 3rd or 4th time it will just duplicate the text that many times.

Here is my code:

```<code>using System;
using System.Windows.Forms;
using SharpAdbClient;
using System.Net;
using System.Linq;

namespace Firemax
{
    public partial class indexControl : UserControl
    {
        readonly string newLine = Environment.NewLine;
        private string deviceData1;
        private string deviceData2;
        private string deviceData3;
        private string deviceData4;
        private string deviceData5;
        private string deviceData6;
        private string deviceData7;
        private string deviceData8;
        private string deviceData9;
        private string deviceData10;
        private string deviceData11;
        private string deviceData12;
        private string deviceData13;
        private string deviceData14;
        private string deviceData15;
        private string deviceData16;
        private string deviceData17;
        private string deviceData18;
        private string deviceData19;
        private string deviceData20;
        private string deviceData21;
        private string deviceData22;
        private string deviceData23;
        private string deviceData24;
        private string deviceData25;

        AdbServer adbServer = new AdbServer();
        AdbServerStatus adbStatus = new AdbServerStatus();

        public indexControl()
        {
            InitializeComponent();
            var monitor = new DeviceMonitor(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
            monitor.DeviceConnected += this.OnDeviceConnected;
            monitor.DeviceDisconnected += this.OnDeviceDisConnected;
            monitor.Start();

        }
        public delegate void SetTextCallback(string text);
        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.statusHome.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                statusHome.Text += text;
            }
        }

        void OnDeviceConnected(object sender, DeviceDataEventArgs e)
        {
            var result = adbServer.StartServer(@"C:\adb\adb.exe", restartServerIfNewer: true);
            var devices = AdbClient.Instance.GetDevices();
            int adbVersion = AdbClient.Instance.GetAdbVersion();

            foreach (var device in devices)
            {
                var displayFS2 = "Fire Stick TV 2";
                if (device.Model == "AFTT")
                {

                    deviceData1 += displayFS2 + " is connected to this PC" + newLine;
                    deviceData2 += "ADB Version: " + adbVersion + newLine;
                    deviceData4 += "ADB Running Version: " + adbServer.GetStatus() + newLine;
                    deviceData5 += "ADB Server Status: " + adbStatus.ToString() + newLine;
                    deviceData6 += "ADB Default Server Port: " + AdbClient.AdbServerPort + newLine;
                    deviceData7 += "ADB Default Port: " + AdbClient.DefaultPort + newLine;
                    deviceData8 += "ADB Default Encoding: " + AdbClient.DefaultEncoding + newLine;
                    deviceData9 += "Device Serial: " + device.Serial + newLine;
                    deviceData10 += "Device State: " + device.State + newLine;
                    deviceData11 += "Device Model: " + device.Model + newLine;
                    deviceData12 += "Product Name: " + device.Product + newLine;

                    if (device.Model == "AFTT")
                    {
                        deviceData13 += "Device Name: " + "Fire TV Stick 2" + newLine;
                        SetText(deviceData13.ToString());
                    }
                    else
                    {
                        deviceData14 += "Device Name: " + "Unknown Model" + newLine;
                        SetText(deviceData14.ToString());
                    }

                    deviceData15 += "Product Features: " + device.Features + newLine;
                    deviceData16 += "Device USB Port: " + device.Usb + newLine;
                    deviceData17 += "Transport ID: " + device.TransportId + newLine;
                    deviceData18 += "Device Message: " + device.Message + newLine;
                    deviceData19 += "Connection Endpoint: " + AdbClient.DefaultEndPoint.ToString() + newLine;
                    deviceData20 += "Connection Serialization: " + AdbClient.DefaultEndPoint.Serialize() + newLine;
                    deviceData21 += "Connection Type: " + AdbClient.DefaultEndPoint.GetType() + newLine;
                    deviceData22 += "Connection Serialization: " + 4 + newLine;

                    SetText(deviceData1.ToString());
                    SetText(deviceData2.ToString());
                    SetText(deviceData4.ToString());
                    SetText(deviceData5.ToString());
                    SetText(deviceData6.ToString());
                    SetText(deviceData7.ToString());
                    SetText(deviceData8.ToString());
                    SetText(deviceData9.ToString());
                    SetText(deviceData10.ToString());
                    SetText(deviceData11.ToString());
                    SetText(deviceData12.ToString());
                    SetText(deviceData15.ToString());
                    SetText(deviceData16.ToString());
                    SetText(deviceData17.ToString());
                    SetText(deviceData18.ToString());
                    SetText(deviceData19.ToString());
                    SetText(deviceData20.ToString());
                    SetText(deviceData21.ToString());
                    SetText(deviceData22.ToString());
                }
                else
                {
                    deviceData23 = "An unknown Android device is connected to this PC" + newLine;
                    SetText(deviceData23.ToString());
                }
            }
            Console.WriteLine($"The device {e.Device.Name} has connected to this PC");
        }
        void OnDeviceDisConnected(object sender, DeviceDataEventArgs e)
        {
            deviceData25 = "There is no device connected to this PC" + newLine;
            SetText(deviceData25.ToString());
        }
        private void bunifuMetroTextbox1_OnValueChanged(object sender, EventArgs e)
        {

        }
        private void statusHome_TextChanged(object sender, EventArgs e)
        {

        }
    }
}
</code>```

答:
Cause of the problem

When assigning the deviceData variables, you used += which adds what you're assigning to what is already stored in the variable.

So when you connect the device to the computer, it triggers the OnDeviceConnected function, which adds "Fire Stick TV 2 is connected to this PC" to the deviceData1 variable. Then when you connect the device again, it triggers the OnDeviceConnected function again, and adds "Fire Stick TV 2 is connected to this PC" to the variable that already contains "Fire Stick TV 2 is connected to this PC".

Simple solution

You could simply assign each deviceData variable using just = so that it overrides whatever text was previously stored in that variable. The problem with that is that your program will no longer support connecting more than one device, because it'll keep on overriding what was stored in the variable.

Better solution

The solution to that would be to have a Device class with all the various properties that you'd like to track, and then instantiate a new Device object each time a new device is plugged in to the computer.

To make sure that you're not duplicating devices if you remove a device and plug it in again, you could have a list of your Device objects, then when detecting a new device connected, only instantiate it if the serial number is not in the list of other devices.

```<code>    List<Device> MyDeviceList = new List<Device>();

    void OnDeviceConnected(object sender, DeviceDataEventArgs e)
    {
        string newDeviceSerial = e.Device.Serial;
        bool wasAlreadyConnected = false;
        foreach(var device in MyDeviceList)
        {
            if(device.Serial == newDeviceSerial)
            {
                wasAlreadyConnected = true;
            }
        }
        if(!wasAlreadyConnected)
        {
             // Instantiate a new Device object, with all the details from the newly connected device
             // Add the new Device object to MyDeviceList
        }
    }
</code>```

Hope that helps ;)

Body:
So I'm using SharpADBClient library to communicate to an android device via C# application. I'm able to query the data from the device and the first time the device is connected it displays the correct data.
I'm also open to any refactoring tips as I'm a novice. Thank You.

Outputted Data to textbox(statusHome) 1st Connection

Device Name: Fire TV Stick 2
Fire Stick TV 2 is connected to this PC
ADB Version: 32
ADB Running Version: Version 1.0.32 of the adb daemon is running.
ADB Server Status: The adb daemon is not running.
ADB Default Server Port: 5037
ADB Default Port: 5555
ADB Default Encoding: ISO-8859-1
Device Serial: G070L81782241RAK
Device State: Online
Device Model: AFTT
Product Name: full_tank
Product Features:
Device USB Port:
Transport ID:
Device Message:
Connection Endpoint: 127.0.0.1:5555
Connection Serialization: InterNetwork:16:{21,179,127,0,0,1,0,0,0,0,0,0,0,0}
Connection Type: System.Net.IPEndPoint
Connection Serialization: 4

If I disconnect the device and reconnect it, it displays duplicated textbox(statusHome):

Device Name: Fire TV Stick 2
Device Name: Fire TV Stick 2
Fire Stick TV 2 is connected to this PC
Fire Stick TV 2 is connected to this PC
ADB Version: 32
ADB Version: 32
ADB Running Version: Version 1.0.32 of the adb daemon is running.
ADB Running Version: Version 1.0.32 of the adb daemon is running.
ADB Server Status: The adb daemon is not running.
ADB Server Status: The adb daemon is not running.
ADB Default Server Port: 5037
ADB Default Server Port: 5037
ADB Default Port: 5555
ADB Default Port: 5555
ADB Default Encoding: ISO-8859-1
ADB Default Encoding: ISO-8859-1
Device Serial: G070L81782241RAK
Device Serial: G070L81782241RAK
Device State: Online
Device State: Online
Device Model: AFTT
Device Model: AFTT
Product Name: full_tank
Product Name: full_tank
Product Features:
Product Features:
Device USB Port:
Device USB Port:
Transport ID:
Transport ID:
Device Message:
Device Message:
Connection Endpoint: 127.0.0.1:5555
Connection Endpoint: 127.0.0.1:5555
Connection Serialization: InterNetwork:16:{21,179,127,0,0,1,0,0,0,0,0,0,0,0}
Connection Serialization: InterNetwork:16:{21,179,127,0,0,1,0,0,0,0,0,0,0,0}
Connection Type: System.Net.IPEndPoint
Connection Type: System.Net.IPEndPoint
Connection Serialization: 4
Connection Serialization: 4

If I disconnect it a 3rd or 4th time it will just duplicate the text that many times.

Here is my code:

using System;
using System.Windows.Forms;
using SharpAdbClient;
using System.Net;
using System.Linq;

namespace Firemax
{
    public partial class indexControl : UserControl
    {
        readonly string newLine = Environment.NewLine;
        private string deviceData1;
        private string deviceData2;
        private string deviceData3;
        private string deviceData4;
        private string deviceData5;
        private string deviceData6;
        private string deviceData7;
        private string deviceData8;
        private string deviceData9;
        private string deviceData10;
        private string deviceData11;
        private string deviceData12;
        private string deviceData13;
        private string deviceData14;
        private string deviceData15;
        private string deviceData16;
        private string deviceData17;
        private string deviceData18;
        private string deviceData19;
        private string deviceData20;
        private string deviceData21;
        private string deviceData22;
        private string deviceData23;
        private string deviceData24;
        private string deviceData25;

        AdbServer adbServer = new AdbServer();
        AdbServerStatus adbStatus = new AdbServerStatus();

        public indexControl()
        {
            InitializeComponent();
            var monitor = new DeviceMonitor(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)));
            monitor.DeviceConnected += this.OnDeviceConnected;
            monitor.DeviceDisconnected += this.OnDeviceDisConnected;
            monitor.Start();

        }
        public delegate void SetTextCallback(string text);
        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.statusHome.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                statusHome.Text += text;
            }
        }

        void OnDeviceConnected(object sender, DeviceDataEventArgs e)
        {
            var result = adbServer.StartServer(@"C:\adb\adb.exe", restartServerIfNewer: true);
            var devices = AdbClient.Instance.GetDevices();
            int adbVersion = AdbClient.Instance.GetAdbVersion();

            foreach (var device in devices)
            {
                var displayFS2 = "Fire Stick TV 2";
                if (device.Model == "AFTT")
                {

                    deviceData1 += displayFS2 + " is connected to this PC" + newLine;
                    deviceData2 += "ADB Version: " + adbVersion + newLine;
                    deviceData4 += "ADB Running Version: " + adbServer.GetStatus() + newLine;
                    deviceData5 += "ADB Server Status: " + adbStatus.ToString() + newLine;
                    deviceData6 += "ADB Default Server Port: " + AdbClient.AdbServerPort + newLine;
                    deviceData7 += "ADB Default Port: " + AdbClient.DefaultPort + newLine;
                    deviceData8 += "ADB Default Encoding: " + AdbClient.DefaultEncoding + newLine;
                    deviceData9 += "Device Serial: " + device.Serial + newLine;
                    deviceData10 += "Device State: " + device.State + newLine;
                    deviceData11 += "Device Model: " + device.Model + newLine;
                    deviceData12 += "Product Name: " + device.Product + newLine;

                    if (device.Model == "AFTT")
                    {
                        deviceData13 += "Device Name: " + "Fire TV Stick 2" + newLine;
                        SetText(deviceData13.ToString());
                    }
                    else
                    {
                        deviceData14 += "Device Name: " + "Unknown Model" + newLine;
                        SetText(deviceData14.ToString());
                    }

                    deviceData15 += "Product Features: " + device.Features + newLine;
                    deviceData16 += "Device USB Port: " + device.Usb + newLine;
                    deviceData17 += "Transport ID: " + device.TransportId + newLine;
                    deviceData18 += "Device Message: " + device.Message + newLine;
                    deviceData19 += "Connection Endpoint: " + AdbClient.DefaultEndPoint.ToString() + newLine;
                    deviceData20 += "Connection Serialization: " + AdbClient.DefaultEndPoint.Serialize() + newLine;
                    deviceData21 += "Connection Type: " + AdbClient.DefaultEndPoint.GetType() + newLine;
                    deviceData22 += "Connection Serialization: " + 4 + newLine;

                    SetText(deviceData1.ToString());
                    SetText(deviceData2.ToString());
                    SetText(deviceData4.ToString());
                    SetText(deviceData5.ToString());
                    SetText(deviceData6.ToString());
                    SetText(deviceData7.ToString());
                    SetText(deviceData8.ToString());
                    SetText(deviceData9.ToString());
                    SetText(deviceData10.ToString());
                    SetText(deviceData11.ToString());
                    SetText(deviceData12.ToString());
                    SetText(deviceData15.ToString());
                    SetText(deviceData16.ToString());
                    SetText(deviceData17.ToString());
                    SetText(deviceData18.ToString());
                    SetText(deviceData19.ToString());
                    SetText(deviceData20.ToString());
                    SetText(deviceData21.ToString());
                    SetText(deviceData22.ToString());
                }
                else
                {
                    deviceData23 = "An unknown Android device is connected to this PC" + newLine;
                    SetText(deviceData23.ToString());
                }
            }
            Console.WriteLine($"The device {e.Device.Name} has connected to this PC");
        }
        void OnDeviceDisConnected(object sender, DeviceDataEventArgs e)
        {
            deviceData25 = "There is no device connected to this PC" + newLine;
            SetText(deviceData25.ToString());
        }
        private void bunifuMetroTextbox1_OnValueChanged(object sender, EventArgs e)
        {

        }
        private void statusHome_TextChanged(object sender, EventArgs e)
        {

        }
    }
}

Body:
Cause of the problem

When assigning the deviceData variables, you used += which adds what you're assigning to what is already stored in the variable.

So when you connect the device to the computer, it triggers the OnDeviceConnected function, which adds "Fire Stick TV 2 is connected to this PC" to the deviceData1 variable. Then when you connect the device again, it triggers the OnDeviceConnected function again, and adds "Fire Stick TV 2 is connected to this PC" to the variable that already contains "Fire Stick TV 2 is connected to this PC".

Simple solution

You could simply assign each deviceData variable using just = so that it overrides whatever text was previously stored in that variable. The problem with that is that your program will no longer support connecting more than one device, because it'll keep on overriding what was stored in the variable.

Better solution

The solution to that would be to have a Device class with all the various properties that you'd like to track, and then instantiate a new Device object each time a new device is plugged in to the computer.

To make sure that you're not duplicating devices if you remove a device and plug it in again, you could have a list of your Device objects, then when detecting a new device connected, only instantiate it if the serial number is not in the list of other devices.

    List<Device> MyDeviceList = new List<Device>();

    void OnDeviceConnected(object sender, DeviceDataEventArgs e)
    {
        string newDeviceSerial = e.Device.Serial;
        bool wasAlreadyConnected = false;
        foreach(var device in MyDeviceList)
        {
            if(device.Serial == newDeviceSerial)
            {
                wasAlreadyConnected = true;
            }
        }
        if(!wasAlreadyConnected)
        {
             // Instantiate a new Device object, with all the details from the newly connected device
             // Add the new Device object to MyDeviceList
        }
    }

Hope that helps ;)


问:
Database development mistakes made by application developers
What are common database development mistakes made by application developers?</p>

答:
Dismissing an ORM like Hibernate out of hand, for reasons like "it's too magical" or "not on my database".

Relying too heavily on an ORM like Hibernate and trying to shoehorn it in where it isn't appropriate.

OwnerDisplayName: Charles Faiga

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: cletus

OwnerDisplayName: Adam Jaskiewicz


问:
VS Find in Files: No .svn contents pleeeeeease?
Is there any way to prevent the contents of .svn subdirectories to show up in Visual Studio Find in Files results?

An alternative would be to make it ignore hidden subdirectories.

答:
According to the documentation for "Find in Files":

The Find and Replace tool does not search directories with the Hidden or System attribute set.

However, this seems to be only partially true.  For VS to ignore hidden/system directories, the "Don't show hidden files, folders, and drives" option in Explorer must be set.

If you're like me, that's one of the first things you do on a Windows computer - change that setting to "Show hidden files, etc..." (along with showing extensions - it baffles me that anyone thinks that not showing extensions is a good idea or is less confusing than showing them).

Having files in the .svn metadata show up in search results is one of the very irritating things about using SVN and/or search tools that don't let you easily exclude the directories.  Unfortunately, VS's "Find in Files" seems to be one of those irritants unless you're OK with to hiding the directories system-wide along with all other hidden files and directories.

Personally, I can usually get by with 'mentally' filtering those directories from the search results.  If it's a particularly bad set of results, and you really, really need the filter, you can flip the setting in Explorer, perform the search , and change the setting back without having to reboot or restart VS or anything. That's a small consolation, but I was half expecting to have to restart VS for the setting change to take effect.

Also, if what you're really searching is the Project or Solution rather than an arbitrary location on the file system, you can tell "Find in Files" to search files in the Project/Solution as hunter suggested. But I assume that's not what you're searching, or you probably wouldn't be having this problem.


问:
Puppeteer to save image open in the browser
I have a link for a (gif) image, obtained manually via 'open in new tab'. I want Puppeteer to open the image and then save it to a file. If doing it in a normal browser I would click right button and choose 'save' from the context menu. Is there a simple way to perform this action in Puppeteer?</p>

答:
In Puppeteer it's possible to right click, but it's not possible to automate the navigation through the "save as" menu. However, there is a solution outlined in the top answer here:

How can I download images on a page using puppeteer?

You can write the images to disk directly from the page response.


问:
Typing unused arguments
I have a function that has to take two arguments, like:

```<code>def f(first_arg: int, unused_arg) -> int:
    first_arg += 1
    return first_arg
</code>```

I want to type my function, what should be the type of unused_arg ? From this question I guess None could be used.

For context, I'm using lax.scan from jax which needs a function with two arguments even when the second one is unused.

答:
You can use Any?

```<code>from typing import Any

def f(first_arg: int, unused_arg: Any) -> int:
    ...
</code>```

Title: Typing unused arguments

Body:
I have a function that has to take two arguments, like:

def f(first_arg: int, unused_arg) -> int:
    first_arg += 1
    return first_arg

I want to type my function, what should be the type of unused_arg ? From this question I guess None could be used.

For context, I'm using lax.scan from jax which needs a function with two arguments even when the second one is unused.

Body:
You can use Any?

from typing import Any

def f(first_arg: int, unused_arg: Any) -> int:
    ...


问:
I keep getting a blank screen in React.JS
I was following a tutorial and my localhost is completely blank after importing {Link} from react-router-dom. Followed word for word but my local host is blank as soon as I added link in navbar.js.

```<code>import React from 'react';
import {Link} from 'react-router-dom';

function Navbar() {
    return(
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
                <div class="container-fluid">

                <Link to="/" class="navbar-brand">SkyCloud</Link>

                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-togglser-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                    <li class="nav-item">
                        <Link to="/" class="nav-link active">Home</Link>
                    </li>

                    <li class="nav-item">
                    <Link to="/about" class="nav-link active">About</Link>
                    </li>

                    <li class="nav-item">
                    <Link to="/contact" class="nav-link active">Contact</Link>
                    </li>

                    </ul>

                </div>
                </div>
      </nav>

    );

}

export default Navbar;
</code>```

And this is my App.js file...

```<code>import React from 'react';
import Navbar from './components/inc/Navbar';
import Home from './components/pages/Home';
import About from './components/pages/About';
import Contact from './components/pages/Contact';
import {BrowserRouter as Router} from 'react-router-dom';

function App() {
  return (

    <Router>
    <div>
     <Navbar/>
    <Home/>
   <About/>
   <Contact/>

    </div>
    </Router>

  );
}

export default App;
</code>```

答:
You need to wrap your components inside Route HOC, if you are using react router v5

```<code> <Route path="/">
    <Home/>
 </Route>
 <Route path="/about">
   <About/>
 </Route>
 <Route path="/Contact">
   <Contact/>
 </Route>
</code>```

if its react router v6, answer is

```<code>  <Route index path="/" element={<Home />} />
  <Route path="/contacts" element={<Contact/>} />
  <Route path=/about" element={<About/>} />
</code>```

Body:
I was following a tutorial and my localhost is completely blank after importing {Link} from react-router-dom. Followed word for word but my local host is blank as soon as I added link in navbar.js.

import React from 'react';
import {Link} from 'react-router-dom';

function Navbar() {
    return(

                <Link to="/" class="navbar-brand">SkyCloud</Link>

                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">

                </button>

                        <Link to="/" class="nav-link active">Home</Link>

                    <Link to="/about" class="nav-link active">About</Link>

                    <Link to="/contact" class="nav-link active">Contact</Link>

    );

}

export default Navbar;

And this is my App.js file...

import React from 'react';
import Navbar from './components/inc/Navbar';
import Home from './components/pages/Home';
import About from './components/pages/About';
import Contact from './components/pages/Contact';
import {BrowserRouter as Router} from 'react-router-dom';

function App() {
  return (

    <Router>

     <Navbar/>
    <Home/>
   <About/>
   <Contact/>

    </Router>

  );
}

export default App;

Body:
You need to wrap your components inside Route HOC, if you are using react router v5

 <Route path="/">
    <Home/>
 </Route>
 <Route path="/about">
   <About/>
 </Route>
 <Route path="/Contact">
   <Contact/>
 </Route>

if its react router v6, answer is

  <Route index path="/" element={<Home />} />
  <Route path="/contacts" element={<Contact/>} />
  <Route path=/about" element={<About/>} />