问:
Print the cards that I used after I typed yes to play again
I want this game to start each hand with the cards left over from the previous hand.  Instead, it begins with a complete, newly-shuffled deck.  How can I fix it to just continue?
I updated the code based in your advice but it doesnt display my show card thanks a lot</p>

```<code>import random, sys

suits = ('Clubs', 'Spades', 'Hearts', 'Diamonds')
pip = ('Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King')
pipValues = {'Ace':11, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'Jack':10, 'Queen':10, 'King':10}

class Card:

    def __init__(self, suit, pip):
        self.suit = suit
        self.pip = pip
        self.value = pipValues.get(pip)

    def __str__(self):
        thisCard = ""
        thisCard += str(self.pip)
        thisCard += str(self.suit)
        return (thisCard)

    def __repr__(self):
        thisCard = ""
        thisCard += str(self.pip)
        thisCard += str(self.suit)
        return (thisCard)

class Player:

    def __init__(self):
        self.hand = []
        self.handTotal = 0

    def __str__(self):
        printHand = ""
        for i in self.hand:
            printHand += str(i) + " "
        return (printHand)

    def __repr__(self):
        printHand = ""
        for i in self.hand:
            printHand += str(i) + " "
        return (printHand)

class Deck:

    def __init__(self):
        self.cardList = []
        #for each suit take every card
        for i in range(len(suits)):
            for j in range(len(pip)):
                self.cardList.append(Card(suits[i], pip[j]))

    def shuffle(self):
        random. shuffle (self.cardList)

    def dealOne(self, player):
        (player.hand).append(self.cardList[0])

        player.handTotal += self.cardList[0].value

        del self.cardList[0]
        print self.cardList
        return self.cardList

    def __str__(self):
        printString = ""
        for i in range(len(self.cardList)):
            if i % 13 == 0:
                printString += "\n \t"
                printString += str(self.cardList[i]) + " "
            else:
                printString += str(self.cardList[i]) + " "
        printString += "\n"

        return printString

def showHands(player, opponent):
    print ('Dealer shows ' + str(opponent.hand[0]) + ' faceup')
    print ('You show ' + str(player.hand[0]) +str(player.hand[0] ))

def playerTurn(deck, player, other):
    #First, check scores to see if either player has a blackjack:

    if player.handTotal == 21 or other.handTotal == 21:
        if other.handTotal == 21:
            print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
            print ("Dealer has " + str(other) + "for a total of 21")
            print ("Dealer has a Blackjack! Dealer wins!")
            print ("Thanks for playing. Come back again soon! ")
            message()
        else:
            print ("You hold " + str(player) + "for a total of 21")
            print ("You have a Blackjack! You win!")

            print ("Thanks for playing. Come back again soon! ")
            message()

    hitOrStand = 0
    aces = False

    #IF TWO ACES
    if player.hand[0].pip == "A" and player.hand[1].pip == "A":
        player.hand[0].pipValue = 1

    if player.handTotal == 21:
            print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
            print ("Blackjack! You win!")
            print ("Thanks for playing. Come back soon!")
            print()
            message()
    while hitOrStand != 2:
        #check for aces
        for i in player.hand:
            if i.pip == "A" and i.value == 11:
                aces = True

        print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
        print()
        hitOrStand = input('Do you hit or stand? Enter "1" for hit and "2" for stand: ')
        while hitOrStand != 1 and hitOrStand != 2:
            try:
                hitOrStand = int(hitOrStand)
                break
            except ValueError:
                print ("Enter a valid integer \n")
            hitOrStand = input('Do you hit hit or stand? Enter "1" for hit and "2" for stand: ')
        print()

        if hitOrStand == 1:
            print('Card dealt:  ' + str(deck.cardList[0]))
            print()
            deck.dealOne(player)
            #check if an ace was drawn
            for i in player.hand:
                if i.pip == "A" and i.value == 11:
                    aces = True

        if player.handTotal == 21:
            print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
            print ("Blackjack!! You Win!")
            print()
            print ("Thanks for playing. Come back soon!")
            message()

        if player.handTotal > 21:
            #check for aces
            if aces:
                print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("Over 21. Value of ace changed to 1")
                #chanlge value of ace and hand
                player.handTotal = player.handTotal - 10
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        i.value = 1
                #check for other standard aces
                aces = False
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        aces = True
            else:
                print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("You Bust! Dealer Wins!")
                #exit, since you're a loser
                print ("Thanks for Playing! Come Back Soon!")
                print()
                raise SystemExit

        if hitOrStand == 2:
            print ('You stand at: ' + str(player.handTotal))
            print()

    print ("Now Dealer's Turn")
    print ()
def message():
        again = raw_input("Do you want to play again? (Y/N) : ")
        if(again == "Y" or again == "y"):
            main()
        else:
            print "\n\n-------Thank you for playing!--------\n\n"
            exit()

def opponentTurn(deck, player, other):
    if other.handTotal == 21:
        raise SystemExit
    aces = False
    hitOrStand = 0

    #IF TWO ACES
    if player.hand[0].pip == "A" and player.hand[1].pip == "A":
        player.hand[0].pipValue = 1

    while hitOrStand != 2:
        #check for aces
        for i in player.hand:
            if i.pip == "A" and i.value == 11:
                aces = True

        print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
        print()
        #if blackjack
        if player.handTotal == 21:
            print ("Dealer has a BlackJack! Dealer Wins!")
            break
        if player.handTotal <21 and other.handTotal == 21:
            print ("Dealer's hand is " + str(player.handTotal) + ". You have a Blackjack! Congratulations! You win! ")
            break

        if player.handTotal < other.handTotal:
            hitOrStand = 1
        if player.handTotal >= other.handTotal:
            hitOrStand = 2

        if hitOrStand == 1:
            print("Dealer hits. " + 'Card dealt:  ' + str(deck.cardList[0]))
            deck.dealOne(player)
            #check if an ace was drawn
            for i in player.hand:
                if i.pip == "A" and i.value == 11:
                    aces = True

        if player.handTotal > 21:
            #check for aces
            if aces:
                print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("Over 21. Value of ace changed to 1")
                #chanlge value of ace and hand
                player.handTotal = player.handTotal - 10
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        i.value = 1

                #check for other standard aces
                aces = False
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        aces = True
            else:
                print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("Dealer Busts! You Win!")
                message()

        if hitOrStand == 2:
            print ("Dealer stands at " + str(player.handTotal))
            print ("Your score is " + str(other.handTotal))
            print ("Dealer Wins!")
            message()
#who won
def main():
    cardDeck = Deck()
    print ('Initial Deck: ')
    print(cardDeck)

    cardDeck.shuffle()
    print ('Shuffled Deck: ')
    print(cardDeck)

    keep_playing = True
    while keep_playing:

        player = Player()
        opponent = Player()

        #give each player 2 cards, alternating
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)

        print ('Deck after giving 2 cards each')
        print (cardDeck)

        #show 1 faceup card for each player
        showHands(player,opponent)

        #start playing
        playerTurn(cardDeck,player, opponent)
        opponentTurn(cardDeck, opponent, player)

        again = raw_input("Do you want to play again? (Y/N) : ")
        keep_playing = again in "Yy"

    # Reach here after dropping out of the while loop
    print "\n\n-------Thank you for playing!--------\n\n"
main()
</code>```

答:
Yes, you can have one game continue from where the previous one left off.  The current problem is that you call main recursively.  This starts over from the beginning, shuffling a full deck, etc.

Instead, you would want a main program something like this:

```<code>def main():
    cardDeck = Deck()
    print ('Initial Deck: ')
    print(cardDeck)

    cardDeck.shuffle()
    print ('Shuffled Deck: ')
    print(cardDeck)

    keep_playing = True
    while keep_playing:

        player = Player()
        opponent = Player()

        #give each player 2 cards, alternating
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)

        print ('Deck after giving 2 cards each')
        print (cardDeck)

        #show 1 faceup card for each player
        showHands(player,opponent)

        #start playing
        playerTurn(cardDeck,player, opponent)
        opponentTurn(cardDeck, opponent, player)

        again = raw_input("Do you want to play again? (Y/N) : ")
        keep_playing = again in "Yy"

    # Reach here after dropping out of the while loop
    print "\n\n-------Thank you for playing!--------\n\n"
</code>```

This gets rid of your message function and the recursive call to main.

Body:
I want this game to start each hand with the cards left over from the previous hand.  Instead, it begins with a complete, newly-shuffled deck.  How can I fix it to just continue?
I updated the code based in your advice but it doesnt display my show card thanks a lot

import random, sys

suits = ('Clubs', 'Spades', 'Hearts', 'Diamonds')
pip = ('Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King')
pipValues = {'Ace':11, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'Jack':10, 'Queen':10, 'King':10}

class Card:

    def __init__(self, suit, pip):
        self.suit = suit
        self.pip = pip
        self.value = pipValues.get(pip)

    def __str__(self):
        thisCard = ""
        thisCard += str(self.pip)
        thisCard += str(self.suit)
        return (thisCard)

    def __repr__(self):
        thisCard = ""
        thisCard += str(self.pip)
        thisCard += str(self.suit)
        return (thisCard)

class Player:

    def __init__(self):
        self.hand = []
        self.handTotal = 0

    def __str__(self):
        printHand = ""
        for i in self.hand:
            printHand += str(i) + " "
        return (printHand)

    def __repr__(self):
        printHand = ""
        for i in self.hand:
            printHand += str(i) + " "
        return (printHand)

class Deck:

    def __init__(self):
        self.cardList = []
        #for each suit take every card
        for i in range(len(suits)):
            for j in range(len(pip)):
                self.cardList.append(Card(suits[i], pip[j]))

    def shuffle(self):
        random. shuffle (self.cardList)

    def dealOne(self, player):
        (player.hand).append(self.cardList[0])

        player.handTotal += self.cardList[0].value

        del self.cardList[0]
        print self.cardList
        return self.cardList

    def __str__(self):
        printString = ""
        for i in range(len(self.cardList)):
            if i % 13 == 0:
                printString += "\n \t"
                printString += str(self.cardList[i]) + " "
            else:
                printString += str(self.cardList[i]) + " "
        printString += "\n"

        return printString

def showHands(player, opponent):
    print ('Dealer shows ' + str(opponent.hand[0]) + ' faceup')
    print ('You show ' + str(player.hand[0]) +str(player.hand[0] ))

def playerTurn(deck, player, other):
    #First, check scores to see if either player has a blackjack:

    if player.handTotal == 21 or other.handTotal == 21:
        if other.handTotal == 21:
            print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
            print ("Dealer has " + str(other) + "for a total of 21")
            print ("Dealer has a Blackjack! Dealer wins!")
            print ("Thanks for playing. Come back again soon! ")
            message()
        else:
            print ("You hold " + str(player) + "for a total of 21")
            print ("You have a Blackjack! You win!")

            print ("Thanks for playing. Come back again soon! ")
            message()

    hitOrStand = 0
    aces = False

    #IF TWO ACES
    if player.hand[0].pip == "A" and player.hand[1].pip == "A":
        player.hand[0].pipValue = 1

    if player.handTotal == 21:
            print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
            print ("Blackjack! You win!")
            print ("Thanks for playing. Come back soon!")
            print()
            message()
    while hitOrStand != 2:
        #check for aces
        for i in player.hand:
            if i.pip == "A" and i.value == 11:
                aces = True

        print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
        print()
        hitOrStand = input('Do you hit or stand? Enter "1" for hit and "2" for stand: ')
        while hitOrStand != 1 and hitOrStand != 2:
            try:
                hitOrStand = int(hitOrStand)
                break
            except ValueError:
                print ("Enter a valid integer \n")
            hitOrStand = input('Do you hit hit or stand? Enter "1" for hit and "2" for stand: ')
        print()

        if hitOrStand == 1:
            print('Card dealt:  ' + str(deck.cardList[0]))
            print()
            deck.dealOne(player)
            #check if an ace was drawn
            for i in player.hand:
                if i.pip == "A" and i.value == 11:
                    aces = True

        if player.handTotal == 21:
            print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
            print ("Blackjack!! You Win!")
            print()
            print ("Thanks for playing. Come back soon!")
            message()

        if player.handTotal > 21:
            #check for aces
            if aces:
                print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("Over 21. Value of ace changed to 1")
                #chanlge value of ace and hand
                player.handTotal = player.handTotal - 10
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        i.value = 1
                #check for other standard aces
                aces = False
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        aces = True
            else:
                print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("You Bust! Dealer Wins!")
                #exit, since you're a loser
                print ("Thanks for Playing! Come Back Soon!")
                print()
                raise SystemExit

        if hitOrStand == 2:
            print ('You stand at: ' + str(player.handTotal))
            print()

    print ("Now Dealer's Turn")
    print ()
def message():
        again = raw_input("Do you want to play again? (Y/N) : ")
        if(again == "Y" or again == "y"):
            main()
        else:
            print "\n\n-------Thank you for playing!--------\n\n"
            exit()

def opponentTurn(deck, player, other):
    if other.handTotal == 21:
        raise SystemExit
    aces = False
    hitOrStand = 0

    #IF TWO ACES
    if player.hand[0].pip == "A" and player.hand[1].pip == "A":
        player.hand[0].pipValue = 1

    while hitOrStand != 2:
        #check for aces
        for i in player.hand:
            if i.pip == "A" and i.value == 11:
                aces = True

        print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
        print()
        #if blackjack
        if player.handTotal == 21:
            print ("Dealer has a BlackJack! Dealer Wins!")
            break
        if player.handTotal <21 and other.handTotal == 21:
            print ("Dealer's hand is " + str(player.handTotal) + ". You have a Blackjack! Congratulations! You win! ")
            break

        if player.handTotal < other.handTotal:
            hitOrStand = 1
        if player.handTotal >= other.handTotal:
            hitOrStand = 2

        if hitOrStand == 1:
            print("Dealer hits. " + 'Card dealt:  ' + str(deck.cardList[0]))
            deck.dealOne(player)
            #check if an ace was drawn
            for i in player.hand:
                if i.pip == "A" and i.value == 11:
                    aces = True

        if player.handTotal > 21:
            #check for aces
            if aces:
                print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("Over 21. Value of ace changed to 1")
                #chanlge value of ace and hand
                player.handTotal = player.handTotal - 10
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        i.value = 1

                #check for other standard aces
                aces = False
                for i in player.hand:
                    if i.pip == "A" and i.value == 11:
                        aces = True
            else:
                print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
                print ("Dealer Busts! You Win!")
                message()

        if hitOrStand == 2:
            print ("Dealer stands at " + str(player.handTotal))
            print ("Your score is " + str(other.handTotal))
            print ("Dealer Wins!")
            message()
#who won
def main():
    cardDeck = Deck()
    print ('Initial Deck: ')
    print(cardDeck)

    cardDeck.shuffle()
    print ('Shuffled Deck: ')
    print(cardDeck)

    keep_playing = True
    while keep_playing:

        player = Player()
        opponent = Player()

        #give each player 2 cards, alternating
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)

        print ('Deck after giving 2 cards each')
        print (cardDeck)

        #show 1 faceup card for each player
        showHands(player,opponent)

        #start playing
        playerTurn(cardDeck,player, opponent)
        opponentTurn(cardDeck, opponent, player)

        again = raw_input("Do you want to play again? (Y/N) : ")
        keep_playing = again in "Yy"

    # Reach here after dropping out of the while loop
    print "\n\n-------Thank you for playing!--------\n\n"
main()

Body:
Yes, you can have one game continue from where the previous one left off.  The current problem is that you call main recursively.  This starts over from the beginning, shuffling a full deck, etc.

Instead, you would want a main program something like this:

def main():
    cardDeck = Deck()
    print ('Initial Deck: ')
    print(cardDeck)

    cardDeck.shuffle()
    print ('Shuffled Deck: ')
    print(cardDeck)

    keep_playing = True
    while keep_playing:

        player = Player()
        opponent = Player()

        #give each player 2 cards, alternating
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)
        cardDeck.dealOne(player)
        cardDeck.dealOne(opponent)

        print ('Deck after giving 2 cards each')
        print (cardDeck)

        #show 1 faceup card for each player
        showHands(player,opponent)

        #start playing
        playerTurn(cardDeck,player, opponent)
        opponentTurn(cardDeck, opponent, player)

        again = raw_input("Do you want to play again? (Y/N) : ")
        keep_playing = again in "Yy"

    # Reach here after dropping out of the while loop
    print "\n\n-------Thank you for playing!--------\n\n"

This gets rid of your message function and the recursive call to main.


来源: stackexchange

问:
Tika standalone app, metadata and content in the same output as plain text
I can't find a way to get an output from tika app that includes metadata and content in the same file as plain text. Anyone knows if it could be done?</p>

答:
Using the app the only way to get a document that contains the metadata and extracted text is to output it in XML, HTML, or JSON recursive - if you need it in plain text you'll then have to do some post processing of that document (JSON is probably the easiest, using jq or the python json modules etc).

Depending on the output format you need, a simple alternative might be to just run the application twice, appending the output together:

```<code>java -jar tika-app-1.14.jar --metadata document.pdf > document.txt
java -jar tika-app-1.14.jar --text document.pdf >> document.txt
</code>```

ContentLicense: CC BY-SA 3.0

Body:
Using the app the only way to get a document that contains the metadata and extracted text is to output it in XML, HTML, or JSON recursive - if you need it in plain text you'll then have to do some post processing of that document (JSON is probably the easiest, using jq or the python json modules etc).

Depending on the output format you need, a simple alternative might be to just run the application twice, appending the output together:

java -jar tika-app-1.14.jar --metadata document.pdf > document.txt
java -jar tika-app-1.14.jar --text document.pdf >> document.txt


问:
Replacing one url base with another in php
I'm trying to figure out how to replace one url base with another within php.

So a function that takes "http://www.website1.com/test" and replaces the "http://www.website1.com" to make it "http://www.website2.com/test" .

This is probably a very easy quick function but i'm having trouble finding the right str_replace() to get this done.

```<code><?php
$pre_replace = "http://www.website1.com/test";
$post_replace = str_replace(
  'http://www.website1.com',
  'http://www.website2.com',
  $pre_replace);
echo $post_replace;
?>
</code>```

isn't quite working for some reason

答:
str_replace should work just fine..</p>

```<code><?php
$string = 'http://www.website1.com/test';
$replace = 'http://www.website1.com';
$replaceWith = 'http://www.website2.com';
echo str_replace($replace, $replaceWith, $string);
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I'm trying to figure out how to replace one url base with another within php.

So a function that takes "http://www.website1.com/test" and replaces the "http://www.website1.com" to make it "http://www.website2.com/test" .

This is probably a very easy quick function but i'm having trouble finding the right str_replace() to get this done.

<?php
$pre_replace = "http://www.website1.com/test";
$post_replace = str_replace(
  'http://www.website1.com',
  'http://www.website2.com',
  $pre_replace);
echo $post_replace;
?>

isn't quite working for some reason

Body:
str_replace should work just fine..

<?php
$string = 'http://www.website1.com/test';
$replace = 'http://www.website1.com';
$replaceWith = 'http://www.website2.com';
echo str_replace($replace, $replaceWith, $string);


问:
Function with more choices
I created a simple key stroke counter code that prints number of entered letters. However I am trying to figure out how to make a function so it recognizes 1 letter from 2 letters (singular and plural). I would like to add also 'stroke' in my code, and when the keyboard key is entered only once Id like it to print "You entered 1 stroke" instead of "You entered 1 strokes.".

I tried something but cant really move forward:

```<code>print('Start typing: ')
count = raw_input()
print('You entered:'), len(count), ('strokes')
</code>```

答:
Just use normal conditionals, e.g. using a conditional expression:

```<code>print "You entered:", len(count), 'stroke' if len(count) == 1 else 'strokes'
</code>```

Also, just for fun, the overly clever for the sake of brevity solution that you should not actually use:

```<code>print "You entered:", len(count), 'strokes'[:6+(len(count) != 1)]
</code>```

or:

```<code>print "You entered:", len(count), 'stroke' + 's' * (len(count) != 1)
</code>```

Title: Function with more choices

Body:
I created a simple key stroke counter code that prints number of entered letters. However I am trying to figure out how to make a function so it recognizes 1 letter from 2 letters (singular and plural). I would like to add also 'stroke' in my code, and when the keyboard key is entered only once Id like it to print "You entered 1 stroke" instead of "You entered 1 strokes.".

I tried something but cant really move forward:

print('Start typing: ')
count = raw_input()
print('You entered:'), len(count), ('strokes')

Body:
Just use normal conditionals, e.g. using a conditional expression:

print "You entered:", len(count), 'stroke' if len(count) == 1 else 'strokes'

Also, just for fun, the overly clever for the sake of brevity solution that you should not actually use:

print "You entered:", len(count), 'strokes'[:6+(len(count) != 1)]

or:

print "You entered:", len(count), 'stroke' + 's' * (len(count) != 1)


问:
Broken FB-omniauth after bundle update, invalid credentials
The oauth data doesn't go to controller action. Can't understand what's wrong. There is one more auth provider in this controller and it works well the core is absolutely same.

```<code>devise  3.5.10
rails 4.2.4

devise.rb
config.omniauth :facebook, Figaro.env.fb_app_id, Figaro.env.fb_app_secret, callback_url: 'https://chotam.ru/users/auth/facebook/callback',
                  scope: 'email, publish_actions'

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

def facebook
    logger.error "fb here" # IT'S NO OUTPUT HERE ON REQUEST!!!
    logger.error(request.env['omniauth.auth'])
    result = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
    @user = result[:user]
    status = result[:status]
    if @user
      token = request.env["omniauth.auth"]["credentials"]["token"]
      @user.account.update_attribute(:fb_token, token)
      if status[:redirect] == 'added' || status[:redirect] == 'existed'
        flash[status[:key]] = status[:value]
        render 'devise/registrations/edit'
      else
        flash[status[:key]] = status[:value]
        sign_in_and_redirect @user, event: :authentication
      end
    else
      flash[status[:key]] = status[:value]
      redirect_to new_user_registration_url
    end
  end
</code>```

UPDATE
With logger I can see following:

```<code>E, [2017-03-28T23:46:41.255481 #21494] ERROR -- : (facebook) Authentication failure! invalid_credentials: OAuth2::Error, :
{"access_token":"real_token","token_type":"bearer"$
</code>```

How to find what's wrong?
And also I found that users can't change their passwords anymore.

答:
Ok...found a way without updating the gem.

You can add the following in your config/initializers/devise.rb file at the config.omniauth line:

```<code>client_options: {
  site: "https://graph.facebook.com/v2.3",
  authorize_url: "https://www.facebook.com/v2.3/dialog/oauth"
},
token_params: {
  parse: :json
}
</code>```

YMMV with the full config, but it would look something like this:

```<code>config.omniauth :facebook, ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"],
    scope: 'email',
    secure_image_url: true,
    auth_type: 'https',
    info_fields: 'email,name,first_name,last_name',
    client_options: {
        site: "https://graph.facebook.com/v2.3",
        authorize_url: "https://www.facebook.com/v2.3/dialog/oauth"
    },
    token_params: {
        parse: :json
    }
</code>```

The main issue is that they upgraded the response format and without the forced version pointer and the token params to parse the new json format (instead of url encoded format), it would break at the response because it didn't recognize what was spit back from the api.

Body:
The oauth data doesn't go to controller action. Can't understand what's wrong. There is one more auth provider in this controller and it works well the core is absolutely same.

devise  3.5.10
rails 4.2.4

devise.rb
config.omniauth :facebook, Figaro.env.fb_app_id, Figaro.env.fb_app_secret, callback_url: 'https://chotam.ru/users/auth/facebook/callback',
                  scope: 'email, publish_actions'

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

def facebook
    logger.error "fb here" # IT'S NO OUTPUT HERE ON REQUEST!!!
    logger.error(request.env['omniauth.auth'])
    result = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
    @user = result[:user]
    status = result[:status]
    if @user
      token = request.env["omniauth.auth"]["credentials"]["token"]
      @user.account.update_attribute(:fb_token, token)
      if status[:redirect] == 'added' || status[:redirect] == 'existed'
        flash[status[:key]] = status[:value]
        render 'devise/registrations/edit'
      else
        flash[status[:key]] = status[:value]
        sign_in_and_redirect @user, event: :authentication
      end
    else
      flash[status[:key]] = status[:value]
      redirect_to new_user_registration_url
    end
  end

UPDATE
With logger I can see following:

E, [2017-03-28T23:46:41.255481 #21494] ERROR -- : (facebook) Authentication failure! invalid_credentials: OAuth2::Error, :
{"access_token":"real_token","token_type":"bearer"$

How to find what's wrong?
And also I found that users can't change their passwords anymore.

Body:
Ok...found a way without updating the gem.

You can add the following in your config/initializers/devise.rb file at the config.omniauth line:

client_options: {
  site: "https://graph.facebook.com/v2.3",
  authorize_url: "https://www.facebook.com/v2.3/dialog/oauth"
},
token_params: {
  parse: :json
}

YMMV with the full config, but it would look something like this:

config.omniauth :facebook, ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"],
    scope: 'email',
    secure_image_url: true,
    auth_type: 'https',
    info_fields: 'email,name,first_name,last_name',
    client_options: {
        site: "https://graph.facebook.com/v2.3",
        authorize_url: "https://www.facebook.com/v2.3/dialog/oauth"
    },
    token_params: {
        parse: :json
    }

The main issue is that they upgraded the response format and without the forced version pointer and the token params to parse the new json format (instead of url encoded format), it would break at the response because it didn't recognize what was spit back from the api.


答:
You can use if and else:

```<code>if len(count) == 1:
    print 'you entered: 1 stroke'
else:
    print 'you entered: {} strokes'.format(len(strokes))
</code>```

Title: Function with more choices

Body:
You can use if and else:

if len(count) == 1:
    print 'you entered: 1 stroke'
else:
    print 'you entered: {} strokes'.format(len(strokes))


问:
pointer to object == pointer to first member?
Why does the if condition in the following code yield true?

```<code>struct A
{
    int firstMember;
} a1;

if (&a1 == static_cast<void*>(&a1.firstMember)) std::cout << "equal";
</code>```

I got a bit confused when reading Stroustrup's FAQ on empty classes, specifically the statement below:

```<code>if (p1 == p2) cout << "nice: good optimizer";
</code>```

答: A reference acts much like a pointer in C++.  When you take the reference to a variable, you are asking for the location in memory for that variable.  In this case, you are comparing the first piece of information in a1 to a1 itself.  This is a specific case where this will work, and isn't something you should rely on.</p>

Body:
Why does the if condition in the following code yield true?

struct A
{
    int firstMember;
} a1;

if (&a1 == static_cast<void*>(&a1.firstMember)) std::cout << "equal";

I got a bit confused when reading Stroustrup's FAQ on empty classes, specifically the statement below:

if (p1 == p2) cout << "nice: good optimizer";


问:
How to lock slider and prevent updating of values with mouse into dat.GUI menu
I try to implement a way to prevent the updating of values with mouse (actually when the three.js animation has started, launched with a click on button).

For the moment, I have the following dat.GUI menu:

Once "start" button is clicked, I would like to prevent user from modifying with mouse the parameters "Rotation x" and "Rotation y".

Here is the concerned part of code for this menu:

```<code>// Create GUI
var gui = new dat.GUI({
      autoplace: false,
      width: 350,
          height: 9 * 32 - 1
});

var params = {
      GreatCircle : '',
      Rotationx : torusRotationInitX,
      Rotationy : torusRotationInitY,
      StartingVector : '',
      ComponentVectorTheta : 15.0,
      ComponentVectorPhi : 15.0,
      CovariantDerivativeVector : '',
      ComponentCovariantDerivativeTheta : 15.0,
      ComponentCovariantDerivativePhi : 15.0
};

// Set parameters for GUI
gui.add(params, 'GreatCircle').name('Great Circle ');
controllerRotationx = gui.add(params, 'Rotationx', 0, 2*Math.PI, 0.001).name('Rotation x ');
controllerRotationy = gui.add(params, 'Rotationy', 0, 2*Math.PI, 0.001).name('Rotation y ');
...
</code>```

When I click on reset button, I call the following function:

```<code>  // Reset Button
  resetButton.onclick = function ResetParameters() {

  ...

  // Reinitialize parameters into gui
  params.Rotationx = torusRotationInitX;
  params.Rotationy = torusRotationInitY;

  for (var i in gui.__controllers) {
     gui.__controllers[i].updateDisplay();
  }

render();

}
</code>```

I don't know if there is an option for controller to lock these sliders which usually change their values. Is it possible?

Update 1

Maybe I could wrapper the dat.GUI menu into a div and make this div not clickable, is it a solution?

Update 2

I tried to apply the method used on Method for disabling a button in dat.gui?

Following this solution, I have added the extension into dat.gui, just after:

```<code>dat.controllers.FunctionController = (function (Controller, dom, common) {

...

});
</code>```

The following added code snippet is:

```<code>function blockEvent(event)
{
  event.stopPropagation();
}

Object.defineProperty(dat.controllers.FunctionController.prototype, "disabled", {
  get: function()
  {
    return this.domElement.hasAttribute("disabled");
  },
  set: function(value)
  {
    if (value)
    {
      this.domElement.setAttribute("disabled", "disabled");
      this.domElement.addEventListener("click", blockEvent, true);
    }
    else
    {
      this.domElement.removeAttribute("disabled");
      this.domElement.removeEventListener("click", blockEvent, true);
    }
  },
  enumerable: true
});
</code>```

Is extension code well located into dat.GUI source?

Then, I set the property "disabled" into my code to prevent user from sliding "controllerRotationx" with mouse (once start button is pressed):

```<code>if (animation)
controllerRotationx.__li.disabled = true;
</code>```

Unfortunately, my method doesn't work : when animation is started, I can still move the slider contained into "controllerRotationx".

I saw that above link (Method for disabling a button in dat.gui?), this was about a button and not for a slider, does it change anything for my case?

I didn't find an explicit controller for the slider.

答:
The solution given by @Radio works pretty well. But, with sliders, the slider is a sibling of the text box's DOM element. We need to disable pointer events on the div which contains all the controls (and which is not exposed directly by dat.gui). So,</p>

```<code>var speeder = menu.add(text, 'speed', -5, 5);
// disables the text box
speeder.domElement.style.pointerEvents = "none"
// disables all controller elements related to "speeder"
speeder.domElement.parentElement.style.pointerEvents = 'none'
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I try to implement a way to prevent the updating of values with mouse (actually when the three.js animation has started, launched with a click on button).

For the moment, I have the following dat.GUI menu:

Once "start" button is clicked, I would like to prevent user from modifying with mouse the parameters "Rotation x" and "Rotation y".

Here is the concerned part of code for this menu:

// Create GUI
var gui = new dat.GUI({
      autoplace: false,
      width: 350,
          height: 9 * 32 - 1
});

var params = {
      GreatCircle : '',
      Rotationx : torusRotationInitX,
      Rotationy : torusRotationInitY,
      StartingVector : '',
      ComponentVectorTheta : 15.0,
      ComponentVectorPhi : 15.0,
      CovariantDerivativeVector : '',
      ComponentCovariantDerivativeTheta : 15.0,
      ComponentCovariantDerivativePhi : 15.0
};

// Set parameters for GUI
gui.add(params, 'GreatCircle').name('Great Circle ');
controllerRotationx = gui.add(params, 'Rotationx', 0, 2*Math.PI, 0.001).name('Rotation x ');
controllerRotationy = gui.add(params, 'Rotationy', 0, 2*Math.PI, 0.001).name('Rotation y ');
...

When I click on reset button, I call the following function:

  // Reset Button
  resetButton.onclick = function ResetParameters() {

  ...

  // Reinitialize parameters into gui
  params.Rotationx = torusRotationInitX;
  params.Rotationy = torusRotationInitY;

  for (var i in gui.__controllers) {
     gui.__controllers[i].updateDisplay();
  }

render();

}

I don't know if there is an option for controller to lock these sliders which usually change their values. Is it possible?

Update 1

Maybe I could wrapper the dat.GUI menu into a div and make this div not clickable, is it a solution?

Update 2

I tried to apply the method used on Method for disabling a button in dat.gui?

Following this solution, I have added the extension into dat.gui, just after:

dat.controllers.FunctionController = (function (Controller, dom, common) {

...

});

The following added code snippet is:

function blockEvent(event)
{
  event.stopPropagation();
}

Object.defineProperty(dat.controllers.FunctionController.prototype, "disabled", {
  get: function()
  {
    return this.domElement.hasAttribute("disabled");
  },
  set: function(value)
  {
    if (value)
    {
      this.domElement.setAttribute("disabled", "disabled");
      this.domElement.addEventListener("click", blockEvent, true);
    }
    else
    {
      this.domElement.removeAttribute("disabled");
      this.domElement.removeEventListener("click", blockEvent, true);
    }
  },
  enumerable: true
});

Is extension code well located into dat.GUI source?

Then, I set the property "disabled" into my code to prevent user from sliding "controllerRotationx" with mouse (once start button is pressed):

if (animation)
controllerRotationx.__li.disabled = true;

Unfortunately, my method doesn't work : when animation is started, I can still move the slider contained into "controllerRotationx".

I saw that above link (Method for disabling a button in dat.gui?), this was about a button and not for a slider, does it change anything for my case?

I didn't find an explicit controller for the slider.

Body:
The solution given by @Radio works pretty well. But, with sliders, the slider is a sibling of the text box's DOM element. We need to disable pointer events on the div which contains all the controls (and which is not exposed directly by dat.gui). So,

var speeder = menu.add(text, 'speed', -5, 5);
// disables the text box
speeder.domElement.style.pointerEvents = "none"
// disables all controller elements related to "speeder"
speeder.domElement.parentElement.style.pointerEvents = 'none'


问:
How can one delete ONLY files in specific folders matching a regular expression in PowerShell?
We have two companies, in two separate containers in AD, accessing one shared directory for all of their scan files. We need to have an automated script run every night, and purge ONLY the files from the user folders in one companies AD container (Office1). I found a very helpful script on here that I was able to modify to match and delete the folders for these specific users, but I need this to be able to delete just the files in these folders only.

Here is the script:

```<code>$UserNames = Get-ADUser -Filter * -SearchBase "OU=Office1,DC=US,DC=parent,DC=net" |
             Select -ExpandProperty SamAccountName
$UserRegex = ($UserNames | ForEach {[RegEx]::Escape($_)}) -join "|"
Get-ChildItem -Path "\\share\scanfiles\Test" -Directory -Recurse |
    Where {$_.Name -match $UserRegex -and !$_.PSIsContainer} |
    Remove-Item -Force
</code>```

答:
Try the following:

```<code>Get-ChildItem -Path "\\share\scanfiles\Test" -Directory -Recurse |
  Where { $_.Name -Match $UserRegex } |
    ForEach-Object { Remove-Item "$($_.FullName)\*" -Force -WhatIf }
</code>```

-WhatIf previews what would be deleted; remove it to perform actual deletion.

Note how the first 2 segments of the pipeline output directory objects only, whereas the last segment then deletes the files inside each directory.

Body:
We have two companies, in two separate containers in AD, accessing one shared directory for all of their scan files. We need to have an automated script run every night, and purge ONLY the files from the user folders in one companies AD container (Office1). I found a very helpful script on here that I was able to modify to match and delete the folders for these specific users, but I need this to be able to delete just the files in these folders only.

Here is the script:

$UserNames = Get-ADUser -Filter * -SearchBase "OU=Office1,DC=US,DC=parent,DC=net" |
             Select -ExpandProperty SamAccountName
$UserRegex = ($UserNames | ForEach {[RegEx]::Escape($_)}) -join "|"
Get-ChildItem -Path "\\share\scanfiles\Test" -Directory -Recurse |
    Where {$_.Name -match $UserRegex -and !$_.PSIsContainer} |
    Remove-Item -Force

Body:
Try the following:

Get-ChildItem -Path "\\share\scanfiles\Test" -Directory -Recurse |
  Where { $_.Name -Match $UserRegex } |
    ForEach-Object { Remove-Item "$($_.FullName)\*" -Force -WhatIf }

-WhatIf previews what would be deleted; remove it to perform actual deletion.

Note how the first 2 segments of the pipeline output directory objects only, whereas the last segment then deletes the files inside each directory.


问:
ValueError badly formed hexadecimal UUID string django ListView
Assume all imports done.

I have a model like this:

```<code>class Package(models.Model):
  uuid = models.UUIDField(default=uuid.uuid4, editable=False)
  name = models.CharField(max_length=400)
</code>```

Then I want to use generic ListView like so:

```<code>class PackageList(ListView):
  model = Package
  template_name = 'package/list.html'
</code>```

All with url like so:

```<code>url(r'^package/list/$', views.PackageList.as_view(), name='package_list'),
</code>```

When I visit the localhost:8000, I get

ValueError at /package/list/
badly formed hexadecimal UUID string

However, a DetailView generic view loads the detail based on the uuid successfully, without any issues.

The error comes up only when using the ListView.

What am I doing wrong?

答:
Figured.

The url sequence was the culprit. Having sequence this way fixed it:

```<code>url(r'^travel/add/$', views.TravelAdd.as_view(), name='travel_add'),
url(r'^travel/list/$', views.TravelList.as_view(), name='travel_list'),
url(r'^travel/(?P<uuid>[\w-]+)/$', views.TravelDetail.as_view(), name='travel_detail'),
</code>```

Previously, it was this:

```<code>url(r'^travel/add/$', views.TravelAdd.as_view(), name='travel_add'),
url(r'^travel/(?P<uuid>[\w-]+)/$', views.TravelDetail.as_view(), name='travel_detail'),
url(r'^travel/list/$', views.TravelList.as_view(), name='travel_list'),
</code>```

Body:
Assume all imports done.

I have a model like this:

class Package(models.Model):
  uuid = models.UUIDField(default=uuid.uuid4, editable=False)
  name = models.CharField(max_length=400)

Then I want to use generic ListView like so:

class PackageList(ListView):
  model = Package
  template_name = 'package/list.html'

All with url like so:

url(r'^package/list/$', views.PackageList.as_view(), name='package_list'),

When I visit the localhost:8000, I get

ValueError at /package/list/
badly formed hexadecimal UUID string

However, a DetailView generic view loads the detail based on the uuid successfully, without any issues.

The error comes up only when using the ListView.

What am I doing wrong?

Body:
Figured.

The url sequence was the culprit. Having sequence this way fixed it:

url(r'^travel/add/$', views.TravelAdd.as_view(), name='travel_add'),
url(r'^travel/list/$', views.TravelList.as_view(), name='travel_list'),
url(r'^travel/(?P<uuid>[\w-]+)/$', views.TravelDetail.as_view(), name='travel_detail'),

Previously, it was this:

url(r'^travel/add/$', views.TravelAdd.as_view(), name='travel_add'),
url(r'^travel/(?P<uuid>[\w-]+)/$', views.TravelDetail.as_view(), name='travel_detail'),
url(r'^travel/list/$', views.TravelList.as_view(), name='travel_list'),


问:
Grouping By with missing data
Image of Data and desired result:

I'm trying to aggregate volunteer hours from a Google spreadsheet a non-profit I volunteer for. We collect volunteer e-mail information and the time that each volunteer has contributed. Each volunteer only puts in their e-mail the first time. I've found examples online on how to send e-mails, but I'm having trouble aggregating the data. I think the trouble might be that not every row has an e-mail address associated with it.

I've been able to get the sum of hours worked by volunteer using QUERY(data, "select A, sum(C) Group By A", ) but can't figure out how to get the e-mail associated with each individual.

答:
Thanks for the advice! The VLOOKUP and ArrayFormula functions were new to me. Here's how I solved it:

QUERY(data, "select A, B where B <>'' ", -1)

This allowed me to get the Key-Value pair (Name, Email) for each volunteer (solving the problem of people who volunteered multiple times, but only left their e-mail once). From there, I was able to generate the 'Name:Hours Worked' table off to the right with:

QUERY(data, "select A, sum(C) Group By A", ).

Then, I used VLOOKUP to query my Name-Email table to get the desired result of:

Name-Email-aggregatedHours

Thanks!

Title: Grouping By with missing data


问:
APPlitools: 401 unauthorized is displayed during the execution of checkWindow() function
I used the code below from your website and also provided my APIKEY from my account. The url is launched and the browser size is also set. When the first checkWindow() function executes, I get a 401 Unauthorized exception.

```<code>using System;
using System.Drawing;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using Applitools;

namespace MyTests
{
    public class TestApplitoolsWebsite
    {
        public static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();

            // This is your api key, make sure you use it in all your tests.
            var eyes = new Eyes();
            eyes.ApiKey = "YOUR_API_KEY";

            try
            {
                // Start visual testing with browser viewport set to 1024x768.
                // Make sure to use the returned driver from this point on.
                driver = eyes.Open(driver, "Applitools", "Test Web Page", new Size(1024, 768));

                driver.Navigate().GoToUrl("http://www.applitools.com");

                // Visual validation point #1
                eyes.CheckWindow("Main Page");

                driver.FindElement(By.CssSelector(".features>a")).Click();

                // Visual validation point #2
                eyes.CheckWindow("Features Page");

                // End visual testing. Validate visual correctness.
                eyes.Close();
            }
            finally
            {
                eyes.AbortIfNotClosed();
                driver.Quit();
            }
        }
    }
}
</code>```

The main purpose of Applitools API is that it will take screen shot and it will compare with baseline screen shot from my local. But during this checkWindow() function i get the exception.

答:
the reasons for 401 Unauthorized could be:
1) Wrong API key.
2) Not setting a server (for private clouds/on prem).

Do you have a dedicated cloud? If not, check to make sure that your API key is correct.

If it is and it is still not working, contact the Applitools team at support@applitools.com and they will be glad to assist.

Body:
I used the code below from your website and also provided my APIKEY from my account. The url is launched and the browser size is also set. When the first checkWindow() function executes, I get a 401 Unauthorized exception.

using System;
using System.Drawing;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using Applitools;

namespace MyTests
{
    public class TestApplitoolsWebsite
    {
        public static void Main(string[] args)
        {
            IWebDriver driver = new FirefoxDriver();

            // This is your api key, make sure you use it in all your tests.
            var eyes = new Eyes();
            eyes.ApiKey = "YOUR_API_KEY";

            try
            {
                // Start visual testing with browser viewport set to 1024x768.
                // Make sure to use the returned driver from this point on.
                driver = eyes.Open(driver, "Applitools", "Test Web Page", new Size(1024, 768));

                driver.Navigate().GoToUrl("http://www.applitools.com");

                // Visual validation point #1
                eyes.CheckWindow("Main Page");

                driver.FindElement(By.CssSelector(".features>a")).Click();

                // Visual validation point #2
                eyes.CheckWindow("Features Page");

                // End visual testing. Validate visual correctness.
                eyes.Close();
            }
            finally
            {
                eyes.AbortIfNotClosed();
                driver.Quit();
            }
        }
    }
}

The main purpose of Applitools API is that it will take screen shot and it will compare with baseline screen shot from my local. But during this checkWindow() function i get the exception.


问:
How to solve "String interpolation produces a debug description for an optional value; did you mean to make this explicit?" in Xcode 8.3 beta?
Since beta 8.3, zillions warnings "String interpolation produces a debug description for an optional value; did you mean to make this explicit?" appeared in my code.

For example, the warning popped in the following situation up, where options could lead to nil:

```<code>let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"
</code>```

As previously designed, it was ok for me (and the compiler) the optionals to be interpolated as 'nil'. But compiler changed its mind.

What the compiler suggests is to add a String constructor with description as follows:

```<code>let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"
</code>```

Obviously, the results is explicit but also very very cumbersome in my opinion. Is there a better option? Do I have to fix all those warning or better wait for the next beta?

答:
After updating to Xcode 8.3 and getting a lot of warning messages, I came up with the following that is more like the original output behavior, easy to add in, reduces the verboseness of using "String(describing:)" both in code and output.

Basically, add an Optional extension that gives a String describing the thing in the optional, or simply "nil" if not set.  In addition, if the thing in the optional is a String, put it in quotes.

```<code>extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}
</code>```

And usage in a playground:

```<code>var s : String?
var i : Int?
var d : Double?

var mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = nil    i = nil   d = nil"

d = 3
i = 5
s = ""
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = ""    i = 5   d = 3.0"

s = "Test"
d = nil
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = "Test"    i = 5   d = nil"
</code>```

Thanks for help from following link:

check-if-variable-is-an-optional-and-what-type-it-wraps

Body:
Since beta 8.3, zillions warnings "String interpolation produces a debug description for an optional value; did you mean to make this explicit?" appeared in my code.

For example, the warning popped in the following situation up, where options could lead to nil:

let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"

As previously designed, it was ok for me (and the compiler) the optionals to be interpolated as 'nil'. But compiler changed its mind.

What the compiler suggests is to add a String constructor with description as follows:

let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"

Obviously, the results is explicit but also very very cumbersome in my opinion. Is there a better option? Do I have to fix all those warning or better wait for the next beta?

Body:
After updating to Xcode 8.3 and getting a lot of warning messages, I came up with the following that is more like the original output behavior, easy to add in, reduces the verboseness of using "String(describing:)" both in code and output.

Basically, add an Optional extension that gives a String describing the thing in the optional, or simply "nil" if not set.  In addition, if the thing in the optional is a String, put it in quotes.

extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}

And usage in a playground:

var s : String?
var i : Int?
var d : Double?

var mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = nil    i = nil   d = nil"

d = 3
i = 5
s = ""
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = ""    i = 5   d = 3.0"

s = "Test"
d = nil
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = "Test"    i = 5   d = nil"

Thanks for help from following link:

check-if-variable-is-an-optional-and-what-type-it-wraps


问:
Removing an object is causing freezes
[For clarification, 'monsters' is a list of NPCs that when shot by an object 'bullet' are removed from the list. ]

Error at start:

```<code>W/System.err: java.util.ConcurrentModificationException
W/System.err:     at java.util.ArrayList$Itr.next(ArrayList.java:831)
W/System.err:     at com.companyname.product.GameplayScene.update(GameplayScene.java:113)
//...
</code>```

I believe this means that it is trying to perform an action on something in the list that isn't there. So my question is could I please get some help identifying the point where an object is being called that isn't there, as I can't seem to find it. I know which class it is in as the first line references it for each error.

```<code>        for (Bullet bullet : player.getList())
            if (npcManager.bulletCollide(bullet)) { //checks for a collision between all npcs and all bullets
                 player.getList().remove(bullet);//npc is removed in method above

        }

       if (!gameOver) {
        npcManager.update(); //updates movement of npcs
        if (npcManager.playerCollideNPC(player)) {
            //end game
        }
    }

    for (RectNPC NPC : npcManager.getList())
        if (obstacleManager.NPCCollide(NPC)) { //checks collision between npcs and other objects
            //
        }

        int i = 0;
        //checks collisions between NPCs themselves
        while (i < (Constants.NUMBER_ENEMIES - 1)) {
            if (npcManager.getList().size() <= 1)
                return;
            if (Rect.intersects(npcManager.getList().get(i).getRectangle(), npcManager.getList().get(i + 1).getRectangle()))
                npcManager.getList().get(i).setRectangle(200);
            i += 1;
        }
    }
</code>```

(Above) I imagine the issue will be with calling something in the update (shown above) where the object is no longer available, is there an issue with any of how I am removing the NPCs?

```<code> public boolean bulletCollide(Bullet bullet) {
    for(RectNPC npc : monsters) {
        if(npc.bulletCollideNPC(bullet)) {
            monsters.remove(npc);
            monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
            return true;
        }
    }
    return false;
}
</code>```

(Above) Code where I am removing the NPC, I've included incase it is helpful - however it does do what it's meant to so I don't believe this is the problem.

My main question is, is there anything here that would be causing this error (the game stopping for a few frames and giving the error at the top) - or is there something/somewhere else in specific I should be looking at? Also I know some of my syntax isn't great, I apologise it's my first Java project.

Current Iterators:

```<code>for(Iterator<RectNPC> iterator = monsters.iterator(); iterator.hasNext();) {
        if(iterator.next().bulletCollideNPC(bullet)) {
            iterator.remove();
            monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
            return true;
        }
    }
</code>```

and

```<code>for (Iterator<Bullet> iterator = player.getList().iterator(); iterator.hasNext(); ) {
            if (npcManager.bulletCollide(iterator.next())) {
                iterator.remove();
                //
            }
        }
</code>```

答:
In java, you cannot do for( T variable : collection ) { collection.remove( variable ); } In other words, you cannot be removing items from a collection which is being iterated with a for loop.  It will result in a ConcurrentModificationException.  Google for "java fail-fast iterator" for more information about why and how.

You have two options:

Collect in a temporary list all the monsters that are to be removed, then once you are done iterating over the main list, iterate once more through the temporary list to remove them from the main list.  The point is that you are not going to be removing from the same list that you are iterating.

Instead of a "foreach" (for) loop, use an actual iterator, and when you want to remove an item, remove it by invoking the iterator's remove() method, not the containing collection's remove() method.  The iterator's remove() method does the necessary tricks to prevent a ConcurrentModificationException from being thrown.

Title: Removing an object is causing freezes

Body:
[For clarification, 'monsters' is a list of NPCs that when shot by an object 'bullet' are removed from the list. ]

Error at start:

W/System.err: java.util.ConcurrentModificationException
W/System.err:     at java.util.ArrayList$Itr.next(ArrayList.java:831)
W/System.err:     at com.companyname.product.GameplayScene.update(GameplayScene.java:113)
//...

I believe this means that it is trying to perform an action on something in the list that isn't there. So my question is could I please get some help identifying the point where an object is being called that isn't there, as I can't seem to find it. I know which class it is in as the first line references it for each error.

        for (Bullet bullet : player.getList())
            if (npcManager.bulletCollide(bullet)) { //checks for a collision between all npcs and all bullets
                 player.getList().remove(bullet);//npc is removed in method above

        }

       if (!gameOver) {
        npcManager.update(); //updates movement of npcs
        if (npcManager.playerCollideNPC(player)) {
            //end game
        }
    }

    for (RectNPC NPC : npcManager.getList())
        if (obstacleManager.NPCCollide(NPC)) { //checks collision between npcs and other objects
            //
        }

        int i = 0;
        //checks collisions between NPCs themselves
        while (i < (Constants.NUMBER_ENEMIES - 1)) {
            if (npcManager.getList().size() <= 1)
                return;
            if (Rect.intersects(npcManager.getList().get(i).getRectangle(), npcManager.getList().get(i + 1).getRectangle()))
                npcManager.getList().get(i).setRectangle(200);
            i += 1;
        }
    }

(Above) I imagine the issue will be with calling something in the update (shown above) where the object is no longer available, is there an issue with any of how I am removing the NPCs?

 public boolean bulletCollide(Bullet bullet) {
    for(RectNPC npc : monsters) {
        if(npc.bulletCollideNPC(bullet)) {
            monsters.remove(npc);
            monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
            return true;
        }
    }
    return false;
}

(Above) Code where I am removing the NPC, I've included incase it is helpful - however it does do what it's meant to so I don't believe this is the problem.

My main question is, is there anything here that would be causing this error (the game stopping for a few frames and giving the error at the top) - or is there something/somewhere else in specific I should be looking at? Also I know some of my syntax isn't great, I apologise it's my first Java project.

Current Iterators:

for(Iterator<RectNPC> iterator = monsters.iterator(); iterator.hasNext();) {
        if(iterator.next().bulletCollideNPC(bullet)) {
            iterator.remove();
            monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
            return true;
        }
    }

and

for (Iterator<Bullet> iterator = player.getList().iterator(); iterator.hasNext(); ) {
            if (npcManager.bulletCollide(iterator.next())) {
                iterator.remove();
                //
            }
        }


问:
Terraform / config: unknown variable referenced
I have .tf file in pt-plan directory with the following express:

```<code>${lookup(var.prod, var.pt)}
</code>```

In addition I have the following terraform.tfvars file:

```<code>variable "prod" {
  type = "map"
  default = {
    pt = "https://pt:9200"
  }
}
</code>```

When I run:

/terraform plan pt-plan, it writes:

```<code>unknown variable referenced: 'prod'. define it with 'variable' blocks
unknown variable referenced: 'pt'. define it with 'variable' blocks
</code>```

What I do wrong?

答:
Try this syntax:

"${var.prod["pt"]}"

Or this:

"${lookup(var.prod, "pt")}"

instead of:

"${lookup(var.prod, var.pt)}"

the [var.] before 'pt' above is redundant, also 'pt' must be quoted.

Body:
I have .tf file in pt-plan directory with the following express:

${lookup(var.prod, var.pt)}

In addition I have the following terraform.tfvars file:

variable "prod" {
  type = "map"
  default = {
    pt = "https://pt:9200"
  }
}

When I run:

/terraform plan pt-plan, it writes:

unknown variable referenced: 'prod'. define it with 'variable' blocks
unknown variable referenced: 'pt'. define it with 'variable' blocks

What I do wrong?


答:
the reference operator sends back a pointer to the memory address which contains the member.

Here, a1 is a class containing only firstMember, so the in-memory structure is just that element: the beginning of a1 in memory is the same as the beginning of firstMember.

Title: pointer to object == pointer to first member?


问:
How to override SqlCommand to grab generated TSQL
Is there any way to intercept the SQL that's generated by SqlCommand?

I currently have a method that will execute a stored procedure:

```<code>public int ExecSP(string spName, params objec[] params)
{
     using (SqlConnection con = new SqlConnection("AdventureWorks"))
     using (SqlCommand cmd = new SqlCommand(spName, con))
     {
         cmd.CommandType = CommandType.StoredProcedure;

        //..calls method to add params and values to cmd object

        con.Open();
        return cmd.ExecuteNonQuery();
     }
}
</code>```

When I use this to call the following:

ExecSP("HumanResources.uspUpdateEmployeePersonalInfo", 1, "295847284", new DateTime(1963, 3, 2), "S", "M");`

I get the following in SQLProfiler:

```<code>exec HumanResources.uspUpdateEmployeePersonalInfo @BusinessEntityID=1,@NationalIDNumber=N'295847284',@BirthDate='1963-03-02 00:00:00',@MaritalStatus=N'S',@Gender=N'M'
</code>```

What I would like to do is intercept that SQL command so that I may add a comment to the end of it that will contain some pertinent information so that it looks like:

```<code>exec HumanResources.uspUpdateEmployeePersonalInfo @BusinessEntityID=1,@NationalIDNumber=N'295847284',@BirthDate='1963-03-02 00:00:00',@MaritalStatus=N'S',@Gender=N'M' -- IMPORTANT INFORMATION HERE
</code>```

I can't change the CommandType to Text and I can't add an extra parameter to the stored procedure. I tried looking at these other questions but had no luck:

Can I override SqlCommand functions?

SqlCommand to T-SQL

答:
In the case of CommandType = CommandType.StoredProcedure, this isn't possible.

Why? The SQL you see in SQL Profiler isn't generated by the client. :-/

When SqlCommand executes a CommandType.StoredProcedure command, it sends SQL Server an execute remote procedure call message with the name of the stored procedure and a data structure containing the parameters.

The TextData SQL Profiler displays for the RPC:Starting/RPC:Completed events is generated server-side. Since this text isn't generated client-side, it's not possible to modify it client-side.

Body:
Is there any way to intercept the SQL that's generated by SqlCommand?

I currently have a method that will execute a stored procedure:

public int ExecSP(string spName, params objec[] params)
{
     using (SqlConnection con = new SqlConnection("AdventureWorks"))
     using (SqlCommand cmd = new SqlCommand(spName, con))
     {
         cmd.CommandType = CommandType.StoredProcedure;

        //..calls method to add params and values to cmd object

        con.Open();
        return cmd.ExecuteNonQuery();
     }
}

When I use this to call the following:

ExecSP("HumanResources.uspUpdateEmployeePersonalInfo", 1, "295847284", new DateTime(1963, 3, 2), "S", "M");`

I get the following in SQLProfiler:

exec HumanResources.uspUpdateEmployeePersonalInfo @BusinessEntityID=1,@NationalIDNumber=N'295847284',@BirthDate='1963-03-02 00:00:00',@MaritalStatus=N'S',@Gender=N'M'

What I would like to do is intercept that SQL command so that I may add a comment to the end of it that will contain some pertinent information so that it looks like:

exec HumanResources.uspUpdateEmployeePersonalInfo @BusinessEntityID=1,@NationalIDNumber=N'295847284',@BirthDate='1963-03-02 00:00:00',@MaritalStatus=N'S',@Gender=N'M' -- IMPORTANT INFORMATION HERE

I can't change the CommandType to Text and I can't add an extra parameter to the stored procedure. I tried looking at these other questions but had no luck:

Can I override SqlCommand functions?

SqlCommand to T-SQL


问:
Mac default Python
How can i set the python on my mac back to the default reference location? When I to do

```<code>sudo easy_install virtualenv
</code>```

I get the following results

```<code>dyld: Library not loaded: @rpath/Python
  Referenced from: /Users/a1ctesta/Library/Enthought/Canopy_64bit/User/bin/python
  Reason: image not found
</code>```

I do not have Canopy installed any longer so I wanted to restore this back to the original reference that came on the computer.

答:
I had this issue as well. If you edit your ~/.bash_profile it will permanently fix the issue.

In terminal enter

```<code>nano ~/.bash_profile
</code>```

It will then show something along the lines of

```<code># Setting PATH for Python 2.7
# The orginal version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
export PATH

# Added by Canopy installer on 2017-03-28
# VIRTUAL_ENV_DISABLE_PROMPT can be set to '' to make the bash prompt show that Canopy is active, otherwise 1
alias activate_canopy="source '/Users/chrisdunstan/Library/Enthought/Canopy_64bit/User/bin/activate'"
VIRTUAL_ENV_DISABLE_PROMPT=1 source '/Users/chrisdunstan/Library/Enthought/Canopy_64bit/User/bin/activate'
</code>```

Delete everything added by the Canopy installer and press ^O to save and then ^X to close. Restart terminal and it should use the built-in python compiler.

Another solution I found was to re-install Canopy and then go to Preferences and unselect Canopy as the default python compiler.

Title: Mac default Python

Body:
How can i set the python on my mac back to the default reference location? When I to do

sudo easy_install virtualenv

I get the following results

dyld: Library not loaded: @rpath/Python
  Referenced from: /Users/a1ctesta/Library/Enthought/Canopy_64bit/User/bin/python
  Reason: image not found

I do not have Canopy installed any longer so I wanted to restore this back to the original reference that came on the computer.

Body:
I had this issue as well. If you edit your ~/.bash_profile it will permanently fix the issue.

In terminal enter

nano ~/.bash_profile

It will then show something along the lines of

# Setting PATH for Python 2.7
# The orginal version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
export PATH

# Added by Canopy installer on 2017-03-28
# VIRTUAL_ENV_DISABLE_PROMPT can be set to '' to make the bash prompt show that Canopy is active, otherwise 1
alias activate_canopy="source '/Users/chrisdunstan/Library/Enthought/Canopy_64bit/User/bin/activate'"
VIRTUAL_ENV_DISABLE_PROMPT=1 source '/Users/chrisdunstan/Library/Enthought/Canopy_64bit/User/bin/activate'

Delete everything added by the Canopy installer and press ^O to save and then ^X to close. Restart terminal and it should use the built-in python compiler.

Another solution I found was to re-install Canopy and then go to Preferences and unselect Canopy as the default python compiler.


问:
jQuery transition on class change and transition delay on paragraph
I am making a section using codepen that can be visited from here: Click Here

If you see my code, you will see that I am repeating the same thing every time now want to improve my JS so that it's less and perform well. Please advice what can be done in order to improve this code.

Thanks in advance.

Regards,
IMMAD

// Here is the Js

```<code>$(".div1").on({
    mouseenter: function() {
        console.log('hello');
        $('.div2, .div3').addClass('widthlow');
        $('.div1').addClass('widthmax');
        $(".widthmax p").addClass('opacity');
    },
    mouseleave: function() {
        $('.div2, .div3').removeClass('widthlow');
        $('.div1').removeClass('widthmax');
        $('.div1 p').removeClass('opacity');
    }
});

$(".div2").on({
    mouseenter: function() {
        console.log('hello');
        $('.div1, .div3').addClass('widthlow');
        $('.div2').addClass('widthmax');
        $('.smoky').addClass('opacity');
    },
    mouseleave: function() {
        $('.div1, .div3').removeClass('widthlow');
        $('.div2').removeClass('widthmax');
        $('.smoky').removeClass('opacity');
    }
});

$(".div3").on({
    mouseenter: function() {
        console.log('hello');
        $('.div1, .div2').addClass('widthlow');
        $('.div3').addClass('widthmax');
        $('.smoky').addClass('opacity');
    },
    mouseleave: function() {
        $('.div1, .div2').removeClass('widthlow');
        $('.div3').removeClass('widthmax');
        $('.smoky').removeClass('opacity');
    }
});
</code>```

答: I added a little opacity animation and changed transitions to ease-in-out here. Looks a little better? http://codepen.io/anon/pen/oZaoZx

Body:
I am making a section using codepen that can be visited from here: Click Here

If you see my code, you will see that I am repeating the same thing every time now want to improve my JS so that it's less and perform well. Please advice what can be done in order to improve this code.

Thanks in advance.

Regards,
IMMAD

// Here is the Js

$(".div1").on({
    mouseenter: function() {
        console.log('hello');
        $('.div2, .div3').addClass('widthlow');
        $('.div1').addClass('widthmax');
        $(".widthmax p").addClass('opacity');
    },
    mouseleave: function() {
        $('.div2, .div3').removeClass('widthlow');
        $('.div1').removeClass('widthmax');
        $('.div1 p').removeClass('opacity');
    }
});

$(".div2").on({
    mouseenter: function() {
        console.log('hello');
        $('.div1, .div3').addClass('widthlow');
        $('.div2').addClass('widthmax');
        $('.smoky').addClass('opacity');
    },
    mouseleave: function() {
        $('.div1, .div3').removeClass('widthlow');
        $('.div2').removeClass('widthmax');
        $('.smoky').removeClass('opacity');
    }
});

$(".div3").on({
    mouseenter: function() {
        console.log('hello');
        $('.div1, .div2').addClass('widthlow');
        $('.div3').addClass('widthmax');
        $('.smoky').addClass('opacity');
    },
    mouseleave: function() {
        $('.div1, .div2').removeClass('widthlow');
        $('.div3').removeClass('widthmax');
        $('.smoky').removeClass('opacity');
    }
});


问:
FileSystemWatcher not firing Events from Office file changes
I'm trying to use a FileSystemWatcher to mirror two directories, but I've hit a hurdle with Office files. I don't seem to be able to get an event when a document/spreadsheet etc changes. This isn't to say that I'm not receiving any events however, as I understand the office apps frequently use temp files.

Here's an example of what I'm seeing, using the following code:

```<code>// Create the new watcher and hook up events
FileSystemWatcher fsw = new FileSystemWatcher(source);
fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.Security;
fsw.IncludeSubdirectories = true;
fsw.InternalBufferSize = 64000;
fsw.Renamed += Fsw_Renamed;
fsw.Error += Fsw_Error;
fsw.Deleted += (o, e) => OnChange(pair, e);
fsw.Changed += (o, e) => OnChange(pair, e);
fsw.Created += (o, e) => OnChange(pair, e);
fsw.EnableRaisingEvents = true;
</code>```

The events that I see are as follows (using breakpoints in onChange, Fsw_Error and Fsw_Renamed):

I create the word document

Created New Microsoft Word Document.docx

Changed New Microsoft Word Document.docx

I open the word document

Created ~$w Microsoft Word Document.docx

Changed ~$w Microsoft Word Document.docx

Changed ~$w Microsoft Word Document.docx

I edit and then save the word document

Created ~WRD0000.tmp

I make more edits and then saves the word document

No events...

I really don't quite understand how this is working. The original docx file is being updated, but I'm not seeing any rename events or modifications. Is there something I'm missing here?

答:
The documentation here indicates the Filter property needs to be set

Even the example below the documentation seems to explicitly set the Filter property

Quoted from there

To watch for changes in all files, set the Filter property to an empty string ("") or use wildcards ("."). To watch a specific file, set the Filter property to the file name. For example, to watch for changes in the file MyDoc.txt, set the Filter property to "MyDoc.txt". You can also watch for changes in a certain type of file. For example, to watch for changes in text files, set the Filter property to "*.txt".

In your case you could try setting it to *.docx

Update

From the comments below, its clear the above didnt work.

I wrote a simple console program like so

```<code>class Program
{
    static void Main(string[] args)
    {
        var source = "D:\\temp\\folder";

        // Create the new watcher and hook up events
        var fsw = new FileSystemWatcher(source)
        {
            NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.Security,
            IncludeSubdirectories = true,
            InternalBufferSize = 64000
        };

        using (fsw)
        {
            fsw.Renamed += (o, e) => Console.WriteLine($"{e.OldFullPath} renamed to {e.FullPath}");
            fsw.Error += (o, e) => Console.WriteLine($"{e}");
            fsw.Deleted += (o, e) => Console.WriteLine($"{e.FullPath} deleted");
            fsw.Changed += (o, e) => Console.WriteLine($"{e.FullPath} changed");
            fsw.Created += (o, e) => Console.WriteLine($"{e.FullPath} created");
            fsw.EnableRaisingEvents = true;

            Console.WriteLine("Ready. Press 'Q' to exit");
            while (Console.ReadKey().KeyChar != 'Q')
            {
            }
        }
    }
}
</code>```

which produces the following output

at launch

```<code>Ready. Press 'Q' to exit
</code>```

creating a new document

```<code>D:\temp\folder\Doc1.docx created
D:\temp\folder\Doc1.docx deleted
D:\temp\folder\Doc1.docx created
D:\temp\folder\~WRD0000.tmp created
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\Doc1.docx renamed to D:\temp\folder\~WRL0001.tmp
D:\temp\folder\~WRD0000.tmp renamed to D:\temp\folder\Doc1.docx
D:\temp\folder\~WRL0001.tmp changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\~WRL0001.tmp changed
D:\temp\folder\~$Doc1.docx created
D:\temp\folder\~$Doc1.docx changed
D:\temp\folder\~WRL0001.tmp deleted
</code>```

editing the document

```<code>D:\temp\folder\~WRD0002.tmp created
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\Doc1.docx renamed to D:\temp\folder\~WRL0003.tmp
D:\temp\folder\~WRD0002.tmp renamed to D:\temp\folder\Doc1.docx
D:\temp\folder\~WRL0003.tmp changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\~WRL0003.tmp changed
D:\temp\folder\~WRL0003.tmp deleted
</code>```

more edits

```<code>D:\temp\folder\~WRD0004.tmp created
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\Doc1.docx renamed to D:\temp\folder\~WRL0005.tmp
D:\temp\folder\~WRD0004.tmp renamed to D:\temp\folder\Doc1.docx
D:\temp\folder\~WRL0005.tmp changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\~WRL0005.tmp changed
D:\temp\folder\~WRL0005.tmp deleted
</code>```

close word

```<code>D:\temp\folder\~$Doc1.docx deleted
</code>```

delete from explorer

```<code>D:\temp\folder\Doc1.docx deleted
</code>```

If you run this sample code and see similar (and expected) output like I did,
you could modify your code to use this.

Body:
I'm trying to use a FileSystemWatcher to mirror two directories, but I've hit a hurdle with Office files. I don't seem to be able to get an event when a document/spreadsheet etc changes. This isn't to say that I'm not receiving any events however, as I understand the office apps frequently use temp files.

Here's an example of what I'm seeing, using the following code:

// Create the new watcher and hook up events
FileSystemWatcher fsw = new FileSystemWatcher(source);
fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.Security;
fsw.IncludeSubdirectories = true;
fsw.InternalBufferSize = 64000;
fsw.Renamed += Fsw_Renamed;
fsw.Error += Fsw_Error;
fsw.Deleted += (o, e) => OnChange(pair, e);
fsw.Changed += (o, e) => OnChange(pair, e);
fsw.Created += (o, e) => OnChange(pair, e);
fsw.EnableRaisingEvents = true;

The events that I see are as follows (using breakpoints in onChange, Fsw_Error and Fsw_Renamed):

I create the word document

Created New Microsoft Word Document.docx

Changed New Microsoft Word Document.docx

I open the word document

Created ~$w Microsoft Word Document.docx

Changed ~$w Microsoft Word Document.docx

Changed ~$w Microsoft Word Document.docx

I edit and then save the word document

Created ~WRD0000.tmp

I make more edits and then saves the word document

No events...

I really don't quite understand how this is working. The original docx file is being updated, but I'm not seeing any rename events or modifications. Is there something I'm missing here?

Body:
The documentation here indicates the Filter property needs to be set

Even the example below the documentation seems to explicitly set the Filter property

Quoted from there

To watch for changes in all files, set the Filter property to an empty string ("") or use wildcards ("."). To watch a specific file, set the Filter property to the file name. For example, to watch for changes in the file MyDoc.txt, set the Filter property to "MyDoc.txt". You can also watch for changes in a certain type of file. For example, to watch for changes in text files, set the Filter property to "*.txt".

In your case you could try setting it to *.docx

Update

From the comments below, its clear the above didnt work.

I wrote a simple console program like so

class Program
{
    static void Main(string[] args)
    {
        var source = "D:\\temp\\folder";

        // Create the new watcher and hook up events
        var fsw = new FileSystemWatcher(source)
        {
            NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.Security,
            IncludeSubdirectories = true,
            InternalBufferSize = 64000
        };

        using (fsw)
        {
            fsw.Renamed += (o, e) => Console.WriteLine($"{e.OldFullPath} renamed to {e.FullPath}");
            fsw.Error += (o, e) => Console.WriteLine($"{e}");
            fsw.Deleted += (o, e) => Console.WriteLine($"{e.FullPath} deleted");
            fsw.Changed += (o, e) => Console.WriteLine($"{e.FullPath} changed");
            fsw.Created += (o, e) => Console.WriteLine($"{e.FullPath} created");
            fsw.EnableRaisingEvents = true;

            Console.WriteLine("Ready. Press 'Q' to exit");
            while (Console.ReadKey().KeyChar != 'Q')
            {
            }
        }
    }
}

which produces the following output

at launch

Ready. Press 'Q' to exit

creating a new document

D:\temp\folder\Doc1.docx created
D:\temp\folder\Doc1.docx deleted
D:\temp\folder\Doc1.docx created
D:\temp\folder\~WRD0000.tmp created
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\~WRD0000.tmp changed
D:\temp\folder\Doc1.docx renamed to D:\temp\folder\~WRL0001.tmp
D:\temp\folder\~WRD0000.tmp renamed to D:\temp\folder\Doc1.docx
D:\temp\folder\~WRL0001.tmp changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\~WRL0001.tmp changed
D:\temp\folder\~$Doc1.docx created
D:\temp\folder\~$Doc1.docx changed
D:\temp\folder\~WRL0001.tmp deleted

editing the document

D:\temp\folder\~WRD0002.tmp created
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\~WRD0002.tmp changed
D:\temp\folder\Doc1.docx renamed to D:\temp\folder\~WRL0003.tmp
D:\temp\folder\~WRD0002.tmp renamed to D:\temp\folder\Doc1.docx
D:\temp\folder\~WRL0003.tmp changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\~WRL0003.tmp changed
D:\temp\folder\~WRL0003.tmp deleted

more edits

D:\temp\folder\~WRD0004.tmp created
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\~WRD0004.tmp changed
D:\temp\folder\Doc1.docx renamed to D:\temp\folder\~WRL0005.tmp
D:\temp\folder\~WRD0004.tmp renamed to D:\temp\folder\Doc1.docx
D:\temp\folder\~WRL0005.tmp changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\Doc1.docx changed
D:\temp\folder\~WRL0005.tmp changed
D:\temp\folder\~WRL0005.tmp deleted

close word

D:\temp\folder\~$Doc1.docx deleted

delete from explorer

D:\temp\folder\Doc1.docx deleted

If you run this sample code and see similar (and expected) output like I did,
you could modify your code to use this.