问:
Haskell binary search tree with custom data
I want to create a binary search tree of custom data type Book. Book has two attributes, name and page. I want to use attribute page as the node of the tree. I've stuck at defining the tree. Can anyone help me with any resource? Here is the code I've tried (it's not working)</p>

```<code>import System.IO
import Data.List

data Book = Book{
    name:: String,
    page::Int
}deriving (Show)

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)

singleton :: (Book _ x) -> Tree x
singleton (Book _ x) = Node x EmptyTree EmptyTree

treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert (Book _ x) EmptyTree = singleton (Book _ x)
treeInsert (Book _ x) (Node a left right)
    | x == a = Node x left right
    | x < a  = Node a (treeInsert (Book _ x) left) right
    | x > a  = Node a left (treeInsert (Book _ x) right)
</code>```

答:
Maybe if we figure out the correct type signatures.

I presume you want the Tree to hold Books, ordered by page.

If we want Tree to hold only Book, we don't need to parameterize it.  However, since you did parameterize Tree, let's assume that it can hold more than just Books.

In this case, we would expect:

```<code>singleton :: a -> Tree a
treeInsert :: Ord a => a -> Tree a -> Tree a
</code>```

Where a could be Book, or any other appropriate type.  However, in order for treeInsert  to work with Book, we require Book to have an Ord instance.

The singleton function just puts the whole a into a Node:

```<code>singleton a = Node a EmptyTree EmptyTree
</code>```

Note that Book does not appear in this definition since it is intended to work with all types.

The insertTree function will also not mention Book, but it will take advantage of the Ord instance it requires of its argument.

Edit

If you want Tree to work only with Book, then you should define it as:

```<code>data Tree = EmptyTree | Node Book Tree Tree
</code>```

The type signatures for the functions then become:

```<code>singleton :: Book -> Tree
insertTree :: Book -> Tree -> Tree
</code>```

The implementation of singleton will be the same as above (just put the whole Book into a Node).

Since insertTree now knows it is dealing with Book, it no longer requires the Ord instance, since it can just get the page.

It will start:

```<code>treeInsert b EmptyTree = singleton b
treeInsert b (Node a l r)
    | page b == page a = ...
</code>```

Body:
I want to create a binary search tree of custom data type Book. Book has two attributes, name and page. I want to use attribute page as the node of the tree. I've stuck at defining the tree. Can anyone help me with any resource? Here is the code I've tried (it's not working)

import System.IO
import Data.List

data Book = Book{
    name:: String,
    page::Int
}deriving (Show)

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)

singleton :: (Book _ x) -> Tree x
singleton (Book _ x) = Node x EmptyTree EmptyTree

treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert (Book _ x) EmptyTree = singleton (Book _ x)
treeInsert (Book _ x) (Node a left right)
    | x == a = Node x left right
    | x  a  = Node a left (treeInsert (Book _ x) right)

Body:
Maybe if we figure out the correct type signatures.

I presume you want the Tree to hold Books, ordered by page.

If we want Tree to hold only Book, we don't need to parameterize it.  However, since you did parameterize Tree, let's assume that it can hold more than just Books.

In this case, we would expect:

singleton :: a -> Tree a
treeInsert :: Ord a => a -> Tree a -> Tree a

Where a could be Book, or any other appropriate type.  However, in order for treeInsert  to work with Book, we require Book to have an Ord instance.

The singleton function just puts the whole a into a Node:

singleton a = Node a EmptyTree EmptyTree

Note that Book does not appear in this definition since it is intended to work with all types.

The insertTree function will also not mention Book, but it will take advantage of the Ord instance it requires of its argument.

Edit

If you want Tree to work only with Book, then you should define it as:

data Tree = EmptyTree | Node Book Tree Tree

The type signatures for the functions then become:

singleton :: Book -> Tree
insertTree :: Book -> Tree -> Tree

The implementation of singleton will be the same as above (just put the whole Book into a Node).

Since insertTree now knows it is dealing with Book, it no longer requires the Ord instance, since it can just get the page.

It will start:

treeInsert b EmptyTree = singleton b
treeInsert b (Node a l r)
    | page b == page a = ...


来源: stackexchange

问:
How can I return rows for IDs that meet criteria for EXACTLY 3 occurrences in a row?
I have a requirement that is throwing me for a loop.I have to return location IDs that have exactly 3 consecutive rows of monthly invoice amounts >$2,000. In other words, I do not want to return IDs for mature locations (that might have hundreds of monthly invoices rows).

Rextester example data: http://rextester.com/CNJC15871

Info:

The report will be run on the first of each month

Monthly invoice dates are the 15th of the month

Desired Output: In the invoice table below,

For a report run date of 10/1, loc_ids 2223 and 3344 would be returned, because 9/15 was the third ever consecutive month of invoice amount >$2,000

For a report run date of 11/1, loc_id 6678 would be returned, by the same logic.

For subsequent report months, 2223, 3344, and 6678 should NOT be returned because they have >3 consecutive months >$2,000.

```<code>| loc_id | invoice_date | invoice_amt | Notes                     |
|--------|--------------|-------------|---------------------------|
| 1234   | 5/15/2002    | 7000        |                           |
| 1234   | 6/15/2002    | 8000        |                           |
| ..     | …            | …           |                           |
| 1234   | 11/15/2017   | 58000       |                           |
|        |              |             |                           |
| 9987   | 11/15/2006   | 7500        |                           |
| 9987   | 12/15/2006   | 8500        |                           |
| …      | …            |             |                           |
| 9987   | 11/15/2017   | 63000       |                           |
|        |              |             |                           |
| 5544   | 3/15/2015    | 9200        |                           |
| 5544   | 4/15/2015    | 10000       |                           |
| …      | …            |             |                           |
| 5544   | 11/15/2017   | 70000       |                           |
|        |              |             |                           |
| 2223   | 5/15/2017    | 2500        | Count| >2000              |
| 2223   | 6/15/2017    | 1375        | Do not count| <2000       |
| 2223   | 7/15/2017    | 8000        | Restart count| >2000 (1)  |
| 2223   | 8/15/2017    | 9000        | Continue count| >2000 (2) |
| 2223   | 9/15/2017    | 9800        | Continue count| >2000 (3) |
| 2223   | 10/15/2017   | 10500       | Stop count| >3 in a row   |
| 2223   | 11/15/2017   | 11200       | Stop count| >3 in a row   |
|        |              |             |                           |
| 3344   | 7/15/2017    | 3500        | Count| >2000 (1)          |
| 3344   | 8/15/2017    | 4500        | Continue count| >2000 (2) |
| 3344   | 9/15/2017    | 6000        | Continue count| >2000 (3) |
| 3344   | 10/15/2017   | 7000        | Stop count| >3 in a row   |
| 3344   | 11/15/2017   | 8000        | Stop count| >3 in a row   |
|        |              |             |                           |
| 6678   | 8/15/2017    | 3000        | Count| >2000 (1)          |
| 6678   | 9/15/2017    | 4000        | Continue count| >2000 (2) |
| 6678   | 10/15/2017   | 5000        | Continue count| >2000 (3) |
</code>```

I also have a loc_id dimension that includes the location open date.

```<code>| loc_id | loc_open_dt |
|--------|-------------|
| 1234   | 2002-05-01  |
| 9987   | 2006-10-22  |
| 5544   | 2015-03-04  |
| 2223   | 2017-05-05  |
| 3344   | 2017-07-05  |
| 6678   | 2017-08-01  |
</code>```

答:
In PostgreSQL you can use a window function. You need to build the windows by aggregating your data by loc_id and then check that 3 conscutive rows have an invoice_amt greater than the target value. The trick is done by using the lag() function that, applied over a window, let you grab data from the previous rows. The code is much simpler than the explanation:

```<code>SELECT DISTINCT loc_id FROM (
  SELECT *,
         invoice_amt > 10000 AS a,
         lag(invoice_amt, 1) OVER w > 10000 AS b,
         lag(invoice_amt, 2) OVER w > 10000 AS c,
         extract('month' from invoice_date::date) AS m1,
         extract('month' from (lag(invoice_date, 1) OVER w)::date + '1 month'::interval) AS m2,
         extract('month' from (lag(invoice_date, 2) OVER w)::date + '2 month'::interval) AS m3
    FROM invoices
  WINDOW w AS (PARTITION BY loc_id ORDER BY invoice_date)
) X
 WHERE a AND b AND c AND m2 = m1 AND m3 = m1
</code>```

Note also the check on consecutive months. We just add 1 or 2 months to the lag()ged date and then check that the month is same for the three consecutive rows (as asked in the comments).

If you want to better understand how that works just run only the inner SELECT and look at the results.

ContentLicense: CC BY-SA 3.0

Body:
I have a requirement that is throwing me for a loop.I have to return location IDs that have exactly 3 consecutive rows of monthly invoice amounts >$2,000. In other words, I do not want to return IDs for mature locations (that might have hundreds of monthly invoices rows).

Rextester example data: http://rextester.com/CNJC15871

Info:

The report will be run on the first of each month

Monthly invoice dates are the 15th of the month

Desired Output: In the invoice table below,

For a report run date of 10/1, loc_ids 2223 and 3344 would be returned, because 9/15 was the third ever consecutive month of invoice amount >$2,000

For a report run date of 11/1, loc_id 6678 would be returned, by the same logic.

For subsequent report months, 2223, 3344, and 6678 should NOT be returned because they have >3 consecutive months >$2,000.

| loc_id | invoice_date | invoice_amt | Notes                     |
|--------|--------------|-------------|---------------------------|
| 1234   | 5/15/2002    | 7000        |                           |
| 1234   | 6/15/2002    | 8000        |                           |
| ..     | …            | …           |                           |
| 1234   | 11/15/2017   | 58000       |                           |
|        |              |             |                           |
| 9987   | 11/15/2006   | 7500        |                           |
| 9987   | 12/15/2006   | 8500        |                           |
| …      | …            |             |                           |
| 9987   | 11/15/2017   | 63000       |                           |
|        |              |             |                           |
| 5544   | 3/15/2015    | 9200        |                           |
| 5544   | 4/15/2015    | 10000       |                           |
| …      | …            |             |                           |
| 5544   | 11/15/2017   | 70000       |                           |
|        |              |             |                           |
| 2223   | 5/15/2017    | 2500        | Count| >2000              |
| 2223   | 6/15/2017    | 1375        | Do not count| <2000       |
| 2223   | 7/15/2017    | 8000        | Restart count| >2000 (1)  |
| 2223   | 8/15/2017    | 9000        | Continue count| >2000 (2) |
| 2223   | 9/15/2017    | 9800        | Continue count| >2000 (3) |
| 2223   | 10/15/2017   | 10500       | Stop count| >3 in a row   |
| 2223   | 11/15/2017   | 11200       | Stop count| >3 in a row   |
|        |              |             |                           |
| 3344   | 7/15/2017    | 3500        | Count| >2000 (1)          |
| 3344   | 8/15/2017    | 4500        | Continue count| >2000 (2) |
| 3344   | 9/15/2017    | 6000        | Continue count| >2000 (3) |
| 3344   | 10/15/2017   | 7000        | Stop count| >3 in a row   |
| 3344   | 11/15/2017   | 8000        | Stop count| >3 in a row   |
|        |              |             |                           |
| 6678   | 8/15/2017    | 3000        | Count| >2000 (1)          |
| 6678   | 9/15/2017    | 4000        | Continue count| >2000 (2) |
| 6678   | 10/15/2017   | 5000        | Continue count| >2000 (3) |

I also have a loc_id dimension that includes the location open date.

| loc_id | loc_open_dt |
|--------|-------------|
| 1234   | 2002-05-01  |
| 9987   | 2006-10-22  |
| 5544   | 2015-03-04  |
| 2223   | 2017-05-05  |
| 3344   | 2017-07-05  |
| 6678   | 2017-08-01  |

Body:
In PostgreSQL you can use a window function. You need to build the windows by aggregating your data by loc_id and then check that 3 conscutive rows have an invoice_amt greater than the target value. The trick is done by using the lag() function that, applied over a window, let you grab data from the previous rows. The code is much simpler than the explanation:

SELECT DISTINCT loc_id FROM (
  SELECT *,
         invoice_amt > 10000 AS a,
         lag(invoice_amt, 1) OVER w > 10000 AS b,
         lag(invoice_amt, 2) OVER w > 10000 AS c,
         extract('month' from invoice_date::date) AS m1,
         extract('month' from (lag(invoice_date, 1) OVER w)::date + '1 month'::interval) AS m2,
         extract('month' from (lag(invoice_date, 2) OVER w)::date + '2 month'::interval) AS m3
    FROM invoices
  WINDOW w AS (PARTITION BY loc_id ORDER BY invoice_date)
) X
 WHERE a AND b AND c AND m2 = m1 AND m3 = m1

Note also the check on consecutive months. We just add 1 or 2 months to the lag()ged date and then check that the month is same for the three consecutive rows (as asked in the comments).

If you want to better understand how that works just run only the inner SELECT and look at the results.


问:
automatically detect web browser window width change?
i know that you with $(window).width() can get the size of the web browser.

i want to detect when the user change the size of his web browser so i could readjust the columns width. is there a way to automatically detect this or do i have to use setTimeinterval to loop and see if it has changed?

答:
You might want to use debounce :
https://davidwalsh.name/javascript-debounce-function

Otherwise the

```<code>window.addEventListener("resize")
</code>```

Will fire the whole time as the window resize is in progress.
Which will tax your CPU overhead.

ContentLicense: CC BY-SA 2.5

Body:
You might want to use debounce :
https://davidwalsh.name/javascript-debounce-function

Otherwise the

window.addEventListener("resize")

Will fire the whole time as the window resize is in progress.
Which will tax your CPU overhead.


问:
Parsing string in multiline data with positive lookbehind
I am trying to parse data like:

```<code>header1
-------
var1 0
var2 5
var3 9
var6 1

header2
-------
var1 -3
var3 5
var5 0
</code>```

Now I want to get e.g. var3 for header2. Whats the best way to do this?

So far I was parsing my files line-by-line via

```<code>open(FILE,"< $file");
while (my $line = <FILE>){
    # do stuff
}
</code>```

but I guess it's not possible to handle multiline parsing properly.

Now I am thinking to parse the file at once but wasn't successful so far...

```<code>my @Input;
open(FILE,"< $file");
while (<FILE>){ @Input = <FILE>; }
if (@Input =~ /header2/){
    #...
}
</code>```

答:
```<code>while (<FILE>){ @Input = <FILE>; }
</code>```

This doesn't make much sense. "While you can read a record from FILE, read all of the data on FILE into @Input". I think what you actually want is just:

```<code>my @Input = <FILE>;
</code>```

```<code>if (@Input =~ /header2/){
</code>```

This is quite strange too. The binding operator (=~) expects scalar operands, so it evaluates both operands in scalar context. That means @Input will be evaluated as the number of elements in @Input. That's an integer and will never match "header2".

A couple of approaches. Firstly a regex approach.

```<code>#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my $file = 'file';

open my $fh, '<', $file or die $!;

my $data = join '', <$fh>;

if ($data =~ /header2.+var3 (.+?)\n/s) {
  say $1;
} else {
  say 'Not found';
}
</code>```

The key to this is the /s on the m// operator. Without it, the two dots in the regex won't match newlines.

The other approach is more of a line by line parser.

```<code>#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my $file = 'file';

open my $fh, '<', $file or die $!;

my $section = '';

while (<$fh>) {
  chomp;
  # if the line all word characters,
  # then we've got a section header.
  if ($_ !~ /\W/) {
    $section = $_;
    next;
  }

  my ($key, $val) = split;
  if ($section eq 'header2' and $key eq 'var3') {
    say $val;
    last;
  }
}
</code>```

We read the file a line at a time and make a note of the section headers. For data lines, we split on whitespace and check to see if we're in the right section and have the right key.

In both cases, I've switched to using a more standard approach (lexical filehandles, 3-arg open(), or die $!) for opening the file.

Body:
I am trying to parse data like:

header1
-------
var1 0
var2 5
var3 9
var6 1

header2
-------
var1 -3
var3 5
var5 0

Now I want to get e.g. var3 for header2. Whats the best way to do this?

So far I was parsing my files line-by-line via

open(FILE,"< $file");
while (my $line = <FILE>){
    # do stuff
}

but I guess it's not possible to handle multiline parsing properly.

Now I am thinking to parse the file at once but wasn't successful so far...

my @Input;
open(FILE,"< $file");
while (<FILE>){ @Input = <FILE>; }
if (@Input =~ /header2/){
    #...
}

Body:
while (<FILE>){ @Input = <FILE>; }

This doesn't make much sense. "While you can read a record from FILE, read all of the data on FILE into @Input". I think what you actually want is just:

my @Input = <FILE>;

if (@Input =~ /header2/){

This is quite strange too. The binding operator (=~) expects scalar operands, so it evaluates both operands in scalar context. That means @Input will be evaluated as the number of elements in @Input. That's an integer and will never match "header2".

A couple of approaches. Firstly a regex approach.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my $file = 'file';

open my $fh, '<', $file or die $!;

my $data = join '', <$fh>;

if ($data =~ /header2.+var3 (.+?)\n/s) {
  say $1;
} else {
  say 'Not found';
}

The key to this is the /s on the m// operator. Without it, the two dots in the regex won't match newlines.

The other approach is more of a line by line parser.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my $file = 'file';

open my $fh, '<', $file or die $!;

my $section = '';

while (<$fh>) {
  chomp;
  # if the line all word characters,
  # then we've got a section header.
  if ($_ !~ /\W/) {
    $section = $_;
    next;
  }

  my ($key, $val) = split;
  if ($section eq 'header2' and $key eq 'var3') {
    say $val;
    last;
  }
}

We read the file a line at a time and make a note of the section headers. For data lines, we split on whitespace and check to see if we're in the right section and have the right key.

In both cases, I've switched to using a more standard approach (lexical filehandles, 3-arg open(), or die $!) for opening the file.


问:
Filter array of dates
I know that there is .filter () in it that filters an array to return it just the way I want, and using a lot to search, when we pass what we want to search in that array.

However I'm having trouble filtering an array of dates like this:

```<code>["08:00" "09:00" "10:10" "10:30" "10:50" "11:30" "11:50" "12:00"];
</code>```

I need to filter it by past date I have start date and end date, for example step to it " 09:00 " and " 11:30 " it should return to me:

```<code>["10:10" "10:30" "10:50"]
</code>```

Trying to do this I did so in my typescript:

```<code>1. this.schedules = this.navigation.lineSelected.schedules;
2. this.schedules.filter (item => {
3. item> this.hourNow && item <this.hourFinish
4.});
</code>```

On line 1 I get all the times I have, so on line 2.4 I filter this array, but it returns everything to me.

How can I do this?

Translating what I need:

I'm going to have two strings of hours like "12:00" and "15:00" I need to make comparisons in my array, because I need the hours that are between interval as in the above example.

When I say time I'm talking about a string, so I need to compare string if it's bigger or not than the other type string that are below "12:00" will not appear in my final array, and strings larger than "15:00" will also do not.

This is the best way I can explain what I need, I do not see any other option to explain. Simply filter an array

答:
You could use a combination of new Date() and valueOf() to compare the timestamps, it seems to me the actual date is irrelevant :

```<code>function filterTimes(arr, min, max) {
   min = new Date('01-01-2017 '+min).valueOf();
   max = new Date('01-01-2017 '+max).valueOf();
   return arr.filter(function(a) {
      var d = new Date('01-01-2017 '+a).valueOf();
      if (d>min && d<max) return a
   })
}
</code>```

Usage filterTimes(array, '09:00', '11:30')

here is a demo -> http://jsfiddle.net/u3g4u256/

Title: Filter array of dates

Body:
I know that there is .filter () in it that filters an array to return it just the way I want, and using a lot to search, when we pass what we want to search in that array.

However I'm having trouble filtering an array of dates like this:

["08:00" "09:00" "10:10" "10:30" "10:50" "11:30" "11:50" "12:00"];

I need to filter it by past date I have start date and end date, for example step to it " 09:00 " and " 11:30 " it should return to me:

["10:10" "10:30" "10:50"]

Trying to do this I did so in my typescript:

1. this.schedules = this.navigation.lineSelected.schedules;
2. this.schedules.filter (item => {
3. item> this.hourNow && item <this.hourFinish
4.});

On line 1 I get all the times I have, so on line 2.4 I filter this array, but it returns everything to me.

How can I do this?

Translating what I need:

I'm going to have two strings of hours like "12:00" and "15:00" I need to make comparisons in my array, because I need the hours that are between interval as in the above example.

When I say time I'm talking about a string, so I need to compare string if it's bigger or not than the other type string that are below "12:00" will not appear in my final array, and strings larger than "15:00" will also do not.

This is the best way I can explain what I need, I do not see any other option to explain. Simply filter an array

Body:
You could use a combination of new Date() and valueOf() to compare the timestamps, it seems to me the actual date is irrelevant :

function filterTimes(arr, min, max) {
   min = new Date('01-01-2017 '+min).valueOf();
   max = new Date('01-01-2017 '+max).valueOf();
   return arr.filter(function(a) {
      var d = new Date('01-01-2017 '+a).valueOf();
      if (d>min && d<max) return a
   })
}

Usage filterTimes(array, '09:00', '11:30')

here is a demo -> http://jsfiddle.net/u3g4u256/


问:
Failed to start project The directory name is invalid
I'm new and learning SSIS, and just to get started I wanted to test funtionality by writing an excel document out to a .csv file. However, I did everything that I believe needs to be done, but when I try to run it, I get this error:

Failed to start project (Microsoft Visual Studio)
  The directory name is invalid (Microsoft.DataTransformationServices.VsIntegration)

I've run over it about as many ways as I can, and even went as far as reinstalling, but I still can't get it to work. Looking up this error doesn't return much to me, either.

Thanks for any help!

答:
First result on Google says this is a DLL error.

From this answer:

Open the Developer Command Prompt for VS212 as Administrator

Execute the command cd C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies

Execute the command gacutil /if Microsoft.SqlServer.Dts.Design.dll

Restart Visual Studio


问:
The most efficient way to compare object's property in two arrays
I need to check in Angular2 if one object's property in one array is the same in another array and return value. Is there any more efficient way to do it or maybe something similar to .contains in Swift?

```<code>doSomething(){
    for (let element1 of array1) {
        for (let element2 of array2) {
            if (element1.id == element2.id) {
                return Observable.fromPromise(element2);
            }
        }
    }
}
</code>```

EDIT:

I have to subscribe to this value because I am loading value from the database (in fromPromise):

```<code>this.doSomething().subscribe(id => {
...
}
</code>```

答:
When dealing with arrays it is usually more readable to use higher order methods;

in your case you could filter the outer array using the return of some through the inner array, and then map it :

```<code>array2.filter( x =>
  array1.some( z => z.id == x.id )
).map(x => Observable.fromPromise(x) )
</code>```

Body:
I need to check in Angular2 if one object's property in one array is the same in another array and return value. Is there any more efficient way to do it or maybe something similar to .contains in Swift?

doSomething(){
    for (let element1 of array1) {
        for (let element2 of array2) {
            if (element1.id == element2.id) {
                return Observable.fromPromise(element2);
            }
        }
    }
}

EDIT:

I have to subscribe to this value because I am loading value from the database (in fromPromise):

this.doSomething().subscribe(id => {
...
}

Body:
When dealing with arrays it is usually more readable to use higher order methods;

in your case you could filter the outer array using the return of some through the inner array, and then map it :

array2.filter( x =>
  array1.some( z => z.id == x.id )
).map(x => Observable.fromPromise(x) )


问:
button1.PerformClick() in wpf
Why this code in WPF does not work ?

```<code>private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("yes");
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        button1.PerformClick();
    }
</code>```

I need to command.

答:
Good practice in WPF is using commands. It improves testability and separates UI and business logic.

First you may try RoutedUICommand.

```<code><Window x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:self ="clr-namespace:Test"
    Title="MainWindow"
    Height="350" Width="525">
<Window.CommandBindings>
    <CommandBinding Command="{x:Static self:MainWindow.RoutedClickCommand}"
                    CanExecute="CommandBinding_CanExecute"
                    Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Grid>
    <Button Content="Test" Name="Btn1" Command="{x:Static self:MainWindow.RoutedClickCommand}"/>
</Grid>
</code>```

In code behind file we have to define RoutedClickCommand and Execute|CanExecute handlers:

```<code>    public static ICommand RoutedClickCommand = new RoutedUICommand("ClickCommand", "ClickCommand", typeof(MainWindow));

    private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("ololo");
    }
</code>```

So, when you need button logic ("button1.PerformClick();" in your sample), just put next line:

```<code>MainWindow.RoutedClickCommand.Execute(null);
</code>```

As for me, I preffer another way which supposes carry command into presentation model. Composite Application Library (Prism) helps me with its DelegateCommand class. Then command definition in presentation model looks like:

```<code>    private DelegateCommand<object> _clickCommand;

    public ICommand ClickCommand
    {
        get
        {
            if (this._clickCommand == null)
            {
                this._clickCommand = new DelegateCommand<object>(p =>
                    {
                        //command logic
                    },
                    p =>
                    {
                        // can execute command logic
                    });
            }
            return this._clickCommand;
        }
    }
</code>```

And view XAML and code behind:

```<code><Window x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:self ="clr-namespace:Test"
    Title="MainWindow"
    Height="350" Width="525">
<Grid>
    <Button Content="Test" Name="Btn1" Command="{Binding ClickCommand}"/>
</Grid>
</code>```

```<code>public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.Model = new SampleModel();
    }

    protected SampleModel Model
    {
        get
        {
            if (this.Model.ClickCommand.CanExecute())
            {
                this.Model.ClickCommand.Execute();
            }
            return (SampleModel)this.DataContext;
        }
        set
        {
            this.DataContext = value;
        }
    }
}
</code>```

Next code calls command in view bypassing clicking on button:

```<code>if (this.Model.ClickCommand.CanExecute())
{
 this.Model.ClickCommand.Execute();
}
</code>```

Title: button1.PerformClick() in wpf

Body:
Why this code in WPF does not work ?

private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("yes");
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        button1.PerformClick();
    }

I need to command.

Body:
Good practice in WPF is using commands. It improves testability and separates UI and business logic.

First you may try RoutedUICommand.

<Window x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:self ="clr-namespace:Test"
    Title="MainWindow"
    Height="350" Width="525">
<Window.CommandBindings>
    <CommandBinding Command="{x:Static self:MainWindow.RoutedClickCommand}"
                    CanExecute="CommandBinding_CanExecute"
                    Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<Grid>
    <Button Content="Test" Name="Btn1" Command="{x:Static self:MainWindow.RoutedClickCommand}"/>
</Grid>

In code behind file we have to define RoutedClickCommand and Execute|CanExecute handlers:

    public static ICommand RoutedClickCommand = new RoutedUICommand("ClickCommand", "ClickCommand", typeof(MainWindow));

    private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("ololo");
    }

So, when you need button logic ("button1.PerformClick();" in your sample), just put next line:

MainWindow.RoutedClickCommand.Execute(null);

As for me, I preffer another way which supposes carry command into presentation model. Composite Application Library (Prism) helps me with its DelegateCommand class. Then command definition in presentation model looks like:

    private DelegateCommand<object> _clickCommand;

    public ICommand ClickCommand
    {
        get
        {
            if (this._clickCommand == null)
            {
                this._clickCommand = new DelegateCommand<object>(p =>
                    {
                        //command logic
                    },
                    p =>
                    {
                        // can execute command logic
                    });
            }
            return this._clickCommand;
        }
    }

And view XAML and code behind:

<Window x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:self ="clr-namespace:Test"
    Title="MainWindow"
    Height="350" Width="525">
<Grid>
    <Button Content="Test" Name="Btn1" Command="{Binding ClickCommand}"/>
</Grid>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.Model = new SampleModel();
    }

    protected SampleModel Model
    {
        get
        {
            if (this.Model.ClickCommand.CanExecute())
            {
                this.Model.ClickCommand.Execute();
            }
            return (SampleModel)this.DataContext;
        }
        set
        {
            this.DataContext = value;
        }
    }
}

Next code calls command in view bypassing clicking on button:

if (this.Model.ClickCommand.CanExecute())
{
 this.Model.ClickCommand.Execute();
}


问:
IOException: read failed, socket might closed - Bluetooth on Android 4.3
Currently I am trying to deal with a strange Exception when opening a BluetoothSocket on my Nexus 7 (2012), with Android 4.3 (Build JWR66Y, I guess the second 4.3 update). I have seen some related postings (e.g. https://stackoverflow.com/questions/13648373/bluetoothsocket-connect-throwing-exception-read-failed), but none seems to provide a workaround for this issue. Also, as suggested in these threads, re-pairing does not help, and constantly trying to connect (through a stupid loop) also has no effect.

I am dealing with an embedded device (a noname OBD-II car adapter, similar to http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE-LIGHTS-WITH-YOUR-PHONE-Oceanside.jpg). My Android 2.3.7 phone does not have any issues connecting, and the Xperia of a colleague (Android 4.1.2) also works. Another Google Nexus (I dont know if 'One' or 'S', but not '4') also fails with Android 4.3.

Here is the Snippet of the connection establishment. It is running in its own Thread, created within a Service.

```<code>private class ConnectThread extends Thread {

    private static final UUID EMBEDDED_BOARD_SPP = UUID
        .fromString("00001101-0000-1000-8000-00805F9B34FB");

    private BluetoothAdapter adapter;
    private boolean secure;
    private BluetoothDevice device;
    private List<UUID> uuidCandidates;
    private int candidate;
    protected boolean started;

    public ConnectThread(BluetoothDevice device, boolean secure) {
        logger.info("initiliasing connection to device "+device.getName() +" / "+ device.getAddress());
        adapter = BluetoothAdapter.getDefaultAdapter();
        this.secure = secure;
        this.device = device;

        setName("BluetoothConnectThread");

        if (!startQueryingForUUIDs()) {
            this.uuidCandidates = Collections.singletonList(EMBEDDED_BOARD_SPP);
            this.start();
        } else{
            logger.info("Using UUID discovery mechanism.");
        }
        /*
         * it will start upon the broadcast receive otherwise
         */
    }

    private boolean startQueryingForUUIDs() {
        Class<?> cl = BluetoothDevice.class;

        Class<?>[] par = {};
        Method fetchUuidsWithSdpMethod;
        try {
            fetchUuidsWithSdpMethod = cl.getMethod("fetchUuidsWithSdp", par);
        } catch (NoSuchMethodException e) {
            logger.warn(e.getMessage());
            return false;
        }

        Object[] args = {};
        try {
            BroadcastReceiver receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    BluetoothDevice deviceExtra = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
                    Parcelable[] uuidExtra = intent.getParcelableArrayExtra("android.bluetooth.device.extra.UUID");

                    uuidCandidates = new ArrayList<UUID>();
                    for (Parcelable uuid : uuidExtra) {
                        uuidCandidates.add(UUID.fromString(uuid.toString()));
                    }

                    synchronized (ConnectThread.this) {
                        if (!ConnectThread.this.started) {
                            ConnectThread.this.start();
                            ConnectThread.this.started = true;
                            unregisterReceiver(this);
                        }

                    }
                }

            };
            registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
            registerReceiver(receiver, new IntentFilter("android.bluetooth.device.action.UUID"));

            fetchUuidsWithSdpMethod.invoke(device, args);
        } catch (IllegalArgumentException e) {
            logger.warn(e.getMessage());
            return false;
        } catch (IllegalAccessException e) {
            logger.warn(e.getMessage());
            return false;
        } catch (InvocationTargetException e) {
            logger.warn(e.getMessage());
            return false;
        }

        return true;
    }

    public void run() {
        boolean success = false;
        while (selectSocket()) {

            if (bluetoothSocket == null) {
                logger.warn("Socket is null! Cancelling!");
                deviceDisconnected();
                openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
            }

            // Always cancel discovery because it will slow down a connection
            adapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                bluetoothSocket.connect();
                success = true;
                break;

            } catch (IOException e) {
                // Close the socket
                try {
                    shutdownSocket();
                } catch (IOException e2) {
                    logger.warn(e2.getMessage(), e2);
                }
            }
        }

        if (success) {
            deviceConnected();
        } else {
            deviceDisconnected();
            openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
        }
    }

    private boolean selectSocket() {
        if (candidate >= uuidCandidates.size()) {
            return false;
        }

        BluetoothSocket tmp;
        UUID uuid = uuidCandidates.get(candidate++);
        logger.info("Attempting to connect to SDP "+ uuid);
        try {
            if (secure) {
                tmp = device.createRfcommSocketToServiceRecord(
                        uuid);
            } else {
                tmp = device.createInsecureRfcommSocketToServiceRecord(
                        uuid);
            }
            bluetoothSocket = tmp;
            return true;
        } catch (IOException e) {
            logger.warn(e.getMessage() ,e);
        }

        return false;
    }

}
</code>```

The code is failing at bluetoothSocket.connect(). I am getting a java.io.IOException: read failed, socket might closed, read ret: -1. This is the corresponding source at GitHub: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L504
Its called through readInt(), called from https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319

Some metadata dump of the used socket resulted in the following information. These are exactly the same on Nexus 7 and my 2.3.7 phone.

```<code>Bluetooth Device 'OBDII'
Address: 11:22:33:DD:EE:FF
Bond state: 12 (bonded)
Type: 1
Class major version: 7936
Class minor version: 7936
Class Contents: 0
Contents: 0
</code>```

I have some other OBD-II adapters (more expansives) and they all work. Is there any chance, that I am missing something or might this be a bug in Android?

答:
Bluetooth devices can operate in both classic and LE mode at the same time. Sometimes they use a different MAC address depending on which way you are connecting. Calling socket.connect() is using Bluetooth Classic, so you have to make sure the device you got when you scanned was really a classic device.

It's easy to filter for only Classic devices, however:

if(BluetoothDevice.DEVICE_TYPE_LE == device.getType()){
    //socket.connect()
}

Without this check, it's a race condition as to whether a hybrid scan will give you the Classic device or the BLE device first. It may appear as intermittent inability to connect, or as certain devices being able to connect reliably while others seemingly never can.

Body:
Currently I am trying to deal with a strange Exception when opening a BluetoothSocket on my Nexus 7 (2012), with Android 4.3 (Build JWR66Y, I guess the second 4.3 update). I have seen some related postings (e.g. https://stackoverflow.com/questions/13648373/bluetoothsocket-connect-throwing-exception-read-failed), but none seems to provide a workaround for this issue. Also, as suggested in these threads, re-pairing does not help, and constantly trying to connect (through a stupid loop) also has no effect.

I am dealing with an embedded device (a noname OBD-II car adapter, similar to http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE-LIGHTS-WITH-YOUR-PHONE-Oceanside.jpg). My Android 2.3.7 phone does not have any issues connecting, and the Xperia of a colleague (Android 4.1.2) also works. Another Google Nexus (I dont know if 'One' or 'S', but not '4') also fails with Android 4.3.

Here is the Snippet of the connection establishment. It is running in its own Thread, created within a Service.

private class ConnectThread extends Thread {

    private static final UUID EMBEDDED_BOARD_SPP = UUID
        .fromString("00001101-0000-1000-8000-00805F9B34FB");

    private BluetoothAdapter adapter;
    private boolean secure;
    private BluetoothDevice device;
    private List<UUID> uuidCandidates;
    private int candidate;
    protected boolean started;

    public ConnectThread(BluetoothDevice device, boolean secure) {
        logger.info("initiliasing connection to device "+device.getName() +" / "+ device.getAddress());
        adapter = BluetoothAdapter.getDefaultAdapter();
        this.secure = secure;
        this.device = device;

        setName("BluetoothConnectThread");

        if (!startQueryingForUUIDs()) {
            this.uuidCandidates = Collections.singletonList(EMBEDDED_BOARD_SPP);
            this.start();
        } else{
            logger.info("Using UUID discovery mechanism.");
        }
        /*
         * it will start upon the broadcast receive otherwise
         */
    }

    private boolean startQueryingForUUIDs() {
        Class<?> cl = BluetoothDevice.class;

        Class<?>[] par = {};
        Method fetchUuidsWithSdpMethod;
        try {
            fetchUuidsWithSdpMethod = cl.getMethod("fetchUuidsWithSdp", par);
        } catch (NoSuchMethodException e) {
            logger.warn(e.getMessage());
            return false;
        }

        Object[] args = {};
        try {
            BroadcastReceiver receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    BluetoothDevice deviceExtra = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
                    Parcelable[] uuidExtra = intent.getParcelableArrayExtra("android.bluetooth.device.extra.UUID");

                    uuidCandidates = new ArrayList<UUID>();
                    for (Parcelable uuid : uuidExtra) {
                        uuidCandidates.add(UUID.fromString(uuid.toString()));
                    }

                    synchronized (ConnectThread.this) {
                        if (!ConnectThread.this.started) {
                            ConnectThread.this.start();
                            ConnectThread.this.started = true;
                            unregisterReceiver(this);
                        }

                    }
                }

            };
            registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
            registerReceiver(receiver, new IntentFilter("android.bluetooth.device.action.UUID"));

            fetchUuidsWithSdpMethod.invoke(device, args);
        } catch (IllegalArgumentException e) {
            logger.warn(e.getMessage());
            return false;
        } catch (IllegalAccessException e) {
            logger.warn(e.getMessage());
            return false;
        } catch (InvocationTargetException e) {
            logger.warn(e.getMessage());
            return false;
        }

        return true;
    }

    public void run() {
        boolean success = false;
        while (selectSocket()) {

            if (bluetoothSocket == null) {
                logger.warn("Socket is null! Cancelling!");
                deviceDisconnected();
                openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
            }

            // Always cancel discovery because it will slow down a connection
            adapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                bluetoothSocket.connect();
                success = true;
                break;

            } catch (IOException e) {
                // Close the socket
                try {
                    shutdownSocket();
                } catch (IOException e2) {
                    logger.warn(e2.getMessage(), e2);
                }
            }
        }

        if (success) {
            deviceConnected();
        } else {
            deviceDisconnected();
            openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
        }
    }

    private boolean selectSocket() {
        if (candidate >= uuidCandidates.size()) {
            return false;
        }

        BluetoothSocket tmp;
        UUID uuid = uuidCandidates.get(candidate++);
        logger.info("Attempting to connect to SDP "+ uuid);
        try {
            if (secure) {
                tmp = device.createRfcommSocketToServiceRecord(
                        uuid);
            } else {
                tmp = device.createInsecureRfcommSocketToServiceRecord(
                        uuid);
            }
            bluetoothSocket = tmp;
            return true;
        } catch (IOException e) {
            logger.warn(e.getMessage() ,e);
        }

        return false;
    }

}

The code is failing at bluetoothSocket.connect(). I am getting a java.io.IOException: read failed, socket might closed, read ret: -1. This is the corresponding source at GitHub: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L504
Its called through readInt(), called from https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319

Some metadata dump of the used socket resulted in the following information. These are exactly the same on Nexus 7 and my 2.3.7 phone.

Bluetooth Device 'OBDII'
Address: 11:22:33:DD:EE:FF
Bond state: 12 (bonded)
Type: 1
Class major version: 7936
Class minor version: 7936
Class Contents: 0
Contents: 0

I have some other OBD-II adapters (more expansives) and they all work. Is there any chance, that I am missing something or might this be a bug in Android?


问:
Checking for null value with DataTable.Select
I'm using a DataTable select like this:

```<code>DataRow[] rows = employees.Select("Name LIKE '%" + TB_Search.Text + "%'");

LV_Employees.DataSource = rows;
LV_Employees.DataBind();
</code>```

I have a listview where I'm checking a value that is contained in the datarows that I'm using in the list and I'm checking a value like this:

```<code><%# Eval("Title") == DBNull.Value ? "" : Eval("Title") %>
</code>```

But when I do this I still get this error:

Unable to cast object of type 'System.DBNull' to type 'System.String'.

I tried checking Eval("Title") == null as well and got the same error. I'm not sure how else to check for the null values that would fix this issue.

Things I've also tried that still gave the same error:

(Eval("Title") as string) ?? ""

Convert.IsDBNull(Eval("Title")) ? "" : "test"

string.IsNullOrEmpty(Eval("Title").ToString()) ? "" : "test"

Eval("Title").ToString().IsNullOrEmpty() ? "" : "test"

答:
CopyToDataTable should fix the issue:</p>

```<code>LV_Employees.DataSource = employees.Select("Name LIKE '%" + TB_Search.Text + "%'")
    .CopyToDataTable();
LV_Employees.DataBind();
</code>```

Body:
I'm using a DataTable select like this:

DataRow[] rows = employees.Select("Name LIKE '%" + TB_Search.Text + "%'");

LV_Employees.DataSource = rows;
LV_Employees.DataBind();

I have a listview where I'm checking a value that is contained in the datarows that I'm using in the list and I'm checking a value like this:

<%# Eval("Title") == DBNull.Value ? "" : Eval("Title") %>

But when I do this I still get this error:

Unable to cast object of type 'System.DBNull' to type 'System.String'.

I tried checking Eval("Title") == null as well and got the same error. I'm not sure how else to check for the null values that would fix this issue.

Things I've also tried that still gave the same error:

(Eval("Title") as string) ?? ""

Convert.IsDBNull(Eval("Title")) ? "" : "test"

string.IsNullOrEmpty(Eval("Title").ToString()) ? "" : "test"

Eval("Title").ToString().IsNullOrEmpty() ? "" : "test"

Body:
CopyToDataTable should fix the issue:

LV_Employees.DataSource = employees.Select("Name LIKE '%" + TB_Search.Text + "%'")
    .CopyToDataTable();
LV_Employees.DataBind();


问:
How can I diff two git branches in bitbucket pipeline

Background

I want to make sure that all commit messages on the pushed branch have a time log in it

ie. add readme /spend 5m

Problem

I want to get the commit diff between two git branches in bitbucket pipeline,

this is my yaml pipeline config:

```<code>pipelines:
  default:
    - step:
        script:
          - git log $BITBUCKET_BRANCH --oneline --not master
</code>```

$BITBUCKET_BRANCH is the branch the pipeline is acting on.

but the pipeline is returning an error when trying to compare with master

```<code>+ git log $BITBUCKET_BRANCH --oneline --not master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
</code>```

Note that the setup step in the pipeline(this is pre-defined by bitbucket and I can't change it)

```<code>git clone --branch="abdullah-s/bitbucketpipelinesyml-created-online-wit-1489917130851" --depth 50 https://x-token-auth:$REPOSITORY_OAUTH_ACCESS_TOKEN@bitbucket.org/abdullah-s/webook.git $BUILD_DIR;
git reset --hard ac61f080a28428bdd885735374164577a2b0aa43;
git remote set-url origin git@bitbucket.org:abdullah-s/webook.git
</code>```

in the first command of the setup, bitbucket is cloning only one branch from my repo

What I tried

I tried to pull master

```<code>- git checkout -b master
- git pull origin master
- git log $BITBUCKET_BRANCH --oneline --not master
</code>```

but got an error

```<code>+ git pull origin master
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
</code>```

Question

How can I compare two branches in bitbucket pipeline?

答:
As you rightfully point out, Bitbucket pipelines will only clone the specific branch that triggered the build.

As such, the RefSpec will be set to the specific branch, and you'll be unable to merge or diff other branches.

For example, if the build was triggered on the develop branch, then the following refspec will be set:

```<code>[remote "origin"]
    url = git@bitbucket.org:xxxxxx
    fetch = +refs/heads/develop:refs/remotes/origin/develop
[branch "develop"]
    remote = origin
    merge = refs/heads/develop
</code>```

If you look at the available branches you'll see this :

```<code>+ git branch -a
* develop
  remotes/origin/develop
</code>```

You can execute the following command :

```<code>git fetch origin "+refs/heads/*:refs/remotes/origin/*"
</code>```

to pull in all other branches / tags

```<code>From bitbucket.org:xxxx/xxxxx
 * [new branch]      master     -> origin/master
 * [new branch]      release    -> origin/release
 * [new tag]         xxxx -> xxxx
</code>```

Body:
Background

I want to make sure that all commit messages on the pushed branch have a time log in it

ie. add readme /spend 5m

Problem

I want to get the commit diff between two git branches in bitbucket pipeline,

this is my yaml pipeline config:

pipelines:
  default:
    - step:
        script:
          - git log $BITBUCKET_BRANCH --oneline --not master

$BITBUCKET_BRANCH is the branch the pipeline is acting on.

but the pipeline is returning an error when trying to compare with master

+ git log $BITBUCKET_BRANCH --oneline --not master
fatal: ambiguous argument 'master': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Note that the setup step in the pipeline(this is pre-defined by bitbucket and I can't change it)

git clone --branch="abdullah-s/bitbucketpipelinesyml-created-online-wit-1489917130851" --depth 50 https://x-token-auth:$REPOSITORY_OAUTH_ACCESS_TOKEN@bitbucket.org/abdullah-s/webook.git $BUILD_DIR;
git reset --hard ac61f080a28428bdd885735374164577a2b0aa43;
git remote set-url origin git@bitbucket.org:abdullah-s/webook.git

in the first command of the setup, bitbucket is cloning only one branch from my repo

What I tried

I tried to pull master

- git checkout -b master
- git pull origin master
- git log $BITBUCKET_BRANCH --oneline --not master

but got an error

+ git pull origin master
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

Question

How can I compare two branches in bitbucket pipeline?

Body:
As you rightfully point out, Bitbucket pipelines will only clone the specific branch that triggered the build.

As such, the RefSpec will be set to the specific branch, and you'll be unable to merge or diff other branches.

For example, if the build was triggered on the develop branch, then the following refspec will be set:

[remote "origin"]
    url = git@bitbucket.org:xxxxxx
    fetch = +refs/heads/develop:refs/remotes/origin/develop
[branch "develop"]
    remote = origin
    merge = refs/heads/develop

If you look at the available branches you'll see this :

+ git branch -a
* develop
  remotes/origin/develop

You can execute the following command :

git fetch origin "+refs/heads/*:refs/remotes/origin/*"

to pull in all other branches / tags

From bitbucket.org:xxxx/xxxxx
 * [new branch]      master     -> origin/master
 * [new branch]      release    -> origin/release
 * [new tag]         xxxx -> xxxx


问:
Modify slinghttpresponse through wrapper
I am trying to override default sendredirect funtionality in AEM.

I would like to redirect to https urls from my server.

FOr the same I have implemented a sling filter. Implemented SlingHttpServletResponseWrapper class and overridden  sendredirect function.

However, in filter when I try to

final SlingHttpServletResponse slingResponse = (ModifyLocResponse) response;

At runtime I get

org.apache.sling.security.impl.ContentDispositionFilter$RewriterResponse cannot be cast to com.adobe.acs.samples.filters.wrappers.ModifyLocResponse

答:
Instead of casting, try instantiating it by something like this:

```<code>final SlingHttpServletResponse slingResponse = new ModifyLocResponse(response);
</code>```

Of course you'll need to make sure the constructor for that class has this pattern too:

```<code>class ModifyLocResponse extends SlingHttpServletResponseWrapper {
    public ModifyLocResponse(SlingHttpServletResponse response) {
        super(response);
    }
    ...
}
</code>```

Body:
Instead of casting, try instantiating it by something like this:

final SlingHttpServletResponse slingResponse = new ModifyLocResponse(response);

Of course you'll need to make sure the constructor for that class has this pattern too:

class ModifyLocResponse extends SlingHttpServletResponseWrapper {
    public ModifyLocResponse(SlingHttpServletResponse response) {
        super(response);
    }
    ...
}


问:
java 8 stream API filter out empty value from map
i have a map, need to operate on each entry's value, and return the modified map. I managed to get it working, but the resulted map contains entries with empty value, and I want to remove those entries but cannot with Java 8 stream API.

here is my original code:

```<code>Map<String, List<Test>> filtered = Maps.newHashMap();
for (String userId : userTests.keySet()) {
    List<Test> tests = userTests.get(userId);
    List<Test> filteredTests = filterByType(tests, supportedTypes);

    if (!CollectionUtils.isEmpty(filteredTests)) {
        filtered.put(userId, filteredTests);
    }
}
return filtered;
</code>```

and here is my Java 8 stream API version:

```<code>userTests.entrySet().stream()
         .forEach(entry -> entry.setValue(filterByType(entry.getValue(), supportedTypes)));

userTests.entrySet().stream().filter(entry -> !entry.getValue().isEmpty());
        return userTests;
</code>```

how can i remove entries with empty/null value from the map?

is there better way to write the code in stream API, so far I don't see it's better than my original code

答:
userTests.entrySet().stream().filter(entry -> !entry.getValue().isEmpty());
this has no effect. filter is not a terminal operation.

You need to collect the stream result into a new map:

```<code>HashMap<String, String> map = new HashMap<>();
map.put("s","");
map.put("not empty", "not empty");

Map<String, String> notEmtpy = map.entrySet().stream()
     .filter(e -> !e.getValue().isEmpty())
     .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
</code>```

Body:
i have a map, need to operate on each entry's value, and return the modified map. I managed to get it working, but the resulted map contains entries with empty value, and I want to remove those entries but cannot with Java 8 stream API.

here is my original code:

Map<String, List<Test>> filtered = Maps.newHashMap();
for (String userId : userTests.keySet()) {
    List<Test> tests = userTests.get(userId);
    List<Test> filteredTests = filterByType(tests, supportedTypes);

    if (!CollectionUtils.isEmpty(filteredTests)) {
        filtered.put(userId, filteredTests);
    }
}
return filtered;

and here is my Java 8 stream API version:

userTests.entrySet().stream()
         .forEach(entry -> entry.setValue(filterByType(entry.getValue(), supportedTypes)));

userTests.entrySet().stream().filter(entry -> !entry.getValue().isEmpty());
        return userTests;

how can i remove entries with empty/null value from the map?

is there better way to write the code in stream API, so far I don't see it's better than my original code

Body:
userTests.entrySet().stream().filter(entry -> !entry.getValue().isEmpty());
this has no effect. filter is not a terminal operation.

You need to collect the stream result into a new map:

HashMap<String, String> map = new HashMap<>();
map.put("s","");
map.put("not empty", "not empty");

Map<String, String> notEmtpy = map.entrySet().stream()
     .filter(e -> !e.getValue().isEmpty())
     .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));


问:
Bug in python tokenize?
Why would this

```<code>if 1 \
and 0:
    pass
</code>```

simplest of code choke on tokenize/untokenize cycle

```<code>import tokenize
import cStringIO

def tok_untok(src):
    f = cStringIO.StringIO(src)
    return tokenize.untokenize(tokenize.generate_tokens(f.readline))

src='''if 1 \\
and 0:
    pass
'''
print tok_untok(src)
</code>```

It throws:

```<code>AssertionError:
File "/mnt/home/anushri/untitled-1.py", line 13, in <module>
  print tok_untok(src)
File "/mnt/home/anushri/untitled-1.py", line 6, in tok_untok
  tokenize.untokenize(tokenize.generate_tokens(f.readline))
File "/usr/lib/python2.6/tokenize.py", line 262, in untokenize
  return ut.untokenize(iterable)
File "/usr/lib/python2.6/tokenize.py", line 198, in untokenize
  self.add_whitespace(start)
File "/usr/lib/python2.6/tokenize.py", line 187, in add_whitespace
  assert row <= self.prev_row
</code>```

Is there a workaround without modifying the src to be tokenized (it seems \ is the culprit)

Another example where it fails is if no newline at end e.g. src='if 1:pass' fails with same error

Workaround:
But it seems  using untokenize different way works

```<code>def tok_untok(src):
    f = cStringIO.StringIO(src)
    tokens = [ t[:2] for t in tokenize.generate_tokens(f.readline)]
    return tokenize.untokenize(tokens)
</code>```

i.e. do not pass back whole token tuple but only  t[:2]

though python doc says extra args are skipped

Converts tokens back into Python source code. The iterable must return
  sequences with at least two elements,
  the token type and the token string.
  Any additional sequence elements are
  ignored.

答: Yes, it's a known bug and there is interest in a cleaner patch than the one attached to that issue. Perfect time to contribute to a better Python ;)</p>

Title: Bug in python tokenize?

Body:
Why would this

if 1 \
and 0:
    pass

simplest of code choke on tokenize/untokenize cycle

import tokenize
import cStringIO

def tok_untok(src):
    f = cStringIO.StringIO(src)
    return tokenize.untokenize(tokenize.generate_tokens(f.readline))

src='''if 1 \\
and 0:
    pass
'''
print tok_untok(src)

It throws:

AssertionError:
File "/mnt/home/anushri/untitled-1.py", line 13, in <module>
  print tok_untok(src)
File "/mnt/home/anushri/untitled-1.py", line 6, in tok_untok
  tokenize.untokenize(tokenize.generate_tokens(f.readline))
File "/usr/lib/python2.6/tokenize.py", line 262, in untokenize
  return ut.untokenize(iterable)
File "/usr/lib/python2.6/tokenize.py", line 198, in untokenize
  self.add_whitespace(start)
File "/usr/lib/python2.6/tokenize.py", line 187, in add_whitespace
  assert row <= self.prev_row

Is there a workaround without modifying the src to be tokenized (it seems \ is the culprit)

Another example where it fails is if no newline at end e.g. src='if 1:pass' fails with same error

Workaround:
But it seems  using untokenize different way works

def tok_untok(src):
    f = cStringIO.StringIO(src)
    tokens = [ t[:2] for t in tokenize.generate_tokens(f.readline)]
    return tokenize.untokenize(tokens)

i.e. do not pass back whole token tuple but only  t[:2]

though python doc says extra args are skipped

Converts tokens back into Python source code. The iterable must return
  sequences with at least two elements,
  the token type and the token string.
  Any additional sequence elements are
  ignored.


问:
Printing select results from an array with a while loop
So I have this assignment where we build upon a website we created little by little each week. This week I have to write some javascript code that's function is to display a requested number of results from within an array. The number requested is entered in a form text input. The instructions are as follows:

a. Create an input that acts as a fill in the blank for a sentence that prompts the user to
enter the number of job duties they want to see.

b. Create a button that calls a function when clicked (the function created in the next step)

c. Crate a function that takes the user input and assigns the value to a variable.

d. Create an array with at least five job duties in it.

e. Create a new variable and set it equal to the inputted value minus 1

f. Create a while loop that runs while the variable (that represents the index value that we want to print) is greater than or equal to the minimum array value.

g. Within the while loop have two things happen: Have the innerHTML of some element within your page be replaced with the array value that corresponds to the index number that we want printed. You specify the array value by the format arrayname[indexnumber]. Also Have the index subtract one from itself to count down

At this point your function should run, but it does not work properly. Only the array value at the last index is printed. To fix this, we need to concatenate the results of the loop.

i. Create a new variable outside of the loop and set it to be equal to blank

You do this by setting it equal to “”

ii. Within the loop, make this variable to be equal to itself plus the array value that we want printed.

iii. Now change the innerHTML to be equal to this variable.

I have this so far yet its not working:

function showDuties() {
  var numDuties = document.getElementById('pfJobs').value;

  var pfDuties = ["Auditing", "Close out registers", "Clean free weights",
    "Sign up new members", "File paperwork"
  ]

  var i = numDuties - 1

  while (i >= 0) {
    document.getElementById('pfj').innerHTML = pfDuties[0, 1, 2, 3, 4];
    i--;
  }```
<pre class="snippet-code-html lang-html prettyprint-override"><code><form>
  <input type="submit" value="Click here"    onclick="showDuties()">
    to see my top
 <input type="text" id="pfJobs" />
   job duties here.
 <p id = "pfj">
 </p>
</form></code>```

What this ends up doing is replacing the text in the paragraph tag in my HTML with an element from within the array, but it only flashes on the screen for half a second then disappears.

I apologize if my formatting is incorrect this is my first time using this site.
Any help would be greatly appreciated.

答:
You can use slice to get a copy of a portion of your array and join to join these array values into a single string

document.querySelector('button').addEventListener('click', showDuties);

function showDuties() {
  var numDuties = document.getElementById('pfJobs').value;

  var pfDuties = ["Auditing", "Close out registers", "Clean free weights", "Sign up new members", "File paperwork"]

  document.getElementById('pfj').innerHTML = pfDuties.slice(0,numDuties).join(", ");
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><input type="number" id="pfJobs" value="0" max="5">
<button>show jobs</button>

<p id="pfj"></p></code>```

Body:
So I have this assignment where we build upon a website we created little by little each week. This week I have to write some javascript code that's function is to display a requested number of results from within an array. The number requested is entered in a form text input. The instructions are as follows:

a. Create an input that acts as a fill in the blank for a sentence that prompts the user to
enter the number of job duties they want to see.

b. Create a button that calls a function when clicked (the function created in the next step)

c. Crate a function that takes the user input and assigns the value to a variable.

d. Create an array with at least five job duties in it.

e. Create a new variable and set it equal to the inputted value minus 1

f. Create a while loop that runs while the variable (that represents the index value that we want to print) is greater than or equal to the minimum array value.

g. Within the while loop have two things happen: Have the innerHTML of some element within your page be replaced with the array value that corresponds to the index number that we want printed. You specify the array value by the format arrayname[indexnumber]. Also Have the index subtract one from itself to count down

At this point your function should run, but it does not work properly. Only the array value at the last index is printed. To fix this, we need to concatenate the results of the loop.

i. Create a new variable outside of the loop and set it to be equal to blank

You do this by setting it equal to “”

ii. Within the loop, make this variable to be equal to itself plus the array value that we want printed.

iii. Now change the innerHTML to be equal to this variable.

I have this so far yet its not working:

function showDuties() {
  var numDuties = document.getElementById('pfJobs').value;

  var pfDuties = ["Auditing", "Close out registers", "Clean free weights",
    "Sign up new members", "File paperwork"
  ]

  var i = numDuties - 1

  while (i >= 0) {
    document.getElementById('pfj').innerHTML = pfDuties[0, 1, 2, 3, 4];
    i--;
  }

<form>
  <input type="submit" value="Click here"    onclick="showDuties()">
    to see my top
 <input type="text" id="pfJobs" />
   job duties here.

</form>

What this ends up doing is replacing the text in the paragraph tag in my HTML with an element from within the array, but it only flashes on the screen for half a second then disappears.

I apologize if my formatting is incorrect this is my first time using this site.
Any help would be greatly appreciated.

Body:
You can use slice to get a copy of a portion of your array and join to join these array values into a single string

document.querySelector('button').addEventListener('click', showDuties);

function showDuties() {
  var numDuties = document.getElementById('pfJobs').value;

  var pfDuties = ["Auditing", "Close out registers", "Clean free weights", "Sign up new members", "File paperwork"]

  document.getElementById('pfj').innerHTML = pfDuties.slice(0,numDuties).join(", ");
}

<input type="number" id="pfJobs" value="0" max="5">
<button>show jobs</button>

<p id="pfj"></p>


问:
Progress bar not working on HTML page
I'm using javascript and HTML to create a questionnaire form. My idea was to inform the user of how many questions they've got to go. I've tried a couple of ways of getting a progress bar to work which has led me to the code below. I want the bar to progress after the user has selected an answer to a question.

This is the javascript code.

```<code><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<script>
var progress = 0;
//need this to check if the question has not been answered before
var questions = {
    "q1": 0,
    "q2":0,
    "q3":0,
    "q4":0
}
$( function() {
    $("#progressbar-1").text(progress)
    $("input, select").change( function() {
        el_name = $(this).attr("name");
        switch (this.nodeName.toLowerCase()) {
            case "select":
            field =$("[name='"+el_name+"']");
            val = (field.val() === ""  || !field.val()) ? null: field.val();
            break;
            case "input":
            field =$("[name='"+el_name+"']:checked");
            val = field.length;
            break;
        }
        if (val) {
            if (!questions[el_name]) {
                progress = progress +1;
                questions[el_name]=1
            }
        } else {
            questions[el_name]=0
            progress = (progress > 0)?progress-1:0;
        }
        $("#progressbar-1").text(progress)
    })
})
</script>
</code>```

This is the HTML code.

```<code><div class="container-main bg-5">
    <button style="float:left" onclick="goBack()">Go Back</button>

    <h1>What IT sector could suit you</h1>
    <p>Take the questionnaire below!</p>

    <form id="quiz">
        <!-- Question 1 -->
        <h2>Do you enjoy fixing things</h2>
        <!-- Here are the choices for the first question. Each input tag must have the same name. For this question, the name is q1. -->
        <!-- The value is which answer the choice corresponds to. -->
        <label>
            <input type="radio" name="q1" id="q1" value="c1">
            Yes
        </label><br />
        <label>
            <input type="radio" name="q1" id="q1" value="c2">
            No
        </label><br />
        <label>
            <input type="radio" name="q1" id="q1" value="c3">
            Maybe
        </label><br />

        <!-- Question 2 -->
        <h2>Do you enjoy problem solving?</h2>
        <!-- Here are the choices for the second question. Notice how each input tag has the same name (q2), but a different name than the previous question. -->
        <label>
            <input type="radio" name="q2" value="c2">
            Yes
        </label><br />
        <label>
            <input type="radio" name="q2" value="c1">
            No
        </label><br />
        <label>
            <input type="radio" name="q2" value="c3">
            Unsure
        </label><br />

        <!-- Question 3 -->
        <h2>Do you enjoy maths?</h2>
        <!-- Choices for the third question -->
        <label>
            <input type="radio" name="q3" value="c2">
            Yes
        </label><br />
        <label>
            <input type="radio" name="q3" value="c1">
            No
        </label><br />
        <label>
            <input type="radio" name="q3" value="c3">
            Unsure
        </label><br />

        <!-- Question 4 -->
        <h2>Do you often take thing apart to rebuild them?</h2>
        <!-- Choices for the fourth question -->
        <label>
            <input type="radio" name="q4" value="c1">
            Yes
        </label><br />
        <label>
            <input type="radio" name="q4" value="c2">
            No
        </label><br />
        <label>
            <input type="radio" name="q4" value="c3">
            I have never done it before so i don't know
        </label><br />

        <!--Question 5 -->
        <h2>Hardware or Software?</h2>
        <label>
            <input type="radio" name="q5" value="c1">
            Hardware
        </label><br />
        <label>
            <input type="radio" name="q5" value="c2">
            Software
        </label><br />

        <button type='button' id="submit" onclick="tabulateAnswers()">Submit Your Answers</button>
        <button type="reset" id="reset" onclick="resetAnswer()">Reset</button>
    </form>

    <div id ="progressbar-1"></div>

</div>
</code>```

The number is increasing but no CSS is happening. I feel like i'm not doing something glaringly obvious.

答:
I have updated your progress bar HTML, JavaScript code and add some CSS.

Progress Bar HTML:

```<code><div class="progress_dashv2">
    <div  id="progressbar-1"> </div>
</div>
</code>```

JQuery Code:

```<code>var total_questions = 4;

// progress bar Calculation
var result =  progress / total_questions;
result = result * 100;

$("#progressbar-1").css({'width':result+'%','background-color':'red'});
$("#progressbar-1").text(progress);
</code>```

CSS Classes :

```<code>.progress_dashv2 {
    margin-top: 0px;
    background: #464646;
    width: 100%;
    float: left;
    border-radius: 3px;
    height: 30px;
}

#progressbar-1{
    line-height: 11px;
    padding: 10px;
    border-radius: 3px;
}
</code>```

Please refer to the following link (Your Example):

https://jsfiddle.net/fd8sntu8/1/

Title: Progress bar not working on HTML page

Body:
I'm using javascript and HTML to create a questionnaire form. My idea was to inform the user of how many questions they've got to go. I've tried a couple of ways of getting a progress bar to work which has led me to the code below. I want the bar to progress after the user has selected an answer to a question.

This is the javascript code.

This is the HTML code.

    <button style="float:left" onclick="goBack()">Go Back</button>

What IT sector could suit you

Take the questionnaire below!

    <form id="quiz">

Do you enjoy fixing things

            <input type="radio" name="q1" id="q1" value="c1">
            Yes

            <input type="radio" name="q1" id="q1" value="c2">
            No

            <input type="radio" name="q1" id="q1" value="c3">
            Maybe

Do you enjoy problem solving?

            <input type="radio" name="q2" value="c2">
            Yes

            <input type="radio" name="q2" value="c1">
            No

            <input type="radio" name="q2" value="c3">
            Unsure

Do you enjoy maths?

            <input type="radio" name="q3" value="c2">
            Yes

            <input type="radio" name="q3" value="c1">
            No

            <input type="radio" name="q3" value="c3">
            Unsure

Do you often take thing apart to rebuild them?

            <input type="radio" name="q4" value="c1">
            Yes

            <input type="radio" name="q4" value="c2">
            No

            <input type="radio" name="q4" value="c3">
            I have never done it before so i don't know

Hardware or Software?

            <input type="radio" name="q5" value="c1">
            Hardware

            <input type="radio" name="q5" value="c2">
            Software

        <button type='button' id="submit" onclick="tabulateAnswers()">Submit Your Answers</button>
        <button type="reset" id="reset" onclick="resetAnswer()">Reset</button>
    </form>

The number is increasing but no CSS is happening. I feel like i'm not doing something glaringly obvious.

Body:
I have updated your progress bar HTML, JavaScript code and add some CSS.

Progress Bar HTML:

<div class="progress_dashv2">
    <div  id="progressbar-1"> </div>
</div>

JQuery Code:

var total_questions = 4;

// progress bar Calculation
var result =  progress / total_questions;
result = result * 100;

$("#progressbar-1").css({'width':result+'%','background-color':'red'});
$("#progressbar-1").text(progress);

CSS Classes :

.progress_dashv2 {
    margin-top: 0px;
    background: #464646;
    width: 100%;
    float: left;
    border-radius: 3px;
    height: 30px;
}

#progressbar-1{
    line-height: 11px;
    padding: 10px;
    border-radius: 3px;
}

Please refer to the following link (Your Example):

https://jsfiddle.net/fd8sntu8/1/


问:
RecyclerView.ItemDecoration doesn't update after item is removed from RecyclerView.Adapter

My question

How can I get my ItemDecoration to "update" the item offsets for other views when I remove a given view from my adapter and then call notifyItemRemoved() ?

In my particular situation, I have an ItemDecoration that provides a small amount of top offset to every item, and a large amount of bottom offset to the last item only. When I remove the last item, the view that becomes the new last item does not have any bottom offset.

Before and after:

If I then scroll the list around, when I return to the bottom of the list, my "new" last item has the correct offsets. It's only an issue for as long as the "new" last item remains visible on the screen.

What I've tried

If I change my notifyItemRemoved() call to notifyDataSetChanged(), the new last item will have the correct item offsets applied, but I lose the built-in animation I get from notifyItemRemoved().

If I keep using notifyItemRemoved() and additionally call notifyItemChanged() on the previous item, then I will get the correct item offsets but the animation is somewhat janky; the second-to-last item (before the removal) seems to fade out and then in again (in this screenshot, the card saying "item 19" was just removed):

I know that I can create a large space at the end of my list by applying bottom padding to my <RecyclerView> tag and specifying android:clipToPadding="false", but this solution is not acceptable for various reasons.

To reproduce

I originally encountered this issue in a much larger app I'm working on, but here's a tiny app that demonstrates the issue.

MainActivity.java:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final MyAdapter adapter = new MyAdapter(20);

    Button button = findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            adapter.removeItemAt(adapter.getItemCount() - 1);
        }
    });

    RecyclerView recycler = findViewById(R.id.recycler);
    recycler.setLayoutManager(new LinearLayoutManager(this));
    recycler.addItemDecoration(new MyItemDecoration());
    recycler.setAdapter(adapter);
}

private static class MyItemDecoration extends RecyclerView.ItemDecoration {

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int viewPosition = parent.getChildViewHolder(view).getLayoutPosition();
        int lastPosition = state.getItemCount() - 1;

        outRect.top = 20;
        outRect.bottom = (viewPosition == lastPosition) ? 200 : 0;
    }
}

private static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    private final List<String> list;

    private MyAdapter(int count) {
        this.list = new ArrayList<>();

        for (int i = 0; i < count; ++i) {
            list.add("" + i);
        }
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.item, parent, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.text.setText("item: " + list.get(position));
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    private void removeItemAt(int position) {
        if (list.size() > 0) {
            list.remove(position);
            notifyItemRemoved(position);
        }
    }
}

private static class MyViewHolder extends RecyclerView.ViewHolder {

    private final TextView text;

    public MyViewHolder(View itemView) {
        super(itemView);
        this.text = itemView.findViewById(R.id.text);
    }
}
}```
</div>
</div>
</p>

<p>activity_main.xml:</p>

<p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-html lang-html prettyprint-override"><code><LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#eee">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="REMOVE LAST ITEM"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout></code>```

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="4dp">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:layout_margin="8dp"
        android:gravity="center"
        android:textColor="#000"
        android:textSize="16sp"/>

</android.support.v7.widget.CardView>```

答:
I solved this by changing my removeItemAt() method as follows:

```<code>private void removeItemAt(int position) {
    if (list.size() > 0) {
        list.remove(position);
        notifyItemRemoved(position);

        if (position != 0) {
            notifyItemChanged(position - 1, Boolean.FALSE);
        }
    }
}
</code>```

The second argument to notifyItemChanged() is the key. It can be literally any object, but I chose Boolean.FALSE because it's a "well-known" object and because it conveys a little bit of intent: I don't want animations to run on the item I'm changing.

Why it works

It turns out that there's a second onBindViewHolder() method defined in RecyclerView.Adapter that I'd never seen before. From the source code:

```<code>public void onBindViewHolder(VH holder, int position, List<Object> payloads) {
    onBindViewHolder(holder, position);
}
</code>```

Excerpted from that method's documentation:

The payloads parameter is a merge list from notifyItemChanged(int, Object) or notifyItemRangeChanged(int, int, Object).  If the payloads list is not empty, the ViewHolder is currently bound to old data and Adapter may run an efficient partial update using the payload info.  If the payload is empty,  Adapter must run a full bind.

In other words, by passing something (anything) as a payload in notifyItemChanged(), we're telling the system that we want to perform only a "partial update" (in situations where that's possible).

So, sure, we've instructed the system to perform a partial update... but how does that stop the flickering caused by simply calling notifyItemChanged(position - 1) ? It has to do with the RecyclerView.ItemAnimator that's attached to all RecyclerViews by default: DefaultItemAnimator.

DefaultItemAnimator's source code includes this method:

```<code>@Override
public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder,
        @NonNull List<Object> payloads) {
    return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}
</code>```

You'll notice that this method also takes a List<Object> payloads parameter. This is the same list of payloads as used in the other onBindViewHolder() call mentioned above.

Because we passed a payload argument, this method will return true. And since the animator is now told that it can reuse the already-existing ViewHolder for our "changed" item, it doesn't tear it down and create a new one (or reuse a recycled one)... which stops the default fade animation on the changed item from running!

Body:
My question

How can I get my ItemDecoration to "update" the item offsets for other views when I remove a given view from my adapter and then call notifyItemRemoved() ?

In my particular situation, I have an ItemDecoration that provides a small amount of top offset to every item, and a large amount of bottom offset to the last item only. When I remove the last item, the view that becomes the new last item does not have any bottom offset.

Before and after:

If I then scroll the list around, when I return to the bottom of the list, my "new" last item has the correct offsets. It's only an issue for as long as the "new" last item remains visible on the screen.

What I've tried

If I change my notifyItemRemoved() call to notifyDataSetChanged(), the new last item will have the correct item offsets applied, but I lose the built-in animation I get from notifyItemRemoved().

If I keep using notifyItemRemoved() and additionally call notifyItemChanged() on the previous item, then I will get the correct item offsets but the animation is somewhat janky; the second-to-last item (before the removal) seems to fade out and then in again (in this screenshot, the card saying "item 19" was just removed):

I know that I can create a large space at the end of my list by applying bottom padding to my <RecyclerView> tag and specifying android:clipToPadding="false", but this solution is not acceptable for various reasons.

To reproduce

I originally encountered this issue in a much larger app I'm working on, but here's a tiny app that demonstrates the issue.

MainActivity.java:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final MyAdapter adapter = new MyAdapter(20);

    Button button = findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            adapter.removeItemAt(adapter.getItemCount() - 1);
        }
    });

    RecyclerView recycler = findViewById(R.id.recycler);
    recycler.setLayoutManager(new LinearLayoutManager(this));
    recycler.addItemDecoration(new MyItemDecoration());
    recycler.setAdapter(adapter);
}

private static class MyItemDecoration extends RecyclerView.ItemDecoration {

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int viewPosition = parent.getChildViewHolder(view).getLayoutPosition();
        int lastPosition = state.getItemCount() - 1;

        outRect.top = 20;
        outRect.bottom = (viewPosition == lastPosition) ? 200 : 0;
    }
}

private static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    private final List<String> list;

    private MyAdapter(int count) {
        this.list = new ArrayList<>();

        for (int i = 0; i < count; ++i) {
            list.add("" + i);
        }
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.item, parent, false);
        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.text.setText("item: " + list.get(position));
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    private void removeItemAt(int position) {
        if (list.size() > 0) {
            list.remove(position);
            notifyItemRemoved(position);
        }
    }
}

private static class MyViewHolder extends RecyclerView.ViewHolder {

    private final TextView text;

    public MyViewHolder(View itemView) {
        super(itemView);
        this.text = itemView.findViewById(R.id.text);
    }
}
}

activity_main.xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#eee">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="REMOVE LAST ITEM"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="4dp">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:layout_margin="8dp"
        android:gravity="center"
        android:textColor="#000"
        android:textSize="16sp"/>

</android.support.v7.widget.CardView>

Body:
I solved this by changing my removeItemAt() method as follows:

private void removeItemAt(int position) {
    if (list.size() > 0) {
        list.remove(position);
        notifyItemRemoved(position);

        if (position != 0) {
            notifyItemChanged(position - 1, Boolean.FALSE);
        }
    }
}

The second argument to notifyItemChanged() is the key. It can be literally any object, but I chose Boolean.FALSE because it's a "well-known" object and because it conveys a little bit of intent: I don't want animations to run on the item I'm changing.

Why it works

It turns out that there's a second onBindViewHolder() method defined in RecyclerView.Adapter that I'd never seen before. From the source code:

public void onBindViewHolder(VH holder, int position, List<Object> payloads) {
    onBindViewHolder(holder, position);
}

Excerpted from that method's documentation:

The payloads parameter is a merge list from notifyItemChanged(int, Object) or notifyItemRangeChanged(int, int, Object).  If the payloads list is not empty, the ViewHolder is currently bound to old data and Adapter may run an efficient partial update using the payload info.  If the payload is empty,  Adapter must run a full bind.

In other words, by passing something (anything) as a payload in notifyItemChanged(), we're telling the system that we want to perform only a "partial update" (in situations where that's possible).

So, sure, we've instructed the system to perform a partial update... but how does that stop the flickering caused by simply calling notifyItemChanged(position - 1) ? It has to do with the RecyclerView.ItemAnimator that's attached to all RecyclerViews by default: DefaultItemAnimator.

DefaultItemAnimator's source code includes this method:

@Override
public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder,
        @NonNull List<Object> payloads) {
    return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}

You'll notice that this method also takes a List<Object> payloads parameter. This is the same list of payloads as used in the other onBindViewHolder() call mentioned above.

Because we passed a payload argument, this method will return true. And since the animator is now told that it can reuse the already-existing ViewHolder for our "changed" item, it doesn't tear it down and create a new one (or reuse a recycled one)... which stops the default fade animation on the changed item from running!


问:
What does this "!string" mean?
I'm going through an old code library at my workplace to document it and re-use it for other projects.
The Library isn't documented at all (not even comments) but that's not a big deal.

I found this strange syntax and I can't find an explanation online to what it is...

```<code>public bool Validate()
    {
        return !string.IsNullOrWhiteSpace(Code) && !string.IsNullOrWhiteSpace(State);
    }
</code>```

I get that the Exclamation point is the negation operator, but it's only possible to use it with Boolean variables. How is it possible to say not(string)? What does that exclamation point before the string keyword does? The tooltip didn't help either..

答: That's the standard logical negation operator.</p>

Title: What does this "!string" mean?

Body:
I'm going through an old code library at my workplace to document it and re-use it for other projects.
The Library isn't documented at all (not even comments) but that's not a big deal.

I found this strange syntax and I can't find an explanation online to what it is...

public bool Validate()
    {
        return !string.IsNullOrWhiteSpace(Code) && !string.IsNullOrWhiteSpace(State);
    }

I get that the Exclamation point is the negation operator, but it's only possible to use it with Boolean variables. How is it possible to say not(string)? What does that exclamation point before the string keyword does? The tooltip didn't help either..


问:
multiple column layout inside a tabPanel
I generate a lot of input using renderUI, I would like to have a multicolumn display inside a tabPanel.

Of course the number of input is dynamic :-)

Any idea how do do this ?

```<code>   library(shiny)
ui <- fluidPage(
  titlePanel("Old Faithful Geyser Data"),
  sidebarLayout(
    sidebarPanel(
    ),
    mainPanel(
      tabsetPanel(
        tabPanel("Plot",
uiOutput("lot_of_input")
        ),
        tabPanel("Summary", verbatimTextOutput("summary"))
      )
    )
  )
)

server <- function(input, output) {

  output$lot_of_input <- renderUI({
list(
  numericInput(inputId = "A","A",1),
      numericInput(inputId = "AB","AB",1),numericInput(inputId = "B","C",1),
      numericInput(inputId = "C2","C",1),
      numericInput(inputId = "A3","A",1),
      numericInput(inputId = "AB3","AB",1),
      numericInput(inputId = "B3","C",1),
      numericInput(inputId = "C23","C",1)#, lot of other input
) # In my code this list is returned by a function
  })

  output$summary <- renderText("coucou")
}

# Run the application
shinyApp(ui = ui, server = server)
</code>```

not this :

but this :

答:
fluidRow and column should arrange it accordingly as shown below:

```<code>list(
          fluidRow(
            column(3,
                   numericInput(inputId = "A","A",1)),
            column(3,
                   numericInput(inputId = "C2","C",1))
          ),

          fluidRow(
            column(3,
                   numericInput(inputId = "AB","AB",1)),
            column(3,
                   numericInput(inputId = "A3","A",1))
          ),

          fluidRow(
            column(3,
                   numericInput(inputId = "B","C",1)),
            column(3,
                   numericInput(inputId = "AB3","AB",1))
          ),

          fluidRow(
            column(3,
                   numericInput(inputId = "B3","C",1)),
            column(3,
                   numericInput(inputId = "C23","C",1))
          )
        )
</code>```

You can add more columns in 1 row  by adjusting the width of column and adding more inputs inside one fluidRow.

Body:
I generate a lot of input using renderUI, I would like to have a multicolumn display inside a tabPanel.

Of course the number of input is dynamic :-)

Any idea how do do this ?

   library(shiny)
ui <- fluidPage(
  titlePanel("Old Faithful Geyser Data"),
  sidebarLayout(
    sidebarPanel(
    ),
    mainPanel(
      tabsetPanel(
        tabPanel("Plot",
uiOutput("lot_of_input")
        ),
        tabPanel("Summary", verbatimTextOutput("summary"))
      )
    )
  )
)

server <- function(input, output) {

  output$lot_of_input <- renderUI({
list(
  numericInput(inputId = "A","A",1),
      numericInput(inputId = "AB","AB",1),numericInput(inputId = "B","C",1),
      numericInput(inputId = "C2","C",1),
      numericInput(inputId = "A3","A",1),
      numericInput(inputId = "AB3","AB",1),
      numericInput(inputId = "B3","C",1),
      numericInput(inputId = "C23","C",1)#, lot of other input
) # In my code this list is returned by a function
  })

  output$summary <- renderText("coucou")
}

# Run the application
shinyApp(ui = ui, server = server)

not this :

but this :

Body:
fluidRow and column should arrange it accordingly as shown below:

list(
          fluidRow(
            column(3,
                   numericInput(inputId = "A","A",1)),
            column(3,
                   numericInput(inputId = "C2","C",1))
          ),

          fluidRow(
            column(3,
                   numericInput(inputId = "AB","AB",1)),
            column(3,
                   numericInput(inputId = "A3","A",1))
          ),

          fluidRow(
            column(3,
                   numericInput(inputId = "B","C",1)),
            column(3,
                   numericInput(inputId = "AB3","AB",1))
          ),

          fluidRow(
            column(3,
                   numericInput(inputId = "B3","C",1)),
            column(3,
                   numericInput(inputId = "C23","C",1))
          )
        )

You can add more columns in 1 row  by adjusting the width of column and adding more inputs inside one fluidRow.