问:
Is there a way to sort gmail using a bookmarklet?
I was looking for a simple solution to sorting my Gmail by Sender, so that I can select all mail from a specific sender and archiving them, but I cannot find a working bookmarklet.  I have searched a few places and found the following bookmarklets:

```<code>javascript:function toArray (c) {var a, k;a = new Array;for (k=0; k < c.length; ++k)a[k] = c[k];return a;}function insAtTop(par,child) {if (par.childNodes.length)par.insertBefore(child, par.childNodes[0]);else par.appendChild(child);}function countCols(tab) {var nCols, i;nCols = 0;for(i = 0; i nCols)nCols = tab.rows[i].cells.length;return nCols;}function makeHeaderLink(colNo, ord, regex, numeric) {var link;link = document.createElement('a');link.href = '#';link.onclick = function() {var __st = window == top ? window : top;__st.sortTable(colNo, ord, regex, numeric);return false;};link.appendChild(document.createTextNode((ord>0)? 'asc':'desc'));return link;}function makeSortControl(header, col, title, regex, numeric) {header.appendChild(document.createTextNode(title + ' ['));header.appendChild(makeHeaderLink(col, 1, regex, numeric));header.appendChild(document.createTextNode('/'));header.appendChild(makeHeaderLink(col, -1, regex, numeric));header.appendChild(document.createTextNode(']'));}function makeHeader(nCols) {var header, headerCell, i;header = document.createElement('span');/*put links in columns 2 and 4 only (sender, subject)*/makeSortControl(header, 2, 'Sender(s)');header.appendChild(document.createTextNode(' | '));makeSortControl(header, 4, 'Subject');header.appendChild(document.createTextNode(' | '));makeSortControl(header, 2, 'Thread Activity', /\(\d*\)$/, true);return header;}function getWidestTable(tables) {var maxTable = undefined;var maxWidth = -1;for (var i = 0; i= maxWidth && table.id != '') {maxWidth = table.clientWidth;maxTable = table;}}return maxTable;}function getAllTables() {g_tables = toArray(document.getElementsByTagName('table'));var iframe = document.getElementById('canvas_frame');if (!iframe)return null;var iframedoc = iframe.contentDocument.document || iframe.contentWindow.document;iframetables = toArray(iframedoc.getElementsByTagName('table'));if (iframetables.length)g_tables = g_tables.concat(iframetables);if (!g_tables.length)return null;return g_tables;}(function () {/* ---- main() ---- ENTRY POINT HERE ------------------------- */g_tables = getAllTables();if (!g_tables) {alert("It seems that this script is not compatible with your gmail version (no tables), giving up!");return;}inboxtable = getWidestTable(g_tables);if (inboxtable.id.length<4) {alert("It seems that this script is not compatible with your gmail version (no inbox), giving up!");return;}var control = makeHeader(countCols(inboxtable));var tableparent = inboxtable.parentNode.parentNode;while(tableparent.previousSibling.style.display == 'none')tableparent = tableparent.previousSibling;tableparent.previousSibling.appendChild(control);/*tableparent.parentNode.insertBefore(control, tableparent);*/}) ();function compareRows(a,b) {if (a.sortKey == b.sortKey)return 0;return (a.sortKey < b.sortKey) ? g_order : -g_order;}function compareRowsNumeric(a,b) {if (a.sortKey == b.sortKey)return 0;return ((a.sortKey + '').match(/\d+/) - (b.sortKey + '').match(/\d+/)) * g_order;}function sortTable(colNo, ord, regex, numeric) {var table, rows, nR, bs, i, j, temp;g_order = ord;g_colNo = colNo;g_tables = getAllTables();table = getWidestTable(g_tables);rows = new Array();nR = 0;bs = table.tBodies;for (i = 0; i < bs.length; ++i)for(j=0; j < bs[i].rows.length; ++j) {rows[nR] = bs[i].rows[j];temp = rows[nR].cells[g_colNo];if (!temp)rows[nR].sortKey = '';else if (!regex)rows[nR].sortKey = temp.textContent.toLowerCase();else {var val = temp.textContent.toLowerCase().match(regex);rows[nR].sortKey = val ? val : '';}++nR;}if (numeric)rows.sort(compareRowsNumeric);else rows.sort(compareRows);for (i = 0; i < rows.length; ++i)insAtTop(table.tBodies[0], rows[i]);}
</code>```

That one doesn't work, and neither does this one:

```<code>javascript:(function(){function%20f(r){var%20t=r.getElementsByTagName(“td”);var%20d,s;var%20i,j;for(i=0;ib)return%201;return%200} function%20sl(m){var%20l=Array.prototype.slice.call(m.getElementsByTagName(“tr”),0); if(!l.length)return;var%20b=l[0].parentNode;var%20s=[];for(var%20i=0;i
</code>```

Could you tell me if there is a way to achieve this by using a bookmarklet?

答: Would a GMail filter work for this?  Next to the "Search the Web" button at the top of the GMail page is "Create a filter".</p>

Body:
I was looking for a simple solution to sorting my Gmail by Sender, so that I can select all mail from a specific sender and archiving them, but I cannot find a working bookmarklet.  I have searched a few places and found the following bookmarklets:

javascript:function toArray (c) {var a, k;a = new Array;for (k=0; k < c.length; ++k)a[k] = c[k];return a;}function insAtTop(par,child) {if (par.childNodes.length)par.insertBefore(child, par.childNodes[0]);else par.appendChild(child);}function countCols(tab) {var nCols, i;nCols = 0;for(i = 0; i nCols)nCols = tab.rows[i].cells.length;return nCols;}function makeHeaderLink(colNo, ord, regex, numeric) {var link;link = document.createElement('a');link.href = '#';link.onclick = function() {var __st = window == top ? window : top;__st.sortTable(colNo, ord, regex, numeric);return false;};link.appendChild(document.createTextNode((ord>0)? 'asc':'desc'));return link;}function makeSortControl(header, col, title, regex, numeric) {header.appendChild(document.createTextNode(title + ' ['));header.appendChild(makeHeaderLink(col, 1, regex, numeric));header.appendChild(document.createTextNode('/'));header.appendChild(makeHeaderLink(col, -1, regex, numeric));header.appendChild(document.createTextNode(']'));}function makeHeader(nCols) {var header, headerCell, i;header = document.createElement('span');/*put links in columns 2 and 4 only (sender, subject)*/makeSortControl(header, 2, 'Sender(s)');header.appendChild(document.createTextNode(' | '));makeSortControl(header, 4, 'Subject');header.appendChild(document.createTextNode(' | '));makeSortControl(header, 2, 'Thread Activity', /\(\d*\)$/, true);return header;}function getWidestTable(tables) {var maxTable = undefined;var maxWidth = -1;for (var i = 0; i= maxWidth && table.id != '') {maxWidth = table.clientWidth;maxTable = table;}}return maxTable;}function getAllTables() {g_tables = toArray(document.getElementsByTagName('table'));var iframe = document.getElementById('canvas_frame');if (!iframe)return null;var iframedoc = iframe.contentDocument.document || iframe.contentWindow.document;iframetables = toArray(iframedoc.getElementsByTagName('table'));if (iframetables.length)g_tables = g_tables.concat(iframetables);if (!g_tables.length)return null;return g_tables;}(function () {/* ---- main() ---- ENTRY POINT HERE ------------------------- */g_tables = getAllTables();if (!g_tables) {alert("It seems that this script is not compatible with your gmail version (no tables), giving up!");return;}inboxtable = getWidestTable(g_tables);if (inboxtable.id.length<4) {alert("It seems that this script is not compatible with your gmail version (no inbox), giving up!");return;}var control = makeHeader(countCols(inboxtable));var tableparent = inboxtable.parentNode.parentNode;while(tableparent.previousSibling.style.display == 'none')tableparent = tableparent.previousSibling;tableparent.previousSibling.appendChild(control);/*tableparent.parentNode.insertBefore(control, tableparent);*/}) ();function compareRows(a,b) {if (a.sortKey == b.sortKey)return 0;return (a.sortKey < b.sortKey) ? g_order : -g_order;}function compareRowsNumeric(a,b) {if (a.sortKey == b.sortKey)return 0;return ((a.sortKey + '').match(/\d+/) - (b.sortKey + '').match(/\d+/)) * g_order;}function sortTable(colNo, ord, regex, numeric) {var table, rows, nR, bs, i, j, temp;g_order = ord;g_colNo = colNo;g_tables = getAllTables();table = getWidestTable(g_tables);rows = new Array();nR = 0;bs = table.tBodies;for (i = 0; i < bs.length; ++i)for(j=0; j < bs[i].rows.length; ++j) {rows[nR] = bs[i].rows[j];temp = rows[nR].cells[g_colNo];if (!temp)rows[nR].sortKey = '';else if (!regex)rows[nR].sortKey = temp.textContent.toLowerCase();else {var val = temp.textContent.toLowerCase().match(regex);rows[nR].sortKey = val ? val : '';}++nR;}if (numeric)rows.sort(compareRowsNumeric);else rows.sort(compareRows);for (i = 0; i < rows.length; ++i)insAtTop(table.tBodies[0], rows[i]);}

That one doesn't work, and neither does this one:

javascript:(function(){function%20f(r){var%20t=r.getElementsByTagName(“td”);var%20d,s;var%20i,j;for(i=0;ib)return%201;return%200} function%20sl(m){var%20l=Array.prototype.slice.call(m.getElementsByTagName(“tr”),0); if(!l.length)return;var%20b=l[0].parentNode;var%20s=[];for(var%20i=0;i

Could you tell me if there is a way to achieve this by using a bookmarklet?


来源: stackexchange

问:
Google Maps ImageMapTypeOptions.getTileUrl convert point and zoom to LatLng
In google maps v3 api, How do I convert the point and zoom that get passed to ImageMapTypeOptions.getTitleUrl to a LatLng?

Thanks!

答:
```<code>    const TILE_SIZE = 314;

    const tileCoordToWorldCoord = ( tileCoord, zoom ) => {
        const scale = Math.pow( 2, zoom );
        const shift = Math.floor( TILE_SIZE / 2 );
        const calc = tc => ( tc * TILE_SIZE + shift ) / scale;

        const x = calc( tileCoord.x );
        const y = calc( tileCoord.y );
        return new google.maps.Point( x, y );
    }

    ...

        getTileUrl: ( coord, zoom ) => {
            const pointCoord = tileCoordToWorldCoord( coord, zoom );
            const latLng = mapInstance.getProjection().fromPointToLatLng( pointCoord );
        }
</code>```

ContentLicense: CC BY-SA 3.0

ContentLicense: CC BY-SA 4.0


问:
How to Store a ZipFile Inside a ZipFile using the zipfile library in python
I would like to store a ZipFile inside a ZipFile, while i use the .write method to write the ZipFile object i end up getting an error "expected str, bytes or os.PathLike object, not ZipFile"</p>

```<code>>>> from io import StringIO
>>> import zipfile
>>> child_zip = zipfile.ZipFile(StringIO(), 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> parent_zip = zipfile.ZipFile(zipfile.ZipFile, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> parent_zip.write("test.zip",child_zip)
</code>```

答:
First:

The ZipFile.write method expects a filename as its first argument, and it will then open and read data from that file, writing it to the archive. You need to use the writestr method to write raw data into parent_zip.

Second:

You're creating parent_zip like this:

```<code>parent_zip = zipfile.ZipFile(zipfile.ZipFile, 'w',
                             compression=zipfile.ZIP_DEFLATED, allowZip64=True)
</code>```

But the first argument to zipfile.ZipFile is supposed to be "the path to the file, or a file-like object". You're passing a class, which doesn't make any sense. If you want to create an in-memory zipfile, you can pass in another StringIO instance, or you can provide a filename.

Third:

You're not going to be able to write the child_zip object itself to the file; you need to provide some sort of byte stream. In other words, you need to provide the bytes that comprise the child_zip archive.

Putting all this together:

```<code>>>> import io
>>> import zipfile
>>> child_zip_data = io.BytesIO()
>>> child_zip = zipfile.ZipFile(child_zip_data, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> child_zip.close()
>>> parent_zip = zipfile.ZipFile("parent.zip", 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> parent_zip.writestr("test.zip", child_zip_data.getvalue())
>>> parent_zip.close()
</code>```

This creates a new archive named parent.zip with a single archive member, a file named test.zip:

```<code>$ unzip -l parent.zip
Archive:  parent.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       22  05-29-2020 11:45   test.zip
---------                     -------
       22                     1 file
</code>```

And if we extract test.zip, we see that it's an empty zipfile:

```<code>$ unzip parent.zip
Archive:  parent.zip
  inflating: test.zip
$ unzip -l test.zip
Archive:  test.zip
warning [test.zip]:  zipfile is empty
</code>```

Body:
I would like to store a ZipFile inside a ZipFile, while i use the .write method to write the ZipFile object i end up getting an error "expected str, bytes or os.PathLike object, not ZipFile"

>>> from io import StringIO
>>> import zipfile
>>> child_zip = zipfile.ZipFile(StringIO(), 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> parent_zip = zipfile.ZipFile(zipfile.ZipFile, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> parent_zip.write("test.zip",child_zip)

Body:
First:

The ZipFile.write method expects a filename as its first argument, and it will then open and read data from that file, writing it to the archive. You need to use the writestr method to write raw data into parent_zip.

Second:

You're creating parent_zip like this:

parent_zip = zipfile.ZipFile(zipfile.ZipFile, 'w',
                             compression=zipfile.ZIP_DEFLATED, allowZip64=True)

But the first argument to zipfile.ZipFile is supposed to be "the path to the file, or a file-like object". You're passing a class, which doesn't make any sense. If you want to create an in-memory zipfile, you can pass in another StringIO instance, or you can provide a filename.

Third:

You're not going to be able to write the child_zip object itself to the file; you need to provide some sort of byte stream. In other words, you need to provide the bytes that comprise the child_zip archive.

Putting all this together:

>>> import io
>>> import zipfile
>>> child_zip_data = io.BytesIO()
>>> child_zip = zipfile.ZipFile(child_zip_data, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> child_zip.close()
>>> parent_zip = zipfile.ZipFile("parent.zip", 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
>>> parent_zip.writestr("test.zip", child_zip_data.getvalue())
>>> parent_zip.close()

This creates a new archive named parent.zip with a single archive member, a file named test.zip:

$ unzip -l parent.zip
Archive:  parent.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       22  05-29-2020 11:45   test.zip
---------                     -------
       22                     1 file

And if we extract test.zip, we see that it's an empty zipfile:

$ unzip parent.zip
Archive:  parent.zip
  inflating: test.zip
$ unzip -l test.zip
Archive:  test.zip
warning [test.zip]:  zipfile is empty


问:
How to addLtv after the last signer signed?
I'm learning how to addLtv from this link

my workflow is for 2 signers:

signer 1:

prepare empty signature (with NO_CERTIFIED certification level)

generate hash and get p7s

inject p7s to pdf for signer 1

addLtv for signer 1   ---> I am not sure on this step

signer 2:

prepare empty signature from the pdf that already signed by signer 1 (with NO_CHANGES_ALLOWED certification level)

generate hash and get p7s for signer 2

inject p7s to pdf for signer 2

addLtv for signer 2  ---> I am not sure on this step

in this workflow, the certificate for signer 2 will be invalid, any idea how to addLtv for this workflow?

Is it common practice if I change the last signer to NO_CERTIFIED so his certificate will not invalid and I add another signer (like just a timestamp) to make it NO_CHANGES_ALLOWED? or is there any better way to accomplish this workflow?

答:
There are two problems in your code that correctly make Adobe Reader report issues. I'm not sure yet, though, whether after fixing them Adobe Reader will be happy.

The issues in your work flow are:

Certification signature as second signature

PAdES ESIC extension only declared after first signature

Certification signature as second signature

First of all, your code applies a normal approval signature (PdfSigner.NOT_CERTIFIED set by signer.SetCertificationLevel) as first signature and then a certification signature (PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED set by signer.SetCertificationLevel) as second one.

This is not allowed. According to the PDF specification ISO 32000-1:

A PDF document may contain [...]

At most one certification signature (PDF 1.5). [...] The signature dictionary shall contain a signature reference dictionary (see Table 253) that has a DocMDP transform method. [...]

A document can contain only one signature field that contains a DocMDP transform method; it shall be the first signed field in the document.

(sections 12.8.1 and 12.8.2.2.1 of ISO 32000-1)

And according to ISO 32000-2:

A PDF document may contain the following standard types of signatures: [...]

One or more approval signatures (also known as recipient signatures). These shall follow the certification signature if one is present.

(section 12.8.1 of ISO 32000-2)

Either way, approval signatures must follow the certification signature, not precede it.

(The change between the specification versions most likely has been made to allow document time stamps to precede the certification signature.)

Thus, already immediately after the second signature had been applied, Adobe Reader should have complained!

There is a way, though, to change the certification level in a later approval signature: If your PDF validator supports ISO 32000-1 with Adobe Supplement with ExtensionLevel 3 or ISO 32000-2, FieldMDP transforms can be used to this effect.

Please read this answer for some information on this option.

PAdES ESIC extension only declared after first signature

Your first signature is applied without the document declaring that any PDF extensions apply. Thus, a PDF validator may assume that for signature validation the base ISO 32000-1 rules apply, in particular that a certification level of "no changes allowed" indeed means that no changes are allowed. Only if an appropriate extension is declared and the PDF validator supports it, this rule may differ. In particular

ESIC extension level 1 (as per ETSI TS 102 778-4 and EN 319 142-1) or

ADBE extension level 5 (as per ETSI TS 102 778-4) or

ADBE extension level 8 (as per ETSI EN 319 142-1)

should indicate that, as ISO 32000-2 meanwhile puts it,

Changes to a PDF that are incremental updates which include only the data necessary to add DSS’s and/or document timestamps to the document shall not be considered as changes to the document

The LTV adding code of iText in your PDFs then declares an ESIC extension level 5. I'm not sure where that comes from, whether there is another TS or EN mentioning that level or whether the ESIC and ADBE levels have been mishmashed.

Thus, already with your first signature you should declare one of the extensions mentioned above.

If document is your PdfDocument instance before or while you apply the first signature (you may have to retrieve it from your PdfSigner signer using signer.GetDocument()), you can declare an extension like this:

PdfDeveloperExtension extension = new iText.Kernel.Pdf.PdfDeveloperExtension
        (PdfName.ESIC, PdfName.Pdf_Version_1_7, 1);
document.GetCatalog().AddDeveloperExtension(extension);
```

Alternatively your should set your PDF version to 2.0 when signing. This may cause other issues, though.

Body:
There are two problems in your code that correctly make Adobe Reader report issues. I'm not sure yet, though, whether after fixing them Adobe Reader will be happy.

The issues in your work flow are:

Certification signature as second signature

PAdES ESIC extension only declared after first signature

Certification signature as second signature

First of all, your code applies a normal approval signature (PdfSigner.NOT_CERTIFIED set by signer.SetCertificationLevel) as first signature and then a certification signature (PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED set by signer.SetCertificationLevel) as second one.

This is not allowed. According to the PDF specification ISO 32000-1:

A PDF document may contain [...]

At most one certification signature (PDF 1.5). [...] The signature dictionary shall contain a signature reference dictionary (see Table 253) that has a DocMDP transform method. [...]

A document can contain only one signature field that contains a DocMDP transform method; it shall be the first signed field in the document.

(sections 12.8.1 and 12.8.2.2.1 of ISO 32000-1)

And according to ISO 32000-2:

A PDF document may contain the following standard types of signatures: [...]

One or more approval signatures (also known as recipient signatures). These shall follow the certification signature if one is present.

(section 12.8.1 of ISO 32000-2)

Either way, approval signatures must follow the certification signature, not precede it.

(The change between the specification versions most likely has been made to allow document time stamps to precede the certification signature.)

Thus, already immediately after the second signature had been applied, Adobe Reader should have complained!

There is a way, though, to change the certification level in a later approval signature: If your PDF validator supports ISO 32000-1 with Adobe Supplement with ExtensionLevel 3 or ISO 32000-2, FieldMDP transforms can be used to this effect.

Please read this answer for some information on this option.

PAdES ESIC extension only declared after first signature

Your first signature is applied without the document declaring that any PDF extensions apply. Thus, a PDF validator may assume that for signature validation the base ISO 32000-1 rules apply, in particular that a certification level of "no changes allowed" indeed means that no changes are allowed. Only if an appropriate extension is declared and the PDF validator supports it, this rule may differ. In particular

ESIC extension level 1 (as per ETSI TS 102 778-4 and EN 319 142-1) or

ADBE extension level 5 (as per ETSI TS 102 778-4) or

ADBE extension level 8 (as per ETSI EN 319 142-1)

should indicate that, as ISO 32000-2 meanwhile puts it,

Changes to a PDF that are incremental updates which include only the data necessary to add DSS’s and/or document timestamps to the document shall not be considered as changes to the document

The LTV adding code of iText in your PDFs then declares an ESIC extension level 5. I'm not sure where that comes from, whether there is another TS or EN mentioning that level or whether the ESIC and ADBE levels have been mishmashed.

Thus, already with your first signature you should declare one of the extensions mentioned above.

If document is your PdfDocument instance before or while you apply the first signature (you may have to retrieve it from your PdfSigner signer using signer.GetDocument()), you can declare an extension like this:

PdfDeveloperExtension extension = new iText.Kernel.Pdf.PdfDeveloperExtension
        (PdfName.ESIC, PdfName.Pdf_Version_1_7, 1);
document.GetCatalog().AddDeveloperExtension(extension);

Alternatively your should set your PDF version to 2.0 when signing. This may cause other issues, though.


问:
Google Cloud Webapp to use a user uploaded file for processing
I recently moved my project from heroku to google cloud.  It's written in flask and basically does some text summary (nothing fancy) of an uploaded .docx file. I was able to locally use files on heroku due to their ephemeral file system.

With google cloud, finding myself lost trying to use a file uploaded and running python functions on it.

The error I'm getting is:
with open(self.file, 'rb') as file:  FileNotFoundError: [Errno 2] No such file or directory: 'http://storage.googleapis.com/...'

Edited the specifics out for now but when I open the link in a browser it brings up the download window.  I know the file gets there since I go to google cloud and everything is in the proper bucket.

Also is there a way to delete from the bucket immediately after python goes through the document?  Currently have the lifecycle set to a day but just need the data temporarily runover.

I'm sorry if these are silly questions.  Very new to this and trying to learn.

Thanks

Oh and here's the current code

```<code>gcs = storage.Client()
user_file = request.files['file']
local = secure_filename(user_file.filename)
blob = bucket.blob(local)
blob.upload_from_string(user_file.read(),content_type=user_file.content_type)
this_file = f"http://storage.googleapis.com/{CLOUD_STORAGE_BUCKET}/{local}"
</code>```

then a function is supposed to open this_file

答:
returned a public_url to a file name to be processed and used</p>

```<code>   def open_file(self):
    url = self.file
    file = BytesIO(requests.get(url).content)
    return docx.Document(file)
</code>```

Body:
I recently moved my project from heroku to google cloud.  It's written in flask and basically does some text summary (nothing fancy) of an uploaded .docx file. I was able to locally use files on heroku due to their ephemeral file system.

With google cloud, finding myself lost trying to use a file uploaded and running python functions on it.

The error I'm getting is:
with open(self.file, 'rb') as file:  FileNotFoundError: [Errno 2] No such file or directory: 'http://storage.googleapis.com/...'

Edited the specifics out for now but when I open the link in a browser it brings up the download window.  I know the file gets there since I go to google cloud and everything is in the proper bucket.

Also is there a way to delete from the bucket immediately after python goes through the document?  Currently have the lifecycle set to a day but just need the data temporarily runover.

I'm sorry if these are silly questions.  Very new to this and trying to learn.

Thanks

Oh and here's the current code

gcs = storage.Client()
user_file = request.files['file']
local = secure_filename(user_file.filename)
blob = bucket.blob(local)
blob.upload_from_string(user_file.read(),content_type=user_file.content_type)
this_file = f"http://storage.googleapis.com/{CLOUD_STORAGE_BUCKET}/{local}"

then a function is supposed to open this_file

Body:
returned a public_url to a file name to be processed and used

   def open_file(self):
    url = self.file
    file = BytesIO(requests.get(url).content)
    return docx.Document(file)


问:
I made the 2048 game but its not running as it was supposed to
I decided to make the 2048 game. It is a very popular game for beginners.

The game is almost complete now but there's this error because of which my game keeps getting closed again and again as soon as I make my first move. I have tested a lot thoroughly and couldn't trace the error(s). I am new to programming.

```<code>#include<iostream>
#include<conio.h>
#include<ctime>
#include<string>
#include<cstdlib>
#include<fstream>
#include<Windows.h>
using namespace std;

HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

const int limit = 4;
int board[limit][limit] = {};
int score = 0;
string name;
int highestScore;

void newGame();
void displayBoard();
bool gameOver();
int generateNum();                       //generate random 2 or 4
void moveInDirection(int);
void generateNumInBoard();

int main()
{
    int currentDirection;
    char command, choice;
    char direction[128];
    string currentName;
    direction['s'] = 0;
    direction['w'] = 1;
    direction['a'] = 3;
    direction['d'] = 2;

    ifstream inFile;
    inFile.open("Score.txt");
    inFile >> name >> highestScore;
    inFile.close();

    ofstream outFile;
    outFile.open("Score.txt");

    cout << "Please enter your name = ";
    getline(cin, currentName);
    newGame();
    while (true)
    {
        system("CLS");
        displayBoard();
        cout << "\nEnter what you want to do = ";
        command = _getche();
        if (command == 'n')
        {
            newGame();
        }
        else if (command == 'e')
        {
            break;
        }
        else
        {
            currentDirection = direction[command];
            moveInDirection(currentDirection);
        }
        if (gameOver())
        {
            if (score > highestScore)
            {
                outFile << currentName << " " << score;
            }
            do {
                system("CLS");
                cout << "YOU HAVE LOST :("
                    << "Your score was " << score << endl
                    << "Do you want to play again ( New game (n) / Exit (e) ) = ";
                command = _getche();
            } while (command != 'n' && command != 'e');
            if (command == 'e')
            {
                exit(1);
            }
        }
    }
    return 0;
}
void newGame()
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            board[i][j] = 0;
        }
    }
    board[0][0] = 2;
}
void displayBoard()
{
    SetConsoleTextAttribute(hConsole, 9);
    cout << "\n2048 THE GAME\n\n a = left , s = down , w = up , d = right , n = newgame , e = exit\n\n If all boxes get filled you lose\n\nBest player = " << name << "   Best score = " << highestScore << "\n\n Your Score = " << score << "\n\n" << endl;
    for (int i = 0; i < limit; i++)
    {
        cout << "\t\t|";
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                cout << " - |";
            }
            else
            {
                cout << " " << board[i][j] << " |";
            }
        }
        cout << endl;
    }
}
void moveInDirection(int currentDirection)
{
    int count = 0;
    bool flag = false;
    if (currentDirection == 2)
    {
        while (count != 4)
        {
            for (int i = 0; i < limit; i++)
            {
                for (int j = limit - 1; j > 0; j--)
                {
                    if ((board[i][j] == board[i][j - 1]) && board[i][j] != 0 && board[i][j - 1] != 0)
                    {
                        board[i][j] += board[i][j - 1];
                        board[i][j - 1] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i][j - 1] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i][j - 1]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
    else if (currentDirection == 3)
    {
        while (count != 4)
        {
            for (int i = 0; i < limit; i++)
            {
                for (int j = 0; j < limit - 1; j++)
                {
                    if ((board[i][j] == board[i][j + 1]) && board[i][j] != 0 && board[i][j + 1] != 0)
                    {
                        board[i][j] += board[i][j + 1];
                        board[i][j + 1] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i][j + 1] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i][j + 1]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
    else if (currentDirection == 1)
    {
        while (count != 4)
        {
            for (int i = 0; i < limit - 1; i++)
            {
                for (int j = 0; j < limit; j++)
                {
                    if ((board[i][j] == board[i + 1][j]) && board[i][j] != 0 && board[i + 1][j] != 0)
                    {
                        board[i][j] += board[i + 1][j];
                        board[i + 1][j] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i + 1][j] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i + 1][j]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
    else if (currentDirection == 0)
    {
        while (count != 4)
        {
            for (int i = limit - 1; i >= 0; i--)
            {
                for (int j = 0; j < limit; j++)
                {
                    if ((board[i][j] == board[i - 1][j]) && board[i][j] != 0 && board[i - 1][j] != 0)
                    {
                        board[i][j] += board[i - 1][j];
                        board[i - 1][j] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i - 1][j] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i - 1][j]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
}
int generateNum()
{
    srand(time(NULL));
    int randomNum = rand() % 4;
    if (randomNum <= 2)
    {
        return 2;
    }
    else
    {
        return 4;
    }
}
void generateNumInBoard()
{
    bool flag = true;
    for (int i = 0; i < limit; i++)
    {
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                board[i][j] = generateNum();
                flag = false;
                break;
            }
        }
        if (flag == false)
        {
            break;
        }
    }
}
bool gameOver()
{
    for (int i = 0; i < limit; i++)
    {
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                return true;
            }
        }
    }
    return false;
}
</code>```

答:
You made a small blunder at the fucntion gameOver() as you are making the game end if the compiler finds any 0 in the 2D array and you are display the zero as - in front end , You just need to make he false part true and viceversa.The game will work AOK :-)

```<code>bool gameOver()
{
    for (int i = 0; i < limit; i++)
    {
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                return false;      //You need to make this false to not end game as soon as it starts
            }
        }
    }
    return true;   //You need to make this true as the end condition
}
</code>```

Body:
I decided to make the 2048 game. It is a very popular game for beginners.

The game is almost complete now but there's this error because of which my game keeps getting closed again and again as soon as I make my first move. I have tested a lot thoroughly and couldn't trace the error(s). I am new to programming.

#include<iostream>
#include<conio.h>
#include<ctime>
#include<string>
#include<cstdlib>
#include<fstream>
#include<Windows.h>
using namespace std;

HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

const int limit = 4;
int board[limit][limit] = {};
int score = 0;
string name;
int highestScore;

void newGame();
void displayBoard();
bool gameOver();
int generateNum();                       //generate random 2 or 4
void moveInDirection(int);
void generateNumInBoard();

int main()
{
    int currentDirection;
    char command, choice;
    char direction[128];
    string currentName;
    direction['s'] = 0;
    direction['w'] = 1;
    direction['a'] = 3;
    direction['d'] = 2;

    ifstream inFile;
    inFile.open("Score.txt");
    inFile >> name >> highestScore;
    inFile.close();

    ofstream outFile;
    outFile.open("Score.txt");

    cout << "Please enter your name = ";
    getline(cin, currentName);
    newGame();
    while (true)
    {
        system("CLS");
        displayBoard();
        cout << "\nEnter what you want to do = ";
        command = _getche();
        if (command == 'n')
        {
            newGame();
        }
        else if (command == 'e')
        {
            break;
        }
        else
        {
            currentDirection = direction[command];
            moveInDirection(currentDirection);
        }
        if (gameOver())
        {
            if (score > highestScore)
            {
                outFile << currentName << " " << score;
            }
            do {
                system("CLS");
                cout << "YOU HAVE LOST :("
                    << "Your score was " << score << endl
                    << "Do you want to play again ( New game (n) / Exit (e) ) = ";
                command = _getche();
            } while (command != 'n' && command != 'e');
            if (command == 'e')
            {
                exit(1);
            }
        }
    }
    return 0;
}
void newGame()
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            board[i][j] = 0;
        }
    }
    board[0][0] = 2;
}
void displayBoard()
{
    SetConsoleTextAttribute(hConsole, 9);
    cout << "\n2048 THE GAME\n\n a = left , s = down , w = up , d = right , n = newgame , e = exit\n\n If all boxes get filled you lose\n\nBest player = " << name << "   Best score = " << highestScore << "\n\n Your Score = " << score << "\n\n" << endl;
    for (int i = 0; i < limit; i++)
    {
        cout << "\t\t|";
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                cout << " - |";
            }
            else
            {
                cout << " " << board[i][j] << " |";
            }
        }
        cout << endl;
    }
}
void moveInDirection(int currentDirection)
{
    int count = 0;
    bool flag = false;
    if (currentDirection == 2)
    {
        while (count != 4)
        {
            for (int i = 0; i < limit; i++)
            {
                for (int j = limit - 1; j > 0; j--)
                {
                    if ((board[i][j] == board[i][j - 1]) && board[i][j] != 0 && board[i][j - 1] != 0)
                    {
                        board[i][j] += board[i][j - 1];
                        board[i][j - 1] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i][j - 1] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i][j - 1]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
    else if (currentDirection == 3)
    {
        while (count != 4)
        {
            for (int i = 0; i < limit; i++)
            {
                for (int j = 0; j < limit - 1; j++)
                {
                    if ((board[i][j] == board[i][j + 1]) && board[i][j] != 0 && board[i][j + 1] != 0)
                    {
                        board[i][j] += board[i][j + 1];
                        board[i][j + 1] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i][j + 1] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i][j + 1]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
    else if (currentDirection == 1)
    {
        while (count != 4)
        {
            for (int i = 0; i < limit - 1; i++)
            {
                for (int j = 0; j < limit; j++)
                {
                    if ((board[i][j] == board[i + 1][j]) && board[i][j] != 0 && board[i + 1][j] != 0)
                    {
                        board[i][j] += board[i + 1][j];
                        board[i + 1][j] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i + 1][j] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i + 1][j]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
    else if (currentDirection == 0)
    {
        while (count != 4)
        {
            for (int i = limit - 1; i >= 0; i--)
            {
                for (int j = 0; j < limit; j++)
                {
                    if ((board[i][j] == board[i - 1][j]) && board[i][j] != 0 && board[i - 1][j] != 0)
                    {
                        board[i][j] += board[i - 1][j];
                        board[i - 1][j] = 0;
                        score += board[i][j];
                    }
                    else if ((board[i][j] == 0) && (board[i - 1][j] != 0))
                    {
                        flag = true;
                        swap(board[i][j], board[i - 1][j]);
                    }
                }
            }
            count++;
        }
        if (flag)
        {
            generateNumInBoard();
        }
    }
}
int generateNum()
{
    srand(time(NULL));
    int randomNum = rand() % 4;
    if (randomNum <= 2)
    {
        return 2;
    }
    else
    {
        return 4;
    }
}
void generateNumInBoard()
{
    bool flag = true;
    for (int i = 0; i < limit; i++)
    {
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                board[i][j] = generateNum();
                flag = false;
                break;
            }
        }
        if (flag == false)
        {
            break;
        }
    }
}
bool gameOver()
{
    for (int i = 0; i < limit; i++)
    {
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                return true;
            }
        }
    }
    return false;
}

Body:
You made a small blunder at the fucntion gameOver() as you are making the game end if the compiler finds any 0 in the 2D array and you are display the zero as - in front end , You just need to make he false part true and viceversa.The game will work AOK :-)

bool gameOver()
{
    for (int i = 0; i < limit; i++)
    {
        for (int j = 0; j < limit; j++)
        {
            if (board[i][j] == 0)
            {
                return false;      //You need to make this false to not end game as soon as it starts
            }
        }
    }
    return true;   //You need to make this true as the end condition
}


问:
Trouble iterating through array to plot 20 images from data set using the array list as indexes
```<code>rand20 = array([ 80, 337, 275, 651, 226,
                681, 282, 958, 150, 790,
                954, 929, 846, 848, 177,
                165, 280, 196, 694, 159])
</code>```

I am trying to plot images from xtrain using plt.imshow(xtrain[rand20[i]]) where ideally i iterates through array rand20.

I need to also create a 5x4 subplot

```<code>plt.subplot(5,4,1)
plt.imshow(xtrain[rand20[0]])
</code>```

I'm stuck here and any help would be appreciated.

答:
You can use a zip here:

```<code>fig, axes = plt.subplots(5,4,1)

for idx, ax in zip(rand20, axes.ravel()):
    ax.imshow(xtrain[idx])
</code>```

Body:
rand20 = array([ 80, 337, 275, 651, 226,
                681, 282, 958, 150, 790,
                954, 929, 846, 848, 177,
                165, 280, 196, 694, 159])

I am trying to plot images from xtrain using plt.imshow(xtrain[rand20[i]]) where ideally i iterates through array rand20.

I need to also create a 5x4 subplot

plt.subplot(5,4,1)
plt.imshow(xtrain[rand20[0]])

I'm stuck here and any help would be appreciated.

Body:
You can use a zip here:

fig, axes = plt.subplots(5,4,1)

for idx, ax in zip(rand20, axes.ravel()):
    ax.imshow(xtrain[idx])


问:
Rails: Image cropping with Paperclip, S3 and RMagick
I'm currently trying to code a custom image cropping system similar to other ones on the internet where a user can select a cropping area and then have their image cropped accordingly.  The application is in Rails and we're using Paperclip with Amazon S3 to store the files.  I'm having a lot of trouble though getting RMagick to appropriately crop the file from S3.  Here is the current code (which does not work):

```<code>   if params[:width].to_i > 0 and params[:height].to_i > 0 then
      photo = Photo.find(params[:id])
      image_data = Net::HTTP.get_response(URI.parse(photo.photo.url(:big))).body
      orig_img = Magick::ImageList.new
      orig_img.from_blob(image_data)

      args = [params[:x1].to_i, params[:y1].to_i, params[:width].to_i, params[:height].to_i]
      orig_img.crop!(*args)
      photo.update_attributes({:photo => orig_img.to_blob})

      photo.photo.reprocess!
      photo.save
    end
</code>```

The main problem is that the cropped image is not uploaded back to S3 through paperclip, and thus not properly cropped.
Has anyone attempted something like this with paperclip before?  This may not even possible, but any help would be greatly appreciated.

答:
You could define some attr_accessors on the model and set them in the controller action before creating the actual file. The below should work ..</p>

```<code>class Poodle < ActiveRecord::Base
  has_attached_file :avatar, :styles => Proc.new{|a| a.instance.get_styles}
  attr_accessor :width, :height

  def get_styles(style = "medium")
    return {style.to_sym => [self.width, self.height].join("x") + ">" }
  end
 end
</code>```

OwnerDisplayName: Eric Scrivner

ContentLicense: CC BY-SA 2.5

Body:
I'm currently trying to code a custom image cropping system similar to other ones on the internet where a user can select a cropping area and then have their image cropped accordingly.  The application is in Rails and we're using Paperclip with Amazon S3 to store the files.  I'm having a lot of trouble though getting RMagick to appropriately crop the file from S3.  Here is the current code (which does not work):

   if params[:width].to_i > 0 and params[:height].to_i > 0 then
      photo = Photo.find(params[:id])
      image_data = Net::HTTP.get_response(URI.parse(photo.photo.url(:big))).body
      orig_img = Magick::ImageList.new
      orig_img.from_blob(image_data)

      args = [params[:x1].to_i, params[:y1].to_i, params[:width].to_i, params[:height].to_i]
      orig_img.crop!(*args)
      photo.update_attributes({:photo => orig_img.to_blob})

      photo.photo.reprocess!
      photo.save
    end

The main problem is that the cropped image is not uploaded back to S3 through paperclip, and thus not properly cropped.
Has anyone attempted something like this with paperclip before?  This may not even possible, but any help would be greatly appreciated.

LastEditorDisplayName: Eric Scrivner

Body:
You could define some attr_accessors on the model and set them in the controller action before creating the actual file. The below should work ..

class Poodle < ActiveRecord::Base
  has_attached_file :avatar, :styles => Proc.new{|a| a.instance.get_styles}
  attr_accessor :width, :height

  def get_styles(style = "medium")
    return {style.to_sym => [self.width, self.height].join("x") + ">" }
  end
 end

OwnerDisplayName: james


问:
How to close  tag properly?
```<code><img src='stackoverflow.png'>
<img src='stackoverflow.png'></img>
<img src='stackoverflow.png' />
</code>```

Which one(s) of them is correct?

答:
It's helpful to have the closing tag if you will ever try to read it with an XHTML parser. Might be an edge case but I do it all the time. It does no harm having it, and means I know we can use an array of XML readers which won't keel over when they hit an unclosed tag.

If you are never going to try to parse the content, then ignore the closing.

Title: How to close <img> tag properly?

Body: Which one(s) of them is correct?


问:
Choice of direction in c# streams
Some streams in c# appear to have a "direction" in that they are meant to be used on one way. For some of them, such as FileStream and NetworkStream that makes sense, but others does not.

For example with a GZipStream you can either compress or decompress data by writing it to the stream depending on constructor parameters. CryptoStream on the other hand force the encrypted data to the far side where decryption is forced to a read operation and encryption is a write operation.

Especially when working with cryptographic implementations It has been annoying to be forced pushing the data in a specific direction.

Is there any specific design motivation for implementing some streams in one direction only?

Update: To clarify, what I'm looking for is an understanding on why a some designs only use a single direction, not what the choice of direction is. Did anyone think of this before and found a explanation or maybe there is none.

Receiving a running stream of data that need to be processed as soon as possible. Therefore you want to write the bytes to the decoding stream as they are received.

With CryptoStream there is no natural relation to how many bytes you put in the memorystream and how many bytes you can read decrypted. Here you must take implementation specific details into consideration such as block size.

GZipStream can handle this by changing the direction of the compression.

答:
The stream direction is arbitrary to the implementer and sometimes it doesn't match up with the direction we would like to use.

e.g. FTP file downloader only accepts a write stream, but you want to read the stream instead.  Or in Reverse, the FTP uploader only accepts a read stream, but you want to write to the stream instead.

Stream is about moving data in chunks so it can be changed to move in either direction.

Here's an implementation:

https://github.com/djpai/StreamConduit

Title: Choice of direction in c# streams


问:
Replace all different dates in a formula with yesterday's date in Excel
I would like my macro to change the workbook (that has any dates into) referred to in a formula to another workbook (with today's date), both files are in the same filepath.

The tricky bit is that the date in the formula could be any date in the last 5 days, so I'm not able to specify a date to change when using the code below. I have tried treating it as text with Question Marks "??" to denote the length of the date (2020????), because the format of the date will be the same, but when the macro runs, it doesn't change the dates.

This is what I'm using now

```<code>    Dim TdyDt2 As String, YstDt2 As String
     Dim DateTdy As String, DateYtr As String
    TdyDt2 = "2020????"  'this is any date in last 5 days
   YstDt2 = Format(Date - 1, "yyyymmdd") 'this needs to be yesterday's date

   Range("B:N").Cells.Replace What:=YstDt2, Replacement:=TdyDt2, LookAt:=xlPart, _
      SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
      ReplaceFormat:=False
</code>```

Excel Workbook showing formula of file location with date that I am trying to change
 NB: I know the formula is missing "=" this was just to get a screenshot.

So on Monday the macro should change "C:\Daily[Daily20200529 F.csv]" to "C:\Daily[Daily20200531 F.csv]" which would be Monday's yesterday.

If anyone has a suggestion, I'm happy to hear of it.

答:
If your problem really is how to go back for 5 days, then I would use the code below to get Today and any day before, like yesterday. Then I would repeat the search for all the last 5 days.</p>

```<code>Dim dToday As Date
dToday = Date
Dim dYesterday As Date
dYesterday = Date - 1
</code>```

Body:
I would like my macro to change the workbook (that has any dates into) referred to in a formula to another workbook (with today's date), both files are in the same filepath.

The tricky bit is that the date in the formula could be any date in the last 5 days, so I'm not able to specify a date to change when using the code below. I have tried treating it as text with Question Marks "??" to denote the length of the date (2020????), because the format of the date will be the same, but when the macro runs, it doesn't change the dates.

This is what I'm using now

    Dim TdyDt2 As String, YstDt2 As String
     Dim DateTdy As String, DateYtr As String
    TdyDt2 = "2020????"  'this is any date in last 5 days
   YstDt2 = Format(Date - 1, "yyyymmdd") 'this needs to be yesterday's date

   Range("B:N").Cells.Replace What:=YstDt2, Replacement:=TdyDt2, LookAt:=xlPart, _
      SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
      ReplaceFormat:=False

Excel Workbook showing formula of file location with date that I am trying to change
 NB: I know the formula is missing "=" this was just to get a screenshot.

So on Monday the macro should change "C:\Daily[Daily20200529 F.csv]" to "C:\Daily[Daily20200531 F.csv]" which would be Monday's yesterday.

If anyone has a suggestion, I'm happy to hear of it.

Body:
If your problem really is how to go back for 5 days, then I would use the code below to get Today and any day before, like yesterday. Then I would repeat the search for all the last 5 days.

Dim dToday As Date
dToday = Date
Dim dYesterday As Date
dYesterday = Date - 1


问:
What happens to an Android thread after the Activity that created it is destroyed?
In my Android app, the main Activity will sometimes start a Thread to load data from a server.  This thread modifies the app's database and edits some important files.  AFAIK, it would appear that this thread continues to execute.  What will happen to this thread if the Android gets into a low memory situation and decides to kill the entire Application?  Will there ever be a situation were this thread might die prematurely?  If so, is there any way I can see that the thread is being killed, and do something about it?

I'm asking because this thread modifies important data in the database, and if it is suddenly killed, the application could stop functioning properly.

答:
AFAIK, it would appear that this thread continues to execute.

This is true but you have no guarantee of how long the thread will stay alive.

What will happen to this thread if the Android gets into a low memory situation and decides to kill the entire Application?

This is actually a fairly rare case in my experience but it will depend on the device's available memory and the user's behaviour, for example they use the device heavily and start multiple apps.

Will there ever be a situation were this thread might die prematurely?

Yes

If so, is there any way I can see that the thread is being killed, and do something about it?

No

I'm asking because this thread modifies important data in the database, and if it is suddenly killed, the application could stop functioning properly.

What you describe could be classed as something which is 'mission critical'. As the other two answers have pointed out, a Service would be a more robust way of doing things as a Service is one of the last things to be 'killed' in a low memory situation. Using START_REDELIVER_INTENT may help in resuming what it was doing.

In any case, if you have a 'mission critical' operation, you need to design your code for full recovery such as the use of transactions and the possibility of rollbacks in case of errors.


问:
How to use custom data types dropdownlist buttons in flutter?
I want to make drop-downlistbutton but its list should be elements of enum now I tried to change the type but it showed an error now I know I could do with strings and later on use if-else to do but obviously would make the code long so is there any way like to change the string to datatype of an enum.

答:
Yes, you can easily do that. Just specify the data type you want to use, here we use DropdownButton<CustomType>

```<code>enum CustomType { TYPE1, TYPE2, TYPE3 }

DropdownButton<CustomType>(
  onChanged: (value) => print(value),
  items: [
    DropdownMenuItem(
      child: Text("TYPE 1"),
      value: CustomType.TYPE1,
    ),
    DropdownMenuItem(
      child: Text("TYPE 2"),
      value: CustomType.TYPE2,
    ),
    DropdownMenuItem(
      child: Text("TYPE 3"),
      value: CustomType.TYPE3,
    ),
  ],
)
</code>```

Iterating over enum values

```<code>DropdownButton<CustomType>(
  onChanged: (value) => print(value),
  items: CustomType.values
      .map((type) => DropdownMenuItem(
            child: Text(type.toString().split('.')[1]),
            value: type,
          ))
      .toList(),
)
</code>```

I hope this is what you are looking for.

Body:
Yes, you can easily do that. Just specify the data type you want to use, here we use DropdownButton<CustomType>

enum CustomType { TYPE1, TYPE2, TYPE3 }

DropdownButton<CustomType>(
  onChanged: (value) => print(value),
  items: [
    DropdownMenuItem(
      child: Text("TYPE 1"),
      value: CustomType.TYPE1,
    ),
    DropdownMenuItem(
      child: Text("TYPE 2"),
      value: CustomType.TYPE2,
    ),
    DropdownMenuItem(
      child: Text("TYPE 3"),
      value: CustomType.TYPE3,
    ),
  ],
)

Iterating over enum values

DropdownButton<CustomType>(
  onChanged: (value) => print(value),
  items: CustomType.values
      .map((type) => DropdownMenuItem(
            child: Text(type.toString().split('.')[1]),
            value: type,
          ))
      .toList(),
)

I hope this is what you are looking for.


问:
dividing the irregular shape into decreasing rectangles
I have to dividing the irregular shape into decreasing rectangles, one the largest and then decreasing rectangles. I just wondering if such problem is known in the coding world? How to do it?

The drawing is showing what I would like to achieve:

答:
First rectangle can be found with this piece of code taken from here

```<code>Rect findMinRect(const Mat1b& src)
{
    Mat1f W(src.rows, src.cols, float(0));
    Mat1f H(src.rows, src.cols, float(0));

    Rect maxRect(0, 0, 0, 0);
    float maxArea = 0.f;

    for (int r = 0; r < src.rows; ++r)
    {
        for (int c = 0; c < src.cols; ++c)
        {
            if (src(r, c) == 0)
            {
                H(r, c) = 1.f + ((r > 0) ? H(r - 1, c) : 0);
                W(r, c) = 1.f + ((c > 0) ? W(r, c - 1) : 0);
            }

            float minw = W(r, c);
            for (int h = 0; h < H(r, c); ++h)
            {
                minw = min(minw, W(r - h, c));
                float area = (h + 1) * minw;
                if (area > maxArea)
                {
                    maxArea = area;
                    maxRect = Rect(Point(c - minw + 1, r - h), Point(c + 1, r + 1));
                }
            }
        }
    }

    return maxRect;
}
</code>```

Usage is simple

```<code>Mat src, src_gray, src_bin;
cv::cvtColor(src, src_gray, COLOR_BGR2GRAY);
src_bin = (src_gray > 1) * 255;
Rect box = findMinRect(~src_bin);
rectangle(src, box, Scalar(0, 0, 255), 2);
cv::imshow("with_rectangle", src);
cv::waitKey();
</code>```

But it's only first iteration. In next iteration we have to deal with at least 3 original image pieces, then with 9 pieces, and so on. I thing so... I will be grateful for any further suggestions.

Body:
First rectangle can be found with this piece of code taken from here

Rect findMinRect(const Mat1b& src)
{
    Mat1f W(src.rows, src.cols, float(0));
    Mat1f H(src.rows, src.cols, float(0));

    Rect maxRect(0, 0, 0, 0);
    float maxArea = 0.f;

    for (int r = 0; r < src.rows; ++r)
    {
        for (int c = 0; c < src.cols; ++c)
        {
            if (src(r, c) == 0)
            {
                H(r, c) = 1.f + ((r > 0) ? H(r - 1, c) : 0);
                W(r, c) = 1.f + ((c > 0) ? W(r, c - 1) : 0);
            }

            float minw = W(r, c);
            for (int h = 0; h < H(r, c); ++h)
            {
                minw = min(minw, W(r - h, c));
                float area = (h + 1) * minw;
                if (area > maxArea)
                {
                    maxArea = area;
                    maxRect = Rect(Point(c - minw + 1, r - h), Point(c + 1, r + 1));
                }
            }
        }
    }

    return maxRect;
}

Usage is simple

Mat src, src_gray, src_bin;
cv::cvtColor(src, src_gray, COLOR_BGR2GRAY);
src_bin = (src_gray > 1) * 255;
Rect box = findMinRect(~src_bin);
rectangle(src, box, Scalar(0, 0, 255), 2);
cv::imshow("with_rectangle", src);
cv::waitKey();

But it's only first iteration. In next iteration we have to deal with at least 3 original image pieces, then with 9 pieces, and so on. I thing so... I will be grateful for any further suggestions.


问:
How to convert JSON string column row into a queryable table
I have exported to BigQuery from Firestore a whole collection to perform certain queries on it.

After the data was populated in my BigQuery console, now I can query the whole set like this

```<code>SELECT *
FROM `myapp-1a602.firestore_orders.orders_raw_changelog`
LIMIT 1000
</code>```

Now, this statement throws my different columns, but the one I'm looking for is the data column, in my data column is each document JSON, but is in json format and I need to query all this values.

Now, this is the data from one row

```<code>{
    "cart": [{
        "qty": 1,
        "description": "Sprite 1 L",
        "productName": "Sprite 1 Liter",
        "price": 1.99,
        "productId": 9
    }],
    "storeName": "My awesome shop",
    "status": 5,
    "timestamp": {
        "_seconds": 1590713204,
        "_nanoseconds": 916000000
    }
}
</code>```

This data is inside the data column, so if I do this

```<code>SELECT data
FROM `myapp-1a602.firestore_orders.orders_raw_changelog`
LIMIT 1000
</code>```

I will get all the json values for each document, but I don't know how to query that values, lets say I want to know all orders with status 5 and shopName My awesome shop , now, I need to do something with this json to convert it into a table ? does I need to perform the query in the json itself ?

How can I query this json output ?

Thanks

答:
What you must do is to extract the values from the json data as:
SELECT .......
WHERE data->'$.storeName'= "My awesome shop" and data->'$.status' = 5

Extracting from the 'cart' or ´the 'timestamp' keys will give you a Json object that needs further extracting to get the data.
I hope it'll help you
You probably want to have a look at the MySql documentation (https://dev.mysql.com/doc/refman/8.0/en/json.html) or https://www.mysqltutorial.org/mysql-json/.

Body:
I have exported to BigQuery from Firestore a whole collection to perform certain queries on it.

After the data was populated in my BigQuery console, now I can query the whole set like this

SELECT *
FROM `myapp-1a602.firestore_orders.orders_raw_changelog`
LIMIT 1000

Now, this statement throws my different columns, but the one I'm looking for is the data column, in my data column is each document JSON, but is in json format and I need to query all this values.

Now, this is the data from one row

{
    "cart": [{
        "qty": 1,
        "description": "Sprite 1 L",
        "productName": "Sprite 1 Liter",
        "price": 1.99,
        "productId": 9
    }],
    "storeName": "My awesome shop",
    "status": 5,
    "timestamp": {
        "_seconds": 1590713204,
        "_nanoseconds": 916000000
    }
}

This data is inside the data column, so if I do this

SELECT data
FROM `myapp-1a602.firestore_orders.orders_raw_changelog`
LIMIT 1000

I will get all the json values for each document, but I don't know how to query that values, lets say I want to know all orders with status 5 and shopName My awesome shop , now, I need to do something with this json to convert it into a table ? does I need to perform the query in the json itself ?

How can I query this json output ?

Thanks


问:
Need to submit Add to Cart form with jQuery / without AJAX /
I am having some trouble submitting the data from add to cart.

Basically i have this function / which prevents the user from buying the product without filling the form /:

```<code>$( document ).on( 'click', '.single_add_to_cart_button', function(e) {
            e.preventDefault();
        var productID = $(".single-product-page").attr('id');
        var productIDstr = productID.replace(/product-/g,'');
        console.log(productIDstr);
        if($("#tmcp_textfield_1").val() == "" || $("#tmcp_textfield_2").val() == "" || $("#tmcp_textfield_3").val() == "" || $("#tmcp_textfield_4").val() == "" ||
        $("#tmcp_textfield_5").val() == "" || $("#tmcp_textfield_6").val() == "" || $("#tmcp_textfield_7").val() == "" || $("#tmcp_textfield_8").val() == "" ||
        $("#tmcp_textfield_10").val() == "" || $("#tmcp_textfield_11").val() == "" || $("#tmcp_textfield_12").val() == "" ||
        $("#tmcp_textfield_13").val() == "" || $("#tmcp_textarea_14").val() == "" || $('#tmcp_choice_14_0_15').prop('checked') != true ) {
            $('.tm-section-link')[0].click();

        }
</code>```

And after all of these are done i have put :

```<code>   else {
            $('form.cart').submit();
        }
</code>```

but that only refreshes the page, without actually adding the product to the cart. I just need to submit the data after that.

Thanks in advance!!

答:
You could use

```<code>.trigger('click');
</code>```

Note:

your code is saying if all of those fields are empty, trigger the click. If you want it to NOT submit if those fields are empty, you may want to change it to != instead of ==

```<code>$( document ).on( 'click', '.single_add_to_cart_button', function(e) {
  e.preventDefault();
  var $addToCartButton = $(this);
  var productID = $(".single-product-page").attr('id');
  var productIDstr = productID.replace(/product-/g,'');

  if($("#tmcp_textfield_1").val() == "" || $("#tmcp_textfield_2").val() == "" || $("#tmcp_textfield_3").val() == "" || $("#tmcp_textfield_4").val() == "" ||
     $("#tmcp_textfield_5").val() == "" || $("#tmcp_textfield_6").val() == "" || $("#tmcp_textfield_7").val() == "" || $("#tmcp_textfield_8").val() == "" ||
     $("#tmcp_textfield_10").val() == "" || $("#tmcp_textfield_11").val() == "" || $("#tmcp_textfield_12").val() == "" ||
     $("#tmcp_textfield_13").val() == "" || $("#tmcp_textarea_14").val() == "" || $('#tmcp_choice_14_0_15').prop('checked') != true ) {
            $addToCartButton.trigger('click');

  }
</code>```

Body:
I am having some trouble submitting the data from add to cart.

Basically i have this function / which prevents the user from buying the product without filling the form /:

$( document ).on( 'click', '.single_add_to_cart_button', function(e) {
            e.preventDefault();
        var productID = $(".single-product-page").attr('id');
        var productIDstr = productID.replace(/product-/g,'');
        console.log(productIDstr);
        if($("#tmcp_textfield_1").val() == "" || $("#tmcp_textfield_2").val() == "" || $("#tmcp_textfield_3").val() == "" || $("#tmcp_textfield_4").val() == "" ||
        $("#tmcp_textfield_5").val() == "" || $("#tmcp_textfield_6").val() == "" || $("#tmcp_textfield_7").val() == "" || $("#tmcp_textfield_8").val() == "" ||
        $("#tmcp_textfield_10").val() == "" || $("#tmcp_textfield_11").val() == "" || $("#tmcp_textfield_12").val() == "" ||
        $("#tmcp_textfield_13").val() == "" || $("#tmcp_textarea_14").val() == "" || $('#tmcp_choice_14_0_15').prop('checked') != true ) {
            $('.tm-section-link')[0].click();

        }

And after all of these are done i have put :

   else {
            $('form.cart').submit();
        }

but that only refreshes the page, without actually adding the product to the cart. I just need to submit the data after that.

Thanks in advance!!

Body:
You could use

.trigger('click');

Note:

your code is saying if all of those fields are empty, trigger the click. If you want it to NOT submit if those fields are empty, you may want to change it to != instead of ==

$( document ).on( 'click', '.single_add_to_cart_button', function(e) {
  e.preventDefault();
  var $addToCartButton = $(this);
  var productID = $(".single-product-page").attr('id');
  var productIDstr = productID.replace(/product-/g,'');

  if($("#tmcp_textfield_1").val() == "" || $("#tmcp_textfield_2").val() == "" || $("#tmcp_textfield_3").val() == "" || $("#tmcp_textfield_4").val() == "" ||
     $("#tmcp_textfield_5").val() == "" || $("#tmcp_textfield_6").val() == "" || $("#tmcp_textfield_7").val() == "" || $("#tmcp_textfield_8").val() == "" ||
     $("#tmcp_textfield_10").val() == "" || $("#tmcp_textfield_11").val() == "" || $("#tmcp_textfield_12").val() == "" ||
     $("#tmcp_textfield_13").val() == "" || $("#tmcp_textarea_14").val() == "" || $('#tmcp_choice_14_0_15').prop('checked') != true ) {
            $addToCartButton.trigger('click');

  }


问:
Connecting to server TCP in C
I need to clarify something. I'm making a server/client TCP program in C.

What happens if a client tries to connect (using connect()) when the server is not stuck in accept()? I mean, when it's busy? What does connect() return?

EDIT:

I'm on Linux environment.

```<code>if (connect(...) < 0) {
    // ERROR AND LEAVE
}
</code>```

This is what I'm doing in my client. From what I've read and learned, if the server is busy and not accepting, connect() should wait a little bit, and then return -1, if the server is still busy. Is that right?

If so, how do I avoid that "little bit"? I want it to return -1 right away.

答:
From what I've read and learned, if the server is busy and not accepting, connect() should wait a little bit, and then return -1, if the server is still busy. Is that right?

The acceptance of the TCP connection, i.e. the TCP handshake, is fully done in the OS kernel independent from a call to accept. accept just returns already accepted connections to user space. Thus, even if the server is currently busy the connection will succeed as long as there is still space in the pending queue. The size of the pending queue is set with listen. If the pending queue is full since the application did not retrieve accepted connections from it for some time but clients still connected, then the server OS will reject the connect attempt, i.e. connect will fail.

Title: Connecting to server TCP in C

Body:
I need to clarify something. I'm making a server/client TCP program in C.

What happens if a client tries to connect (using connect()) when the server is not stuck in accept()? I mean, when it's busy? What does connect() return?

EDIT:

I'm on Linux environment.

if (connect(...) < 0) {
    // ERROR AND LEAVE
}

This is what I'm doing in my client. From what I've read and learned, if the server is busy and not accepting, connect() should wait a little bit, and then return -1, if the server is still busy. Is that right?

If so, how do I avoid that "little bit"? I want it to return -1 right away.


问:
Sorting HTML table with empty cells placed at the bottom
I'm using this answer here - sort html table with jquery to properly sort my HTML table.
However, I would like to simply sort the table with all of the empty TD cells at the bottom. Does anyone have a simple tweak to do this?
Here's my exact code -</p>

```<code>   $('#sortAnniv').click(function() {
    var table = $('#myTable')
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})

function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }
</code>```

答:
just add a case for it</p>

```<code>function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        // Add this line
        if (valA.length === 0) return 1; if (valB.length === 0) return -1;
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
</code>```

Body:
I'm using this answer here - sort html table with jquery to properly sort my HTML table.
However, I would like to simply sort the table with all of the empty TD cells at the bottom. Does anyone have a simple tweak to do this?
Here's my exact code -

   $('#sortAnniv').click(function() {
    var table = $('#myTable')
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})

function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }

Body:
just add a case for it

function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        // Add this line
        if (valA.length === 0) return 1; if (valB.length === 0) return -1;
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}


问:
How To Reload Table?
I have 2 views we are dealing with.  Main View, and Sub View.

Main View's tablecell's string shows the count of the number of objects in that cell's subView.  When I delete a cell from the subview, and go back to the mainView, the string that shows the count should go down by 1.  Right now this string is not changing until I restart the app.

Any ideas how I can fix this?  The count is being pulled from a NSFetch.

Edit: Added Code

```<code>- (void)configureCell:(TDBadgedCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    NSDate *today = [NSDate date];
    NSDate *thisWeek  = [today dateByAddingTimeInterval: -604800.0];
    NSDate *thisMonth = [today dateByAddingTimeInterval: -2629743.83];
    else if (indexPath.row == 2)
    {
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        self.predicate = [NSPredicate predicateWithFormat:@"(timeStamp >= %@) AND (timeStamp <= %@)", thisWeek, today];
        [fetchRequest setPredicate: predicate];
        [fetchRequest setEntity:[NSEntityDescription entityForName:@"Session" inManagedObjectContext:managedObjectContext]];
        NSError *error = nil;
        NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
        NSLog(@"Fetch error: %@", error);

        cell.badgeString = [NSString stringWithFormat:@"%i", [results count]];
        [fetchRequest release];
    }
    else if (indexPath.row == 3)
    {
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        self.predicate = [NSPredicate predicateWithFormat:@"(timeStamp >= %@) AND (timeStamp <= %@)", thisMonth, today];
        [fetchRequest setPredicate:predicate];
        [fetchRequest setEntity:[NSEntityDescription entityForName:@"Session" inManagedObjectContext:managedObjectContext]];

        NSError *error = nil;
        NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
        NSLog(@"Fetch error: %@", error);

        cell.badgeString = [NSString stringWithFormat:@"%i", [results count]];
        [fetchRequest release];
    }
    else if (indexPath.row == 4)
    {
        cell.badgeString = [NSString stringWithFormat:@"%i", [[self.fetchedResultsController fetchedObjects] count]];
    }
</code>```

答:
If your data is in fact being updated correctly on the model side of things, you should be able to call

```<code>[tableView reloadData];
</code>```

and everything will update correctly. You can probably put this in viewWillAppear.

Hope this helps.

Title: How To Reload Table?

Body:
I have 2 views we are dealing with.  Main View, and Sub View.

Main View's tablecell's string shows the count of the number of objects in that cell's subView.  When I delete a cell from the subview, and go back to the mainView, the string that shows the count should go down by 1.  Right now this string is not changing until I restart the app.

Any ideas how I can fix this?  The count is being pulled from a NSFetch.

Edit: Added Code

- (void)configureCell:(TDBadgedCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    NSDate *today = [NSDate date];
    NSDate *thisWeek  = [today dateByAddingTimeInterval: -604800.0];
    NSDate *thisMonth = [today dateByAddingTimeInterval: -2629743.83];
    else if (indexPath.row == 2)
    {
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        self.predicate = [NSPredicate predicateWithFormat:@"(timeStamp >= %@) AND (timeStamp <= %@)", thisWeek, today];
        [fetchRequest setPredicate: predicate];
        [fetchRequest setEntity:[NSEntityDescription entityForName:@"Session" inManagedObjectContext:managedObjectContext]];
        NSError *error = nil;
        NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
        NSLog(@"Fetch error: %@", error);

        cell.badgeString = [NSString stringWithFormat:@"%i", [results count]];
        [fetchRequest release];
    }
    else if (indexPath.row == 3)
    {
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        self.predicate = [NSPredicate predicateWithFormat:@"(timeStamp >= %@) AND (timeStamp <= %@)", thisMonth, today];
        [fetchRequest setPredicate:predicate];
        [fetchRequest setEntity:[NSEntityDescription entityForName:@"Session" inManagedObjectContext:managedObjectContext]];

        NSError *error = nil;
        NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
        NSLog(@"Fetch error: %@", error);

        cell.badgeString = [NSString stringWithFormat:@"%i", [results count]];
        [fetchRequest release];
    }
    else if (indexPath.row == 4)
    {
        cell.badgeString = [NSString stringWithFormat:@"%i", [[self.fetchedResultsController fetchedObjects] count]];
    }

Body:
If your data is in fact being updated correctly on the model side of things, you should be able to call

[tableView reloadData];

and everything will update correctly. You can probably put this in viewWillAppear.

Hope this helps.


问:
file paths to json tree structure
I have data as following:
`

```<code>[
  {path: "path1/path2/path3/index.file", title: "path3 Title"},
  {path: "path1/path2/index.file", title: "path2 Title"},
  {path: "path1/path2/path3/path4.file", title: "path4 Title"},
  {path: "path5/path5.file", title: "path5 Title"},
  {path: "path1/index.file", title: "path1 Title"},
  {path: "index.file", title: "path0 Title"},
]
</code>```

`
and i need something like :-

`

```<code>[
  {title: "path1 title", children: [
    {title: "path2 Title", children: [
      title: "path3 Title", children: [
        title: "path 4 Title", children: []
      ]
    ]
  ]},
  {
    title: "path 5 title", children: []
  },
  {
    title: "path 0 title", children: []
  }
]
</code>```

`

so far i have written this but its not helping me at all.
`

```<code>let treepath = {};
      paths.forEach(path => {
        let levels = path.split("/");
        let file = levels.pop();

        let prevLevel = treePath;
        let prevProp = levels.shift();

        levels.forEach(prop => {
          prevLevel[prevProp] = prevLevel[prevProp] || {};
          prevLevel = prevLevel[prevProp];
          prevProp = prop;
        });

        prevLevel[prevProp] = (prevLevel[prevProp] || []).concat([file]);
      });

    console.log('treepath', treePath);
</code>```

`

There can be various paths. they are coming dynamically. i need to set them as children. i need to do this in Javascript code.Appreciate your help. Thanks.

答:
You could take a shadow tree and assign the title later to the the structure.

var data = [{ path: "path1/path2/path3/index.file", title: "path3 Title" }, { path: "path1/path2/index.file", title: "path2 Title" }, { path: "path1/path2/path3/path4.file", title: "path4 Title" }, { path: "path5/path5.file", title: "path5 Title" }, { path: "path1/index.file", title: "path1 Title" }, { path: "index.file", title: "path0 Title" }],
    tree = data
        .reduce((r, { path, title }) => {
            let directories = ('root/' + path).split('/');

            directories.pop();

            directories
                .reduce((d, key) => {
                    if (!d[key]) {
                        d[key] = { _: [] };
                        d._.push(d[key].parent = { title: null, children: d[key]._ });
                    }
                    return d[key];
                }, r)
                .parent
                .title = title;
            return r;
        }, { _: [] })
        ._;

console.log(tree);```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.as-console-wrapper { max-height: 100% !important; top: 0; }</code>```

Title: file paths to json tree structure

Body:
I have data as following:
`

[
  {path: "path1/path2/path3/index.file", title: "path3 Title"},
  {path: "path1/path2/index.file", title: "path2 Title"},
  {path: "path1/path2/path3/path4.file", title: "path4 Title"},
  {path: "path5/path5.file", title: "path5 Title"},
  {path: "path1/index.file", title: "path1 Title"},
  {path: "index.file", title: "path0 Title"},
]

`
and i need something like :-

`

[
  {title: "path1 title", children: [
    {title: "path2 Title", children: [
      title: "path3 Title", children: [
        title: "path 4 Title", children: []
      ]
    ]
  ]},
  {
    title: "path 5 title", children: []
  },
  {
    title: "path 0 title", children: []
  }
]

`

so far i have written this but its not helping me at all.
`

let treepath = {};
      paths.forEach(path => {
        let levels = path.split("/");
        let file = levels.pop();

        let prevLevel = treePath;
        let prevProp = levels.shift();

        levels.forEach(prop => {
          prevLevel[prevProp] = prevLevel[prevProp] || {};
          prevLevel = prevLevel[prevProp];
          prevProp = prop;
        });

        prevLevel[prevProp] = (prevLevel[prevProp] || []).concat([file]);
      });

    console.log('treepath', treePath);

`

There can be various paths. they are coming dynamically. i need to set them as children. i need to do this in Javascript code.Appreciate your help. Thanks.

Body:
You could take a shadow tree and assign the title later to the the structure.

var data = [{ path: "path1/path2/path3/index.file", title: "path3 Title" }, { path: "path1/path2/index.file", title: "path2 Title" }, { path: "path1/path2/path3/path4.file", title: "path4 Title" }, { path: "path5/path5.file", title: "path5 Title" }, { path: "path1/index.file", title: "path1 Title" }, { path: "index.file", title: "path0 Title" }],
    tree = data
        .reduce((r, { path, title }) => {
            let directories = ('root/' + path).split('/');

            directories.pop();

            directories
                .reduce((d, key) => {
                    if (!d[key]) {
                        d[key] = { _: [] };
                        d._.push(d[key].parent = { title: null, children: d[key]._ });
                    }
                    return d[key];
                }, r)
                .parent
                .title = title;
            return r;
        }, { _: [] })
        ._;

console.log(tree);

.as-console-wrapper { max-height: 100% !important; top: 0; }


问:
Translate SQL query into a well made QuerySet
I have a raw queryset that i want to translate in QuerySet. But i always ends up with error.

Here is the raw query :

```<code>q = Table1.objects.raw(
     '''SELECT base_table1.id, base_table1.name, base_table1.n_id, count(base_table2.id) as 'count', max(base_table2.timestamp) as 'latest'
                                     FROM base_table1
                                     INNER JOIN base_table3 on base_table3.table1_id = base_table1.id
                                     INNER JOIN base_table2 on base_table2.table3_id = base_table3.id
                                     GROUP by base_table1.id'''
</code>```

Note : here i don't need the base_table1.id, but it was required for the rawQuerySet

Here are the models :

```<code>class Table1(models.Model):
n_id = models.PositiveIntegerField()
name = models.CharField(max_length=45)

class Table2(models.Model):
table3 = models.ForeignKey(
    Table3, null=True, blank=True, on_delete=models.SET_NULL
)
timestamp = models.DateTimeField(null=True)

class Table3(models.Model):
table1 = models.ForeignKey(
    Table1, null=True, related_name='t_entries', on_delete=models.SET_NULL
)
</code>```

Great thanks in advance for your answers.

答:
You can annotate the Table1 model with:

```<code>from django.db.models import Max, Count

Table1.objects.annotate(
    count=Count('t_entries__table3'),
    latest=Max('t_entries__table3__timestamp')
)</code>```

The Table1 objects that arise from this queryset will have extra attributes .count and .latest.

Body:
I have a raw queryset that i want to translate in QuerySet. But i always ends up with error.

Here is the raw query :

q = Table1.objects.raw(
     '''SELECT base_table1.id, base_table1.name, base_table1.n_id, count(base_table2.id) as 'count', max(base_table2.timestamp) as 'latest'
                                     FROM base_table1
                                     INNER JOIN base_table3 on base_table3.table1_id = base_table1.id
                                     INNER JOIN base_table2 on base_table2.table3_id = base_table3.id
                                     GROUP by base_table1.id'''

Note : here i don't need the base_table1.id, but it was required for the rawQuerySet

Here are the models :

class Table1(models.Model):
n_id = models.PositiveIntegerField()
name = models.CharField(max_length=45)

class Table2(models.Model):
table3 = models.ForeignKey(
    Table3, null=True, blank=True, on_delete=models.SET_NULL
)
timestamp = models.DateTimeField(null=True)

class Table3(models.Model):
table1 = models.ForeignKey(
    Table1, null=True, related_name='t_entries', on_delete=models.SET_NULL
)

Great thanks in advance for your answers.

Body:
You can annotate the Table1 model with:

from django.db.models import Max, Count

Table1.objects.annotate(
    count=Count('t_entries__table3'),
    latest=Max('t_entries__table3__timestamp')
)

The Table1 objects that arise from this queryset will have extra attributes .count and .latest.


问:
How can you apply AVG() on a row instead of a column?
I have a procedure that is fetching data from the DB and as an example the final result is the following:

```<code>Column1 |Column2         |Column3       |Column4     |Column5     |Column6
--------|----------------|--------------|------------|------------|-------
 1      |2               |1111          |001         |345.000000  |22
 3      |5               |1111          |001         |700.000000  |22
 1      |0               |1112          |001         |345.000000  |22
 2      |7               |5454          |001         |1200.000000 |22
 2      |5               |2364          |001         |1350.000000 |22
</code>```

I'd like to apply the AVG function per row meaning I'd like to add a 7th column under which the AVG of all the values of column 1,2,3,4,5 and 6 for that specific row is "averaged"

Please note that some of the data can be nullable

答:
but the division will be always a 6 which will affect the mathematical result – Houssem Timoumi

you must wirte a little bit more:

```<code>alter table t add  column7 as
( ( ISNULL (column1, 0)
  + ISNULL (column2, 0)
  + ISNULL (column3, 0)
  + ISNULL (column4, 0)
  + ISNULL (column5, 0)
  + ISNULL (column6, 0)
  )
  / CASE  WHEN column1 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column2 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column3 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column4 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column5 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column6 IS NULL THEN 0 ELSE 1 END
);
</code>```

Body:
I have a procedure that is fetching data from the DB and as an example the final result is the following:

Column1 |Column2         |Column3       |Column4     |Column5     |Column6
--------|----------------|--------------|------------|------------|-------
 1      |2               |1111          |001         |345.000000  |22
 3      |5               |1111          |001         |700.000000  |22
 1      |0               |1112          |001         |345.000000  |22
 2      |7               |5454          |001         |1200.000000 |22
 2      |5               |2364          |001         |1350.000000 |22

I'd like to apply the AVG function per row meaning I'd like to add a 7th column under which the AVG of all the values of column 1,2,3,4,5 and 6 for that specific row is "averaged"

Please note that some of the data can be nullable

Body:
but the division will be always a 6 which will affect the mathematical result – Houssem Timoumi

you must wirte a little bit more:

alter table t add  column7 as
( ( ISNULL (column1, 0)
  + ISNULL (column2, 0)
  + ISNULL (column3, 0)
  + ISNULL (column4, 0)
  + ISNULL (column5, 0)
  + ISNULL (column6, 0)
  )
  / CASE  WHEN column1 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column2 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column3 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column4 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column5 IS NULL THEN 0 ELSE 1 END
  + CASE  WHEN column6 IS NULL THEN 0 ELSE 1 END
);


问:
Strange outline appears in Chrome 83/IE on my Windows 10
something very, very strange has happened.
Since a few hours, my Chrome (also IE) shows a different default outline on input.
Inspecting the code I saw that the outline set is as follows:

outline: -webkit-focus-ring-color auto 1px

and result is like this:

happens both incognito and in navigation with or without extensions.

how can I restore it ?

答:
it's a new "feature" of chrome 83....(that afflict all S.O.) I hope will be removed soon.
https://support.google.com/chrome/thread/48974735?hl=en</p>


问:
How to change datetime values into a separately formatted value
I have a data set, which unfortunately has sporadic DateTime values, rather than int or str.

How could I go about editing the values, by iterating through the database and replacing the 2019-05-03 00:00:00 into 5-3, for example?

I have tried a few for loops but to no avail. Is there a pandas shortcut?

```<code>,age,menopause,tumor-size,inv-nodes,node-caps,deg-malig,breast,breast-quad,irradiat,Class
0,40-49,premeno,15-19,0-2,yes,3,right,left_up,no,recurrence-events
1,50-59,ge40,15-19,0-2,no,1,right,central,no,no-recurrence-events
2,50-59,ge40,35-39,0-2,no,2,left,left_low,no,recurrence-events
3,40-49,premeno,35-39,0-2,yes,3,right,left_low,yes,no-recurrence-events
4,40-49,premeno,30-34,2019-05-03 00:00:00,yes,2,left,right_up,no,recurrence-events
5,50-59,premeno,25-29,2019-05-03 00:00:00,no,2,right,left_up,yes,no-recurrence-events
6,50-59,ge40,40-44,0-2,no,3,left,left_up,no,no-recurrence-events
7,40-49,premeno,2014-10-01 00:00:00,0-2,no,2,left,left_up,no,no-recurrence-events
8,40-49,premeno,0-4,0-2,no,2,right,right_low,no,no-recurrence-events
9,40-49,ge40,40-44,15-17,yes,2,right,left_up,yes,no-recurrence-events
10,50-59,premeno,25-29,0-2,no,2,left,left_low,no,no-recurrence-events
11,60-69,ge40,15-19,0-2,no,2,right,left_up,no,no-recurrence-events
12,50-59,ge40,30-34,0-2,no,1,right,central,no,no-recurrence-events
13,50-59,ge40,25-29,0-2,no,2,right,left_up,no,no-recurrence-events
14,40-49,premeno,25-29,0-2,no,2,left,left_low,yes,recurrence-events
15,30-39,premeno,20-24,0-2,no,3,left,central,no,no-recurrence-events
16,50-59,premeno,2014-10-01 00:00:00,2019-05-03 00:00:00,no,1,right,left_up,no,no-recurrence-events
17,60-69,ge40,15-19,0-2,no,2,right,left_up,no,no-recurrence-events
18,50-59,premeno,40-44,0-2,no,2,left,left_up,no,no-recurrence-events
19,50-59,ge40,20-24,0-2,no,3,left,left_up,no,no-recurrence-events
20,50-59,lt40,20-24,0-2,?,1,left,left_low,no,recurrence-events
21,60-69,ge40,40-44,2019-05-03 00:00:00,no,2,right,left_up,yes,no-recurrence-events
22,50-59,ge40,15-19,0-2,no,2,right,left_low,no,no-recurrence-events
23,40-49,premeno,2014-10-01 00:00:00,0-2,no,1,right,left_up,no,no-recurrence-events
24,30-39,premeno,15-19,2019-08-06 00:00:00,yes,3,left,left_low,yes,recurrence-events
25,50-59,ge40,20-24,2019-05-03 00:00:00,yes,2,right,left_up,no,no-recurrence-events
</code>```

Body:
I have a data set, which unfortunately has sporadic DateTime values, rather than int or str.

How could I go about editing the values, by iterating through the database and replacing the 2019-05-03 00:00:00 into 5-3, for example?

I have tried a few for loops but to no avail. Is there a pandas shortcut?

,age,menopause,tumor-size,inv-nodes,node-caps,deg-malig,breast,breast-quad,irradiat,Class
0,40-49,premeno,15-19,0-2,yes,3,right,left_up,no,recurrence-events
1,50-59,ge40,15-19,0-2,no,1,right,central,no,no-recurrence-events
2,50-59,ge40,35-39,0-2,no,2,left,left_low,no,recurrence-events
3,40-49,premeno,35-39,0-2,yes,3,right,left_low,yes,no-recurrence-events
4,40-49,premeno,30-34,2019-05-03 00:00:00,yes,2,left,right_up,no,recurrence-events
5,50-59,premeno,25-29,2019-05-03 00:00:00,no,2,right,left_up,yes,no-recurrence-events
6,50-59,ge40,40-44,0-2,no,3,left,left_up,no,no-recurrence-events
7,40-49,premeno,2014-10-01 00:00:00,0-2,no,2,left,left_up,no,no-recurrence-events
8,40-49,premeno,0-4,0-2,no,2,right,right_low,no,no-recurrence-events
9,40-49,ge40,40-44,15-17,yes,2,right,left_up,yes,no-recurrence-events
10,50-59,premeno,25-29,0-2,no,2,left,left_low,no,no-recurrence-events
11,60-69,ge40,15-19,0-2,no,2,right,left_up,no,no-recurrence-events
12,50-59,ge40,30-34,0-2,no,1,right,central,no,no-recurrence-events
13,50-59,ge40,25-29,0-2,no,2,right,left_up,no,no-recurrence-events
14,40-49,premeno,25-29,0-2,no,2,left,left_low,yes,recurrence-events
15,30-39,premeno,20-24,0-2,no,3,left,central,no,no-recurrence-events
16,50-59,premeno,2014-10-01 00:00:00,2019-05-03 00:00:00,no,1,right,left_up,no,no-recurrence-events
17,60-69,ge40,15-19,0-2,no,2,right,left_up,no,no-recurrence-events
18,50-59,premeno,40-44,0-2,no,2,left,left_up,no,no-recurrence-events
19,50-59,ge40,20-24,0-2,no,3,left,left_up,no,no-recurrence-events
20,50-59,lt40,20-24,0-2,?,1,left,left_low,no,recurrence-events
21,60-69,ge40,40-44,2019-05-03 00:00:00,no,2,right,left_up,yes,no-recurrence-events
22,50-59,ge40,15-19,0-2,no,2,right,left_low,no,no-recurrence-events
23,40-49,premeno,2014-10-01 00:00:00,0-2,no,1,right,left_up,no,no-recurrence-events
24,30-39,premeno,15-19,2019-08-06 00:00:00,yes,3,left,left_low,yes,recurrence-events
25,50-59,ge40,20-24,2019-05-03 00:00:00,yes,2,right,left_up,no,no-recurrence-events

Body:
you could use a custom function which uses regex to find datetime strings and replaces them with not-zero-padded '%m-%d' (on Linux, you could potientially also strftime with '%-m-%-d'...):

import re

def to_month_day(s):
    m = re.match("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}", s)
    if m:
        return m[0][5:7].lstrip('0') + '-' + m[0][8:10].lstrip('0')
    return s

# e.g.
df['inv-nodes'].apply(to_month_day)
# 0       0-2
# 1       0-2
# 2       0-2
# 3       0-2
# 4       5-3
# 5       5-3
# 6       0-2
# 7       0-2
# 8       0-2
# 9     15-17
# 10      0-2
# 11      0-2
# 12      0-2
# 13      0-2
# 14      0-2
# 15      0-2
# 16      5-3
# 17      0-2
# 18      0-2
# 19      0-2
# 20      0-2
# 21      5-3
# 22      0-2
# 23      0-2
# 24      8-6
# 25      5-3