问:
Check if split token came from left or right
I need to set the variables termLast / termFirst on a string of the form LastName,FirstName where either part can be omitted.

The following are valid and should be set accordingly,

```<code>,John
Smith,
Smith,John
</code>```

At least one token will always be present. If I do

```<code>String termWhole = null, termLast = null, termFirst = null;
String[] tokens = str.split(",");
termLast = tokens[0];
termFirst = (tokens.length > 1 ? tokens[1] : null);
</code>```

that assumes the rightward direction. Any suggestions on bidirectional parsing? The goal is to have the variables set correctly.

答:
Split with a negative second parameter:

```<code>String[] tokens = str.split(",", -1);
</code>```

so as to keep empty tokens on the end of the string. Then:

```<code>termLast = tokens[0].isEmpty() ? null : tokens[0];
termFirst = tokens[1].isEmpty() ? null : tokens[1];
</code>```

Body:
I need to set the variables termLast / termFirst on a string of the form LastName,FirstName where either part can be omitted.

The following are valid and should be set accordingly,

,John
Smith,
Smith,John

At least one token will always be present. If I do

String termWhole = null, termLast = null, termFirst = null;
String[] tokens = str.split(",");
termLast = tokens[0];
termFirst = (tokens.length > 1 ? tokens[1] : null);

that assumes the rightward direction. Any suggestions on bidirectional parsing? The goal is to have the variables set correctly.

Body:
Split with a negative second parameter:

String[] tokens = str.split(",", -1);

so as to keep empty tokens on the end of the string. Then:

termLast = tokens[0].isEmpty() ? null : tokens[0];
termFirst = tokens[1].isEmpty() ? null : tokens[1];


来源: stackexchange

问:
openapi: referring to an existing example in a list
I have an OpenAPI 3.0.0 spec with a Widget component, which includes an example section:

```<code>components:
  schemas:
    Widget:
      properties:
        id:
          type: string
        description:
          type: string
        cost:
          type: float
      example:
        id: 1234
        description: An example widget
        cost: 0.10
</code>```

I'm adding a Warehouse component that includes a list of Widgets.  Is there a way to make use of the example on the Widget schema in the Warehouse schema?  Something like:

```<code>    Warehouse:
      properties:
        id:
          type: string
        location:
          type: string
        widgets:
          type: array
          items:
            $ref: '#/components/schemas/Widget'
      example:
        id: 4321
        widgets:
          - $ref: '#/components/schemas/Widget'
</code>```

The above didn't work.  I looked at moving the example out of the Widget schema and into a #/components/examples/WidgetExample, but I still wasn't sure what the syntax would look like to refer to that.

答:
The example keyword does not support $ref.

What you can do instead is change the Warehouse schema to use property-level examples for properties other than widgets, in this case the example for widgets will be "inherited" from the Widget schema. At least this is how it works in Swagger UI and Swagger Editor.

    Warehouse:
      properties:
        id:
          type: string
          example: 4321   # <----
        location:
          type: string
          example: Sample location   # <----
        widgets:
          type: array
          items:
            $ref: '#/components/schemas/Widget'
```

<p>Swagger UI will display the following example for <code>Warehouse</code> in the requests and responses:</p>

<pre class="lang-json prettyprint-override"><code>{
  "id": 4321,
  "location": "Sample location",
  "widgets": [
    "id": 1234,
    "description": "An example widget",
    "cost": 0.1
  ]
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have an OpenAPI 3.0.0 spec with a Widget component, which includes an example section:

components:
  schemas:
    Widget:
      properties:
        id:
          type: string
        description:
          type: string
        cost:
          type: float
      example:
        id: 1234
        description: An example widget
        cost: 0.10

I'm adding a Warehouse component that includes a list of Widgets.  Is there a way to make use of the example on the Widget schema in the Warehouse schema?  Something like:

    Warehouse:
      properties:
        id:
          type: string
        location:
          type: string
        widgets:
          type: array
          items:
            $ref: '#/components/schemas/Widget'
      example:
        id: 4321
        widgets:
          - $ref: '#/components/schemas/Widget'

The above didn't work.  I looked at moving the example out of the Widget schema and into a #/components/examples/WidgetExample, but I still wasn't sure what the syntax would look like to refer to that.

Body:
The example keyword does not support $ref.

What you can do instead is change the Warehouse schema to use property-level examples for properties other than widgets, in this case the example for widgets will be "inherited" from the Widget schema. At least this is how it works in Swagger UI and Swagger Editor.

    Warehouse:
      properties:
        id:
          type: string
          example: 4321   # <----
        location:
          type: string
          example: Sample location   # <----
        widgets:
          type: array
          items:
            $ref: '#/components/schemas/Widget'

Swagger UI will display the following example for Warehouse in the requests and responses:

{
  "id": 4321,
  "location": "Sample location",
  "widgets": [
    "id": 1234,
    "description": "An example widget",
    "cost": 0.1
  ]
}


问:
Can I return columns in text form from a function with sql query in coldfusion
I want to write a function in CF, that has a query that returns multiple columns.  I researched and read and could only find examples of functions with sql queries only returning the table view of the struct.

How would I write a function in CF with sql queries and output each column in text format

I been googling it and looking on tutorial websites, with no luck

```<code><cffunction name="queryListEmployee" returntype="query" output="false">
<cfargument name="EMPID" type="numeric" default="1"/>
<cfset var listEmployee = ""/>
    <cfquery name="local.listContractors" datasource="DB">
        SELECT E.FIRSTNAME, E.LASTNAME
        FROM EMPLOYEE E
        WHERE E.ID = <cfqueryparam value="#arguments.EMPID#" cfsqltype="cf_sql_decimal" scale="0"/>
    </cfquery>
<cfreturn local.listEmployee/>
</code>```

I want to be able to output column names like queryListEmployee.firstname and queryListEmployee.lastname

答:
You've got the idea right. Just a few tweaks:

```<code><cffunction name="getEmployeeByID" returntype="query" output="false">
    <cfargument name="EMPID" type="numeric" default="1"/>
    <cfquery name="local.employee" datasource="DB">
        SELECT E.FIRSTNAME, E.LASTNAME
        FROM EMPLOYEE E
        WHERE E.ID = <cfqueryparam
                          value="#arguments.EMPID#"
                          cfsqltype="cf_sql_integer"/>
    </cfquery>
    <cfreturn local.employee/>
</cffunction>
</code>```

Then call this function like so:

```<code><cfset qEmployee = getEmployeeByID(1)>
</code>```

and output the data like this:

```<code><cfoutput query="qEmployee">
    <li>#qEmployee.FIRSTNAME# #qEmployee.LASTNAME#</li>
</cfoutput>
</code>```

This function will only ever return one record. You can search and figure out how to dynamically adjust the search criteria in order to return multiple records.

You might check out http://www.learncfinaweek.com/ to get learn more of the basics of ColdFusion.

Body:
I want to write a function in CF, that has a query that returns multiple columns.  I researched and read and could only find examples of functions with sql queries only returning the table view of the struct.

How would I write a function in CF with sql queries and output each column in text format

I been googling it and looking on tutorial websites, with no luck

<cffunction name="queryListEmployee" returntype="query" output="false">
<cfargument name="EMPID" type="numeric" default="1"/>
<cfset var listEmployee = ""/>
    <cfquery name="local.listContractors" datasource="DB">
        SELECT E.FIRSTNAME, E.LASTNAME
        FROM EMPLOYEE E
        WHERE E.ID = <cfqueryparam value="#arguments.EMPID#" cfsqltype="cf_sql_decimal" scale="0"/>
    </cfquery>
<cfreturn local.listEmployee/>

I want to be able to output column names like queryListEmployee.firstname and queryListEmployee.lastname

Body:
You've got the idea right. Just a few tweaks:

<cffunction name="getEmployeeByID" returntype="query" output="false">
    <cfargument name="EMPID" type="numeric" default="1"/>
    <cfquery name="local.employee" datasource="DB">
        SELECT E.FIRSTNAME, E.LASTNAME
        FROM EMPLOYEE E
        WHERE E.ID = <cfqueryparam
                          value="#arguments.EMPID#"
                          cfsqltype="cf_sql_integer"/>
    </cfquery>
    <cfreturn local.employee/>
</cffunction>

Then call this function like so:

<cfset qEmployee = getEmployeeByID(1)>

and output the data like this:

<cfoutput query="qEmployee">
    <li>#qEmployee.FIRSTNAME# #qEmployee.LASTNAME#</li>
</cfoutput>

This function will only ever return one record. You can search and figure out how to dynamically adjust the search criteria in order to return multiple records.

You might check out http://www.learncfinaweek.com/ to get learn more of the basics of ColdFusion.


问:
lombok & jackson do not work together with openjdk12
Reproducible here:

I used to have java 8.x all was working ok. both open jdk and Oracle.

Once JDK & and Oracle JDK is upgraded, I got exceptions from the jackson.

```<code>    Error:(10, 1) java: constructor ClientResponseData in class my.response.ClientResponseData cannot be applied to given types;
  required: no arguments
  found: java.lang.String,java.lang.String
  reason: actual and formal argument lists differ in length
</code>```

My ClientResponseData defined as follow:

```<code>@JacksonXmlRootElement(localName = "ClientResponseData")
@Builder
@Getter
public class ClientResponseData {

    @JacksonXmlProperty(localName = "responseCode")
    private String responseCode;

    @JacksonXmlProperty(localName = "number")
    private String number;

}
</code>```

The dependency that worked for me before java update:

```<code>    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.9.8</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.18</version>
        <scope>provided</scope>
    </dependency>
</code>```

in pom.xml, I still use: <java.version>1.8</java.version>

After java uprade I had to update the Lombok at least to latest: 1.18.8

Then I start having issues.

```<code>  Error:(10, 1) java: constructor ClientResponseData in class my.response.ClientResponseData cannot be applied to given types;
  required: no arguments
  found: java.lang.String,java.lang.String
  reason: actual and formal argument lists differ in length
</code>```

It fails on:

```<code> return new com.fasterxml.jackson.dataformat.xml.XmlMapper().readValue(xmlString, cls);
</code>```

Any clue how to make it work?

I tried:

to add @NoArgsConstructor - nope

update jackson to latest - nope

答:
I found that combination of @AllArgsConstructor and public ClientResponseData() {} make a trick and it starts working.

(I did not need to this with java 8, but for java11, 12 this only way I could make it work)

```<code>@JacksonXmlRootElement(localName = "ClientResponseData")
@Builder
@Getter
@AllArgsConstructor
@ToString
public class ClientResponseData {

    public ClientResponseData() {}

    @JacksonXmlProperty(localName = "responseCode")
    private String responseCode;

    @JacksonXmlProperty(localName = "number")
    private String number;

}
</code>```

If there is a better solution, please let me know!

Also:

@AllArgsConstructor +
@NoArgsConstructor

makes a trick too.

Body:
Reproducible here:

I used to have java 8.x all was working ok. both open jdk and Oracle.

Once JDK & and Oracle JDK is upgraded, I got exceptions from the jackson.

    Error:(10, 1) java: constructor ClientResponseData in class my.response.ClientResponseData cannot be applied to given types;
  required: no arguments
  found: java.lang.String,java.lang.String
  reason: actual and formal argument lists differ in length

My ClientResponseData defined as follow:

@JacksonXmlRootElement(localName = "ClientResponseData")
@Builder
@Getter
public class ClientResponseData {

    @JacksonXmlProperty(localName = "responseCode")
    private String responseCode;

    @JacksonXmlProperty(localName = "number")
    private String number;

}

The dependency that worked for me before java update:

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.9.8</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.18</version>
        <scope>provided</scope>
    </dependency>

in pom.xml, I still use: <java.version>1.8</java.version>

After java uprade I had to update the Lombok at least to latest: 1.18.8

Then I start having issues.

  Error:(10, 1) java: constructor ClientResponseData in class my.response.ClientResponseData cannot be applied to given types;
  required: no arguments
  found: java.lang.String,java.lang.String
  reason: actual and formal argument lists differ in length

It fails on:

 return new com.fasterxml.jackson.dataformat.xml.XmlMapper().readValue(xmlString, cls);

Any clue how to make it work?

I tried:

to add @NoArgsConstructor - nope

update jackson to latest - nope

Body:
I found that combination of @AllArgsConstructor and public ClientResponseData() {} make a trick and it starts working.

(I did not need to this with java 8, but for java11, 12 this only way I could make it work)

@JacksonXmlRootElement(localName = "ClientResponseData")
@Builder
@Getter
@AllArgsConstructor
@ToString
public class ClientResponseData {

    public ClientResponseData() {}

    @JacksonXmlProperty(localName = "responseCode")
    private String responseCode;

    @JacksonXmlProperty(localName = "number")
    private String number;

}

If there is a better solution, please let me know!

Also:

@AllArgsConstructor +
@NoArgsConstructor

makes a trick too.


问:
SELECTing top N rows without ROWNUM?
I hope you can help me with my homework :)

We need to build a query that outputs the top N best paid employees.

My version works perfectly fine.

For example the top 3:

```<code>SELECT name, salary
FROM staff
WHERE salary IN ( SELECT *
                  FROM ( SELECT salary
                         FROM staff
                         ORDER BY salary DESC )
                  WHERE ROWNUM <= 3 )
ORDER BY salary DESC
;
</code>```

Note that this will output employees that are in the top 3 and have the same salary, too.

1: Mike, 4080

  2: Steve, 2800

  2: Susan, 2800

  2: Jack, 2800

  3: Chloe, 1400

But now our teacher does not allow us to use ROWNUM.

I searched far and wide and didn't find anything useable.

My second solution thanks to Justin Caves' hint.

First i tried this:

```<code>SELECT name, salary, ( rank() OVER ( ORDER BY salary DESC ) ) as myorder
FROM staff
WHERE myorder <= 3
;
</code>```

The errormessage is: "myorder: invalid identifier"

Thanks to DCookie its now clear:

"[...] Analytics are applied AFTER
  the where clause is evaluated, which
  is why you get the error that myorder
  is an invalid identifier."

Wrapping a SELECT around solves this:

```<code>SELECT *
FROM ( SELECT name, salary, rank() OVER ( ORDER BY salary DESC ) as myorder FROM staff )
WHERE myorder <= 3
;
</code>```

My teacher strikes again and don't allow such exotic analytic functions.

3rd solution from @Justin Caves.

"If analytic functions are also
  disallowed, the other option I could
  imagine-- one that you would never,
  ever, ever actually write in practice,
  would be something like"

```<code>SELECT name, salary
  FROM staff s1
 WHERE (SELECT COUNT(*)
          FROM staff s2
         WHERE s1.salary < s2.salary) <= 3
</code>```

答:
Oracle? What about window functions? </p>

```<code>select * from
(SELECT s.*, row_number over (order by salary desc ) as rn FROM staff s )
where rn <=3
</code>```

ContentLicense: CC BY-SA 3.0

Title: SELECTing top N rows without ROWNUM?

Body:
I hope you can help me with my homework :)

We need to build a query that outputs the top N best paid employees.

My version works perfectly fine.

For example the top 3:

SELECT name, salary
FROM staff
WHERE salary IN ( SELECT *
                  FROM ( SELECT salary
                         FROM staff
                         ORDER BY salary DESC )
                  WHERE ROWNUM <= 3 )
ORDER BY salary DESC
;

Note that this will output employees that are in the top 3 and have the same salary, too.

1: Mike, 4080

  2: Steve, 2800

  2: Susan, 2800

  2: Jack, 2800

  3: Chloe, 1400

But now our teacher does not allow us to use ROWNUM.

I searched far and wide and didn't find anything useable.

My second solution thanks to Justin Caves' hint.

First i tried this:

SELECT name, salary, ( rank() OVER ( ORDER BY salary DESC ) ) as myorder
FROM staff
WHERE myorder <= 3
;

The errormessage is: "myorder: invalid identifier"

Thanks to DCookie its now clear:

"[...] Analytics are applied AFTER
  the where clause is evaluated, which
  is why you get the error that myorder
  is an invalid identifier."

Wrapping a SELECT around solves this:

SELECT *
FROM ( SELECT name, salary, rank() OVER ( ORDER BY salary DESC ) as myorder FROM staff )
WHERE myorder <= 3
;

My teacher strikes again and don't allow such exotic analytic functions.

3rd solution from @Justin Caves.

"If analytic functions are also
  disallowed, the other option I could
  imagine-- one that you would never,
  ever, ever actually write in practice,
  would be something like"

SELECT name, salary
  FROM staff s1
 WHERE (SELECT COUNT(*)
          FROM staff s2
         WHERE s1.salary < s2.salary) <= 3

Body:
Oracle? What about window functions?

select * from
(SELECT s.*, row_number over (order by salary desc ) as rn FROM staff s )
where rn <=3


问:
How can I identify requests made via AJAX in Python's Flask?
I'd like to detect if the browser made a request via AJAX (AngularJS) so that I can return a JSON array, or if I have to render the template. How can I do this?</p>

答:
There isn't any way to be certain whether a request is made by ajax.

What I found that worked for me, was to simply include a get parameter for xhr requests and simply omit the parameter on non-xhr requests.

For example:

XHR Request: example.com/search?q=Boots&api=1

Other Requests: example.com/search?q=Boots


问:
"auto.arima" in SAS?
I used to run arima model in R using "auto.arima" to identify the best arima model that fits the data. Even without it, it's easy in R to write a function to perform similar task. However, I have googled for the past few days, and I can't find a similar procedure in SAS. Does anyone know if there is a "auto.arima" in SAS? Or do I have to write one by myself? Thank you!

Edit:
After days of searching online, the closest one that I can find is Automatic Model Selection in time series forecasting package. However, that function is the one using GUI, and still one has to manually select all the different models to test. Does anyone know a command line procedure or package to do this? Thank you.

答:
SAS has high performance forecasting procedures (PROC HPFDIAGNOSE+PROC HPFENGINE), which not only selects the best ARIMA model, but can also select the best among ARIMA, ESM, UCM, IDM, combination models, and external models, etc. You can either let it automatically picks the best based on default selection criterion, or customize the selection criterion. There is a procedure family to customize everything: PROC HPFDIAGNOSE, PROC HPFENGINE, PROC ARIMASPEC, etc. If you want to do more flexible time series analysis plus coding, you can also use PROC TIMEDATA with all the built-in time series packages, which allows you to program whatever you want and also do all the automatic modeling.

Like being mentioned above, it is the best in market for time series forecasting, and nothing can beat its accuracy when you are trying to generate forecasts for multiple series. However, it usually licensed with SAS Forecast Server or SAS Forecast Studio, which are enterprised forecasting solutions with GUI. It's understandable since other forecasting solutions built on R and Python which can handle automatic
 parallelization and automatic forecasting also charge money.

For the cloud computing version, there is also PROC TSMODEL and Visual Forecasting version, which has both forecast accuracy and computation performance advantages. However, it is also for enterprise use and pricey. Afterall, it is targeted to markets that require forecasting for thousands or millions of time series.

For free versions, maybe the closest one would be PROC FORECAST.

Title: "auto.arima" in SAS?


问:
ESP8266 stack trace: find position of "last failed alloc call" in code
I'm trying to debug a large sketch, I'm occasionally getting a crash related to the web interface, and am trying to find out where exactly this is going wrong.

The stack trace ends with:

```<code>last failed alloc call: 4022D552(1480)
</code>```

This particular address is not present in the decode stack trace itself, but may hold the key to finding the source of the problem. Any suggestions on how to track this one down?

```<code>Decoding 36 results
0x402222c5: BearSSL::WiFiClientSecure::_installClientX509Validator() at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr_base.h line 986
:  (inlined by) ?? at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr.h line 316
:  (inlined by) ?? at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr.h line 598
:  (inlined by) ?? at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr.h line 614
:  (inlined by) BearSSL::WiFiClientSecure::_installClientX509Validator() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp line 877
0x40222cfc: BearSSL::WiFiClientSecure::_connectSSL(char const*) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp line 962
0x40219c70: esp_yield at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_main.cpp line 91
0x4021a8c3: delay at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_wiring.cpp line 54
0x40206d6d: WiFiClient::connect(IPAddress, unsigned short) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/include/ClientContext.h line 136
:  (inlined by) WiFiClient::connect(IPAddress, unsigned short) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClient.cpp line 170
0x40222eed: BearSSL::WiFiClientSecure::connect(char const*, unsigned short) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp line 231
0x40225230: BearSSL::PrivateKey::getEC() const at ?? line ?
0x40225230: BearSSL::PrivateKey::getEC() const at ?? line ?
0x40216b5c: HTTPClient::connect() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp line 1165
0x4021c16e: uart_write at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/uart.cpp line 498
0x40217820: HTTPClient::sendRequest(char const*, unsigned char*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp line 655
0x40217d98: HardwareSerial::write(unsigned char const*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 158
0x40273eba: sleep_reset_analog_rtcreg_8266 at ?? line ?
0x402180a5: Print::write(char const*) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.h line 60
0x40217d83: HardwareSerial::write(unsigned char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 154
0x402179ba: HTTPClient::GET() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp line 575
0x402118e8: HydroMonitorLogging::sendPostData(char*) at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 730
0x40225470: BearSSL::PrivateKey::getEC() const at ?? line ?
0x4022c4c0: _vsprintf_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/vsprintf.c line 65
0x40217d98: HardwareSerial::write(unsigned char const*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 158
0x4022000a: spiffs_object_truncate at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/spiffs/spiffs_nucleus.cpp line 1727
0x40211d41: HydroMonitorLogging::transmitMessages() at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 337
0x40211caa: HydroMonitorLogging::transmitMessages() at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 326
0x40204dab: handleAPI() at /home/wouter/Arduino/Williams_fridge/Fridge_control/webAPI.ino line 149
0x402251c8: BearSSL::PrivateKey::getEC() const at ?? line ?
0x40217d98: HardwareSerial::write(unsigned char const*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 158
0x40218130: Print::println() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.cpp line 178
0x402121b5: HydroMonitorLogging::logData() at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 250
0x40217d83: HardwareSerial::write(unsigned char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 154
0x40224948: Print::write(char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.h line 73
0x40218114: Print::print(char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.cpp line 126
0x402106f4: HydroMonitorIsolatedSensorBoard::readSensor(bool) at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorIsolatedSensorBoard.cpp line 36
0x40207a07: TwoWire::requestFrom(int, int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/Wire/Wire.cpp line 134
0x402042f9: loop at /home/wouter/Arduino/Williams_fridge/Fridge_control/loop.ino line 36
0x40219d20: loop_wrapper() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_main.cpp line 125
0x401015d5: cont_wrapper at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/cont.S line 81
</code>```

Note: I also asked on the esp8266 forum, and opened an issue on github about the same.

答:
Intermittent ESP crashes are most often due to running out of RAM. A "failed alloc call" likely refers to a failure to allocate memory for an operation (encryption takes a good bit, as does every open request in the queue). The stack trace will not point to a specific spot in your code because client libraries run "in the background" (triggered by interrupts or once-per-loop calls to a function that does everything) and no specific event in your firmware caused it. On a memory-starved ESP with a long response time, sending several AJAX requests at once from the frontend can cause the overload.

To see whether this is the case, try printing the result of ESP.getFreeHeap() at various points in your loop. If it falls much below 10kb, there is a risk that another request will drive it over the edge.

Body:
I'm trying to debug a large sketch, I'm occasionally getting a crash related to the web interface, and am trying to find out where exactly this is going wrong.

The stack trace ends with:

last failed alloc call: 4022D552(1480)

This particular address is not present in the decode stack trace itself, but may hold the key to finding the source of the problem. Any suggestions on how to track this one down?

Decoding 36 results
0x402222c5: BearSSL::WiFiClientSecure::_installClientX509Validator() at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr_base.h line 986
:  (inlined by) ?? at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr.h line 316
:  (inlined by) ?? at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr.h line 598
:  (inlined by) ?? at /home/wouter/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/xtensa-lx106-elf/include/c++/4.8.2/bits/shared_ptr.h line 614
:  (inlined by) BearSSL::WiFiClientSecure::_installClientX509Validator() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp line 877
0x40222cfc: BearSSL::WiFiClientSecure::_connectSSL(char const*) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp line 962
0x40219c70: esp_yield at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_main.cpp line 91
0x4021a8c3: delay at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_wiring.cpp line 54
0x40206d6d: WiFiClient::connect(IPAddress, unsigned short) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/include/ClientContext.h line 136
:  (inlined by) WiFiClient::connect(IPAddress, unsigned short) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClient.cpp line 170
0x40222eed: BearSSL::WiFiClientSecure::connect(char const*, unsigned short) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp line 231
0x40225230: BearSSL::PrivateKey::getEC() const at ?? line ?
0x40225230: BearSSL::PrivateKey::getEC() const at ?? line ?
0x40216b5c: HTTPClient::connect() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp line 1165
0x4021c16e: uart_write at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/uart.cpp line 498
0x40217820: HTTPClient::sendRequest(char const*, unsigned char*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp line 655
0x40217d98: HardwareSerial::write(unsigned char const*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 158
0x40273eba: sleep_reset_analog_rtcreg_8266 at ?? line ?
0x402180a5: Print::write(char const*) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.h line 60
0x40217d83: HardwareSerial::write(unsigned char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 154
0x402179ba: HTTPClient::GET() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp line 575
0x402118e8: HydroMonitorLogging::sendPostData(char*) at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 730
0x40225470: BearSSL::PrivateKey::getEC() const at ?? line ?
0x4022c4c0: _vsprintf_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/vsprintf.c line 65
0x40217d98: HardwareSerial::write(unsigned char const*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 158
0x4022000a: spiffs_object_truncate at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/spiffs/spiffs_nucleus.cpp line 1727
0x40211d41: HydroMonitorLogging::transmitMessages() at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 337
0x40211caa: HydroMonitorLogging::transmitMessages() at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 326
0x40204dab: handleAPI() at /home/wouter/Arduino/Williams_fridge/Fridge_control/webAPI.ino line 149
0x402251c8: BearSSL::PrivateKey::getEC() const at ?? line ?
0x40217d98: HardwareSerial::write(unsigned char const*, unsigned int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 158
0x40218130: Print::println() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.cpp line 178
0x402121b5: HydroMonitorLogging::logData() at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorLogging.cpp line 250
0x40217d83: HardwareSerial::write(unsigned char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/HardwareSerial.h line 154
0x40224948: Print::write(char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.h line 73
0x40218114: Print::print(char) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.cpp line 126
0x402106f4: HydroMonitorIsolatedSensorBoard::readSensor(bool) at /home/wouter/Arduino/libraries/HydroMonitor/src/HydroMonitorIsolatedSensorBoard.cpp line 36
0x40207a07: TwoWire::requestFrom(int, int) at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/Wire/Wire.cpp line 134
0x402042f9: loop at /home/wouter/Arduino/Williams_fridge/Fridge_control/loop.ino line 36
0x40219d20: loop_wrapper() at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_main.cpp line 125
0x401015d5: cont_wrapper at /home/wouter/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/cont.S line 81

Note: I also asked on the esp8266 forum, and opened an issue on github about the same.


问:
ImportError: cannot import name 'http' from 'scapy.layers
I am getting this error and I don't understand why?

```<code>ImportError: cannot import name 'http' from 'scapy.layers
</code>```

Here is my code:

```<code>import scapy.all as scapy
from scapy.layers import http  #error line

def sniff(interface):
    scapy.sniff(iface=interface,store=False,prn=p_s_p)

def p_s_p(packet):
    if packet.haslayer(http.HTTPRequest):
        print(packet)

sniff('wlan0')
</code>```

答:
Use the scapy_http library:

from scapy_http import http

Body:
I am getting this error and I don't understand why?

ImportError: cannot import name 'http' from 'scapy.layers

Here is my code:

import scapy.all as scapy
from scapy.layers import http  #error line

def sniff(interface):
    scapy.sniff(iface=interface,store=False,prn=p_s_p)

def p_s_p(packet):
    if packet.haslayer(http.HTTPRequest):
        print(packet)

sniff('wlan0')


问:
ES6 async/await parallel processing
I am writing code for async/await parallel processing but it's not processing all the records if any error occurred not processing rest of the record

```<code>async function test() {

 let i = 0
 let userId = [5000, 1000, 7000]
 try {
    while (i < userId.length) {
        const userEmail = await getUserEmail(userId[i])
        let sendEmailResult = await postSendUserEmail(userEmail)
        i++
    }
 } catch (err) {
    console.log('Got error')
 }
}

(async () => {
 await test();
 // Do some logic here
 console.log('All  done')
})().catch(e => console.log(e));

function getUserEmail(milis) {
 return new Promise(function(resolve, reject) {
    if (milis == 1000) {

        setTimeout(() => {
            console.log('Rejecting millis', milis)
            return reject('Got error')
        }, milis);

    } else {

        setTimeout(() => {
            console.log('Processing millis', milis)
            return resolve(milis);
        }, milis);

    }
  })
}

function postSendUserEmail(milis) {
  return new Promise(function(resolve, reject) {
    if (milis == 1000) {

        setTimeout(() => {
            console.log('Rejecting  email', milis)
            return reject('Got email error')
        }, milis);

    } else {

        setTimeout(() => {
            console.log('Sending  email', milis)
            return resolve(milis);
        }, milis);

    }
})
}
</code>```

Here getUserEmail is rejecting promise when value is 1000,

My question is while loop processing all the operation in parallel for each records and why all records are not processing if any reject occurs then how to process all the records whether resolve/reject using async/await

答:
The awaits you have inside the while loop is blocking the execution and continuation of the loop until they've completed.

You could move those function calls to a separate function and it will continue to execute:

```<code>async function test() {

    let i = 0
    let userId = [5000, 1000, 7000]
    try {
        while (i < userId.length) {
            handleUser(userId[i]);
            // const userEmail = await getUserEmail(userId[i])
            // let sendEmailResult = await postSendUserEmail(userEmail)
            i++
        }
    } catch (err) {
        console.log('Got error')
    }
}

async function handleUser(user) {
    const userEmail = await getUserEmail(user)
    let sendEmailResult = await postSendUserEmail(userEmail)
}
</code>```

Or, if you want each user to be handled 1 at a time, you can move the try...catch to be inside the while loop.

Title: ES6 async/await parallel processing

Body:
I am writing code for async/await parallel processing but it's not processing all the records if any error occurred not processing rest of the record

async function test() {

 let i = 0
 let userId = [5000, 1000, 7000]
 try {
    while (i < userId.length) {
        const userEmail = await getUserEmail(userId[i])
        let sendEmailResult = await postSendUserEmail(userEmail)
        i++
    }
 } catch (err) {
    console.log('Got error')
 }
}

(async () => {
 await test();
 // Do some logic here
 console.log('All  done')
})().catch(e => console.log(e));

function getUserEmail(milis) {
 return new Promise(function(resolve, reject) {
    if (milis == 1000) {

        setTimeout(() => {
            console.log('Rejecting millis', milis)
            return reject('Got error')
        }, milis);

    } else {

        setTimeout(() => {
            console.log('Processing millis', milis)
            return resolve(milis);
        }, milis);

    }
  })
}

function postSendUserEmail(milis) {
  return new Promise(function(resolve, reject) {
    if (milis == 1000) {

        setTimeout(() => {
            console.log('Rejecting  email', milis)
            return reject('Got email error')
        }, milis);

    } else {

        setTimeout(() => {
            console.log('Sending  email', milis)
            return resolve(milis);
        }, milis);

    }
})
}

Here getUserEmail is rejecting promise when value is 1000,

My question is while loop processing all the operation in parallel for each records and why all records are not processing if any reject occurs then how to process all the records whether resolve/reject using async/await

Body:
The awaits you have inside the while loop is blocking the execution and continuation of the loop until they've completed.

You could move those function calls to a separate function and it will continue to execute:

async function test() {

    let i = 0
    let userId = [5000, 1000, 7000]
    try {
        while (i < userId.length) {
            handleUser(userId[i]);
            // const userEmail = await getUserEmail(userId[i])
            // let sendEmailResult = await postSendUserEmail(userEmail)
            i++
        }
    } catch (err) {
        console.log('Got error')
    }
}

async function handleUser(user) {
    const userEmail = await getUserEmail(user)
    let sendEmailResult = await postSendUserEmail(userEmail)
}

Or, if you want each user to be handled 1 at a time, you can move the try...catch to be inside the while loop.


答:
Your try/catch block is outside of the loop. If you rearrange it so that it is on a per-iteration basis you can avoid the situation where one bad apple ruins the bunch. Try changing your test function to:

```<code>    while (i < userId.length) {
      try {
        const userEmail = await getUserEmail(userId[i])
        let sendEmailResult = await postSendUserEmail(userEmail)
      } catch (err) {
        // err handling here
        // ....
     }
      // Need to do this regardless of whether or not error occured.
      i++
    }
</code>```

Title: ES6 async/await parallel processing

Body:
Your try/catch block is outside of the loop. If you rearrange it so that it is on a per-iteration basis you can avoid the situation where one bad apple ruins the bunch. Try changing your test function to:

    while (i < userId.length) {
      try {
        const userEmail = await getUserEmail(userId[i])
        let sendEmailResult = await postSendUserEmail(userEmail)
      } catch (err) {
        // err handling here
        // ....
     }
      // Need to do this regardless of whether or not error occured.
      i++
    }


问:
How to make this simple function more efficient?
I have data on wages and about 95% of them are given in hourly format, however some of them are given as an annual salary. So I made a function to convert the annual salaries to hourly, however it takes 1 min 40 sec to run, when my dataset is 43000 rows x 12 columns (which I didnt think would be too big) so I did not think it would take this long.

I am curious if there is a better way to do this than the current function I have created. I am new with dplyr and tidyverse so ideally an answer using those capabilities.

Here is some sample data:

```<code>NOC4  Region Region_Name Wage_2012 Wage_2013 Wage_2014
0011  ER10   National    28.1      65000     NA
0011  ER1010 Northern    NA        30.5      18
0011  ER1020 Southern    42.3      72000     22
0011  ER1030 Eastern     12        NA        45500
0011  ER1040 Western     8         NA        99000
0011  ER10   National    NA        65000     NA
</code>```

Here is what it should look like after the function:

```<code>NOC4  Region Region_Name Wage_2012 Wage_2013 Wage_2014
0011  ER10   National    28.1      33.33     NA
0011  ER1010 Northern    NA        30.5      18
0011  ER1020 Southern    42.3      36.92     22
0011  ER1030 Eastern     12        NA        23.33
0011  ER1040 Western     8         NA        50.77
0011  ER10   National    NA        33.33     NA
</code>```

Here is the function:

```<code>year_to_hour <- function(dataset, salary, startcol){
  # where "startcol" should be the first column containing the numeric
  # values that you are trying to convert.
  for(i in startcol:ncol(dataset)){

    for(j in 1:nrow(dataset)){

      if(is.na(dataset[j, i])){

        j = j+1

      }else if(as.numeric(dataset[j, i]) >= as.numeric(salary)){

        dataset[j, i] = dataset[j, i]/1950
      }
      else{

        dataset[j, i] = dataset[j, i]

      }

    }

  }

  return(as_tibble(dataset))

}

converted <- year_to_hour(wage_data_messy, 1000, 4)
</code>```

答:
R will work much faster if you let it handle the loops under the hood through "vectorized" code.

http://www.noamross.net/blog/2014/4/16/vectorization-in-r--why.html

Here's an approach using dplyr:

```<code>library(dplyr)
salary <- 1000
df %>%
  mutate_at(vars(Wage_2012:Wage_2014),          # For these columns...
            ~ . / if_else(. > salary, 1950, 1)) # Divide by 1950 if > salary
</code>```

Body:
I have data on wages and about 95% of them are given in hourly format, however some of them are given as an annual salary. So I made a function to convert the annual salaries to hourly, however it takes 1 min 40 sec to run, when my dataset is 43000 rows x 12 columns (which I didnt think would be too big) so I did not think it would take this long.

I am curious if there is a better way to do this than the current function I have created. I am new with dplyr and tidyverse so ideally an answer using those capabilities.

Here is some sample data:

NOC4  Region Region_Name Wage_2012 Wage_2013 Wage_2014
0011  ER10   National    28.1      65000     NA
0011  ER1010 Northern    NA        30.5      18
0011  ER1020 Southern    42.3      72000     22
0011  ER1030 Eastern     12        NA        45500
0011  ER1040 Western     8         NA        99000
0011  ER10   National    NA        65000     NA

Here is what it should look like after the function:

NOC4  Region Region_Name Wage_2012 Wage_2013 Wage_2014
0011  ER10   National    28.1      33.33     NA
0011  ER1010 Northern    NA        30.5      18
0011  ER1020 Southern    42.3      36.92     22
0011  ER1030 Eastern     12        NA        23.33
0011  ER1040 Western     8         NA        50.77
0011  ER10   National    NA        33.33     NA

Here is the function:

year_to_hour <- function(dataset, salary, startcol){
  # where "startcol" should be the first column containing the numeric
  # values that you are trying to convert.
  for(i in startcol:ncol(dataset)){

    for(j in 1:nrow(dataset)){

      if(is.na(dataset[j, i])){

        j = j+1

      }else if(as.numeric(dataset[j, i]) >= as.numeric(salary)){

        dataset[j, i] = dataset[j, i]/1950
      }
      else{

        dataset[j, i] = dataset[j, i]

      }

    }

  }

  return(as_tibble(dataset))

}

converted <- year_to_hour(wage_data_messy, 1000, 4)

Body:
R will work much faster if you let it handle the loops under the hood through "vectorized" code.

http://www.noamross.net/blog/2014/4/16/vectorization-in-r--why.html

Here's an approach using dplyr:

library(dplyr)
salary <- 1000
df %>%
  mutate_at(vars(Wage_2012:Wage_2014),          # For these columns...
            ~ . / if_else(. > salary, 1950, 1)) # Divide by 1950 if > salary


问:
Python Combining a FOR Loop and an IF statement
I have some issues with this small piece of code:

```<code>for key in UserInput.objects.all():
        if UserInput.category_id == 2:
            data = {}
            data['label'] = key.input_date
            data['value'] = key.input_value
            dataSource['data'].append(data)
</code>```

I just don't seem to get it working. The only thing I want to do is to retrieve all rows from the UserInput table which have a category_id of 2 and then execute the four data lines for each row to use in my bar chart.

I get a variety of errors. I get an Object of type date is not JSON serializable on data['label'] = key.input_date. If I replace input_date with another (string) value, my bar chart seems to work, but it shows an empty bar chart. I tried to serialize my input_date, but I get even more errors when I try to do that.

```<code>json_data = serializers.serialize("xml", UserInput.objects.all())
</code>```

and

```<code>fields = ['input_date']
    qs = UserInput.objects.all()
    json_input_data = serializers.serialize('json', qs, fields=fields)
</code>```

My Python knowledge doesn't reach far enough to solve this on my own.

I would prefer to sort the data to month-year instead of day-month-year, but I would understand if this is beyond the scope of my question

EDIT:
As many pointed it out in the comments, I do indeed use Django. I didn't mention it before because I thought it wouldn't be relevant.

答:
Seems like you are using Django, so you should use the tools provided by Django.</p>

```<code>objects_with_category_id_2 = UserInput.objects.filter(category_id=2)
for obj in objects_with_category_id_2:
     data =  {'label': obj.input_date,
              'value': obj.input_value}
     dataSource['data'].append(data)
</code>```

Body:
I have some issues with this small piece of code:

for key in UserInput.objects.all():
        if UserInput.category_id == 2:
            data = {}
            data['label'] = key.input_date
            data['value'] = key.input_value
            dataSource['data'].append(data)

I just don't seem to get it working. The only thing I want to do is to retrieve all rows from the UserInput table which have a category_id of 2 and then execute the four data lines for each row to use in my bar chart.

I get a variety of errors. I get an Object of type date is not JSON serializable on data['label'] = key.input_date. If I replace input_date with another (string) value, my bar chart seems to work, but it shows an empty bar chart. I tried to serialize my input_date, but I get even more errors when I try to do that.

json_data = serializers.serialize("xml", UserInput.objects.all())

and

fields = ['input_date']
    qs = UserInput.objects.all()
    json_input_data = serializers.serialize('json', qs, fields=fields)

My Python knowledge doesn't reach far enough to solve this on my own.

I would prefer to sort the data to month-year instead of day-month-year, but I would understand if this is beyond the scope of my question

EDIT:
As many pointed it out in the comments, I do indeed use Django. I didn't mention it before because I thought it wouldn't be relevant.

Body:
Seems like you are using Django, so you should use the tools provided by Django.

objects_with_category_id_2 = UserInput.objects.filter(category_id=2)
for obj in objects_with_category_id_2:
     data =  {'label': obj.input_date,
              'value': obj.input_value}
     dataSource['data'].append(data)


问:
How do you balance working for a living and contributing to open source projects?
I have been a working programmer since the turn of the century and I have always been fascinated by the open source world. I have wanted to contribute to these projects but I find it difficult to find the time that I think these projects would require.

I find professional software development to be a huge time sink. Almost every project I have worked on has a familiar litany inflexible deadlines and inevitable round the clock last minute pushes that eat up your nights and weekends and everything else in sight. Even in the project that don't have this - the typical work day is 10 to 12 hours and after that one has errands and chores, reading up on the latest stuff, etc...

Since this happens with a fair amount of regularity - I am hesitant to join projects since I can't promise to devote a regular number of hours every week.

My question is how do you people do it?

Do you work at open source companies? Am I exaggerating the amount of time I need to spend (I am thinking a couple of hours everyday)? Am I way off base and simply not managing my time efficiently? How do you manage your time?

答:
First of all, get a new job. ;)  Second of all, because Open Source IS all volunteer, you don't have to commit to any specific schedule.  I would say a couple of hours a day would be MORE then enough to make SIGNIFICANT contributions to any open source project.  I tend to do most of my open source stuff on the weekends.  I probably average about 3 hours during the week, and an additional 5-6 over the weekend.

By the by, Open Source work is one of the best ways to "keep up" on new stuff ;)

OwnerDisplayName: Nikhil

ContentLicense: CC BY-SA 2.5

OwnerDisplayName: TheProkrammer


问:
Is it possible to define default object inside a SET element in HBM?
lets say I have mapping of a set within Parent hbm file:

```<code>    <set cascade="all" inverse="true" lazy="false" name="children">
       <key column="parentChildId" foreign-key="fk_fk" not-null="true" on-
         delete="cascade"/>
     <one-to-many class="Child" not-found="ignore"/>
   </set>
</code>```

Is it anyhow possible to define  in Parent hbm a default child, that when ever parent is created, one child is added inside of this set????

I know it sounds weird, but because of some performance issue i must try to create as least calls to server (here one was saving parent and other call was saving default child).

I appreciate all the help.

Thank you

答:
What do you mean by "server"? Do you mean the database server? If so, then there's no way to create a parent and a child in one SQL statement. But Hibernate uses batch updates, so it should be very efficient.

If you mean the "application server", then it sounds like a functional problem, not a technical one. Change your parent creation method to make it create a child at the same time. You could even do that using a factory method in the Parent class :

```<code>public class Parent {
    public static Parent createParentWithDefaultChild() {
        Parent p = new Parent();
        p.addChild(new Child());
        return p;
    }
    // ...
}
</code>```

Body:
lets say I have mapping of a set within Parent hbm file:

    <set cascade="all" inverse="true" lazy="false" name="children">
       <key column="parentChildId" foreign-key="fk_fk" not-null="true" on-
         delete="cascade"/>
     <one-to-many class="Child" not-found="ignore"/>
   </set>

Is it anyhow possible to define  in Parent hbm a default child, that when ever parent is created, one child is added inside of this set????

I know it sounds weird, but because of some performance issue i must try to create as least calls to server (here one was saving parent and other call was saving default child).

I appreciate all the help.

Thank you

Body:
What do you mean by "server"? Do you mean the database server? If so, then there's no way to create a parent and a child in one SQL statement. But Hibernate uses batch updates, so it should be very efficient.

If you mean the "application server", then it sounds like a functional problem, not a technical one. Change your parent creation method to make it create a child at the same time. You could even do that using a factory method in the Parent class :

public class Parent {
    public static Parent createParentWithDefaultChild() {
        Parent p = new Parent();
        p.addChild(new Child());
        return p;
    }
    // ...
}


问:
NetSuite SuiteScript 2.0 How do I create a Bank Deposit Slip (suitelet function) from a UserEvent Button
I'm a non-developer who's brand new to NetSuite and SuiteScript and I'm stumbling my way through.

The problem: For each deposit record I need to create a printable pdf which lists each of the payments on that record (a Bank Deposit Slip). I would like to call this pdf on a custom button to display in a new window that I can print from. I do not need to save the document in the file cabinet.

1. Right now I have a UserEvent button that shows up on Deposits in view and edit modes.

define([], function () {
  /**
   * @NApiVersion 2.x
  * @NScriptType UserEventScript
  */
 var exports = {};

 function beforeLoad(context) {
  context.form.addButton({
            id: "custpage_printdepositslip",
         label: "Print Deposit Slip",
   functionName: "onButtonClick"
        });
  context.form.clientScriptModulePath = "SuiteScripts/depositSlips/customDepositSlipButton.js"
 }

 exports.beforeLoad = beforeLoad;
 return exports;

});```
</div>
</div>
</p>

<p><strong>2.</strong> This button calls a clickhandler function "onButtonClick" from a ClientScript named "customDepositSlipButton.js" </p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override"><code>define(["N/ui/dialog"], function (dialog) {
  /**
   * @NApiVersion 2.x
  * @NScriptType ClientScript
  */
 var exports = {};

 function pageInit(context) {
   // TODO
 }

   function onButtonClick() {
     dialog.alert({
            title: "COMING SOON",
         message: "This feature will eventually create a bank deposit slip"
        });
 }

 exports.onButtonClick = onButtonClick;
 exports.pageInit = pageInit;
 return exports;

});</code>```

Currently this works, but only creates a dialog popup for testing purposes. So far, so good.
testing popup

And here's where I'm stuck: I don't understand how to now connect this to a function on a Suitelet which should generate a pdf file from xml.

3. I've set up a Suitelet with a pdf from xml script in that same file cabinet location titled "depositSlipPDF.js" with the function "generatePdfFileFromRawXml" as follows.

define(['N/render', 'N/record'],
function(render, record) {
/**
  * @NApiVersion 2.x
  * @NScriptType Suitelet
  * @appliedtorecord deposit
  */
/**
  * onRequest event handler
   * @gov 0
  *
  * @param request
  *    {Object}
  * @param response
  *    {String}
  *
  * @return {void}
  *
  * @static
  * @function onRequest
  */

    function generatePdfFileFromRawXml() {
                var xml = '<?xml version="1.0"?>n<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">n<pdf>nn';

        xml += '
n';
        xml += '
n';
        xml += 'Deposit Number: ' + depositRecord.getFieldValue('tranid') + '	n';
        xml += '
n';
        xml += '
n';
        xml += 'Date: ' + depositRecord.getFieldValue('trandate') + '	n';
        xml += '
n';
        xml += '
n';
        xml += 'Total: ' + depositRecord.getFieldValue('total') + '	n';
        xml += '
n';
        xml += '
n';
        xml += 'Posting Period: ' + depositRecord.getFieldText('postingperiod') + '	n';
        xml += '
n';
        xml += '
n';

        xml += '

n';

        xml += '
n';
        xml += '
n';
        xml += '
n';
        xml += 'Date	n';
        xml += 'ID	n';
        xml += 'Customer	n';
        xml += 'Payment Amount	n';
        xml += 'Transaction Amount	n';
        xml += 'Transaction Type	n';
        xml += 'Payment Method	n';
        xml += '
n';
        xml += '
n';
        xml += '
n';

        for (var i = 1; i < parseInt(depositRecord.getLineItemCount('payment')) + 1; i++)
        {
        if (depositRecord.getLineItemValue('payment', 'deposit', i) == 'T')
        {
        xml += '
n';
        xml += '' + depositRecord.getLineItemValue('payment', 'docdate', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'docnumber', i) + '	n';
        xml += '' + depositRecord.getLineItemText('payment', 'entity', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'paymentamount', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'transactionamount', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'type', i) + '	n';
        xml += '' + depositRecord.getLineItemText('payment', 'paymentmethod', i) + '	n';
        xml += '
n';
        }
        }

        xml += '
n';
        xml += '
n';
        xml += 'n</pdf>';

        var pdfFile = render.xmlToPdf({
            xmlString: xmlStr
        });
    }
   return {
     onRequest: generatePdfFileFromRawXml
    }
});```

How do I call generatePdfFileFromRawXml(); from onButtonClick();?

Credit for getting this far goes to Stoic Software where SS2 is made understandable (thank you, Eric) and to teamtag for this post where I'm getting the code for these initial xml data pulls.

答:
Using input from both of the previous answers, here's the full working solution and screenshot of the result:

Step 1) Client Script to establish a click-handler for a custom button, this grabs the id of my current record and passes it to my suitelet which executes in a new window

```<code>define(['N/url', 'N/currentRecord'], function (url, currentRecord) {
/**
  *
  * @NApiVersion 2.x
  * @NScriptType ClientScript
  * @appliedtorecord deposit
  */
var exports = {};
/**
  * <code>pageInit</code> event handler
  *
  * @gov XXX
  *
  * @param context
  *             {Object}
  * @param context.mode
  *             {String} The access mode of the current record. will be one of
  *                 <ul>
  *                 <li>copy</li>
  *             <li>create</li>
  *             <li>edit</li>
  *             </ul>
  *
  * @return {void}
  *
  * @static
  * @function pageInit
  */
 function pageInit(context) {
     // TODO
 }
 function onButtonClick() {
  var suiteletUrl = url.resolveScript({
    scriptId: 'customscript_depositslip_pdf', //the script id of my suitelet
    deploymentId: 'customdeploy_depositslip_pdf', //the deployment id of my suitelet
    returnExternalUrl: false,
    params: {
        custom_id: currentRecord.get().id,
    },
 });
 window.open(suiteletUrl);
 }
 exports.onButtonClick = onButtonClick;
 exports.pageInit = pageInit;
 return exports;
 });
</code>```

Step 2) User Event Script to create a custom button visible in both edit and view modes of my deposit record and calls the click-handler from my Client Script.

```<code>define([], function () {
/**
  *
  * @NApiVersion 2.x
  * @NScriptType UserEventScript
  * @appliedtorecord deposit
  */
 var exports = {};
 /**
  * <code>beforeLoad</code> event handler
  *
  * @gov 0
  *
  * @param context
  *             {Object}
  * @param context.newRecord
  *             {record} the new record being loaded
  * @param context.type
  *             {UserEventType} the action that triggered this event
  * @param context.form
  *             {form} The current UI form
  *
  * @return {void}
  *
  * @static
  * @function beforeLoad
  */
  function beforeLoad(context) {
    context.form.addButton({
        id: "custpage_printdepositslip",
        label: "Print Deposit Slip",
        functionName: "onButtonClick"
    });
    context.form.clientScriptModulePath = "SuiteScripts/ss2-add-button/customDepositSlipButton.js"
    }
  exports.beforeLoad = beforeLoad;
  return exports;
 });
</code>```

Step 3) Suitelet Script to create a custom form from xml relative to the record id of the current deposit (where you clicked the button), which pulls info from the deposit sublist and returns it in an organized table in a pdf with a header and footer section that persist on each page if the table requires multiple pages.

```<code>define(['N/render', 'N/record', 'N/xml', 'N/format'],
function(render, record, xml, format) {
 /**
    *@NApiVersion 2.x
    * @NScriptType Suitelet
    * @appliedtorecord deposit
    */
 /**
    * <code>onRequest</code> event handler
    * @gov 0
    *
    * @param request
    *           {Object}
    * @param response
    *           {String}
    *
    * @return {void}
    *
    * @static
    * @function onRequest
    * @function generateXml
    */
function onRequest(context) {
    var id = context.request.parameters.custom_id;
    if (!id) {
        context.response.write('The parameter "custom_id" is required');
        return;
    }
    var xmlString = generateXml(id);
    context.response.renderPdf({ xmlString : xmlString });
}
function generateXml(id) {
      var depositRecord = record.load({ type: record.Type.DEPOSIT, id: id });
      var totes = depositRecord.getValue('total');
      var totally = format.format({value:totes, type:format.Type.CURRENCY});
      var fulldate = depositRecord.getValue('trandate');
      var mmdddate = format.format({value:fulldate, type:format.Type.DATE});
      var xml='<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">\n<pdf>\n<head>\n<macrolist>\n<macro id="nlheader">\n';
        xml += '<table width="100%" align="center" style="font-size:11px;">\n';
        xml += '<tr>\n';
        xml += '<td><b>Deposit Number:</b> ' + depositRecord.getValue('tranid') + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Date:</b> ' + mmdddate + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Account:</b> ' + depositRecord.getText('account') + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Total:</b> ' + totally + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Posting Period:</b> ' + depositRecord.getText('postingperiod') + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Memo:</b> ' + depositRecord.getText('memo') + '</td>\n';
        xml += '</tr>\n';
        xml += '</table>\n';
        xml += '</macro>\n<macro id="nlfooter">\n<table style="width: 100%;">\n<tr>\n<td align="right" style="padding: 0; font-size:8pt;">\n<p align="right" text-align="right" ><br /><pagenumber/> of <totalpages/></p>\n</td>\n</tr>\n</table>\n</macro>\n</macrolist>\n</head>\n<body header="nlheader" header-height="13%" footer="nlfooter" footer-height="10pt" padding="0.375in 0.5in 0.5in 0.5in"  style="font:10px arial, sans-serif; text-align:left;">\n';
        xml += '<table width="100%" align="center" cellpadding="4" cellspacing="0" style="text-align:left; border-left:1px solid #ccc; border-right:1px solid #ccc;">\n';
        xml += '<thead>\n';
        xml += '<tr style="border:1px solid #ccc; background-color:#efefef;">\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Date</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>ID</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Customer</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Payment Method</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Type</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Ref No.</b></th>\n';
        xml += '<th><b>Amount</b></th>\n';
        xml += '</tr>\n';
        xml += '</thead>\n';
        xml += '<tbody>\n';
        for (var i = 0; i < parseInt(depositRecord.getLineCount({sublistId: 'payment'})); i++)
        {
        var amt = depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'paymentamount', line: i});
        var payamt = format.format({value:amt, type:format.Type.CURRENCY});
        var longdate = depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'docdate', line: i});
        var shortdate = format.format({value:longdate, type:format.Type.DATE});
        if (depositRecord.getSublistText({sublistId: 'payment', fieldId: 'deposit', line: i}) == 'T')
        {
        xml += '<tr style="border-bottom:1px solid #ccc;">\n';
        xml += '<td style="border-right:1px solid #ccc;">' + shortdate  + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'docnumber', line: i}) + '</td>\n';
        var name= depositRecord.getSublistText({sublistId: 'payment', fieldId: 'entity', line: i})
                var andName = name.match('&')
                if(andName){
                var newName = name.replace("&", "&");
                xml += '<td style="border-right:1px solid #ccc;">' + newName + '</td>\n';
                }
                else
                    xml += '<td style="border-right:1px solid #ccc;">' + name + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistText({sublistId: 'payment', fieldId: 'paymentmethod', line: i}) + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'type', line: i}) + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'refnum', line: i}) + '</td>\n';
        xml += '<td align="right" style="text-align:right !important;"><p style="text-align:right !important;">' + payamt + '</p></td>\n';
        xml += '</tr>\n';
        }
        }
        xml += '</tbody>\n';
        xml += '</table>\n';
        xml += '</body>\n</pdf>';
      return xml;
    }
  return {
    generateXml:generateXml,
    onRequest: onRequest
  }
});
</code>```

The major hurdle I ran in to was that many of our customers have ampersands in their customer name and xml was interpreting this as an operator, this required the conditional ampersand handling on the "entity" sublist field. Additionally, xml wanted to return a much longer form of the date field which included time stamps, I'm using variables and the N/format module to change the date into a mm/dd/yyyy format on the resulting form.

All of this will put a custom button on your deposit screen labelled "Print Deposit Slip" or whatever you choose to label it in your User Event Script. And when you click on that, it should give you a pdf form in a new window that looks like this (note that potentially sensitive information has been pixelated for the purposes of this demo):

And that's it! I hope this helps someone else out in the future.

Body:
I'm a non-developer who's brand new to NetSuite and SuiteScript and I'm stumbling my way through.

The problem: For each deposit record I need to create a printable pdf which lists each of the payments on that record (a Bank Deposit Slip). I would like to call this pdf on a custom button to display in a new window that I can print from. I do not need to save the document in the file cabinet.

1. Right now I have a UserEvent button that shows up on Deposits in view and edit modes.

define([], function () {
  /**
   * @NApiVersion 2.x
  * @NScriptType UserEventScript
  */
 var exports = {};

 function beforeLoad(context) {
  context.form.addButton({
            id: "custpage_printdepositslip",
         label: "Print Deposit Slip",
   functionName: "onButtonClick"
        });
  context.form.clientScriptModulePath = "SuiteScripts/depositSlips/customDepositSlipButton.js"
 }

 exports.beforeLoad = beforeLoad;
 return exports;

});

2. This button calls a clickhandler function "onButtonClick" from a ClientScript named "customDepositSlipButton.js"

define(["N/ui/dialog"], function (dialog) {
  /**
   * @NApiVersion 2.x
  * @NScriptType ClientScript
  */
 var exports = {};

 function pageInit(context) {
   // TODO
 }

   function onButtonClick() {
     dialog.alert({
            title: "COMING SOON",
         message: "This feature will eventually create a bank deposit slip"
        });
 }

 exports.onButtonClick = onButtonClick;
 exports.pageInit = pageInit;
 return exports;

});

Currently this works, but only creates a dialog popup for testing purposes. So far, so good.
testing popup

And here's where I'm stuck: I don't understand how to now connect this to a function on a Suitelet which should generate a pdf file from xml.

3. I've set up a Suitelet with a pdf from xml script in that same file cabinet location titled "depositSlipPDF.js" with the function "generatePdfFileFromRawXml" as follows.

define(['N/render', 'N/record'],
function(render, record) {
/**
  * @NApiVersion 2.x
  * @NScriptType Suitelet
  * @appliedtorecord deposit
  */
/**
  * onRequest event handler
   * @gov 0
  *
  * @param request
  *    {Object}
  * @param response
  *    {String}
  *
  * @return {void}
  *
  * @static
  * @function onRequest
  */

    function generatePdfFileFromRawXml() {
                var xml = '<?xml version="1.0"?>n<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">n<pdf>nn';

        xml += '
n';
        xml += '
n';
        xml += 'Deposit Number: ' + depositRecord.getFieldValue('tranid') + '	n';
        xml += '
n';
        xml += '
n';
        xml += 'Date: ' + depositRecord.getFieldValue('trandate') + '	n';
        xml += '
n';
        xml += '
n';
        xml += 'Total: ' + depositRecord.getFieldValue('total') + '	n';
        xml += '
n';
        xml += '
n';
        xml += 'Posting Period: ' + depositRecord.getFieldText('postingperiod') + '	n';
        xml += '
n';
        xml += '
n';

        xml += '

n';

        xml += '
n';
        xml += '
n';
        xml += '
n';
        xml += 'Date	n';
        xml += 'ID	n';
        xml += 'Customer	n';
        xml += 'Payment Amount	n';
        xml += 'Transaction Amount	n';
        xml += 'Transaction Type	n';
        xml += 'Payment Method	n';
        xml += '
n';
        xml += '
n';
        xml += '
n';

        for (var i = 1; i < parseInt(depositRecord.getLineItemCount('payment')) + 1; i++)
        {
        if (depositRecord.getLineItemValue('payment', 'deposit', i) == 'T')
        {
        xml += '
n';
        xml += '' + depositRecord.getLineItemValue('payment', 'docdate', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'docnumber', i) + '	n';
        xml += '' + depositRecord.getLineItemText('payment', 'entity', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'paymentamount', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'transactionamount', i) + '	n';
        xml += '' + depositRecord.getLineItemValue('payment', 'type', i) + '	n';
        xml += '' + depositRecord.getLineItemText('payment', 'paymentmethod', i) + '	n';
        xml += '
n';
        }
        }

        xml += '
n';
        xml += '
n';
        xml += 'n</pdf>';

        var pdfFile = render.xmlToPdf({
            xmlString: xmlStr
        });
    }
   return {
     onRequest: generatePdfFileFromRawXml
    }
});

How do I call generatePdfFileFromRawXml(); from onButtonClick();?

Credit for getting this far goes to Stoic Software where SS2 is made understandable (thank you, Eric) and to teamtag for this post where I'm getting the code for these initial xml data pulls.

Body:
Using input from both of the previous answers, here's the full working solution and screenshot of the result:

Step 1) Client Script to establish a click-handler for a custom button, this grabs the id of my current record and passes it to my suitelet which executes in a new window

define(['N/url', 'N/currentRecord'], function (url, currentRecord) {
/**
  *
  * @NApiVersion 2.x
  * @NScriptType ClientScript
  * @appliedtorecord deposit
  */
var exports = {};
/**
  * <code>pageInit</code> event handler
  *
  * @gov XXX
  *
  * @param context
  *             {Object}
  * @param context.mode
  *             {String} The access mode of the current record. will be one of
  *                 <ul>
  *                 <li>copy</li>
  *             <li>create</li>
  *             <li>edit</li>
  *             </ul>
  *
  * @return {void}
  *
  * @static
  * @function pageInit
  */
 function pageInit(context) {
     // TODO
 }
 function onButtonClick() {
  var suiteletUrl = url.resolveScript({
    scriptId: 'customscript_depositslip_pdf', //the script id of my suitelet
    deploymentId: 'customdeploy_depositslip_pdf', //the deployment id of my suitelet
    returnExternalUrl: false,
    params: {
        custom_id: currentRecord.get().id,
    },
 });
 window.open(suiteletUrl);
 }
 exports.onButtonClick = onButtonClick;
 exports.pageInit = pageInit;
 return exports;
 });

Step 2) User Event Script to create a custom button visible in both edit and view modes of my deposit record and calls the click-handler from my Client Script.

define([], function () {
/**
  *
  * @NApiVersion 2.x
  * @NScriptType UserEventScript
  * @appliedtorecord deposit
  */
 var exports = {};
 /**
  * <code>beforeLoad</code> event handler
  *
  * @gov 0
  *
  * @param context
  *             {Object}
  * @param context.newRecord
  *             {record} the new record being loaded
  * @param context.type
  *             {UserEventType} the action that triggered this event
  * @param context.form
  *             {form} The current UI form
  *
  * @return {void}
  *
  * @static
  * @function beforeLoad
  */
  function beforeLoad(context) {
    context.form.addButton({
        id: "custpage_printdepositslip",
        label: "Print Deposit Slip",
        functionName: "onButtonClick"
    });
    context.form.clientScriptModulePath = "SuiteScripts/ss2-add-button/customDepositSlipButton.js"
    }
  exports.beforeLoad = beforeLoad;
  return exports;
 });

Step 3) Suitelet Script to create a custom form from xml relative to the record id of the current deposit (where you clicked the button), which pulls info from the deposit sublist and returns it in an organized table in a pdf with a header and footer section that persist on each page if the table requires multiple pages.

define(['N/render', 'N/record', 'N/xml', 'N/format'],
function(render, record, xml, format) {
 /**
    *@NApiVersion 2.x
    * @NScriptType Suitelet
    * @appliedtorecord deposit
    */
 /**
    * <code>onRequest</code> event handler
    * @gov 0
    *
    * @param request
    *           {Object}
    * @param response
    *           {String}
    *
    * @return {void}
    *
    * @static
    * @function onRequest
    * @function generateXml
    */
function onRequest(context) {
    var id = context.request.parameters.custom_id;
    if (!id) {
        context.response.write('The parameter "custom_id" is required');
        return;
    }
    var xmlString = generateXml(id);
    context.response.renderPdf({ xmlString : xmlString });
}
function generateXml(id) {
      var depositRecord = record.load({ type: record.Type.DEPOSIT, id: id });
      var totes = depositRecord.getValue('total');
      var totally = format.format({value:totes, type:format.Type.CURRENCY});
      var fulldate = depositRecord.getValue('trandate');
      var mmdddate = format.format({value:fulldate, type:format.Type.DATE});
      var xml='<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE pdf PUBLIC "-//big.faceless.org//report" "report-1.1.dtd">\n<pdf>\n<head>\n<macrolist>\n<macro id="nlheader">\n';
        xml += '<table width="100%" align="center" style="font-size:11px;">\n';
        xml += '<tr>\n';
        xml += '<td><b>Deposit Number:</b> ' + depositRecord.getValue('tranid') + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Date:</b> ' + mmdddate + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Account:</b> ' + depositRecord.getText('account') + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Total:</b> ' + totally + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Posting Period:</b> ' + depositRecord.getText('postingperiod') + '</td>\n';
        xml += '</tr>\n';
        xml += '<tr>\n';
        xml += '<td><b>Memo:</b> ' + depositRecord.getText('memo') + '</td>\n';
        xml += '</tr>\n';
        xml += '</table>\n';
        xml += '</macro>\n<macro id="nlfooter">\n<table style="width: 100%;">\n<tr>\n<td align="right" style="padding: 0; font-size:8pt;">\n<p align="right" text-align="right" ><br /><pagenumber/> of <totalpages/></p>\n</td>\n</tr>\n</table>\n</macro>\n</macrolist>\n</head>\n<body header="nlheader" header-height="13%" footer="nlfooter" footer-height="10pt" padding="0.375in 0.5in 0.5in 0.5in"  style="font:10px arial, sans-serif; text-align:left;">\n';
        xml += '<table width="100%" align="center" cellpadding="4" cellspacing="0" style="text-align:left; border-left:1px solid #ccc; border-right:1px solid #ccc;">\n';
        xml += '<thead>\n';
        xml += '<tr style="border:1px solid #ccc; background-color:#efefef;">\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Date</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>ID</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Customer</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Payment Method</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Type</b></th>\n';
        xml += '<th style="border-right:1px solid #ccc;"><b>Ref No.</b></th>\n';
        xml += '<th><b>Amount</b></th>\n';
        xml += '</tr>\n';
        xml += '</thead>\n';
        xml += '<tbody>\n';
        for (var i = 0; i < parseInt(depositRecord.getLineCount({sublistId: 'payment'})); i++)
        {
        var amt = depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'paymentamount', line: i});
        var payamt = format.format({value:amt, type:format.Type.CURRENCY});
        var longdate = depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'docdate', line: i});
        var shortdate = format.format({value:longdate, type:format.Type.DATE});
        if (depositRecord.getSublistText({sublistId: 'payment', fieldId: 'deposit', line: i}) == 'T')
        {
        xml += '<tr style="border-bottom:1px solid #ccc;">\n';
        xml += '<td style="border-right:1px solid #ccc;">' + shortdate  + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'docnumber', line: i}) + '</td>\n';
        var name= depositRecord.getSublistText({sublistId: 'payment', fieldId: 'entity', line: i})
                var andName = name.match('&')
                if(andName){
                var newName = name.replace("&", "&amp;");
                xml += '<td style="border-right:1px solid #ccc;">' + newName + '</td>\n';
                }
                else
                    xml += '<td style="border-right:1px solid #ccc;">' + name + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistText({sublistId: 'payment', fieldId: 'paymentmethod', line: i}) + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'type', line: i}) + '</td>\n';
        xml += '<td style="border-right:1px solid #ccc;">' + depositRecord.getSublistValue({sublistId: 'payment', fieldId: 'refnum', line: i}) + '</td>\n';
        xml += '<td align="right" style="text-align:right !important;"><p style="text-align:right !important;">' + payamt + '</p></td>\n';
        xml += '</tr>\n';
        }
        }
        xml += '</tbody>\n';
        xml += '</table>\n';
        xml += '</body>\n</pdf>';
      return xml;
    }
  return {
    generateXml:generateXml,
    onRequest: onRequest
  }
});

The major hurdle I ran in to was that many of our customers have ampersands in their customer name and xml was interpreting this as an operator, this required the conditional ampersand handling on the "entity" sublist field. Additionally, xml wanted to return a much longer form of the date field which included time stamps, I'm using variables and the N/format module to change the date into a mm/dd/yyyy format on the resulting form.

All of this will put a custom button on your deposit screen labelled "Print Deposit Slip" or whatever you choose to label it in your User Event Script. And when you click on that, it should give you a pdf form in a new window that looks like this (note that potentially sensitive information has been pixelated for the purposes of this demo):

And that's it! I hope this helps someone else out in the future.


问:
How do I use Boolean logic within a pyspark dataframe for sets
I'm trying to create a new column in a pyspark dataframe that is predicated on the contents of another column. The other column has all integers, and I want the new column to be encoded with either 1's or 0's.

import pyspark.sql.functions as F
df2 = df2.withColumn('Industrial', F.when(F.col('CODE') in (1,2,3,4), 1).otherwise(0))
```

This doesn't work since it wants just Boolean logic. Is there a work around for this?

EDIT: Could still be useful for others since it creates a new column and does a little more than just a check of isin().

答:
Use col.isin method

```<code>df2 = df2.withColumn('Industrial', F.when(F.col('CODE').isin((1,2,3,4)), 1).otherwise(0))
</code>```

Body:
I'm trying to create a new column in a pyspark dataframe that is predicated on the contents of another column. The other column has all integers, and I want the new column to be encoded with either 1's or 0's.

import pyspark.sql.functions as F
df2 = df2.withColumn('Industrial', F.when(F.col('CODE') in (1,2,3,4), 1).otherwise(0))

This doesn't work since it wants just Boolean logic. Is there a work around for this?

EDIT: Could still be useful for others since it creates a new column and does a little more than just a check of isin().

Body:
Use col.isin method

df2 = df2.withColumn('Industrial', F.when(F.col('CODE').isin((1,2,3,4)), 1).otherwise(0))


问:
How do I display a UISearchController on a UINavigationItem without an underlying UIScrollView?
Maybe this is impossible, but I always assumed you could just throw a UISearchController instance onto any old view controller's navigationItem and get a search bar. It seems to me like no matter what I try, I can't get it to work. It's making me think this behavior is hardcoded to only work when the view controller's view property is a subclass of UIScrollView.

I hope this is just a red herring. If I missed something obvious, please help! This is infuriating.

Here's what I did:

```<code>import UIKit.UIViewController

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.hidesSearchBarWhenScrolling = false

        navigationItem.searchController = {
            let searchController = UISearchController()
            searchController.hidesNavigationBarDuringPresentation = false
            searchController.dimsBackgroundDuringPresentation = false
            searchController.obscuresBackgroundDuringPresentation = false
            return searchController
        }()
    }
}
</code>```

No search bar ever appears on screen. It just looks like a regular old navigation bar.

答:
The UISearchController initializer should be let searchController = UISearchController(searchResultsController: nil) or replace nil with a seperate controller to display the search results.

If your viewController is in a UINavigationController stack then the above code should work (with the corrected initializer). Otherwise you will need to create a UINavigationBar and add it to the view. Then add the searchController.searchBar to the navigationItem.titleView

```<code>    let navigationBar = UINavigationBar()
    view.addSubview(navigationBar)
    navigationBar.barTintColor = UIColor.gray
    navigationBar.translatesAutoresizingMaskIntoConstraints = false
    navigationBar.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    navigationBar.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    navigationBar.delegate = self

    navigationBar.items = [navigationItem]

    navigationItem.searchController = {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.dimsBackgroundDuringPresentation = false
        searchController.obscuresBackgroundDuringPresentation = false
        return searchController
    }()

    navigationItem.titleView = navigationItem.searchController?.searchBar
</code>```

Body:
Maybe this is impossible, but I always assumed you could just throw a UISearchController instance onto any old view controller's navigationItem and get a search bar. It seems to me like no matter what I try, I can't get it to work. It's making me think this behavior is hardcoded to only work when the view controller's view property is a subclass of UIScrollView.

I hope this is just a red herring. If I missed something obvious, please help! This is infuriating.

Here's what I did:

import UIKit.UIViewController

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.hidesSearchBarWhenScrolling = false

        navigationItem.searchController = {
            let searchController = UISearchController()
            searchController.hidesNavigationBarDuringPresentation = false
            searchController.dimsBackgroundDuringPresentation = false
            searchController.obscuresBackgroundDuringPresentation = false
            return searchController
        }()
    }
}

No search bar ever appears on screen. It just looks like a regular old navigation bar.

Body:
The UISearchController initializer should be let searchController = UISearchController(searchResultsController: nil) or replace nil with a seperate controller to display the search results.

If your viewController is in a UINavigationController stack then the above code should work (with the corrected initializer). Otherwise you will need to create a UINavigationBar and add it to the view. Then add the searchController.searchBar to the navigationItem.titleView

    let navigationBar = UINavigationBar()
    view.addSubview(navigationBar)
    navigationBar.barTintColor = UIColor.gray
    navigationBar.translatesAutoresizingMaskIntoConstraints = false
    navigationBar.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    navigationBar.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    navigationBar.delegate = self

    navigationBar.items = [navigationItem]

    navigationItem.searchController = {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.dimsBackgroundDuringPresentation = false
        searchController.obscuresBackgroundDuringPresentation = false
        return searchController
    }()

    navigationItem.titleView = navigationItem.searchController?.searchBar


问:
Winsock udp recv not receiving all data even within a loop
I have some UDP recv code utilizing winsock, specifically AF_INET, SOCK_DGRAM, and IPPROTO_UDP. The recv call exists in a loop that reads until all data is received. The problem is that I only get partial data every time. Furthermore I shouldn't even need the loop since I can see that all the data exists in a single packet. In wireshark I see that the real data length is 299 bytes. Wireshark successfully sees the entire packet so I know the packet sender is working correctly.

With my windows UDP code I only get 8 bytes until my receive method returns. I can see that the UDP code is stopping when it sees a 00 byte. Wireshark is able to read past those 00 bytes but windows udp recv is not able to read past it. It seems like windows sees the 00 as the end and therefore concludes that the packet is only 8 bytes.

I have looked at the header in wireshark and I see that the length specified is correct so i'm very confused as to why its only reading 8 bytes. Thank you for your help in advance.

This is what my receive call looks like for reference:

```<code>int ret = recv(socket, buffer, 1500, 0);
</code>```

ret becomes 8 and buffer, which has been allocated to be 1500 bytes, is only filled with 8 bytes

答:
UDP is message-oriented, not stream-oriented like TCP is.

In UDP, the only way that recv() would return 8 bytes is if either:

you set the len parameter to > 8, and a datagram containing exactly 8 bytes is received.

you set the len parameter to == 8, and a datagram containing more than 8 bytes is received.

Given your claim that that you are setting the len to 1500, then the only possibility is that the datagram received only has 8 bytes in it, not 299 bytes like you claim.

Unlike in TCP, in UDP you cannot read a datagram in pieces, a read is an all-or-nothing operation (unless you peek the data, which you are not doing).  In UDP, recv()/recvfrom() reads whole datagrams at a time, and if the provided buffer is too small to receive the data (which it is not in this case) then an WSAEMSGSIZE error is reported and the data is truncated, discarding the rest of the data that does not fit in the buffer.

The 00 null bytes you describe have NO EFFECT WHATEVER on recv()/recvfrom()'s ability to read a whole datagram.  A datagram carries a payload length, and recv()/recvfrom() will read up to that payload length or the specified buffer size, whichever is smaller, regardless of the actual payload content.

So, chances are, in your code, recv() is simply not receiving the datagram you are expecting.

For instance, in order to use recv() in UDP at all, you must connect() the UDP socket first to associate it with a specific peer IP/port, thus allowing recv() to ignore inbound datagrams from other peers (and for send() to send datagrams to a specific peer).  Maybe you are connect'ing your UDP socket to the wrong peer, and thus reading datagrams that are meant for something else.  Or, maybe you are connect'ing to the correct peer and it really is sending an 8-byte datagram that you are not expecting.

Since you did not provide any context info about your setup, the peer involved, the protocol involved, the Wireshark capture, nothing, there is really no way for anyone here to diagnose your situation with any certainty.  But, what I described above would account for the symptom you have described.  If you feel that is not the case, then you need to edit your question to provide more details.

Body:
I have some UDP recv code utilizing winsock, specifically AF_INET, SOCK_DGRAM, and IPPROTO_UDP. The recv call exists in a loop that reads until all data is received. The problem is that I only get partial data every time. Furthermore I shouldn't even need the loop since I can see that all the data exists in a single packet. In wireshark I see that the real data length is 299 bytes. Wireshark successfully sees the entire packet so I know the packet sender is working correctly.

With my windows UDP code I only get 8 bytes until my receive method returns. I can see that the UDP code is stopping when it sees a 00 byte. Wireshark is able to read past those 00 bytes but windows udp recv is not able to read past it. It seems like windows sees the 00 as the end and therefore concludes that the packet is only 8 bytes.

I have looked at the header in wireshark and I see that the length specified is correct so i'm very confused as to why its only reading 8 bytes. Thank you for your help in advance.

This is what my receive call looks like for reference:

int ret = recv(socket, buffer, 1500, 0);

ret becomes 8 and buffer, which has been allocated to be 1500 bytes, is only filled with 8 bytes