问:
Does this implementation of merge sort use mutual recursion?
Does this mergeSort algorithm use mutual recursion?  I realize that mergeSort calls the merge function and it calls itself (mergeSort), but since merge does not call mergeSort is it not mutual recursion and simply just recursion?

```<code>function mergeSort(arr) {
    // split array
    ...
    return merge(mergSort(firstHalf), mergeSort(secondHalf));
}

function merge (array1, array2) {
    // merge both arrays
    ...
    return singleArray;
}
</code>```

答:
To follow up with an explanation about mutual recursion for merge sort, it is one of the methods used to optimize top down merge sort to avoid a copy step during the merge, where the direction of the merging depends on the level of recursion. The alternative to this is to pass a flag as a parameter for the direction to merge. In the example code below, a[] is the original array, b[] is the working array. TopDownSplitMergeAtoA returns with sorted data in the original array, and TopDownSplitMergeAtoB returns with sorted data in the working array, with TopDownSplitMergeAtoA  calling TopDownSplitMergeAtoB and vice versa (this is the mutual recursion). The only copy operation occurs if the sub-array size is one for TopDownSplitMergeAtoB, in which case one element is copied from the original array to the working array.</p>

```<code>void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee);
void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee);
void Merge(int a[], int b[], size_t ll, size_t rr, size_t ee);

void MergeSort(int a[], size_t n)       // entry function
{
    if(n < 2)                           // if size < 2 return
        return;
    int *b = new int[n];
    TopDownSplitMergeAtoA(a, b, 0, n);
    delete[] b;
}

void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1)                  // if size == 1 return
        return;
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoB(a, b, ll, rr);
    TopDownSplitMergeAtoB(a, b, rr, ee);
    Merge(b, a, ll, rr, ee);     // merge b to a
}

void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1){                 // if size == 1 copy a to b
        b[ll] = a[ll];
        return;
    }
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoA(a, b, ll, rr);
    TopDownSplitMergeAtoA(a, b, rr, ee);
    Merge(a, b, ll, rr, ee);     // merge a to b
}

void Merge(int a[], int b[], size_t ll, size_t rr, size_t ee)
{
    size_t o = ll;                      // b[]       index
    size_t l = ll;                      // a[] left  index
    size_t r = rr;                      // a[] right index
    while(1){                           // merge data
        if(a[l] <= a[r]){               // if a[l] <= a[r]
            b[o++] = a[l++];            //   copy a[l]
            if(l < rr)                  //   if not end of left run
                continue;               //     continue (back to while)
            while(r < ee)               //   else copy rest of right run
                b[o++] = a[r++];
            break;                      //     and return
        } else {                        // else a[l] > a[r]
            b[o++] = a[r++];            //   copy a[r]
            if(r < ee)                  //   if not end of right run
                continue;               //     continue (back to while)
            while(l < rr)               //   else copy rest of left run
                b[o++] = a[l++];
            break;                      //     and return
        }
    }
}
</code>```

Body:
Does this mergeSort algorithm use mutual recursion?  I realize that mergeSort calls the merge function and it calls itself (mergeSort), but since merge does not call mergeSort is it not mutual recursion and simply just recursion?

function mergeSort(arr) {
    // split array
    ...
    return merge(mergSort(firstHalf), mergeSort(secondHalf));
}

function merge (array1, array2) {
    // merge both arrays
    ...
    return singleArray;
}

Body:
To follow up with an explanation about mutual recursion for merge sort, it is one of the methods used to optimize top down merge sort to avoid a copy step during the merge, where the direction of the merging depends on the level of recursion. The alternative to this is to pass a flag as a parameter for the direction to merge. In the example code below, a[] is the original array, b[] is the working array. TopDownSplitMergeAtoA returns with sorted data in the original array, and TopDownSplitMergeAtoB returns with sorted data in the working array, with TopDownSplitMergeAtoA  calling TopDownSplitMergeAtoB and vice versa (this is the mutual recursion). The only copy operation occurs if the sub-array size is one for TopDownSplitMergeAtoB, in which case one element is copied from the original array to the working array.

void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee);
void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee);
void Merge(int a[], int b[], size_t ll, size_t rr, size_t ee);

void MergeSort(int a[], size_t n)       // entry function
{
    if(n < 2)                           // if size < 2 return
        return;
    int *b = new int[n];
    TopDownSplitMergeAtoA(a, b, 0, n);
    delete[] b;
}

void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1)                  // if size == 1 return
        return;
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoB(a, b, ll, rr);
    TopDownSplitMergeAtoB(a, b, rr, ee);
    Merge(b, a, ll, rr, ee);     // merge b to a
}

void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1){                 // if size == 1 copy a to b
        b[ll] = a[ll];
        return;
    }
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoA(a, b, ll, rr);
    TopDownSplitMergeAtoA(a, b, rr, ee);
    Merge(a, b, ll, rr, ee);     // merge a to b
}

void Merge(int a[], int b[], size_t ll, size_t rr, size_t ee)
{
    size_t o = ll;                      // b[]       index
    size_t l = ll;                      // a[] left  index
    size_t r = rr;                      // a[] right index
    while(1){                           // merge data
        if(a[l] <= a[r]){               // if a[l] <= a[r]
            b[o++] = a[l++];            //   copy a[l]
            if(l < rr)                  //   if not end of left run
                continue;               //     continue (back to while)
            while(r < ee)               //   else copy rest of right run
                b[o++] = a[r++];
            break;                      //     and return
        } else {                        // else a[l] > a[r]
            b[o++] = a[r++];            //   copy a[r]
            if(r < ee)                  //   if not end of right run
                continue;               //     continue (back to while)
            while(l < rr)               //   else copy rest of left run
                b[o++] = a[l++];
            break;                      //     and return
        }
    }
}


来源: stackexchange

问:
AWS Aurora cache metrics meanings
Aurora has two query-cache related metrics :

Buffer cache hit ratio : The percentage of requests that are served by the Buffer cache.

Resultset cache hit ratio : The percentage of requests that are served by the Resultset cache.

http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.Monitoring.html

But I can't find the documentation that explains the difference between "Buffer cache" and "Resultset cache".

What are they?

答:
"Resultset Cache Hit Ratio" is related to the query cache, which is a feature that enables caching the read queries' results (that's why called result set cache hit). So,if the engine started to execute a new read query, it will check the cached results before executing the query itself and if it found that this same query has been executed before and that its result wasn't invalidated yet, then it will serve the result of the new query from the cache. This is generally useful & shows up high in number when the workload contains a lot of similar select queries that has the similar values and conditions.

On the other hand, "Buffer Cache Hit Ratio" is more related to the innodb page caching hit ratio (& not the query result cache), and this should increase with increasing all types of read queries, as this process is called by bufferpool warm up which will cause the engine to load all the needed pages from the storage to the memory for faster access to the data. However, with increased amount of writes to the writer, this will make the readers to invalidate there in memory pages then load these pages again from the storage when needed. The "ratio" here depends on the percentage of hitting the in memory pages which should be very high ex: more than 99%.

Query cache is generally considered with low connections, similar type of queries over & over again (based on few observations on mysql/aurora, query cache might be actually bad for performance if you have high no. of connections & lots of adhoc style, changing queries).

ContentLicense: CC BY-SA 3.0

Title: AWS Aurora cache metrics meanings


问:
PDO how do I returns the total number of executed queries
With mysql wrapper

```<code>function query($msql)
{
    $this->last_connection =& $this->connection;
    $this->msql =& $msql;
    $queryult = mysql_query($msql, $this->connection);
    if ($queryult) {
        $this->queries_count++;
        return $queryult;
    } else {
        $this->display_errors();
        return false;
    }
}

function num_queries()
{
    return @$this->queries_count;
}
</code>```

With PDO how to get the total number of executed queries.

答: PDO does not count queries. You have to implement it yourself e.g. with a custom extension of the PDO class.</p>

ContentLicense: CC BY-SA 2.5

Body:
With mysql wrapper

function query($msql)
{
    $this->last_connection =& $this->connection;
    $this->msql =& $msql;
    $queryult = mysql_query($msql, $this->connection);
    if ($queryult) {
        $this->queries_count++;
        return $queryult;
    } else {
        $this->display_errors();
        return false;
    }
}

function num_queries()
{
    return @$this->queries_count;
}

With PDO how to get the total number of executed queries.


问:
Alter user defined type in SQL Server
I created few user defined types in my database as below

```<code>CREATE TYPE [dbo].[StringID] FROM [nvarchar](20) NOT NULL
</code>```

and assigned them to various tables. The tables in my database are in various schemas (not only dbo)

But I realized I need bigger field, and I need to alter, e.g increase from [nvarchar](20) to [nvarchar](50), but there is no ALTER TYPE statement.

I need a script that uses a temp table/cursor whatever and saves all the tables and fields where my type is used. Then change existing fields to base type - e.g. from CustID [StringID] to CustID [nvarchar(20)].
Drop the user type and recreate it with new type - e.g. nvarchar(50)
and finally set back fields to user type

I do not have rules defined on types, so don't have to drop rules and re-add them.

Any help is appreciated.

答:
New answer to an old question:

Visual Studio Database Projects handle the drop and recreate process when you deploy changes. It will drop stored procs that use UDDTs and then recreate them after dropping and recreating the data type.

ContentLicense: CC BY-SA 4.0

Title: Alter user defined type in SQL Server

Body:
I created few user defined types in my database as below

CREATE TYPE [dbo].[StringID] FROM [nvarchar](20) NOT NULL

and assigned them to various tables. The tables in my database are in various schemas (not only dbo)

But I realized I need bigger field, and I need to alter, e.g increase from [nvarchar](20) to [nvarchar](50), but there is no ALTER TYPE statement.

I need a script that uses a temp table/cursor whatever and saves all the tables and fields where my type is used. Then change existing fields to base type - e.g. from CustID [StringID] to CustID [nvarchar(20)].
Drop the user type and recreate it with new type - e.g. nvarchar(50)
and finally set back fields to user type

I do not have rules defined on types, so don't have to drop rules and re-add them.

Any help is appreciated.


问:
Why does a closure introduce a borrow when the same code inlined does not?
This code works:

```<code>extern crate num;

use num::{BigInt, FromPrimitive, Zero};

fn sample() {
    let mut to_factor = "600851475143".parse::<BigInt>().unwrap();

    let mut prime = BigInt::from_i32(2).unwrap();

    let zero = BigInt::zero();

    //let is_div = |n, p| { n % p == zero};

    loop {
        if &to_factor % &prime == zero {
            to_factor = &to_factor / ′
        } else {
            break;
        }
    }

    println!("{}", to_factor);
}
</code>```

but if I try to replace the condition in the loop with a closure, it doesn't compile anymore:

```<code>fn sample() {
    let mut to_factor = "600851475143".parse::<BigInt>().unwrap();

    let mut prime = BigInt::from_i32(2).unwrap();

    let zero = BigInt::zero();

    let is_div = |n, p| { n % p == zero};

    loop {
        if is_div(&to_factor, &prime) {
            to_factor = &to_factor / ′
        } else {
            break;
        }
    }

    println!("{}", to_factor);
}
</code>```

The error is as follows:

error[E0506]: cannot assign to `to_factor` because it is borrowed
  --> src/main.rs:16:13
   |
15 |         if is_div(&to_factor, &prime) {
   |                    --------- borrow of `to_factor` occurs here
16 |             to_factor = &to_factor / ′
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `to_factor` occurs here
```

<p>It seems fine to me -- the borrow should be "over" by the time we alter <code>to_factor</code>, certainly?</p>

<p>To increase the confusion, if I replace <code>is_div</code> with an actual function:</p>

```fn is_div(n: &BigInt, p: &BigInt) -> bool {
    return to_factor % p == BigInt::zero()
}
```

it works fine.

I am a beginner in Rust, but not to programming generally. I'm pretty sure this has to do with ownership, but it might also have to do with how closures are implemented?

These examples are a MWE from the actual code I was trying to write. They're not really meaningful at this point but they demonstrate the same compile error.

答:
You are running into a implementation limitation of the Rust type system, specifically with regards to type inference of closure arguments. Namely, the inferred types are subtly different when you declare a closure that isn't immediately used compared to a closure that is immediately used.

This closure works because type inference can immediately connect the parameters to the arguments:

```<code>loop {
    if (|n, p| n % p == zero)(&to_factor, &prime) {
        to_factor = &to_factor / ′
    } else {
        break;
    }
}
</code>```

This also works, as we define the types of the arguments immediately:

```<code>let is_div = |n: &BigInt, p: &BigInt| n % p == zero;

loop {
    if is_div(&to_factor, &prime) {
        to_factor = &to_factor / ′
    } else {
        break;
    }
}
</code>```

This is also the reason that your function version worked.

There are a multitude of issues about this on the issue tracker (it's a very hard thing to search for!), but 12679 is an older one.

This is a reason you often see closures defined inline.

Body:
This code works:

extern crate num;

use num::{BigInt, FromPrimitive, Zero};

fn sample() {
    let mut to_factor = "600851475143".parse::<BigInt>().unwrap();

    let mut prime = BigInt::from_i32(2).unwrap();

    let zero = BigInt::zero();

    //let is_div = |n, p| { n % p == zero};

    loop {
        if &to_factor % &prime == zero {
            to_factor = &to_factor / ′
        } else {
            break;
        }
    }

    println!("{}", to_factor);
}

but if I try to replace the condition in the loop with a closure, it doesn't compile anymore:

fn sample() {
    let mut to_factor = "600851475143".parse::<BigInt>().unwrap();

    let mut prime = BigInt::from_i32(2).unwrap();

    let zero = BigInt::zero();

    let is_div = |n, p| { n % p == zero};

    loop {
        if is_div(&to_factor, &prime) {
            to_factor = &to_factor / ′
        } else {
            break;
        }
    }

    println!("{}", to_factor);
}

The error is as follows:

error[E0506]: cannot assign to `to_factor` because it is borrowed
  --> src/main.rs:16:13
   |
15 |         if is_div(&to_factor, &prime) {
   |                    --------- borrow of `to_factor` occurs here
16 |             to_factor = &to_factor / ′
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `to_factor` occurs here

It seems fine to me -- the borrow should be "over" by the time we alter to_factor, certainly?

To increase the confusion, if I replace is_div with an actual function:

fn is_div(n: &BigInt, p: &BigInt) -> bool {
    return to_factor % p == BigInt::zero()
}

it works fine.

I am a beginner in Rust, but not to programming generally. I'm pretty sure this has to do with ownership, but it might also have to do with how closures are implemented?

These examples are a MWE from the actual code I was trying to write. They're not really meaningful at this point but they demonstrate the same compile error.

Body:
You are running into a implementation limitation of the Rust type system, specifically with regards to type inference of closure arguments. Namely, the inferred types are subtly different when you declare a closure that isn't immediately used compared to a closure that is immediately used.

This closure works because type inference can immediately connect the parameters to the arguments:

loop {
    if (|n, p| n % p == zero)(&to_factor, &prime) {
        to_factor = &to_factor / &prime;
    } else {
        break;
    }
}

This also works, as we define the types of the arguments immediately:

let is_div = |n: &BigInt, p: &BigInt| n % p == zero;

loop {
    if is_div(&to_factor, &prime) {
        to_factor = &to_factor / &prime;
    } else {
        break;
    }
}

This is also the reason that your function version worked.

There are a multitude of issues about this on the issue tracker (it's a very hard thing to search for!), but 12679 is an older one.

This is a reason you often see closures defined inline.


问:
How can I check if an element contains another element using $(this)?
I'm trying to check if an element contains an input element in the following function

```<code> $(document).on("click", ".edit_text", function() {
    if($(this).children().is("input")) {
      $(this).html("<input type='text'>")
    }
 })
</code>```

I can't figure a way of doing this as all the solutions point to using the selector such as $(".edit_text :contains(input)")

I need to use $(this) as I am using the function on elements that have a class and not on a specific element.

Is there any way of achieving this?

答:
Try :has() as in:

```<code>if($(':has("input")', this)) {
</code>```

As the docs for :has() state:

Selects elements which contain at least one element that matches the
  specified selector.

:has() searches all descendants, not just children. Or you could use .has() like:

```<code>if($(this).has("input")) {
</code>```

Usually .has() performs better than :has()

Body:
I'm trying to check if an element contains an input element in the following function

 $(document).on("click", ".edit_text", function() {
    if($(this).children().is("input")) {
      $(this).html("<input type='text'>")
    }
 })

I can't figure a way of doing this as all the solutions point to using the selector such as $(".edit_text :contains(input)")

I need to use $(this) as I am using the function on elements that have a class and not on a specific element.

Is there any way of achieving this?

Body:
Try :has() as in:

if($(':has("input")', this)) {

As the docs for :has() state:

Selects elements which contain at least one element that matches the
  specified selector.

:has() searches all descendants, not just children. Or you could use .has() like:

if($(this).has("input")) {

Usually .has() performs better than :has()


问:
Why do we wrap a SSL public key with a certificate?
With some research I know

how the public/private keys work

SSL certificate wraps the public key

given a Certificate Signing Requests (CSR), Certificate Authorities (CA) issues certificates

when an user first connects to an SSL-secured website, the user first verifies the certificate with a trusted third party

I read that SSL certificates promise users that they are connecting to the party which they think they are connecting to. What does this mean? What extra security does wrapping the public key provide us, as opposed to just having the public key itself? An example would be greatly appreciated.

E.g. If Facebook only gives me its public key, instead of an SSL certificate wrapping the public key, what dangers would I be exposed to? Is making sure the address bar reading https://www.facebook.com/ not enough?

答:
By wrapping the public key in a certificate you can verify that:

The key really belongs to the party you want to access. The certificate provides this by having the domain in the subject. And you know you can trust this information because the certificate is directly or indirectly signed by a locally trusted certificate agency.

The key is still valid and not compromised. The certificate has a lifetime (begin and end) and can also be revoked.

The key can be used for server authentication. The issuing CA puts the appropriate key usage information into the certificate.


问:
go and multicast (ospf specifically)
I'm trying to listen for OSPFv2 Hello messages as follows:

```<code>    ens192, err := net.InterfaceByName("ens192")
    if err != nil {
            return err
    }
    c, err := net.ListenPacket("ip4:89", "0.0.0.0") // ipv4 proto 89, all local interfaces
    if err != nil {
            return err
    }
    defer c.Close()

    p := ipv4.NewPacketConn(c)
    if err != nil {
            return err
    }

    allSPFRouters := net.ParseIP("224.0.0.5")
    if err := p.JoinGroup(ens192, &net.IPAddr{IP: allSPFRouters}); err != nil {
            return err
    }

    if err := p.SetControlMessage(ipv4.FlagDst|ipv4.FlagSrc|ipv4.FlagInterface, true); err != nil {
            return err
    }

    b := make([]byte, 8192)
    for {
            n, cm, src, err := p.ReadFrom(b)
            _ = n
            if err != nil {
                    return err
            }
            if cm.Dst.IsMulticast() {
                    if cm.Dst.Equal(allSPFRouters) {
                            hdr := &ospfHeader{}
                            hdr.Decode(b)
                            fmt.Printf("%s\n", hdr)
                    } else {
                            // ignore/discard
                            fmt.Printf("Received packet from: %v to %v\n", src, cm.Dst)
                            continue
                    }
            } else {
                    fmt.Printf("Not mcast\n")
            }
    }
</code>```

but I can only see locally generated OSPF messages (ie. from OSPF process on local machine). I can't see any OSPF packets coming from remote machines (I can see them with tcpdump though).
Any ideas what's wrong with the code above? Why I can only see local Hellos and not remote...?

答: Problem solved. The code is OK - the "problem" is red hat and it's firewalld...</p>

Title: go and multicast (ospf specifically)

Body:
I'm trying to listen for OSPFv2 Hello messages as follows:

    ens192, err := net.InterfaceByName("ens192")
    if err != nil {
            return err
    }
    c, err := net.ListenPacket("ip4:89", "0.0.0.0") // ipv4 proto 89, all local interfaces
    if err != nil {
            return err
    }
    defer c.Close()

    p := ipv4.NewPacketConn(c)
    if err != nil {
            return err
    }

    allSPFRouters := net.ParseIP("224.0.0.5")
    if err := p.JoinGroup(ens192, &net.IPAddr{IP: allSPFRouters}); err != nil {
            return err
    }

    if err := p.SetControlMessage(ipv4.FlagDst|ipv4.FlagSrc|ipv4.FlagInterface, true); err != nil {
            return err
    }

    b := make([]byte, 8192)
    for {
            n, cm, src, err := p.ReadFrom(b)
            _ = n
            if err != nil {
                    return err
            }
            if cm.Dst.IsMulticast() {
                    if cm.Dst.Equal(allSPFRouters) {
                            hdr := &ospfHeader{}
                            hdr.Decode(b)
                            fmt.Printf("%s\n", hdr)
                    } else {
                            // ignore/discard
                            fmt.Printf("Received packet from: %v to %v\n", src, cm.Dst)
                            continue
                    }
            } else {
                    fmt.Printf("Not mcast\n")
            }
    }

but I can only see locally generated OSPF messages (ie. from OSPF process on local machine). I can't see any OSPF packets coming from remote machines (I can see them with tcpdump though).
Any ideas what's wrong with the code above? Why I can only see local Hellos and not remote...?


问:
How do I remove illegal characters from an NSString?
I am parsing a tab seperated list using a NSScanner based upon each line and the tabs. However for some reason the last field in the array (parsed from each row) contains a \r character.

How can I strip this from the NSString that represents the line (or the field)

答: Just FYI, The \r is part of the line ending for a file created in a windows environment.</p>

OwnerDisplayName: tigermain

LastEditorDisplayName: Chris Hanson

OwnerDisplayName: Matthew Brubaker


问:
Split a string into a String[] of a specific size
Assuming my delimiter is ',' (comma), I'm looking for a function split that will guarantee that the returned String[] array is a certain size (no more, no less):

```<code>String[] split(String str, int limit);

split("hello", 2);               => ["hello", ""]
split("hello,", 2);              => ["hello", ""]
split(",hello", 2);              => ["", "hello"]
split("hello,world", 2);         => ["hello", "world"]
split("hello,world,goodbye", 2); => ["hello", "world,goodbye"]
</code>```

See how the array size is always 2? I can get some of this behavior with Pattern.split, but not for every case... How can I do this?

答:
Well, if I understood you correctly you just want to stop splitting as soon as you have a reached the count provided via argument and move the remaining bit wholly into the last field, right? In addition, the limit-parameter should always ensure the fieldcount?

Wrap a method around the Pattern.split() method which just adds fields until your limit/threshold/minimum is reached.

```<code>for(i=0;i<limit;++i){
 //add empty fields to array until limit is reached
}
</code>```

Body:
Assuming my delimiter is ',' (comma), I'm looking for a function split that will guarantee that the returned String[] array is a certain size (no more, no less):

String[] split(String str, int limit);

split("hello", 2);               => ["hello", ""]
split("hello,", 2);              => ["hello", ""]
split(",hello", 2);              => ["", "hello"]
split("hello,world", 2);         => ["hello", "world"]
split("hello,world,goodbye", 2); => ["hello", "world,goodbye"]

See how the array size is always 2? I can get some of this behavior with Pattern.split, but not for every case... How can I do this?

Body:
Well, if I understood you correctly you just want to stop splitting as soon as you have a reached the count provided via argument and move the remaining bit wholly into the last field, right? In addition, the limit-parameter should always ensure the fieldcount?

Wrap a method around the Pattern.split() method which just adds fields until your limit/threshold/minimum is reached.

for(i=0;i<limit;++i){
 //add empty fields to array until limit is reached
}


问:
R Shiny app with ggplot2 error
I am trying to build my first shiny app and have come across an error I can't resolve. I have searched and searched but can't seem to find an answer that resolves this question.

My code is below using the mtcars dataset. The goal is to develop visual and text analysis tools for a survey dataset. I currently have two drop down menus with survey questions, a drop down menu with a grouping variable menu, and some radio buttons for plot types. I am trying to create the first plot - a histogram. After I run the code I get the correctly rendered data tables, but no histogram plot - and the error:

object 's1' not found

I have tried this with and without wrapping my ggplot code with print().

Any help would be very appreciated !

Thanks!

```<code>library(shiny)
install.packages("shinythemes")
library(shinythemes)
library(ggplot2)
library(dplyr)

mt <- mtcars
ui <- fluidPage(theme=shinytheme("readable"),

                titlePanel("Test"),

                sidebarLayout(

                  sidebarPanel(
                    # use mpg and cyl as survey option groups
                    selectizeInput(inputId = 's1',
                                   label = 'Survey Question 1 (X-Axis)',
                                   choices = c("mpg", "cyl")),

                    selectizeInput(inputId = 's2',
                                   label ='Survey Question 2 (Y-Axis)',
                                   choices = c("mpg", "cyl")),

                    # use gear and vs as grouping variables
                    selectizeInput(inputId = 'g',
                                   label = 'Group By',
                                   choices = c("Gear"="gear", "VS" = "vs")),

                    # use radio buttons for pot type options
                    radioButtons(inputId = 'plottype',
                                label = 'Plot Type',
                                choices = c("Histogram" = "geom_histogram", "Box Plot" = "geom_boxplot", "Scatterplot" = "geom_point")
                    )
                  ),
                      mainPanel(
                        plotOutput("plot1"), # ui for plot
                        verbatimTextOutput("table1") # ui for table
                    )
                  )
)

server <- function(input, output, session) {

## subset dataset to include only two options for now - include grouping after
  plotData <- reactive({
    ((mt[,c(input$s1,input$s2)])) ## data for plot
  })

## render hist plot in ggplot
output$plot1 <- renderPlot({
  d1<-(plotData())
 print(ggplot(d1, aes(x=s1)) + geom_histogram(fill = "dark green", alpha = 0.6, binwidth = 1))
  print(str(d1))
  })

## render summary table for survey questions
output$table1 <- renderPrint({
  summary(plotData())
  })
}
shinyApp(ui = ui, server = server)

## but this works
ggplot(mt, aes(x=mpg)) + geom_histogram(fill = "dark green", alpha = 0.6, binwidth = 1)
</code>```

答: There's no column s1 in the data set d1. Use ggplot(d1, aes_string(x=input$s1)).

Title: R Shiny app with ggplot2 error

Body:
I am trying to build my first shiny app and have come across an error I can't resolve. I have searched and searched but can't seem to find an answer that resolves this question.

My code is below using the mtcars dataset. The goal is to develop visual and text analysis tools for a survey dataset. I currently have two drop down menus with survey questions, a drop down menu with a grouping variable menu, and some radio buttons for plot types. I am trying to create the first plot - a histogram. After I run the code I get the correctly rendered data tables, but no histogram plot - and the error:

object 's1' not found

I have tried this with and without wrapping my ggplot code with print().

Any help would be very appreciated !

Thanks!

library(shiny)
install.packages("shinythemes")
library(shinythemes)
library(ggplot2)
library(dplyr)

mt <- mtcars
ui <- fluidPage(theme=shinytheme("readable"),

                titlePanel("Test"),

                sidebarLayout(

                  sidebarPanel(
                    # use mpg and cyl as survey option groups
                    selectizeInput(inputId = 's1',
                                   label = 'Survey Question 1 (X-Axis)',
                                   choices = c("mpg", "cyl")),

                    selectizeInput(inputId = 's2',
                                   label ='Survey Question 2 (Y-Axis)',
                                   choices = c("mpg", "cyl")),

                    # use gear and vs as grouping variables
                    selectizeInput(inputId = 'g',
                                   label = 'Group By',
                                   choices = c("Gear"="gear", "VS" = "vs")),

                    # use radio buttons for pot type options
                    radioButtons(inputId = 'plottype',
                                label = 'Plot Type',
                                choices = c("Histogram" = "geom_histogram", "Box Plot" = "geom_boxplot", "Scatterplot" = "geom_point")
                    )
                  ),
                      mainPanel(
                        plotOutput("plot1"), # ui for plot
                        verbatimTextOutput("table1") # ui for table
                    )
                  )
)

server <- function(input, output, session) {

## subset dataset to include only two options for now - include grouping after
  plotData <- reactive({
    ((mt[,c(input$s1,input$s2)])) ## data for plot
  })

## render hist plot in ggplot
output$plot1 <- renderPlot({
  d1<-(plotData())
 print(ggplot(d1, aes(x=s1)) + geom_histogram(fill = "dark green", alpha = 0.6, binwidth = 1))
  print(str(d1))
  })

## render summary table for survey questions
output$table1 <- renderPrint({
  summary(plotData())
  })
}
shinyApp(ui = ui, server = server)

## but this works
ggplot(mt, aes(x=mpg)) + geom_histogram(fill = "dark green", alpha = 0.6, binwidth = 1)


问:
First steps in python: how to combine two lists
So I just started learning a few basics with Python. Since I am a pretty practical person, I enjoy doing it with the book "Automate the boring stuff with Python".

No there is a chapter introducing lists in python and their advantages.
To be practical one should write a code which asks the user to enter cat names, which then will be added to the list. If no cat name is added anymore, all the cat names should be displayed.

Until now, fair enough. So I thought I should give it a try and go a small step further and extend the functionality by adding the ages of the cats. The desired result would be that the user is asked for the name input, then the age input, the name input again and the age input again and so on. If the user doesn´t put in a name again, it should list the cats with the respective ages.

I created a second list and also the second input and everything kinda works but I just dont know how to combine the both lists or rather the values.

It just gives me the two names first and then the two ages.

Is anyone happy to help me with this beginner problem?

Thanks in advance

```<code>catNames = []
catAges = []

while True:
    print("Enter the name of Cat " + str(len(catNames) + 1) + "(Or enter
          nothing to stop.)")
    name = input()
    while name !="":
        print("Enter the age of cat ")
        age = input()
        break

    if name == "":
        print("The cat names and ages are: ")
        for name in catNames:
            print(" " + name)
        for age in catAges:
            print(" " + age)
        break
    catNames = catNames + [name]
    catAges = catAges + [age]
</code>```

答:
I think you're looking for zip:

```<code>catNames = ['Fluffy', 'Whiskers', 'Bob']
catAges = [5, 18, 2]
catZip = zip(catNames, catAges)
print(list(catZip))
</code>```

Out:

```<code>[('Fluffy', 5), ('Whiskers', 18), ('Bob', 2)]
</code>```

Body:
So I just started learning a few basics with Python. Since I am a pretty practical person, I enjoy doing it with the book "Automate the boring stuff with Python".

No there is a chapter introducing lists in python and their advantages.
To be practical one should write a code which asks the user to enter cat names, which then will be added to the list. If no cat name is added anymore, all the cat names should be displayed.

Until now, fair enough. So I thought I should give it a try and go a small step further and extend the functionality by adding the ages of the cats. The desired result would be that the user is asked for the name input, then the age input, the name input again and the age input again and so on. If the user doesn´t put in a name again, it should list the cats with the respective ages.

I created a second list and also the second input and everything kinda works but I just dont know how to combine the both lists or rather the values.

It just gives me the two names first and then the two ages.

Is anyone happy to help me with this beginner problem?

Thanks in advance

catNames = []
catAges = []

while True:
    print("Enter the name of Cat " + str(len(catNames) + 1) + "(Or enter
          nothing to stop.)")
    name = input()
    while name !="":
        print("Enter the age of cat ")
        age = input()
        break

    if name == "":
        print("The cat names and ages are: ")
        for name in catNames:
            print(" " + name)
        for age in catAges:
            print(" " + age)
        break
    catNames = catNames + [name]
    catAges = catAges + [age]

Body:
I think you're looking for zip:

catNames = ['Fluffy', 'Whiskers', 'Bob']
catAges = [5, 18, 2]
catZip = zip(catNames, catAges)
print(list(catZip))

Out:

[('Fluffy', 5), ('Whiskers', 18), ('Bob', 2)]


问:
How Spring data jpa checks whether to perform update or save?
Spring data jpa contains only save method unlike hibernate where we have save as well as update method. So how spring data jpa checks whether to update or save the current object .</p>

答:
spring data detect automatically what should be create or update.
Source code for save method in for example in SimpleJpaRepository (implement CrudRepository) in case if your entity implements Persistable

```<code>public <S extends T> S save(S entity) {
    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}
</code>```

so , there is a check what to do with entity save it or update based on if entity is new - then save it. is new check it's just check that id not null

for exaple if an entity implements Persistable :

```<code>public boolean isNew() {
    return null == getId();
}
</code>```

Body:
spring data detect automatically what should be create or update.
Source code for save method in for example in SimpleJpaRepository (implement CrudRepository) in case if your entity implements Persistable

public <S extends T> S save(S entity) {
    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

so , there is a check what to do with entity save it or update based on if entity is new - then save it. is new check it's just check that id not null

for exaple if an entity implements Persistable :

public boolean isNew() {
    return null == getId();
}


答:
You could do it with a loop that scans the string searching for the delimiter, then put whatever is not ahead of the delimiter in the array, then re-do it until it hits the top array size, that way it just return whatever was ahead as the last entry in the array:

```<code>public string[] mySplit(String Split, char Delimiter, int Top)
 {
  string[] returned = new string[Top];
  for(int i = 0; i < Top; i++){
    if(i==Top)
    {
     returned[i] = Split; return;
    }
    else
    {
     int compPlace = 0;
     char comp = Split.toCharArray()[compPlace];
     while(comp != Delimiter)
     {
      compPlace++;
      comp = Split.toCharArray()[compPlace];
      }
    returned[i] = Split.SubString(0,compPlace);
    Split = Split.SubString(compPlace);
    }
  }
  return returned;
}
</code>```

Im sure youll have to tweak this as i have a little headache as of now :)

Title: Split a string into a String[] of a specific size

Body:
You could do it with a loop that scans the string searching for the delimiter, then put whatever is not ahead of the delimiter in the array, then re-do it until it hits the top array size, that way it just return whatever was ahead as the last entry in the array:

public string[] mySplit(String Split, char Delimiter, int Top)
 {
  string[] returned = new string[Top];
  for(int i = 0; i < Top; i++){
    if(i==Top)
    {
     returned[i] = Split; return;
    }
    else
    {
     int compPlace = 0;
     char comp = Split.toCharArray()[compPlace];
     while(comp != Delimiter)
     {
      compPlace++;
      comp = Split.toCharArray()[compPlace];
      }
    returned[i] = Split.SubString(0,compPlace);
    Split = Split.SubString(compPlace);
    }
  }
  return returned;
}

Im sure youll have to tweak this as i have a little headache as of now :)


问:
iOS 10 : CSS styles not being applied on class change
I am using ionic with angular to create an app for Android and iOS.  On android everything is working fine.  iOS is the problem (of course).

I am applying a class change to an element using ng-class.  I can see the class change in the safari inspector in the HTML and the CSS.  But I do not see the changes on the screen.  The only way I can see the change is if I were to manipulate the CSS selector (as simple as turning on/off a style).

Here's the HTML with Angular:

```<code><div class="avatar-view__initial__question question-hide" ng-class="{'question-show': speech.captured === true, 'question-hide': speech.captured === false}">{{question.text}}</div>
</code>```

and the CSS

```<code>  .avatar-view__initial__question {
    text-align: left;
    background-color: #E9EBEF;
    font-size: 1.5em;
    position: relative;
    background-image: url(../img/icons/icon-ear.svg);
    background-size: 50px;
    background-repeat: no-repeat;
    background-position: 10px center;
    flex-shrink:1;
    @extend .css-animate;

    &.question-show {
      padding: 20px 10px 20px 60px;
      height: auto !important;
    }
    &.question-hide {
      height:0 !important;
      padding:0 10px 0 60px;
    }
  }
</code>```

As I mentioned, the CSS IS being applied, though I can not view the change until I manipulate the any style (pertaining to the element) in the inspector.

Is this a bug? or something I can work around?

UPDATE  I just tried this on an iOS 9 device and it works perfectly.  It seems to be a 10 problem.

UPDATE 2 I feel like it's a flexbox problem.  I had them filling the screen as a column, but I was giving the bottom one zero height when it had no content in it.  It was acting funny.  I reformatted the html to make it work differently.  But I'd like to keep this out there in case someone else is having this issue.

答:
From what I understand it's an issue of the iOS 10 webview not re-rendering the template, even though the class has correctly changed and been applied.

So what we want to achieve is enforce a template re-render on class change. We know that the class changes every time the object member speech.captured changes value.

So we could enforce re-render when whenever this value changes by adding a conditionally rendered empty span like this:

{{question.text}}

```

Body:
I am using ionic with angular to create an app for Android and iOS.  On android everything is working fine.  iOS is the problem (of course).

I am applying a class change to an element using ng-class.  I can see the class change in the safari inspector in the HTML and the CSS.  But I do not see the changes on the screen.  The only way I can see the change is if I were to manipulate the CSS selector (as simple as turning on/off a style).

Here's the HTML with Angular:

{{question.text}}

and the CSS

  .avatar-view__initial__question {
    text-align: left;
    background-color: #E9EBEF;
    font-size: 1.5em;
    position: relative;
    background-image: url(../img/icons/icon-ear.svg);
    background-size: 50px;
    background-repeat: no-repeat;
    background-position: 10px center;
    flex-shrink:1;
    @extend .css-animate;

    &.question-show {
      padding: 20px 10px 20px 60px;
      height: auto !important;
    }
    &.question-hide {
      height:0 !important;
      padding:0 10px 0 60px;
    }
  }

As I mentioned, the CSS IS being applied, though I can not view the change until I manipulate the any style (pertaining to the element) in the inspector.

Is this a bug? or something I can work around?

UPDATE  I just tried this on an iOS 9 device and it works perfectly.  It seems to be a 10 problem.

UPDATE 2 I feel like it's a flexbox problem.  I had them filling the screen as a column, but I was giving the bottom one zero height when it had no content in it.  It was acting funny.  I reformatted the html to make it work differently.  But I'd like to keep this out there in case someone else is having this issue.

Body:
From what I understand it's an issue of the iOS 10 webview not re-rendering the template, even though the class has correctly changed and been applied.

So what we want to achieve is enforce a template re-render on class change. We know that the class changes every time the object member speech.captured changes value.

So we could enforce re-render when whenever this value changes by adding a conditionally rendered empty span like this:

<span *ngIf="speech.captured"></span>

<div class="avatar-view__initial__question question-hide" ng-class="{'question-show': speech.captured === true, 'question-hide': speech.captured === false}">{{question.text}}</div>


问:
Raspberry Pi 3 + temperature sensor + servo motor
I have raspberry pi 3 and trying to create smart green house model. This model should open window if temperature is too hight.

I am new writing codes in Python, found several examples: 1. for temperature sensor and 2. for servo motor to rotating.

Could anyone help me with servo motor? I would like to move servo for example to 30° if temperature is 20°C, if it is 21°C move 40° servo and so on.

I have Python code:

```<code>import sys
import Adafruit_DHT
import time
import wiringpi
sensor_args = { '11': Adafruit_DHT.DHT11,
            '22': Adafruit_DHT.DHT22,
            '2302': Adafruit_DHT.AM2302 }
if len(sys.argv) == 3 and sys.argv[1] in sensor_args:
  sensor = sensor_args[sys.argv[1]]
  pin = sys.argv[2]
else:
  print('usage: sudo ./Adafruit_DHT.py [11|22|2302] GPIOpin#')
  print('example: sudo ./Adafruit_DHT.py 2302 4 - Read from an AM2302
  connected to GPIO #4')
  sys.exit(1)

humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)

if humidity is not None and temperature is not None:
  print('Temp={0:0.1f}*  Humidity={1:0.1f}%'.format(temperature, humidity))
else:
  print('Failed to get reading. Try again!')
  sys.exit(1)

temp=temperature
text_file = open("output.txt", "w")
text_file.write("%s" %(temp))
text_file.close()

wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(18,wiringpi.GPIO.PWM_OUTPUT)
wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS)

wiringpi.pwmSetClock(192)
wiringpi.pwmSetRange(2000)
delay_period = 0.01

while temp==20.0:
  for pulse in range(50,250,1):
    wiringpi.pwmWrite(18,50)
    time.sleep(delay_period)

for pulse in range(250,50,-1):
    wiringpi.pwmWrite(18,pulse)
    time.sleep(delay_period)
</code>```

Part about servo motor ir example I found on the internet. I need to replace "while" to "if". I tried by myself, but rotor all the time spin to the same angle.
Can anyone help me with this little part of code?

Second question, how can I run this command in terminal "sudo python servo.py 11 17" on raspberry pi automatically in every 10 mminutes and when raspberry pi is turned on?

Thanks for your help!

答:
The pulse is how you are controlling the position of the servo in your code:

```<code>wiringpi.pwmWrite(18,pulse)
</code>```

See this example:
 https://learn.adafruit.com/adafruits-raspberry-pi-lesson-8-using-a-servo-motor?view=all

Depending on your servo, a pulse value of 100 move the servo all the way left (closed in this example), and 200 all the way to the right (open in this example). You need to find these values by reading the datasheet or by experimentation. Once you have these, here is how you would set the position of the servo:

```<code>min_servo_val = 100
max_servo_val = 200

wiringpi.pwmWrite(18, min_servo_val) # Move all the way left
time.sleep(1) # Wait a second
wiringpi.pwmWrite(18, max_servo_val) # Move all the way right
</code>```

Now you can either write a function that translates temperature to a servo position between min_servo_val and max_servo_val, or use a simple if statement. Here is an example of a function to translate temp into a pulse (servo position):

```<code>def get_servo_position(temp):

    min_servo_val = 100 # Pulse value at which window is all the way closed closed
    max_servo_val = 200 # Pulse value at which window is all the way open

    full_closed_temp = 20.0 # Temperature at which window is completely closed
    full_open_temp = 26.0 # Temperature at which window is completely open

    if temp <= full_closed_temp:
        return min_servo_val
    elif temp >= full_open_temp:
        return max_servo_val
    else:
        return ((temp - full_closed_temp) / (full_open_temp - full_closed_temp)) * (max_servo_val - min_servo_val) + min_servo_val
</code>```

Now you can do:

```<code>print get_servo_position(19) # 100 all the way closed

print get_servo_position(22) # 133.3, or 33% of the way between min_servo_val and max_servo_val

print get_servo_position(25) # 183.3, or 83% of the way between min_servo_val and max_servo_val

print get_servo_position(27) # 200 all the way open
</code>```

Now you need a loop that checks the temperature every ten minutes and adjusts the servo position. Something like this:

```<code>while True:
    humidity, temp = Adafruit_DHT.read_retry(sensor, pin) # Get temperature.
    position = get_servo_position(temp) # Get the servo position
    wiringpi.pwmWrite(18,position) # Move to the position
    time.sleep(10*60) # Wait 10 minutes
</code>```

Putting it all together, your script should look something like this:

```<code>import sys
import Adafruit_DHT
import time
import wiringpi

dht_pin = 17 # GPIO conencted to DHT
servo_pin = 18 # GPIO connected to servo

dht_sensor = Adafruit_DHT.DHT11 # Put your sensor here, or set it from command line args

min_servo_val = 100 # Pulse value at which window is all the way closed closed
max_servo_val = 200 # Pulse value at which window is all the way open

full_closed_temp = 20.0 # Temperature at which window is completely closed
full_open_temp = 26.0 # Temperature at which window is completely open

def get_servo_position(temp):

    if temp <= full_closed_temp:
        return min_servo_val
    elif temp >= full_open_temp:
        return max_servo_val
    else:
        return ((temp - full_closed_temp) / (full_open_temp - full_closed_temp)) * (max_servo_val - min_servo_val) + min_servo_val

def main_loop():
    while True:
        humidity, temp = Adafruit_DHT.read_retry(dht_sensor, dht_pin) # Get temperature.
        position = get_servo_position(temp) # Get the servo position
        wiringpi.pwmWrite(18,position) # Move to the position
        time.sleep(10*60) # Wait 10 minutes

if __name__ == '__main__':
    # If you need to get command line arguments, do it below, otherwise just set the pins and other settings at the top of this script.

    # For example...
    # dht_pin = sys.argv[1]
    # servo_pin = sys.argv[2]

    # Set up servo
    wiringpi.wiringPiSetupGpio()
    wiringpi.pinMode(18,wiringpi.GPIO.PWM_OUTPUT)
    wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS)

    wiringpi.pwmSetClock(192)
    wiringpi.pwmSetRange(2000)

    # Enter main loop
    main_loop()
</code>```

Note that I left out command line arg parsing. If you need those you can add them right after if __name__ == '__main__':

Finally, making a script run on startup is a well covered topic:
Start shell script on Raspberry Pi startup

Body:
I have raspberry pi 3 and trying to create smart green house model. This model should open window if temperature is too hight.

I am new writing codes in Python, found several examples: 1. for temperature sensor and 2. for servo motor to rotating.

Could anyone help me with servo motor? I would like to move servo for example to 30° if temperature is 20°C, if it is 21°C move 40° servo and so on.

I have Python code:

import sys
import Adafruit_DHT
import time
import wiringpi
sensor_args = { '11': Adafruit_DHT.DHT11,
            '22': Adafruit_DHT.DHT22,
            '2302': Adafruit_DHT.AM2302 }
if len(sys.argv) == 3 and sys.argv[1] in sensor_args:
  sensor = sensor_args[sys.argv[1]]
  pin = sys.argv[2]
else:
  print('usage: sudo ./Adafruit_DHT.py [11|22|2302] GPIOpin#')
  print('example: sudo ./Adafruit_DHT.py 2302 4 - Read from an AM2302
  connected to GPIO #4')
  sys.exit(1)

humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)

if humidity is not None and temperature is not None:
  print('Temp={0:0.1f}*  Humidity={1:0.1f}%'.format(temperature, humidity))
else:
  print('Failed to get reading. Try again!')
  sys.exit(1)

temp=temperature
text_file = open("output.txt", "w")
text_file.write("%s" %(temp))
text_file.close()

wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(18,wiringpi.GPIO.PWM_OUTPUT)
wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS)

wiringpi.pwmSetClock(192)
wiringpi.pwmSetRange(2000)
delay_period = 0.01

while temp==20.0:
  for pulse in range(50,250,1):
    wiringpi.pwmWrite(18,50)
    time.sleep(delay_period)

for pulse in range(250,50,-1):
    wiringpi.pwmWrite(18,pulse)
    time.sleep(delay_period)

Part about servo motor ir example I found on the internet. I need to replace "while" to "if". I tried by myself, but rotor all the time spin to the same angle.
Can anyone help me with this little part of code?

Second question, how can I run this command in terminal "sudo python servo.py 11 17" on raspberry pi automatically in every 10 mminutes and when raspberry pi is turned on?

Thanks for your help!

Body:
The pulse is how you are controlling the position of the servo in your code:

wiringpi.pwmWrite(18,pulse)

See this example:
 https://learn.adafruit.com/adafruits-raspberry-pi-lesson-8-using-a-servo-motor?view=all

Depending on your servo, a pulse value of 100 move the servo all the way left (closed in this example), and 200 all the way to the right (open in this example). You need to find these values by reading the datasheet or by experimentation. Once you have these, here is how you would set the position of the servo:

min_servo_val = 100
max_servo_val = 200

wiringpi.pwmWrite(18, min_servo_val) # Move all the way left
time.sleep(1) # Wait a second
wiringpi.pwmWrite(18, max_servo_val) # Move all the way right

Now you can either write a function that translates temperature to a servo position between min_servo_val and max_servo_val, or use a simple if statement. Here is an example of a function to translate temp into a pulse (servo position):

def get_servo_position(temp):

    min_servo_val = 100 # Pulse value at which window is all the way closed closed
    max_servo_val = 200 # Pulse value at which window is all the way open

    full_closed_temp = 20.0 # Temperature at which window is completely closed
    full_open_temp = 26.0 # Temperature at which window is completely open

    if temp <= full_closed_temp:
        return min_servo_val
    elif temp >= full_open_temp:
        return max_servo_val
    else:
        return ((temp - full_closed_temp) / (full_open_temp - full_closed_temp)) * (max_servo_val - min_servo_val) + min_servo_val

Now you can do:

print get_servo_position(19) # 100 all the way closed

print get_servo_position(22) # 133.3, or 33% of the way between min_servo_val and max_servo_val

print get_servo_position(25) # 183.3, or 83% of the way between min_servo_val and max_servo_val

print get_servo_position(27) # 200 all the way open

Now you need a loop that checks the temperature every ten minutes and adjusts the servo position. Something like this:

while True:
    humidity, temp = Adafruit_DHT.read_retry(sensor, pin) # Get temperature.
    position = get_servo_position(temp) # Get the servo position
    wiringpi.pwmWrite(18,position) # Move to the position
    time.sleep(10*60) # Wait 10 minutes

Putting it all together, your script should look something like this:

import sys
import Adafruit_DHT
import time
import wiringpi

dht_pin = 17 # GPIO conencted to DHT
servo_pin = 18 # GPIO connected to servo

dht_sensor = Adafruit_DHT.DHT11 # Put your sensor here, or set it from command line args

min_servo_val = 100 # Pulse value at which window is all the way closed closed
max_servo_val = 200 # Pulse value at which window is all the way open

full_closed_temp = 20.0 # Temperature at which window is completely closed
full_open_temp = 26.0 # Temperature at which window is completely open

def get_servo_position(temp):

    if temp <= full_closed_temp:
        return min_servo_val
    elif temp >= full_open_temp:
        return max_servo_val
    else:
        return ((temp - full_closed_temp) / (full_open_temp - full_closed_temp)) * (max_servo_val - min_servo_val) + min_servo_val

def main_loop():
    while True:
        humidity, temp = Adafruit_DHT.read_retry(dht_sensor, dht_pin) # Get temperature.
        position = get_servo_position(temp) # Get the servo position
        wiringpi.pwmWrite(18,position) # Move to the position
        time.sleep(10*60) # Wait 10 minutes

if __name__ == '__main__':
    # If you need to get command line arguments, do it below, otherwise just set the pins and other settings at the top of this script.

    # For example...
    # dht_pin = sys.argv[1]
    # servo_pin = sys.argv[2]

    # Set up servo
    wiringpi.wiringPiSetupGpio()
    wiringpi.pinMode(18,wiringpi.GPIO.PWM_OUTPUT)
    wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS)

    wiringpi.pwmSetClock(192)
    wiringpi.pwmSetRange(2000)

    # Enter main loop
    main_loop()

Note that I left out command line arg parsing. If you need those you can add them right after if __name__ == '__main__':

Finally, making a script run on startup is a well covered topic:
Start shell script on Raspberry Pi startup


问:
Consolidate rows in report

If a row has the same ID as the last one, I want to combine them - summing up the cubicFt and Savings. $perFt divides the savings by the cubicFt, so it wouldn't be summed, simply dividing the new results.  I also want the Descriptions to be concatenated, like this:

答:
You need to do grouping, either by modifying the SELECT statement or the stored query that generates the data, or within Crystal Reports. I'm literally 20 years out of date on Crystal Reports, although I have used similar software, so this will have to be tweaked.

For the first solution, all you need is a concatenation aggregation function for the string field. Your DB may or may not have one built in, so you may need to add it.

```<code>SELECT Building, ID,
  SUM(cubicFt), SUM(savings),
  SUM(savings)/SUM(cubicFt) AS [$perft],
  LEFT(STRING_AGG(description, ';'), -1) -- drop extra ; at end
GROUP BY Building, ID;
</code>```

However, you should be able to do the same within Crystal by setting this up as a subtotal group (not sure if you have to do user definitions for the string aggregation), and then hiding the detail section.

Title: Consolidate rows in report

Body:
You need to do grouping, either by modifying the SELECT statement or the stored query that generates the data, or within Crystal Reports. I'm literally 20 years out of date on Crystal Reports, although I have used similar software, so this will have to be tweaked.

For the first solution, all you need is a concatenation aggregation function for the string field. Your DB may or may not have one built in, so you may need to add it.

SELECT Building, ID,
  SUM(cubicFt), SUM(savings),
  SUM(savings)/SUM(cubicFt) AS [$perft],
  LEFT(STRING_AGG(description, ';'), -1) -- drop extra ; at end
GROUP BY Building, ID;

However, you should be able to do the same within Crystal by setting this up as a subtotal group (not sure if you have to do user definitions for the string aggregation), and then hiding the detail section.


问:
Pandas - Find and Replace values starting with a '<'
I have values in a data frame with certain cells starting '< 101' and certain cells with '< 2' and some with '< 1'. I am trying to write regex using a Pandas Dataframe to find those cells and replace them entirely with the value '0.0'.

Here is what I have:

```<code>df_new2=df_new.replace('(?=<)','0', regex=True)
</code>```

The above code simply adds a '0' in front of '< 101'
with this output '0< 101'.

What I am looking for is an output that finds the '< 101' and replaces it with '0'. Is there a way to do this?

答:
```<code>df_new2 = df_new.replace('^.*<.*$', '0', regex=True)
</code>```

Body:
I have values in a data frame with certain cells starting '< 101' and certain cells with '< 2' and some with '< 1'. I am trying to write regex using a Pandas Dataframe to find those cells and replace them entirely with the value '0.0'.

Here is what I have:

df_new2=df_new.replace('(?=<)','0', regex=True)

The above code simply adds a '0' in front of '< 101'
with this output '0< 101'.

What I am looking for is an output that finds the '< 101' and replaces it with '0'. Is there a way to do this?


问:
Single boxplot for multiple group comparison
Here is the sample code that i used to compare two groups with random mean and standard deviation. However, i want to plot both groups in a single box in the box plot as shown in the attached figure where x-axis is group 1 and y-axis is group 2. I could not find any code doing this. Can some one please help me with this?

```<code>    clc
clear

x=[rand(1,10) rand(1,10) rand(1,10) rand(1,10) rand(1,10) rand(1,10)];
n=10 ; xx=([1:6])'; % example
r=repmat(xx,1,n)';
g=r(:)';

positions = [1 2 3 4 5 6 ];
h=boxplot(x,g, 'positions', positions);
set(h,'linewidth',2)

set(gca,'xtick',[mean(positions(1:2)) mean(positions(3:4)) mean(positions(5:6)) ])
set(gca,'xticklabel',{'exp1','exp2','exp3'},'Fontsize',28)

color = ['c', 'y', 'c', 'y','c', 'y'];
h = findobj(gca,'Tag','Box');
for j=1:length(h)
patch(get(h(j),'XData'),get(h(j),'YData'),color(j),'FaceAlpha',.5);
end
</code>```

now i want yellow and blue for exp1 in one box as shown below.. similarly for exp2 and exp3 so on.. so 3 boxes in one boxplot..Ideally this should work for any number of experiments.

答:
For a single two-sided boxplot, we can use the 'Orientation' property, and overlay 2 boxplots one above the other:

```<code>x = [1 2 3 4 5 6 7 1 2 3 4 5 6 7];
group = [1,1,1,1,1,1,1,2,2,2,2,2,2,2];
% we need the precntiles of the groups so the boxes will overlap.
% on each boxplot we set the width to the other boxplot hight:
p1 = prctile(x(group==1),[25 75]);
p2 = prctile(x(group==2),[25 75]);
ax = axes;
% first group is vertical:
boxplot(x(group==2),'Positions',mean(x(group==1)),...
    'Orientation','vertical','Widths',p1(2)-p1(1),'Colors','r');
lims1 = axis;
hold on
% secound group is horizontal:
boxplot(x(group==1),'Positions',mean(x(group==2)),...
    'Orientation','horizontal','Widths',p2(2)-p2(1),'Colors','k');
% the values of the axis are no longer relevant, since they have two
% different meanings, depend on the group. So we hide them.
ax.XAxis.Visible = 'off';
ax.YAxis.Visible = 'off';
hold off
lims2 = axis;
% because each axis represent to different things, we make sure we see
% everything:
axis([max(lims1(1),lims2(1)),...
    min(lims1(2),lims2(2)),...
    min(lims1(3),lims2(3)),...
    max(lims1(4),lims2(4))])
</code>```

To create multiple two-sided box-plots you need to use an axes for each experiment:

```<code>x = rand(10,6);
nsp = floor(size(x,2)/2); % the number of subplots
meanx = mean(x);
% we need the precntiles of the groups so the boxes will overlap.
% on each boxplot we set the width to the other boxplot hight:
width = range(prctile(x,[25; 75]));
main_ax = axes; % create a tmporary axes
% we get the measurements of the ploting area:
pos = main_ax.Position;
% and divide it to our data:
axwidth = pos(3)/nsp; % the width of each group
% the bottom left corner of each group:
corner = linspace(pos(1),pos(3)+pos(1),nsp+1);
clf % clear the area!
% now we plot each pair of boxplot on a different subplot:
for k = 1:2:size(x,2)
    ax = axes('Position',[corner((k+1)/2) pos(2) axwidth pos(4)]);
    hold on
    % first group is vertical:
    boxplot(x(:,k),'Positions',meanx(k+1),...
        'Orientation','vertical','Widths',width(k+1),'Colors','r');
    % secound group is horizontal:
    boxplot(x(:,k+1),'Positions',meanx(k),...
        'Orientation','horizontal','Widths',width(k),'Colors','k');
    % the values of the y-axis are no longer relevant, since they have two
    % different meanings, depend on the group. So we hide them.
    ax.YAxis.Visible = 'off';
    % we use the x-axis to label the pairs of boxplots:
    ax.XAxis.TickLabels = ['Exp ' num2str((k+1)/2)];
    % because each axis represent to different things, we make sure we see
    % everything:
    minx = min(min(x(:,k:k+1)))*0.1;
    maxx = max(max(x(:,k:k+1)))*1.1;
    axis ([minx maxx minx maxx])
    hold off
    box off
    % set the locations to the exact same place:
    bx = findobj(ax,'tag','Box'); % get the boxes
    posXdif = bx(2).XData(1)-bx(1).XData(1); % get the horizontal difference
    posYdif = bx(2).YData(1)-bx(1).YData(1); % get the vertical difference
    bx2Xdata = get(ax.Children(2).Children,{'XData'}); % get all X-data of box 2
    bx2Ydata = get(ax.Children(2).Children,{'YData'}); % get all Y-data of box 2
    % substruct horizontal difference X-data:
    set(ax.Children(2).Children,{'XData'},...
        cellfun(@(x) x-posXdif,bx2Xdata,'UniformOutput',false))
    % substruct vertical difference Y-data:
    set(ax.Children(2).Children,{'YData'},...
        cellfun(@(y) y-posYdif,bx2Ydata,'UniformOutput',false))
end
</code>```

Body:
Here is the sample code that i used to compare two groups with random mean and standard deviation. However, i want to plot both groups in a single box in the box plot as shown in the attached figure where x-axis is group 1 and y-axis is group 2. I could not find any code doing this. Can some one please help me with this?

    clc
clear

x=[rand(1,10) rand(1,10) rand(1,10) rand(1,10) rand(1,10) rand(1,10)];
n=10 ; xx=([1:6])'; % example
r=repmat(xx,1,n)';
g=r(:)';

positions = [1 2 3 4 5 6 ];
h=boxplot(x,g, 'positions', positions);
set(h,'linewidth',2)

set(gca,'xtick',[mean(positions(1:2)) mean(positions(3:4)) mean(positions(5:6)) ])
set(gca,'xticklabel',{'exp1','exp2','exp3'},'Fontsize',28)

color = ['c', 'y', 'c', 'y','c', 'y'];
h = findobj(gca,'Tag','Box');
for j=1:length(h)
patch(get(h(j),'XData'),get(h(j),'YData'),color(j),'FaceAlpha',.5);
end

now i want yellow and blue for exp1 in one box as shown below.. similarly for exp2 and exp3 so on.. so 3 boxes in one boxplot..Ideally this should work for any number of experiments.

Body:
For a single two-sided boxplot, we can use the 'Orientation' property, and overlay 2 boxplots one above the other:

x = [1 2 3 4 5 6 7 1 2 3 4 5 6 7];
group = [1,1,1,1,1,1,1,2,2,2,2,2,2,2];
% we need the precntiles of the groups so the boxes will overlap.
% on each boxplot we set the width to the other boxplot hight:
p1 = prctile(x(group==1),[25 75]);
p2 = prctile(x(group==2),[25 75]);
ax = axes;
% first group is vertical:
boxplot(x(group==2),'Positions',mean(x(group==1)),...
    'Orientation','vertical','Widths',p1(2)-p1(1),'Colors','r');
lims1 = axis;
hold on
% secound group is horizontal:
boxplot(x(group==1),'Positions',mean(x(group==2)),...
    'Orientation','horizontal','Widths',p2(2)-p2(1),'Colors','k');
% the values of the axis are no longer relevant, since they have two
% different meanings, depend on the group. So we hide them.
ax.XAxis.Visible = 'off';
ax.YAxis.Visible = 'off';
hold off
lims2 = axis;
% because each axis represent to different things, we make sure we see
% everything:
axis([max(lims1(1),lims2(1)),...
    min(lims1(2),lims2(2)),...
    min(lims1(3),lims2(3)),...
    max(lims1(4),lims2(4))])

To create multiple two-sided box-plots you need to use an axes for each experiment:

x = rand(10,6);
nsp = floor(size(x,2)/2); % the number of subplots
meanx = mean(x);
% we need the precntiles of the groups so the boxes will overlap.
% on each boxplot we set the width to the other boxplot hight:
width = range(prctile(x,[25; 75]));
main_ax = axes; % create a tmporary axes
% we get the measurements of the ploting area:
pos = main_ax.Position;
% and divide it to our data:
axwidth = pos(3)/nsp; % the width of each group
% the bottom left corner of each group:
corner = linspace(pos(1),pos(3)+pos(1),nsp+1);
clf % clear the area!
% now we plot each pair of boxplot on a different subplot:
for k = 1:2:size(x,2)
    ax = axes('Position',[corner((k+1)/2) pos(2) axwidth pos(4)]);
    hold on
    % first group is vertical:
    boxplot(x(:,k),'Positions',meanx(k+1),...
        'Orientation','vertical','Widths',width(k+1),'Colors','r');
    % secound group is horizontal:
    boxplot(x(:,k+1),'Positions',meanx(k),...
        'Orientation','horizontal','Widths',width(k),'Colors','k');
    % the values of the y-axis are no longer relevant, since they have two
    % different meanings, depend on the group. So we hide them.
    ax.YAxis.Visible = 'off';
    % we use the x-axis to label the pairs of boxplots:
    ax.XAxis.TickLabels = ['Exp ' num2str((k+1)/2)];
    % because each axis represent to different things, we make sure we see
    % everything:
    minx = min(min(x(:,k:k+1)))*0.1;
    maxx = max(max(x(:,k:k+1)))*1.1;
    axis ([minx maxx minx maxx])
    hold off
    box off
    % set the locations to the exact same place:
    bx = findobj(ax,'tag','Box'); % get the boxes
    posXdif = bx(2).XData(1)-bx(1).XData(1); % get the horizontal difference
    posYdif = bx(2).YData(1)-bx(1).YData(1); % get the vertical difference
    bx2Xdata = get(ax.Children(2).Children,{'XData'}); % get all X-data of box 2
    bx2Ydata = get(ax.Children(2).Children,{'YData'}); % get all Y-data of box 2
    % substruct horizontal difference X-data:
    set(ax.Children(2).Children,{'XData'},...
        cellfun(@(x) x-posXdif,bx2Xdata,'UniformOutput',false))
    % substruct vertical difference Y-data:
    set(ax.Children(2).Children,{'YData'},...
        cellfun(@(y) y-posYdif,bx2Ydata,'UniformOutput',false))
end


问:
Node.js - console.log does not show items in array but instead shows [Object]
I have a problem with logging out the contents of an array inside an object. The actual object looks like this

```<code>   var stuff = { accepted: [ 'item1', 'item2' ],
         rejected: [],
         response: 'Foo',
         envelope: { from: 'The sender', to: ['new item1', 'new item2'] },
         messageId: 'xxxxxxxxxxxxx' } }
</code>```

The console.log shows the items of the first array fine but the second array is being output as [Object].

```<code> { accepted: [ 'item1', 'item2' ],
             rejected: [],
             response: 'Foo',
             envelope: { from: 'The sender', to: [Object] },
             messageId: 'xxxxxxxxxxxxx' } }
</code>```

What is happening here and how can I get the items of the second array to show when I console.log. Thanks for any help!

UPDATE

Sorry, I forgot to add that I am working exclusively in Node.js so it's a server side log that needs to display the object exactly as it's received from a callback with a straight console.log, ie. no further stringify-ing.

I also just tried creating another random object with a similar structure like this.

```<code> var objText = {
      fun: {
        stuff: 'Some stuff',
        list: ['this', 'it', 'takes']
      }
    };
</code>```

The console.log for the above is:

```<code>{ fun: { stuff: 'Some stuff', list: [ 'this', 'it', 'takes' ] } }
</code>```

This appears to be the same structure to me and yet the console.log works fine so it seems to be perfectly possible in Node to log arrays content even when it's embedded inside and an object inside an outer object.

答: Try it with: console.log(JSON.stringify(variable))

Body:
I have a problem with logging out the contents of an array inside an object. The actual object looks like this

   var stuff = { accepted: [ 'item1', 'item2' ],
         rejected: [],
         response: 'Foo',
         envelope: { from: 'The sender', to: ['new item1', 'new item2'] },
         messageId: 'xxxxxxxxxxxxx' } }

The console.log shows the items of the first array fine but the second array is being output as [Object].

 { accepted: [ 'item1', 'item2' ],
             rejected: [],
             response: 'Foo',
             envelope: { from: 'The sender', to: [Object] },
             messageId: 'xxxxxxxxxxxxx' } }

What is happening here and how can I get the items of the second array to show when I console.log. Thanks for any help!

UPDATE

Sorry, I forgot to add that I am working exclusively in Node.js so it's a server side log that needs to display the object exactly as it's received from a callback with a straight console.log, ie. no further stringify-ing.

I also just tried creating another random object with a similar structure like this.

 var objText = {
      fun: {
        stuff: 'Some stuff',
        list: ['this', 'it', 'takes']
      }
    };

The console.log for the above is:

{ fun: { stuff: 'Some stuff', list: [ 'this', 'it', 'takes' ] } }

This appears to be the same structure to me and yet the console.log works fine so it seems to be perfectly possible in Node to log arrays content even when it's embedded inside and an object inside an outer object.


问:
ArgumentException: Unterminated string passed in
I recently encountered this error in one of the pages in my site.

```<code>[ArgumentException: Unterminated string passed in. (26): {"selectedIndexes":["0"],"]
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeString()
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeMemberName()
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32\ depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32\ depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String\ input, Int32 depthLimit, JavaScriptSerializer serializer)
at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer\ serializer, String input, Type type, Int32 depthLimit)
at System.Web.Script.Serialization.JavaScriptSerializer.DeserializeObject(String\ input)
at Telerik.Web.UI.RadCompositeDataBoundControl.LoadPostData(String postDataKey,\ NameValueCollection postCollection)
at Telerik.Web.UI.RadCompositeDataBoundControl.System.Web.UI.IPostBackDataHandler.LoadPostData(String\ postDataKey, NameValueCollection postCollection)
at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean\ fBeforeLoad)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,\ Boolean includeStagesAfterAsyncPoint)

[HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown.]
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,\ Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint,\ Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.pages_appeal_appealaction_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
</code>```

What could be the reason for this exception ? Any ideas how to solve it ??

答:
Yep. This error happens when the ASP.NET system receives a request, routes it to your handler and ModelBinder takes over to map values passed in to parameters in your handler. When one of those parms is a string and that string is started but not terminated, it throws the System.ArgumentException from the System.String.DeserializeString() method.

You have two options.

Fix the string data on the browser in JavaScript before you send it. (duh).

Create a custom Model Binder to handle the exception gracefully and send back a 500-series HTTP error or better yet, fix the data in a predictable way. That fixing is not always possible like in a sound file, image, movie or other base64-encoded blob.

Here's how to do #2 - Creating a custom model binder.

Body:
I recently encountered this error in one of the pages in my site.

[ArgumentException: Unterminated string passed in. (26): {"selectedIndexes":["0"],"]
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeString()
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeMemberName()
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32\ depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32\ depth)
at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String\ input, Int32 depthLimit, JavaScriptSerializer serializer)
at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer\ serializer, String input, Type type, Int32 depthLimit)
at System.Web.Script.Serialization.JavaScriptSerializer.DeserializeObject(String\ input)
at Telerik.Web.UI.RadCompositeDataBoundControl.LoadPostData(String postDataKey,\ NameValueCollection postCollection)
at Telerik.Web.UI.RadCompositeDataBoundControl.System.Web.UI.IPostBackDataHandler.LoadPostData(String\ postDataKey, NameValueCollection postCollection)
at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean\ fBeforeLoad)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,\ Boolean includeStagesAfterAsyncPoint)

[HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown.]
at System.Web.UI.Page.HandleError(Exception e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,\ Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint,\ Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.pages_appeal_appealaction_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

What could be the reason for this exception ? Any ideas how to solve it ??


答:
This is the default way for some browser and implementations of showing too complex or deep objects/arrays with console.log. An alternative is to use JSON.stringify with console.log:

var stuff = {
  accepted: ['item1', 'item2'],
  rejected: [],
  response: 'Foo',
  envelope: {
    from: 'The sender',
    to: ['new item1', 'new item2']
  },
  messageId: 'xxxxxxxxxxxxx'
}

console.log(JSON.stringify(stuff, null, 4));```

EDIT:

Another alternative is to use console.dir in case you have a too complex or recursive object, see https://stackoverflow.com/a/27534731/6051261

Title: Node.js - console.log does not show items in array but instead shows [Object]

Body:
This is the default way for some browser and implementations of showing too complex or deep objects/arrays with console.log. An alternative is to use JSON.stringify with console.log:

var stuff = {
  accepted: ['item1', 'item2'],
  rejected: [],
  response: 'Foo',
  envelope: {
    from: 'The sender',
    to: ['new item1', 'new item2']
  },
  messageId: 'xxxxxxxxxxxxx'
}

console.log(JSON.stringify(stuff, null, 4));

EDIT:

Another alternative is to use console.dir in case you have a too complex or recursive object, see https://stackoverflow.com/a/27534731/6051261


问:
How do I download a file in segments in C#?
I am using HttpWebRequest with the AddRange function like:

```<code>HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpWebRequest.AddRange(20, 30);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
Stream streamResponse = myHttpWebResponse.GetResponseStream();
SaveFileStream(name, streamResponse); //save file function
</code>```

...but the entire file downloaded.

AddRange() in the above code expects the bytes between 20 and 30 to be downloaded (in other words, to download those 10 bytes from the file).

But my code is not working, since the download is not segmented. This link provides an example: http://stackoverflow.com/robots.txt That file was downloaded in its entirety. Why?

答:
HTTP server are not required to support Range header requests. You can verify server's range support by issuing HEAD request and checking value of Accept-Ranges header in response (see HTTP range requests). But this still doesn't guarantee that server will not ignore Range header, in particular for very small ranges (it would be very inefficient for HTTP server to serve content in such small segments).

From RFC7233:

Because servers are free to ignore Range, many implementations will
simply respond with the entire selected representation in a 200 (OK)
response. That is partly because most clients are prepared to receive
a 200 (OK) to complete the task (albeit less efficiently) and partly
because clients might not stop making an invalid partial request until
they have received a complete representation.  Thus, clients cannot
depend on receiving a 416 (Range Not Satisfiable) response even when
it is most appropriate.

To determine if server accepted or ignored Range header, you must check response status code. 200 (OK) indicates that server ignored Range header and returned whole response body, 206 (Partial Content) indicates that range specified in header was returned by server and 416 (Range Not Satisfiable) indicates that the set of ranges requested has been rejected due to invalid ranges or an excessive request of small or overlapping ranges.

In case of http://stackoverflow.com/robots.txt, server indicates support of Range header by returning Accept-Ranges: bytes header in response on HEAD request, but on GET request with AddRange(20, 30) specified, response is 200 (OK), so server just ignored such small range a returned whole reponse body. You have to cut requested range from response yourself, if you need to.

Body:
I am using HttpWebRequest with the AddRange function like:

HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpWebRequest.AddRange(20, 30);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
Stream streamResponse = myHttpWebResponse.GetResponseStream();
SaveFileStream(name, streamResponse); //save file function

...but the entire file downloaded.

AddRange() in the above code expects the bytes between 20 and 30 to be downloaded (in other words, to download those 10 bytes from the file).

But my code is not working, since the download is not segmented. This link provides an example: http://stackoverflow.com/robots.txt That file was downloaded in its entirety. Why?


问:
How .NET Remoting handles changes of IP address in Remoting Server side
Precondition - the remoting server and client are both setup, the client is able to invoke methods and receive events in/from the server side by client-activated business object.

Change the ip address of remoting server with keeping the server and client running, the client is still able to do the above tasks.

This is tricky.

EDIT:
bindTo was removed when setting the channels

答:
The only scenarios where .NET Remoting is faster than WCF are when remoting data between appdomains in the same process and when serializing ADO.NET DataSet objects.

Other than that, WCF is almost always faster: A Performance Comparison of Windows Communication Foundation (WCF) with Existing Distributed Communication Technologies:

Further, when hosted within IIS, WCF services are automatically mapped to a network connection's new IP address. The same cannot be said for .NET Remoting.

While some existing apps continue to use .NET Remoting, it is deprecated and you should realize that any .NET code you write and deploy will at some point need to be replaced. Better to do the port to WCF now rather than later when you're up against a brick-wall-deadline.


问:
Custom action during de-installation not executing
I am working on an MSI installer using installshield 2016. I am trying to add a custom action to the uninstall, that runs a tool before de-installation of the software. The tool is installed with the software and needs to run in administrator mode. The tool is intended to run some manual clean-up actions before de-installation starts.

I've added a custom action using the custom action wizard using "New EXE > Path referencing a directory". INSTALLDIR is defined in the directory table and contains the user-defined installation path. The name of the .exe and parameters are substitutes.

Working Directory: INSTALLDIR

  File Name & Command Line: tool.exe /action parameter1 parameter2 parameter3

  Return processing: Synchronous

  In-Script execution: Deferred Execution in System Context

  Execution schedulintg: Always execute

  MSI type number: 3170

  Run During Patch Uninstall: No

  Install Exec Sequence: After AnotherCustomAction

  Install Exec Condition:

Note: AnotherCustomAction is set to execute after InstallInitialize. It is very similar to this one, but executes properly.

(I know the install exec condition should ultimately be REMOVE="ALL", but I removed that at some point to be sure that wasn't causing problems)

The INSTALLDIR property is written to the registry during installation; I've added AppSearch and RegLocator entries to make sure it is read back.

I've run the installer with logging enabled, and I see the following:

MSI (s) (30:14) [13:57:19:162]: Executing op: ActionStart(Name=RunTool,,)

  MSI (s) (30:14) [13:57:19:162]: Executing op: CustomActionSchedule(Action=RunTool,ActionType=3170,Source=C:\Installation Test\,Target=tool.exe /action parameter1 parameter2 parameter3,)

  MSI (s) (30:14) [13:57:19:162]: Note: 1: 1721 2: RunTool 3: C:\Installation Test\ 4: tool.exe /action parameter1 parameter2 parameter3

  Info 1721.There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: RunTool, location: C:\Installation Test\, command: tool.exe /action parameter1 parameter2 parameter3

If I got to the folder C:\Installation Test\ and manually run tool.exe /action parameter1 parameter2 parameter3, everything works as its supposed to. At some point, someone suggested that maybe the problem is that there is a space in the installation path, but a new attempt with a path without spaces did not fix it.

Any idea what is going wrong here? Is this the right approach?

I can't provide the project itself (company policy) but I'll try to answer any additional questions you may have.

答:
I only have experience with using InstallShield 2015, and have found custom actions to be a bit tricky at times, I actually just wanted to post this in comments (but my rep too low) for you to try rather than an answer so hopefully people won't downvote me too harshly if this doesn't work.

At first, have your return processing set to Synchronous (Ignore exit code), then even though you may specify the correct folder, try setting the path explicitly in Filename and command, and surround your filename and arguments separately in quotes.

Example:

Working Directory: INSTALLDIR

File Name & Command Line: "[INSTALLDIR]tool.exe" "/action" "parameter1" "parameter2" "parameter3"

I've not used MSI type 3170, but have used this for types 1122, 1058, and 1250.

As Christopher mentioned you will also want to look into scheduling, but wrapping in quotes shouldn't hurt.

Best of luck.


问:
How to make better lines?
So I'm making a paint app in C# and it works by marking a point when the user clicks on the paint panel, then while the user has his/her mouse down drawing a line when the mouse is moved to the new position; I'm learning C# so its pretty basic. Now everything's fine until I size up the pen, when I do that the lines start to look super weird? Does anyone know any possible solutions to make the line look normal?

here's my code, I'm using a windows form app:

```<code>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using System.Drawing.Drawing2D;

namespace paintApplication
{

    public partial class frmPaintApp : Form
    {
        /// <summary>
        /// variables
        /// </summary>
        bool shouldPaint = false;
        Point prePoint;
        float penSize = 1;
        Graphics g;

        ColorDialog cd = new ColorDialog();

        public frmPaintApp()
        {
            InitializeComponent();
            g = pnlPaintPanel.CreateGraphics();
            g.SmoothingMode = SmoothingMode.AntiAlias;
        }

        private void msPensize_Click(object sender, EventArgs e)
        {

            if (float.TryParse(msTxtchoosesize.Text , out penSize))
            {
                msTxtchoosesize.Text = "";
            }
        }

        private void pnlPaintPanel_MouseDown(object sender, MouseEventArgs e)
        {
            shouldPaint = true;
            prePoint = new Point(e.X, e.Y);
        }

        private void pnlPaintPanel_MouseUp(object sender, MouseEventArgs e)
        {
            shouldPaint = false;
        }

        private void pnlPaintPanel_MouseMove(object sender, MouseEventArgs e)
        {
            Pen p = new Pen(cd.Color, penSize);

            if (shouldPaint == true)
            {
                g.DrawLine(p, prePoint, new Point(e.X, e.Y));
            }

            prePoint = new Point(e.X, e.Y);

        }

        private void msChoosecolor_Click(object sender, EventArgs e)
        {
            cd.ShowDialog();
        }

        private void frmPaintApp_ResizeEnd(object sender, EventArgs e)
        {
            g = pnlPaintPanel.CreateGraphics();
            g.SmoothingMode = SmoothingMode.AntiAlias;
        }

        private void msClear_Click(object sender, EventArgs e)
        {
            g.Clear(pnlPaintPanel.BackColor);

        }

        private void msExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void pnlPaintPanel_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}
</code>```

答:
Besides my comments regarding using CreateGraphics, etc, try changing your LineCaps (and dispose of your pen, you're leaking memory):</p>

```<code>using (Pen p = new Pen(Color.Black, penSize)) {
  p.StartCap = LineCap.Round;
  p.EndCap = LineCap.Round;
  if (shouldPaint) {
    g.DrawLine(p, prePoint, new Point(e.X, e.Y));
  }
}
</code>```

Title: How to make better lines?

Body:
So I'm making a paint app in C# and it works by marking a point when the user clicks on the paint panel, then while the user has his/her mouse down drawing a line when the mouse is moved to the new position; I'm learning C# so its pretty basic. Now everything's fine until I size up the pen, when I do that the lines start to look super weird? Does anyone know any possible solutions to make the line look normal?

here's my code, I'm using a windows form app:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using System.Drawing.Drawing2D;

namespace paintApplication
{

    public partial class frmPaintApp : Form
    {
        ///
        /// variables
        ///
        bool shouldPaint = false;
        Point prePoint;
        float penSize = 1;
        Graphics g;

        ColorDialog cd = new ColorDialog();

        public frmPaintApp()
        {
            InitializeComponent();
            g = pnlPaintPanel.CreateGraphics();
            g.SmoothingMode = SmoothingMode.AntiAlias;
        }

        private void msPensize_Click(object sender, EventArgs e)
        {

            if (float.TryParse(msTxtchoosesize.Text , out penSize))
            {
                msTxtchoosesize.Text = "";
            }
        }

        private void pnlPaintPanel_MouseDown(object sender, MouseEventArgs e)
        {
            shouldPaint = true;
            prePoint = new Point(e.X, e.Y);
        }

        private void pnlPaintPanel_MouseUp(object sender, MouseEventArgs e)
        {
            shouldPaint = false;
        }

        private void pnlPaintPanel_MouseMove(object sender, MouseEventArgs e)
        {
            Pen p = new Pen(cd.Color, penSize);

            if (shouldPaint == true)
            {
                g.DrawLine(p, prePoint, new Point(e.X, e.Y));
            }

            prePoint = new Point(e.X, e.Y);

        }

        private void msChoosecolor_Click(object sender, EventArgs e)
        {
            cd.ShowDialog();
        }

        private void frmPaintApp_ResizeEnd(object sender, EventArgs e)
        {
            g = pnlPaintPanel.CreateGraphics();
            g.SmoothingMode = SmoothingMode.AntiAlias;
        }

        private void msClear_Click(object sender, EventArgs e)
        {
            g.Clear(pnlPaintPanel.BackColor);

        }

        private void msExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void pnlPaintPanel_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}

Body:
Besides my comments regarding using CreateGraphics, etc, try changing your LineCaps (and dispose of your pen, you're leaking memory):

using (Pen p = new Pen(Color.Black, penSize)) {
  p.StartCap = LineCap.Round;
  p.EndCap = LineCap.Round;
  if (shouldPaint) {
    g.DrawLine(p, prePoint, new Point(e.X, e.Y));
  }
}