问:
node-ytdl-core promise audio title and file download
I'm relatively new to promises, and i'm having trouble with two things while using node-ytdl-core.

```<code> exports.downloadMP3 = function(bot, msg, sSuffix) {
    return Promise
    .all([
        ytdl(sSuffix, {filter : 'audioonly',}).pipe(fs.createWriteStream('audio.mp3')),
        promiseTitle(sSuffix)
    ])
    .then(function(results) {msg.channel.sendFile('audio.mp3', results[1], '', '')})
    .catch(error => console.error(error));
}

function promiseTitle(sSuffix) {
    return new Promise(function (resolve, reject) {
        ytdl.getInfo(sSuffix, function(err, info) {
            if (err) reject(err);
            console.log(info.title);
            return resolve(info.title);
        });
    });
}
</code>```

When I use the above code, the returned title is a string along the lines of a25998454d48491.V, though the console logs the correct title. Meaning the promise doesn't return my desired value.

Furthermore the createWriteStream doesn't get resolved before the file gets sent (sendFile) meaning i get a 0byte file, though after a bit the file is done downloading and has the correct size/content in the filesystem.

My question therefore is how do I return the correct value in my promise, and turn createWriteStream into a promise?

Thanks in advance.

答:
Figured it out. The title was fine, but sendFile() doesn't allow '/' in the filename. The video I was testing with had that character. Furthermode in the code below I managed to turn the ytdl stream into a buffer by appending all the data of the stream to an array using stream events. The another event can be used (the end event) to finally send your buffer. </p>

```<code>exports.downloadMP3 = function(bot, msg, sSuffix) {
    return Promise
    .all([
        promiseTitle(sSuffix)
    ])
    .then(function(results) {
        let stream = ytdl(sSuffix, {filter : 'audioonly',});
        let aData = [];

        stream.on('data', function(data) {
          aData.push(data);
        });

        stream.on('end', function() {
            let buffer = Buffer.concat(aData);
            let title = results[0].replace(/[^a-zA-Z0-9]/g,'_');
            console.log(title);
            msg.channel.sendFile(buffer, `${title}.mp3`, '', '');
        });
    })
    .catch(error => console.error(error));
}

function promiseTitle(sSuffix) {
    return new Promise(function (resolve, reject) {
        ytdl.getInfo(sSuffix, function(err, info) {
            if (err) reject(err);
            console.log(info);
            resolve(info.title);
        });
    });
}
</code>```

Body:
I'm relatively new to promises, and i'm having trouble with two things while using node-ytdl-core.

 exports.downloadMP3 = function(bot, msg, sSuffix) {
    return Promise
    .all([
        ytdl(sSuffix, {filter : 'audioonly',}).pipe(fs.createWriteStream('audio.mp3')),
        promiseTitle(sSuffix)
    ])
    .then(function(results) {msg.channel.sendFile('audio.mp3', results[1], '', '')})
    .catch(error => console.error(error));
}

function promiseTitle(sSuffix) {
    return new Promise(function (resolve, reject) {
        ytdl.getInfo(sSuffix, function(err, info) {
            if (err) reject(err);
            console.log(info.title);
            return resolve(info.title);
        });
    });
}

When I use the above code, the returned title is a string along the lines of a25998454d48491.V, though the console logs the correct title. Meaning the promise doesn't return my desired value.

Furthermore the createWriteStream doesn't get resolved before the file gets sent (sendFile) meaning i get a 0byte file, though after a bit the file is done downloading and has the correct size/content in the filesystem.

My question therefore is how do I return the correct value in my promise, and turn createWriteStream into a promise?

Thanks in advance.

Body:
Figured it out. The title was fine, but sendFile() doesn't allow '/' in the filename. The video I was testing with had that character. Furthermode in the code below I managed to turn the ytdl stream into a buffer by appending all the data of the stream to an array using stream events. The another event can be used (the end event) to finally send your buffer.

exports.downloadMP3 = function(bot, msg, sSuffix) {
    return Promise
    .all([
        promiseTitle(sSuffix)
    ])
    .then(function(results) {
        let stream = ytdl(sSuffix, {filter : 'audioonly',});
        let aData = [];

        stream.on('data', function(data) {
          aData.push(data);
        });

        stream.on('end', function() {
            let buffer = Buffer.concat(aData);
            let title = results[0].replace(/[^a-zA-Z0-9]/g,'_');
            console.log(title);
            msg.channel.sendFile(buffer, `${title}.mp3`, '', '');
        });
    })
    .catch(error => console.error(error));
}

function promiseTitle(sSuffix) {
    return new Promise(function (resolve, reject) {
        ytdl.getInfo(sSuffix, function(err, info) {
            if (err) reject(err);
            console.log(info);
            resolve(info.title);
        });
    });
}


来源: stackexchange

问:
Unable to locate JDK
i ve installed visual studio 2017 but its giving me jdk error for xamarin. I have browsed to C:\ProgramData\Microsoft\VisualStudio\Packages\JavaJDKV2,version=1.8.1,chip=x64 but its still giving me error unable to locate JDK. Please guide me through.</p>

答:
Environment variables for java installation

Add Java to your Environment variables as shown in the above post.

Make sure you already have Java installed on your computer:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

ContentLicense: CC BY-SA 3.0

Title: Unable to locate JDK


问:
Kotlin generics
How is it possible to enforce a generic type for a method in Kotlin?
I know for instance you can do the following:

```<code>var someVar: MutableSet<out SomeType> = hashSetOf()
</code>```

How can you do the same for a method?

```<code>fun <T> doSomething() {
}
</code>```

I'd like to enforce T to be of type X or a sub-type of it.

Thanks.

答:
Actually out SomeType means more than "type Parameter can be SomeType or any of its subtypes" as your questions suggests.

The keyword out is Kotlin's way to say that, in this example, the MutableSet is a Producer of SomeType, i.e.  it is covariant in its type parameter. As a consequence you will not be able to call methods like add(t:T), but only those which return Ts, like get():T.

Back to your question: if your method is supposed to accept types of X or its subtypes, you should use "bounds":

```<code>fun <T : X> doSomething() {
}
</code>```

This is just what you need, but to make it clear again, it cannot be said to be the equivalent to your other example.

Title: Kotlin generics

Body:
How is it possible to enforce a generic type for a method in Kotlin?
I know for instance you can do the following:

var someVar: MutableSet<out SomeType> = hashSetOf()

How can you do the same for a method?

fun <T> doSomething() {
}

I'd like to enforce T to be of type X or a sub-type of it.

Thanks.

Body:
Actually out SomeType means more than "type Parameter can be SomeType or any of its subtypes" as your questions suggests.

The keyword out is Kotlin's way to say that, in this example, the MutableSet is a Producer of SomeType, i.e.  it is covariant in its type parameter. As a consequence you will not be able to call methods like add(t:T), but only those which return Ts, like get():T.

Back to your question: if your method is supposed to accept types of X or its subtypes, you should use "bounds":

fun <T : X> doSomething() {
}

This is just what you need, but to make it clear again, it cannot be said to be the equivalent to your other example.


问:
Why are string in .net case sensitive by default?
Most times I want to do string comparisons I want them to be case insensitive.

So why are string in .net case sensitive by default?

EDIT 1: To be clear I think the below should return true by default. Or at least allow me to have a compile time flag that makes it so.

```<code>"John Smith" == "JOHN SMITH"
</code>```

EDIT 2: I can think of many more examples of things that should be case insensitive

Examples of things that should be case insensitive

Usernames

Urls

File extensions / File names / Directory names / Paths

Machine / servernames

State / Country / Location etc

FirstName / LastName / Initials

Guids

Month / Day names

Examples of things that should be case sensitive

Passwords

答:
String comparison in .Net is case-sensitive because strings (and individual characters) are inherently case-sensitive.

The character 'a' is stored internally with a different ASCII or Unicode value as 'A'. Saying that 'a' is the same as 'A' is not "correct".

This distinction becomes critical when comparing values in languages other than English, when using algorithms like hash tables, or when using many encryption/decryption algorithms.

My two cents: case sensitive compare is the default because it is correct.

ContentLicense: CC BY-SA 2.5

Body:
Most times I want to do string comparisons I want them to be case insensitive.

So why are string in .net case sensitive by default?

EDIT 1: To be clear I think the below should return true by default. Or at least allow me to have a compile time flag that makes it so.

"John Smith" == "JOHN SMITH"

EDIT 2: I can think of many more examples of things that should be case insensitive

Examples of things that should be case insensitive

Usernames

Urls

File extensions / File names / Directory names / Paths

Machine / servernames

State / Country / Location etc

FirstName / LastName / Initials

Guids

Month / Day names

Examples of things that should be case sensitive

Passwords


问:
Firebase Authentication - User Shifting from Google to Facebook and vice versa
I have an Android App where user can Login from Google or Facebook.

Considering user can download app in many devices I am facing a situation I need some help or guidance about.

The situations and problems are:

When user login in device A with Google and later in Device B => Everything is fine.

When user login in device A with Google and later in device B with Facebook firebase auth fail even user is using same email in Google and Facebook.

The same if user login first in Facebook and later in Google.

Any idea how to manage that in Firebase Authentication ?

答:
For scenario 2: If you sign up with Google and then try to login with a Facebook account that has the same email as the google account, you will get an error account-exists-with-different-credential:. To handle this situation, check this post: Handling linking accounts in Firebase

For scenario 3: This happens because Google is the issuer of the account (gmail.com). In that case, the Facebook account is unlinked. The next time the user tries to login with the Facebook account they will encounter scenario 2. For more on this, check this post: Authentication using Facebook at first and then Google causes an error in Firebase for Android


问:
Python selection-sort with while loop returns unaltered array—why?
I hate having to ask like this, but I'm at my wits' end. Doesn't help that the assignment I'm doing this for requires a while loop contained in a for loop, rather than a nested for loop that every example I've ever been able to find has used. Very frustrating.

So here's the code, with comments written out for my own reference as best as I can understand what's going on (I'm not a very good programmer as of now).

```<code>def selection_sort(arr):
    for indexvalue in range (0, len(arr) - 1): #we want to start with the 0th item in the index for selection sort and end at the second-to-last one,
        currentmin = indexvalue #establishes the first variable as our lowest looked at so far. This is something that changes every time we go over the array, looking for the next lowest number
        while indexvalue<len(arr):
            if arr[indexvalue] < arr[currentmin]: #allows us to find the new lowest value—anything lower than our currently-located minimum should count as our new lowest value
                arr[indexvalue], arr[currentmin] = arr[currentmin], arr[indexvalue] #exchanges the two values so that our current lowest value is set one to the left in the array, and the new lowest value one to the right
                indexvalue = indexvalue+1 #adds another 1 to our counter so that we can compare the next-indexed items
            else: #should occur when we reach the end of our array
                break #forcibly ends the while loop, and by extension the function
</code>```

Not really sure what's going on—as best as I can process it works, but it clearly doesn't. For example, when I run:

```<code>testlist=[10, 12, 15, 1, 0, 4, 99]
selection_sort(testlist)
print(testlist)
</code>```

I get testlist, unaltered. Any idea why this might be? I'm clearly missing something important, but I have no clue what it might be.

Edit: new, improved code below. Not perfect, but it's sorting something now at least. This set results in a set of data that seems to be replacing elements with their index positions; I'm fairly sure that it's being caused by line 6. Not sure why though.

```<code>def selection_sort(arr):
    for indexvalue in range (0, len(arr) - 1): #we want to start with the 0th item in the index for selection sort and end at the second-to-last one,
        currentmin = indexvalue #establishes the first variable as our lowest looked at so far. This is something that changes every time we go over the array, looking for the next lowest number
        while indexvalue<len(arr):
            if arr[indexvalue] > currentmin: #allows us to find the new lowest value—anything lower than our currently-located minimum should count as our new lowest value
                arr[indexvalue], currentmin = currentmin, arr[indexvalue] #exchanges the two values so that our current lowest value is set one to the left in the array, and the new lowest value one to the right
                indexvalue = indexvalue+1 #adds another 1 to our counter so that we can compare the next-indexed items
                print (arr)
            else: #should occur when we reach the end of our array
                break #forcibly ends the while loop, and by extension the function
</code>```

答:
Since you mentioned that you could learn best from fiddling around with working examples:

Enjoy and learn! ;)

```<code>def selection_sort(arr):
    for indexvalue in range (0, len(arr) - 1): #we want to start with the 0th item in the index for selection sort and end at the second-to-last one,
        indexval2 = indexvalue + 1 #new running-index in order not to lose track of where the unsorted part starts
        currentmin = indexvalue #establishes the first variable as our lowest looked at so far. This is something that changes every time we go over the array, looking for the next lowest number
        while indexval2 < len(arr):
            if arr[indexval2] < arr[currentmin]: #allows us to find the new lowest value—anything lower than our currently-located minimum should count as our new lowest value
                currentmin = indexval2 #sets currentmin to the new lowest value
            indexval2 = indexval2 + 1 #adds another 1 to our counter so that we can compare the next-indexed items
        arr[currentmin], arr[indexvalue] = arr[indexvalue], arr[currentmin] #swapping lowest to beginning of unsorted elements. This way it will be neglegted in the next for-iteration
</code>```

Body:
I hate having to ask like this, but I'm at my wits' end. Doesn't help that the assignment I'm doing this for requires a while loop contained in a for loop, rather than a nested for loop that every example I've ever been able to find has used. Very frustrating.

So here's the code, with comments written out for my own reference as best as I can understand what's going on (I'm not a very good programmer as of now).

def selection_sort(arr):
    for indexvalue in range (0, len(arr) - 1): #we want to start with the 0th item in the index for selection sort and end at the second-to-last one,
        currentmin = indexvalue #establishes the first variable as our lowest looked at so far. This is something that changes every time we go over the array, looking for the next lowest number
        while indexvalue<len(arr):
            if arr[indexvalue] < arr[currentmin]: #allows us to find the new lowest value—anything lower than our currently-located minimum should count as our new lowest value
                arr[indexvalue], arr[currentmin] = arr[currentmin], arr[indexvalue] #exchanges the two values so that our current lowest value is set one to the left in the array, and the new lowest value one to the right
                indexvalue = indexvalue+1 #adds another 1 to our counter so that we can compare the next-indexed items
            else: #should occur when we reach the end of our array
                break #forcibly ends the while loop, and by extension the function

Not really sure what's going on—as best as I can process it works, but it clearly doesn't. For example, when I run:

testlist=[10, 12, 15, 1, 0, 4, 99]
selection_sort(testlist)
print(testlist)

I get testlist, unaltered. Any idea why this might be? I'm clearly missing something important, but I have no clue what it might be.

Edit: new, improved code below. Not perfect, but it's sorting something now at least. This set results in a set of data that seems to be replacing elements with their index positions; I'm fairly sure that it's being caused by line 6. Not sure why though.

def selection_sort(arr):
    for indexvalue in range (0, len(arr) - 1): #we want to start with the 0th item in the index for selection sort and end at the second-to-last one,
        currentmin = indexvalue #establishes the first variable as our lowest looked at so far. This is something that changes every time we go over the array, looking for the next lowest number
        while indexvalue<len(arr):
            if arr[indexvalue] > currentmin: #allows us to find the new lowest value—anything lower than our currently-located minimum should count as our new lowest value
                arr[indexvalue], currentmin = currentmin, arr[indexvalue] #exchanges the two values so that our current lowest value is set one to the left in the array, and the new lowest value one to the right
                indexvalue = indexvalue+1 #adds another 1 to our counter so that we can compare the next-indexed items
                print (arr)
            else: #should occur when we reach the end of our array
                break #forcibly ends the while loop, and by extension the function

Body:
Since you mentioned that you could learn best from fiddling around with working examples:

Enjoy and learn! ;)

def selection_sort(arr):
    for indexvalue in range (0, len(arr) - 1): #we want to start with the 0th item in the index for selection sort and end at the second-to-last one,
        indexval2 = indexvalue + 1 #new running-index in order not to lose track of where the unsorted part starts
        currentmin = indexvalue #establishes the first variable as our lowest looked at so far. This is something that changes every time we go over the array, looking for the next lowest number
        while indexval2 < len(arr):
            if arr[indexval2] < arr[currentmin]: #allows us to find the new lowest value—anything lower than our currently-located minimum should count as our new lowest value
                currentmin = indexval2 #sets currentmin to the new lowest value
            indexval2 = indexval2 + 1 #adds another 1 to our counter so that we can compare the next-indexed items
        arr[currentmin], arr[indexvalue] = arr[indexvalue], arr[currentmin] #swapping lowest to beginning of unsorted elements. This way it will be neglegted in the next for-iteration


答:
Compile with any optimization flag other than the default -O0.  For example:

emcc counter.c -O1 -o counter.wasm -s WASM=1 -s SIDE_MODULE=1

The various optimization flags are listed here:

https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html

Title: WebAssembly Link Error: import object field 'DYNAMICTOP_PTR' is not a Number

Body:
The following C file is compiled to wasm with emscripten:

int counter = 100;

int count() {
    counter += 1;
    return counter;
}

$ emcc counter.c -o counter.wasm -s WASM=1 -s SIDE_MODULE=1

With no issues. I then have webpack loading the wasm file (with wasm-loader) as an UInt8Array:

var buffer = new ArrayBuffer(648);
var uint8 = new Uint8Array(buffer);
uint8.set([0,97,115,109,1,0,0,0,0,12,6,100,121,108,105,110,107,144,128,192,2,0,1,150,128,128,128,0,5,96,1,127,0,96,1,127,1,127,96,0,1,127,96,2,127,127,0,96,0,0,2,179,129,128,128,0,10,3,101,110,118,14,68,89,78,65,77,73,67,84,79,80,95,80,84,82,3,127,0,3,101,110,118,13,116,101,109,112,68,111,117,98,108,101,80,116,114,3,127,0,3,101,110,118,5,65,66,79,82,84,3,127,0,3,101,110,118,10,109,101,109,111,114,121,66,97,115,101,3,127,0,3,101,110,118,9,116,97,98,108,101,66,97,115,101,3,127,0,6,103,108,111,98,97,108,3,78,97,78,3,124,0,6,103,108,111,98,97,108,8,73,110,102,105,110,105,116,121,3,124,0,3,101,110,118,18,97,98,111,114,116,83,116,97,99,107,79,118,101,114,102,108,111,119,0,0,3,101,110,118,6,109,101,109,111,114,121,2,0,128,2,3,101,110,118,5,116,97,98,108,101,1,112,0,0,3,137,128,128,128,0,8,1,2,0,3,3,2,4,4,6,242,128,128,128,0,20,127,1,35,0,11,127,1,35,1,11,127,1,35,2,11,127,1,65,0,11,127,1,65,0,11,127,1,65,0,11,127,1,65,0,11,127,1,65,0,11,127,1,65,0,11,124,1,35,5,11,124,1,35,6,11,127,1,65,0,11,127,1,65,0,11,127,1,65,0,11,127,1,65,0,11,124,1,68,0,0,0,0,0,0,0,0,11,127,1,65,0,11,125,1,67,0,0,0,0,11,125,1,67,0,0,0,0,11,127,0,65,0,11,7,184,128,128,128,0,4,6,95,99,111,117,110,116,0,6,18,95,95,112,111,115,116,95,105,110,115,116,97,110,116,105,97,116,101,0,8,11,114,117,110,80,111,115,116,83,101,116,115,0,7,8,95,99,111,117,110,116,101,114,3,26,9,129,128,128,128,0,0,10,190,129,128,128,0,8,173,128,128,128,0,1,1,127,2,64,35,10,33,1,35,10,32,0,106,36,10,35,10,65,15,106,65,112,113,36,10,35,10,35,11,78,4,64,32,0,16,0,11,32,1,15,0,11,0,11,133,128,128,128,0,0,35,10,15,11,134,128,128,128,0,0,32,0,36,10,11,141,128,128,128,0,0,2,64,32,0,36,10,32,1,36,11,11,11,146,128,128,128,0,0,35,12,65,0,70,4,64,32,0,36,12,32,1,36,13,11,11,161,128,128,128,0,1,4,127,2,64,35,10,33,3,35,3,65,0,106,40,2,0,33,0,32,0,65,1,106,33,1,32,1,15,0,11,0,11,133,128,128,128,0,1,1,127,1,11,152,128,128,128,0,0,2,64,35,3,65,16,106,36,10,35,10,65,128,128,192,2,106,36,11,16,7,11,11,11,135,128,128,128,0,1,0,35,3,11,1,100,]);

My JS code then call the following:

import Counter from './wasm/counter'
const counter = new Counter();

And fails on the instantiation with the following Error:

LinkError: import object field 'DYNAMICTOP_PTR' is not a Number

wasm-loader uses the following default options (importObject) for WebAssembly.Instance(module, importObject):

{
  'global': {},
  'env': {
    'memory': new Memory({initial: 10, limit: 100}),
    'table': new Table({initial: 0, element: 'anyfunc'})
  }
}

Am I doing something wrong ? How can I successfully load the wasm code ?

Edit:
Following @Ghillie advice I tried to compile the C code with different optimization flags:

-O1, -02, -O3, -Os and -Oz  throw a LinkError: import object field 'memoryBase' is not a Number which is a different error but doesn't solve the issue.

Edit 2:

Solely adding the -O1 optimization flag didn't work but having a different error message allowed to debug the code so both @Ghillie and my answer offer the complete solution to my question.


问:
Multiple touches on a single button android
I have an app with buttons and I am trying to handle multitouch events. Currently I am using the on touch method and looking for MotionEven.ACTION_DOWN and MotionEven.ACTION_UP to keep track of touch events. This works fine if two buttons are touched at the same time. However, I want to have the buttons have one behavior when touched with a single finger and different behavior when touched with more fingers. For example, if you touch a button with one finger that button turns red, if you touch a button with 2 fingers that button turns yellow, if you touch a button with 3 fingers it turns green, and so on.

The problem I am running into is that when I touch a button with more than one finger, the second touch does not seem to trigger an event. How can I detect multiple touches on the same button?

答:
This is the basics of what you want.  It may not be completely what you want because there must be some space between fingers for the MotionEvents I used to be recognized.  If 2 fingers are close together, it gives ACTION_MOVE as the MotionEvent.  If you really need, you may be able to interpret those & determine if 2 or more fingers are down close together. MotionEvent

MainActivity.java

```<code>public class MainActivity extends AppCompatActivity {

    private static final int MAX_TOUCHES = 3;

    private View buttonView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        buttonView = findViewById(R.id.button_view);
        buttonView.setOnTouchListener(new View.OnTouchListener() {
            boolean eventConsumed = false;

            // Only handling these 4 events means that there must be some space
            //      between fingers when touching
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Log.d(TAG, "" + motionEvent.toString());
                switch (motionEvent.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                    case MotionEvent.ACTION_POINTER_DOWN:
                        setButtonColor(motionEvent.getPointerCount());
                        eventConsumed = true;
                        break;

                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        // subtract 1 from the count, this event still includes the touch just removed
                        setButtonColor(motionEvent.getPointerCount() - 1);
                        eventConsumed = true;
                        break;

                    default:
                        break;
                }

                return eventConsumed;
            }
        });
    }

    private void setButtonColor(int count) {
        Log.d(TAG, "count = " + count);

        if(count < 0) {
            count = 0;
        } else if(count > MAX_TOUCHES) {
            count = MAX_TOUCHES;
        }

        switch (count) {
            case 0:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorNotPressed));
                break;

            case 1:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorRed));
                break;

            case 2:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorYellow));
                break;

            case 3:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorGreen));
                break;

            default:
                break;
        }
    }

    // This keeps you from getting a warning about getResources().getColor() being deprecated
    @SuppressWarnings(value = "deprecation")
    private int getButtonColor(int id) {
        int color;

        if(Build.VERSION.SDK_INT >= 23) {
            color = getColor(id);
        } else {
            color = getResources().getColor(id);
        }
        return color;
    }
}
</code>```

activity_main.xml (not including AppBar or FAB stuff)

```<code><RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    >

    <View
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_centerInParent="true"
        android:text="Big Button"
        android:background="@color/colorNotPressed"
        android:id="@+id/button_view"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Big Button"
        android:textSize="20sp"
        />

</RelativeLayout>
</code>```

With these in your colors.xml file

```<code><color name="colorNotPressed">#606060</color>
<color name="colorRed">#FF0000</color>
<color name="colorYellow">#FFFF00</color>
<color name="colorGreen">#00FF00</color>
</code>```

Body:
This is the basics of what you want.  It may not be completely what you want because there must be some space between fingers for the MotionEvents I used to be recognized.  If 2 fingers are close together, it gives ACTION_MOVE as the MotionEvent.  If you really need, you may be able to interpret those & determine if 2 or more fingers are down close together. MotionEvent

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final int MAX_TOUCHES = 3;

    private View buttonView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        buttonView = findViewById(R.id.button_view);
        buttonView.setOnTouchListener(new View.OnTouchListener() {
            boolean eventConsumed = false;

            // Only handling these 4 events means that there must be some space
            //      between fingers when touching
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Log.d(TAG, "" + motionEvent.toString());
                switch (motionEvent.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                    case MotionEvent.ACTION_POINTER_DOWN:
                        setButtonColor(motionEvent.getPointerCount());
                        eventConsumed = true;
                        break;

                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        // subtract 1 from the count, this event still includes the touch just removed
                        setButtonColor(motionEvent.getPointerCount() - 1);
                        eventConsumed = true;
                        break;

                    default:
                        break;
                }

                return eventConsumed;
            }
        });
    }

    private void setButtonColor(int count) {
        Log.d(TAG, "count = " + count);

        if(count < 0) {
            count = 0;
        } else if(count > MAX_TOUCHES) {
            count = MAX_TOUCHES;
        }

        switch (count) {
            case 0:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorNotPressed));
                break;

            case 1:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorRed));
                break;

            case 2:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorYellow));
                break;

            case 3:
                buttonView.setBackgroundColor(getButtonColor(R.color.colorGreen));
                break;

            default:
                break;
        }
    }

    // This keeps you from getting a warning about getResources().getColor() being deprecated
    @SuppressWarnings(value = "deprecation")
    private int getButtonColor(int id) {
        int color;

        if(Build.VERSION.SDK_INT >= 23) {
            color = getColor(id);
        } else {
            color = getResources().getColor(id);
        }
        return color;
    }
}

activity_main.xml (not including AppBar or FAB stuff)

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    >

    <View
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_centerInParent="true"
        android:text="Big Button"
        android:background="@color/colorNotPressed"
        android:id="@+id/button_view"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Big Button"
        android:textSize="20sp"
        />

</RelativeLayout>

With these in your colors.xml file

<color name="colorNotPressed">#606060</color>
<color name="colorRed">#FF0000</color>
<color name="colorYellow">#FFFF00</color>
<color name="colorGreen">#00FF00</color>


问:
Not Found Page React Router V4
I want to have a not found component on my routes

```<code>import React from 'react';
import { Route, Switch } from 'react-router-dom';
import PropTypes from 'prop-types';
import Home from './components/home';
import MyWork from './components/work/myWork';
import WorkShow from './components/work/workShow';
import NavigationBar from './components/shared/navbar';
import Footer from './components/shared/footer';
import CategoryShow from './components/category/categoryShow';
import PostIndex from './components/post/postIndex';
import PostShow from './components/post/postShow';
import PostSearch from './components/post/postSearch';
import TagShow from './components/tag/tagShow';
import NotFound from './components/shared/notFound';

const DefaultLayout = ({ component: Component, ...rest }) => (
  <Route
    {...rest} render={matchProps => (
      <div>
        <NavigationBar />
        <div className="mainContent">
          <Component {...matchProps} />
        </div>
        <Footer />
      </div>
    )}
  />
);

DefaultLayout.propTypes = ({
  component: PropTypes.shape.isRequired,
});

const BlogLayout = ({ component: Component, ...rest }) => (
  <Route
    {...rest} render={matchProps => (
      <div>
        <NavigationBar path="blog" />
        <div className="mainContent">
          <Component {...matchProps} />
        </div>
        <Footer />
      </div>
    )}
  />
);

BlogLayout.propTypes = ({
  component: PropTypes.shape.isRequired,
});

const Work = () => (
  <Switch>
    <Route exact path="/my-work" component={MyWork} />
    <Route path="/my-work/:workName" component={WorkShow} />
  </Switch>
);

const Blog = () => (
  <Switch>
    <Route exact path="/blog" component={PostIndex} />
    <Route path="/blog/search" component={PostSearch} />
    <Route exact path="/blog/:postName" component={PostShow} />
    <Route path="/blog/category/:categoryName" component={CategoryShow} />
    <Route path="/blog/tag/:tagName" component={TagShow} />
  </Switch>
);

const routes = (
  <div>
    <DefaultLayout exact path="/" component={Home} />
    <DefaultLayout path="/my-work" component={Work} />
    <BlogLayout path="/blog" component={Blog} />
  </div>
);

export default routes;
</code>```

I tried:

```<code>const routes = (
      <div>
        <DefaultLayout exact path="/" component={Home} />
        <DefaultLayout path="/my-work" component={Work} />
        <BlogLayout path="/blog" component={Blog} />
        <BlogLayout path="*" component={NotFound} />
      </div>
    );
</code>```

But the NotFound component always renders, I only want this to render when the user enters an incorrect URL. How would I do this in react router v4?

答:
This is not a valid react router block:

```<code>const routes = (
  <div>
    <DefaultLayout exact path="/" component={Home} />
    <DefaultLayout path="/my-work" component={Work} />
    <BlogLayout path="/blog" component={Blog} />
  </div>
);
</code>```

You need to actually use React components like Route and Switch (just like you did in the Components themselves). Something like:

```<code><Switch>
  <Route exact path='/' component={Home}/>
  <Route path='/my-work' component={Work}/>
  <Route path='/blog' component={Blog}/>
</Switch>
</code>```

Title: Not Found Page React Router V4

Body:
I want to have a not found component on my routes

import React from 'react';
import { Route, Switch } from 'react-router-dom';
import PropTypes from 'prop-types';
import Home from './components/home';
import MyWork from './components/work/myWork';
import WorkShow from './components/work/workShow';
import NavigationBar from './components/shared/navbar';
import Footer from './components/shared/footer';
import CategoryShow from './components/category/categoryShow';
import PostIndex from './components/post/postIndex';
import PostShow from './components/post/postShow';
import PostSearch from './components/post/postSearch';
import TagShow from './components/tag/tagShow';
import NotFound from './components/shared/notFound';

const DefaultLayout = ({ component: Component, ...rest }) => (
  <Route
    {...rest} render={matchProps => (

        <NavigationBar />

          <Component {...matchProps} />

    )}
  />
);

DefaultLayout.propTypes = ({
  component: PropTypes.shape.isRequired,
});

const BlogLayout = ({ component: Component, ...rest }) => (
  <Route
    {...rest} render={matchProps => (

        <NavigationBar path="blog" />

          <Component {...matchProps} />

    )}
  />
);

BlogLayout.propTypes = ({
  component: PropTypes.shape.isRequired,
});

const Work = () => (
  <Switch>
    <Route exact path="/my-work" component={MyWork} />
    <Route path="/my-work/:workName" component={WorkShow} />
  </Switch>
);

const Blog = () => (
  <Switch>
    <Route exact path="/blog" component={PostIndex} />
    <Route path="/blog/search" component={PostSearch} />
    <Route exact path="/blog/:postName" component={PostShow} />
    <Route path="/blog/category/:categoryName" component={CategoryShow} />
    <Route path="/blog/tag/:tagName" component={TagShow} />
  </Switch>
);

const routes = (

    <DefaultLayout exact path="/" component={Home} />
    <DefaultLayout path="/my-work" component={Work} />
    <BlogLayout path="/blog" component={Blog} />

);

export default routes;

I tried:

const routes = (

        <DefaultLayout exact path="/" component={Home} />
        <DefaultLayout path="/my-work" component={Work} />
        <BlogLayout path="/blog" component={Blog} />
        <BlogLayout path="*" component={NotFound} />

    );

But the NotFound component always renders, I only want this to render when the user enters an incorrect URL. How would I do this in react router v4?

Body:
This is not a valid react router block:

const routes = (
  <div>
    <DefaultLayout exact path="/" component={Home} />
    <DefaultLayout path="/my-work" component={Work} />
    <BlogLayout path="/blog" component={Blog} />
  </div>
);

You need to actually use React components like Route and Switch (just like you did in the Components themselves). Something like:

<Switch>
  <Route exact path='/' component={Home}/>
  <Route path='/my-work' component={Work}/>
  <Route path='/blog' component={Blog}/>
</Switch>


问:
table elements not detecting :hover
so I have a small problem with my code. In my  element, I have a table. I have added titles to each of the images in the table, however they simply aren't displaying upon mousing over the image. I also have something in my css, that changes the colour of the table row and text, upon hovering over it. This also is not working. I have pasted the relevant code below, any help is appreciated. :D

HTML
`

```<code><aside class="second">
    <center><u>Popular Champions</u></center>
        <table border="1">
  <tr>
    <th>Champion</th>
    <th>Playrate (%)</th>
    <th>Lane</th>
    <th>Difficulty</th>
  </tr>
  <tr>
    <td><img src="Thresh.png"  title="Thresh" alt="Thresh"/></td>
    <td>42.75%</td>
    <td>Support</td>
    <td>2/5</td>
  </tr>
    <tr>
    <td><img src="LeeSin.png"  title="Lee Sin" alt="Lee Sin"/></td>
    <td>38.14%</td>
    <td>Jungle</td>
    <td>4/5</td>
  </tr>
  <tr>
    <td><img src="Caitlyn.png"  title="Caitlyn" alt="Caitlyn"/></td>
    <td>34.79%</td>
    <td>ADC</td>
    <td>1/5</td>
  </tr>
  <tr>
    <td><img src="Ezreal.png"  title="Ezreal" alt="Ezreal"/></td>
    <td>25.14%</td>
    <td>ADC</td>
    <td>1/5</td>
  </tr>
    <tr>
    <td><img src="Blitzcrank.png"  title="Blitzcrank" alt="Blitzcrank"/></td>
    <td>22.82%</td>
    <td>Support</td>
    <td>3/5</td>
  </tr>
    <tr>
    <td><img src="Elise.png"  title="Elise" alt="Elise"/></td>
    <td>22.62%</td>
    <td>Jungle</td>
    <td>4/5</td>
  </tr>
    <tr>
    <td><img src="Ahri.png"  title="Ahri" alt="Ahri"/></td>
    <td>17.15%</td>
    <td>Middle</td>
    <td>5/5</td>
  </tr>
    <tr>
    <td><img src="Orianna.png"  title="Orianna" alt="Orianna"/></td>
    <td>16.50%</td>
    <td>Middle</td>
    <td>3/5</td>
  </tr>
    <tr>
    <td><img src="Fiora.png"  title="Fiora" alt="Fiora"/></td>
    <td>16.18%</td>
    <td>Top</td>
    <td>4/5</td>
  </tr>
    <tr>
    <td><img src="Graves.png"  title="Graves" alt="Graves"/></td>
    <td>15.98%</td>
    <td>Jungle</td>
    <td>2/5</td>
  </tr>
</table>
</aside>
</code>```

`

CSS

`

```<code>aside tr:hover {
    background-color: white;
    color: black;
}
</code>```

`

EDIT
Turns out Hyperlinks positioned above (in a separate  element are also not registering any form of mouse input (unclickable links) I have pasted my entire code below:

HTML
`

```<code><!doctype html>
<html>
<head>
    <title>LoL Guide: Home</title>
    <link rel="stylesheet" href="style.css" type="text/css">
</head>

<body>
    <header>
        <nav>
            <a href="http://euw.leagueoflegends.com/" target="_blank">
            <img src="Logo.png">
            </a>
            <h1>League Of Legends Beginner's Guide</h1>
            <ul>
                <li>Home</li>
                <li><a href="page2.html">Champions</a></li>
                <li><a href="page3.html">Gameplay</a></li>
            </ul>
        </nav>
    </header>

    <aside class="New">
        <center> <u>Useful Links</u> </center>
        <ul>
        <li><a href="http://euw.leagueoflegends.com/" target="_blank">Official League of Legends website.</a> </li>
        <li><a href="http://leagueoflegends.wikia.com/wiki/League_of_Legends_Wiki" target="_blank">Official League of Legends Wiki</a> </li>
        <li><a href="https://www.reddit.com/r/leagueoflegends/" target="_blank">Official League of Legends Reddit</a> </li>
        </ul>
    </aside>
    <aside class="second">
    <center><u>Popular Champions</u></center>
        <table border="1">
  <tr>
    <th>Champion</th>
    <th>Playrate (%)</th>
    <th>Lane</th>
    <th>Difficulty</th>
  </tr>
  <tr>
    <td><img src="Thresh.png"  title="Thresh" alt="Thresh"/></td>
    <td>42.75%</td>
    <td>Support</td>
    <td>2/5</td>
  </tr>
    <tr>
    <td><img src="LeeSin.png"  title="Lee Sin" alt="Lee Sin"/></td>
    <td>38.14%</td>
    <td>Jungle</td>
    <td>4/5</td>
  </tr>
  <tr>
    <td><img src="Caitlyn.png"  title="Caitlyn" alt="Caitlyn"/></td>
    <td>34.79%</td>
    <td>ADC</td>
    <td>1/5</td>
  </tr>
  <tr>
    <td><img src="Ezreal.png"  title="Ezreal" alt="Ezreal"/></td>
    <td>25.14%</td>
    <td>ADC</td>
    <td>1/5</td>
  </tr>
    <tr>
    <td><img src="Blitzcrank.png"  title="Blitzcrank" alt="Blitzcrank"/></td>
    <td>22.82%</td>
    <td>Support</td>
    <td>3/5</td>
  </tr>
    <tr>
    <td><img src="Elise.png"  title="Elise" alt="Elise"/></td>
    <td>22.62%</td>
    <td>Jungle</td>
    <td>4/5</td>
  </tr>
    <tr>
    <td><img src="Ahri.png"  title="Ahri" alt="Ahri"/></td>
    <td>17.15%</td>
    <td>Middle</td>
    <td>5/5</td>
  </tr>
    <tr>
    <td><img src="Orianna.png"  title="Orianna" alt="Orianna"/></td>
    <td>16.50%</td>
    <td>Middle</td>
    <td>3/5</td>
  </tr>
    <tr>
    <td><img src="Fiora.png"  title="Fiora" alt="Fiora"/></td>
    <td>16.18%</td>
    <td>Top</td>
    <td>4/5</td>
  </tr>
    <tr>
    <td><img src="Graves.png"  title="Graves" alt="Graves"/></td>
    <td>15.98%</td>
    <td>Jungle</td>
    <td>2/5</td>
  </tr>
</table>
</aside>

    <div class="row">
        <div class="col">To become a good League of Legends player, there is a great learning curve. During this curve, the player is expected to master each of the key features of the game, in order to dominate their opposition. During the course of this guide, My aim will be to both educate you and to attempt to provide you with an understanding of the many key gameplay aspects that the game posseses.
        <hr>
        <center><u>An Ever Changing Meta</u></center>
        Riot Games (League of Legend's developers) frequently update the game, sometimes as often as every two weeks. This brings new content constantly, with almost constant changes to various champions.
        <br>
        <center><img src="Malhazar.jpg" alt="Malhazar" height="300" width="630" border="5" title="Malhazar"></center>
        Levels 1 to 30 are fairly straight forward, allowing the player to become experienced at the game. After the player reaches level 30, they can play ranked. Ranked is a much harder version of the game, where people will be trying their hardest, in order to try and attain a high rank. The ranks are shown below.

        <div class="slider">
            <figure>
            <div class="slide">
                <p>Bronze</p>
            <img src="bronze.png" alt="Bronze">
            </div>
            <div class="slide">
                <p>Silver</p>
            <img src="silver.png" alt="Silver">
            </div>
            <div class="slide">
                <p>Gold</p>
            <img src="gold.jpg" alt="Gold">
            </div>
            <div class="slide">
                <p>Platinum</p>
            <img src="platinum.jpg" alt="Platinum">
            </div>
            <div class="slide">
                <p>Diamond</p>
            <img src="diamond.png" alt="Diamond">
            </div>
            <div class="slide">
                <p>Challenger</p>
            <img src="challenger.jpg">
            </div>
            </figure>
        </div>
        <br>
        Using an account that is already level 30, when first starting the game is generally discouraged. This is because the game will match you against <u>Any</u> level 30 players. This means anything from Bronze players, through to Diamond. With over 100 champions, its safe to say that with the broad range of champions available, any one of them can be effective when played right. This makes it a simple case of finding your main.
        <hr>
        <center><u>Free Rotation</u></center>
        Every week, there are 10 champions on free rotation. During this time, anyone can pick them and play as them. The 10 champions usually range in both champion type and popularity. As the 10 champions change every week, this gives users a chance to play a wide range of champions, and may influence their decision as to whether they want to purchase it.
        <br>
        <center><img src="freerotation.jpg" alt="Malhazar" height="300" width="630" border="5" title="Current Free rotation"></center>
        <u>This Week's free rotation is as follows:</u>
        <ol>
           <li> Ashe. -<i>The Frost Archer.</i> </li>
            <li> Vel'Koz. -<i>The Eye Of The Void.</i></li>
            <li> Yorick. -<i>The shepherd Of Souls.</i> </li>
            <li> Azir. -<i>The Emperor Of The Sands.</i></li>
            <li> Rammus. -<i>The Armordillo.</i></li>
            <li> Caitlyn. -<i>The Sheriff Of Piltover.</i></li>
            <li> Fiddlesticks. -<i>The Harbinger Of Doom.</i></li>
            <li> Ekko. -<i>The Boy Who Shattered Time.</i> </li>
            <li> Karma. -<i>The Enlightened One.</i> </li>
            <li> Kennen. -<i>The Heart Of The Tempest.</i></li>
        </ol>

    </div>
    </div>
    <footer class="Footer">
    <table>
        <th>Contact Us</th>
        <th>Home</th>
        <th>Champions</th>
        <th>Gameplay</th>

    </table>
    </footer>
</body>

</html>
</code>```

`

CSS
`

```<code>body {
    margin: 0;
    background-image: url("backgroundimage.png");
    padding-bottom: 20px;
}
header {
     background: linear-gradient(#2e2e30, #cbcbd6);
    color: black;
    padding: 15px 15px 0 10px;
}
header h1{
    margin: 0;
    display: inline;
    padding: 0 0 0 15px;
    text-decoration: underline;
}
nav ul{
    margin: 0;
    display: inline;
    padding: 0 0 0 15px;
}
nav img {
    float: left;
    width: 80px;
    height: 50px;
    position: relative;
    top: -13px;
}
nav ul li {
    list-style-type: none;
    display: inline-block;
    background: #333;
    color: white;
    padding: 5px 15px;
}

nav ul li a {
    color: white;
}
nav ul li a:hover{
    padding: 5px 15px;
}

.row:after {
    clear: both;
    content: **;
    display: table;
}

.col {
    float: left;
    background: #333;
    width: 60%;
    margin: .5%;
    border-radius: 5px;
    padding: .5%;
    color: white;
    position: relative;
    top: -16px;
}

footer {
    clear: both;
}

aside {
    float: right;
    background: #333;
    width: 30%;
    margin: .5%;
    border-radius: 5px;
    padding: .5%;
    color: white;
    position: relative;
    left: -50px;
}
center u {
    font-size: 25px;
}

aside a {
color: white;
}

.slider .slide p {
    font-size: 20px;
    text-align: left;
    position: relative;
    width: 20%;
    padding-top 10px;
    right: -130px;

}

.slider {
    overflow: hidden;
    height: 300px;
}

.slider figure div {
    width: 20%;
    float: left;
}
.slider figure img{
    width: 300px;
    float: left;
}

.slider figure{
    position: relative;
    width: 500%;
    margin: 0;
    left: 20px;
    animation: 30s slidy infinite;

}

@keyframes slidy{
    0% {
        left: 0%;
    }

    10% {
        left: 0%;
    }

    12%{
        left: -100%;
    }

    22% {
        left: -100%;
    }

    24% {
        left: -200%;
    }

    34% {
        left: -200%;
    }

    36% {
        left: -300%;
    }

    46% {
        left: -300%;
    }

    48% {
        left: -400%;
    }

    58% {
        left: -400%;
    }

    60% {
        left: -300%;
    }

    70% {
        left: -300%;
    }

    72% {
        left: -200%;
    }

    82% {
        left: -200%;
    }

    84% {
        left: -100%;
    }

    94% {
        left: -100%;
    }

    96% {
        left: 0%;
    }

    100% {
        left: 0%;
    }

}

.slider {
    position:;
    right: -250px;
    top: -10px;
    height: 370px;
    float: left;
}

.second {
    position: relative;
    left: 381.5px;
    top: 160px;
}

.row {
    position: absolute;
    top: 62px
}

aside table{
    text-align: center;
}
#footer {
    overflow: hidden;
}

aside table img{
    display:block;
}

footer {
    float: left;
    background: #333;
    width: 100%;
    height: 50px;
    margin: .5;
    border-radius: 5px;
    padding: .5%;
    color: white;
    position: relative;
    top: 350px;
}

aside tr:hover  {
    background-color: black;
    color: white;
}
</code>```

`

答: your .row DIV has position: absolute and is covering the first aside element completely, that's why the mouse-pointer doesn't change and no clicks can get through to the links. Either change that àbsolute` or move the aside further to the right to fix that.

Title: table elements not detecting :hover

Body:
so I have a small problem with my code. In my  element, I have a table. I have added titles to each of the images in the table, however they simply aren't displaying upon mousing over the image. I also have something in my css, that changes the colour of the table row and text, upon hovering over it. This also is not working. I have pasted the relevant code below, any help is appreciated. :D

HTML
`

    Popular Champions

    Champion
    Playrate (%)
    Lane
    Difficulty

    42.75%
    Support
    2/5

    38.14%
    Jungle
    4/5

    34.79%
    ADC
    1/5

    25.14%
    ADC
    1/5

    22.82%
    Support
    3/5

    22.62%
    Jungle
    4/5

    17.15%
    Middle
    5/5

    16.50%
    Middle
    3/5

    16.18%
    Top
    4/5

    15.98%
    Jungle
    2/5

`

CSS

`

aside tr:hover {
    background-color: white;
    color: black;
}

`

EDIT
Turns out Hyperlinks positioned above (in a separate  element are also not registering any form of mouse input (unclickable links) I have pasted my entire code below:

HTML
`

<!doctype html>

    <title>LoL Guide: Home</title>
    <link rel="stylesheet" href="style.css" type="text/css">

League Of Legends Beginner's Guide

Home

Champions

Gameplay

         Useful Links

Official League of Legends website.

Official League of Legends Wiki

Official League of Legends Reddit

    Popular Champions

    Champion
    Playrate (%)
    Lane
    Difficulty

    42.75%
    Support
    2/5

    38.14%
    Jungle
    4/5

    34.79%
    ADC
    1/5

    25.14%
    ADC
    1/5

    22.82%
    Support
    3/5

    22.62%
    Jungle
    4/5

    17.15%
    Middle
    5/5

    16.50%
    Middle
    3/5

    16.18%
    Top
    4/5

    15.98%
    Jungle
    2/5

To become a good League of Legends player, there is a great learning curve. During this curve, the player is expected to master each of the key features of the game, in order to dominate their opposition. During the course of this guide, My aim will be to both educate you and to attempt to provide you with an understanding of the many key gameplay aspects that the game posseses.

        An Ever Changing Meta
        Riot Games (League of Legend's developers) frequently update the game, sometimes as often as every two weeks. This brings new content constantly, with almost constant changes to various champions.

        Levels 1 to 30 are fairly straight forward, allowing the player to become experienced at the game. After the player reaches level 30, they can play ranked. Ranked is a much harder version of the game, where people will be trying their hardest, in order to try and attain a high rank. The ranks are shown below.

Bronze

Silver

Gold

Platinum

Diamond

Challenger

        Using an account that is already level 30, when first starting the game is generally discouraged. This is because the game will match you against Any level 30 players. This means anything from Bronze players, through to Diamond. With over 100 champions, its safe to say that with the broad range of champions available, any one of them can be effective when played right. This makes it a simple case of finding your main.

        Free Rotation
        Every week, there are 10 champions on free rotation. During this time, anyone can pick them and play as them. The 10 champions usually range in both champion type and popularity. As the 10 champions change every week, this gives users a chance to play a wide range of champions, and may influence their decision as to whether they want to purchase it.

        This Week's free rotation is as follows:

 Ashe. -The Frost Archer.

 Vel'Koz. -The Eye Of The Void.

 Yorick. -The shepherd Of Souls.

 Azir. -The Emperor Of The Sands.

 Rammus. -The Armordillo.

 Caitlyn. -The Sheriff Of Piltover.

 Fiddlesticks. -The Harbinger Of Doom.

 Ekko. -The Boy Who Shattered Time.

 Karma. -The Enlightened One.

 Kennen. -The Heart Of The Tempest.

        Contact Us
        Home
        Champions
        Gameplay

`

CSS
`

body {
    margin: 0;
    background-image: url("backgroundimage.png");
    padding-bottom: 20px;
}
header {
     background: linear-gradient(#2e2e30, #cbcbd6);
    color: black;
    padding: 15px 15px 0 10px;
}
header h1{
    margin: 0;
    display: inline;
    padding: 0 0 0 15px;
    text-decoration: underline;
}
nav ul{
    margin: 0;
    display: inline;
    padding: 0 0 0 15px;
}
nav img {
    float: left;
    width: 80px;
    height: 50px;
    position: relative;
    top: -13px;
}
nav ul li {
    list-style-type: none;
    display: inline-block;
    background: #333;
    color: white;
    padding: 5px 15px;
}

nav ul li a {
    color: white;
}
nav ul li a:hover{
    padding: 5px 15px;
}

.row:after {
    clear: both;
    content: **;
    display: table;
}

.col {
    float: left;
    background: #333;
    width: 60%;
    margin: .5%;
    border-radius: 5px;
    padding: .5%;
    color: white;
    position: relative;
    top: -16px;
}

footer {
    clear: both;
}

aside {
    float: right;
    background: #333;
    width: 30%;
    margin: .5%;
    border-radius: 5px;
    padding: .5%;
    color: white;
    position: relative;
    left: -50px;
}
center u {
    font-size: 25px;
}

aside a {
color: white;
}

.slider .slide p {
    font-size: 20px;
    text-align: left;
    position: relative;
    width: 20%;
    padding-top 10px;
    right: -130px;

}

.slider {
    overflow: hidden;
    height: 300px;
}

.slider figure div {
    width: 20%;
    float: left;
}
.slider figure img{
    width: 300px;
    float: left;
}

.slider figure{
    position: relative;
    width: 500%;
    margin: 0;
    left: 20px;
    animation: 30s slidy infinite;

}

@keyframes slidy{
    0% {
        left: 0%;
    }

    10% {
        left: 0%;
    }

    12%{
        left: -100%;
    }

    22% {
        left: -100%;
    }

    24% {
        left: -200%;
    }

    34% {
        left: -200%;
    }

    36% {
        left: -300%;
    }

    46% {
        left: -300%;
    }

    48% {
        left: -400%;
    }

    58% {
        left: -400%;
    }

    60% {
        left: -300%;
    }

    70% {
        left: -300%;
    }

    72% {
        left: -200%;
    }

    82% {
        left: -200%;
    }

    84% {
        left: -100%;
    }

    94% {
        left: -100%;
    }

    96% {
        left: 0%;
    }

    100% {
        left: 0%;
    }

}

.slider {
    position:;
    right: -250px;
    top: -10px;
    height: 370px;
    float: left;
}

.second {
    position: relative;
    left: 381.5px;
    top: 160px;
}

.row {
    position: absolute;
    top: 62px
}

aside table{
    text-align: center;
}
#footer {
    overflow: hidden;
}

aside table img{
    display:block;
}

footer {
    float: left;
    background: #333;
    width: 100%;
    height: 50px;
    margin: .5;
    border-radius: 5px;
    padding: .5%;
    color: white;
    position: relative;
    top: 350px;
}

aside tr:hover  {
    background-color: black;
    color: white;
}

`


问:
How attach a sequence of numbers to a string using `paste0` in R?
I'm trying to a create labels for dotchart() below. Specifically, I'm trying to create Yes_1 to Yes_5 under group 1 in groups below, and create No_1 to No_15 under group 2 in groups below (see picture below).

Here is the R code I have tried with no success:(problem is in paste0())

```<code>y = rnorm(20)
groups = factor( rep(1:2, times = c(5, 15) ) )
dotchart(y, groups = groups, labels = c(paste0("Yes_",1:5), paste0("No_", 1:15))[groups])
</code>```

答:
Just drop the [group] at the end. And reverse the order of the ranges if you want them like this.

y = rnorm(20)
groups = factor( rep(1:2, times = c(5, 15) ) )
dotchart(y, groups = groups, labels = c(paste0("Yes_",5:1), paste0("No_", 15:1)))
```

Body:
I'm trying to a create labels for dotchart() below. Specifically, I'm trying to create Yes_1 to Yes_5 under group 1 in groups below, and create No_1 to No_15 under group 2 in groups below (see picture below).

Here is the R code I have tried with no success:(problem is in paste0())

y = rnorm(20)
groups = factor( rep(1:2, times = c(5, 15) ) )
dotchart(y, groups = groups, labels = c(paste0("Yes_",1:5), paste0("No_", 1:15))[groups])


问:
How do I get text to align to around a picture on a website
I'm working on a personal website highlighting my certifications on a personal website. Part of the ToS to use the images is to place a TM in the upper right corner of each image. I'm having trouble getting the text to align where it needs to be.

This is what I have:

HTML

```<code><div id="imagesMain">
        <img src="aplus.png"> TM
        <img src="network.png"> TM
        <img src="security.png"> TM
    </div>
</code>```

CSS

```<code>#imagesMain {
 padding: 0;
    margin-left: auto;
    margin-right: auto;
    margin-top: 20px;
    text-align: center;
}

#imagesMain img {
    height: 100px;
     width: auto;
    vertical-align: middle;
}
</code>```

The end result gives this...

What I'd like is all images in a tight line and a small "TM" in the proper place. Any help would be appreciated.

答:
Wrap your images with a span and then use a pseudo to add the TM in upper right corner

#imagesMain {
  padding: 0;
  margin-left: auto;
  margin-right: auto;
  margin-top: 20px;
  text-align: center;
}
#imagesMain span {
  position: relative;
  display: inline-block;
}
#imagesMain span::after {
  content: 'TM';
  position: absolute;
  top: -4px;
  right: -4px;
}
#imagesMain img {
  height: 100px;
  width: auto;
  vertical-align: middle;
  border-radius: 50%;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div id="imagesMain">
  <span><img src="http://placehold.it/100/f00"></span>
  <span><img src="http://placehold.it/100/f00"></span>
  <span><img src="http://placehold.it/100/f00"></span>
</div></code>```

Body:
I'm working on a personal website highlighting my certifications on a personal website. Part of the ToS to use the images is to place a TM in the upper right corner of each image. I'm having trouble getting the text to align where it needs to be.

This is what I have:

HTML

         TM
         TM
         TM

CSS

#imagesMain {
 padding: 0;
    margin-left: auto;
    margin-right: auto;
    margin-top: 20px;
    text-align: center;
}

#imagesMain img {
    height: 100px;
     width: auto;
    vertical-align: middle;
}

The end result gives this...

What I'd like is all images in a tight line and a small "TM" in the proper place. Any help would be appreciated.

Body:
Wrap your images with a span and then use a pseudo to add the TM in upper right corner

#imagesMain {
  padding: 0;
  margin-left: auto;
  margin-right: auto;
  margin-top: 20px;
  text-align: center;
}
#imagesMain span {
  position: relative;
  display: inline-block;
}
#imagesMain span::after {
  content: 'TM';
  position: absolute;
  top: -4px;
  right: -4px;
}
#imagesMain img {
  height: 100px;
  width: auto;
  vertical-align: middle;
  border-radius: 50%;
}

<div id="imagesMain">
  <span><img src="http://placehold.it/100/f00"></span>
  <span><img src="http://placehold.it/100/f00"></span>
  <span><img src="http://placehold.it/100/f00"></span>
</div>


答:
```<code>y = rnorm(20)
groups = factor( rep(1:2, times = c(5, 15) ) )
dotchart(y, groups = groups, labels = c(paste0("Yes_",5:1), paste0("No_", 15:1)))
</code>```

If we remove the [groups] index at line 3, and reverse the ranges, then we obtain:

Title: How attach a sequence of numbers to a string using `paste0` in R?

Body:
y = rnorm(20)
groups = factor( rep(1:2, times = c(5, 15) ) )
dotchart(y, groups = groups, labels = c(paste0("Yes_",5:1), paste0("No_", 15:1)))

If we remove the [groups] index at line 3, and reverse the ranges, then we obtain:


问:
Cassandra QUORUM write consistency level and multiple DC
I'm a bit confused about how QUORUM write selects nodes to write into in case of multiple DC.

Suppose, for example, that I have a 3 DC cluster with 3 nodes in each DC, and the replications factor is 2, so that the number of replicas needed to achieve QUORUM is 3. Note: this is just an example to help me formulate my question and not the actual configuration.

My question is the following: in case of write, how these 3 replicas will be distributed across all the DCs in my cluster? Is it possible that all 3 replicas will end up in the same DC?

答:
The replication is defined at the key space level. So for example

```<code>create keyspace test with replication = { 'class' : 'NetworkTopologyStrategy', 'DC1' : 2, 'DC2' : 2, 'DC3' : 2 };
</code>```

As you can see clearly each DC will hold two copies of data for that keyspace and not more. You could have another key space in the same cluster defined only to replicate in one DC and not the other two. So its flexible.

Now for consistency, with 3 DCs and RF=2 in each DC, you have 6 copies of data. By definition of Quorum a majority (which is RF/2 + 1) of those 6 members needs to acknowledge the write, before claiming that the write was successful. So 4 nodes needs to respond for a quorum write here and these 4 members could be a combination of nodes from any DC. Remember the number of replicas matter to calculate quorum and not the total no. of nodes in DC.

On a side note, in Cassandra, RF=2 is as good as RF=1. To simplify, lets imagine a 3 node single DC situation. With RF=2 there are two copies of data and in order to achieve quorum ((RF=2)/2 + 1), 2 nodes needs to acknowledge the write.  So both the nodes always have to be available. Even if one node fails the writes will start to fail. Event another node can take hints here, but your reads with quorum are bound to fail. So fault tolerance of node failure is equal to zero in this situation.

You could use local_quorum to speed up the writes instead of quorum. Its sacrifice of consistency over speed. Welcome to "eventually consistency".

Body:
The replication is defined at the key space level. So for example

create keyspace test with replication = { 'class' : 'NetworkTopologyStrategy', 'DC1' : 2, 'DC2' : 2, 'DC3' : 2 };

As you can see clearly each DC will hold two copies of data for that keyspace and not more. You could have another key space in the same cluster defined only to replicate in one DC and not the other two. So its flexible.

Now for consistency, with 3 DCs and RF=2 in each DC, you have 6 copies of data. By definition of Quorum a majority (which is RF/2 + 1) of those 6 members needs to acknowledge the write, before claiming that the write was successful. So 4 nodes needs to respond for a quorum write here and these 4 members could be a combination of nodes from any DC. Remember the number of replicas matter to calculate quorum and not the total no. of nodes in DC.

On a side note, in Cassandra, RF=2 is as good as RF=1. To simplify, lets imagine a 3 node single DC situation. With RF=2 there are two copies of data and in order to achieve quorum ((RF=2)/2 + 1), 2 nodes needs to acknowledge the write.  So both the nodes always have to be available. Even if one node fails the writes will start to fail. Event another node can take hints here, but your reads with quorum are bound to fail. So fault tolerance of node failure is equal to zero in this situation.

You could use local_quorum to speed up the writes instead of quorum. Its sacrifice of consistency over speed. Welcome to "eventually consistency".


问:
ModelForms & DRY placeholders
So I wanted a DRY way to specify the placeholders for my form fields. So whipped up this Mixin:

```<code>class FormPlaceholderMixin(object):
    def __init__(self, *args, **kwargs):
        super(FormPlaceholderMixin, self).__init__(*args,**kwargs)
        for index, placeholder in self.PLACEHOLDERS.iteritems():
            self.fields[index].widget.attrs['placeholder'] = placeholder
</code>```

This works great as it allows me to do this:

```<code>class PostcardOrderForm(FormPlaceholderMixin, forms.ModelForm):

    PLACEHOLDERS = {
        'name': 'Order Name',
        'order_contacts': 'Send it only to contacts in this group...',
    }

    class Meta:
        model = PostcardOrder
        fields = ['name', 'order_contacts']
</code>```

Although this is kinda ugly. I would rather do this:

```<code>    class Meta:
        # ...
        placeholders = {
            'name': 'Order Name',
            'order_contacts': 'Send it only to contacts in this group...',
        }
</code>```

But when I inspect self._meta, the placeholders dict is no where to be found. Why is this and I can I make that work?

答:
Variables are copied in the _meta attribute at the metaclass level. Only a particuliar list of meta options are copied. If you want to add to the self._meta you will need to subclass the ModelBase metaclass and use your own.

Possible meta options
https://docs.djangoproject.com/en/1.11/ref/models/options/

ModelBase metaclass
https://github.com/django/django/blob/master/django/db/models/base.py

Title: ModelForms & DRY placeholders

Body:
So I wanted a DRY way to specify the placeholders for my form fields. So whipped up this Mixin:

class FormPlaceholderMixin(object):
    def __init__(self, *args, **kwargs):
        super(FormPlaceholderMixin, self).__init__(*args,**kwargs)
        for index, placeholder in self.PLACEHOLDERS.iteritems():
            self.fields[index].widget.attrs['placeholder'] = placeholder

This works great as it allows me to do this:

class PostcardOrderForm(FormPlaceholderMixin, forms.ModelForm):

    PLACEHOLDERS = {
        'name': 'Order Name',
        'order_contacts': 'Send it only to contacts in this group...',
    }

    class Meta:
        model = PostcardOrder
        fields = ['name', 'order_contacts']

Although this is kinda ugly. I would rather do this:

    class Meta:
        # ...
        placeholders = {
            'name': 'Order Name',
            'order_contacts': 'Send it only to contacts in this group...',
        }

But when I inspect self._meta, the placeholders dict is no where to be found. Why is this and I can I make that work?


问:
Service Stack Razor View Not Found
I added the RazorPlugin along with a Test.cshtml in the root View folder (tried wwwroot as well along with TestGet.cshtml).  This is an donet Core project.  Whenever browsing to:  /api/test the following error is generated:

Snapshot of TestGet generated by ServiceStack on 6/3/2017 4:20:40 PM
  view json datasource from original url:
  http://localhost:51550/api/test? in other formats: json xml csv jsv
  Response Status Error CodeNullReferenceExceptionMessageObject
  reference not set to an instance of an object.Stack Trace[TestGet:
  6/3/2017 4:20:40 PM]: [REQUEST: {}] System.NullReferenceException:
  Object reference not set to an instance of an object. at
  ServiceStack.Mvc.RazorFormat.FindView(IEnumerable1 viewNames) in
  /opt/lib/teamcity-agent/work/d09206570215629/src/ServiceStack.Mvc/RazorFormat.cs:line
  174 at ServiceStack.Mvc.RazorFormat.ProcessRequest(IRequest req,
  IResponse res, Object dto) in
  /opt/lib/teamcity-agent/work/d09206570215629/src/ServiceStack.Mvc/RazorFormat.cs:line
  138 at System.Linq.Enumerable.Any[TSource](IEnumerable1 source,
  Func`2 predicate) at
  ServiceStack.Formats.HtmlFormat.SerializeToStream(IRequest req, Object
  response, IResponse res) in
  /opt/lib/teamcity-agent/work/d09206570215629/src/ServiceStack/Formats/HtmlFormat.cs:line
  63Errors

The other formats work (json/etc).

```<code> public class Test
 {
     public string ExternalId { get; set; }
 }

  [Authenticate, Route("/test")]
  public class TestGet : IGet, IReturn<Test>
  {
  }

 public class TestService : Service
    {
        public IAutoQueryDb _autoQueryDb { get; set; }
        public IDbConnectionFactory _dbFactory { get; set; }

        public TestService(IDbConnectionFactory dbFactory)
        {
            _dbFactory = dbFactory;
        }

        public Test Get(TestGet request)
        {
            var test = new Test();
            test.ExternalId = "abc";
            return test;
        }

    }
</code>```

Test.cshtml

```<code>@using App.Shared.DomainModel
@model Test

<div>Test</div>
</code>```

AppHost.cs

```<code>using App.DomainServices;
using App.FontEnd.Infrastructure.Configuration;
using App.FontEnd.Infrastructure.Core;
using App.Shared.DomainModel;
using Funq;
using LightInject;
using ServiceStack;
using ServiceStack.Admin;
using ServiceStack.Api.Swagger;
using ServiceStack.Auth;
using ServiceStack.Caching;
using ServiceStack.Configuration;
using ServiceStack.Data;
using ServiceStack.Mvc;
using ServiceStack.OrmLite;
using ServiceStack.Validation;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace App.FrontEnd
{
    public class AppHost : AppHostBase
    {
        /// <summary>
        /// Base constructor requires a Name and Assembly where web service implementation is located
        /// </summary>
        public AppHost()
            : base("TestApi", typeof(CompanyService).GetAssembly())
        {

        }

        /// <summary>
        /// Application specific configuration
        /// This method should initialize any IoC resources utilized by your web service classes.
        /// </summary>
        public override void Configure(Container container)
        {

            this.GlobalRequestFilters.Add((httpReq, httpResp, requestDto) =>
            {
                var currentSession = httpReq.GetSession();
                if (currentSession != null)
                {
                    RequestContext.Instance.Items.Add("CurrentUserName", currentSession.UserName);
                    RequestContext.Instance.Items.Add("CurrentUserId", currentSession.UserAuthId);
                }
            });

            ServiceContainer LightContainer = new ServiceContainer();

            LightContainer.RegisterInstance<IDbConnectionFactory>
            (
                new OrmLiteConnectionFactory(
                    "removed",
                    SqlServer2014Dialect.Provider
                )
            );

            LightContainer.Register<IDbConnection>(c =>
                c.GetInstance<IDbConnectionFactory>().OpenDbConnection(),
                new PerScopeLifetime()
            );

            LightContainer.Register<OrmLiteAppSettings>(c =>
                new OrmLiteAppSettings(c.GetInstance<IDbConnectionFactory>()));
            LightContainer.Register<ServiceStack.Web.IServiceGatewayFactory>(x => new ApiServiceGatewayFactory());
            container.Adapter = new LightInjectAdapter(LightContainer);

            var settings = LightContainer.GetInstance<OrmLiteAppSettings>();
            settings.InitSchema();
            AppSettings = new MultiAppSettings(
                settings
            );

            container.Register<ICacheClient>(new OrmLiteCacheClient
            {
                DbFactory = LightContainer.GetInstance<IDbConnectionFactory>()
            });
            var cacheclient = container.Resolve<ICacheClient>();
            cacheclient.InitSchema();

            AuthConfig(container, AppSettings);

            Plugins.Add(new RegistrationFeature());
            Plugins.Add(new SwaggerFeature());
            Plugins.Add(new RequestLogsFeature());
            Plugins.Add(new PostmanFeature());
            Plugins.Add(new CorsFeature(allowCredentials: true));
            Plugins.Add(new ValidationFeature());

            Plugins.Add(new RazorFormat());

            OrmLiteConfig.InsertFilter = (dbCmd, row) =>
            {
                var auditRow = row as CoreModel;
                if (auditRow != null)
                {
                    var currentDate = DateTime.UtcNow;
                    var insertUserId = RequestContext.Instance.Items["CurrentUserId"] as string;

                    auditRow.Id = Guid.NewGuid();
                    auditRow.CreatedDate = currentDate;
                    auditRow.CreatedBy = insertUserId;
                    auditRow.UpdatedDate = currentDate;
                    auditRow.UpdatedBy = insertUserId;
                }
            };

            OrmLiteConfig.UpdateFilter = (dbCmd, row) =>
            {
                var auditRow = row as CoreModel;

                if (auditRow != null)
                {
                    var updateUserId = RequestContext.Instance.Items["CurrentUserId"] as string;
                    auditRow.UpdatedDate = DateTime.UtcNow;
                    auditRow.UpdatedBy = updateUserId;
                }
            };

            var aq = new AutoQueryFeature { MaxLimit = 100, EnableAutoQueryViewer = true };
            aq.ImplicitConventions.Add("%neq", aq.ImplicitConventions["%NotEqualTo"]);
            aq.ImplicitConventions.Add("%eq", "{Field} = {Value}");
            Plugins.Add(aq);
            Plugins.Add(new AdminFeature());

            SetConfig(new HostConfig
            {
                HandlerFactoryPath = "api",
                DebugMode = true
            });

            container.CheckAdapterFirst = true;

            //Set up service stack validators
            container.ValidatorsSetup();
        }

        public void AuthConfig(Container container, IAppSettings settings)
        {
            Plugins.Add(new AuthFeature(() => new AuthUserSession(),
                new IAuthProvider[] {
                    new CredentialsAuthProvider(AppSettings),
                    new JwtAuthProvider(AppSettings)
                    {
                        AuthKeyBase64 = "abcdefgh"
                    },

                    new BasicAuthProvider()
            }));

            var authRepo = CreateOrmLiteAuthRepo(container, settings);

        }

        private static IUserAuthRepository CreateOrmLiteAuthRepo(Container container, IAppSettings appSettings)
        {
            //Store User Data into the referenced SqlServer database
            container.Register<IAuthRepository>(c =>
                new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));

            //Use OrmLite DB Connection to persist the UserAuth and AuthProvider info
            var authRepo = (OrmLiteAuthRepository)container.Resolve<IAuthRepository>();
            //If using and RDBMS to persist UserAuth, we must create required tables
            if (appSettings.Get("RecreateAuthTables", false))
                authRepo.DropAndReCreateTables(); //Drop and re-create all Auth and registration tables
            else
                authRepo.InitSchema(); //Create only the missing tables

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

答:
I've created a minimal verifiable MVC test project to simulate your configuration which is working as expected at: https://github.com/NetCoreApps/scratch/tree/master/src/RazorApi

It includes the same Test Services, (sans [Authenticate] attribute):

```<code>public class Test
{
    public string ExternalId { get; set; }
}

[Route("/test")]
public class TestGet : IGet, IReturn<Test>
{
}

public class TestService : Service
{
    public Test Get(TestGet request)
    {
        var test = new Test { ExternalId = "abc" };
        return test;
    }
}
</code>```

And the minimal AppHost configuration which just sets the HandlerFactoryPath to api and registers ServiceStack's RazorFormat plugin:

```<code>public class AppHost : AppHostBase
{
    public AppHost()
        : base("ServiceStack + .NET Core", typeof(MyServices).GetTypeInfo().Assembly) {}

    public override void Configure(Funq.Container container)
    {
        SetConfig(new HostConfig
        {
            HandlerFactoryPath = "api",
            DebugMode = true,
        });

        Plugins.Add(new RazorFormat());
    }
}
</code>```

With the Test.cshtml maintained in /Views/Test.cshtml:

```<code>@model Test
@{
    Layout = "_Layout";
}

<h1>Test.cshtml</h1>

<p>@Model.ExternalId</p>
</code>```

Which works as expected with the Razor View executed when calling:

```<code>http://localhost:5000/api/test
</code>```

Which also works when renamed to match the Request DTO at TestGet.cshtml.

As the issue seems specific to your project I'd compare your layout with bare RazorApi Github Project to see if you can find any differences, failing that I'd recommend commenting out configuration to get it to a working state then uncomment sections at a time to find out which configuration is causing the issue.

Title: Service Stack Razor View Not Found

Body:
I added the RazorPlugin along with a Test.cshtml in the root View folder (tried wwwroot as well along with TestGet.cshtml).  This is an donet Core project.  Whenever browsing to:  /api/test the following error is generated:

Snapshot of TestGet generated by ServiceStack on 6/3/2017 4:20:40 PM
  view json datasource from original url:
  http://localhost:51550/api/test? in other formats: json xml csv jsv
  Response Status Error CodeNullReferenceExceptionMessageObject
  reference not set to an instance of an object.Stack Trace[TestGet:
  6/3/2017 4:20:40 PM]: [REQUEST: {}] System.NullReferenceException:
  Object reference not set to an instance of an object. at
  ServiceStack.Mvc.RazorFormat.FindView(IEnumerable1 viewNames) in
  /opt/lib/teamcity-agent/work/d09206570215629/src/ServiceStack.Mvc/RazorFormat.cs:line
  174 at ServiceStack.Mvc.RazorFormat.ProcessRequest(IRequest req,
  IResponse res, Object dto) in
  /opt/lib/teamcity-agent/work/d09206570215629/src/ServiceStack.Mvc/RazorFormat.cs:line
  138 at System.Linq.Enumerable.Any[TSource](IEnumerable1 source,
  Func`2 predicate) at
  ServiceStack.Formats.HtmlFormat.SerializeToStream(IRequest req, Object
  response, IResponse res) in
  /opt/lib/teamcity-agent/work/d09206570215629/src/ServiceStack/Formats/HtmlFormat.cs:line
  63Errors

The other formats work (json/etc).

 public class Test
 {
     public string ExternalId { get; set; }
 }

  [Authenticate, Route("/test")]
  public class TestGet : IGet, IReturn<Test>
  {
  }

 public class TestService : Service
    {
        public IAutoQueryDb _autoQueryDb { get; set; }
        public IDbConnectionFactory _dbFactory { get; set; }

        public TestService(IDbConnectionFactory dbFactory)
        {
            _dbFactory = dbFactory;
        }

        public Test Get(TestGet request)
        {
            var test = new Test();
            test.ExternalId = "abc";
            return test;
        }

    }

Test.cshtml

@using App.Shared.DomainModel
@model Test

Test

AppHost.cs

using App.DomainServices;
using App.FontEnd.Infrastructure.Configuration;
using App.FontEnd.Infrastructure.Core;
using App.Shared.DomainModel;
using Funq;
using LightInject;
using ServiceStack;
using ServiceStack.Admin;
using ServiceStack.Api.Swagger;
using ServiceStack.Auth;
using ServiceStack.Caching;
using ServiceStack.Configuration;
using ServiceStack.Data;
using ServiceStack.Mvc;
using ServiceStack.OrmLite;
using ServiceStack.Validation;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace App.FrontEnd
{
    public class AppHost : AppHostBase
    {
        ///
        /// Base constructor requires a Name and Assembly where web service implementation is located
        ///
        public AppHost()
            : base("TestApi", typeof(CompanyService).GetAssembly())
        {

        }

        ///
        /// Application specific configuration
        /// This method should initialize any IoC resources utilized by your web service classes.
        ///
        public override void Configure(Container container)
        {

            this.GlobalRequestFilters.Add((httpReq, httpResp, requestDto) =>
            {
                var currentSession = httpReq.GetSession();
                if (currentSession != null)
                {
                    RequestContext.Instance.Items.Add("CurrentUserName", currentSession.UserName);
                    RequestContext.Instance.Items.Add("CurrentUserId", currentSession.UserAuthId);
                }
            });

            ServiceContainer LightContainer = new ServiceContainer();

            LightContainer.RegisterInstance<IDbConnectionFactory>
            (
                new OrmLiteConnectionFactory(
                    "removed",
                    SqlServer2014Dialect.Provider
                )
            );

            LightContainer.Register<IDbConnection>(c =>
                c.GetInstance<IDbConnectionFactory>().OpenDbConnection(),
                new PerScopeLifetime()
            );

            LightContainer.Register<OrmLiteAppSettings>(c =>
                new OrmLiteAppSettings(c.GetInstance<IDbConnectionFactory>()));
            LightContainer.Register<ServiceStack.Web.IServiceGatewayFactory>(x => new ApiServiceGatewayFactory());
            container.Adapter = new LightInjectAdapter(LightContainer);

            var settings = LightContainer.GetInstance<OrmLiteAppSettings>();
            settings.InitSchema();
            AppSettings = new MultiAppSettings(
                settings
            );

            container.Register<ICacheClient>(new OrmLiteCacheClient
            {
                DbFactory = LightContainer.GetInstance<IDbConnectionFactory>()
            });
            var cacheclient = container.Resolve<ICacheClient>();
            cacheclient.InitSchema();

            AuthConfig(container, AppSettings);

            Plugins.Add(new RegistrationFeature());
            Plugins.Add(new SwaggerFeature());
            Plugins.Add(new RequestLogsFeature());
            Plugins.Add(new PostmanFeature());
            Plugins.Add(new CorsFeature(allowCredentials: true));
            Plugins.Add(new ValidationFeature());

            Plugins.Add(new RazorFormat());

            OrmLiteConfig.InsertFilter = (dbCmd, row) =>
            {
                var auditRow = row as CoreModel;
                if (auditRow != null)
                {
                    var currentDate = DateTime.UtcNow;
                    var insertUserId = RequestContext.Instance.Items["CurrentUserId"] as string;

                    auditRow.Id = Guid.NewGuid();
                    auditRow.CreatedDate = currentDate;
                    auditRow.CreatedBy = insertUserId;
                    auditRow.UpdatedDate = currentDate;
                    auditRow.UpdatedBy = insertUserId;
                }
            };

            OrmLiteConfig.UpdateFilter = (dbCmd, row) =>
            {
                var auditRow = row as CoreModel;

                if (auditRow != null)
                {
                    var updateUserId = RequestContext.Instance.Items["CurrentUserId"] as string;
                    auditRow.UpdatedDate = DateTime.UtcNow;
                    auditRow.UpdatedBy = updateUserId;
                }
            };

            var aq = new AutoQueryFeature { MaxLimit = 100, EnableAutoQueryViewer = true };
            aq.ImplicitConventions.Add("%neq", aq.ImplicitConventions["%NotEqualTo"]);
            aq.ImplicitConventions.Add("%eq", "{Field} = {Value}");
            Plugins.Add(aq);
            Plugins.Add(new AdminFeature());

            SetConfig(new HostConfig
            {
                HandlerFactoryPath = "api",
                DebugMode = true
            });

            container.CheckAdapterFirst = true;

            //Set up service stack validators
            container.ValidatorsSetup();
        }

        public void AuthConfig(Container container, IAppSettings settings)
        {
            Plugins.Add(new AuthFeature(() => new AuthUserSession(),
                new IAuthProvider[] {
                    new CredentialsAuthProvider(AppSettings),
                    new JwtAuthProvider(AppSettings)
                    {
                        AuthKeyBase64 = "abcdefgh"
                    },

                    new BasicAuthProvider()
            }));

            var authRepo = CreateOrmLiteAuthRepo(container, settings);

        }

        private static IUserAuthRepository CreateOrmLiteAuthRepo(Container container, IAppSettings appSettings)
        {
            //Store User Data into the referenced SqlServer database
            container.Register<IAuthRepository>(c =>
                new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));

            //Use OrmLite DB Connection to persist the UserAuth and AuthProvider info
            var authRepo = (OrmLiteAuthRepository)container.Resolve<IAuthRepository>();
            //If using and RDBMS to persist UserAuth, we must create required tables
            if (appSettings.Get("RecreateAuthTables", false))
                authRepo.DropAndReCreateTables(); //Drop and re-create all Auth and registration tables
            else
                authRepo.InitSchema(); //Create only the missing tables

            return authRepo;
        }
    }
}

Body:
I've created a minimal verifiable MVC test project to simulate your configuration which is working as expected at: https://github.com/NetCoreApps/scratch/tree/master/src/RazorApi

It includes the same Test Services, (sans [Authenticate] attribute):

public class Test
{
    public string ExternalId { get; set; }
}

[Route("/test")]
public class TestGet : IGet, IReturn<Test>
{
}

public class TestService : Service
{
    public Test Get(TestGet request)
    {
        var test = new Test { ExternalId = "abc" };
        return test;
    }
}

And the minimal AppHost configuration which just sets the HandlerFactoryPath to api and registers ServiceStack's RazorFormat plugin:

public class AppHost : AppHostBase
{
    public AppHost()
        : base("ServiceStack + .NET Core", typeof(MyServices).GetTypeInfo().Assembly) {}

    public override void Configure(Funq.Container container)
    {
        SetConfig(new HostConfig
        {
            HandlerFactoryPath = "api",
            DebugMode = true,
        });

        Plugins.Add(new RazorFormat());
    }
}

With the Test.cshtml maintained in /Views/Test.cshtml:

@model Test
@{
    Layout = "_Layout";
}

<h1>Test.cshtml</h1>

<p>@Model.ExternalId</p>

Which works as expected with the Razor View executed when calling:

http://localhost:5000/api/test

Which also works when renamed to match the Request DTO at TestGet.cshtml.

As the issue seems specific to your project I'd compare your layout with bare RazorApi Github Project to see if you can find any differences, failing that I'd recommend commenting out configuration to get it to a working state then uncomment sections at a time to find out which configuration is causing the issue.


问:
Hello! How do I get the program to recognize the largest number with input+output dialog boxes with two integers? JAVA
I've been working on this for about two hours now and am now looking for help. My main issue is that I can't seem to put the largest number in to effect. I don't know what is wrong. Do I use the MIN/MAX that I've seen a few people use? Does that work with JOptionPane? Program is down below.</p>

```<code>import java.util.Scanner
public class Blah
{
  public static void main(String[] args)
  {
     Scanner input=new Scanner(System.in);

      double num1;
      double num2;
      String inputted_text;

     inputted_text=JOptionPane.showInputDialog("Enter first number: ");
     inputted_text=JOptionPane.showInputDialog("Enter second number:");

     num1=input.nextInt();
     num2=input.nextInt();

     if(num1>num2)
         JOptionPane.showMessageDialog(null, "The first number is bigger than the second number.");

         JOptionPane.showMessageDialog(null, "The second number is bigger than the first number.";
  }
}
</code>```

答:
It appears you are using both the swing and console for input. Try the following code to see if this is the desired behavior, you are looking for. You will want to add a try/catch to verify that the user types in a valid number.</p>

```<code>double num1;
double num2;
String inputted_text1;
String inputted_text2;

inputted_text1 = JOptionPane.showInputDialog("Enter first number: ");
num1 = Integer.parseInt(inputted_text1);
inputted_text2 = JOptionPane.showInputDialog("Enter second number:");
num2 = Integer.parseInt(inputted_text2);
if (num1 > num2) {
  JOptionPane.showMessageDialog(null, "The first number is bigger than the second number.");
} else {
  JOptionPane.showMessageDialog(null, "The second number is bigger than the first number.");
}
</code>```

Body:
I've been working on this for about two hours now and am now looking for help. My main issue is that I can't seem to put the largest number in to effect. I don't know what is wrong. Do I use the MIN/MAX that I've seen a few people use? Does that work with JOptionPane? Program is down below.

import java.util.Scanner
public class Blah
{
  public static void main(String[] args)
  {
     Scanner input=new Scanner(System.in);

      double num1;
      double num2;
      String inputted_text;

     inputted_text=JOptionPane.showInputDialog("Enter first number: ");
     inputted_text=JOptionPane.showInputDialog("Enter second number:");

     num1=input.nextInt();
     num2=input.nextInt();

     if(num1>num2)
         JOptionPane.showMessageDialog(null, "The first number is bigger than the second number.");

         JOptionPane.showMessageDialog(null, "The second number is bigger than the first number.";
  }
}

Body:
It appears you are using both the swing and console for input. Try the following code to see if this is the desired behavior, you are looking for. You will want to add a try/catch to verify that the user types in a valid number.

double num1;
double num2;
String inputted_text1;
String inputted_text2;

inputted_text1 = JOptionPane.showInputDialog("Enter first number: ");
num1 = Integer.parseInt(inputted_text1);
inputted_text2 = JOptionPane.showInputDialog("Enter second number:");
num2 = Integer.parseInt(inputted_text2);
if (num1 > num2) {
  JOptionPane.showMessageDialog(null, "The first number is bigger than the second number.");
} else {
  JOptionPane.showMessageDialog(null, "The second number is bigger than the first number.");
}


问:
Python select.select leaking threads
I have a program that maintains a connection to a server with a periodic heartbeat. Every once in a while, the server stops responding to heartbeats and I have to reconnect. I implemented this with a timer that, if no response is heard after n seconds, will call reconnect. Every time this happens, I leak a thread and over time I eventually run out of threads.

Now, simplifying massively for an easy repro, this illlustrates how reconnecting after a delay and how always causes an increase in threads. How can I kill the old threads/sockets/selects (which may be waiting on a recv)?

```<code>import socket
import select
import threading

class Connection():

    def tick(self):
        print(threading.active_count()) # this increases every 1s!
        # ... certain conditions not met / it's been too long, then:
        self.reconnect()

    def reconnect(self):
        self.socket.shutdown(socket.SHUT_WR)
        self.socket.close()
        self.timer.cancel()
        self.connect()

    def connect(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((IP, TCP_PORT))
        self.timer = threading.Timer(1, self.tick)
        self.timer.start()
        r,_,_ = select.select([self.socket], [], [])

if __name__ == '__main__':
    Connection().connect()
</code>```

答:
I'm pretty sure, it's not select() that leaks any threads. Let's assume the select() doesn't return, i.e it blocks forever.

In that case

.tick() is called from the timer thread.

.tick() calls .reconnect() within the timer thread.

.reconnect() closes the existing socket. This causes the active select() call to fail with IOError "Bad file descriptor" (which is also why you should really fix your code).

.reconnect() tries to cancel the current timer.
This does nothing, since the timer already triggered (we are currently inside the timer function!).

.reconnect() calls .connect() and that one establishes a new timer and here we go again.

So the question is: Where does this mode of operation hang on to the existing timer object? Well, all your timer threads get terminated by an IOError from the select() call. This stores a per-thread reference of the exception.

My guess is that this prevents the reference counted cleanup in CPython to trigger and hence the timer thread will only be cleaned up during garbage collection. This is unreliable, since there is no guarantee that the timer thread is ever cleaned up in time.

If you add import gc; gc.collect() at the start of .connect(), the problem (seems to) goes away. But yeah, that's a non-solution.

Why don't you use the timeout parameter to select() to achieve a similar result without having to use a timer thread?

```<code>r = []
while not r:
    if self.socket:
        self.socket.shutdown(socket.SHUT_WR)
        self.socket.close()

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.socket.connect((IP, TCP_PORT))
    # select returns empty lists on timeout
    r, _, _ = select.select([self.socket], [], [], 1)
</code>```

Don't forget to set self.socket = None in Connection.__init__() for this to work.

Title: Python select.select leaking threads

Body:
I have a program that maintains a connection to a server with a periodic heartbeat. Every once in a while, the server stops responding to heartbeats and I have to reconnect. I implemented this with a timer that, if no response is heard after n seconds, will call reconnect. Every time this happens, I leak a thread and over time I eventually run out of threads.

Now, simplifying massively for an easy repro, this illlustrates how reconnecting after a delay and how always causes an increase in threads. How can I kill the old threads/sockets/selects (which may be waiting on a recv)?

import socket
import select
import threading

class Connection():

    def tick(self):
        print(threading.active_count()) # this increases every 1s!
        # ... certain conditions not met / it's been too long, then:
        self.reconnect()

    def reconnect(self):
        self.socket.shutdown(socket.SHUT_WR)
        self.socket.close()
        self.timer.cancel()
        self.connect()

    def connect(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((IP, TCP_PORT))
        self.timer = threading.Timer(1, self.tick)
        self.timer.start()
        r,_,_ = select.select([self.socket], [], [])

if __name__ == '__main__':
    Connection().connect()

Body:
I'm pretty sure, it's not select() that leaks any threads. Let's assume the select() doesn't return, i.e it blocks forever.

In that case

.tick() is called from the timer thread.

.tick() calls .reconnect() within the timer thread.

.reconnect() closes the existing socket. This causes the active select() call to fail with IOError "Bad file descriptor" (which is also why you should really fix your code).

.reconnect() tries to cancel the current timer.
This does nothing, since the timer already triggered (we are currently inside the timer function!).

.reconnect() calls .connect() and that one establishes a new timer and here we go again.

So the question is: Where does this mode of operation hang on to the existing timer object? Well, all your timer threads get terminated by an IOError from the select() call. This stores a per-thread reference of the exception.

My guess is that this prevents the reference counted cleanup in CPython to trigger and hence the timer thread will only be cleaned up during garbage collection. This is unreliable, since there is no guarantee that the timer thread is ever cleaned up in time.

If you add import gc; gc.collect() at the start of .connect(), the problem (seems to) goes away. But yeah, that's a non-solution.

Why don't you use the timeout parameter to select() to achieve a similar result without having to use a timer thread?

r = []
while not r:
    if self.socket:
        self.socket.shutdown(socket.SHUT_WR)
        self.socket.close()

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.socket.connect((IP, TCP_PORT))
    # select returns empty lists on timeout
    r, _, _ = select.select([self.socket], [], [], 1)

Don't forget to set self.socket = None in Connection.__init__() for this to work.