问:
ODBC connections in Visual Studio 2022 : Unable to connect to Redshift Cluster
I'm trying to get something very simple to work :-)

The driver is mapped in ODBC x64

Imports System.Data.Odbc

Dim odbcconn As New OdbcConnection()

connstr = "Provider=MSDASQL;DSN=Redshift-awsuser;Driver={Amazon Redshift (x64)}; Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"

odbcconn.ConnectionString = connstr
odbcconn.Open()
```
<p>I've run into the following errors:</p>
<blockquote>
<p>System.Data.Odbc.OdbcException: 'ERROR [IM014] [Microsoft][ODBC Driver Manager] The specified DSN contains an architecture mismatch between the Driver and Application'</p>
</blockquote>
<p>Other connection strings I've tried :</p>
<pre class="lang-vb prettyprint-override"><code>connstr = "Provider=MSDASQL;DSN=Redshift-awsuser;Driver={Amazon Redshift (x86)}; Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"
</code>```

OR

connstr = "DSN=Redshift-awsuser;Driver={Amazon Redshift (x86)}; Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"
```
<p>OR</p>
<pre class="lang-vb prettyprint-override"><code>connstr = "DSN=Redshift-awsuser;Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"
</code>```

I can connect as a Dataset, but not through the ODBCConnection. I need the connection to perform a loop function within VS / Visual Basic.

I haven't used Visual Studio in a while so I'm hoping the solution is super simple!

答:
I unchecked the part highlighted "Prefer 32-bit" under the Compile settings. To find this go to Project -> (last menu item) [Application name] properties; then compile settings.

I also copied the connection string from the Server Explorer -> Data Connections -> Modify Connection -> Connection String field.

Super confused how this started working.

Body:
I'm trying to get something very simple to work :-)

The driver is mapped in ODBC x64

Imports System.Data.Odbc

Dim odbcconn As New OdbcConnection()

connstr = "Provider=MSDASQL;DSN=Redshift-awsuser;Driver={Amazon Redshift (x64)}; Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"

odbcconn.ConnectionString = connstr
odbcconn.Open()

I've run into the following errors:

System.Data.Odbc.OdbcException: 'ERROR [IM014] [Microsoft][ODBC Driver Manager] The specified DSN contains an architecture mismatch between the Driver and Application'

Other connection strings I've tried :

connstr = "Provider=MSDASQL;DSN=Redshift-awsuser;Driver={Amazon Redshift (x86)}; Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"

OR

connstr = "DSN=Redshift-awsuser;Driver={Amazon Redshift (x86)}; Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"

OR

connstr = "DSN=Redshift-awsuser;Server=gref-cluster-1.yyy.us-east-1.redshift.amazonaws.com; Database=xxx; UID=yyy; PWD=xxx; Port=1234"

I can connect as a Dataset, but not through the ODBCConnection. I need the connection to perform a loop function within VS / Visual Basic.

I haven't used Visual Studio in a while so I'm hoping the solution is super simple!


来源: stackexchange

问:
CocoaPods could not find compatible versions for pod "Flipper-Folly"
I have been trying to run ios for a new but kept getting this error

```<code>** BUILD FAILED **

The following build commands failed:
        CompileC /Users/struggle/Library/Developer/Xcode/DerivedData/client-grabnjjdhfcfyugfdqcwdvbebnva/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/Flipper.build/Objects-normal/x86_64/FlipperRSocketResponder.o /Users/struggle/Desktop/Tax/client/ios/Pods/Flipper/xplat/Flipper/FlipperRSocketResponder.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)
</code>```

I saw a solution that said to add use_flipper!({ 'Flipper-Folly' => '2.3.0' }) in my podfile now when i run pod install i get the following error

```<code>`[!] CocoaPods could not find compatible versions for pod "Flipper-Folly":

In Podfile:
Flipper-Folly (= 2.3.0)

FlipperKit (~> 0.54.0) was resolved to 0.54.0, which depends on
  FlipperKit/Core (= 0.54.0) was resolved to 0.54.0, which depends on
    Flipper (~> 0.54.0) was resolved to 0.54.0, which depends on
      Flipper-Folly (~> 2.2)

FlipperKit (~> 0.54.0) was resolved to 0.54.0, which depends on
  FlipperKit/Core (= 0.54.0) was resolved to 0.54.0, which depends on
    Flipper (~> 0.54.0) was resolved to 0.54.0, which depends on
      Flipper-RSocket (~> 1.1) was resolved to 1.3.0, which depends on
        Flipper-Folly (~> 2.5)`
</code>```

Using ({'Flipper-Folly' => '2.3.0'}) results in me getting the inital error again.
Please help me fix this issue. Thank You

答:
I needed to go down one version before it, since the last one was 3 hours ago and obviously still not available in any repo.

Check this:
https://github.com/facebook/flipper/releases
And this:
https://fbflipper.com/docs/getting-started/react-native/

ContentLicense: CC BY-SA 4.0

Body:
I have been trying to run ios for a new but kept getting this error

** BUILD FAILED **

The following build commands failed:
        CompileC /Users/struggle/Library/Developer/Xcode/DerivedData/client-grabnjjdhfcfyugfdqcwdvbebnva/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/Flipper.build/Objects-normal/x86_64/FlipperRSocketResponder.o /Users/struggle/Desktop/Tax/client/ios/Pods/Flipper/xplat/Flipper/FlipperRSocketResponder.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)

I saw a solution that said to add use_flipper!({ 'Flipper-Folly' => '2.3.0' }) in my podfile now when i run pod install i get the following error

`[!] CocoaPods could not find compatible versions for pod "Flipper-Folly":

In Podfile:
Flipper-Folly (= 2.3.0)

FlipperKit (~> 0.54.0) was resolved to 0.54.0, which depends on
  FlipperKit/Core (= 0.54.0) was resolved to 0.54.0, which depends on
    Flipper (~> 0.54.0) was resolved to 0.54.0, which depends on
      Flipper-Folly (~> 2.2)

FlipperKit (~> 0.54.0) was resolved to 0.54.0, which depends on
  FlipperKit/Core (= 0.54.0) was resolved to 0.54.0, which depends on
    Flipper (~> 0.54.0) was resolved to 0.54.0, which depends on
      Flipper-RSocket (~> 1.1) was resolved to 1.3.0, which depends on
        Flipper-Folly (~> 2.5)`

Using ({'Flipper-Folly' => '2.3.0'}) results in me getting the inital error again.
Please help me fix this issue. Thank You


问:
Throttle JS Event Listeners added by 3rd party library
I want to throttle function calls which are added as Event Listeners to the window.scroll function by a 3rd party library provided by an external supplied (cant be changed).

I figured out that the library causes some overhead by its scroll event listener, because if I remove the event handler, my page runs much smoother.

As I cannot directly control or change the external JS file, I thought to read the scroll-events attached to the Window and delete / rebind them again, but in a throttled format, as I have already the Underscore.js library in use.

I'm trying to read the Scroll events and than replace the function callback as a throttled version:

```<code>  jQuery(document).ready(function($) {
    let scrollEvents = $._data(window, 'events').scroll;
    for(evt of scrollEvents ) {
      evt.handler = _.throttle(evt.handler, 200)
    }
  });
</code>```

Does not seem to bring the appropriate improvement. In the Webdeveloper Bar "Global Event Listeners" I still see the original event listeners attached, I do NOT see the Underscore Library (as intermediate layer) listed there.

What is potentially wrong with this code?

Thanks

EDIT
Those events are added globally to the Window, see WebDev Screenshot:
 and I run the above code within the WebDev console, so it is ran only after those events exist already.

AND $._data(window, 'events').scroll; shows ALL those 5 events, so jQuery should be able to change them, isnt it?

答:
Found a beautiful solution using Underscore.js, proxying the callback functions by a Throttler before adding it as Event Handler:

```<code>    var f_add = EventTarget.prototype.addEventListener;
    var f_remove = EventTarget.prototype.removeEventListener;

    EventTarget.prototype.addEventListener = function(type, fn, capture) {
        this.f = f_add;
        if(type == 'scroll' && typeof _ === 'function')
            fn = _.throttle(fn, 350);
        this.f(type, fn, capture);
    }

    EventTarget.prototype.removeEventListener = function(type, fn, capture) {
        this.f = f_remove;
        if(type == 'scroll' && typeof _ === 'function')
            fn = _.throttle(fn, 350);
        this.f(type, fn, capture);
    }
</code>```

It overwrites the prototype for add/removeEventListener -> And if the event is a scroll event, it surrounds the Function fn with _.throttle().

Body:
I want to throttle function calls which are added as Event Listeners to the window.scroll function by a 3rd party library provided by an external supplied (cant be changed).

I figured out that the library causes some overhead by its scroll event listener, because if I remove the event handler, my page runs much smoother.

As I cannot directly control or change the external JS file, I thought to read the scroll-events attached to the Window and delete / rebind them again, but in a throttled format, as I have already the Underscore.js library in use.

I'm trying to read the Scroll events and than replace the function callback as a throttled version:

  jQuery(document).ready(function($) {
    let scrollEvents = $._data(window, 'events').scroll;
    for(evt of scrollEvents ) {
      evt.handler = _.throttle(evt.handler, 200)
    }
  });

Does not seem to bring the appropriate improvement. In the Webdeveloper Bar "Global Event Listeners" I still see the original event listeners attached, I do NOT see the Underscore Library (as intermediate layer) listed there.

What is potentially wrong with this code?

Thanks

EDIT
Those events are added globally to the Window, see WebDev Screenshot:
 and I run the above code within the WebDev console, so it is ran only after those events exist already.

AND $._data(window, 'events').scroll; shows ALL those 5 events, so jQuery should be able to change them, isnt it?

Body:
Found a beautiful solution using Underscore.js, proxying the callback functions by a Throttler before adding it as Event Handler:

    var f_add = EventTarget.prototype.addEventListener;
    var f_remove = EventTarget.prototype.removeEventListener;

    EventTarget.prototype.addEventListener = function(type, fn, capture) {
        this.f = f_add;
        if(type == 'scroll' && typeof _ === 'function')
            fn = _.throttle(fn, 350);
        this.f(type, fn, capture);
    }

    EventTarget.prototype.removeEventListener = function(type, fn, capture) {
        this.f = f_remove;
        if(type == 'scroll' && typeof _ === 'function')
            fn = _.throttle(fn, 350);
        this.f(type, fn, capture);
    }

It overwrites the prototype for add/removeEventListener -> And if the event is a scroll event, it surrounds the Function fn with _.throttle().


问:
Trying to fix error on Google Sheets to Docs data merge
How can I fix this error?

The code was working well and then I added some more code for more functionality but now I can't get past this error.

Error: Too many changes applied before saving document. Please save changes in smaller batches using Document.saveAndClose(), then reopen the document with Document.openById().

Here is my code

```<code>function myFunction() {
  var docTemplateID = "1g87Ak-ms8Ctv1B4zAquGaBn55shBKFZi5VUoP0Fgfvg";
  var docFinalID = "19K9N2uuBV312FuW0dLQv0BD8wBZYvtJmJHsjbSlqgCc";
  var wsID = "12sS_0rZn5_OzOigB75gSkSR1i7NkW5bMqY99onIi3qY";

  var docTemplate = DocumentApp.openById(docTemplateID);
  var docFinal = DocumentApp.openById(docFinalID);
  var ws = SpreadsheetApp.openById(wsID).getSheetByName("SCRAPED22PROBATE7");

  var data = ws.getRange(2,1,3,4,5,6,7,ws.getLastRow()-1,7).getValues();

  var templateParagraphs = docTemplate.getBody().getParagraphs();

  docFinal.getBody().clear();

  data.forEach(function(r){
    createMailMerge(r[1],r[0],r[2],r[3],r[4],r[5],r[6],templateParagraphs,docFinal);
  });

}

function createMailMerge(first,decdname,last,address,city,state,zip,templateParagraphs,docFinal){
  templateParagraphs.forEach(function(p){
    var elType = p.getType();

    if(elType == "PARAGRAPH"){
    docFinal.getBody().appendParagraph(
      p
      .copy()
      .replaceText("{PRFirstName}",first)
      .replaceText("{DecdNamePulled}",decdname)
      .replaceText("{PRFirstMail}",first)
      .replaceText("{PRLastMail}",last)
      .replaceText("{PRAddressMail}",address)
      .replaceText("{PRCityMail}",city)
      .replaceText("{PRStateMail}",state)
      .replaceText("{PRZipMail}",zip)
    );
     docFinal.saveAndClose()
  } else if(elType == "LIST_ITEM"){
    docFinal.getBody().appendListItem(
      p
      .copy()
      .replaceText("{PRFirstName}",first)
      .replaceText("{DecdNamePulled}",decdname)
      .replaceText("{PRFirstMail}",first)
      .replaceText("{PRLastMail}",last)
      .replaceText("{PRAddressMail}",address)
      .replaceText("{PRCityMail}",city)
      .replaceText("{PRStateMail}",state)
      .replaceText("{PRZipMail}",zip)
    ).setGlyphType(DocumentApp.GlyphType.BULLET);
  }

  });

  docFinal.getBody().appendPageBreak();
}
</code>```

答:
This is wrong: var data = ws.getRange(2,1,3,4,5,6,7,ws.getLastRow()-1,7).getValues(); way too many parameters row,column,number of rows, number of columns

sheet.getRange()

Body:
How can I fix this error?

The code was working well and then I added some more code for more functionality but now I can't get past this error.

Error: Too many changes applied before saving document. Please save changes in smaller batches using Document.saveAndClose(), then reopen the document with Document.openById().

Here is my code

function myFunction() {
  var docTemplateID = "1g87Ak-ms8Ctv1B4zAquGaBn55shBKFZi5VUoP0Fgfvg";
  var docFinalID = "19K9N2uuBV312FuW0dLQv0BD8wBZYvtJmJHsjbSlqgCc";
  var wsID = "12sS_0rZn5_OzOigB75gSkSR1i7NkW5bMqY99onIi3qY";

  var docTemplate = DocumentApp.openById(docTemplateID);
  var docFinal = DocumentApp.openById(docFinalID);
  var ws = SpreadsheetApp.openById(wsID).getSheetByName("SCRAPED22PROBATE7");

  var data = ws.getRange(2,1,3,4,5,6,7,ws.getLastRow()-1,7).getValues();

  var templateParagraphs = docTemplate.getBody().getParagraphs();

  docFinal.getBody().clear();

  data.forEach(function(r){
    createMailMerge(r[1],r[0],r[2],r[3],r[4],r[5],r[6],templateParagraphs,docFinal);
  });

}

function createMailMerge(first,decdname,last,address,city,state,zip,templateParagraphs,docFinal){
  templateParagraphs.forEach(function(p){
    var elType = p.getType();

    if(elType == "PARAGRAPH"){
    docFinal.getBody().appendParagraph(
      p
      .copy()
      .replaceText("{PRFirstName}",first)
      .replaceText("{DecdNamePulled}",decdname)
      .replaceText("{PRFirstMail}",first)
      .replaceText("{PRLastMail}",last)
      .replaceText("{PRAddressMail}",address)
      .replaceText("{PRCityMail}",city)
      .replaceText("{PRStateMail}",state)
      .replaceText("{PRZipMail}",zip)
    );
     docFinal.saveAndClose()
  } else if(elType == "LIST_ITEM"){
    docFinal.getBody().appendListItem(
      p
      .copy()
      .replaceText("{PRFirstName}",first)
      .replaceText("{DecdNamePulled}",decdname)
      .replaceText("{PRFirstMail}",first)
      .replaceText("{PRLastMail}",last)
      .replaceText("{PRAddressMail}",address)
      .replaceText("{PRCityMail}",city)
      .replaceText("{PRStateMail}",state)
      .replaceText("{PRZipMail}",zip)
    ).setGlyphType(DocumentApp.GlyphType.BULLET);
  }

  });

  docFinal.getBody().appendPageBreak();
}


问:
How to search a text contains or not in particular column that contain Json object using linq

I have a table that contains the column "FEEDDATA". In FEEDDATA column the values stored in json object. Now i want make a serach and fetch the data where "AuthorFirstName" key in FEEDDATA column have value "Lalit". I need to implement it in LINQ.
e.g f.FeedData.AuthorFirstName.contains("%Lal%")

In short: I need to implement search on the feedata column and fetch only those records in which key AuthorFirstName contains text "lal" .

Please help.

答:
Using general LINQ to SQL, you can use the Contain method to do a LIKE SQL search and find matching records:

```<code>var ans = db.Where(r => r.FEEDDATA.Contains("\"AuthorFirstName\":\"Lalit\""));
</code>```

Assuming the type of FEEDDATA is actually e.g. varchar and not a database specific special JSON type.

Body:
Using general LINQ to SQL, you can use the Contain method to do a LIKE SQL search and find matching records:

var ans = db.Where(r => r.FEEDDATA.Contains("\"AuthorFirstName\":\"Lalit\""));

Assuming the type of FEEDDATA is actually e.g. varchar and not a database specific special JSON type.


问:
How to write procedure which will loop the input line N times in TCL
looking for what could be the "proc_of_for_loop"

puts $fp [proc_of_for_loop abc[$i] 5]

output should be like,

```<code>abc0
abc1
abc2
abc3
abc4
abc5
</code>```

答:
The natural way of doing that in Tcl would be this:

```<code>proc n_range {varName from to body} {
    upvar 1 $varName var
    for {set var $from} {$var <= $to} {incr var} {
        uplevel 1 $body
    }
}

n_range i 0 5 {
    puts $fp "abc$i"
}
</code>```

The upvar and uplevel commands are a major part of the secret sauce of Tcl; they let you create your own control constructs in very little code.

Body:
looking for what could be the "proc_of_for_loop"

puts $fp [proc_of_for_loop abc[$i] 5]

output should be like,

abc0
abc1
abc2
abc3
abc4
abc5

Body:
The natural way of doing that in Tcl would be this:

proc n_range {varName from to body} {
    upvar 1 $varName var
    for {set var $from} {$var <= $to} {incr var} {
        uplevel 1 $body
    }
}

n_range i 0 5 {
    puts $fp "abc$i"
}

The upvar and uplevel commands are a major part of the secret sauce of Tcl; they let you create your own control constructs in very little code.


问:
LINQ Aggregate algorithm explained
This might sound lame, but  I have not been able to find a really good explanation of Aggregate.

Good means short, descriptive, comprehensive with a small and clear example.

答:
The easiest-to-understand definition of Aggregate is that it performs an operation on each element of the list taking into account the operations that have gone before. That is to say it performs the action on the first and second element and carries the result forward. Then it operates on the previous result and the third element and carries forward. etc.

Example 1. Summing numbers

```<code>var nums = new[]{1,2,3,4};
var sum = nums.Aggregate( (a,b) => a + b);
Console.WriteLine(sum); // output: 10 (1+2+3+4)
</code>```

This adds 1 and 2 to make 3. Then adds 3 (result of previous) and 3 (next element in sequence) to make 6. Then adds 6 and 4 to make 10.

Example 2. create a csv from an array of strings

```<code>var chars = new []{"a","b","c","d"};
var csv = chars.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(csv); // Output a,b,c,d
</code>```

This works in much the same way. Concatenate a a comma and b to make a,b. Then concatenates a,b  with a comma and c to make a,b,c. and so on.

Example 3. Multiplying numbers using a seed

For completeness, there is an overload of Aggregate which takes a seed value.

```<code>var multipliers = new []{10,20,30,40};
var multiplied = multipliers.Aggregate(5, (a,b) => a * b);
Console.WriteLine(multiplied); //Output 1200000 ((((5*10)*20)*30)*40)
</code>```

Much like the above examples, this starts with a value of 5 and multiplies it by the first element of the sequence 10 giving a result of 50. This result is carried forward and multiplied by the next number in the sequence 20 to give a result of 1000. This continues through the remaining 2 element of the sequence.

Live examples: http://rextester.com/ZXZ64749

Docs: http://msdn.microsoft.com/en-us/library/bb548651.aspx

Addendum

Example 2, above, uses string concatenation to create a list of values separated by a comma. This is a simplistic way to explain the use of Aggregate which was the intention of this answer. However, if using this technique to actually create a large amount of comma separated data, it would be more appropriate to use a StringBuilder, and this is entirely compatible with Aggregate using the seeded overload to initiate the StringBuilder.

```<code>var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate(new StringBuilder(), (a,b) => {
    if(a.Length>0)
        a.Append(",");
    a.Append(b);
    return a;
});
Console.WriteLine(csv);
</code>```

Updated example: http://rextester.com/YZCVXV6464

ContentLicense: CC BY-SA 3.0

Title: LINQ Aggregate algorithm explained

Body:
The easiest-to-understand definition of Aggregate is that it performs an operation on each element of the list taking into account the operations that have gone before. That is to say it performs the action on the first and second element and carries the result forward. Then it operates on the previous result and the third element and carries forward. etc.

Example 1. Summing numbers

var nums = new[]{1,2,3,4};
var sum = nums.Aggregate( (a,b) => a + b);
Console.WriteLine(sum); // output: 10 (1+2+3+4)

This adds 1 and 2 to make 3. Then adds 3 (result of previous) and 3 (next element in sequence) to make 6. Then adds 6 and 4 to make 10.

Example 2. create a csv from an array of strings

var chars = new []{"a","b","c","d"};
var csv = chars.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(csv); // Output a,b,c,d

This works in much the same way. Concatenate a a comma and b to make a,b. Then concatenates a,b  with a comma and c to make a,b,c. and so on.

Example 3. Multiplying numbers using a seed

For completeness, there is an overload of Aggregate which takes a seed value.

var multipliers = new []{10,20,30,40};
var multiplied = multipliers.Aggregate(5, (a,b) => a * b);
Console.WriteLine(multiplied); //Output 1200000 ((((5*10)*20)*30)*40)

Much like the above examples, this starts with a value of 5 and multiplies it by the first element of the sequence 10 giving a result of 50. This result is carried forward and multiplied by the next number in the sequence 20 to give a result of 1000. This continues through the remaining 2 element of the sequence.

Live examples: http://rextester.com/ZXZ64749

Docs: http://msdn.microsoft.com/en-us/library/bb548651.aspx

Addendum

Example 2, above, uses string concatenation to create a list of values separated by a comma. This is a simplistic way to explain the use of Aggregate which was the intention of this answer. However, if using this technique to actually create a large amount of comma separated data, it would be more appropriate to use a StringBuilder, and this is entirely compatible with Aggregate using the seeded overload to initiate the StringBuilder.

var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate(new StringBuilder(), (a,b) => {
    if(a.Length>0)
        a.Append(",");
    a.Append(b);
    return a;
});
Console.WriteLine(csv);

Updated example: http://rextester.com/YZCVXV6464


问:
What is the best lossless way to scale up a barcode image in c#
I've come across this problem many times over the years and still live in hope that there is an easy way to do this that I have missed.
I work with barcodes a lot.  They are usually made of black dots or lines on a white background.  Barcode readers generally work faster and more accurately when the edges are crisp and then size of the lines or dots are precise.

Most barcode generation algorithms will give you a compact barcode usually with the smallest element size being one pixel.  A typical QR code could fit in a 21 x 21 grid.  This would be too small to see if printed pixel to pixel on most printers and would typically be scaled up.  The result of scaling it up depends on the method used and although sometimes you are given a choice, often you have no options that make the image suitable.  Even printing directly will often give you expected gray artefacts or forms of dithering.  The most consistent way I have found is to scale the images before they are use daily in other places such as Microsoft Word, lightburn and a few others I use that still give me a headache.

Below I will go through what I have tried and show the results.  I am limiting this to bitmaps only because using vectors here is not something I need on my current project.

My current best resolution is not pretty, it is slow and although I could improve the speed by locking the bits in the bitmap, I am hoping someone has a really simple answer that I had totally missed on my search again this time.

Here is an image of a simple QR code blown up in GIMP.

The problem is, if it is scaled up, it'll often end up looking like this:

Below I created a small test program to go through all the different modes I know of and then generate a matrix of images which I have reproduced below.  The version I currently use is Mode 99 which involves inspecting each pixel and drawing a square.

Does anyone have any better ideas?

```<code>using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace PSWpfCommon.Images
{
    public partial class WPFImageHelper
    {

        public class Test
        {
            public int smode = 0;
            public int imode = 0;
            public int mode = 0;
            public string title = "";
            public Test(int s, int i, int m, string t)
            {
                smode = s;
                imode = i;
                mode = m;
                title = t;
            }
        }

        public static Bitmap TestImage()
        {
            byte[] img =
             {
           0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44,
           0x52, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x08, 0x06, 0x00, 0x00, 0x00, 0xA9,
           0x17, 0xA5, 0x96, 0x00, 0x00, 0x00, 0xCF, 0x49, 0x44, 0x41, 0x54, 0x38, 0xCB, 0x9D, 0x54,
           0x5B, 0x0E, 0xC3, 0x30, 0x08, 0xB3, 0xAB, 0xDC, 0xFF, 0xCA, 0xDE, 0xC7, 0xD4, 0x88, 0x7A,
           0x3C, 0xD2, 0x21, 0x55, 0xAD, 0x48, 0xA0, 0xC6, 0x80, 0x09, 0x40, 0x28, 0x4C, 0x12, 0x48,
           0xEE, 0x6F, 0x00, 0x20, 0xF9, 0xF0, 0x67, 0xB6, 0x62, 0x40, 0xB4, 0x98, 0xAC, 0x4A, 0x50,
           0xC5, 0x2D, 0x4F, 0xE2, 0x97, 0x23, 0xB2, 0xEE, 0xE7, 0x31, 0xEE, 0xC2, 0xA1, 0x75, 0x89,
           0xD3, 0xF2, 0x27, 0x73, 0x5E, 0x8F, 0x93, 0x56, 0x01, 0x53, 0xA2, 0xEC, 0x7C, 0x39, 0x2F,
           0x19, 0xCA, 0x58, 0x7A, 0xA4, 0xA0, 0x8A, 0xA3, 0x0E, 0x6A, 0x7A, 0x5B, 0xFE, 0x45, 0x12,
           0xF1, 0xF1, 0x44, 0x59, 0x73, 0xFC, 0x5E, 0x8C, 0x25, 0xF9, 0xED, 0xBE, 0xA4, 0x47, 0x49,
           0xDD, 0x18, 0x79, 0xF9, 0x25, 0xA7, 0xD9, 0xA6, 0x74, 0xE3, 0xE3, 0x48, 0x9D, 0xE3, 0x55,
           0xA1, 0x98, 0xB8, 0xCC, 0x16, 0xE4, 0xF6, 0x5F, 0xBE, 0xDF, 0x8E, 0x74, 0x42, 0x9F, 0x4D,
           0xC0, 0x0F, 0xA7, 0xFE, 0x76, 0x14, 0x5D, 0x65, 0xDB, 0x3F, 0xA9, 0x54, 0xC7, 0x9D, 0x8B,
           0xCD, 0x7D, 0x3E, 0xAA, 0xD4, 0x24, 0x77, 0x99, 0x7F, 0x54, 0xA9, 0xAA, 0x69, 0x7E, 0x3F,
           0xCE, 0xEA, 0xFA, 0x67, 0x9B, 0x3A, 0x2A, 0x24, 0x9D, 0x49, 0x9F, 0x23, 0x99, 0x64, 0x71,
           0x9D, 0xA8, 0x51, 0xC5, 0x6F, 0x36, 0x21, 0x5B, 0xF9, 0x3B, 0x95, 0xAA, 0x1A, 0x52, 0xAD,
           0xB1, 0x24, 0x7C, 0x00, 0x22, 0x8E, 0xDE, 0x4C, 0xC4, 0x8F, 0x11, 0x7F, 0x00, 0x00, 0x00,
           0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82,
             };

            Bitmap qr;
            using (var ms = new MemoryStream(img))
            {
                qr = new Bitmap(ms);
            }

            int factor = 4;

            var l = new List<Test>();
            for (int i = 0; i <= 7; i++)
                for (int s = 0; s <= 4; s++)
                    l.Add(new Test(s, i, 0, $"s={s} i={i}"));

            l.Add(new Test(2, 8, 99, $"Mode 99"));

            Bitmap fullimage = new Bitmap(((qr.Width * factor) + 20) * 5, ((qr.Height * factor) + 20) * 9);

            fullimage.SetResolution(72, 72);
            var font = new Font("Arial", 10);

            using (var grPhoto = Graphics.FromImage(fullimage))
            using (var blackbrush = new SolidBrush(System.Drawing.Color.Black))
            using (var whitebrush = new SolidBrush(System.Drawing.Color.White))
            {
                grPhoto.InterpolationMode = InterpolationMode.High;

                grPhoto.FillRectangle(whitebrush, 0, 0, fullimage.Width, fullimage.Height);

                foreach (var t in l)
                {
                    var newqr = GrowImage(qr, factor: 4, mode: t.mode, imode: t.imode, smode: t.smode);

                    grPhoto.DrawImage(newqr,
                        t.smode * ((qr.Width * factor) + 20),
                        t.imode * ((qr.Height * factor) + 20));
                    grPhoto.DrawString(t.title, font, blackbrush,
                        t.smode * ((qr.Width * factor) + 20),
                        (t.imode + 1) * ((qr.Height * factor) + 20) - 20);

                }
            }

            fullimage.Save(@"c:\temp\newqr.png", ImageFormat.Png);

            return null;
        }

        public static Bitmap GrowImage(Bitmap im, int factor = 4, int mode = 1, int imode = 0, int smode = 0, int border = 2)
        {
            bool translate = true;

            var bmPhoto = new Bitmap(im.Width * factor + 2 * border, im.Height * factor + border * 2, PixelFormat.Format24bppRgb);

            bmPhoto.SetResolution(72, 72);

            using (var grPhoto = Graphics.FromImage(bmPhoto))
            using (var blackbrush = new SolidBrush(System.Drawing.Color.Black))
            using (var whitebrush = new SolidBrush(System.Drawing.Color.White))
            {
                grPhoto.FillRectangle(whitebrush, 0, 0, bmPhoto.Width, bmPhoto.Height);

                switch (smode)
                {
                    case 0:
                        grPhoto.SmoothingMode = SmoothingMode.Default;
                        break;
                    case 1:
                        grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
                        break;
                    case 2:
                        grPhoto.SmoothingMode = SmoothingMode.HighQuality;
                        break;
                    case 3:
                        grPhoto.SmoothingMode = SmoothingMode.HighSpeed;
                        break;
                    case 4:
                        grPhoto.SmoothingMode = SmoothingMode.None;
                        break;
                    default:
                        break;
                }
                switch (imode)
                {
                    case 0:
                        grPhoto.InterpolationMode = InterpolationMode.Default;
                        break;
                    case 1:
                        grPhoto.InterpolationMode = InterpolationMode.Bicubic;
                        break;
                    case 2:
                        grPhoto.InterpolationMode = InterpolationMode.Bilinear;
                        break;
                    case 3:
                        grPhoto.InterpolationMode = InterpolationMode.High;
                        break;
                    case 4:
                        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        break;
                    case 5:
                        grPhoto.InterpolationMode = InterpolationMode.HighQualityBilinear;
                        break;
                    case 6:
                        grPhoto.InterpolationMode = InterpolationMode.Low;
                        break;
                    case 7:
                        grPhoto.InterpolationMode = InterpolationMode.NearestNeighbor;
                        break;
                    default:
                        break;
                }

                switch (mode)
                {
                    case 99:
                        // These are what worked best for me...
                        grPhoto.SmoothingMode = SmoothingMode.None;
                        grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;

                        for (int x = 0; x < im.Width; x++)
                            for (int y = 0; y < im.Height; y++)
                            {
                                var g = im.GetPixel(x, y);
                                if (g.R < 120 && g.B < 120) // Just being really lazy here... if the pixel has not much blue and not much red I'll treat it as black
                                {
                                    grPhoto.FillRectangle(blackbrush, border + factor * x, border + factor * y, factor, factor);

                                }
                            }
                        translate = false;
                        break;
                    default:
                        break;
                }

                if (translate) // If we used mode 99, don't draw the image
                    grPhoto.DrawImage(im, new System.Drawing.Rectangle(border, border, im.Width * factor, im.Height * factor), 0, 0, im.Width, im.Height, System.Drawing.GraphicsUnit.Pixel);
            }

            return bmPhoto;
        }
    }
}

</code>```

答:
In the first place, I find it weird that your generators don't just allow you to specify the cell size/modulus. Double check the manual(s).

To obtain what you want from single pixel cells/modulus, you can use any image magnification function with a size that is an exact multiple of your original image, using the nearest neighbor resampling rule, and no other.

If you can't find such a function, it is an easy matter to write one that copies an image while replicating every pixel as an NxN square (under lockbits).

Body:
I've come across this problem many times over the years and still live in hope that there is an easy way to do this that I have missed.
I work with barcodes a lot.  They are usually made of black dots or lines on a white background.  Barcode readers generally work faster and more accurately when the edges are crisp and then size of the lines or dots are precise.

Most barcode generation algorithms will give you a compact barcode usually with the smallest element size being one pixel.  A typical QR code could fit in a 21 x 21 grid.  This would be too small to see if printed pixel to pixel on most printers and would typically be scaled up.  The result of scaling it up depends on the method used and although sometimes you are given a choice, often you have no options that make the image suitable.  Even printing directly will often give you expected gray artefacts or forms of dithering.  The most consistent way I have found is to scale the images before they are use daily in other places such as Microsoft Word, lightburn and a few others I use that still give me a headache.

Below I will go through what I have tried and show the results.  I am limiting this to bitmaps only because using vectors here is not something I need on my current project.

My current best resolution is not pretty, it is slow and although I could improve the speed by locking the bits in the bitmap, I am hoping someone has a really simple answer that I had totally missed on my search again this time.

Here is an image of a simple QR code blown up in GIMP.

The problem is, if it is scaled up, it'll often end up looking like this:

Below I created a small test program to go through all the different modes I know of and then generate a matrix of images which I have reproduced below.  The version I currently use is Mode 99 which involves inspecting each pixel and drawing a square.

Does anyone have any better ideas?

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace PSWpfCommon.Images
{
    public partial class WPFImageHelper
    {

        public class Test
        {
            public int smode = 0;
            public int imode = 0;
            public int mode = 0;
            public string title = "";
            public Test(int s, int i, int m, string t)
            {
                smode = s;
                imode = i;
                mode = m;
                title = t;
            }
        }

        public static Bitmap TestImage()
        {
            byte[] img =
             {
           0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44,
           0x52, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x08, 0x06, 0x00, 0x00, 0x00, 0xA9,
           0x17, 0xA5, 0x96, 0x00, 0x00, 0x00, 0xCF, 0x49, 0x44, 0x41, 0x54, 0x38, 0xCB, 0x9D, 0x54,
           0x5B, 0x0E, 0xC3, 0x30, 0x08, 0xB3, 0xAB, 0xDC, 0xFF, 0xCA, 0xDE, 0xC7, 0xD4, 0x88, 0x7A,
           0x3C, 0xD2, 0x21, 0x55, 0xAD, 0x48, 0xA0, 0xC6, 0x80, 0x09, 0x40, 0x28, 0x4C, 0x12, 0x48,
           0xEE, 0x6F, 0x00, 0x20, 0xF9, 0xF0, 0x67, 0xB6, 0x62, 0x40, 0xB4, 0x98, 0xAC, 0x4A, 0x50,
           0xC5, 0x2D, 0x4F, 0xE2, 0x97, 0x23, 0xB2, 0xEE, 0xE7, 0x31, 0xEE, 0xC2, 0xA1, 0x75, 0x89,
           0xD3, 0xF2, 0x27, 0x73, 0x5E, 0x8F, 0x93, 0x56, 0x01, 0x53, 0xA2, 0xEC, 0x7C, 0x39, 0x2F,
           0x19, 0xCA, 0x58, 0x7A, 0xA4, 0xA0, 0x8A, 0xA3, 0x0E, 0x6A, 0x7A, 0x5B, 0xFE, 0x45, 0x12,
           0xF1, 0xF1, 0x44, 0x59, 0x73, 0xFC, 0x5E, 0x8C, 0x25, 0xF9, 0xED, 0xBE, 0xA4, 0x47, 0x49,
           0xDD, 0x18, 0x79, 0xF9, 0x25, 0xA7, 0xD9, 0xA6, 0x74, 0xE3, 0xE3, 0x48, 0x9D, 0xE3, 0x55,
           0xA1, 0x98, 0xB8, 0xCC, 0x16, 0xE4, 0xF6, 0x5F, 0xBE, 0xDF, 0x8E, 0x74, 0x42, 0x9F, 0x4D,
           0xC0, 0x0F, 0xA7, 0xFE, 0x76, 0x14, 0x5D, 0x65, 0xDB, 0x3F, 0xA9, 0x54, 0xC7, 0x9D, 0x8B,
           0xCD, 0x7D, 0x3E, 0xAA, 0xD4, 0x24, 0x77, 0x99, 0x7F, 0x54, 0xA9, 0xAA, 0x69, 0x7E, 0x3F,
           0xCE, 0xEA, 0xFA, 0x67, 0x9B, 0x3A, 0x2A, 0x24, 0x9D, 0x49, 0x9F, 0x23, 0x99, 0x64, 0x71,
           0x9D, 0xA8, 0x51, 0xC5, 0x6F, 0x36, 0x21, 0x5B, 0xF9, 0x3B, 0x95, 0xAA, 0x1A, 0x52, 0xAD,
           0xB1, 0x24, 0x7C, 0x00, 0x22, 0x8E, 0xDE, 0x4C, 0xC4, 0x8F, 0x11, 0x7F, 0x00, 0x00, 0x00,
           0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82,
             };

            Bitmap qr;
            using (var ms = new MemoryStream(img))
            {
                qr = new Bitmap(ms);
            }

            int factor = 4;

            var l = new List<Test>();
            for (int i = 0; i <= 7; i++)
                for (int s = 0; s <= 4; s++)
                    l.Add(new Test(s, i, 0, $"s={s} i={i}"));

            l.Add(new Test(2, 8, 99, $"Mode 99"));

            Bitmap fullimage = new Bitmap(((qr.Width * factor) + 20) * 5, ((qr.Height * factor) + 20) * 9);

            fullimage.SetResolution(72, 72);
            var font = new Font("Arial", 10);

            using (var grPhoto = Graphics.FromImage(fullimage))
            using (var blackbrush = new SolidBrush(System.Drawing.Color.Black))
            using (var whitebrush = new SolidBrush(System.Drawing.Color.White))
            {
                grPhoto.InterpolationMode = InterpolationMode.High;

                grPhoto.FillRectangle(whitebrush, 0, 0, fullimage.Width, fullimage.Height);

                foreach (var t in l)
                {
                    var newqr = GrowImage(qr, factor: 4, mode: t.mode, imode: t.imode, smode: t.smode);

                    grPhoto.DrawImage(newqr,
                        t.smode * ((qr.Width * factor) + 20),
                        t.imode * ((qr.Height * factor) + 20));
                    grPhoto.DrawString(t.title, font, blackbrush,
                        t.smode * ((qr.Width * factor) + 20),
                        (t.imode + 1) * ((qr.Height * factor) + 20) - 20);

                }
            }

            fullimage.Save(@"c:\temp\newqr.png", ImageFormat.Png);

            return null;
        }

        public static Bitmap GrowImage(Bitmap im, int factor = 4, int mode = 1, int imode = 0, int smode = 0, int border = 2)
        {
            bool translate = true;

            var bmPhoto = new Bitmap(im.Width * factor + 2 * border, im.Height * factor + border * 2, PixelFormat.Format24bppRgb);

            bmPhoto.SetResolution(72, 72);

            using (var grPhoto = Graphics.FromImage(bmPhoto))
            using (var blackbrush = new SolidBrush(System.Drawing.Color.Black))
            using (var whitebrush = new SolidBrush(System.Drawing.Color.White))
            {
                grPhoto.FillRectangle(whitebrush, 0, 0, bmPhoto.Width, bmPhoto.Height);

                switch (smode)
                {
                    case 0:
                        grPhoto.SmoothingMode = SmoothingMode.Default;
                        break;
                    case 1:
                        grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
                        break;
                    case 2:
                        grPhoto.SmoothingMode = SmoothingMode.HighQuality;
                        break;
                    case 3:
                        grPhoto.SmoothingMode = SmoothingMode.HighSpeed;
                        break;
                    case 4:
                        grPhoto.SmoothingMode = SmoothingMode.None;
                        break;
                    default:
                        break;
                }
                switch (imode)
                {
                    case 0:
                        grPhoto.InterpolationMode = InterpolationMode.Default;
                        break;
                    case 1:
                        grPhoto.InterpolationMode = InterpolationMode.Bicubic;
                        break;
                    case 2:
                        grPhoto.InterpolationMode = InterpolationMode.Bilinear;
                        break;
                    case 3:
                        grPhoto.InterpolationMode = InterpolationMode.High;
                        break;
                    case 4:
                        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        break;
                    case 5:
                        grPhoto.InterpolationMode = InterpolationMode.HighQualityBilinear;
                        break;
                    case 6:
                        grPhoto.InterpolationMode = InterpolationMode.Low;
                        break;
                    case 7:
                        grPhoto.InterpolationMode = InterpolationMode.NearestNeighbor;
                        break;
                    default:
                        break;
                }

                switch (mode)
                {
                    case 99:
                        // These are what worked best for me...
                        grPhoto.SmoothingMode = SmoothingMode.None;
                        grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;

                        for (int x = 0; x < im.Width; x++)
                            for (int y = 0; y < im.Height; y++)
                            {
                                var g = im.GetPixel(x, y);
                                if (g.R < 120 && g.B < 120) // Just being really lazy here... if the pixel has not much blue and not much red I'll treat it as black
                                {
                                    grPhoto.FillRectangle(blackbrush, border + factor * x, border + factor * y, factor, factor);

                                }
                            }
                        translate = false;
                        break;
                    default:
                        break;
                }

                if (translate) // If we used mode 99, don't draw the image
                    grPhoto.DrawImage(im, new System.Drawing.Rectangle(border, border, im.Width * factor, im.Height * factor), 0, 0, im.Width, im.Height, System.Drawing.GraphicsUnit.Pixel);
            }

            return bmPhoto;
        }
    }
}


问:
Outlook add-in sync events
Developing an outlook add-in you can add buttons which for example allow you to add additional meta information to a meeting event. Assume you have an add-in that links events with an external system when user presses a button.

Now that is all fine but now the user can also delete the event and in this case you also want to delete it on your external system. Now there are no easy events you can just register to.

You seem to have the option to subscribe for event web-hooks on the graph api on the behalf of the user. However such a subscription has the maximum lifetime of 3 days. Alternatively you could also use the deltaAPI to detect potential deletion of calendar events.

But your add-in does only run when the user clicks a button and only then you could renew an event subscription or execute a delta query. But then you see that there exists also event based activation possibilities that you could consider. You could use it to renew web-hook event subscriptions if needed or execute delta-queries directly to detect changes. Now it seems event-based add-in is a special kind of add-in you cannot easily distributed as the docs state:

Important

Event-based add-ins are restricted to admin-managed deployments only.
For now, users can't get event-based add-ins from AppSource or in-app
Office Store. To learn more, refer to AppSource listing options for
your event-based Outlook add-in.

And even it does not pair easily with SSO which obviously you need because you need access-tokens to subscribe for web-hooks or execute delta queries.

So in this Microsoft office add-in world: What is the idea to react on deleted events? How is this possible in a feasible way? Right now it feels like fighting a crazy three feeted drunk dragon rolling in circles around a green stone (or imagine something else that does not make sense) with nothing more than a bendable pencil made of plastic.

答: Does your app need to be an addin? You can create a standalone app that uses Graph. Or you can create a COM (VSTO) addin (Windows only) - it will run every time Outlook is running and use events in the Outlook Object Model.</p>

Title: Outlook add-in sync events


问:
Find link in specific tags using python, beautiful soup and lambda functions
I have the following html and I am using bs4 beautiful soup in python 3 to extract all hrefs from links that are located inside a specific tag: . It should not be important if there might me more than one or no link nested in the . Furthermore, there would be another step where I filter out links that don't have the "base.html" ending.

```<code><article>
   <a href='link/base.html'>click me!</a>
</article>
...
<article>
   <a href='link2/base.html'>click me!</a>
</article>
...
<article>
   <a href='link3/base.html'>click me!</a>
</article>
</code>```

This is my code

```<code>page = bs4.BeautifulSoup(source, 'html.parser')

articles = page.find_all(name="article")

article_links = map(lambda article: article.a, articles)

article_links = map(lambda tag: tag.get('href'), article_links)

article_links = filter(lambda link: 'base.html' in link, article_links)

article_links = map(lambda link: url + link, article_links)
</code>```

However, this results in an

AttributeError: 'NoneType' object has no attribute 'get''

at the .get('href') part in line 4. Other variations result in different errors. It needs to be lambda functions. Preferably, I would also like to combine the first two lambda functions into one.

答:
Not sure why to use lambda, so just in case select your targets more specific with css selectors and iterate result set with list comprehension:

```<code>[url+a['href'] for a in page.select('article a[href*="base.html"]')]
</code>```

Example

```<code>from bs4 import BeautifulSoup

url = 'http://www.example.com/'
html = '''<article>
   <a href='link/base.html'>click me!</a>
</article>
...
<article>
   <a href='link2/base.html'>click me!</a>
</article>
...
<article>
   <a href='link3/base.html'>click me!</a>
</article>'''

page = BeautifulSoup(html, 'html.parser')

[url+a['href'] for a in page.select('article a[href*="base.html"]')]
</code>```

Output

```<code>['http://www.example.com/link/base.html',
 'http://www.example.com/link2/base.html',
 'http://www.example.com/link3/base.html']
</code>```

Body:
I have the following html and I am using bs4 beautiful soup in python 3 to extract all hrefs from links that are located inside a specific tag: . It should not be important if there might me more than one or no link nested in the . Furthermore, there would be another step where I filter out links that don't have the "base.html" ending.

   click me!

...

   click me!

...

   click me!

This is my code

page = bs4.BeautifulSoup(source, 'html.parser')

articles = page.find_all(name="article")

article_links = map(lambda article: article.a, articles)

article_links = map(lambda tag: tag.get('href'), article_links)

article_links = filter(lambda link: 'base.html' in link, article_links)

article_links = map(lambda link: url + link, article_links)

However, this results in an

AttributeError: 'NoneType' object has no attribute 'get''

at the .get('href') part in line 4. Other variations result in different errors. It needs to be lambda functions. Preferably, I would also like to combine the first two lambda functions into one.

Body:
Not sure why to use lambda, so just in case select your targets more specific with css selectors and iterate result set with list comprehension:

[url+a['href'] for a in page.select('article a[href*="base.html"]')]

Example

from bs4 import BeautifulSoup

url = 'http://www.example.com/'
html = '''<article>
   <a href='link/base.html'>click me!</a>
</article>
...
<article>
   <a href='link2/base.html'>click me!</a>
</article>
...
<article>
   <a href='link3/base.html'>click me!</a>
</article>'''

page = BeautifulSoup(html, 'html.parser')

[url+a['href'] for a in page.select('article a[href*="base.html"]')]

Output

['http://www.example.com/link/base.html',
 'http://www.example.com/link2/base.html',
 'http://www.example.com/link3/base.html']


问:
Closure containing a declaration cannot be used with function builder 'ViewBuilder'
I cant declare a variable inside swift ui view block</p>

```<code> var body: some View {
     let isHuman = false
     Text("Levels \(isHuman)")
 }
</code>```

答:
When SwiftUI was first released (in 2019), the Swift language didn't allow local declarations (like let isHuman = false) inside what were then called “function builders”. However, function builders evolved into what are now called “result builders” and do support local declarations as of Swift 5.4.

This behavior is documented in SE-0289 Result Builders:

Declaration statements

Local declarations are left alone by the transformation. This allows developers to factor out subexpressions freely to clarify their code, without affecting the result builder transformation.

Body:
I cant declare a variable inside swift ui view block

 var body: some View {
     let isHuman = false
     Text("Levels \(isHuman)")
 }


问:
Item Counter with oval/elipse shape in Flutter
What I'm trying to do is make a counter in Flutter which will be in this shape:

I'm fairly new regarding flutter and dart so I have tried to put this element inside of a Card but yeah I faced some issues due to overflow and it would be great if someone could give me a hint or point me to the right direction.

Here is my code for counter:

```<code>Card(child:Row(
        children: <Widget>[
           IconButton(icon:Icon(Icons.remove),onPressed: ()=>setState(()=>_itemCount--)),
           Text(_itemCount.toString()),
             IconButton(icon:Icon(Icons.add),onPressed: ()=>setState(()=>_itemCount++))
        ],
      ),);
</code>```

Any help would be great, thanks in advance :)

答:
Create a container and add decoration to it.  Then inside the container use a row widget. In row use Iconbutton and text .</p>
```<code> Container(
   padding : EdgeInsets.all(7),
    decoration:BoxDecoration(
      borderRadius: BorderRadius.circular(10),
      color: Colors.grey,
     ),
     child: Row(
      mainAxisSize: MainAxisSize.min,
       children:[
          IconButton(.....),
          Text(......),
          IconButton(......),
       ]
     )
</code>```

Body:
What I'm trying to do is make a counter in Flutter which will be in this shape:

I'm fairly new regarding flutter and dart so I have tried to put this element inside of a Card but yeah I faced some issues due to overflow and it would be great if someone could give me a hint or point me to the right direction.

Here is my code for counter:

Card(child:Row(
        children: <Widget>[
           IconButton(icon:Icon(Icons.remove),onPressed: ()=>setState(()=>_itemCount--)),
           Text(_itemCount.toString()),
             IconButton(icon:Icon(Icons.add),onPressed: ()=>setState(()=>_itemCount++))
        ],
      ),);

Any help would be great, thanks in advance :)

Body:
Create a container and add decoration to it.  Then inside the container use a row widget. In row use Iconbutton and text .

 Container(
   padding : EdgeInsets.all(7),
    decoration:BoxDecoration(
      borderRadius: BorderRadius.circular(10),
      color: Colors.grey,
     ),
     child: Row(
      mainAxisSize: MainAxisSize.min,
       children:[
          IconButton(.....),
          Text(......),
          IconButton(......),
       ]
     )


问:
Why does a session variable have to be serializable?
When trying to store a List variable of custom objects

session.setAttribute is complaining that’s the variable is not serializable.

答:
Since you want to access the model in different request scope, you need to store it in http session. According to the requirement of JPA entity class, which is
involved in http session, has to implement the  Serializable interface.</p>


问:
Unordered F# AsyncSeq.mapParallel with throttling
I'm using F# and have an AsyncSeq<Async<'t>>. Each item will take a varying amount of time to process and does I/O that's rate-limited.

I want to run all the operations in parallel and then pass them down the chain as an AsyncSeq<'t> so I can perform further manipulations on them and ultimately AsyncSeq.fold them into a final outcome.

The following AsyncSeq operations almost meet my needs:

mapAsyncParallel - does the parallelism, but it's unconstrained, (and I don't need the order preserved)

iterAsyncParallelThrottled - parallel and has a max degree of parallelism but doesn't let me return results (and I don't need the order preserved)

What I really need is like a mapAsyncParallelThrottled. But, to be more precise, really the operation would be entitled mapAsyncParallelThrottledUnordered.

Things I'm considering:

use mapAsyncParallel but use a Semaphore within the function to constrain the parallelism myself, which is probably not going to be optimal in terms of concurrency, and due to buffering the results to reorder them.

use iterAsyncParallelThrottled and do some ugly folding of the results into an accumulator as they arrive guarded by a lock kinda like this - but I don't need the ordering so it won't be optimal.

build what I need by enumerating the source and emitting results via AsyncSeqSrc like this. I'd probably have a set of Async.StartAsTask tasks in flight and start more after each Task.WaitAny gives me something to AsyncSeqSrc.put until I reach the maxDegreeOfParallelism

Surely I'm missing a simple answer and there's a better way?

Failing that, would love someone to sanity check my option 3 in either direction!

I'm open to using AsyncSeq.toAsyncEnum and then use an IAsyncEnumerable way of achieving the same outcome if that exists, though ideally without getting into TPL DataFlow or RX land if it can be avoided (I've done extensive SO searching for that without results...).

答:
If I'm understanding your requirements then something like this will work. It effectively combines the iter unordered with a channel to allow a mapping instead.

```<code>let mapAsyncParallelBoundedUnordered boundedAmount (mapper: 't -> Async<_>) source = asyncSeq {
    let! ct = Async.CancellationToken
    let channel = Channel.CreateUnbounded()

    let! _ =
        async {
            do!
                source
                |> AsyncSeq.iterAsyncParallelThrottled boundedAmount (fun s -> async {
                    let! orderChild = mapper s
                    do! channel.Writer.WriteAsync(orderChild, ct)
                })

            channel.Writer.Complete()
        }
        |> Async.StartChild

    for item in channel.Reader.ReadAllAsync(ct) |> AsyncSeq.ofAsyncEnum do
        let! toReturn = item
        yield toReturn
}
</code>```

Also with a little bit of variation of the above (e.g. child tasks) you can make it ordered and parallelism bounded.

```<code>let mapAsyncParallelBounded boundedAmount mapper source = asyncSeq {
    let! ct = Async.CancellationToken
    let channel = Channel.CreateBounded(BoundedChannelOptions(boundedAmount))

    let! _ =
        source
        |> AsyncSeq.iterAsync (fun s -> async {
            let! orderChild = mapper s |> Async.StartChild
            do! channel.Writer.WriteAsync(orderChild, ct)
        })
        |> Async.StartChild

    let! ct = Async.CancellationToken
    for item in channel.Reader.ReadAllAsync(ct) |> AsyncSeq.ofAsyncEnum do
        let! toReturn = item
        yield toReturn
}
</code>```

Body:
If I'm understanding your requirements then something like this will work. It effectively combines the iter unordered with a channel to allow a mapping instead.

let mapAsyncParallelBoundedUnordered boundedAmount (mapper: 't -> Async<_>) source = asyncSeq {
    let! ct = Async.CancellationToken
    let channel = Channel.CreateUnbounded()

    let! _ =
        async {
            do!
                source
                |> AsyncSeq.iterAsyncParallelThrottled boundedAmount (fun s -> async {
                    let! orderChild = mapper s
                    do! channel.Writer.WriteAsync(orderChild, ct)
                })

            channel.Writer.Complete()
        }
        |> Async.StartChild

    for item in channel.Reader.ReadAllAsync(ct) |> AsyncSeq.ofAsyncEnum do
        let! toReturn = item
        yield toReturn
}

Also with a little bit of variation of the above (e.g. child tasks) you can make it ordered and parallelism bounded.

let mapAsyncParallelBounded boundedAmount mapper source = asyncSeq {
    let! ct = Async.CancellationToken
    let channel = Channel.CreateBounded(BoundedChannelOptions(boundedAmount))

    let! _ =
        source
        |> AsyncSeq.iterAsync (fun s -> async {
            let! orderChild = mapper s |> Async.StartChild
            do! channel.Writer.WriteAsync(orderChild, ct)
        })
        |> Async.StartChild

    let! ct = Async.CancellationToken
    for item in channel.Reader.ReadAllAsync(ct) |> AsyncSeq.ofAsyncEnum do
        let! toReturn = item
        yield toReturn
}


问:
JavaFx changing Label text color conditionally
I'm trying to change the color and text of a Label conditionally.

The text change works, but the color change does not.

I get an error:

```<code>The method setFill(Color) is undefined for the type When.StringConditionBuilder
</code>```

Code snippet:

```<code>assessmentLabel.textProperty().bind(
    new When(alcoholPercentageField.textProperty().greaterThanOrEqualTo("5"))
        .then("Be careful").setFill(Color.RED)
        .otherwise("Smart choice").setFill(Color.GREEN)
);
</code>```

Any way to do this?

答:
Use a change listener, not a binding

You are trying to use a single bind to change multiple target properties. You can’t do that.

You could create multiple bindings to change multiple properties, but I wouldn’t advise that.

Instead, place a change listener on the property you wish to listen to (in this case alcoholPercentageField.textProperty()) and in the code block of the listener, check the status of the new value and update all related properties (in this case the assessment label text and fill).

Aside

Text comparison of numeric values is not a good idea, even if might work in some single-digit cases.  Instead, you should convert the text to a number to compare it with another number.

Use CSS and style classes rather than setting fills directly.

this can be more complex and unnecessary for some applications, so evaluate this on a case-by-case basis.

When using bindings, always check to see if you can make use of the helper functions in the Bindings class, such as Bindings.when().

It is often better and more fluent and well tested to use the Bindings API rather than directly creating binding expressions using constructs such as When.

Simple Solution

Demonstrates use of a change listener to change multiple properties.

text and fill of a label.

Does not use a text formatter or style classes.

```<code>import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class SimpleChangeReaction extends Application {

    @Override
    public void start(Stage stage) {
        final TextField alcoholPercentageField = new TextField();
        final Label assessmentLabel = new Label();
        alcoholPercentageField.textProperty().addListener((observable, oldValue, newValue) -> {
            try {
                int intValue = Integer.parseInt(newValue);

                if (intValue > 5) {
                    assessmentLabel.setText("Be careful");
                    assessmentLabel.setTextFill(Color.RED);
                } else {
                    assessmentLabel.setText("Smart choice");
                    assessmentLabel.setTextFill(Color.GREEN);
                }
            } catch (NumberFormatException e) {
                assessmentLabel.setText("Invalid");
                assessmentLabel.setTextFill(Color.ORANGE);
            }
        });

        VBox layout = new VBox(10,
                alcoholPercentageField,
                assessmentLabel
        );
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

</code>```

More Complex Solution

Demonstrates use of a change listener to change multiple properties.

Uses a text formatter and style classes.

This more complex solution is not necessary to demonstrate change listeners, it is just provided to show an alternate way of switching logic and UI based on user input.

output of the complex solution is the same as the simple solution.

the behavior of the complex solution differs from the simple solution in that it disallows invalid input from occurring.

```<code>import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.util.converter.IntegerStringConverter;

import java.util.Arrays;
import java.util.function.UnaryOperator;

public class ChangeReaction extends Application {

    @Override
    public void start(Stage stage) {
        final Style style = new Style();

        final TextField alcoholPercentageField = new TextField();
        final Label assessmentLabel = new Label();

        PositiveIntTextFormatterFactory formatterFactory = new PositiveIntTextFormatterFactory();
        TextFormatter<Integer> positiveIntFormatter = formatterFactory.createPositiveIntTextFormatter(0);
        alcoholPercentageField.setTextFormatter(positiveIntFormatter);

        positiveIntFormatter.valueProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue > 5) {
                assessmentLabel.setText("Be careful");
                style.getStatusStyleClassChooser().chooseStyleClass(
                        assessmentLabel,
                        Style.StatusStyleClassChoices.warning
                );
            } else {
                assessmentLabel.setText("Smart choice");
                style.getStatusStyleClassChooser().chooseStyleClass(
                        assessmentLabel,
                        Style.StatusStyleClassChoices.ok
                );
            }
        });

        VBox layout = new VBox(10,
                alcoholPercentageField,
                assessmentLabel
        );
        layout.setPadding(new Insets(10));

        Scene scene = new Scene(layout);
        scene.getStylesheets().add(Style.CSS);

        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

final class Style {
    public static final String CSS = """
            data:text/css,
            .label.ok {
                -fx-text-fill: green;
            }
            .label.warning {
                -fx-text-fill: red;
            }
            """;

    public enum StatusStyleClassChoices {
        ok, warning;
    };

    private final StyleClassChooser<StatusStyleClassChoices> statusStyleClassChooser = new StyleClassChooser<>(StatusStyleClassChoices.class);

    public StyleClassChooser<StatusStyleClassChoices> getStatusStyleClassChooser() {
        return statusStyleClassChooser;
    }
}

final class PositiveIntTextFormatterFactory {
    private static final String POSITIVE_INT_PATTERN = "([1-9][0-9]*)?";

    private final UnaryOperator<TextFormatter.Change> positiveIntFilter = change -> {
        String newText = change.getControlNewText();

        if (newText.matches(POSITIVE_INT_PATTERN) && newText.length() < 4) {
            return change;  // allow change
        }

        return null; // disallow change
    };

    private final StringConverter<Integer> positiveIntConverter = new IntegerStringConverter() {
        @Override
        public Integer fromString(String s) {
            if (s.isEmpty()) return 0 ;
            return super.fromString(s);
        }
    };

    public TextFormatter<Integer> createPositiveIntTextFormatter(int defaultValue) {
        return new TextFormatter<>(
                positiveIntConverter,
                defaultValue,
                positiveIntFilter
        );
    }
}

final class StyleClassChooser<T extends Enum<T>> {
    private final String[] choices;

    public StyleClassChooser(Class<T> styleclassEnum) {
        choices = Arrays.stream(styleclassEnum.getEnumConstants())
                .map(Enum::toString)
                .toArray(String[]::new);
    }

    public void chooseStyleClass(Node node, T styleClass) {
        node.getStyleClass().removeAll(choices);
        node.getStyleClass().add(styleClass.toString());
    }
}
</code>```

Body:
I'm trying to change the color and text of a Label conditionally.

The text change works, but the color change does not.

I get an error:

The method setFill(Color) is undefined for the type When.StringConditionBuilder

Code snippet:

assessmentLabel.textProperty().bind(
    new When(alcoholPercentageField.textProperty().greaterThanOrEqualTo("5"))
        .then("Be careful").setFill(Color.RED)
        .otherwise("Smart choice").setFill(Color.GREEN)
);

Any way to do this?

Body:
Use a change listener, not a binding

You are trying to use a single bind to change multiple target properties. You can’t do that.

You could create multiple bindings to change multiple properties, but I wouldn’t advise that.

Instead, place a change listener on the property you wish to listen to (in this case alcoholPercentageField.textProperty()) and in the code block of the listener, check the status of the new value and update all related properties (in this case the assessment label text and fill).

Aside

Text comparison of numeric values is not a good idea, even if might work in some single-digit cases.  Instead, you should convert the text to a number to compare it with another number.

Use CSS and style classes rather than setting fills directly.

this can be more complex and unnecessary for some applications, so evaluate this on a case-by-case basis.

When using bindings, always check to see if you can make use of the helper functions in the Bindings class, such as Bindings.when().

It is often better and more fluent and well tested to use the Bindings API rather than directly creating binding expressions using constructs such as When.

Simple Solution

Demonstrates use of a change listener to change multiple properties.

text and fill of a label.

Does not use a text formatter or style classes.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class SimpleChangeReaction extends Application {

    @Override
    public void start(Stage stage) {
        final TextField alcoholPercentageField = new TextField();
        final Label assessmentLabel = new Label();
        alcoholPercentageField.textProperty().addListener((observable, oldValue, newValue) -> {
            try {
                int intValue = Integer.parseInt(newValue);

                if (intValue > 5) {
                    assessmentLabel.setText("Be careful");
                    assessmentLabel.setTextFill(Color.RED);
                } else {
                    assessmentLabel.setText("Smart choice");
                    assessmentLabel.setTextFill(Color.GREEN);
                }
            } catch (NumberFormatException e) {
                assessmentLabel.setText("Invalid");
                assessmentLabel.setTextFill(Color.ORANGE);
            }
        });

        VBox layout = new VBox(10,
                alcoholPercentageField,
                assessmentLabel
        );
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

More Complex Solution

Demonstrates use of a change listener to change multiple properties.

Uses a text formatter and style classes.

This more complex solution is not necessary to demonstrate change listeners, it is just provided to show an alternate way of switching logic and UI based on user input.

output of the complex solution is the same as the simple solution.

the behavior of the complex solution differs from the simple solution in that it disallows invalid input from occurring.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.util.converter.IntegerStringConverter;

import java.util.Arrays;
import java.util.function.UnaryOperator;

public class ChangeReaction extends Application {

    @Override
    public void start(Stage stage) {
        final Style style = new Style();

        final TextField alcoholPercentageField = new TextField();
        final Label assessmentLabel = new Label();

        PositiveIntTextFormatterFactory formatterFactory = new PositiveIntTextFormatterFactory();
        TextFormatter<Integer> positiveIntFormatter = formatterFactory.createPositiveIntTextFormatter(0);
        alcoholPercentageField.setTextFormatter(positiveIntFormatter);

        positiveIntFormatter.valueProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue > 5) {
                assessmentLabel.setText("Be careful");
                style.getStatusStyleClassChooser().chooseStyleClass(
                        assessmentLabel,
                        Style.StatusStyleClassChoices.warning
                );
            } else {
                assessmentLabel.setText("Smart choice");
                style.getStatusStyleClassChooser().chooseStyleClass(
                        assessmentLabel,
                        Style.StatusStyleClassChoices.ok
                );
            }
        });

        VBox layout = new VBox(10,
                alcoholPercentageField,
                assessmentLabel
        );
        layout.setPadding(new Insets(10));

        Scene scene = new Scene(layout);
        scene.getStylesheets().add(Style.CSS);

        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

final class Style {
    public static final String CSS = """
            data:text/css,
            .label.ok {
                -fx-text-fill: green;
            }
            .label.warning {
                -fx-text-fill: red;
            }
            """;

    public enum StatusStyleClassChoices {
        ok, warning;
    };

    private final StyleClassChooser<StatusStyleClassChoices> statusStyleClassChooser = new StyleClassChooser<>(StatusStyleClassChoices.class);

    public StyleClassChooser<StatusStyleClassChoices> getStatusStyleClassChooser() {
        return statusStyleClassChooser;
    }
}

final class PositiveIntTextFormatterFactory {
    private static final String POSITIVE_INT_PATTERN = "([1-9][0-9]*)?";

    private final UnaryOperator<TextFormatter.Change> positiveIntFilter = change -> {
        String newText = change.getControlNewText();

        if (newText.matches(POSITIVE_INT_PATTERN) && newText.length() < 4) {
            return change;  // allow change
        }

        return null; // disallow change
    };

    private final StringConverter<Integer> positiveIntConverter = new IntegerStringConverter() {
        @Override
        public Integer fromString(String s) {
            if (s.isEmpty()) return 0 ;
            return super.fromString(s);
        }
    };

    public TextFormatter<Integer> createPositiveIntTextFormatter(int defaultValue) {
        return new TextFormatter<>(
                positiveIntConverter,
                defaultValue,
                positiveIntFilter
        );
    }
}

final class StyleClassChooser<T extends Enum<T>> {
    private final String[] choices;

    public StyleClassChooser(Class<T> styleclassEnum) {
        choices = Arrays.stream(styleclassEnum.getEnumConstants())
                .map(Enum::toString)
                .toArray(String[]::new);
    }

    public void chooseStyleClass(Node node, T styleClass) {
        node.getStyleClass().removeAll(choices);
        node.getStyleClass().add(styleClass.toString());
    }
}


问:
How to do deferred jobs in Node API (Express)
I have an API in Node with many endpoints. It works well but there is one that can have large requests run up to 1 hour of processing which can often break. I'm thinking of only sending back a url on a request where you can check the status of the request and then download it once it's ready. What would be the best way to handle a queue of jobs in Node for this?

Sample code below for the current endpoint

```<code>const router = express.Router();
const schema = joi.object().keys // This is a schema to validate the json input

router.post('/', async (req, res) => {
  let conn = await connect(); // Util method that connects to a Q/KDB server
  let request = req.body;

  joi.validate(request, schema, (err, _result) => {
    if (err) {
      res.status(400).send({ error: err['details'][0]['message'] });
    }
    else {
      let qRequest = buildRequest(request); // Util function to build request
      // Connect to Q/KDB server with node-q package and process request
      conn.k('api.process', qRequest, function(err, resp) {
        if (err) {
          log // Write to log
          res.status(400).send({ error: err['details'][0]['message']
        }
        else {
          res.status(200).send(resp);
        }
      });
    }
  });

});

</code>```

EDIT:
I have found that I basically just have to build a job queue with job ids corresponding to them. The package Bull seems to be good but I don't want to add another dependency such as Redis.

答:
Conceptually there are a couple ways to approach a problem like this:

You can return a jobID and let the client query that jobID on some recurring basis using a URL that contains the jobID until they get a result (this sounds like what you envisioned)

You can have the client connect a webSocket or socket.io connection to the server and when the result is done, the server can directly send the result over the websocket/socket.io connection.

You can use Server Sent Events (SSE) to "push" the result to the client when it's done.

Here's the outline of a scheme for the first option above:

Coins a unique jobID for each incoming job to process

Creates a route for querying the status of a jobID

Has a Map object that contains a list of jobs in process that is indexed by jobID

Has a setInterval() that sweeps through the jobs in the job Map to remove any expired jobs (jobs where the client never came back to get them).  You can set the frequency of that sweep and the amount of time that you keep the job.

When a request comes in, it coins a new jobID, adds a "pending" job to the Map and returns back to the client a URL which they can query the job status on.

When you eventually finish processing the job, the result is added to the job object and its status is changed to "complete".

A route is added to query job status that includes the jobID.

If, when queried, the job status is "complete", then the result is returned and the job is removed from the Map.

If, when queried, the job status is "error", then the error is returned and the job is removed from the Map.

If, when queried, the jobID is not present, 404 status is returned

If, when queried, the job status is anything other than "complete" or "error", then the job.status and optional job.progress is returned.  This allows your long running process to communicate back any progress if you want and you can use multiple status values if you want.

Here's code to illustrate the concept:

```<code>// A map of objects,
//   the key is the jobID
//   data is an object {status: "complete", result: someResult, timeStarted: someTime}
// If the job is not yet complete, status will be something other than "complete"
// and result will not yet exist
const jobs = new Map();

// check for expired jobs
const expirationInterval = 60 * 60 * 1000; // run expiration check once an hour
const expirationTime = 12 * 60 * 60 * 1000; // let jobs stay here for 12 hours
setInterval(() => {
    // accumulate an array of items to remove so we aren't modifying while iterating
    const expired = [];
    const now = Date.now();
    for (let [key, job] of jobs) {
        if (now - job.timeStarted > expirationTime) {
            expired.push(key);
        }
    }
    // now remove all expired jobs
    for (let key of expired) {
        jobs.delete(key);
    }
}, expirationInterval);

// make a job id that consists of current time (in ms) plus random number
// jobs can then be sorted or aged by time also
function makeJobID() {
    const base = Date.now().toString();
    const random = Math.random().toFixed(6).toString().slice(2);
    return base + "_" + random;
}

// fetch data for a jobID
// The job may either not exist any more,
//   may still be "pending" (or have some other status)
//   or may be "complete"
// Note: if this router is not at the top level, you will have to make
// this path line up with the URL you sent back to the client
router.get("/jobstatus/:jobID", (req, res) => {
    let job = jobs.get(req.params.jobID);
    if (!job) {
        res.sendStatus(404);
        return;
    }
    if (job.status === "complete") {
        // remove it from the jobs Map and send the data
        jobs.delete(req.params.jobID);
        res.send({
            status: "complete",
            result: job.result
        });
    } else if (job.status === "error") {
        // remove it from the jobs Map and send the data
        jobs.delete(req.params.jobID);
        res.send({
            status: "error",
            error: job.error
        });
    } else {
        // optional job.progress can also be communicated back.  This can be
        // a number, a string or an object of other data
        if (job.progress) {
            res.send({ status: job.status, progress: job.progress });
        } else {
            res.send({ status: job.status });
        }
    }
});

router.post('/', async (req, res) => {
    let conn;
    try {
        conn = await connect(); // Util method that connects to a Q/KDB server
    } catch (e) {
        console.log(e);
        res.sendStatus(500);
    }
    let request = req.body;

    joi.validate(request, schema, (err, _result) => {
        if (err) {
            res.status(400).send({ error: err['details'][0]['message'] });
        } else {
            // coin job id and add a job object to the jobs map
            const jobID = makeJobID();
            const job = {
                timeStarted: Date.now(),
                status: "pending"
            };
            jobs.set(jobID, job);

            // send response now that gives them a URL to query
            res.status(202).send({
                status: "Job submitted",
                url: `https://yourdomain.com/jobstatus/${jobID}` // pick whatever URL you want here
            });

            let qRequest = buildRequest(request); // Util function to build request
            // Connect to Q/KDB server with node-q package and process request
            conn.k('api.process', qRequest, function(err, resp) {
                if (err) {
                    // set job status to "error"
                    job.status = "error";
                    job.timeCompleted = Date.now();
                    try {
                        job.error = err['details'][0]['message'];
                    } catch (e) {
                        console.log(e);
                        job.error = "known";
                    }
                } else {
                    // job has finished, update the job
                    // we can update the job object directly because the job Map
                    // points at this same object
                    job.status = "complete";
                    job.timeCompleted = Date.now();
                    job.result = resp;
                }
            });
        }
    });
});
</code>```

Body:
I have an API in Node with many endpoints. It works well but there is one that can have large requests run up to 1 hour of processing which can often break. I'm thinking of only sending back a url on a request where you can check the status of the request and then download it once it's ready. What would be the best way to handle a queue of jobs in Node for this?

Sample code below for the current endpoint

const router = express.Router();
const schema = joi.object().keys // This is a schema to validate the json input

router.post('/', async (req, res) => {
  let conn = await connect(); // Util method that connects to a Q/KDB server
  let request = req.body;

  joi.validate(request, schema, (err, _result) => {
    if (err) {
      res.status(400).send({ error: err['details'][0]['message'] });
    }
    else {
      let qRequest = buildRequest(request); // Util function to build request
      // Connect to Q/KDB server with node-q package and process request
      conn.k('api.process', qRequest, function(err, resp) {
        if (err) {
          log // Write to log
          res.status(400).send({ error: err['details'][0]['message']
        }
        else {
          res.status(200).send(resp);
        }
      });
    }
  });

});

EDIT:
I have found that I basically just have to build a job queue with job ids corresponding to them. The package Bull seems to be good but I don't want to add another dependency such as Redis.

Body:
Conceptually there are a couple ways to approach a problem like this:

You can return a jobID and let the client query that jobID on some recurring basis using a URL that contains the jobID until they get a result (this sounds like what you envisioned)

You can have the client connect a webSocket or socket.io connection to the server and when the result is done, the server can directly send the result over the websocket/socket.io connection.

You can use Server Sent Events (SSE) to "push" the result to the client when it's done.

Here's the outline of a scheme for the first option above:

Coins a unique jobID for each incoming job to process

Creates a route for querying the status of a jobID

Has a Map object that contains a list of jobs in process that is indexed by jobID

Has a setInterval() that sweeps through the jobs in the job Map to remove any expired jobs (jobs where the client never came back to get them).  You can set the frequency of that sweep and the amount of time that you keep the job.

When a request comes in, it coins a new jobID, adds a "pending" job to the Map and returns back to the client a URL which they can query the job status on.

When you eventually finish processing the job, the result is added to the job object and its status is changed to "complete".

A route is added to query job status that includes the jobID.

If, when queried, the job status is "complete", then the result is returned and the job is removed from the Map.

If, when queried, the job status is "error", then the error is returned and the job is removed from the Map.

If, when queried, the jobID is not present, 404 status is returned

If, when queried, the job status is anything other than "complete" or "error", then the job.status and optional job.progress is returned.  This allows your long running process to communicate back any progress if you want and you can use multiple status values if you want.

Here's code to illustrate the concept:

// A map of objects,
//   the key is the jobID
//   data is an object {status: "complete", result: someResult, timeStarted: someTime}
// If the job is not yet complete, status will be something other than "complete"
// and result will not yet exist
const jobs = new Map();

// check for expired jobs
const expirationInterval = 60 * 60 * 1000; // run expiration check once an hour
const expirationTime = 12 * 60 * 60 * 1000; // let jobs stay here for 12 hours
setInterval(() => {
    // accumulate an array of items to remove so we aren't modifying while iterating
    const expired = [];
    const now = Date.now();
    for (let [key, job] of jobs) {
        if (now - job.timeStarted > expirationTime) {
            expired.push(key);
        }
    }
    // now remove all expired jobs
    for (let key of expired) {
        jobs.delete(key);
    }
}, expirationInterval);

// make a job id that consists of current time (in ms) plus random number
// jobs can then be sorted or aged by time also
function makeJobID() {
    const base = Date.now().toString();
    const random = Math.random().toFixed(6).toString().slice(2);
    return base + "_" + random;
}

// fetch data for a jobID
// The job may either not exist any more,
//   may still be "pending" (or have some other status)
//   or may be "complete"
// Note: if this router is not at the top level, you will have to make
// this path line up with the URL you sent back to the client
router.get("/jobstatus/:jobID", (req, res) => {
    let job = jobs.get(req.params.jobID);
    if (!job) {
        res.sendStatus(404);
        return;
    }
    if (job.status === "complete") {
        // remove it from the jobs Map and send the data
        jobs.delete(req.params.jobID);
        res.send({
            status: "complete",
            result: job.result
        });
    } else if (job.status === "error") {
        // remove it from the jobs Map and send the data
        jobs.delete(req.params.jobID);
        res.send({
            status: "error",
            error: job.error
        });
    } else {
        // optional job.progress can also be communicated back.  This can be
        // a number, a string or an object of other data
        if (job.progress) {
            res.send({ status: job.status, progress: job.progress });
        } else {
            res.send({ status: job.status });
        }
    }
});

router.post('/', async (req, res) => {
    let conn;
    try {
        conn = await connect(); // Util method that connects to a Q/KDB server
    } catch (e) {
        console.log(e);
        res.sendStatus(500);
    }
    let request = req.body;

    joi.validate(request, schema, (err, _result) => {
        if (err) {
            res.status(400).send({ error: err['details'][0]['message'] });
        } else {
            // coin job id and add a job object to the jobs map
            const jobID = makeJobID();
            const job = {
                timeStarted: Date.now(),
                status: "pending"
            };
            jobs.set(jobID, job);

            // send response now that gives them a URL to query
            res.status(202).send({
                status: "Job submitted",
                url: `https://yourdomain.com/jobstatus/${jobID}` // pick whatever URL you want here
            });

            let qRequest = buildRequest(request); // Util function to build request
            // Connect to Q/KDB server with node-q package and process request
            conn.k('api.process', qRequest, function(err, resp) {
                if (err) {
                    // set job status to "error"
                    job.status = "error";
                    job.timeCompleted = Date.now();
                    try {
                        job.error = err['details'][0]['message'];
                    } catch (e) {
                        console.log(e);
                        job.error = "known";
                    }
                } else {
                    // job has finished, update the job
                    // we can update the job object directly because the job Map
                    // points at this same object
                    job.status = "complete";
                    job.timeCompleted = Date.now();
                    job.result = resp;
                }
            });
        }
    });
});


问:
Use a custom font for our e-mail campaigns
I know that you "can't" use a custom font for your e-mails in tools like ActiveCampaign, but I'm subscribed to a newsletter that does use Open Sans among other fonts. I have asked them how they did it but I didn't received any answer.
I'm receiving the emails in my gmail address, so I know it is possible.

Thanks!

答:
A very few email clients support @font-face in CSS and the use of custom fonts. (See Can I email for details.)

There’s one specificity of Gmail (desktop webmail) which does support fonts like Google Sans or Roboto. But that’s not because it supports @font-face for those, but only because Gmail embeds these fonts itself for its own interface, thus making them available within emails as well.


问:
Why can i create local variables in a view builder in SwiftUI
I think I used to get error complaining about having a local variable in the view builder. I also looked up online and found this:
Closure containing a declaration cannot be used with function builder 'ViewBuilder'

However, today when I tried it out, I was able to create local variables in a view builder without any problem:

```<code>  @ViewBuilder
  private var foo: some View {
    let something = 3
    Text("foo")
    Text("bar")
  }
</code>```

May I know why?

答:
When SwiftUI was first released (in 2019), the Swift language didn't allow local declarations (like let something = 3) inside what were then called “function builders”. However, function builders evolved into what are now called “result builders” and do support local declarations as of Swift 5.4.

This behavior is documented in SE-0289 Result Builders:

Declaration statements

Local declarations are left alone by the transformation. This allows developers to factor out subexpressions freely to clarify their code, without affecting the result builder transformation.

Body:
I think I used to get error complaining about having a local variable in the view builder. I also looked up online and found this:
Closure containing a declaration cannot be used with function builder 'ViewBuilder'

However, today when I tried it out, I was able to create local variables in a view builder without any problem:

  @ViewBuilder
  private var foo: some View {
    let something = 3
    Text("foo")
    Text("bar")
  }

May I know why?


问:
When executing a perl search and replace on the command line, how do I lower case a matched token?
I have a file with lines like

```<code>TEST=value
</code>```

I would like to do a search and replace such that I replace the first token with its lower case equivalent.  So the above would be transformed into

```<code>prefix/test —output value
</code>```

I tried the below

```<code>perl -pi -e ’s/(.*)=(.*)/prefix\/lc($1) —output $2/g' .env
</code>```

But evidently “lc” is being interpreted literally because the result is

```<code>prefix/lc(TEST) —output value
</code>```

答:
Can use \L...\E escapes, which work in a double-quoted context (see it in perlop)

```<code>perl -i -pe's{(.*)=(.*)}{prefix/\L$1\E --output $2}g' .env
</code>```

Note that \L keeps lower-casing all following characters until it runs into \E so it's safer to have \E even though it's not needed here. I used {}{} delimiters  so to not have to escape /'s.

Or, in particular if there's more to do, evaluate code in replacement part via /e modifier, like

```<code>perl -i -pe's{(.*)=(.*)}{"prefix/" . lc($1) . " --output $2"}eg' .env
</code>```

Body:
I have a file with lines like

TEST=value

I would like to do a search and replace such that I replace the first token with its lower case equivalent.  So the above would be transformed into

prefix/test —output value

I tried the below

perl -pi -e ’s/(.*)=(.*)/prefix\/lc($1) —output $2/g' .env

But evidently “lc” is being interpreted literally because the result is

prefix/lc(TEST) —output value

Body:
Can use \L...\E escapes, which work in a double-quoted context (see it in perlop)

perl -i -pe's{(.*)=(.*)}{prefix/\L$1\E --output $2}g' .env

Note that \L keeps lower-casing all following characters until it runs into \E so it's safer to have \E even though it's not needed here. I used {}{} delimiters  so to not have to escape /'s.

Or, in particular if there's more to do, evaluate code in replacement part via /e modifier, like

perl -i -pe's{(.*)=(.*)}{"prefix/" . lc($1) . " --output $2"}eg' .env


问:
How to set params dynamically for AjaxUpload?
I have created a function to upload a file using this library as follows:

```<code>new AjaxUpload($('#addImage'), {
                action: 'SaveDataBank.aspx',
                name: 'uploadimage',
                dataType: 'json',
                params: { clientid: GetSelectedClient() }
                onSubmit: function (file, ext) {
                },
                onComplete: function (file, response) {
                }
            });
</code>```

I would like to perform some task before opening a file dialog. How could I update the above code?

UPDATE:

I would like to pass a parameter dynamically with the file upload. I have a dropdown containing a list of client ids. If I click on the Upload button it will open File Dialog. I would then like it to pass in the selected client from the dropdown. Currently, it only passes the initially selected value.

```<code>params: { clientid: GetSelectedClient() },
</code>```

The above line does not work as per my requirement.

答:
try:

```<code>$('#addImage').mousedown(function(){
    //code here
});
</code>```

Or

```<code>$('#addImage').bind('mousedown',function(){
    //code here
});
</code>```

Body:
I have created a function to upload a file using this library as follows:

new AjaxUpload($('#addImage'), {
                action: 'SaveDataBank.aspx',
                name: 'uploadimage',
                dataType: 'json',
                params: { clientid: GetSelectedClient() }
                onSubmit: function (file, ext) {
                },
                onComplete: function (file, response) {
                }
            });

I would like to perform some task before opening a file dialog. How could I update the above code?

UPDATE:

I would like to pass a parameter dynamically with the file upload. I have a dropdown containing a list of client ids. If I click on the Upload button it will open File Dialog. I would then like it to pass in the selected client from the dropdown. Currently, it only passes the initially selected value.

params: { clientid: GetSelectedClient() },

The above line does not work as per my requirement.

Body:
try:

$('#addImage').mousedown(function(){
    //code here
});

Or

$('#addImage').bind('mousedown',function(){
    //code here
});