问:
Deploy multi-project .Net Core App to Windows server
I acknowledge this is a noob question, but it is the first time we have had to deploy a multi-project .Net Core Web App to an IIS server and it's causing problems.

Solution consists of four projects:

App.Web - primary startup project. Standard .Net Core MVC web app

App.Data - primary data project

Shared.Data

Hmrc.Data

We want to install it to a Windows 2019 server running IIS. I have installed the .Net Core Hosting Bundle and have shared a folder on the server to publish to. I have created the website in IIS and set the pool config.

I set the publish profile on the .Web project to the target shared folder on my IIS server, and repeat for the other three .Data projects.

Publishing appears to complete perfectly, and I have separately deployed the databases to another DB server (having updated the connection strings in the appsettings.json file). Once publishing completes, I can browse to the http://target-server/appname index page, but any page which has a requirement to hit the DB's is failing.

Am I missing anything obvious? Can't see any permission issues on the SQL end.

Any pointers very welcome!

答: Ok, this one needs to never be seen again. Entirely my fault and boiled down to an issue in a connection string that I just couldn't see.</p>


来源: stackexchange

问:
How to do a function call in HTML with vueJS
For my dev lessons, I need to create a social network for a company.

One of the functionalities is to display the comment number linked to a publication (a bit like on Facebook).

To get the comments, I am using vueX to get all data from one source. So, to display the comment count number, here is my idea : for each publication contained in an array, I get all publication comments in another array. So, if I do a {{comments.length}}, for example, this should display "3 comments"

So I wrote the following code :

```<code>  <div v-if="publications.length > 0">
    <AddPostForm />
    <section
      v-for="post in publications"
      :key="post.postId"
      class="publications"
    >
      <div v-bind:data-id="post.postId" class="publications__card">
        <div class="publications__author" :data-user-id="post.userId">
          <img :src="post.avatarUrl" alt="Photo de profil" />
          <span
            class="publications__author-profile"
            @click="goToProfile(post.userId)"
          >
            {{ post.firstName }} {{ post.lastName }}
          </span>
        </div>

        <div
          class="publications__content"
          v-if="post.postContent !== null && post.postContent !== ''"
        >
          <p>{{ post.postContent }}</p>
        </div>

        <div
          class="publications__content"
          v-else-if="
            post.postContent === null ||
            (post.postContent === '' &&
              (post.imageUrl !== null || post.imageUrl !== ''))
          "
        >
          <img :src="post.imageUrl" alt="Image de publication" />
        </div>

        <div
          class="publications__content"
          v-else-if="
            (post.postContent !== null || post.postContent !== '') &&
            (post.imageUrl !== null || post.imageUrl !== '')
          "
        >
          <p>{{ post.postContent }}</p>
          <img :src="post.imageUrl" alt="Image de publication" />
        </div>

        <div class="publications__date-time">
          <p>Publié le {{ post.post_date }}</p>
        </div>

        <div class="publications__delete" v-if="user.admin === 1">
          <p class="publications__delete-txt" @click="deletePost(post.postId)">
            Supprimer
          </p>
        </div>
        <div
          class="publications__like-comment-count"
          v-if="post.comment_count > 0"
        >
          <div
            class="publications__comment-count"
            @click="goToComments(post.userId, post.postId)"
            v-if="comments.length === 1"
          >
            {{ comments.length }} commentaire
          </div>

          <div
            class="publications__comment-count"
            @click="goToComments(post.userId, post.postId)"
            v-else
          >
            {{ comments.length }} commentaires
          </div>
        </div>

        <div class="publications__like-comment">
          <div class="like-comment__like">
            <FaSolidHeart />
            <span class="icon__legend"> J'aime</span>
          </div>

          <div class="like-comment__comment" @click="comment = true">
            <FaSolidComment />
            <span
              class="icon__legend"
              @click="goToComments(post.userId, post.postId)"
              > Commenter</span
            >
          </div>
        </div>
      </div>
    </section>
  </div>
  <div v-else-if="publications.length === 0">
    <p>Aucune publication pour le moment</p>
  </div>
</template>

<script>
import axios from 'axios';
import { mapState } from 'vuex';

import FaSolidHeart from './Heart.vue';
import FaSolidComment from './CommentIcon.vue';
import AddPostForm from './AddPost.vue';

const userSessionData = JSON.parse(localStorage.getItem('userSession'));
const sessionToken = userSessionData.token;
if (sessionToken) {
  axios.defaults.headers.common['Authorization'] = 'Bearer ' + sessionToken;
}

export default {
  name: 'Wall',
  components: {
    FaSolidHeart,
    FaSolidComment,
    AddPostForm
  },
  data() {
    return {
      comment: false,
      user: []
    };
  },
  beforeMount() {
    this.getResult();
    this.getSession();
  },
  methods: {
    getResult: function () {
      this.$store.dispatch('setPublications');
    },
    goToProfile: function (userId) {
      this.$router.push(`/profile/${userId}`);
    },
    goToComments: function (userId, postId) {
      this.$router.push(`/comments/${userId}/${postId}`);
    },
    getSession: function () {
      if (localStorage.userSession) {
        this.user = JSON.parse(localStorage.userSession);
      }
    },
    deletePost: function (postId) {
      axios
        .delete(`http://localhost:3000/api/publications/${postId}`)
        .then(() => this.$router.go())
        .catch((error) => console.log(error));
    },
    getComments: function (postId) {
      // this.$store.dispatch('getPublicationComments', postId);
      console.log(postId);
    }
  },
  computed: {
    ...mapState(['publications', 'comments'])
  }
};
</script>

<style scoped>
.publications {
  width: 30%;
  margin: 10px auto;
}

.publications__card {
  width: 99%;
  padding: 10px;
  padding-left: 15px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background-color: rgba(138, 185, 241, 0.4);
}

.publications__card .publications__author:hover {
  cursor: pointer;
}

.publications__card .publications__date-time {
  margin-top: -20px;
  font-size: 0.8rem;
  color: grey;
}

.publications__card .publications__delete .publications__delete-txt {
  margin-top: -5px;
  font-size: 0.85rem;
}

.publications__card .publications__like-comment-count {
  width: 92%;
  height: fit-content;
  margin: auto 0;
  padding: 5px;
  border-top: 1px solid white;
}

.publications__card .publications__comment-count {
  margin-right: 15px;
  text-align: right;
}

.publications__card .publications__like-comment {
  width: 95%;
  height: fit-content;
  margin: auto 0;
  padding-top: 10px;
  display: flex;
  justify-content: space-around;
  border-top: 1px solid white;
}

.publications__card .like-comment__like:hover,
.publications__card .like-comment__comment:hover,
.publications__card .publications__comment-count:hover,
.publications__card .publications__delete .publications__delete-txt:hover {
  cursor: pointer;
  color: #4b77be;
}

.publications__card .publications__add-comment {
  width: 95%;
  padding-top: 5px;
  border-top: 1px solid white;
}

.publications__card .publications__add-comment .add-comment__field {
  width: 98%;
  height: 25px;
  margin-top: 5px;
  padding-top: 0px;
  padding: 13px;
  border-radius: 50px;
  resize: none;
  font-family: 'poppins';
  outline: none;
}
</style>
</code>```

My question is how may I call the getComments function from the HTML so that I can display comment count number properly ?

Thank you so much for your help :)

答:
I am not sure if this will work, but if you store the comments in vuex, you can use this:

{{ this.$store.state.comments.length }}

This only works if the comments is correctly stored in vuex, I hope this will work for you.

ContentLicense: CC BY-SA 4.0

Body:
For my dev lessons, I need to create a social network for a company.

One of the functionalities is to display the comment number linked to a publication (a bit like on Facebook).

To get the comments, I am using vueX to get all data from one source. So, to display the comment count number, here is my idea : for each publication contained in an array, I get all publication comments in another array. So, if I do a {{comments.length}}, for example, this should display "3 comments"

So I wrote the following code :

 0">
    <AddPostForm />

            {{ post.firstName }} {{ post.lastName }}

{{ post.postContent }}

{{ post.postContent }}

Publié le {{ post.post_date }}

            Supprimer

 0"
        >

            {{ comments.length }} commentaire

            {{ comments.length }} commentaires

            <FaSolidHeart />
             J'aime

            <FaSolidComment />
             Commenter

Aucune publication pour le moment

</template>

My question is how may I call the getComments function from the HTML so that I can display comment count number properly ?

Thank you so much for your help :)

Body:
I am not sure if this will work, but if you store the comments in vuex, you can use this:

<p>{{ this.$store.state.comments.length }}<p>

This only works if the comments is correctly stored in vuex, I hope this will work for you.


问:
Postgres generate_series joined onto result set to fill empty dates within a range
I have a result set that sometimes has missing dates (because no data is present within that week), and need to fill those with zero's. For simplicity I've reduced the query and table down to

```<code>Table: generated_data
id | data | date_key
1  |  3   | 2021-12-13 03:00:00.000
2  |  1   | 2021-12-22 05:00:00.000
3  |  4   | 2021-12-24 07:00:00.000
4  |  7   | 2022-01-03 01:00:00.000
5  |  2   | 2022-01-05 02:00:00.000

Query:
Select
  sum(data) / count(data),
  DATE_TRUNC('week', date_key AT TIME ZONE 'America/New_York') as date_key
from generated_data
group by DATE_TRUNC('week', date_key AT TIME ZONE 'America/New_York') as date_key

would produce the following result set:
3   | 2021-12-13 00:00:00.000
2.5 | 2021-12-20 00:00:00.000
5.5 | 2022-01-03 00:00:00.000
</code>```

but as you can see there's a missing date of 12/27 which I'd like to return in the result set as a zero. I've looked into using generate_series and joining onto the above simplified query, but haven't found a good solution.

The idea would be doing something like

```<code>SELECT GENERATE_SERIES('2021-11-08T00:00:00+00:00'::date, '2022-01-17T04:59:59.999000+00:00'::date, '1 week'::interval) as date_key
</code>```

but I'm not sure how to join that back to the result query where just the missing dates are added. What would a on clause look like for something like that?

```<code>final result set would look like
3   | 2021-12-13 00:00:00.000
2.5 | 2021-12-20 00:00:00.000
0   | 2021-12-27 00:00:00.000
5.5 | 2022-01-03 00:00:00.000
</code>```

答:
At first, you should find the min and max of date and generate based on that. Then join a table with generated data

Demo

WITH data_range AS (
  SELECT
    min(date_key) AT TIME ZONE 'America/New_York' min,
    max(date_key) AT TIME ZONE 'America/New_York' max
  from generated_data
),
generated_range AS (
  SELECT DATE_TRUNC(
    'week',
    GENERATE_SERIES(min, max, '1 week'::interval)
  ) AS date FROM data_range
)
SELECT
  coalesce(sum(data) / count(data), 0),
  DATE_TRUNC('week', gr.date)
FROM
  generated_range gr
  LEFT JOIN generated_data gd ON
    DATE_TRUNC('week', gd.date_key AT TIME ZONE 'America/New_York') = gr.date
GROUP BY DATE_TRUNC('week', gr.date)
ORDER BY 2
```

Body:
I have a result set that sometimes has missing dates (because no data is present within that week), and need to fill those with zero's. For simplicity I've reduced the query and table down to

Table: generated_data
id | data | date_key
1  |  3   | 2021-12-13 03:00:00.000
2  |  1   | 2021-12-22 05:00:00.000
3  |  4   | 2021-12-24 07:00:00.000
4  |  7   | 2022-01-03 01:00:00.000
5  |  2   | 2022-01-05 02:00:00.000

Query:
Select
  sum(data) / count(data),
  DATE_TRUNC('week', date_key AT TIME ZONE 'America/New_York') as date_key
from generated_data
group by DATE_TRUNC('week', date_key AT TIME ZONE 'America/New_York') as date_key

would produce the following result set:
3   | 2021-12-13 00:00:00.000
2.5 | 2021-12-20 00:00:00.000
5.5 | 2022-01-03 00:00:00.000

but as you can see there's a missing date of 12/27 which I'd like to return in the result set as a zero. I've looked into using generate_series and joining onto the above simplified query, but haven't found a good solution.

The idea would be doing something like

SELECT GENERATE_SERIES('2021-11-08T00:00:00+00:00'::date, '2022-01-17T04:59:59.999000+00:00'::date, '1 week'::interval) as date_key

but I'm not sure how to join that back to the result query where just the missing dates are added. What would a on clause look like for something like that?

final result set would look like
3   | 2021-12-13 00:00:00.000
2.5 | 2021-12-20 00:00:00.000
0   | 2021-12-27 00:00:00.000
5.5 | 2022-01-03 00:00:00.000


问:
Compress RSA Encoded value in java
I am having a java class in which RSA Encryption is performed for the passed String value. getting encoded value as lengthy.

Input String: justin

RSA Encoded value as output: .eJwdy00OwiAQBtC7zFqS4Ufg8zLNUIaGDZjaxoXx7ja-_fvQc751X3qlB2Wp4kKCU47BZy4A7pa9uuitqNKN5t63PuToY1vO87-wri02gSlSiwloMKhcDZxoSClDAl-zj9exjHkFy0zfH5pUI3w.YfvMdQ.GcmMQuY3BN33JATAfFB3ZyeXO8U

RSA Encryption Code:

```<code>String username="justin";
String encrypteduser=getEncryptedPassword(username);
System.out.println("encrypteduser! " + encrypteduser);
public String getEncryptedPassword(String plainTextPassword)
    {
        String result="";

        try {
            result= getEncryptedPasswd(plainTextPassword);
            log.info("result:   " + result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

 protected String getEncryptedPasswd(String plain) throws Exception {
            try {
                InputStream is = new ByteArrayInputStream(getCertificate().getBytes());
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) cf.generateCertificate(is);

                PublicKey pubKey = cert.getPublicKey();
                Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                cipher.init(Cipher.ENCRYPT_MODE, pubKey);

                byte cipherBytes[] = cipher.doFinal(plain.getBytes());
                String encrypted = Base64.getEncoder().encodeToString(cipherBytes);
                return encrypted;
            } catch (Exception ex) {
                ex.printStackTrace();
                return null;
            }
        }

        private String getCertificate() {

        String certStr = "-----BEGIN CERTIFICATE-----\n"
                + "MIIGgDCCBWigAwIBAgIKMvrulAAAAARG5DANBgkqhkiG9w0BAQsFADBbMRMwEQYK"
                + "CZImiZPyLGQBGRYDbmV0MRkwFwYKCZIm"
                + "-----END CERTIFICATE-----";

        return certStr;
    }
</code>```

and my goal here is that wanna compress RSA Encoded value into shorten one.

I hope after conversion(RSA to UTF-8) will get some shortened value.

Note: looking for some compression to the Encoded value if UTF-8 conversion not helps.

Is there any way to achieve this in java 8?

答:
To remain largely compatible with US-ASCII, a 7 bit character code, UTF-8 only encodes single byte characters using the lower 7 bits as well. That means that the same 95 printable characters are present using a single byte in UTF-8 and ASCII. Moving to two or higher byte UTF-8 encoding takes more space, so that's not useful at all.

So basically you can use any text encoding for ASCII  that exists. You are already using base 64 which is already pretty dense. However, you could e.g. also use Z85 which can contain more binary data, with the disadvantage that it is not a power of two, so the encoding / decoding (or base conversion) will be somewhat trickier and costly. Furthermore, a base 85 encoding only encodes around 6.41 bits per character over 6 bits for base 64, so the return is minimal (around 6.82%).

You should always indicate the encoding when performing conversion. However,UTF-8 is fully compatible to ASCII for base 64 and Z85 as mentioned before. So I'd indicate encoding StandardCharsets.US_ASCII, not UTF_8 as others no doubt will propose.

Just to be sure: if you are able to handle bytes then no encoding is always better than performing some conversion to a less efficient representation.

The only real way of creating smaller ciphertext is to look at hybrid encryption. Just encrypting or deriving a symmetric key with RSA and use that to encrypt a small string such as a password is not really feasible. An RSA ciphertext consist of (largely) random bytes, so at least on average is not possible to compress these bytes any further.

However, you could take a look at ECIES, possibly with a compressed ephemeral public key. Then you could use 33 bytes for the public key (of e.g. curve type P256, for a 128 bit strength) and a specific maximum password size for the password itself, encrypted with e.g. AES-CTR. You should use a static sized encoding for the passwords, or you could leak the password size.

Title: Compress RSA Encoded value in java

Body:
I am having a java class in which RSA Encryption is performed for the passed String value. getting encoded value as lengthy.

Input String: justin

RSA Encoded value as output: .eJwdy00OwiAQBtC7zFqS4Ufg8zLNUIaGDZjaxoXx7ja-_fvQc751X3qlB2Wp4kKCU47BZy4A7pa9uuitqNKN5t63PuToY1vO87-wri02gSlSiwloMKhcDZxoSClDAl-zj9exjHkFy0zfH5pUI3w.YfvMdQ.GcmMQuY3BN33JATAfFB3ZyeXO8U

RSA Encryption Code:

String username="justin";
String encrypteduser=getEncryptedPassword(username);
System.out.println("encrypteduser! " + encrypteduser);
public String getEncryptedPassword(String plainTextPassword)
    {
        String result="";

        try {
            result= getEncryptedPasswd(plainTextPassword);
            log.info("result:   " + result);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

 protected String getEncryptedPasswd(String plain) throws Exception {
            try {
                InputStream is = new ByteArrayInputStream(getCertificate().getBytes());
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) cf.generateCertificate(is);

                PublicKey pubKey = cert.getPublicKey();
                Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                cipher.init(Cipher.ENCRYPT_MODE, pubKey);

                byte cipherBytes[] = cipher.doFinal(plain.getBytes());
                String encrypted = Base64.getEncoder().encodeToString(cipherBytes);
                return encrypted;
            } catch (Exception ex) {
                ex.printStackTrace();
                return null;
            }
        }

        private String getCertificate() {

        String certStr = "-----BEGIN CERTIFICATE-----\n"
                + "MIIGgDCCBWigAwIBAgIKMvrulAAAAARG5DANBgkqhkiG9w0BAQsFADBbMRMwEQYK"
                + "CZImiZPyLGQBGRYDbmV0MRkwFwYKCZIm"
                + "-----END CERTIFICATE-----";

        return certStr;
    }

and my goal here is that wanna compress RSA Encoded value into shorten one.

I hope after conversion(RSA to UTF-8) will get some shortened value.

Note: looking for some compression to the Encoded value if UTF-8 conversion not helps.

Is there any way to achieve this in java 8?


问:
Insert spaceing between chaptername and thechapter in header
I am using the scrheadings package in Latex. I want to add the chapter name and number with the following command to my header:

```<code>\ihead[\chaptername \thechapter]{}
</code>```

The output looks like "Chapter1". I would like to have a 'normal' space between the chaptername and the number like "Chapter 1". What can I do?

答:
You can use

```<code>\ihead[\chaptername{} \thechapter]{}
</code>```

to ensure that the macro does not shallow the space following it

Body:
I am using the scrheadings package in Latex. I want to add the chapter name and number with the following command to my header:

\ihead[\chaptername \thechapter]{}

The output looks like "Chapter1". I would like to have a 'normal' space between the chaptername and the number like "Chapter 1". What can I do?

Body:
You can use

\ihead[\chaptername{} \thechapter]{}

to ensure that the macro does not shallow the space following it


问:
plotly sankey - is it able to put the node labels to the right for last layer(column)
I have a  sankey chart created by python plotly with 8 layers(columns).

dataset = pd.read_csv('cleanSankey.csv')

labelListTemp1 = list(set(dataset.source.values))
labelListTemp2 = list(set(dataset.target.values))
labelList = labelListTemp1 + labelListTemp2
sankey_node = list(dict.fromkeys(labelList))

def nodify(node_names):
    node_names = sankey_node
    # uniqe name endings
    ends = sorted(list(set([e[-1] for e in node_names])))

    # intervals
    steps = 1/len(ends)

    # x-values for each unique name ending
    # for input as node position
    nodes_x = {}
    xVal = 0
    for e in ends:
        nodes_x[str(e)] = xVal
        xVal += steps

    # x and y values in list form
    x_values = [nodes_x[n[-1]] for n in node_names]
    y_values = [0.1]*len(x_values)

    return x_values, y_values

nodified = nodify(node_names=sankey_node)

fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=15,line = dict(color = "black", width = 0.5),label = labelList,color = 'grey',x=nodified[0],y=nodified[1] ),
                                  link = dict(source = dataset.source.apply(lambda x: labelList.index(x)),
                                              target = dataset.target.apply(lambda x: labelList.index(x)),
                                              value = dataset.value),
                                              arrangement='snap')])

fig.update_layout(title="performance Goal user behavior monitor",margin=dict(l=150))
fig.write_html('perfUXRGoal.html', auto_open=True)
```

Issue:
The labels are  positioned to the right side of the nodes, but the the node labels for last layer, it's always positioned to the left side of the nodes.

Question:
Is it possible to put the labels to the right side of nodes for the last layer as well?

Screenshot sample:

Thanks,
Cherie

答:
A workaround.  Have an additional layer that has no label and all target nodes lead to it.

```<code>import pandas as pd
import numpy as np
import plotly.graph_objects as go

links = [
    {'source': 'start', 'target': 'A', 'value': 2},
    {'source': 'A', 'target': 'B', 'value': 1},
    {'source': 'A', 'target':'C', 'value':.5},
    {'source': 'B', 'target':'', 'value':10**-10},
    {'source': 'C', 'target':'', 'value':10**-10},

]

df = pd.DataFrame(links)
nodes = np.unique(df[["source","target"]], axis=None)
nodes = pd.Series(index=nodes, data=range(len(nodes)))

fig = go.Figure(
    go.Sankey(
        node={"label": nodes.index},
        link={
            "source": nodes.loc[df["source"]],
            "target": nodes.loc[df["target"]],
            "value": df["value"],
            "color": np.where(df["target"].eq(""), "white", "rgba(30,30,30,.3)")
        },
    )
)

fig
</code>```

Body:
I have a  sankey chart created by python plotly with 8 layers(columns).

dataset = pd.read_csv('cleanSankey.csv')

labelListTemp1 = list(set(dataset.source.values))
labelListTemp2 = list(set(dataset.target.values))
labelList = labelListTemp1 + labelListTemp2
sankey_node = list(dict.fromkeys(labelList))

def nodify(node_names):
    node_names = sankey_node
    # uniqe name endings
    ends = sorted(list(set([e[-1] for e in node_names])))

    # intervals
    steps = 1/len(ends)

    # x-values for each unique name ending
    # for input as node position
    nodes_x = {}
    xVal = 0
    for e in ends:
        nodes_x[str(e)] = xVal
        xVal += steps

    # x and y values in list form
    x_values = [nodes_x[n[-1]] for n in node_names]
    y_values = [0.1]*len(x_values)

    return x_values, y_values

nodified = nodify(node_names=sankey_node)

fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=15,line = dict(color = "black", width = 0.5),label = labelList,color = 'grey',x=nodified[0],y=nodified[1] ),
                                  link = dict(source = dataset.source.apply(lambda x: labelList.index(x)),
                                              target = dataset.target.apply(lambda x: labelList.index(x)),
                                              value = dataset.value),
                                              arrangement='snap')])

fig.update_layout(title="performance Goal user behavior monitor",margin=dict(l=150))
fig.write_html('perfUXRGoal.html', auto_open=True)

Issue:
The labels are  positioned to the right side of the nodes, but the the node labels for last layer, it's always positioned to the left side of the nodes.

Question:
Is it possible to put the labels to the right side of nodes for the last layer as well?

Screenshot sample:

Thanks,
Cherie

Body:
A workaround.  Have an additional layer that has no label and all target nodes lead to it.

import pandas as pd
import numpy as np
import plotly.graph_objects as go

links = [
    {'source': 'start', 'target': 'A', 'value': 2},
    {'source': 'A', 'target': 'B', 'value': 1},
    {'source': 'A', 'target':'C', 'value':.5},
    {'source': 'B', 'target':'', 'value':10**-10},
    {'source': 'C', 'target':'', 'value':10**-10},

]

df = pd.DataFrame(links)
nodes = np.unique(df[["source","target"]], axis=None)
nodes = pd.Series(index=nodes, data=range(len(nodes)))

fig = go.Figure(
    go.Sankey(
        node={"label": nodes.index},
        link={
            "source": nodes.loc[df["source"]],
            "target": nodes.loc[df["target"]],
            "value": df["value"],
            "color": np.where(df["target"].eq(""), "white", "rgba(30,30,30,.3)")
        },
    )
)

fig


问:
Using bash script to remove from sentence words longer than [x] characters
I have a sentence (array) and I would like to remove from it all words longer than 8 characters.

Example sentence:

var="one two three four giberish-giberish five giberish-giberish six"
```
<p>I would like to get:</p>
<pre class="lang-bash prettyprint-override"><code>var="one two three four five six"
</code>```

So far I'm using this:

echo $var | tr ' ' '\n' | awk 'length($1) <= 6 { print $1 }' | tr '\n ' ' ' ```
Solution above works fine but as you can see I'm replacing space with newline then filtering words and then replacing back newline with space.

I'm pretty sure there must be better and more "elegant" solution without swapping space/newline.
</code>```

答:
In pure Bash, you can filter into a new array the words less than some chosen length:

```<code>#!/bin/bash

var="one two three four giberish-giberish five giberish-giberish six"

new_arr=()
for w in $var; do  # no quotes on purpose to split string
    [[ ${#w} -lt 6 ]] && new_arr+=( "$w" )
done

declare -p new_arr
# declare -a new_arr=([0]="one" [1]="two" [2]="three" [3]="four" [4]="five" [5]="six")
</code>```

Or if the source is already an array:

```<code>old_arr=(one two three four giberish-giberish five giberish-giberish six)
new_arr=()
for w in ${old_arr[@]}; do
    [[ ${#w} -lt 6 ]] && new_arr+=( "$w" )
done
</code>```

You may want to delete the words in old_arr as you loop over it. If you know that each $w is unique, you can do:

```<code>old_arr=(one two three four giberish-giberish five giberish-giberish six)
for w in ${old_arr[@]}; do
    [[ ${#w} -ge 6 ]] && old_arr=("${old_arr[@]/$w}")
done
</code>```

But this has two issues: 1) If you have equal prefixes, all will be deleted and 2) The existing indices will remain:

```<code>$ declare -p old_arr
declare -a old_arr=([0]="one" [1]="two" [2]="three" [3]="four" [4]="" [5]="five" [6]="" [7]="six")
</code>```

You could also unset the offending item by keeping a separate index:

```<code>old_arr=(one two three four giberish-giberish five giberish-giberish six)
idx=0
for w in ${old_arr[@]}; do
    [[ ${#w} -ge 6 ]] && unset 'old_arr[idx]'
    (( idx++ ))
done
</code>```

But then you end up with discontinuous array indexes (but the existing qualifying words remain at the same index):

```<code>$ declare -p old_arr
declare -a old_arr=([0]="one" [1]="two" [2]="three" [3]="four" [5]="five" [7]="six")
</code>```

It usually better to filter into a new array unless you want to keep the existing indexes.

Body:
I have a sentence (array) and I would like to remove from it all words longer than 8 characters.

Example sentence:

var="one two three four giberish-giberish five giberish-giberish six"

I would like to get:

var="one two three four five six"

So far I'm using this:

echo $var | tr ' ' '\n' | awk 'length($1) <= 6 { print $1 }' | tr '\n ' ' ' ```
Solution above works fine but as you can see I'm replacing space with newline then filtering words and then replacing back newline with space.

I'm pretty sure there must be better and more "elegant" solution without swapping space/newline.

Body:
In pure Bash, you can filter into a new array the words less than some chosen length:

#!/bin/bash

var="one two three four giberish-giberish five giberish-giberish six"

new_arr=()
for w in $var; do  # no quotes on purpose to split string
    [[ ${#w} -lt 6 ]] && new_arr+=( "$w" )
done

declare -p new_arr
# declare -a new_arr=([0]="one" [1]="two" [2]="three" [3]="four" [4]="five" [5]="six")

Or if the source is already an array:

old_arr=(one two three four giberish-giberish five giberish-giberish six)
new_arr=()
for w in ${old_arr[@]}; do
    [[ ${#w} -lt 6 ]] && new_arr+=( "$w" )
done

You may want to delete the words in old_arr as you loop over it. If you know that each $w is unique, you can do:

old_arr=(one two three four giberish-giberish five giberish-giberish six)
for w in ${old_arr[@]}; do
    [[ ${#w} -ge 6 ]] && old_arr=("${old_arr[@]/$w}")
done

But this has two issues: 1) If you have equal prefixes, all will be deleted and 2) The existing indices will remain:

$ declare -p old_arr
declare -a old_arr=([0]="one" [1]="two" [2]="three" [3]="four" [4]="" [5]="five" [6]="" [7]="six")

You could also unset the offending item by keeping a separate index:

old_arr=(one two three four giberish-giberish five giberish-giberish six)
idx=0
for w in ${old_arr[@]}; do
    [[ ${#w} -ge 6 ]] && unset 'old_arr[idx]'
    (( idx++ ))
done

But then you end up with discontinuous array indexes (but the existing qualifying words remain at the same index):

$ declare -p old_arr
declare -a old_arr=([0]="one" [1]="two" [2]="three" [3]="four" [5]="five" [7]="six")

It usually better to filter into a new array unless you want to keep the existing indexes.


问:
How to fix hermes on android
I have an existing react native app which even though I configure hermes in android/app/build.gradle and in proguard-rules won't work.

What I mean by won't work is that when I check at runtime, it says that hermes is not running.

```<code>    const isHermes = () => !!global.HermesInternal;
    console.log('hermes: ', isHermes()); <==== logs false
</code>```

In the logs I can see

```<code>not allowing consideration of lib/armeabi-v7a/libhermes-executor-common-debug.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-executor-common-release.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-executor-debug.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-executor-release.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-inspector.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes.so: deferring to libdir
</code>```

in proguard-rules.pro

```<code># hermes
-keep class com.facebook.hermes.unicode.** { *; }
-keep class com.facebook.jni.** { *; }
</code>```

the app/build.gradle

```<code>apply plugin: "com.android.application"

apply plugin: "com.bugsnag.android.gradle"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

//react-native-config (https://github.com/luggit/react-native-config#android-1)
project.ext.envConfigFiles = [
    dev: ".env.dev",
    staging: ".env.staging",
    beta: ".env.production",
    release: ".env.production"
]

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
//!react-native-config

apply plugin: "com.google.firebase.firebase-perf"
import com.android.build.OutputFile

project.ext.react = [
   // clean and rebuild if changing,
    entryFile: "index.js",
    enableHermes: true
]

apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = true

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'
/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", true);
logger.warn('enableHermes: {}', enableHermes)
/**
 * Architectures to build native code for in debug.
 */
def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures")

android {

    ndkVersion rootProject.ext.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

   packagingOptions {
        pickFirst '**/armeabi-v7a/libc++_shared.so'
        pickFirst '**/x86/libc++_shared.so'
        pickFirst '**/arm64-v8a/libc++_shared.so'
        pickFirst '**/x86_64/libc++_shared.so'
        pickFirst '**/x86/libjsc.so'
        pickFirst '**/armeabi-v7a/libjsc.so'
        pickFirst '**/x86_64/libjsc.so'
        pickFirst '**/arm64-v8a/libjsc.so'

        pickFirst "lib/armeabi-v7a/libc++_shared.so"
        pickFirst "lib/arm64-v8a/libc++_shared.so"
        pickFirst "org/bouncycastle/x509/CertPathReviewerMessages_de.properties"
        pickFirst "org/bouncycastle/x509/CertPathReviewerMessages.properties"
        pickFirst "lib/x86/libc++_shared.so"
        pickFirst "lib/x86_64/libc++_shared.so"
         exclude "**/libjsc.so"
    }

    compileSdkVersion rootProject.ext.compileSdkVersion
    defaultConfig {
        applicationIdSuffix ""
        applicationId "XXX.YYY"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1038160033
        vectorDrawables.useSupportLibrary = true
        versionName "5.8.130"
        resConfigs "fr", "FR"
         if (nativeArchitectures) {
                ndk {
                    abiFilters nativeArchitectures.split(',')
                }
            }
        resValue "string", "build_config_package", "XXX.YYY"

        //fix for codepush not being able to install downloaded package
        //https://github.com/microsoft/react-native-code-push/issues/1961#issuecomment-710698621
        resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
    }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }

    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }

    bugsnag {
      uploadReactNativeMappings = true // enables upload of React Native source maps
    }

    buildTypes {
        //note that config name that contain 'release' will be build with DEV turned off for React Native
        //all other will have DEV set to true. Look for the Note in the android section of this page
        //https://learn.microsoft.com/en-us/appcenter/distribution/codepush/rn-deployment#android

        //!!!!! don't modify the version via versionNameSuffix, else code push will not find the version anymore

        debug {
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false",
                                    DOMAIN:"XXX",
                                    FIREBASE_DOMAIN:'XXX',
                                    brandTestMode:"true",
                                    BUGSNAG_KEY:"XXX"]
            applicationIdSuffix ".debug"
            debuggable true
            signingConfig signingConfigs.release

            firebaseCrashlytics {
              nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxx"'
        }

        dev {
            initWith debug

            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false",
                                    DOMAIN:"xxx",
                                    FIREBASE_DOMAIN:'xxx',
                                    brandTestMode:"true",
                                    BUGSNAG_KEY:"xxxx"]

            matchingFallbacks = ['debug']
            applicationIdSuffix ".debug"
             firebaseCrashlytics {
                nativeSymbolUploadEnabled false
            }

            //disable codepush in dev builds
            resValue "string", "CodePushDeploymentKey", '""' // '"xxxx"'
        }

        staging {
            initWith debug

            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false",
                                    DOMAIN:"xxxco",
                                    FIREBASE_DOMAIN:'xxxx',
                                    brandTestMode:"true",
                                    BUGSNAG_KEY:"xxxxx"]

            matchingFallbacks = ['debug']
            applicationIdSuffix ".debug"
            firebaseCrashlytics {
              nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxxx"'
        }

        beta {
            initWith release
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "true",
                                    DOMAIN:"xxx",
                                    FIREBASE_DOMAIN:'fbxxx',
                                    brandTestMode:"false",
                                    BUGSNAG_KEY:"xxxx"]
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
            matchingFallbacks = ['release']
            applicationIdSuffix ".beta"
            shrinkResources true
            firebaseCrashlytics {
              nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxx"'
        }

        release {
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "true",
                                    DOMAIN:"xxxx",
                                    FIREBASE_DOMAIN:'xxx',
                                    brandTestMode:"false",
                                    BUGSNAG_KEY:"xxxxx"]
            minifyEnabled false
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
            firebaseCrashlytics {
                nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxxx"'
        }
    }
}
    ext.abiCodes = ['armeabi-v7a':'1', 'arm64-v8a':'2', 'mips':'3', 'x86':'4', 'x86_64':'5']
// For each APK output variant, override version code of outputs based on ABI codes
// ex) 'mips' -> 3xxx
// ex) 'x86' -> 4xxx
android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def baseVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
        if (baseVersionCode != null) {
            output.versionCodeOverride = Integer.valueOf(baseVersionCode + variant.versionCode)
        }
    }
}

dependencies {
    implementation "com.google.firebase:firebase-messaging:22"

    implementation 'com.google.firebase:firebase-appcheck-safetynet:16.0.0-beta01'
    // To enable the Google Advertising ID for adjust
    // https://help.adjust.com/en/article/get-started-android-sdk#add-google-play-services
    implementation 'com.google.android.gms:play-services-location:18.0.0'

 implementation fileTree(dir: "libs", include: ["*.jar"])
   implementation ("com.facebook.react:react-native:+") { force = true
}

   implementation 'org.chromium:v8-android:9.93.+'

        debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
        exclude group:'com.squareup.okhttp3', module:'okhttp'
    }

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
    }

       debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
         exclude group:'com.facebook.fbjni'
    }

implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation("com.squareup.okhttp3:okhttp-urlconnection:4.4.1")
implementation 'com.instabug.library:instabug-apm-okhttp-interceptor:10.4.0'

    implementation ('com.facebook.fresco:fresco:2.4.0') {
  exclude module: 'nativeimagefilters'
  exclude module: 'nativeimagetranscoder'
}

//   implementation project(':react-native-fast-image')
      // For animated GIF support
    implementation 'com.facebook.fresco:animated-gif:2.4.0'
    implementation 'com.google.android.gms:play-services-wallet:18.1.2'
  // For WebP support, including animated WebP
    implementation 'com.facebook.fresco:animated-webp:2.4.0'
    implementation 'com.facebook.fresco:webpsupport:2.4.0'

     implementation 'com.facebook.android:facebook-core:9.1.0'

    implementation project(':react-native-check-app-install')

   implementation "com.stripe:stripe-3ds2-android:5.3.1"
    implementation 'com.braintreepayments.api:braintree:3.17.3'
    implementation 'com.braintreepayments.api:three-d-secure:3.17.3'

    implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
    implementation 'com.android.installreferrer:installreferrer:2.2'

    implementation 'com.google.android.gms:play-services-auth:18.1.0'

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

    implementation project(':tipsi-stripe')
    implementation 'me.leolin:ShortcutBadger:1.1.22@aar' // <-- Add this line if you wish to use badge on Android

    implementation('com.eightbitlab:blurview:1.6.6') {
        force = true
    }

logger.warn('enableHermes 3: {}', enableHermes)
    if (enableHermes) {
logger.warn('enableHermes 4')
      def hermesPath = "../../node_modules/hermes-engine/android/";
      debugImplementation files(hermesPath + "hermes-debug.aar")
      releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
      implementation jscFlavor
    }
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.implementation
    into 'libs'
}

project.ext.vectoricons = [
    iconFontNames: [ 'Ionicons.ttf' ] // Name of the font files you want to copy
]

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
apply plugin: 'com.google.gms.google-services'
googleServices { disableVersionCheck = true }

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle");
applyNativeModulesAppBuildGradle(project)
</code>```

答: Turns out that this project has V8 configured for android. Once I removed V8, the problem went away.</p>

Title: How to fix hermes on android

Body:
I have an existing react native app which even though I configure hermes in android/app/build.gradle and in proguard-rules won't work.

What I mean by won't work is that when I check at runtime, it says that hermes is not running.

    const isHermes = () => !!global.HermesInternal;
    console.log('hermes: ', isHermes()); <==== logs false

In the logs I can see

not allowing consideration of lib/armeabi-v7a/libhermes-executor-common-debug.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-executor-common-release.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-executor-debug.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-executor-release.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes-inspector.so: deferring to libdir
not allowing consideration of lib/armeabi-v7a/libhermes.so: deferring to libdir

in proguard-rules.pro

# hermes
-keep class com.facebook.hermes.unicode.** { *; }
-keep class com.facebook.jni.** { *; }

the app/build.gradle

apply plugin: "com.android.application"

apply plugin: "com.bugsnag.android.gradle"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

//react-native-config (https://github.com/luggit/react-native-config#android-1)
project.ext.envConfigFiles = [
    dev: ".env.dev",
    staging: ".env.staging",
    beta: ".env.production",
    release: ".env.production"
]

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
//!react-native-config

apply plugin: "com.google.firebase.firebase-perf"
import com.android.build.OutputFile

project.ext.react = [
   // clean and rebuild if changing,
    entryFile: "index.js",
    enableHermes: true
]

apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = true

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'
/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", true);
logger.warn('enableHermes: {}', enableHermes)
/**
 * Architectures to build native code for in debug.
 */
def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures")

android {

    ndkVersion rootProject.ext.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

   packagingOptions {
        pickFirst '**/armeabi-v7a/libc++_shared.so'
        pickFirst '**/x86/libc++_shared.so'
        pickFirst '**/arm64-v8a/libc++_shared.so'
        pickFirst '**/x86_64/libc++_shared.so'
        pickFirst '**/x86/libjsc.so'
        pickFirst '**/armeabi-v7a/libjsc.so'
        pickFirst '**/x86_64/libjsc.so'
        pickFirst '**/arm64-v8a/libjsc.so'

        pickFirst "lib/armeabi-v7a/libc++_shared.so"
        pickFirst "lib/arm64-v8a/libc++_shared.so"
        pickFirst "org/bouncycastle/x509/CertPathReviewerMessages_de.properties"
        pickFirst "org/bouncycastle/x509/CertPathReviewerMessages.properties"
        pickFirst "lib/x86/libc++_shared.so"
        pickFirst "lib/x86_64/libc++_shared.so"
         exclude "**/libjsc.so"
    }

    compileSdkVersion rootProject.ext.compileSdkVersion
    defaultConfig {
        applicationIdSuffix ""
        applicationId "XXX.YYY"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1038160033
        vectorDrawables.useSupportLibrary = true
        versionName "5.8.130"
        resConfigs "fr", "FR"
         if (nativeArchitectures) {
                ndk {
                    abiFilters nativeArchitectures.split(',')
                }
            }
        resValue "string", "build_config_package", "XXX.YYY"

        //fix for codepush not being able to install downloaded package
        //https://github.com/microsoft/react-native-code-push/issues/1961#issuecomment-710698621
        resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
    }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }

    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }

    bugsnag {
      uploadReactNativeMappings = true // enables upload of React Native source maps
    }

    buildTypes {
        //note that config name that contain 'release' will be build with DEV turned off for React Native
        //all other will have DEV set to true. Look for the Note in the android section of this page
        //https://learn.microsoft.com/en-us/appcenter/distribution/codepush/rn-deployment#android

        //!!!!! don't modify the version via versionNameSuffix, else code push will not find the version anymore

        debug {
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false",
                                    DOMAIN:"XXX",
                                    FIREBASE_DOMAIN:'XXX',
                                    brandTestMode:"true",
                                    BUGSNAG_KEY:"XXX"]
            applicationIdSuffix ".debug"
            debuggable true
            signingConfig signingConfigs.release

            firebaseCrashlytics {
              nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxx"'
        }

        dev {
            initWith debug

            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false",
                                    DOMAIN:"xxx",
                                    FIREBASE_DOMAIN:'xxx',
                                    brandTestMode:"true",
                                    BUGSNAG_KEY:"xxxx"]

            matchingFallbacks = ['debug']
            applicationIdSuffix ".debug"
             firebaseCrashlytics {
                nativeSymbolUploadEnabled false
            }

            //disable codepush in dev builds
            resValue "string", "CodePushDeploymentKey", '""' // '"xxxx"'
        }

        staging {
            initWith debug

            manifestPlaceholders = [excludeSystemAlertWindowPermission: "false",
                                    DOMAIN:"xxxco",
                                    FIREBASE_DOMAIN:'xxxx',
                                    brandTestMode:"true",
                                    BUGSNAG_KEY:"xxxxx"]

            matchingFallbacks = ['debug']
            applicationIdSuffix ".debug"
            firebaseCrashlytics {
              nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxxx"'
        }

        beta {
            initWith release
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "true",
                                    DOMAIN:"xxx",
                                    FIREBASE_DOMAIN:'fbxxx',
                                    brandTestMode:"false",
                                    BUGSNAG_KEY:"xxxx"]
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
            matchingFallbacks = ['release']
            applicationIdSuffix ".beta"
            shrinkResources true
            firebaseCrashlytics {
              nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxx"'
        }

        release {
            manifestPlaceholders = [excludeSystemAlertWindowPermission: "true",
                                    DOMAIN:"xxxx",
                                    FIREBASE_DOMAIN:'xxx',
                                    brandTestMode:"false",
                                    BUGSNAG_KEY:"xxxxx"]
            minifyEnabled false
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
            firebaseCrashlytics {
                nativeSymbolUploadEnabled false
            }

            resValue "string", "CodePushDeploymentKey", '"xxxxx"'
        }
    }
}
    ext.abiCodes = ['armeabi-v7a':'1', 'arm64-v8a':'2', 'mips':'3', 'x86':'4', 'x86_64':'5']
// For each APK output variant, override version code of outputs based on ABI codes
// ex) 'mips' -> 3xxx
// ex) 'x86' -> 4xxx
android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def baseVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
        if (baseVersionCode != null) {
            output.versionCodeOverride = Integer.valueOf(baseVersionCode + variant.versionCode)
        }
    }
}

dependencies {
    implementation "com.google.firebase:firebase-messaging:22"

    implementation 'com.google.firebase:firebase-appcheck-safetynet:16.0.0-beta01'
    // To enable the Google Advertising ID for adjust
    // https://help.adjust.com/en/article/get-started-android-sdk#add-google-play-services
    implementation 'com.google.android.gms:play-services-location:18.0.0'

 implementation fileTree(dir: "libs", include: ["*.jar"])
   implementation ("com.facebook.react:react-native:+") { force = true
}

   implementation 'org.chromium:v8-android:9.93.+'

        debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
        exclude group:'com.squareup.okhttp3', module:'okhttp'
    }

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
    }

       debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
         exclude group:'com.facebook.fbjni'
    }

implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation("com.squareup.okhttp3:okhttp-urlconnection:4.4.1")
implementation 'com.instabug.library:instabug-apm-okhttp-interceptor:10.4.0'

    implementation ('com.facebook.fresco:fresco:2.4.0') {
  exclude module: 'nativeimagefilters'
  exclude module: 'nativeimagetranscoder'
}

//   implementation project(':react-native-fast-image')
      // For animated GIF support
    implementation 'com.facebook.fresco:animated-gif:2.4.0'
    implementation 'com.google.android.gms:play-services-wallet:18.1.2'
  // For WebP support, including animated WebP
    implementation 'com.facebook.fresco:animated-webp:2.4.0'
    implementation 'com.facebook.fresco:webpsupport:2.4.0'

     implementation 'com.facebook.android:facebook-core:9.1.0'

    implementation project(':react-native-check-app-install')

   implementation "com.stripe:stripe-3ds2-android:5.3.1"
    implementation 'com.braintreepayments.api:braintree:3.17.3'
    implementation 'com.braintreepayments.api:three-d-secure:3.17.3'

    implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
    implementation 'com.android.installreferrer:installreferrer:2.2'

    implementation 'com.google.android.gms:play-services-auth:18.1.0'

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

    implementation project(':tipsi-stripe')
    implementation 'me.leolin:ShortcutBadger:1.1.22@aar' // <-- Add this line if you wish to use badge on Android

    implementation('com.eightbitlab:blurview:1.6.6') {
        force = true
    }

logger.warn('enableHermes 3: {}', enableHermes)
    if (enableHermes) {
logger.warn('enableHermes 4')
      def hermesPath = "../../node_modules/hermes-engine/android/";
      debugImplementation files(hermesPath + "hermes-debug.aar")
      releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
      implementation jscFlavor
    }
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.implementation
    into 'libs'
}

project.ext.vectoricons = [
    iconFontNames: [ 'Ionicons.ttf' ] // Name of the font files you want to copy
]

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
apply plugin: 'com.google.gms.google-services'
googleServices { disableVersionCheck = true }

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle");
applyNativeModulesAppBuildGradle(project)


问:
Bitly API V4 in Google Apps Script: getting errors when trying to call clicks summary
I am fairly new to Apps Script and this is my first custom function using an API. Thankyou in advance for your advice.

I have been following this code to integrate Bitly into Google Sheets. https://gist.github.com/misterhay/38a500545ce7abc75b875f33f01c9f51

The code they provide for ShortenBitly works perfectly, however I cannot get ExpandBitly or Stats functions to work.

Below is my code for BitlyStats, and the error code I am getting.

```<code> * Retrieves the final URL from a bitlink
 *
 * @param {string} the bitly link
 * @return {string} the total clicks
 * @customfunction
 */

function bitlyStats(bitlink) {
  var bitlink = 'bitlink'
  Logger.log(bitlink)
  var accessToken = 'MYTOKEN';
  var fetchUrl = 'https://api-ssl.bitly.com/v4/bitlinks/' + bitlink + '/clicks/summary';
  Logger.log(fetchUrl)
  var headers = {
    'Authorization': 'Bearer '+ accessToken,
    'Content-Type': 'application/json',
  };
  var params = {
    'method' : 'get',
    'headers' : headers,
    'muteHttpExceptions' : true
  };
  var response = UrlFetchApp.fetch(fetchUrl, params);
  Logger.log(response.getContent());
  var clickCount = JSON.parse(response.getContent()).total_clicks;
  return clickCount;
}
</code>```

This is the error message;

SyntaxError: Unexpected token , in JSON at position 2
bitlyStats  @ Code.gs:26

the Log for line 25 reads [52.0, 48.0, 52.0, 32.0, 112.0, 97.0, 103.0, 101.0, 32.0, 110.0, 111.0, 116.0, 32.0, 102.0, 111.0, 117.0, 110.0, 100.0, 10.0]

答:
This is a working code for Bitly using v4 API to shorten a long URL. You can also create a copy of this sheet and bulk create bitly links using the function bitlyShortenUrl in the 3rd column- https://docs.google.com/spreadsheets/d/1TS-aQcDu3rRv-LexEoIqDiX0ydv69ijkXQP-nuQdBz4/edit#gid=0

```<code>function bitlyShortenUrl(longLink, accessToken) {
  var form = {
    "domain": "bit.ly",
    "long_url": longLink
  };
  var url = "https://api-ssl.bitly.com/v4/shorten";

  var options = {
      "headers": { Authorization: `Bearer ${accessToken}` },
      "method": "POST",
      "contentType" : "application/json",
      "payload": JSON.stringify(form)
  };
  var response = UrlFetchApp.fetch(url, options);
  var responseParsed = JSON.parse(response.getContentText());
  return(responseParsed["link"]);
}
</code>```

PS: Bitly access token details given here https://support.bitly.com/hc/en-us/articles/230647907-How-do-I-generate-an-OAuth-access-token-for-the-Bitly-API-

Body:
I am fairly new to Apps Script and this is my first custom function using an API. Thankyou in advance for your advice.

I have been following this code to integrate Bitly into Google Sheets. https://gist.github.com/misterhay/38a500545ce7abc75b875f33f01c9f51

The code they provide for ShortenBitly works perfectly, however I cannot get ExpandBitly or Stats functions to work.

Below is my code for BitlyStats, and the error code I am getting.

 * Retrieves the final URL from a bitlink
 *
 * @param {string} the bitly link
 * @return {string} the total clicks
 * @customfunction
 */

function bitlyStats(bitlink) {
  var bitlink = 'bitlink'
  Logger.log(bitlink)
  var accessToken = 'MYTOKEN';
  var fetchUrl = 'https://api-ssl.bitly.com/v4/bitlinks/' + bitlink + '/clicks/summary';
  Logger.log(fetchUrl)
  var headers = {
    'Authorization': 'Bearer '+ accessToken,
    'Content-Type': 'application/json',
  };
  var params = {
    'method' : 'get',
    'headers' : headers,
    'muteHttpExceptions' : true
  };
  var response = UrlFetchApp.fetch(fetchUrl, params);
  Logger.log(response.getContent());
  var clickCount = JSON.parse(response.getContent()).total_clicks;
  return clickCount;
}

This is the error message;

SyntaxError: Unexpected token , in JSON at position 2
bitlyStats  @ Code.gs:26

the Log for line 25 reads [52.0, 48.0, 52.0, 32.0, 112.0, 97.0, 103.0, 101.0, 32.0, 110.0, 111.0, 116.0, 32.0, 102.0, 111.0, 117.0, 110.0, 100.0, 10.0]

Body:
This is a working code for Bitly using v4 API to shorten a long URL. You can also create a copy of this sheet and bulk create bitly links using the function bitlyShortenUrl in the 3rd column- https://docs.google.com/spreadsheets/d/1TS-aQcDu3rRv-LexEoIqDiX0ydv69ijkXQP-nuQdBz4/edit#gid=0

function bitlyShortenUrl(longLink, accessToken) {
  var form = {
    "domain": "bit.ly",
    "long_url": longLink
  };
  var url = "https://api-ssl.bitly.com/v4/shorten";

  var options = {
      "headers": { Authorization: `Bearer ${accessToken}` },
      "method": "POST",
      "contentType" : "application/json",
      "payload": JSON.stringify(form)
  };
  var response = UrlFetchApp.fetch(url, options);
  var responseParsed = JSON.parse(response.getContentText());
  return(responseParsed["link"]);
}

PS: Bitly access token details given here https://support.bitly.com/hc/en-us/articles/230647907-How-do-I-generate-an-OAuth-access-token-for-the-Bitly-API-


问:
Where GCP dataproc stores notebook instances?
I created a Spark cluster using Dataproc with Jupyter Notebook attached to it. Then I Deleted the cluster and I assumed the notebooks are gone. However after creating another cluster (connected to the same Bucket) I can see my old notebooks. Does it mean that notebooks (or their checkpoints) are stored into my bucket? Or where are they stored and how to make sure they are deleted?

答:
Dataproc allows creating distributed computing cluster (Hadoop, Map reduce, spark,...). It's only for processing (you can keep temporary data in the internal HDFS system) but all the input and output and done in a bucket (Cloud Storage is the new/internal Google version of HDFS -> HDFS is the open source implementation of the specification publicly released by Google. Since then, Google has internally improve the system (Cloud Storage), but it's still compliant with HDFS).

Therefore, yes, it's normal that your data are still in your Cloud Storage bucket.


问:
How can i reduce the Facebook permissions to minimum required
For example my web site name is "DOMINOS". I have a DOMINOS facebook APP called DOMINOS.FB.APP (App name)

If user is not added under DOMINOS.FB.APP, it show one page when user try to login with facebook. (User will be added only once)

In that pop-up facebook show ,

```<code>DOMINOS is requesting permission to do the following:

Access my basic information
Includes name, profile picture, gender, networks, user ID, list of friends, and any other information I've shared with everyone.

Send me email
Dev.SJ may email me directly at sahal006@gmail.com ·

.......
.....
etc etc
</code>```

I don't want above pop up to be displayed Or i can control the permission somewhere in the APP account ?

答: From what you describe, I think you are saying about Facebook login button (<fb:login-button> tag). If that is the case, you should find an attribute "perms" that is set "email" on your HTML page (where user click to login with Facebook), not in the FB app settings.

ContentLicense: CC BY-SA 3.0

Body:
For example my web site name is "DOMINOS". I have a DOMINOS facebook APP called DOMINOS.FB.APP (App name)

If user is not added under DOMINOS.FB.APP, it show one page when user try to login with facebook. (User will be added only once)

In that pop-up facebook show ,

DOMINOS is requesting permission to do the following:

Access my basic information
Includes name, profile picture, gender, networks, user ID, list of friends, and any other information I've shared with everyone.

Send me email
Dev.SJ may email me directly at sahal006@gmail.com ·

.......
.....
etc etc

I don't want above pop up to be displayed Or i can control the permission somewhere in the APP account ?


问:
Could not load file or assembly 'Microsoft.SqlServer.Types,Version=15.0.0.0,Culture Neutral,PublicKeyToken=89845dcd8080cc91'
I'm a C# Developer, and i encounter a problem when i create the DataSet type (especially TableAdapter).

I installed the Microsoft.SqlServer.Types package from Nuget Packages Solution
but still the same thing.

Could not load file or assembly
  'Microsoft.SqlServer.Types,Version=15.0.0.0,Culture
  Neutral,PublicKeyToken=89845dcd8080cc91' or one of its dependencies.
  the specific file is not found.

答:
I'm on visual studio 2019 community edition and use data source i will try update to 2022 next

Select Tools > Import and Export Settings from the menu bar to open
the Import and Export Settings Wizard.

In the Import and Export Settings Wizard, select Reset all settings,choose no to

save current

restart visual studio and data source worked


问:
When is postgres database created?
Let's say I'm running pg_ctl init or initdb to initialise cluster.
When is the exact moment the default database inside this cluster is created?

In the initdb procedure?

After I run the server?

After the first connection to the database?

答:
To see:

```<code>/usr/local/pgsql14/bin/initdb -D data/
cd data/
ls -al base/
drwx------  2 postgres users 4096 Feb  9 08:17 1
drwx------  2 postgres users 4096 Feb  9 08:17 13596
drwx------  2 postgres users 4096 Feb  9 08:17 13597

ls -al base/1
total 8304
drwx------ 2 postgres users   4096 Feb  9 08:17 .
drwx------ 5 postgres users   4096 Feb  9 08:17 ..
-rw------- 1 postgres users   8192 Feb  9 08:17 112
-rw------- 1 postgres users   8192 Feb  9 08:17 113
-rw------- 1 postgres users 114688 Feb  9 08:17 1247
-rw------- 1 postgres users  24576 Feb  9 08:17 1247_fsm
-rw------- 1 postgres users   8192 Feb  9 08:17 1247_vm
...
</code>```

From here [Database File Layout]:

base   Subdirectory containing per-database subdirectories

So the 'system' databases are built upon using init(db).

Title: When is postgres database created?

Body:
To see:

/usr/local/pgsql14/bin/initdb -D data/
cd data/
ls -al base/
drwx------  2 postgres users 4096 Feb  9 08:17 1
drwx------  2 postgres users 4096 Feb  9 08:17 13596
drwx------  2 postgres users 4096 Feb  9 08:17 13597

ls -al base/1
total 8304
drwx------ 2 postgres users   4096 Feb  9 08:17 .
drwx------ 5 postgres users   4096 Feb  9 08:17 ..
-rw------- 1 postgres users   8192 Feb  9 08:17 112
-rw------- 1 postgres users   8192 Feb  9 08:17 113
-rw------- 1 postgres users 114688 Feb  9 08:17 1247
-rw------- 1 postgres users  24576 Feb  9 08:17 1247_fsm
-rw------- 1 postgres users   8192 Feb  9 08:17 1247_vm
...

From here [Database File Layout]:

base   Subdirectory containing per-database subdirectories

So the 'system' databases are built upon using init(db).


问:
Break While Loop adding "last" to

In WordPress, I'm using this:

```<code>while ($wp_query->have_posts()) : $wp_query->the_post(); ?>
echo "<div class='test'>test</div>";
<?php endwhile; ?>
</code>```

I'd now like it so for every 2nd element, it would add the "last" class to the div, so the final code could be:

```<code><div class='test'>test</div>
<div class='test last'>test</div>
<div class='test'>test</div>
<div class='test last'>test</div>
<div class='test'>test</div>
<div class='test last'>test</div>.....
</code>```

Many thanks for any pointers.

答:
```<code>$i = 0;
while ($wp_query->have_posts()) {
    $wp_query->the_post();
    $i++
    if ($i %% 2){
        echo "<div class='test last'>test</div>";
    }
    else{
        echo "<div class='test'>test</div>";
    }
endwhile; ?>
</code>```

Title: Break While Loop adding "last" to <div>

Body:
In WordPress, I'm using this:

while ($wp_query->have_posts()) : $wp_query->the_post(); ?>
echo "
test
";
<?php endwhile; ?>

I'd now like it so for every 2nd element, it would add the "last" class to the div, so the final code could be:

test

test

test

test

test

test
.....

Many thanks for any pointers.


问:
Classic ASP: how to show a PDF that is returned by Json
I want to let the users download a PDF that is received back from a API after a Json request.
When a user opens ShowPDF.asp the request happens and there opens a new window where the PDF is downloaded.

The problem is that the downloaded PDF is not valid; it says that the file can't be opened. The size of the file is around 500kb, so there is something in it.
When I make the same request in Postman I see the content from the PDF file in the result screen and when I save it it's also around 500kb.

What is received back from the request is the actual content of the PDF file:

```<code>%PDF-1.4
3 0 obj
<</Type /Page
/Parent 1 0 R
</code>```

The code:

PDF.asp

```<code>Response.AddHeader "Content-Disposition","attachment; filename=name.pdf
Response.ContentType = "application/pdf"

PDFcontent = GetPDF(strToken)
response.write PDFcontent
</code>```

GetPDF(sToken)

```<code>public function GetPDF(sToken)
    Set xmlhttp = CreateObject("Msxml2.ServerXMLHTTP.6.0")
    xmlhttp.open "GET", "www.fakeUrl.com/rest/download", false
    xmlhttp.setRequestHeader "Authorization", "Bearer "& sToken
    xmlhttp.setRequestHeader "Content-Type", "application/json; charset=UTF-8"
    xmlhttp.send ""
    GetPDF = xmlhttp.responseText
end function
</code>```

ShowPDF.asp

```<code>window.open('PDF.asp');
</code>```

What am I missing here?

答:
The problem is you are treating the download of a binary file as if it was text. But luckily the fix isn't too difficult.

Adjust the

```<code>GetPDF = xmlhttp.responseText
</code>```

to

```<code>GetPDF = xmlhttp.responseBody
</code>```

Then change

```<code>response.write PDFcontent
</code>```

to

```<code>Response.BinaryWrite PDFcontent
</code>```

Useful Links

Answer to: How to show a byte stream response

Body:
I want to let the users download a PDF that is received back from a API after a Json request.
When a user opens ShowPDF.asp the request happens and there opens a new window where the PDF is downloaded.

The problem is that the downloaded PDF is not valid; it says that the file can't be opened. The size of the file is around 500kb, so there is something in it.
When I make the same request in Postman I see the content from the PDF file in the result screen and when I save it it's also around 500kb.

What is received back from the request is the actual content of the PDF file:

%PDF-1.4
3 0 obj
<</Type /Page
/Parent 1 0 R

The code:

PDF.asp

Response.AddHeader "Content-Disposition","attachment; filename=name.pdf
Response.ContentType = "application/pdf"

PDFcontent = GetPDF(strToken)
response.write PDFcontent

GetPDF(sToken)

public function GetPDF(sToken)
    Set xmlhttp = CreateObject("Msxml2.ServerXMLHTTP.6.0")
    xmlhttp.open "GET", "www.fakeUrl.com/rest/download", false
    xmlhttp.setRequestHeader "Authorization", "Bearer "& sToken
    xmlhttp.setRequestHeader "Content-Type", "application/json; charset=UTF-8"
    xmlhttp.send ""
    GetPDF = xmlhttp.responseText
end function

ShowPDF.asp

window.open('PDF.asp');

What am I missing here?

Body:
The problem is you are treating the download of a binary file as if it was text. But luckily the fix isn't too difficult.

Adjust the

GetPDF = xmlhttp.responseText

to

GetPDF = xmlhttp.responseBody

Then change

response.write PDFcontent

to

Response.BinaryWrite PDFcontent

Useful Links

Answer to: How to show a byte stream response


问:
How to include OpenGapps in AOSP 12 build?
I am building AOSP 12 for my Pixel 3a sargo. It worked but I wanted to install Gapps on it. When I tried to flash any Gapps zip in TWRP, it said that my system partition was read-only or full, so I tried remounting it with the read and write permissions. But it showed the same thing. After that, I saw that my system partition was full. So I was wondering, how I can include Gapps while building AOSP? But since OpenGapps is not available for Android 12 (I tried but the build failed), I don't know how to include Gapps in my build.

Can someone help me, please?

答:
I finally found how to do this:

First add this to your repo manifest:

```<code><remote name="MindTheGapps" fetch="https://gitlab.com/MindTheGapps/" />
<project path="vendor/gapps" name="vendor_gapps" remote="MindTheGapps" revision="sigma" />
</code>```

Then repo sync.
After, add this lines to your device.mk:

```<code>include vendor/gapps/arm64/arm64-vendor.mk
</code>```

And build.

If you have an error with ELF files, add this line to your boardconfig.mk:

```<code>BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true
</code>```

and this should work.

Body:
I finally found how to do this:

First add this to your repo manifest:

<remote name="MindTheGapps" fetch="https://gitlab.com/MindTheGapps/" />
<project path="vendor/gapps" name="vendor_gapps" remote="MindTheGapps" revision="sigma" />

Then repo sync.
After, add this lines to your device.mk:

include vendor/gapps/arm64/arm64-vendor.mk

And build.

If you have an error with ELF files, add this line to your boardconfig.mk:

BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true

and this should work.


问:
What is the correct way of dealing loading state in flutter?
for example I have 4 future builder in one screen. All of them returns CircularProgress indicator when they are still waiting for the data. In this case my screen gets full of circular progress indicator. Instead of this I want to show loading screen until all of the FutureBuilders gets their data. What is the correct way to handle this ?</p>

答:
The correct way is to wrap the tasks of those 4 futures into one and wait for them to finish using await sequentially, after last await you can simply hide your loader.

If your requirement is different and you can't wait for all 4 task synchronously. You can have an array of int(data type doesn't matter).

and simply initialise it with 4 elements, remove first element on finishing task from future builder.

```<code>List<int> _taskList = [0,1,2,3];
</code>```

remove when one of the future finishes

```<code>_taskList.removeAt(0);
</code>```

Use one Loader Widget in parent with condition

```<code>[if(_taskList.length >= 1) Loader(),]
</code>```

For asynchronous transactions you've to manage some kind of ledger. Preferred way is using await

Body:
The correct way is to wrap the tasks of those 4 futures into one and wait for them to finish using await sequentially, after last await you can simply hide your loader.

If your requirement is different and you can't wait for all 4 task synchronously. You can have an array of int(data type doesn't matter).

and simply initialise it with 4 elements, remove first element on finishing task from future builder.

List<int> _taskList = [0,1,2,3];

remove when one of the future finishes

_taskList.removeAt(0);

Use one Loader Widget in parent with condition

[if(_taskList.length >= 1) Loader(),]

For asynchronous transactions you've to manage some kind of ledger. Preferred way is using await


问:
Kubernetes global variables (for all namespaces)
I need to create and mantain some global variables accessible for applications running in all namespaces, because some tools/apps are standard in my dev cluster.

For example:

APM ENDPOINT

APM User/pass

RabbitMQ endpoint

MongoDB endpoint

For any reason, when i change/migrate any global variable, i want to change one time for all running applications in cluster (just needed restart pod), and if a create an "global" configmap and read in envFrom, i need to change/update the configmap in all namespaces.

Someone have an idea to do this? I thinked to use Hashicorp vault with specific role for global environments, but i need to adapt all applications to use Vault, and maybe have better idea.

Thanks

答: There is no in-built solution in Kubernetes for it except for creating a ConfigMap, and use  envFrom  to define all of the ConfigMap's data as Pod environment variables, which will indeed require to update them separately for each namespace. So using HashiCorp Vault is a better solution here; one more option here can be trying to customize env with Kubernetes addons like this.


问:
In HTML, how do I make an Image in a table cell resize to text in the same row?
I'm creating an 'About' section for a website, which is a table with three equal-width columns: a headshot, a paragraph, and another paragraph (see screenshots below).

I'd like to have the image automatically resize (keeping its aspect ratio) to be the height of the largest text- aligned left within the cell- without hardcoding any height/width values. However, I've played around a bunch and nothing seems to make the image resize.

/* an element that's one-third the width of its container */

.third-width {
  width: 33%;
}

/* the headshot photo */

#headshot {
  border-radius: 5px;
  max-width: 100%;
  max-height: 100%;
  display: inline-block;
}

#about-table td {
  background-color: pink;
  padding: 1vw;
  text-align: justify;
  vertical-align: top;
  font-family: var(--body-font);
  font-weight: lighter;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><table id="about-table">
  <tr>
    <td class="third-width">
      <img id="headshot" src="https://via.placeholder.com/80" alt="None">
    </td>
    <td class="third-width">
      <p>[... SOME TEXT ...]</p>
    </td>
    <td class="third-width">
      <p>[... SOME TEXT ...]</p>
    </td>
  </tr></code>```

Current state:

What I would like:

Thank you!

答:
Use CSS Flex instead of table

Make the cells flex: 1; position: relative;

Make the image position: absolute; with 100% W/H and object-fit: cover to not distort the image

/* QuickReset */

* { margin:0; box-sizing: border-box; }

/* About component */

.About {
  display: flex;
}

.About > div {
  position: relative;
  flex: 1;
  outline: 1px solid #000;
  padding: 20px;
}

.About > div img {
  position: absolute;
  top:0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="About">
  <div><img src="https://placekitten.com/408/287" alt="Catz!"></div>
  <div>Lorem ipsum</div>
  <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae sunt nisi nostrum sed, assumenda sequi doloribus excepturi quibusdam obcaecati tenetur tempora voluptatibus eligendi dolorem. Excepturi perspiciatis ipsa porro, minus ea.</div>
</div>

<div class="About">
  <div>Lorem ipsum</div>
  <div>Molestiae sunt nisi nostrum sed,  ipsa porro, minus ea.</div>
  <div><img src="https://placekitten.com/500/300" alt="Catz!"></div>
</div>

<div class="About">
  <div><img src="https://placekitten.com/310/290" alt="Catz!"></div>
  <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae sunt nisi nostrum sed, assumenda sequi doloribus excepturi quibusdam obcaecati tenetur</div>
  <div>Lorem ipsum</div>
</div></code>```

Body:
I'm creating an 'About' section for a website, which is a table with three equal-width columns: a headshot, a paragraph, and another paragraph (see screenshots below).

I'd like to have the image automatically resize (keeping its aspect ratio) to be the height of the largest text- aligned left within the cell- without hardcoding any height/width values. However, I've played around a bunch and nothing seems to make the image resize.

/* an element that's one-third the width of its container */

.third-width {
  width: 33%;
}

/* the headshot photo */

#headshot {
  border-radius: 5px;
  max-width: 100%;
  max-height: 100%;
  display: inline-block;
}

#about-table td {
  background-color: pink;
  padding: 1vw;
  text-align: justify;
  vertical-align: top;
  font-family: var(--body-font);
  font-weight: lighter;
}

[... SOME TEXT ...]

[... SOME TEXT ...]

Current state:

What I would like:

Thank you!

Body:
Use CSS Flex instead of table

Make the cells flex: 1; position: relative;

Make the image position: absolute; with 100% W/H and object-fit: cover to not distort the image

/* QuickReset */

* { margin:0; box-sizing: border-box; }

/* About component */

.About {
  display: flex;
}

.About > div {
  position: relative;
  flex: 1;
  outline: 1px solid #000;
  padding: 20px;
}

.About > div img {
  position: absolute;
  top:0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

<div class="About">
  <div><img src="https://placekitten.com/408/287" alt="Catz!"></div>
  <div>Lorem ipsum</div>
  <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae sunt nisi nostrum sed, assumenda sequi doloribus excepturi quibusdam obcaecati tenetur tempora voluptatibus eligendi dolorem. Excepturi perspiciatis ipsa porro, minus ea.</div>
</div>

<div class="About">
  <div>Lorem ipsum</div>
  <div>Molestiae sunt nisi nostrum sed,  ipsa porro, minus ea.</div>
  <div><img src="https://placekitten.com/500/300" alt="Catz!"></div>
</div>

<div class="About">
  <div><img src="https://placekitten.com/310/290" alt="Catz!"></div>
  <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae sunt nisi nostrum sed, assumenda sequi doloribus excepturi quibusdam obcaecati tenetur</div>
  <div>Lorem ipsum</div>
</div>


问:
How to plot histograms in base R in the margin of a plot
I'd like to add histograms in base R to the margins of a plot, I've tried many ways, and used points and segments to plot the values calculated from a histogram. The challenge is that after plotting the data, the width of the bars have to be set manually in order to show a histogram like margin plot.

```<code># Inspired from
# https://github.com/ChrKoenig/R_marginal_plot/blob/master/marginal_plot.R
par(mfrow = c(1,2), mar =c(4,4,3,3), cex = 1.4)
set.seed(1234)
n = 250
x.1 = rnorm(n, mean = 15, sd = 5)
y.1 = rnorm(n, mean = 5, sd = 2)

x.2 = rnorm(n, mean = 15, sd = 1)
y.2 = rnorm(n, mean = 5, sd = .5)
x = x.1
y = y.1
moreargs$xlim[1] <- range(c(-3,x.1,x.2, max(x.1,x.2)+5))[1]
moreargs$xlim[2] <- range(c(-3,x.1,x.2, max(x.1,x.2)+5))[2]
moreargs$ylim[1] <- range(c(y.1,y.2,max(y.1,y.2)+5))[1]
moreargs$ylim[2] <- range(c(y.1,y.2,max(y.1,y.2)+5))[2]
require(scales)

# plotting
data = data.frame(x = as.numeric(x), y = as.numeric(y))
group_colors = "black"

ifelse(test = !is.null(data$group),
       yes = data_split <- split(data, data$group),
       no = data_split <- list(data))
orig_par = par(no.readonly = T)
par(mar = c(0.25,5,1,0))
layout(matrix(1:4, nrow = 2, byrow = T), widths = c(10,3), heights = c(3,10))

histval = hist(x = data_split[[1]]$x, plot = FALSE)

# upper density plot
plot(NULL, type = "n",
     ylab = "Counts",
     xlim = moreargs$xlim,
     ylim = c(0, max(histval$counts)),
     main = NA, axes = F)
points(histval$mids,histval$counts, type= "h", lwd = 33, lend="butt", col = 'gray60')
# points(histval$mids,histval$counts-1, type= "h", lwd = 30, lend="butt", col = 'gray80')
axis(2, tck = 0.04)

# (add an empty plot in the corner)
par(mar = c(0.25,0.25,0,0))
plot.new()

# main plot
par(mar = c(4,5,0,0))
plot(y.1~x.1,
     ylim = moreargs$ylim,
     xlim = moreargs$xlim,
     pch = 19, col = scales::alpha("black",.8), ylab = "Y",xlab = "X")
axis(3, labels = F, tck = 0.01)
axis(4, labels = F, tck = 0.01)
box()

# right density plot
par(mar = c(4,0.25,0,1))
histval.y = hist(x = data_split[[1]]$y, plot = FALSE)
plot(NULL, type = "n",
     xlab = "Counts",
     xlim = c(0, max(histval$counts)),
     ylim = moreargs$ylim,
     main = NA, axes = F)

segments(x0 = 0,x1 = histval.y$counts,
         y0 = histval.y$mids,y1 = histval.y$mids,
         lwd = rep(c(46,2), each = length(histval.y$counts)), col = "gray60", lend="butt")
axis(1,tck=0.04)
par(orig_par)
</code>```

Is there a way to make histograms in base R in the margin of plots?

答:
Using layout, you can set a space to 0 so that it does not require a plot, it is empty space.

hist does not support horizontal mode, and recommendations (example) to use barplot are constrained in that one cannot fix where on the x-axis the bars are positioned. Yet another workaround is needed: since barplot is a wrapper around rect, we can write our own.

This function mimics some of barplot but allows us to set where the bars are located. This is to ensure that the shared axis can be the same dimensions.

barplot2 <- function(xs, ys, ..., space = 0, horiz = FALSE) {
  mids <- diff(xs) / 2
  mids <- c(mids[1], mids) - space/2
  if (horiz) {
    rect(0, xs - mids, ys, xs + mids, ...)
  } else {
    rect(xs - mids, 0, xs + mids, ys, ...)
  }
}
```
<p>It should be feasible to add <code>plot</code> in there as well, but then one needs to either be explicit with all arguments, or determine which from <code>...</code>-arguments go to <code>plot</code> and which go to <code>rect</code>. I'll dodge that discussion for now, and just explicitly call <code>plot</code> myself.</p>
<pre class="lang-r prettyprint-override"><code>layout(
  matrix(c(2,0,
           1,3), byrow=TRUE, nrow=2),
  widths = c(4,1), heights = c(1,4)
)
# main plot
par(mar = c(4, 5, 0, 0) + 0.1)
plot(y ~ x, data = data, pch = 16)
usr <- par("usr")
# top margin
par(mar = c(0, 5, 0, 0) + 0.1)
hx <- hist(data$x, plot = FALSE)
hy <- hist(data$y, plot = FALSE)
plot(NA, type = "n", xlim = usr[1:2], ylim = c(0, max(c(hx$counts, hy$counts))),
     xaxs = "i", yaxs = "i", xaxt = "n", ylab = "Counts", frame = FALSE)
barplot2(hx$mids, hx$counts, space = 0, horiz = FALSE, col = "gray")
# right margin
par(mar = c(4, 0, 0, 0) + 0.1)
plot(NA, type = "n", xlim = c(0, max(c(hx$counts, hy$counts))), ylim = usr[3:4],
     xaxs = "i", yaxs = "i", yaxt = "n", xlab = "Counts", frame = FALSE)
barplot2(hy$mids, hy$counts, space = 0, horiz = TRUE, col = "gray")
</code>```

Body:
I'd like to add histograms in base R to the margins of a plot, I've tried many ways, and used points and segments to plot the values calculated from a histogram. The challenge is that after plotting the data, the width of the bars have to be set manually in order to show a histogram like margin plot.

# Inspired from
# https://github.com/ChrKoenig/R_marginal_plot/blob/master/marginal_plot.R
par(mfrow = c(1,2), mar =c(4,4,3,3), cex = 1.4)
set.seed(1234)
n = 250
x.1 = rnorm(n, mean = 15, sd = 5)
y.1 = rnorm(n, mean = 5, sd = 2)

x.2 = rnorm(n, mean = 15, sd = 1)
y.2 = rnorm(n, mean = 5, sd = .5)
x = x.1
y = y.1
moreargs$xlim[1] <- range(c(-3,x.1,x.2, max(x.1,x.2)+5))[1]
moreargs$xlim[2] <- range(c(-3,x.1,x.2, max(x.1,x.2)+5))[2]
moreargs$ylim[1] <- range(c(y.1,y.2,max(y.1,y.2)+5))[1]
moreargs$ylim[2] <- range(c(y.1,y.2,max(y.1,y.2)+5))[2]
require(scales)

# plotting
data = data.frame(x = as.numeric(x), y = as.numeric(y))
group_colors = "black"

ifelse(test = !is.null(data$group),
       yes = data_split <- split(data, data$group),
       no = data_split <- list(data))
orig_par = par(no.readonly = T)
par(mar = c(0.25,5,1,0))
layout(matrix(1:4, nrow = 2, byrow = T), widths = c(10,3), heights = c(3,10))

histval = hist(x = data_split[[1]]$x, plot = FALSE)

# upper density plot
plot(NULL, type = "n",
     ylab = "Counts",
     xlim = moreargs$xlim,
     ylim = c(0, max(histval$counts)),
     main = NA, axes = F)
points(histval$mids,histval$counts, type= "h", lwd = 33, lend="butt", col = 'gray60')
# points(histval$mids,histval$counts-1, type= "h", lwd = 30, lend="butt", col = 'gray80')
axis(2, tck = 0.04)

# (add an empty plot in the corner)
par(mar = c(0.25,0.25,0,0))
plot.new()

# main plot
par(mar = c(4,5,0,0))
plot(y.1~x.1,
     ylim = moreargs$ylim,
     xlim = moreargs$xlim,
     pch = 19, col = scales::alpha("black",.8), ylab = "Y",xlab = "X")
axis(3, labels = F, tck = 0.01)
axis(4, labels = F, tck = 0.01)
box()

# right density plot
par(mar = c(4,0.25,0,1))
histval.y = hist(x = data_split[[1]]$y, plot = FALSE)
plot(NULL, type = "n",
     xlab = "Counts",
     xlim = c(0, max(histval$counts)),
     ylim = moreargs$ylim,
     main = NA, axes = F)

segments(x0 = 0,x1 = histval.y$counts,
         y0 = histval.y$mids,y1 = histval.y$mids,
         lwd = rep(c(46,2), each = length(histval.y$counts)), col = "gray60", lend="butt")
axis(1,tck=0.04)
par(orig_par)

Is there a way to make histograms in base R in the margin of plots?

Body:
Using layout, you can set a space to 0 so that it does not require a plot, it is empty space.

hist does not support horizontal mode, and recommendations (example) to use barplot are constrained in that one cannot fix where on the x-axis the bars are positioned. Yet another workaround is needed: since barplot is a wrapper around rect, we can write our own.

This function mimics some of barplot but allows us to set where the bars are located. This is to ensure that the shared axis can be the same dimensions.

barplot2 <- function(xs, ys, ..., space = 0, horiz = FALSE) {
  mids <- diff(xs) / 2
  mids <- c(mids[1], mids) - space/2
  if (horiz) {
    rect(0, xs - mids, ys, xs + mids, ...)
  } else {
    rect(xs - mids, 0, xs + mids, ys, ...)
  }
}

It should be feasible to add plot in there as well, but then one needs to either be explicit with all arguments, or determine which from ...-arguments go to plot and which go to rect. I'll dodge that discussion for now, and just explicitly call plot myself.

layout(
  matrix(c(2,0,
           1,3), byrow=TRUE, nrow=2),
  widths = c(4,1), heights = c(1,4)
)
# main plot
par(mar = c(4, 5, 0, 0) + 0.1)
plot(y ~ x, data = data, pch = 16)
usr <- par("usr")
# top margin
par(mar = c(0, 5, 0, 0) + 0.1)
hx <- hist(data$x, plot = FALSE)
hy <- hist(data$y, plot = FALSE)
plot(NA, type = "n", xlim = usr[1:2], ylim = c(0, max(c(hx$counts, hy$counts))),
     xaxs = "i", yaxs = "i", xaxt = "n", ylab = "Counts", frame = FALSE)
barplot2(hx$mids, hx$counts, space = 0, horiz = FALSE, col = "gray")
# right margin
par(mar = c(4, 0, 0, 0) + 0.1)
plot(NA, type = "n", xlim = c(0, max(c(hx$counts, hy$counts))), ylim = usr[3:4],
     xaxs = "i", yaxs = "i", yaxt = "n", xlab = "Counts", frame = FALSE)
barplot2(hy$mids, hy$counts, space = 0, horiz = TRUE, col = "gray")


问:
How method hiding works in C#? (Part Two)
The following program prints

```<code>A:C(A,B)
B:C(A,B)
</code>```

(as it should)

```<code>public interface I
{
    string A();
}

public class C : I
{
    public string A()
    {
        return "A";
    }

    public string B()
    {
        return "B";
    }
}

public class A
{
    public virtual void Print(C c)
    {
        Console.WriteLine("A:C(" + c.A() + "," + c.B() + ")");
    }
}

public class B : A
{
    public new void Print(C c)
    {
        Console.WriteLine("B:C(" + c.A() + "," + c.B() + ")");
    }

    public void Print(I i)
    {
        Console.WriteLine("B:I(" + i.A() + ")");
    }
}

class Program
{
    public static void Main(string[] args)
    {
        A a = new A();
        B b = new B();
        C c = new C();
        a.Print(c);
        b.Print(c);
    }
}
</code>```

however, if I change keyword 'new' to 'override' in class B like so:

```<code>    public override void Print(C c)
</code>```

all of a sudden program starts to print:

```<code>A:C(A,B)
B:I(A)
</code>```

Why?

答:
This was a great question.

All the answers can be found here:
http://msdn.microsoft.com/en-us/library/6fawty39(VS.80).aspx

The gist of it is this:

...the C# compiler will first try to make
the call compatible with the versions
of [functionName] declared originally on
[the derived class]. Override methods are not
considered as declared on a class,
they are new implementations of a
method declared on a base class. Only
if the C# compiler cannot match the
method call to an original method on
[the Derived class] will it try to match the call
to an overridden method with the same
name and compatible parameters.

So because you have a new method Print(I i) on the derived class which matches the argument "c", (because c implements I), that method takes precedence over the "override" method.

When you mark the method as "new", they are both considered to be implemented on the derived class, and the Print(C c) method more closely matches the parameter "c", so it takes precedence.

ContentLicense: CC BY-SA 2.5

Body:
The following program prints

A:C(A,B)
B:C(A,B)

(as it should)

public interface I
{
    string A();
}

public class C : I
{
    public string A()
    {
        return "A";
    }

    public string B()
    {
        return "B";
    }
}

public class A
{
    public virtual void Print(C c)
    {
        Console.WriteLine("A:C(" + c.A() + "," + c.B() + ")");
    }
}

public class B : A
{
    public new void Print(C c)
    {
        Console.WriteLine("B:C(" + c.A() + "," + c.B() + ")");
    }

    public void Print(I i)
    {
        Console.WriteLine("B:I(" + i.A() + ")");
    }
}

class Program
{
    public static void Main(string[] args)
    {
        A a = new A();
        B b = new B();
        C c = new C();
        a.Print(c);
        b.Print(c);
    }
}

however, if I change keyword 'new' to 'override' in class B like so:

    public override void Print(C c)

all of a sudden program starts to print:

A:C(A,B)
B:I(A)

Why?

OwnerDisplayName: womp