问:
Checking to see if String variable was modified or not, if not no Toast. But Toast is appearing always
Having a slight problem with some logic that I am trying to implement to test whether a String variable has been modified or not. So in EditProfileActivity the user has the option of changing their name,username, and bio. Only thing is that when they enter the EditProfileActivity, if the username was Not changed, then when the user clicks on the checkmark to save changes it checks to see if the username already exists in the database. If so, a Toast message comes up indicating that that username already exist, and for you to pick another one.

The problem is that if the user doesn't change anything, and clicks the checkmark the Toast message pops up anyways, because that username that the user didn't change exists in the database obviously.

How can I change the code or implement logic so that even if the user clicks in the checkmark, and if the username wasn't changed the Toast message doesn't pop up and just the Activity finish();?

I tried implementing another condition in the updateProfile(); method to the if statement to check whether the original username was the same as the final username, but didn't work... I'm pretty sure that's where the I have to add another condition to check whether or not it's the same username. This is the logic that I added, but didn't work:

&& !mUsername.getText().toString().toLowerCase().equals(mUsername1.toLowerCase()).

EditProfileActivity

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

    ImageView mClose, mCheckmark, mImageProfile;
    TextView mChangePhoto;
    MaterialEditText mName, mUsername, mBio;

    private String mUsername1;

    FirebaseUser mFirebaseUser;

    private Uri mImageUri;
    StorageReference mStorageReference;

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

        mClose = findViewById(R.id.close);
        mCheckmark = findViewById(R.id.post_checkmark);
        mImageProfile = findViewById(R.id.image_profile);
        mChangePhoto = findViewById(R.id.text_view_change_profile_picture);
        mName = findViewById(R.id.fullname);
        mUsername = findViewById(R.id.username);
        mBio = findViewById(R.id.bio);

        mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
        mStorageReference = FirebaseStorage.getInstance().getReference("uploads");

        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(mFirebaseUser.getUid());
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                User user = dataSnapshot.getValue(User.class);
                if (user != null) {
                    mName.setText(user.getFullname());
                    mUsername.setText(user.getUsername().toLowerCase());
                    mBio.setText(user.getBio());
                    Glide.with(getApplicationContext()).load(user.getImageurl()).into(mImageProfile);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        mClose.setOnClickListener(v -> new AlertDialog.Builder(EditProfileActivity.this)
                .setTitle("Exit without saving changes?")
                .setPositiveButton("Yes", (dialog, which) -> {
                    finish();
                }).setNegativeButton("No", null).show());

        mChangePhoto.setOnClickListener(v -> CropImage.activity()
                .setAspectRatio(1, 1)
                .setCropShape(CropImageView.CropShape.OVAL)
                .start(EditProfileActivity.this));

        mImageProfile.setOnClickListener(v -> CropImage.activity()
                .setAspectRatio(1, 1)
                .setCropShape(CropImageView.CropShape.OVAL)
                .start(EditProfileActivity.this));

        mCheckmark.setOnClickListener(v -> {

            String str_name = mName.getText().toString();
            String str_username = mUsername.getText().toString();
            String str_bio = mBio.getText().toString();

            if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_bio) || TextUtils.isEmpty(str_name)) {
                Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show();
            } else if (str_username.length() > 20) {
                Toast.makeText(this, "Username cannot contain more than 20 characters", Toast.LENGTH_SHORT).show();
            } else {
                updateProfile(mName.getText().toString(), mUsername.getText().toString().toLowerCase(), mBio.getText().toString());
            }
        });
    }

    private void updateProfile(String fullname, String username, String bio) {
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(mFirebaseUser.getUid());

        mUsername1 = username.replaceAll("\\s+", "");
        mUsername1 = username.replaceAll("[^\\w]", "");

        DatabaseReference reference1 = FirebaseDatabase.getInstance().getReference("Users");
        reference1.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                boolean ifUserNameExists = false;
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    User user = snapshot.getValue(User.class);
                    if (user != null) {
                        if (user.getUsername().equals(mUsername1.toLowerCase())) {
                            Toast.makeText(EditProfileActivity.this, "That username has already been taken. Try another", Toast.LENGTH_SHORT).show();
                            ifUserNameExists = true;
                        }
                    }
                }

                if (!ifUserNameExists) {
                    HashMap<String, Object> hashMap = new HashMap<>();
                    hashMap.put("fullname", fullname);
                    hashMap.put("username", mUsername1.toLowerCase());
                    hashMap.put("bio", bio);

                    reference.updateChildren(hashMap);
                    Toast.makeText(EditProfileActivity.this, "Username has been changed", Toast.LENGTH_LONG).show();
                    finish();
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }
</code>```

UPDATED

```<code> mCheckmark.setOnClickListener(v -> {

        String str_name = mName.getText().toString();
        String str_username = mUsername.getText().toString();
            String str_bio = mBio.getText().toString();

            if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_bio) || TextUtils.isEmpty(str_name)) {
                Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show();
            } else if (str_username.length() > 20) {
                Toast.makeText(this, "Username cannot contain more than 20 characters", Toast.LENGTH_SHORT).show();
            } else if (!mUser.getUsername().equals(mUsername.getText().toString().toLowerCase()) && !mUser.getFullname().equals(mName.getText().toString()) && !mUser.getBio().equals(mBio.getText().toString())) {
                updateProfile(mName.getText().toString(), mUsername.getText().toString().toLowerCase(), mBio.getText().toString());
            }
        });
</code>```

答:
Would this solution work for you?

```<code>private User user;
</code>```

When user is fetched from database save user:

```<code>user = dataSnapshot.getValue(User.class);
</code>```

And before calling updateProfile() check if username is equal to user.username

```<code>if(!user.username.equals(mUsername.getText().toString())){
    updateProfile(mName.getText().toString(),
    mUsername.getText().toString().toLowerCase(), mBio.getText().toString());
}
</code>```

Like this you will not make unnecessary calls to Firebase.

Body:
Having a slight problem with some logic that I am trying to implement to test whether a String variable has been modified or not. So in EditProfileActivity the user has the option of changing their name,username, and bio. Only thing is that when they enter the EditProfileActivity, if the username was Not changed, then when the user clicks on the checkmark to save changes it checks to see if the username already exists in the database. If so, a Toast message comes up indicating that that username already exist, and for you to pick another one.

The problem is that if the user doesn't change anything, and clicks the checkmark the Toast message pops up anyways, because that username that the user didn't change exists in the database obviously.

How can I change the code or implement logic so that even if the user clicks in the checkmark, and if the username wasn't changed the Toast message doesn't pop up and just the Activity finish();?

I tried implementing another condition in the updateProfile(); method to the if statement to check whether the original username was the same as the final username, but didn't work... I'm pretty sure that's where the I have to add another condition to check whether or not it's the same username. This is the logic that I added, but didn't work:

&& !mUsername.getText().toString().toLowerCase().equals(mUsername1.toLowerCase()).

EditProfileActivity

public class EditProfileActivity extends AppCompatActivity {

    ImageView mClose, mCheckmark, mImageProfile;
    TextView mChangePhoto;
    MaterialEditText mName, mUsername, mBio;

    private String mUsername1;

    FirebaseUser mFirebaseUser;

    private Uri mImageUri;
    StorageReference mStorageReference;

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

        mClose = findViewById(R.id.close);
        mCheckmark = findViewById(R.id.post_checkmark);
        mImageProfile = findViewById(R.id.image_profile);
        mChangePhoto = findViewById(R.id.text_view_change_profile_picture);
        mName = findViewById(R.id.fullname);
        mUsername = findViewById(R.id.username);
        mBio = findViewById(R.id.bio);

        mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
        mStorageReference = FirebaseStorage.getInstance().getReference("uploads");

        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(mFirebaseUser.getUid());
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                User user = dataSnapshot.getValue(User.class);
                if (user != null) {
                    mName.setText(user.getFullname());
                    mUsername.setText(user.getUsername().toLowerCase());
                    mBio.setText(user.getBio());
                    Glide.with(getApplicationContext()).load(user.getImageurl()).into(mImageProfile);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        mClose.setOnClickListener(v -> new AlertDialog.Builder(EditProfileActivity.this)
                .setTitle("Exit without saving changes?")
                .setPositiveButton("Yes", (dialog, which) -> {
                    finish();
                }).setNegativeButton("No", null).show());

        mChangePhoto.setOnClickListener(v -> CropImage.activity()
                .setAspectRatio(1, 1)
                .setCropShape(CropImageView.CropShape.OVAL)
                .start(EditProfileActivity.this));

        mImageProfile.setOnClickListener(v -> CropImage.activity()
                .setAspectRatio(1, 1)
                .setCropShape(CropImageView.CropShape.OVAL)
                .start(EditProfileActivity.this));

        mCheckmark.setOnClickListener(v -> {

            String str_name = mName.getText().toString();
            String str_username = mUsername.getText().toString();
            String str_bio = mBio.getText().toString();

            if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_bio) || TextUtils.isEmpty(str_name)) {
                Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show();
            } else if (str_username.length() > 20) {
                Toast.makeText(this, "Username cannot contain more than 20 characters", Toast.LENGTH_SHORT).show();
            } else {
                updateProfile(mName.getText().toString(), mUsername.getText().toString().toLowerCase(), mBio.getText().toString());
            }
        });
    }

    private void updateProfile(String fullname, String username, String bio) {
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(mFirebaseUser.getUid());

        mUsername1 = username.replaceAll("\\s+", "");
        mUsername1 = username.replaceAll("[^\\w]", "");

        DatabaseReference reference1 = FirebaseDatabase.getInstance().getReference("Users");
        reference1.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                boolean ifUserNameExists = false;
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    User user = snapshot.getValue(User.class);
                    if (user != null) {
                        if (user.getUsername().equals(mUsername1.toLowerCase())) {
                            Toast.makeText(EditProfileActivity.this, "That username has already been taken. Try another", Toast.LENGTH_SHORT).show();
                            ifUserNameExists = true;
                        }
                    }
                }

                if (!ifUserNameExists) {
                    HashMap<String, Object> hashMap = new HashMap<>();
                    hashMap.put("fullname", fullname);
                    hashMap.put("username", mUsername1.toLowerCase());
                    hashMap.put("bio", bio);

                    reference.updateChildren(hashMap);
                    Toast.makeText(EditProfileActivity.this, "Username has been changed", Toast.LENGTH_LONG).show();
                    finish();
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }

UPDATED

 mCheckmark.setOnClickListener(v -> {

        String str_name = mName.getText().toString();
        String str_username = mUsername.getText().toString();
            String str_bio = mBio.getText().toString();

            if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_bio) || TextUtils.isEmpty(str_name)) {
                Toast.makeText(this, "Please fill in all fields", Toast.LENGTH_SHORT).show();
            } else if (str_username.length() > 20) {
                Toast.makeText(this, "Username cannot contain more than 20 characters", Toast.LENGTH_SHORT).show();
            } else if (!mUser.getUsername().equals(mUsername.getText().toString().toLowerCase()) && !mUser.getFullname().equals(mName.getText().toString()) && !mUser.getBio().equals(mBio.getText().toString())) {
                updateProfile(mName.getText().toString(), mUsername.getText().toString().toLowerCase(), mBio.getText().toString());
            }
        });

Body:
Would this solution work for you?

private User user;

When user is fetched from database save user:

user = dataSnapshot.getValue(User.class);

And before calling updateProfile() check if username is equal to user.username

if(!user.username.equals(mUsername.getText().toString())){
    updateProfile(mName.getText().toString(),
    mUsername.getText().toString().toLowerCase(), mBio.getText().toString());
}

Like this you will not make unnecessary calls to Firebase.


来源: stackexchange

问:
How to sink structured records directly from KSQL into a connector (e.g., InfluxDB)
I'm trying to sink data directly from KSQL into InfluxDB (or any other connector that would require definitions). I'm able to get things working in the simple case, but I start having trouble when the schema requires complex types. (I.e., tags for InfuxDB).

Here's an example of my stream/schema:

```<code> Field    | Type
-------------------------------------------------------------------
 ROWKEY   | VARCHAR(STRING)  (primary key)
 FIELD_1  | VARCHAR(STRING)
 FIELD_2  | VARCHAR(STRING)
 FIELD_3  | VARCHAR(STRING)
 FIELD_4  | DOUBLE
 TAGS     | MAP<STRING, VARCHAR(STRING)>
</code>```

If I manually create an AVRO schema and populate the records from a simple producer, I can get through the getting started guide here and embed the tags for InfluxDB.

However, when I move to KSQL, if I try to sink the AVRO stream directly into InfluxDB, I lose information on the complex types (tags). I notice the warning from this blog post, "Warning ksqlDB/KSQL cannot yet write data in an Avro format that is compatible with this connector"

Next, I try converting the AVRO stream into JSON format, but now I understand that I would have to specify the schema in each record, similar to what this question is posing. I haven't been able to convert an AVRO stream into a JSON stream and embed the schema and payload at the same time.

Finally, I see the "jiggling solution" with kafkacat, but this would force me to dump records out from KSQL into kafkacat, and then back into Kafka before finally arriving at Influx.

Is there a method to sink complex records directly from KSQL in either JSON or AVRO format into a connector?

答:
I would imagine the reason ksqlDB can't yet output the AVRO data in the format InfluxDB requires is because it won't output the TAGS field as an Avro map type due to Avro maps requiring a non-null key and the SQL MAP<STRING, STRING> type allowing null keys.  Hence ksqlDB serializes the map as an Avro array of key-value entries.

To get something working with Avro you'll need either:

Support for non-null types: https://github.com/confluentinc/ksql/issues/4436, or

Support for using existing Avro schema: https://github.com/confluentinc/ksql/issues/3634

Please feel free to up-vote / comment on these issues to raise their profiles.

Previously, a JSON based solution would not of worked because, as you've pointed out, the connector requires the JSON schema embedded in the payload. However, the most recent version of Confluent Platform / Schema Registry supports JSON schemas in the Schema Registry.  Hence, while I haven't tried it, upgrading to the latest CP version may mean a JSON based solution will work. If not, it is probably work raise a Jira/Github ticket to get the appropriate component upgraded for this to work.

ContentLicense: CC BY-SA 4.0

Body:
I'm trying to sink data directly from KSQL into InfluxDB (or any other connector that would require definitions). I'm able to get things working in the simple case, but I start having trouble when the schema requires complex types. (I.e., tags for InfuxDB).

Here's an example of my stream/schema:

 Field    | Type
-------------------------------------------------------------------
 ROWKEY   | VARCHAR(STRING)  (primary key)
 FIELD_1  | VARCHAR(STRING)
 FIELD_2  | VARCHAR(STRING)
 FIELD_3  | VARCHAR(STRING)
 FIELD_4  | DOUBLE
 TAGS     | MAP<STRING, VARCHAR(STRING)>

If I manually create an AVRO schema and populate the records from a simple producer, I can get through the getting started guide here and embed the tags for InfluxDB.

However, when I move to KSQL, if I try to sink the AVRO stream directly into InfluxDB, I lose information on the complex types (tags). I notice the warning from this blog post, "Warning ksqlDB/KSQL cannot yet write data in an Avro format that is compatible with this connector"

Next, I try converting the AVRO stream into JSON format, but now I understand that I would have to specify the schema in each record, similar to what this question is posing. I haven't been able to convert an AVRO stream into a JSON stream and embed the schema and payload at the same time.

Finally, I see the "jiggling solution" with kafkacat, but this would force me to dump records out from KSQL into kafkacat, and then back into Kafka before finally arriving at Influx.

Is there a method to sink complex records directly from KSQL in either JSON or AVRO format into a connector?


问:
jQuery Twitter/Facebook like page navigation
I have really liked how the new Twitter and Facebook have saved page loads by instead loading the content dynamically through ajax. I want to start rolling this out to my sites, but I have no idea where to even start.

Twitter and Facebook now have uri's like this:
http://twitter.com/#!/messages

```<code>$(document).ready(function () {

// Check if a hash exists already and if so load that page instead.
if(window.location.hash) {
    $("div#content").load(window.location.hash);
} else {
    // load the home page.
    $("div#content").load("http://localhost/home/");
}

// Allow menu to change url hash and load new content.
$('ul#menu li a').click(function() {
    $("div#content").load(window.location.hash);
});

});
</code>```

The html for the menu I have:

```<code><ul id="menu">
    <li>< a href="#">logout</a></li>
    <li>< a href="#!/settings">settings</a></li>
    <li>< a href="#!/messages" class="notify">messages <span>3</span></a></li>
    <li>< a href="#!/profile">profile</a></li>
    <li>< a href="#!/" class="selected">home</a></li></ul>
</code>```

Any idea how Facebook or Twitter does this?

答:
This will be the best answer

hope will help others too.

ContentLicense: CC BY-SA 2.5

Body:
I have really liked how the new Twitter and Facebook have saved page loads by instead loading the content dynamically through ajax. I want to start rolling this out to my sites, but I have no idea where to even start.

Twitter and Facebook now have uri's like this:
http://twitter.com/#!/messages

$(document).ready(function () {

// Check if a hash exists already and if so load that page instead.
if(window.location.hash) {
    $("div#content").load(window.location.hash);
} else {
    // load the home page.
    $("div#content").load("http://localhost/home/");
}

// Allow menu to change url hash and load new content.
$('ul#menu li a').click(function() {
    $("div#content").load(window.location.hash);
});

});

The html for the menu I have:

logout

settings

messages 3

profile

home

Any idea how Facebook or Twitter does this?

ContentLicense: CC BY-SA 3.0


答:
one logic that could work.

when user enter EditProfileActivity you may want to save user info that you retrieved  from db into local variables. when user clicks on the checkmark to save changes you just need to compare what user input with your local variables. if they don't match, this means user have changed their profile info.

Title: Checking to see if String variable was modified or not, if not no Toast. But Toast is appearing always


问:
hackerrank new year chaos code optimization
I'm trying to optimize my solution for Hackerranks's 'New Year Chaos' problem. The gist of the problem goes like this

There's a queue of n people, labeled 1 through n, and each person can bribe the person directly in front of them to swap places and get closer to the front of the queue (in this case, index 0 of the list/array). Each person can only bribe a maximum of two times (and they cannot bribe someone who has already bribed them)

You are given the order of the people after all of the bribes have taken place and your job is to determine how many bribes took place to get to that point. For example, if you were given [3, 2, 1] then the answer would be 3 bribes (person 3 bribed person 1, 2 and person 2 bribed person 1).

My solution was, for each person I, count the number of people to the left of I that have a label greater than I (they would've had to bribe person I to get to the left of them). To complicate things (slightly), some of the test cases given would only be possible if someone bribed more than 2 times (i.e. [4, 1, 2, 3] - person 4 bribed person 3, then 2, then 1 to get to the front). If this is the case, simply output "Too chaotic"

Anyway here's the code:

```<code># n is the number of people in the list
# q is the order of the people after the bribery has taken place ex. [1, 3, 2, 5, 4]

for I in range(1, n + 1): # for each person I in the list
    index = q.index(I)
    if I - index > 3: # more than two bribes
        bribes = "Too chaotic"
        break
    for j in range(index): # for each number to the left of I, if greater than I, count it as a bribe
        if q[j] > I:
            bribes = bribes + 1
print bribes
</code>```

My problem is that the code times out with some of the larger test cases (you're only given so much time for each test case to run). How can I optimize the algorithm so that it doesn't time out? Should I be trying this problem in another language?

答:
Just came across this problem, took me some time but here's a nice clean solution that is optimized for larger test cases (and passes 10/10 on HackerRank). I realise it takes a slightly different approach to yours but thought I'd share as it is working nicely and might still help.

A key point that helped me is that for any given person X in the queue, the furthest you'll need to look for a person that overtook them is 1 spot in front of where person X started. People can be overtaken more than 2 times, so for example, person 1 can end up at the back of the queue even if the queue is 1000 people long. However, person Y can't end up more than two places ahead of where they began (otherwise they must have overtaken more than twice). This is the reason you can be sure you don't need to look further than 1 place in front of where person X began (2 places in front of the nearest possible overtaker) for the people that overtook them.

```<code>def minimumBribes(q):

    count = 0
    tooChaotic = False

    for i in range(len(q)):

        # to translate between q[i] and the position in a zero-indexed python list, you have to add 1, so here it's i+3 rather than i+2

        if q[i] > i + 3:
            print("Too chaotic")
            tooChaotic = True
            break
        else:

            # q[i]-2 rather than q[i]-1 since python is zero-indexed but the people in the queue start at 1

            start = max(0, q[i]-2)
            for j in range(start, i):
                    if q[j] > q[i]:
                        count += 1

    if tooChaotic == False:
        print(count)
</code>```

Body:
I'm trying to optimize my solution for Hackerranks's 'New Year Chaos' problem. The gist of the problem goes like this

There's a queue of n people, labeled 1 through n, and each person can bribe the person directly in front of them to swap places and get closer to the front of the queue (in this case, index 0 of the list/array). Each person can only bribe a maximum of two times (and they cannot bribe someone who has already bribed them)

You are given the order of the people after all of the bribes have taken place and your job is to determine how many bribes took place to get to that point. For example, if you were given [3, 2, 1] then the answer would be 3 bribes (person 3 bribed person 1, 2 and person 2 bribed person 1).

My solution was, for each person I, count the number of people to the left of I that have a label greater than I (they would've had to bribe person I to get to the left of them). To complicate things (slightly), some of the test cases given would only be possible if someone bribed more than 2 times (i.e. [4, 1, 2, 3] - person 4 bribed person 3, then 2, then 1 to get to the front). If this is the case, simply output "Too chaotic"

Anyway here's the code:

# n is the number of people in the list
# q is the order of the people after the bribery has taken place ex. [1, 3, 2, 5, 4]

for I in range(1, n + 1): # for each person I in the list
    index = q.index(I)
    if I - index > 3: # more than two bribes
        bribes = "Too chaotic"
        break
    for j in range(index): # for each number to the left of I, if greater than I, count it as a bribe
        if q[j] > I:
            bribes = bribes + 1
print bribes

My problem is that the code times out with some of the larger test cases (you're only given so much time for each test case to run). How can I optimize the algorithm so that it doesn't time out? Should I be trying this problem in another language?

Body:
Just came across this problem, took me some time but here's a nice clean solution that is optimized for larger test cases (and passes 10/10 on HackerRank). I realise it takes a slightly different approach to yours but thought I'd share as it is working nicely and might still help.

A key point that helped me is that for any given person X in the queue, the furthest you'll need to look for a person that overtook them is 1 spot in front of where person X started. People can be overtaken more than 2 times, so for example, person 1 can end up at the back of the queue even if the queue is 1000 people long. However, person Y can't end up more than two places ahead of where they began (otherwise they must have overtaken more than twice). This is the reason you can be sure you don't need to look further than 1 place in front of where person X began (2 places in front of the nearest possible overtaker) for the people that overtook them.

def minimumBribes(q):

    count = 0
    tooChaotic = False

    for i in range(len(q)):

        # to translate between q[i] and the position in a zero-indexed python list, you have to add 1, so here it's i+3 rather than i+2

        if q[i] > i + 3:
            print("Too chaotic")
            tooChaotic = True
            break
        else:

            # q[i]-2 rather than q[i]-1 since python is zero-indexed but the people in the queue start at 1

            start = max(0, q[i]-2)
            for j in range(start, i):
                    if q[j] > q[i]:
                        count += 1

    if tooChaotic == False:
        print(count)


问:
How to speed up tf.data.Dataset.from_generator()
In tensorflow2.0, I want to train a skip-gram model with nce loss. tf.data.Dataset.from_tensor_slices() is not suitable because the input file is really huge. So I write a dataset generator class like this:

class DataSet:
    """"""

    def __init__(self, args, vocab):
        self.args = args
        self.vocab = vocab

    def generator(self):
        """a generator function, it will return skip-gram sample or cbow sample"""
        with open(self.args.input) as f_input:
            for line in tqdm.tqdm(f_input.readlines()):
                tokens = line.strip().split()
                tokens_indices = self.vocab.indices(tokens)
                for index, target_word in enumerate(tokens_indices):
                    context_words = list()
                    begin = index - self.args.window_size if index - self.args.window_size > 0 else 0
                    end = index + 1 + self.args.window_size if index + self.args.window_size + 1 < len(tokens_indices) else len(
                        tokens_indices)
                    context_words.extend(tokens_indices[begin:index])
                    context_words.extend(tokens_indices[index + 1:end])
                    if self.args.cbow > 0:
                        yield context_words, target_word
                    else:
                        for i in range(len(context_words)):
                            yield target_word, context_words[i]

    def dataset(self):
        """Using tf.data.Dataset.from_generator() to return sample"""
        if self.args.cbow:
            dataset = tf.data.Dataset.from_generator(
                self.generator,
                (tf.int32, tf.int32),
                (tf.TensorShape([None]), tf.TensorShape([]))
            )
        else:
            dataset = tf.data.Dataset.from_generator(
                self.generator,
                (tf.int32, tf.int32),
                (tf.TensorShape([]), tf.TensorShape([]))
            )

        return dataset
```

<p>Then I test my code with follow:</p>

<pre class="lang-py prettyprint-override"><code>dataset = DataSet(args, vocab).dataset()
iterator = dataset.make_one_shot_iterator()
for batch, (x,y) in enumerate(dataset.batch(128)):
    pass
print(batch, x.shape, y.shape)
</code>```

But it cost a lot of time to iterate all lines(about 10 minutes / 15000 lines in MacBook pro 2012). Does there any methods can speed up the code?

答:
If you are working with large datasets then TFRecord is suitable option. It uses a binary file format for storage of your data and can have a significant impact on the performance of your import pipeline and as a consequence on the training time of your model. Binary data takes up less space on disk, takes less time to copy and can be read much more efficiently from disk. This is especially true if your data is stored on spinning disks, due to the much lower read/write performance in comparison with SSDs.

However, pure performance isn’t the only advantage of the TFRecord file format. It is optimized for use with Tensorflow in multiple ways. To start with, it makes it easy to combine multiple datasets and integrates seamlessly with the data import and preprocessing functionality provided by the library. Especially for datasets that are too large to be stored fully in memory this is an advantage as only the data that is required at the time (e.g. a batch) is loaded from disk and then processed. Another major advantage of TFRecords is that it is possible to store sequence data — for instance, a time series or word encodings — in a way that allows for very efficient and (from a coding perspective) convenient import of this type of data.

Would recommend to go through this official link for glimpse on TFRecord. Also you can go through this link on how to build TFRecord pipeline.

Here is a simple example of writing the serialized record using TFRecordWriter and then loading it in TFRecordDatset

```<code>%tensorflow_version 2.x
import tensorflow as tf
print(tf.__version__)

def write_date_tfrecord():
    #writes 10 dummy values to replicate the issue
    Output = [20191221 + x for x in range(0,10)]
    print("Writing Output - ", Output)

    example = tf.train.Example(
            features = tf.train.Features(
                feature = {
                    'Output':tf.train.Feature(float_list=tf.train.FloatList(value=Output))
                     }
                ))

    writer = tf.io.TFRecordWriter("Output.tf_record")
    writer.write(example.SerializeToString())

def parse_function(serialized_example):
        features = {
            'Output': tf.io.FixedLenSequenceFeature([], tf.float32,allow_missing=True)
             }
        features = tf.io.parse_single_example(serialized=serialized_example, features=features)
        Output = features['Output']
        return Output

def dataset_generator():
    trRecordDataset = tf.data.TFRecordDataset("Output.tf_record")
    trRecordDataset = trRecordDataset.map(parse_function, num_parallel_calls = tf.data.experimental.AUTOTUNE)
    return trRecordDataset

if __name__ == '__main__':
    write_date_tfrecord()
    generator = dataset_generator()
    for Output in generator:
        print(Output)
</code>```

Output -

```<code>2.2.0
Writing Output -  [20191221, 20191222, 20191223, 20191224, 20191225, 20191226, 20191227, 20191228, 20191229, 20191230]
tf.Tensor(
[20191220. 20191222. 20191224. 20191224. 20191224. 20191226. 20191228.
 20191228. 20191228. 20191230.], shape=(10,), dtype=float32)
</code>```

Hope this answers your question. Happy Learning.

Body:
In tensorflow2.0, I want to train a skip-gram model with nce loss. tf.data.Dataset.from_tensor_slices() is not suitable because the input file is really huge. So I write a dataset generator class like this:

class DataSet:
    """"""

    def __init__(self, args, vocab):
        self.args = args
        self.vocab = vocab

    def generator(self):
        """a generator function, it will return skip-gram sample or cbow sample"""
        with open(self.args.input) as f_input:
            for line in tqdm.tqdm(f_input.readlines()):
                tokens = line.strip().split()
                tokens_indices = self.vocab.indices(tokens)
                for index, target_word in enumerate(tokens_indices):
                    context_words = list()
                    begin = index - self.args.window_size if index - self.args.window_size > 0 else 0
                    end = index + 1 + self.args.window_size if index + self.args.window_size + 1 < len(tokens_indices) else len(
                        tokens_indices)
                    context_words.extend(tokens_indices[begin:index])
                    context_words.extend(tokens_indices[index + 1:end])
                    if self.args.cbow > 0:
                        yield context_words, target_word
                    else:
                        for i in range(len(context_words)):
                            yield target_word, context_words[i]

    def dataset(self):
        """Using tf.data.Dataset.from_generator() to return sample"""
        if self.args.cbow:
            dataset = tf.data.Dataset.from_generator(
                self.generator,
                (tf.int32, tf.int32),
                (tf.TensorShape([None]), tf.TensorShape([]))
            )
        else:
            dataset = tf.data.Dataset.from_generator(
                self.generator,
                (tf.int32, tf.int32),
                (tf.TensorShape([]), tf.TensorShape([]))
            )

        return dataset

Then I test my code with follow:

dataset = DataSet(args, vocab).dataset()
iterator = dataset.make_one_shot_iterator()
for batch, (x,y) in enumerate(dataset.batch(128)):
    pass
print(batch, x.shape, y.shape)

But it cost a lot of time to iterate all lines(about 10 minutes / 15000 lines in MacBook pro 2012). Does there any methods can speed up the code?

Body:
If you are working with large datasets then TFRecord is suitable option. It uses a binary file format for storage of your data and can have a significant impact on the performance of your import pipeline and as a consequence on the training time of your model. Binary data takes up less space on disk, takes less time to copy and can be read much more efficiently from disk. This is especially true if your data is stored on spinning disks, due to the much lower read/write performance in comparison with SSDs.

However, pure performance isn’t the only advantage of the TFRecord file format. It is optimized for use with Tensorflow in multiple ways. To start with, it makes it easy to combine multiple datasets and integrates seamlessly with the data import and preprocessing functionality provided by the library. Especially for datasets that are too large to be stored fully in memory this is an advantage as only the data that is required at the time (e.g. a batch) is loaded from disk and then processed. Another major advantage of TFRecords is that it is possible to store sequence data — for instance, a time series or word encodings — in a way that allows for very efficient and (from a coding perspective) convenient import of this type of data.

Would recommend to go through this official link for glimpse on TFRecord. Also you can go through this link on how to build TFRecord pipeline.

Here is a simple example of writing the serialized record using TFRecordWriter and then loading it in TFRecordDatset

%tensorflow_version 2.x
import tensorflow as tf
print(tf.__version__)

def write_date_tfrecord():
    #writes 10 dummy values to replicate the issue
    Output = [20191221 + x for x in range(0,10)]
    print("Writing Output - ", Output)

    example = tf.train.Example(
            features = tf.train.Features(
                feature = {
                    'Output':tf.train.Feature(float_list=tf.train.FloatList(value=Output))
                     }
                ))

    writer = tf.io.TFRecordWriter("Output.tf_record")
    writer.write(example.SerializeToString())

def parse_function(serialized_example):
        features = {
            'Output': tf.io.FixedLenSequenceFeature([], tf.float32,allow_missing=True)
             }
        features = tf.io.parse_single_example(serialized=serialized_example, features=features)
        Output = features['Output']
        return Output

def dataset_generator():
    trRecordDataset = tf.data.TFRecordDataset("Output.tf_record")
    trRecordDataset = trRecordDataset.map(parse_function, num_parallel_calls = tf.data.experimental.AUTOTUNE)
    return trRecordDataset

if __name__ == '__main__':
    write_date_tfrecord()
    generator = dataset_generator()
    for Output in generator:
        print(Output)

Output -

2.2.0
Writing Output -  [20191221, 20191222, 20191223, 20191224, 20191225, 20191226, 20191227, 20191228, 20191229, 20191230]
tf.Tensor(
[20191220. 20191222. 20191224. 20191224. 20191224. 20191226. 20191228.
 20191228. 20191228. 20191230.], shape=(10,), dtype=float32)

Hope this answers your question. Happy Learning.


问:
Filter a pandas dataframe based on two columns
I am trying to filter a pandas dataframe based on two columns, so that for each value in column 1 only those rows are left where column 2 is the minimum. I know it sounds confusing like this, so here is an example:

```<code>> df = pd.DataFrame([{'a':'anno1', 'ppm':1},{'a':'anno1', 'ppm':2},{'a':'anno2', 'ppm':2},{'a':'anno2', 'ppm':2}])

> df
       a  ppm
0  anno1    1
1  anno1    2
2  anno2    2
3  anno2    2
</code>```

And I want rows 0,2 and 3, because for anno1, the minimum ppm is 1, and for anno2 the minimum ppm is 2 (keep both rows!). So I started with a groupby:

```<code>> grouped_series = df.groupby(['a']).ppm.min()
> grouped_series
a
anno1    1
anno2    2
</code>```

Now I have for each value in a the minimum ppm. But how do I use this series to filter the original dataframe? Or is there even an easier way to do this? I tried several variations of:

```<code>new_df = df.loc[ df.loc[:,'ppm']==grouped_series.loc[df.loc[:,'a']] , :]
</code>```

but this gives me a ValueError: Can only compare identically-labeled Series objects

答:
Here is an alternative approach if you don't mind resetting the original index:

```<code>df.merge(df.groupby(['a'])['ppm'].min().reset_index(), how='inner')
</code>```

Output:

```<code>    a   ppm
0   anno1   1
1   anno2   2
2   anno2   2
</code>```

Body:
I am trying to filter a pandas dataframe based on two columns, so that for each value in column 1 only those rows are left where column 2 is the minimum. I know it sounds confusing like this, so here is an example:

> df = pd.DataFrame([{'a':'anno1', 'ppm':1},{'a':'anno1', 'ppm':2},{'a':'anno2', 'ppm':2},{'a':'anno2', 'ppm':2}])

> df
       a  ppm
0  anno1    1
1  anno1    2
2  anno2    2
3  anno2    2

And I want rows 0,2 and 3, because for anno1, the minimum ppm is 1, and for anno2 the minimum ppm is 2 (keep both rows!). So I started with a groupby:

> grouped_series = df.groupby(['a']).ppm.min()
> grouped_series
a
anno1    1
anno2    2

Now I have for each value in a the minimum ppm. But how do I use this series to filter the original dataframe? Or is there even an easier way to do this? I tried several variations of:

new_df = df.loc[ df.loc[:,'ppm']==grouped_series.loc[df.loc[:,'a']] , :]

but this gives me a ValueError: Can only compare identically-labeled Series objects

Body:
Here is an alternative approach if you don't mind resetting the original index:

df.merge(df.groupby(['a'])['ppm'].min().reset_index(), how='inner')

Output:

    a   ppm
0   anno1   1
1   anno2   2
2   anno2   2


问:
How to display soft keyboard after AlertDialog show
I have Google this proplem, but none of the answers works for me.
This is the style of my AlertDialog

```<code><style name="dialog_full_screen">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowFullscreen">true</item>
        <item name="android:backgroundDimEnabled">true</item>
</style>
</code>```

This is the code to show it.

```<code>  val alertDialog = AlertDialog.Builder(this, R.style.dialog_full_screen).apply {
            setCancelable(true)
        }.create()
        alertDialog.apply {
            val wlp = window!!.attributes
            wlp.gravity = Gravity.BOTTOM
            wlp.flags = wlp.flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()
            val displayMetrics = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(displayMetrics)
            wlp.width = displayMetrics.widthPixels
            wlp.height = WindowManager.LayoutParams.WRAP_CONTENT
            window!!.attributes = wlp
        }
        alertDialog.show()
</code>```

The following code is layout

```<code><LinearLayout
    android:id="@+id/linear_layout_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    style="@style/CenterInConstraintLayout"
    tools:ignore="MissingConstraints">

<ImageView
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@drawable/index_play_page_icon_comments_null"
    />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/homepage_no_comments"
    android:textColor="@color/color_gray_dark2"
    android:textSize="@dimen/font_size_14"
    />
</LinearLayout>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="horizontal"
    app:layout_constraintBottom_toBottomOf="parent"
    android:gravity="center">
    <EditText
        android:id="@+id/edit_text_comment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:maxLength="150"
        android:hint="@string/homepage_hint_comment"
        android:textColorHint="@color/color_gray_dark2"
        android:background="@null"
        android:importantForAutofill="no" />
    <ImageView
        android:id="@+id/image_view_send"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginEnd="30dp"
        />
</LinearLayout>
</code>```

This AlertDialog can show properly, but i can't show soft keyboard

Body:
I have Google this proplem, but none of the answers works for me.
This is the style of my AlertDialog

This is the code to show it.

  val alertDialog = AlertDialog.Builder(this, R.style.dialog_full_screen).apply {
            setCancelable(true)
        }.create()
        alertDialog.apply {
            val wlp = window!!.attributes
            wlp.gravity = Gravity.BOTTOM
            wlp.flags = wlp.flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()
            val displayMetrics = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(displayMetrics)
            wlp.width = displayMetrics.widthPixels
            wlp.height = WindowManager.LayoutParams.WRAP_CONTENT
            window!!.attributes = wlp
        }
        alertDialog.show()

The following code is layout

<LinearLayout
    android:id="@+id/linear_layout_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    style="@style/CenterInConstraintLayout"
    tools:ignore="MissingConstraints">

<ImageView
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@drawable/index_play_page_icon_comments_null"
    />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/homepage_no_comments"
    android:textColor="@color/color_gray_dark2"
    android:textSize="@dimen/font_size_14"
    />
</LinearLayout>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="horizontal"
    app:layout_constraintBottom_toBottomOf="parent"
    android:gravity="center">
    <EditText
        android:id="@+id/edit_text_comment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:maxLength="150"
        android:hint="@string/homepage_hint_comment"
        android:textColorHint="@color/color_gray_dark2"
        android:background="@null"
        android:importantForAutofill="no" />
    <ImageView
        android:id="@+id/image_view_send"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginEnd="30dp"
        />
</LinearLayout>

This AlertDialog can show properly, but i can't show soft keyboard

Body: alertDialog.window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)


问:
How to fill the custom columns with joined values
I have a query like:

```<code>    SELECT `main_table`.*,
       IF(sosh.status = 'pending_payment', sosh.created_at, null)      AS `pending_payment_status_datetime`,
       IF(sosh.status = 'processing_payd', sosh.created_at, null)      AS `processing_payd_status_datetime`,
       IF(sosh.status = 'processing', sosh.created_at, null)           AS `processing_status_datetime`,
       IF(sosh.status = 'complete', sosh.created_at, null)             AS `complete_status_datetime`,
       IF(sosh.status = 'shipping_ready', sosh.created_at, null)       AS `shipping_ready_status_datetime`,
       IF(sosh.status = 'shipping_ready_cod', sosh.created_at, null)   AS `shipping_ready_cod_status_datetime`,
       IF(sosh.status = 'shipping_in_progress', sosh.created_at, null) AS `shipping_in_progress_status_datetime`,
       IF(sosh.status = 'closed', sosh.created_at, null)               AS `closed_status_datetime`,
       IF(sosh.status = 'archived', sosh.created_at, null)             AS `archived_status_datetime`,
       IF(sosh.status = 'withdraw', sosh.created_at, null)             AS `withdraw_status_datetime`,
       IF(sosh.status = 'canceled', sosh.created_at, null)             AS `canceled_status_datetime`
FROM `sales_order_grid` AS `main_table`
         LEFT JOIN `sales_order_status_history` AS `sosh` ON sosh.parent_id = main_table.entity_id
GROUP BY `main_table`.`entity_id`;
</code>```

I have 2 tables:

sales_order_grid (where the main data is)

sales_order_status_history (where I want to attach the status data)

I need to fetch custom columns values of the latest statuses (I mean there could be more than one status for the order, but the date differs).

Could you please help me with that?

答:
Assuming a status is later than the other if its created_at is later then you could use:</p>

```<code>SELECT `main_table`.*,
   IF(sosh.status = 'pending_payment', sosh.created_at, null)      AS `pending_payment_status_datetime`,
   IF(sosh.status = 'processing_payd', sosh.created_at, null)      AS `processing_payd_status_datetime`,
   IF(sosh.status = 'processing', sosh.created_at, null)           AS `processing_status_datetime`,
   IF(sosh.status = 'complete', sosh.created_at, null)             AS `complete_status_datetime`,
   IF(sosh.status = 'shipping_ready', sosh.created_at, null)       AS `shipping_ready_status_datetime`,
   IF(sosh.status = 'shipping_ready_cod', sosh.created_at, null)   AS `shipping_ready_cod_status_datetime`,
   IF(sosh.status = 'shipping_in_progress', sosh.created_at, null) AS `shipping_in_progress_status_datetime`,
   IF(sosh.status = 'closed', sosh.created_at, null)               AS `closed_status_datetime`,
   IF(sosh.status = 'archived', sosh.created_at, null)             AS `archived_status_datetime`,
   IF(sosh.status = 'withdraw', sosh.created_at, null)             AS `withdraw_status_datetime`,
   IF(sosh.status = 'canceled', sosh.created_at, null)             AS `canceled_status_datetime`
FROM `sales_order_grid` AS `main_table`
LEFT JOIN `sales_order_status_history` AS `sosh` ON sosh.parent_id = main_table.entity_id
LEFT JOIN `sales_order_status_history` AS `sosh2` ON sosh2.parent_id = main_table.entity_id
-- latest of sosh
  AND sosh2.created_at > sosh.created_at
WHERE sosh2.created_at IS NULL
GROUP BY `main_table`.`entity_id`;
</code>```

Body:
I have a query like:

    SELECT `main_table`.*,
       IF(sosh.status = 'pending_payment', sosh.created_at, null)      AS `pending_payment_status_datetime`,
       IF(sosh.status = 'processing_payd', sosh.created_at, null)      AS `processing_payd_status_datetime`,
       IF(sosh.status = 'processing', sosh.created_at, null)           AS `processing_status_datetime`,
       IF(sosh.status = 'complete', sosh.created_at, null)             AS `complete_status_datetime`,
       IF(sosh.status = 'shipping_ready', sosh.created_at, null)       AS `shipping_ready_status_datetime`,
       IF(sosh.status = 'shipping_ready_cod', sosh.created_at, null)   AS `shipping_ready_cod_status_datetime`,
       IF(sosh.status = 'shipping_in_progress', sosh.created_at, null) AS `shipping_in_progress_status_datetime`,
       IF(sosh.status = 'closed', sosh.created_at, null)               AS `closed_status_datetime`,
       IF(sosh.status = 'archived', sosh.created_at, null)             AS `archived_status_datetime`,
       IF(sosh.status = 'withdraw', sosh.created_at, null)             AS `withdraw_status_datetime`,
       IF(sosh.status = 'canceled', sosh.created_at, null)             AS `canceled_status_datetime`
FROM `sales_order_grid` AS `main_table`
         LEFT JOIN `sales_order_status_history` AS `sosh` ON sosh.parent_id = main_table.entity_id
GROUP BY `main_table`.`entity_id`;

I have 2 tables:

sales_order_grid (where the main data is)

sales_order_status_history (where I want to attach the status data)

I need to fetch custom columns values of the latest statuses (I mean there could be more than one status for the order, but the date differs).

Could you please help me with that?

Body:
Assuming a status is later than the other if its created_at is later then you could use:

SELECT `main_table`.*,
   IF(sosh.status = 'pending_payment', sosh.created_at, null)      AS `pending_payment_status_datetime`,
   IF(sosh.status = 'processing_payd', sosh.created_at, null)      AS `processing_payd_status_datetime`,
   IF(sosh.status = 'processing', sosh.created_at, null)           AS `processing_status_datetime`,
   IF(sosh.status = 'complete', sosh.created_at, null)             AS `complete_status_datetime`,
   IF(sosh.status = 'shipping_ready', sosh.created_at, null)       AS `shipping_ready_status_datetime`,
   IF(sosh.status = 'shipping_ready_cod', sosh.created_at, null)   AS `shipping_ready_cod_status_datetime`,
   IF(sosh.status = 'shipping_in_progress', sosh.created_at, null) AS `shipping_in_progress_status_datetime`,
   IF(sosh.status = 'closed', sosh.created_at, null)               AS `closed_status_datetime`,
   IF(sosh.status = 'archived', sosh.created_at, null)             AS `archived_status_datetime`,
   IF(sosh.status = 'withdraw', sosh.created_at, null)             AS `withdraw_status_datetime`,
   IF(sosh.status = 'canceled', sosh.created_at, null)             AS `canceled_status_datetime`
FROM `sales_order_grid` AS `main_table`
LEFT JOIN `sales_order_status_history` AS `sosh` ON sosh.parent_id = main_table.entity_id
LEFT JOIN `sales_order_status_history` AS `sosh2` ON sosh2.parent_id = main_table.entity_id
-- latest of sosh
  AND sosh2.created_at > sosh.created_at
WHERE sosh2.created_at IS NULL
GROUP BY `main_table`.`entity_id`;


问:
Convert space separated string of coordinates into JavaScript object array
This space separated string:

```<code>const polygon = "42.44492,75.637764 42.445503,75.64534 42.433681,75.6604"
</code>```

..should be converted to array consisting objects:

```<code>const polygon = [
    { lat: 42.44492, lng: 75.637764 },
    { lat: 42.445503, lng: 75.64534 },
    { lat: 42.433681, lng: 75.6604 }
]
</code>```

What is the most simplest (beautiful) way to achieve this with JavaScript? Is there a nice one liner for this? The initial string can consist any amount coordinate pairs.

答:
const polygon = "42.44492,75.637764 42.445503,75.64534 42.433681,75.6604"
const polygonsArr = polygon.split(' ')
const result = []
polygonsArr.map(item => {
    let a = item.split(',');
    result.push({"lat": a[0], "lng": a[1]})
})
console.log(result)```

Body:
This space separated string:

const polygon = "42.44492,75.637764 42.445503,75.64534 42.433681,75.6604"

..should be converted to array consisting objects:

const polygon = [
    { lat: 42.44492, lng: 75.637764 },
    { lat: 42.445503, lng: 75.64534 },
    { lat: 42.433681, lng: 75.6604 }
]

What is the most simplest (beautiful) way to achieve this with JavaScript? Is there a nice one liner for this? The initial string can consist any amount coordinate pairs.


问:
Taking user input to Google Sheets using Apps Script and process with queries
I created a spreadsheet for reporting students attendance that contains 8 sheets (each sheet named as a subject code). After completing a particular class, I go to the specific sheet (subject) and select all the rows of that particular date and press the button AfterClass-->Process Data (sorting, removing duplicates and protecting) using Google Apps Script/Macros. All working fine.

Now I created a DASHBOARD and I want that a teacher can do everything from the dashboard rather than going to individual sheet (subject). S/he can give two inputs - subject (sheetname) and Date from the Dashboard and then automatically process these specific dataset of that Sheet (Not all data of the sheet). Please note that date is in Column A and subject-code in Column F. The code I wrote as follows:

```<code>  function AfterClass() {
      var spreadsheet = SpreadsheetApp.getActive();
  //Sorting and removing duplicates
  var height = spreadsheet.getActiveSheet().getActiveRange().getHeight();
  spreadsheet.getCurrentCell().offset(0, 0, height, 6).activate()
  .sort({column: spreadsheet.getActiveRange().getColumn() + 2, ascending: true});
  spreadsheet.getActiveRange().removeDuplicates([spreadsheet.getActiveRange().getColumn() + 2]).activate();

  //Protecting data finally
  //var lastRow = spreadsheet.getLastRow();
  var timeZone = Session.getScriptTimeZone();
  var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
  var me = Session.getEffectiveUser();
  var description = 'Protected on ' + stringDate + ' by ' + me;
  var protection = SpreadsheetApp.getActiveSheet().getActiveRange().protect().setDescription(description);
  //protection.setDomainEdit(false);
  protection.addEditor(me);
  protection.removeEditors(protection.getEditors());
  if (protection.canDomainEdit()) {
    protection.setDomainEdit(false);
  }

//Removing blank spacess in between data
      var sheet = SpreadsheetApp.getActiveSheet();
      var rows = sheet.getDataRange();
      var numRows = rows.getNumRows();
      var values = rows.getValues();
      var rowsDeleted = 0;
      for (var i = 0; i <= numRows - 1; i++) {
        var row = values[i];
        if (row[1] == '') {
          sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
          rowsDeleted++;
        }
      }

     //For Double periods in a class
          //var ss = SpreadsheetApp.getActiveSpreadsheet()
          //var database = SpreadsheetApp.openById("xxx");
          //var source = ss.getSheetByName('yyy');
          var dataToCopyRng = SpreadsheetApp.getActiveSheet().getActiveRange(); //Gets range object of all data on source sheet
          var dataToCopy = dataToCopyRng.getValues(); //Gets the values of the source range in a 2 dimensional array
          var copyToSheet = SpreadsheetApp.getActiveSheet();
          var copyData = copyToSheet.getRange(copyToSheet.getLastRow()+1,1,dataToCopy.length,dataToCopy[0].length).setValues(dataToCopy);

      //Calculate class attendance and signed
      var height2 = spreadsheet.getActiveSheet().getActiveRange().getHeight();
      SpreadsheetApp.getActiveSheet().getCurrentCell().offset(2*height2,1).activate();
      SpreadsheetApp.getActiveSheet().getCurrentCell().setRichTextValue(SpreadsheetApp.newRichTextValue()
      .setText(height2 + ' Students, SIGNED')
      .setTextStyle(0, 12, SpreadsheetApp.newTextStyle()
      .setBold(true)
      .build())
      .build());
      spreadsheet.getCurrentCell().offset(0, -1, 1, 6).activate();
      spreadsheet.getActiveRangeList().setBackground('#e6b8af');
      //.setBackground('#d9d9d9')

    }

  [dashboard][1]

  [1]: https://i.stack.imgur.com/cMtHC.png
</code>```

答:
How to run your script from Dashboard after selecting the specified sheet and time

Modify your function in a way that it takes input from the cells A2 and C2 and  D2 from Dashboard

Replace all instances of getActiveSheet() through getSheetByName(name), whereby name is your input from A1

Replace all instances of getActiveRange() through sheet.getRange(), whereby you define the range as as subrange as defined by the dates you retrieved

In order to find the first occurrence of the start date and the last occurrence of the end date - use the methods indexOf() and lastIndexOf()

Make sure that your date notation in Dashboard is the same as in the sheets for correct functionality

Sample:

```<code>function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('After Class')
  .addItem('Process Data', 'AfterClass')
  .addToUi();
}

function AfterClass() {
  var spreadsheet = SpreadsheetApp.getActive();
  var dashboard = spreadsheet.getSheetByName("Dashboard");
  var sheetName = dashboard.getRange("A2").getValue();
  //retrieve the start date to use as desired
  var startDate = dashboard.getRange("C2").getDisplayValue();
  var endDate = dashboard.getRange("D2").getDisplayValue();
  var sheet = spreadsheet.getSheetByName(sheetName);
  //chose the range within the specified dates, for this first locate the date column
  var startRow = 2;
  var dateColumn = sheet.getRange(startRow,1,sheet.getLastRow(), 1);
  var dates = dateColumn.getDisplayValues().flat();
  var firstRow = dates.indexOf(startDate)+startRow;
  var lastRow = dates.lastIndexOf(endDate)+startRow;
  //now get the range between (and including) those rows
  var range = sheet.getRange(firstRow, 1, lastRow-firstRow+1, sheet.getLastColumn());
  //Sorting and removing duplicates
  // You need to specify by which column you want to sort your data, in this sample it it column 3 - that it column C
  var column = 3;
  range.sort({column: column, ascending:true});
  range.removeDuplicates([column]);
  //now delete empty rows if any
  for (var i = range.getHeight(); i >= 1; i--){
    if(range.getCell(i, 1).isBlank()){
      sheet.deleteRow(range.getCell(i, 1).getRow());
    }
  }
  //Protecting data
  var timeZone = Session.getScriptTimeZone();
  var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
  var me = Session.getEffectiveUser();
  var description = 'Protected on ' + stringDate + ' by ' + me;
  var protection = range.protect().setDescription(description)
  //protection.setDomainEdit(false);
  protection.addEditor(me);
  protection.removeEditors(protection.getEditors());
  if (protection.canDomainEdit()) {
    protection.setDomainEdit(false);
  }
}
</code>```

Important

The sample above will work if your sheet is sorted by dates (ascending) - as you specified in the comments. However, once the data is sorted by column C and not dates anymore it might not work as intended.

Sidenote:

From your code I understand that you recorded it as a macro rather than writing it from scratch (visible by the (unnecessary) calls of activate()).

I very much recommend you to take some time to study Apps Script in roder to understand your code in depth and be able to perform modificaitons and adjustments according to your needs.

There is the basic tutorial for Apps Script in general, samples and explanations for Google Sheets in specific and the references for all available Apps Script methods, whereby most methods feature a code sample.

Body:
I created a spreadsheet for reporting students attendance that contains 8 sheets (each sheet named as a subject code). After completing a particular class, I go to the specific sheet (subject) and select all the rows of that particular date and press the button AfterClass-->Process Data (sorting, removing duplicates and protecting) using Google Apps Script/Macros. All working fine.

Now I created a DASHBOARD and I want that a teacher can do everything from the dashboard rather than going to individual sheet (subject). S/he can give two inputs - subject (sheetname) and Date from the Dashboard and then automatically process these specific dataset of that Sheet (Not all data of the sheet). Please note that date is in Column A and subject-code in Column F. The code I wrote as follows:

  function AfterClass() {
      var spreadsheet = SpreadsheetApp.getActive();
  //Sorting and removing duplicates
  var height = spreadsheet.getActiveSheet().getActiveRange().getHeight();
  spreadsheet.getCurrentCell().offset(0, 0, height, 6).activate()
  .sort({column: spreadsheet.getActiveRange().getColumn() + 2, ascending: true});
  spreadsheet.getActiveRange().removeDuplicates([spreadsheet.getActiveRange().getColumn() + 2]).activate();

  //Protecting data finally
  //var lastRow = spreadsheet.getLastRow();
  var timeZone = Session.getScriptTimeZone();
  var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
  var me = Session.getEffectiveUser();
  var description = 'Protected on ' + stringDate + ' by ' + me;
  var protection = SpreadsheetApp.getActiveSheet().getActiveRange().protect().setDescription(description);
  //protection.setDomainEdit(false);
  protection.addEditor(me);
  protection.removeEditors(protection.getEditors());
  if (protection.canDomainEdit()) {
    protection.setDomainEdit(false);
  }

//Removing blank spacess in between data
      var sheet = SpreadsheetApp.getActiveSheet();
      var rows = sheet.getDataRange();
      var numRows = rows.getNumRows();
      var values = rows.getValues();
      var rowsDeleted = 0;
      for (var i = 0; i <= numRows - 1; i++) {
        var row = values[i];
        if (row[1] == '') {
          sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
          rowsDeleted++;
        }
      }

     //For Double periods in a class
          //var ss = SpreadsheetApp.getActiveSpreadsheet()
          //var database = SpreadsheetApp.openById("xxx");
          //var source = ss.getSheetByName('yyy');
          var dataToCopyRng = SpreadsheetApp.getActiveSheet().getActiveRange(); //Gets range object of all data on source sheet
          var dataToCopy = dataToCopyRng.getValues(); //Gets the values of the source range in a 2 dimensional array
          var copyToSheet = SpreadsheetApp.getActiveSheet();
          var copyData = copyToSheet.getRange(copyToSheet.getLastRow()+1,1,dataToCopy.length,dataToCopy[0].length).setValues(dataToCopy);

      //Calculate class attendance and signed
      var height2 = spreadsheet.getActiveSheet().getActiveRange().getHeight();
      SpreadsheetApp.getActiveSheet().getCurrentCell().offset(2*height2,1).activate();
      SpreadsheetApp.getActiveSheet().getCurrentCell().setRichTextValue(SpreadsheetApp.newRichTextValue()
      .setText(height2 + ' Students, SIGNED')
      .setTextStyle(0, 12, SpreadsheetApp.newTextStyle()
      .setBold(true)
      .build())
      .build());
      spreadsheet.getCurrentCell().offset(0, -1, 1, 6).activate();
      spreadsheet.getActiveRangeList().setBackground('#e6b8af');
      //.setBackground('#d9d9d9')

    }

  [dashboard][1]

  [1]: https://i.stack.imgur.com/cMtHC.png

Body:
How to run your script from Dashboard after selecting the specified sheet and time

Modify your function in a way that it takes input from the cells A2 and C2 and  D2 from Dashboard

Replace all instances of getActiveSheet() through getSheetByName(name), whereby name is your input from A1

Replace all instances of getActiveRange() through sheet.getRange(), whereby you define the range as as subrange as defined by the dates you retrieved

In order to find the first occurrence of the start date and the last occurrence of the end date - use the methods indexOf() and lastIndexOf()

Make sure that your date notation in Dashboard is the same as in the sheets for correct functionality

Sample:

function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('After Class')
  .addItem('Process Data', 'AfterClass')
  .addToUi();
}

function AfterClass() {
  var spreadsheet = SpreadsheetApp.getActive();
  var dashboard = spreadsheet.getSheetByName("Dashboard");
  var sheetName = dashboard.getRange("A2").getValue();
  //retrieve the start date to use as desired
  var startDate = dashboard.getRange("C2").getDisplayValue();
  var endDate = dashboard.getRange("D2").getDisplayValue();
  var sheet = spreadsheet.getSheetByName(sheetName);
  //chose the range within the specified dates, for this first locate the date column
  var startRow = 2;
  var dateColumn = sheet.getRange(startRow,1,sheet.getLastRow(), 1);
  var dates = dateColumn.getDisplayValues().flat();
  var firstRow = dates.indexOf(startDate)+startRow;
  var lastRow = dates.lastIndexOf(endDate)+startRow;
  //now get the range between (and including) those rows
  var range = sheet.getRange(firstRow, 1, lastRow-firstRow+1, sheet.getLastColumn());
  //Sorting and removing duplicates
  // You need to specify by which column you want to sort your data, in this sample it it column 3 - that it column C
  var column = 3;
  range.sort({column: column, ascending:true});
  range.removeDuplicates([column]);
  //now delete empty rows if any
  for (var i = range.getHeight(); i >= 1; i--){
    if(range.getCell(i, 1).isBlank()){
      sheet.deleteRow(range.getCell(i, 1).getRow());
    }
  }
  //Protecting data
  var timeZone = Session.getScriptTimeZone();
  var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
  var me = Session.getEffectiveUser();
  var description = 'Protected on ' + stringDate + ' by ' + me;
  var protection = range.protect().setDescription(description)
  //protection.setDomainEdit(false);
  protection.addEditor(me);
  protection.removeEditors(protection.getEditors());
  if (protection.canDomainEdit()) {
    protection.setDomainEdit(false);
  }
}

Important

The sample above will work if your sheet is sorted by dates (ascending) - as you specified in the comments. However, once the data is sorted by column C and not dates anymore it might not work as intended.

Sidenote:

From your code I understand that you recorded it as a macro rather than writing it from scratch (visible by the (unnecessary) calls of activate()).

I very much recommend you to take some time to study Apps Script in roder to understand your code in depth and be able to perform modificaitons and adjustments according to your needs.

There is the basic tutorial for Apps Script in general, samples and explanations for Google Sheets in specific and the references for all available Apps Script methods, whereby most methods feature a code sample.


问:
What's the proper terminology for 32- vs 64- "bits"
I'm crystal clear on different architectures providing 32-bit or 64-bit registers and how that all works out at a low level.  However, one thing has always eluded me.. specific terminology for whether you're 32- or 64- bit.  For example:

```
string XXX;</p>

<p>if(architecture == i386)
  XXX = "32";
else if(architecture == x86_64)
  XXX = "64";</p>

<p>... go on to use variable XXX ...
</code>```

So, what would I name my variable?  Not architecture.  Not "bits".  Not "bus width" or "register width" (that would seem quite out of place I think)

So what would this variable be named and what would someone say in conversation?

答: I'd call it wordSize = "xx", I'd say 'word size'.</p>

Body:
I'm crystal clear on different architectures providing 32-bit or 64-bit registers and how that all works out at a low level.  However, one thing has always eluded me.. specific terminology for whether you're 32- or 64- bit.  For example:

string XXX;

if(architecture == i386)
  XXX = "32";
else if(architecture == x86_64)
  XXX = "64";

... go on to use variable XXX ...

So, what would I name my variable?  Not architecture.  Not "bits".  Not "bus width" or "register width" (that would seem quite out of place I think)

So what would this variable be named and what would someone say in conversation?


问:
python:find a ascending/decreasing elements in a list without using loop
Suppose I have a list, I need to find two lists in list 'a', in a increasing/decreasing order, respectively.

```<code>a=[4,2,6,5,2,6,9,7,10,1,2,1]
</code>```

The output should be a list :

```<code>b=[4,6,9,10] # in an ascending order
</code>```

and

```<code>c=[4,2,1] # in a decreasing order , c[-1] is the first '1' in list a, c[1] is the first '2' in list a.
</code>```

Is there a possible way to do it without using loop (I have solved it using a loop)? As a have a large dataset, using loop would be slow. So I am looking for a faster way if possible. Thanks a lot.

答:
You should use the .sort() method. If no parameters are entered then it automatically sorts the list in ascending order. For descending just do .sort(reverse=True).

```<code>b = a.sort()
#ascending

c = a.sort(reverse=True)
#descending
</code>```

I hope this is what you are looking for.

Body:
Suppose I have a list, I need to find two lists in list 'a', in a increasing/decreasing order, respectively.

a=[4,2,6,5,2,6,9,7,10,1,2,1]

The output should be a list :

b=[4,6,9,10] # in an ascending order

and

c=[4,2,1] # in a decreasing order , c[-1] is the first '1' in list a, c[1] is the first '2' in list a.

Is there a possible way to do it without using loop (I have solved it using a loop)? As a have a large dataset, using loop would be slow. So I am looking for a faster way if possible. Thanks a lot.

Body:
You should use the .sort() method. If no parameters are entered then it automatically sorts the list in ascending order. For descending just do .sort(reverse=True).

b = a.sort()
#ascending

c = a.sort(reverse=True)
#descending

I hope this is what you are looking for.


问:
Get children for any level in tree structure but without theirs children using Hibernate?
I have a Folder entity in Hibernate, like so:

```<code>@Entity
@Table(name = "folders")
public class Folder {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "folder_id", unique = true, nullable = false)
    private int id;

    @NonNull
    @Column(name = "name", length = 100, unique = true, nullable = false)
    private String name;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", orphanRemoval = true)
    @Column(name = "sub_folders")
    private Set<Folder> childFolders = new HashSet<>();

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JsonIgnore
    @JoinColumn(name = "parent", referencedColumnName = "folder_id", nullable = true)
    private Folder parent;

    public Folder() {
    }

}
</code>```

I'm trying to write a finder method or custom query which will do what I wrote in the subject.

So if I send a request going like folders/{parent_folder_id}, let's say value being 1, I should get objects 4 and 5, but without their children, so not including 6,7,8 and 9.

Ideally, hibernate query would be preferred. If not, any sql language is also fine. I'll try to tumble it up to hibernate.

This is what I got, I still get children...

```<code>@Query(value = "Select * from folders f where f.parent = ?1 ", nativeQuery = true)
Set<Folder> getFolders(int folder_id);
</code>```

答:
I think this should work:

make the default fetchtype lazy:

```<code>@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", orphanRemoval = true)
@Column(name = "sub_folders")
private Set<Folder> childFolders = new HashSet<>();
</code>```

Use a JOIN FETCH in order to eagerly fetch the relationships you want.

```<code>SELECT f FROM folders f JOIN FETCH f.childFolders
</code>```

You probably can achieve something similar with entity graphs but I'm not sure about their interaction with queries.

Body:
I have a Folder entity in Hibernate, like so:

@Entity
@Table(name = "folders")
public class Folder {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "folder_id", unique = true, nullable = false)
    private int id;

    @NonNull
    @Column(name = "name", length = 100, unique = true, nullable = false)
    private String name;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", orphanRemoval = true)
    @Column(name = "sub_folders")
    private Set<Folder> childFolders = new HashSet<>();

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JsonIgnore
    @JoinColumn(name = "parent", referencedColumnName = "folder_id", nullable = true)
    private Folder parent;

    public Folder() {
    }

}

I'm trying to write a finder method or custom query which will do what I wrote in the subject.

So if I send a request going like folders/{parent_folder_id}, let's say value being 1, I should get objects 4 and 5, but without their children, so not including 6,7,8 and 9.

Ideally, hibernate query would be preferred. If not, any sql language is also fine. I'll try to tumble it up to hibernate.

This is what I got, I still get children...

@Query(value = "Select * from folders f where f.parent = ?1 ", nativeQuery = true)
Set<Folder> getFolders(int folder_id);

Body:
I think this should work:

make the default fetchtype lazy:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", orphanRemoval = true)
@Column(name = "sub_folders")
private Set<Folder> childFolders = new HashSet<>();

Use a JOIN FETCH in order to eagerly fetch the relationships you want.

SELECT f FROM folders f JOIN FETCH f.childFolders

You probably can achieve something similar with entity graphs but I'm not sure about their interaction with queries.


问:
JGroups : explain mcast_addr for dummies
Using the following command to listen in for MCast messages.

```<code>java -cp $CLASSPATH:./jgroups-all.jar org.jgroups.tests.McastReceiverTest -mcast_addr 228.1.1.1 -port 55555
</code>```

Based on this image, the 228.1.1.1 should be a valid IP for multicasting.

Now the questions...

1 - In layman's terms, what exactly is this mcast_addr? Is the mcast_addr essentially a virtual name (set up as an IP address format) for the group machines that send messages to/from each other?  So, instead of mcast_addr being something like "MyConferenceRoom1" I call it "228.1.1.1"?

2 - If 3 machines used the same mcast_addr, they can all use different -port options?

3 - A bit of an exaggeration, but if I were to write a program that iterated through all the mcast_addr 288.x.x.x, could I essentially be eavesdropping on someone else's messages?

答:
In layman's terms, mcast_addr is like a radio frequency with the exception of that you need to join it before you can listen in (not true within a net without a router hop). Most often, a port is also used but you can view this as part of the frequency.

So, instead of mcast_addr being something like "MyConferenceRoom1" I
  call it "228.1.1.1"?

Yes, exactly.

Yes, but for super-high volumes, filtering of unwanted messages will then happen higher up the IP stack which can degrade the performance. You usually want to separate classes of traffic on the multicast group for reasons explained below.

Yes, there is no permissioning built-in to this at the IP level. You might run into routers not playing along, this is one of the reasons you need to join a multicast group before listening:

+--------+    +--------+    +----------+
| Sender | -> | Router | -> | Listener |
+--------+    +--------+    +----------+```
</div>
</div>
</p>

<p>As a listener, when you <em>join</em> a multicast group, a message gets sent to the router that, depending on its configuration, will start routing messages to the listener. </p>

<p>Now, imaging having a network of subnets where there might be 2 routers between the sender and listener: </p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override"><code>+--------+    +----------+    +------------+
| Sender | -> | Router A | -> | Listener 1 |
+--------+    +----------+    +------------+
                    |
                    V
              +----------+    +------------+
              | Router B | -> | Listener 2 |
              +----------+    +------------+</code>```

If Listener 1 joins 224.1.2.3 and Listener 2 joins 228.1.1.1 they won't see each other's traffic. This mechanism prevents flooding the network with multicast messages very few are interested in. Listener 2 could certainly try to join 224.1.2.3 but it's the router that decides if this should be allowed.

In an enterprise setting, routers are usually configured to block multicast traffic other than within a subnet because then routers are not typically involved.

As mentioned before, if you are separating classes of traffic on the port, the routers won't be able to perform their work as efficiently since they usually don't care about the port.

Body:
Using the following command to listen in for MCast messages.

java -cp $CLASSPATH:./jgroups-all.jar org.jgroups.tests.McastReceiverTest -mcast_addr 228.1.1.1 -port 55555

Based on this image, the 228.1.1.1 should be a valid IP for multicasting.

Now the questions...

1 - In layman's terms, what exactly is this mcast_addr? Is the mcast_addr essentially a virtual name (set up as an IP address format) for the group machines that send messages to/from each other?  So, instead of mcast_addr being something like "MyConferenceRoom1" I call it "228.1.1.1"?

2 - If 3 machines used the same mcast_addr, they can all use different -port options?

3 - A bit of an exaggeration, but if I were to write a program that iterated through all the mcast_addr 288.x.x.x, could I essentially be eavesdropping on someone else's messages?

Body:
In layman's terms, mcast_addr is like a radio frequency with the exception of that you need to join it before you can listen in (not true within a net without a router hop). Most often, a port is also used but you can view this as part of the frequency.

So, instead of mcast_addr being something like "MyConferenceRoom1" I
  call it "228.1.1.1"?

Yes, exactly.

Yes, but for super-high volumes, filtering of unwanted messages will then happen higher up the IP stack which can degrade the performance. You usually want to separate classes of traffic on the multicast group for reasons explained below.

Yes, there is no permissioning built-in to this at the IP level. You might run into routers not playing along, this is one of the reasons you need to join a multicast group before listening:

+--------+    +--------+    +----------+
| Sender | -> | Router | -> | Listener |
+--------+    +--------+    +----------+

As a listener, when you join a multicast group, a message gets sent to the router that, depending on its configuration, will start routing messages to the listener.

Now, imaging having a network of subnets where there might be 2 routers between the sender and listener:

+--------+    +----------+    +------------+
| Sender | -> | Router A | -> | Listener 1 |
+--------+    +----------+    +------------+
                    |
                    V
              +----------+    +------------+
              | Router B | -> | Listener 2 |
              +----------+    +------------+

If Listener 1 joins 224.1.2.3 and Listener 2 joins 228.1.1.1 they won't see each other's traffic. This mechanism prevents flooding the network with multicast messages very few are interested in. Listener 2 could certainly try to join 224.1.2.3 but it's the router that decides if this should be allowed.

In an enterprise setting, routers are usually configured to block multicast traffic other than within a subnet because then routers are not typically involved.

As mentioned before, if you are separating classes of traffic on the port, the routers won't be able to perform their work as efficiently since they usually don't care about the port.


问:
How to change which C++ version compiler is used when installing an R package from source?
I'm trying to install an R package from source using remotes::install_github("pkgname"). I get the following error:

```<code>/bin/sh: /usr/local/Cellar/gcc/9.2.0/bin/g++-7: No such file or directory
</code>```

I checked and I have g++-9 instead. I've been looking for a way to change the settings to direct to the correct path but so far have had no luck. I'm not even sure which package to look in or whether to approach R config files. Any help would be greatly appreciated.

I'm using R version 3.6.3 on Mac OSX 10.15.5 (Catalina). I have XCode developer tools installed but whenever I run checks RStudio suggests that I install them as if it can't find it.

Many thanks

答:
Besides what @bats_n_stats (great handle!) wrote, the following holds:

Each Rcpp use is driven by R itself

R can tell us what it uses via R CMD config calls. On my system

```<code>edd@rob:~$ R CMD config CXX
ccache g++
edd@rob:~$
</code>```

meaning the (standard) value of g++ (no qualified version) is used in conjunction with the accelerating cache provided by ccache (different topic, I blogged about it in the past)

You can also look at that via grep in the actual conffile (which I look up directly below)

```<code>edd@rob:~$ grep ^CXX $(R RHOME)/etc/Makeconf
CXX = g++ -std=gnu++11
CXXCPP = $(CXX) -E
CXXFLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXXPICFLAGS = -fpic
CXX11 = g++
CXX11FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX11PICFLAGS = -fpic
CXX11STD = -std=gnu++11
CXX14 = g++
CXX14FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX14PICFLAGS = -fpic
CXX14STD = -std=gnu++14
CXX17 = g++
CXX17FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX17PICFLAGS = -fpic
CXX17STD = -std=gnu++17
CXX20 = g++
CXX20FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX20PICFLAGS = -fpic
CXX20STD = -std=gnu++2a
CXX_VISIBILITY = -fvisibility=hidden
edd@rob:~$
</code>```

This values all come from when R itself was built. So if that bites on your Catalina system you need to review where you got R from and what can possibly be wrong there. Use of Cellar suggests something macOS specific and likely not the suggested R from the https://mac.r-project.org/ page.

Body:
I'm trying to install an R package from source using remotes::install_github("pkgname"). I get the following error:

/bin/sh: /usr/local/Cellar/gcc/9.2.0/bin/g++-7: No such file or directory

I checked and I have g++-9 instead. I've been looking for a way to change the settings to direct to the correct path but so far have had no luck. I'm not even sure which package to look in or whether to approach R config files. Any help would be greatly appreciated.

I'm using R version 3.6.3 on Mac OSX 10.15.5 (Catalina). I have XCode developer tools installed but whenever I run checks RStudio suggests that I install them as if it can't find it.

Many thanks

Body:
Besides what @bats_n_stats (great handle!) wrote, the following holds:

Each Rcpp use is driven by R itself

R can tell us what it uses via R CMD config calls. On my system

edd@rob:~$ R CMD config CXX
ccache g++
edd@rob:~$

meaning the (standard) value of g++ (no qualified version) is used in conjunction with the accelerating cache provided by ccache (different topic, I blogged about it in the past)

You can also look at that via grep in the actual conffile (which I look up directly below)

edd@rob:~$ grep ^CXX $(R RHOME)/etc/Makeconf
CXX = g++ -std=gnu++11
CXXCPP = $(CXX) -E
CXXFLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXXPICFLAGS = -fpic
CXX11 = g++
CXX11FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX11PICFLAGS = -fpic
CXX11STD = -std=gnu++11
CXX14 = g++
CXX14FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX14PICFLAGS = -fpic
CXX14STD = -std=gnu++14
CXX17 = g++
CXX17FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX17PICFLAGS = -fpic
CXX17STD = -std=gnu++17
CXX20 = g++
CXX20FLAGS = -g -O2 -fdebug-prefix-map=/build/r-base-Do_dS_/r-base-4.0.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g $(LTO)
CXX20PICFLAGS = -fpic
CXX20STD = -std=gnu++2a
CXX_VISIBILITY = -fvisibility=hidden
edd@rob:~$

This values all come from when R itself was built. So if that bites on your Catalina system you need to review where you got R from and what can possibly be wrong there. Use of Cellar suggests something macOS specific and likely not the suggested R from the https://mac.r-project.org/ page.


问:
Deploying Apache Beam pipeline on Alibaba cloud
I am new to Alibaba Cloud and I have an Apache Beam application running on Google Cloud Dataflow.
Now I want to deploy the same apache beam pipeline to Alibaba Cloud.
I am seeking help on how/what setups are needed to run an apache beam pipeline in Alibaba Cloud?
Is there a resource in Alibaba that is equivalent to Google Cloud Platform Dataflow?</p>

答:
You may try Alibaba DataStudio, in the Data Works section of the Alibaba Cloud Console as it is similar to Data Flow from google cloud .

You can drag and drop nodes to create a workflow, collaborate, integrate with other AC products etc.

Here is how you can create workflow: https://www.alibabacloud.com/help/doc-detail/85554.htm?spm=a2c63.l28256.a3.31.591c5b5aLHvJ68

It is not based on Apache Beam, but I believe that it will be available very soon.

Hope this will help to get idea about your needs, and what is offered right now.


问:
How to plot a histogram with colored bars in which the coloring should be in accordance to the value in x-axis?
I have written a code which gives me one histogram and one bar plot. My code looks this:
`

```<code>from math import pi, sin
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('seaborn-whitegrid')

with open('output.txt', 'r') as f:
    lines = f.readlines()
    x = [float(line.split()[12]) for line in lines]

b=[]
a=np.histogram(x,bins=[90,92.5,95,97.5,100,102.5,105,107.5,110,112.5,115,117.5,120,122.5,125,127.5,130,132.5,135,137.5,140,142.5,145,147.5,150,152.5,155,157.5,160,162.5,165,167.5,170,172.5,175,177.5,180])

for i in range(len(a[0])):
    a[0][i]=a[0][i]/sin((91.25 + 2.5*i)*pi/180)
    b.append((91.25 + 2.5*i))

plt.bar(b,a[0],2.5,edgecolor='black')
plt.xlabel('angle($\Theta$)($\circ$)')
plt.ylabel('corrected Frequency')
plt.title('corrected angle distribution')
plt.savefig('Cone_corrected_angle_distribution.jpg', dpi=600)
plt.show()

plt.hist(x,bins=[90,92.5,95,97.5,100,102.5,105,107.5,110,112.5,115,117.5,120,122.5,125,127.5,130,132.5,135,137.5,140,142.5,145,147.5,150,152.5,155,157.5,160,162.5,165,167.5,170,172.5,175,177.5,180],edgecolor='black')
plt.xlabel('angle($\Theta$)($\circ$)')
plt.ylabel('Frequency')
plt.title('Angle distribution')
plt.savefig('angle_distribution.jpg', dpi=600)
plt.show()
</code>```

`
Now, I want to do two modifications for the graph:

I want to color the bars of the histogram such that each bar has a unique color. The coloring of the bars should be according to the values of x-axis. And there should also be a color bar beneath the x-axis for reference.

I want to plot the kernel distribution function along with the histogram.The methods that I have tried, give me a normalised curve. But I want to plot it along the histogram.

It would be a great help!!

答:
The bars of a bar plot can be colored via the color= parameter which can either be one specific color or an array of colors. A histogram doesn't allow an array of colors, but the returned rectangles can be easily colored in a loop.

The kde is an estimation of the kernel density and is preferably calculated from the original x-values. It is normalized to have a surface area of 1, so simply multiply it by the area of the histogram (i.e. the sum of all heights times the bar width) to have similar proportions.

The code below first creates some random data. The different arrays in the original code are as much as possible calculated via numpy (which is faster and often more readable and easier to create variations by changing a value at only one spot).

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde

x = np.random.normal(135, 15, 1000)
bin_width = 2.5
bins_bounds = np.arange(90, 180.01, bin_width)
bin_values, _ = np.histogram(x, bins=bins_bounds)
bin_centers = (bins_bounds[:-1] + bins_bounds[1:]) / 2
bin_values = bin_values / np.sin(bin_centers * np.pi / 180)

plt.style.use('seaborn-whitegrid')
fig, ax = plt.subplots(ncols=2, figsize=(10, 4))
cmap = plt.cm.get_cmap('inferno')
norm = plt.Normalize(vmin=90, vmax=180)
colors = cmap(norm(bin_centers))
ax[0].bar(bin_centers, bin_values, bin_width, color=colors, edgecolor='black')
ax[0].set_xlabel('angle($\Theta$)($\circ$)')
ax[0].set_ylabel('corrected Frequency')
ax[0].set_title('corrected angle distribution')

sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
fig.colorbar(sm, ax=ax[0], orientation='horizontal')

_, _, bars = ax[1].hist(x, bins=bins_bounds, edgecolor='black')
for bar, color in zip(bars, colors):
    bar.set_facecolor(color)
xs = np.linspace(90, 180, 200)
kde = gaussian_kde(x)
ax[1]. plot(xs, kde(xs) * len(x) * bin_width, color='dodgerblue', lw=2)
ax[1].set_xlabel('angle($\Theta$)($\circ$)')
ax[1].set_ylabel('Frequency')
ax[1].set_title('Angle distribution')
fig.colorbar(sm, ax=ax[1], orientation='horizontal')
plt.tight_layout()
plt.show()
```

Body:
I have written a code which gives me one histogram and one bar plot. My code looks this:
`

from math import pi, sin
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('seaborn-whitegrid')

with open('output.txt', 'r') as f:
    lines = f.readlines()
    x = [float(line.split()[12]) for line in lines]

b=[]
a=np.histogram(x,bins=[90,92.5,95,97.5,100,102.5,105,107.5,110,112.5,115,117.5,120,122.5,125,127.5,130,132.5,135,137.5,140,142.5,145,147.5,150,152.5,155,157.5,160,162.5,165,167.5,170,172.5,175,177.5,180])

for i in range(len(a[0])):
    a[0][i]=a[0][i]/sin((91.25 + 2.5*i)*pi/180)
    b.append((91.25 + 2.5*i))

plt.bar(b,a[0],2.5,edgecolor='black')
plt.xlabel('angle($\Theta$)($\circ$)')
plt.ylabel('corrected Frequency')
plt.title('corrected angle distribution')
plt.savefig('Cone_corrected_angle_distribution.jpg', dpi=600)
plt.show()

plt.hist(x,bins=[90,92.5,95,97.5,100,102.5,105,107.5,110,112.5,115,117.5,120,122.5,125,127.5,130,132.5,135,137.5,140,142.5,145,147.5,150,152.5,155,157.5,160,162.5,165,167.5,170,172.5,175,177.5,180],edgecolor='black')
plt.xlabel('angle($\Theta$)($\circ$)')
plt.ylabel('Frequency')
plt.title('Angle distribution')
plt.savefig('angle_distribution.jpg', dpi=600)
plt.show()

`
Now, I want to do two modifications for the graph:

I want to color the bars of the histogram such that each bar has a unique color. The coloring of the bars should be according to the values of x-axis. And there should also be a color bar beneath the x-axis for reference.

I want to plot the kernel distribution function along with the histogram.The methods that I have tried, give me a normalised curve. But I want to plot it along the histogram.

It would be a great help!!


问:
C++ Function Calling Assembly Module
I want to write a customized module in assembly and have my C++ functions invoke it.  Instead of starting from scratch I would like to write the "draft" in C and let the compiler generates a blue print assembly source i.e.the listing file generated by the /FA compiler option.

However, I found that all the procedure names generated are already in decorated form.  Furthermore, the MASM will carry out its own name decoration again. So if I assemble my version without undecorating the compiler generated procedure name manually first I would get a linker error since the function names would not be matching.

Is possible to prevent this type of duplicated name decoration?

答: Declaring the function extern "C" should result in the generated assembler showing the name you should use in assembler.  Just don't forget to make it extern "C" in the header which declares it to C++ later.

Title: C++ Function Calling Assembly Module