问:
RxJava issue with zip operator
I am facing issue with zip operation, I have 3 Observables that I am combining with zip operator. The problem is sometimes the statement in the subscribe code does not get executed. Is the zip operator not supposed to wait for all the observable to emit the event. Below is the sample code.</p>

```<code>import java.util.Date;

import rx.Observable;
import rx.schedulers.Schedulers;
public class ZipRxJava {

    public static void main(String[] args) {
        ZipRxJava z = new ZipRxJava();
        Observable<CartPlanResponse> o1 = Observable.<CartPlanResponse>create(sub -> sub.onNext(createPlanResponse(z))).subscribeOn(Schedulers.io());
        Observable<CartFeatureResponse> o2 = Observable.<CartFeatureResponse>create(sub -> sub.onNext(createFeatureResponse(z))).subscribeOn(Schedulers.io());
        Observable<CartAccessoriesResponse> o3 = Observable.<CartAccessoriesResponse>create(sub -> sub.onNext(createAccessoriesResponse(z))).subscribeOn(Schedulers.io());
        Observable.zip(o1, o2, o3, (p1, p2, p3) -> {
            System.out.println("Inside Transformer $$$$$$$$$$$››››" + Thread.currentThread().getName());
            Response res = z.new Response();
            res.setPlanResponse(p1);
            res.setFeatureResponse(p2);
            res.setAccesoriesResponse(p3);
            return res;
        }).subscribe(r1 -> System.out.println("&&&&&&&&&&&"+ Thread.currentThread().getName() + "*******" +  r1.getPlanResponse().getPlanId() + " " + r1.getFeatureResponse().getFeatureId() + " " +
            r1.getAccesoriesResponse().getAccessoryId()), e1 -> System.out.println("Error"));
        System.out.println("Main Method ********** " + Thread.currentThread().getName());
    }

    private static CartPlanResponse createPlanResponse(ZipRxJava z) {
        System.out.println("Plan ********** " + Thread.currentThread().getName());
        CartPlanResponse res = z.new CartPlanResponse();
        res.setPlanId("123");
        System.out.println("Before Return Plan ********** " + Thread.currentThread().getName());
        return res;
    }

    private static CartFeatureResponse createFeatureResponse(ZipRxJava z) {
        System.out.println("Feature ********** " + Thread.currentThread().getName());
        //sleep();
        int y =0;
        for (int i =0 ; i <100000000; i++) {
            y +=i;
        }
        CartFeatureResponse res = z.new CartFeatureResponse();
        res.setFeatureId("345");
        System.out.println("Before Return Feature ********** " + Thread.currentThread().getName());
        return res;
    }

    private static CartAccessoriesResponse createAccessoriesResponse(ZipRxJava z) {
        System.out.println("Accessories ********** " + Thread.currentThread().getName());
        CartAccessoriesResponse res = z.new CartAccessoriesResponse();
        res.setAccessoryId("567");
        System.out.println("Before Return Accessories ********** " + Thread.currentThread().getName());
        return res;
    }

    private static void sleep() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private class CartPlanResponse {
        String planId;

        public String getPlanId() {
            return planId;
        }

        public void setPlanId(String planId) {
            this.planId = planId;
        }
    }

    private class CartFeatureResponse {
        private String featureId;

        public String getFeatureId() {
            return featureId;
        }

        public void setFeatureId(String featureId) {
            this.featureId = featureId;
        }
    }

    private class CartAccessoriesResponse {
        private String accessoryId;

        public String getAccessoryId() {
            return accessoryId;
        }

        public void setAccessoryId(String accessoryId) {
            this.accessoryId = accessoryId;
        }
    }

    private class Response {
        private CartPlanResponse planResponse;
        private CartFeatureResponse featureResponse;
        private CartAccessoriesResponse accesoriesResponse;
        public CartPlanResponse getPlanResponse() {
            return planResponse;
        }
        public void setPlanResponse(CartPlanResponse planResponse) {
            this.planResponse = planResponse;
        }
        public CartFeatureResponse getFeatureResponse() {
            return featureResponse;
        }
        public void setFeatureResponse(CartFeatureResponse featureResponse) {
            this.featureResponse = featureResponse;
        }
        public CartAccessoriesResponse getAccesoriesResponse() {
            return accesoriesResponse;
        }
        public void setAccesoriesResponse(CartAccessoriesResponse accesoriesResponse) {
            this.accesoriesResponse = accesoriesResponse;
        }

    }
</code>```

答:
You have to sleep in the main method because RxJava Schedulers run on daemon threads which stop and don't execute work if the main thread quits in your case:

```<code>    System.out.println("Main Method ********** " + Thread.currentThread().getName());
    sleep();
</code>```

Prints:

```<code>Plan ********** RxIoScheduler-2
Before Return Plan ********** RxIoScheduler-2
Feature ********** RxIoScheduler-3
Main Method ********** main
Accessories ********** RxIoScheduler-4
Before Return Accessories ********** RxIoScheduler-4
Before Return Feature ********** RxIoScheduler-3
Inside Transformer $$$$$$$$$$$››››RxIoScheduler-3
&&&&&&&&&&&RxIoScheduler-3*******123 345 567
</code>```

Title: RxJava issue with zip operator

Body:
I am facing issue with zip operation, I have 3 Observables that I am combining with zip operator. The problem is sometimes the statement in the subscribe code does not get executed. Is the zip operator not supposed to wait for all the observable to emit the event. Below is the sample code.

import java.util.Date;

import rx.Observable;
import rx.schedulers.Schedulers;
public class ZipRxJava {

    public static void main(String[] args) {
        ZipRxJava z = new ZipRxJava();
        Observable<CartPlanResponse> o1 = Observable.<CartPlanResponse>create(sub -> sub.onNext(createPlanResponse(z))).subscribeOn(Schedulers.io());
        Observable<CartFeatureResponse> o2 = Observable.<CartFeatureResponse>create(sub -> sub.onNext(createFeatureResponse(z))).subscribeOn(Schedulers.io());
        Observable<CartAccessoriesResponse> o3 = Observable.<CartAccessoriesResponse>create(sub -> sub.onNext(createAccessoriesResponse(z))).subscribeOn(Schedulers.io());
        Observable.zip(o1, o2, o3, (p1, p2, p3) -> {
            System.out.println("Inside Transformer $$$$$$$$$$$››››" + Thread.currentThread().getName());
            Response res = z.new Response();
            res.setPlanResponse(p1);
            res.setFeatureResponse(p2);
            res.setAccesoriesResponse(p3);
            return res;
        }).subscribe(r1 -> System.out.println("&&&&&&&&&&&"+ Thread.currentThread().getName() + "*******" +  r1.getPlanResponse().getPlanId() + " " + r1.getFeatureResponse().getFeatureId() + " " +
            r1.getAccesoriesResponse().getAccessoryId()), e1 -> System.out.println("Error"));
        System.out.println("Main Method ********** " + Thread.currentThread().getName());
    }

    private static CartPlanResponse createPlanResponse(ZipRxJava z) {
        System.out.println("Plan ********** " + Thread.currentThread().getName());
        CartPlanResponse res = z.new CartPlanResponse();
        res.setPlanId("123");
        System.out.println("Before Return Plan ********** " + Thread.currentThread().getName());
        return res;
    }

    private static CartFeatureResponse createFeatureResponse(ZipRxJava z) {
        System.out.println("Feature ********** " + Thread.currentThread().getName());
        //sleep();
        int y =0;
        for (int i =0 ; i <100000000; i++) {
            y +=i;
        }
        CartFeatureResponse res = z.new CartFeatureResponse();
        res.setFeatureId("345");
        System.out.println("Before Return Feature ********** " + Thread.currentThread().getName());
        return res;
    }

    private static CartAccessoriesResponse createAccessoriesResponse(ZipRxJava z) {
        System.out.println("Accessories ********** " + Thread.currentThread().getName());
        CartAccessoriesResponse res = z.new CartAccessoriesResponse();
        res.setAccessoryId("567");
        System.out.println("Before Return Accessories ********** " + Thread.currentThread().getName());
        return res;
    }

    private static void sleep() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private class CartPlanResponse {
        String planId;

        public String getPlanId() {
            return planId;
        }

        public void setPlanId(String planId) {
            this.planId = planId;
        }
    }

    private class CartFeatureResponse {
        private String featureId;

        public String getFeatureId() {
            return featureId;
        }

        public void setFeatureId(String featureId) {
            this.featureId = featureId;
        }
    }

    private class CartAccessoriesResponse {
        private String accessoryId;

        public String getAccessoryId() {
            return accessoryId;
        }

        public void setAccessoryId(String accessoryId) {
            this.accessoryId = accessoryId;
        }
    }

    private class Response {
        private CartPlanResponse planResponse;
        private CartFeatureResponse featureResponse;
        private CartAccessoriesResponse accesoriesResponse;
        public CartPlanResponse getPlanResponse() {
            return planResponse;
        }
        public void setPlanResponse(CartPlanResponse planResponse) {
            this.planResponse = planResponse;
        }
        public CartFeatureResponse getFeatureResponse() {
            return featureResponse;
        }
        public void setFeatureResponse(CartFeatureResponse featureResponse) {
            this.featureResponse = featureResponse;
        }
        public CartAccessoriesResponse getAccesoriesResponse() {
            return accesoriesResponse;
        }
        public void setAccesoriesResponse(CartAccessoriesResponse accesoriesResponse) {
            this.accesoriesResponse = accesoriesResponse;
        }

    }

Body:
You have to sleep in the main method because RxJava Schedulers run on daemon threads which stop and don't execute work if the main thread quits in your case:

    System.out.println("Main Method ********** " + Thread.currentThread().getName());
    sleep();

Prints:

Plan ********** RxIoScheduler-2
Before Return Plan ********** RxIoScheduler-2
Feature ********** RxIoScheduler-3
Main Method ********** main
Accessories ********** RxIoScheduler-4
Before Return Accessories ********** RxIoScheduler-4
Before Return Feature ********** RxIoScheduler-3
Inside Transformer $$$$$$$$$$$››››RxIoScheduler-3
&&&&&&&&&&&RxIoScheduler-3*******123 345 567


来源: stackexchange

问:
How do I convert a cell that has only a year (probably a string) into DateTime datatype?
I've got cells in an excel file that contain data like:

"2006","2005","2015"

It is read into a datagridview temporarily, which is later inserted into an access database like so:

```<code>using (OleDbConnection conn = new OleDbConnection(Con))
{
    using (OleDbCommand cmd = new OleDbCommand())
    {
        cmd.Connection = conn;
        conn.Open();
        cmd.CommandText =
        "Insert INTO ACTB (ID,Business,Account,Description,Span_Year,Period,Amount_PHP,Project_Number,Status_Regime,Department,Description_Dept,Accounts,Class) " +
        "VALUES(@ID,@Business,@Account,@Description,@Span_Year,@Period,@Amount_PHP,@Project_Number,@Status_Regime,@Department,@Description_Dept,@Accounts,@Class)";
        for (int s = 0; s < DGVExcel.Rows.Count; s++)
        {
            cmd.Parameters.Clear();
            int theDoubleDate = Convert.ToInt32(DGVExcel.Rows[s].Cells[4].Value);
            DateTime theDate = DateTime.FromOADate(theDoubleDate);
            cmd.Parameters.AddWithValue("@ID", DGVExcel.Rows[s].Cells[0].Value);
            cmd.Parameters.AddWithValue("@Business_Unit", DGVExcel.Rows[s].Cells[1].Value);
            cmd.Parameters.AddWithValue("@Account", DGVExcel.Rows[s].Cells[2].Value);
            cmd.Parameters.AddWithValue("@Description", DGVExcel.Rows[s].Cells[3].Value);
            cmd.Parameters.AddWithValue("@Span_Year", theDate);
            cmd.Parameters.AddWithValue("@Period", DGVExcel.Rows[s].Cells[5].Value);
            cmd.Parameters.AddWithValue("@Amount_PHP", DGVExcel.Rows[s].Cells[6].Value == null ? 0 : Convert.ToDouble(DGVExcel.Rows[s].Cells[6].Value));
            cmd.Parameters.AddWithValue("@Project_Number", DGVExcel.Rows[s].Cells[7].Value);
            cmd.Parameters.AddWithValue("@Status_Regime", DGVExcel.Rows[s].Cells[8].Value);
            cmd.Parameters.AddWithValue("@Department", DGVExcel.Rows[s].Cells[9].Value);
            cmd.Parameters.AddWithValue("@Description_Dept", DGVExcel.Rows[s].Cells[10].Value);
            cmd.Parameters.AddWithValue("@IS_Accounts", DGVExcel.Rows[s].Cells[11].Value);
            cmd.Parameters.AddWithValue("@ITR_Class", DGVExcel.Rows[s].Cells[12].Value);
            cmd.ExecuteNonQuery();
        }
    }
}
</code>```

However, these write the values wrong, like 8/7/1905 all ending in 1905.

Another requirement is that the end value be day and month agnostic, meaning the value would come up as say: 2016 => 1/1/2016, just before the data is inserted into the database. Some have suggested that I merely use int values, however, datetime is required for me because I intend to use the between keyword to easily look up data between certain periods.

Edit: I just realized that some of my data might not have a year listed. Normally, I could be able to insert nulls just fine, however, if I'm doing some convert before that, I'm sure it will throw an exception like Cannot convert DB.Null into other types.

答:
You can check if there is a value in the cell and then create a new DateTime

```<code>if (string.IsNullOrEmpty(DGVExcel.Rows[s].Cells[3].Value))
{
    cmd.Parameters.AddWithValue("@Span_Year", DateTime.Now.Date);
}
else
{
    cmd.Parameters.AddWithValue("@Span_Year", new DateTime(Convert.ToInt32(DGVExcel.Rows[s].Cells[3].Value), 1, 1);
}
</code>```

I would also recommend specifying the datatype in the parameter, this will provide more type-safety and prevent conversion errors with datetime.

```<code>cmd.Parameters.Add("@ID", SqlDbType.Int).Value = 45;
cmd.Parameters.Add("@Span_Year", SqlDbType.DateTime).Value = date;
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I've got cells in an excel file that contain data like:

"2006","2005","2015"

It is read into a datagridview temporarily, which is later inserted into an access database like so:

using (OleDbConnection conn = new OleDbConnection(Con))
{
    using (OleDbCommand cmd = new OleDbCommand())
    {
        cmd.Connection = conn;
        conn.Open();
        cmd.CommandText =
        "Insert INTO ACTB (ID,Business,Account,Description,Span_Year,Period,Amount_PHP,Project_Number,Status_Regime,Department,Description_Dept,Accounts,Class) " +
        "VALUES(@ID,@Business,@Account,@Description,@Span_Year,@Period,@Amount_PHP,@Project_Number,@Status_Regime,@Department,@Description_Dept,@Accounts,@Class)";
        for (int s = 0; s < DGVExcel.Rows.Count; s++)
        {
            cmd.Parameters.Clear();
            int theDoubleDate = Convert.ToInt32(DGVExcel.Rows[s].Cells[4].Value);
            DateTime theDate = DateTime.FromOADate(theDoubleDate);
            cmd.Parameters.AddWithValue("@ID", DGVExcel.Rows[s].Cells[0].Value);
            cmd.Parameters.AddWithValue("@Business_Unit", DGVExcel.Rows[s].Cells[1].Value);
            cmd.Parameters.AddWithValue("@Account", DGVExcel.Rows[s].Cells[2].Value);
            cmd.Parameters.AddWithValue("@Description", DGVExcel.Rows[s].Cells[3].Value);
            cmd.Parameters.AddWithValue("@Span_Year", theDate);
            cmd.Parameters.AddWithValue("@Period", DGVExcel.Rows[s].Cells[5].Value);
            cmd.Parameters.AddWithValue("@Amount_PHP", DGVExcel.Rows[s].Cells[6].Value == null ? 0 : Convert.ToDouble(DGVExcel.Rows[s].Cells[6].Value));
            cmd.Parameters.AddWithValue("@Project_Number", DGVExcel.Rows[s].Cells[7].Value);
            cmd.Parameters.AddWithValue("@Status_Regime", DGVExcel.Rows[s].Cells[8].Value);
            cmd.Parameters.AddWithValue("@Department", DGVExcel.Rows[s].Cells[9].Value);
            cmd.Parameters.AddWithValue("@Description_Dept", DGVExcel.Rows[s].Cells[10].Value);
            cmd.Parameters.AddWithValue("@IS_Accounts", DGVExcel.Rows[s].Cells[11].Value);
            cmd.Parameters.AddWithValue("@ITR_Class", DGVExcel.Rows[s].Cells[12].Value);
            cmd.ExecuteNonQuery();
        }
    }
}

However, these write the values wrong, like 8/7/1905 all ending in 1905.

Another requirement is that the end value be day and month agnostic, meaning the value would come up as say: 2016 => 1/1/2016, just before the data is inserted into the database. Some have suggested that I merely use int values, however, datetime is required for me because I intend to use the between keyword to easily look up data between certain periods.

Edit: I just realized that some of my data might not have a year listed. Normally, I could be able to insert nulls just fine, however, if I'm doing some convert before that, I'm sure it will throw an exception like Cannot convert DB.Null into other types.

Body:
You can check if there is a value in the cell and then create a new DateTime

if (string.IsNullOrEmpty(DGVExcel.Rows[s].Cells[3].Value))
{
    cmd.Parameters.AddWithValue("@Span_Year", DateTime.Now.Date);
}
else
{
    cmd.Parameters.AddWithValue("@Span_Year", new DateTime(Convert.ToInt32(DGVExcel.Rows[s].Cells[3].Value), 1, 1);
}

I would also recommend specifying the datatype in the parameter, this will provide more type-safety and prevent conversion errors with datetime.

cmd.Parameters.Add("@ID", SqlDbType.Int).Value = 45;
cmd.Parameters.Add("@Span_Year", SqlDbType.DateTime).Value = date;


问:
submitting POST data when you hang up on Twilio
I have an application that runs with Twilio. The idea is that you will call a phone number twilio will answer and give you menu options. Once you press a digit it will submit the post data and then hang up (That part all works correctly) The problem I'm having is finding out if there is a way to submit post data if the user just hangs up as soon as twilio answers... I found the following code on their documentation.

```<code><?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/gather_hints.xml -->
<Response>
 <Gather action="/process_gather.php" method="GET">
     <Say>Enter something, or not</Say>
 </Gather>
 <Redirect method="GET">
     /process_gather.php?Digits=TIMEOUT
 </Redirect>
</Response>
</code>```

The problem with this is you need to wait until the end of the message for gather to time out. Is there a way to make it so as soon as  starts, if the user hangs up it'll do something like go to the redirect tag?

Thanks!

Edit: So on the process_gather.php page, I can save the completed status as a variable?

```<code>$Completed = $_POST["completed"]; //which would set $Completed == 'completed'
</code>```

and then in that page I can just basically say if if(!empty($Completed)) do something
(I have to work it into my logic, but I just want to make sure I get the general idea)

答:
The best way to solve this is by using the StatusCallback URL. You can set this URL for inbound calls in the Number configuration in your account, or through an optional argument for outbound calls.

When the call completes, Twilio will POST (or GET) to the URL with all the same variables it passes during a normal request. The CallStatus variable will be set to completed.

If that URL is called before you get input from the user (to your `/process_gather.php' script), then they hung up.

Note: You can use cookies to manage session state within a call: all requests made by Twilio during the same call (and the StatusCallback request) will contain any cookies you send. This allows you to use a session variable to track call progress.

PHP Example for /proces_gather.php:

```<code> <?php
 session_start();
 // adds it to our session
 $_SESSION['gather_result']=$_POST["Digits"];
 // then do whatever else you want your gather script to do.
 ?>
</code>```

PHP Example for /status_callback.php, which should be configured as the StatusCallback URL for the phone number in the Twilio Account screen:

```<code><?php
session_start();
//check for gather_result
if(isset($_SESSION['gather_result'])){
  //user did enter digits
} else {
  //do whatever you want to do if the user entered no digits.
}
?>
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I have an application that runs with Twilio. The idea is that you will call a phone number twilio will answer and give you menu options. Once you press a digit it will submit the post data and then hang up (That part all works correctly) The problem I'm having is finding out if there is a way to submit post data if the user just hangs up as soon as twilio answers... I found the following code on their documentation.

<?xml version="1.0" encoding="UTF-8"?>

<Response>
 <Gather action="/process_gather.php" method="GET">
     <Say>Enter something, or not</Say>
 </Gather>
 <Redirect method="GET">
     /process_gather.php?Digits=TIMEOUT
 </Redirect>
</Response>

The problem with this is you need to wait until the end of the message for gather to time out. Is there a way to make it so as soon as  starts, if the user hangs up it'll do something like go to the redirect tag?

Thanks!

Edit: So on the process_gather.php page, I can save the completed status as a variable?

$Completed = $_POST["completed"]; //which would set $Completed == 'completed'

and then in that page I can just basically say if if(!empty($Completed)) do something
(I have to work it into my logic, but I just want to make sure I get the general idea)

Body:
The best way to solve this is by using the StatusCallback URL. You can set this URL for inbound calls in the Number configuration in your account, or through an optional argument for outbound calls.

When the call completes, Twilio will POST (or GET) to the URL with all the same variables it passes during a normal request. The CallStatus variable will be set to completed.

If that URL is called before you get input from the user (to your `/process_gather.php' script), then they hung up.

Note: You can use cookies to manage session state within a call: all requests made by Twilio during the same call (and the StatusCallback request) will contain any cookies you send. This allows you to use a session variable to track call progress.

PHP Example for /proces_gather.php:

 <?php
 session_start();
 // adds it to our session
 $_SESSION['gather_result']=$_POST["Digits"];
 // then do whatever else you want your gather script to do.
 ?>

PHP Example for /status_callback.php, which should be configured as the StatusCallback URL for the phone number in the Twilio Account screen:

<?php
session_start();
//check for gather_result
if(isset($_SESSION['gather_result'])){
  //user did enter digits
} else {
  //do whatever you want to do if the user entered no digits.
}
?>


问:
momentjs change string mm/yyyy format to yyyy-mm
I have a date string 11/2004 that comes to me via an API and on mobile I am trying to display this on a date field.

If i try to render this as it is I see the following warning on console

The specified value "11/2004" does not conform to the required format.
  The format is "yyyy-MM" where yyyy is year in four or more digits, and
  MM is 01-12.

so using momentjs i thought this should be easy to change to date or month format but i am struggling with it as i cant seem to get the output i want.

I tried the following code but that give me invalid date

```<code>moment('11/2004').format('yyyy-MM')
</code>```

What am i doing wrong here? How do i display the date on an input field in the correct format? I cant change the field type to anything else as its a date picker field on mobile.

答:
You should create your date with the string-format

```<code>moment('11/2004', 'MM/YYYY')
</code>```

and then display it using the format() function

```<code>moment('11/2004', 'MM/YYYY').format('YYYY-MM')
</code>```

Body:
I have a date string 11/2004 that comes to me via an API and on mobile I am trying to display this on a date field.

If i try to render this as it is I see the following warning on console

The specified value "11/2004" does not conform to the required format.
  The format is "yyyy-MM" where yyyy is year in four or more digits, and
  MM is 01-12.

so using momentjs i thought this should be easy to change to date or month format but i am struggling with it as i cant seem to get the output i want.

I tried the following code but that give me invalid date

moment('11/2004').format('yyyy-MM')

What am i doing wrong here? How do i display the date on an input field in the correct format? I cant change the field type to anything else as its a date picker field on mobile.

Body:
You should create your date with the string-format

moment('11/2004', 'MM/YYYY')

and then display it using the format() function

moment('11/2004', 'MM/YYYY').format('YYYY-MM')


问:
Ansible - how to run different playbook/module?
I am newbie to ansible and i am looking for help on ansible playbook.

My sample architecture (folder location)

```<code>Action1

- roles
  - module1_action1
      - tasks
      - templates
  - module2_action2
      - tasks
      - templates
  - module3_action3
      - tasks
      - templates
  - action1.yml

Action2

- roles
  - module4_action4
      - tasks
      - templates
  - action2.yml
</code>```

Here is my question: How can i use action2.yml to execute Action1's module2_action2?

Thank so much for your help.

LAU

答:
Set roles_path in ansible.cfg to include Action1/roles and Action2/roles.

This way you can access action1's roles from actions2 playbook.

Body:
I am newbie to ansible and i am looking for help on ansible playbook.

My sample architecture (folder location)

Action1

- roles
  - module1_action1
      - tasks
      - templates
  - module2_action2
      - tasks
      - templates
  - module3_action3
      - tasks
      - templates
  - action1.yml

Action2

- roles
  - module4_action4
      - tasks
      - templates
  - action2.yml

Here is my question: How can i use action2.yml to execute Action1's module2_action2?

Thank so much for your help.

LAU


问:
Labeling Gmail message (not the whole thread) with Google Apps Script
Is it possible to search to messages with the label 'Apps script queue' and give just these specific messages (not the whole thread) a new label?

When I use GmailApp.search('label:Apps script queue') I get the requested messages but when I assign a new label to these messages, all the other messages of the thread (on other places in the mailbox) will get the same label. And that is not what I want.

答:
This code does not return an error while adding a label to a specific message in a thread and if you use thread list method you'll see that it is only placed in the specific messageID(treated separately). But once your UI(Gmail site) is in conversation mode, it will be viewable in both labels.</p>

```<code>function searchMail(){
  var threads = GmailApp.search("SOME SEARCH");
  Logger.log(threads.length);
  listLabel('me');
  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();
    Logger.log(messages.length);

    for (var j = 0; j < messages.length; j++){
      if (messages[j].isInInbox()){
        Logger.log('me' + 'id msg: ' + messages[j].getId());
        //Add label to the first reply
        addLabel('me',messages[1].getId());
      }
      else{
       Logger.log('me' + 'id msg: ' + messages[j].getId() +" not in inbox");
      }
    }
  }
}

function addLabel(userId, messageId){

  var resource = {addLabelIds: ["Label_6"]}

  Gmail.Users.Messages.modify(resource, userId, messageId);

}
</code>```

Body:
This code does not return an error while adding a label to a specific message in a thread and if you use thread list method you'll see that it is only placed in the specific messageID(treated separately). But once your UI(Gmail site) is in conversation mode, it will be viewable in both labels.

function searchMail(){
  var threads = GmailApp.search("SOME SEARCH");
  Logger.log(threads.length);
  listLabel('me');
  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();
    Logger.log(messages.length);

    for (var j = 0; j < messages.length; j++){
      if (messages[j].isInInbox()){
        Logger.log('me' + 'id msg: ' + messages[j].getId());
        //Add label to the first reply
        addLabel('me',messages[1].getId());
      }
      else{
       Logger.log('me' + 'id msg: ' + messages[j].getId() +" not in inbox");
      }
    }
  }
}

function addLabel(userId, messageId){

  var resource = {addLabelIds: ["Label_6"]}

  Gmail.Users.Messages.modify(resource, userId, messageId);

}


问:
how to get all keys and values in redis in javascript?
I am creating a node API using javascript. I have used redis as my key value store.
I created a redis-client in my app and am able to get values for perticular key.

I want to retrieve all keys along with their values.
So Far I have done this :

```<code>app.get('/jobs', function (req, res) {
    var jobs = [];
    client.keys('*', function (err, keys) {
        if (err) return console.log(err);
        if(keys){
            for(var i=0;i<keys.length;i++){
                client.get(keys[i], function (error, value) {
                    if (err) return console.log(err);
                    var job = {};
                    job['jobId']=keys[i];
                    job['data']=value;
                    jobs.push(job);
                });
            }
            console.log(jobs);
            res.json({data:jobs});
        }
    });
});
</code>```

but I always get blank array in response.

is there any way to do this in javascript?

Thanks

答:
You should never do this. First off, it is not recommended to use KEYS * in production. Second, this does not scale (cluster).

You can organise your cached entries into SETs and query for the items within the SET, then retrieve the references keys. This also makes invalidation easier.

Have a look at some data storage best practices.

https://redis.io/topics/data-types-intro
how to get all keys and values in redis in javascript?

Body:
I am creating a node API using javascript. I have used redis as my key value store.
I created a redis-client in my app and am able to get values for perticular key.

I want to retrieve all keys along with their values.
So Far I have done this :

app.get('/jobs', function (req, res) {
    var jobs = [];
    client.keys('*', function (err, keys) {
        if (err) return console.log(err);
        if(keys){
            for(var i=0;i<keys.length;i++){
                client.get(keys[i], function (error, value) {
                    if (err) return console.log(err);
                    var job = {};
                    job['jobId']=keys[i];
                    job['data']=value;
                    jobs.push(job);
                });
            }
            console.log(jobs);
            res.json({data:jobs});
        }
    });
});

but I always get blank array in response.

is there any way to do this in javascript?

Thanks

ContentLicense: CC BY-SA 4.0


问:
GIMP Python, toggle all paths visible or invisible, how?
I'm trying to create a GIMP Python plug-in to toggle visibility of all paths in the image on or off. This is to more easily process images with lots of paths (>100+) instead of endless clicking in the paths dialog.

The GIMP Python documentation is not very helpful and I could only find the function set_component_visible. But when I try img.set_component_visible(v, False) or img.set_component_visible(v, 0) is gives this error:

```<code>TypeError: an integer is required
</code>```

Here is the code I have got so far:

```<code>from gimpfu import *
import os

def select_paths_visible(img, layer, tog, apl, wc):

    # iterate all paths (internally called "vectors")
    for v in img.vectors:
        img.set_component_visible(v, 0) # <== TypeError on this line

# tell gimp about our plugin
register(
    "python_fu_select_paths_visible",
    "Toggle paths visible",
    "Toggle paths visible",
    "BdR",
    "BdR",
    "2017",
    "<Image>/Tools/Toggle paths visible", # menu path
    "",
    [
        (PF_RADIO, "p1", "Toggle paths:", 1, (("Invisible", 0), ("Visible", 1))),
        (PF_RADIO, "p2", "Apply to paths:", 1, (("All", 0), ("With name", 1))),
        (PF_TEXT, "p3", "Pathname contains:", "test")
    ],
    [],
    select_paths_visible
)

main()
</code>```

My question is

1. should I use set_component_visible differently

2. is there a different function to toggle paths visibility on/off?

3. What is a good source for documentation on the GIMP Python functions

答:
Simply:

```<code>for v in image.vectors:
    v.visible = False
</code>```

set_component_visible() is about RGB channels and not paths (it seems to be the equivalent of clicking he visibility of the RGB channels in the Channels dialog)

gimp_vectors_set_visible() or change the attribute of the vector directly as done above

The Procedure Browser (Browse... button in the Python-fu console) is quite efficient IMHO. In Python, the more often used calls have equivalents as object methods and attributes. Use dir(object) to list methods and attributes. You will find many things that have obvious equivalents as PDB functions. Attributes may be be R/W (as visible above) or just R/O (and should then be changed with a method or a PDB function).

If you need sample code, see these two scripts repositories: general scripts and paths-related scripts

PS: for you name criterion:

```<code>for v in image.vectors:
    if string in v.name:
        v.visible = False
</code>```

Body:
I'm trying to create a GIMP Python plug-in to toggle visibility of all paths in the image on or off. This is to more easily process images with lots of paths (>100+) instead of endless clicking in the paths dialog.

The GIMP Python documentation is not very helpful and I could only find the function set_component_visible. But when I try img.set_component_visible(v, False) or img.set_component_visible(v, 0) is gives this error:

TypeError: an integer is required

Here is the code I have got so far:

from gimpfu import *
import os

def select_paths_visible(img, layer, tog, apl, wc):

    # iterate all paths (internally called "vectors")
    for v in img.vectors:
        img.set_component_visible(v, 0) # <== TypeError on this line

# tell gimp about our plugin
register(
    "python_fu_select_paths_visible",
    "Toggle paths visible",
    "Toggle paths visible",
    "BdR",
    "BdR",
    "2017",
    "<Image>/Tools/Toggle paths visible", # menu path
    "",
    [
        (PF_RADIO, "p1", "Toggle paths:", 1, (("Invisible", 0), ("Visible", 1))),
        (PF_RADIO, "p2", "Apply to paths:", 1, (("All", 0), ("With name", 1))),
        (PF_TEXT, "p3", "Pathname contains:", "test")
    ],
    [],
    select_paths_visible
)

main()

My question is

1. should I use set_component_visible differently

2. is there a different function to toggle paths visibility on/off?

3. What is a good source for documentation on the GIMP Python functions

Body:
Simply:

for v in image.vectors:
    v.visible = False

set_component_visible() is about RGB channels and not paths (it seems to be the equivalent of clicking he visibility of the RGB channels in the Channels dialog)

gimp_vectors_set_visible() or change the attribute of the vector directly as done above

The Procedure Browser (Browse... button in the Python-fu console) is quite efficient IMHO. In Python, the more often used calls have equivalents as object methods and attributes. Use dir(object) to list methods and attributes. You will find many things that have obvious equivalents as PDB functions. Attributes may be be R/W (as visible above) or just R/O (and should then be changed with a method or a PDB function).

If you need sample code, see these two scripts repositories: general scripts and paths-related scripts

PS: for you name criterion:

for v in image.vectors:
    if string in v.name:
        v.visible = False


问:
SpringBoot Multiple Data Source JPA
I have following code

Entity

```<code> @Entity
    public class Employee {

        @Id
        @GeneratedValue
        long id;

        @Column(name="first_name")
        String firstName;

        @Column(name="last_name")
        String lastName;

        @Column(name="salary")
        int salary;

        @ManyToOne
        @JoinColumn(name="address")
        Address address;

    ..... setter & getter

    }
</code>```

Repo

```<code>public interface EmpRepository extends JpaRepository<Employee, Long>{}
</code>```

Service

```<code>@Service
public class EmpService {

    @Autowired
    private EmpRepository empRepo;

    @Autowired @Qualifier("primaryEntityManagerFactory") EntityManager em;

    public List<Employee> findAll(){
        return empRepo.findAll();
    }

}
</code>```

Controller

```<code>@RestController
@RequestMapping(value = "/demo")
public class DemoController {

    @Autowired
    private EmpService empService;

    @RequestMapping("/abcd")
    public List<Employee> findAll(){
        return empService.findAll();
    }

}
</code>```

Data Source Configuraion (Primary)

```<code>@Configuration
@EnableJpaRepositories(basePackages="com.example",
entityManagerFactoryRef = "primaryEntityManagerFactory")
public class DataSourceConfiguration {

    @Bean(name="primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(primaryEntityManagerFactory().getObject());
        return tm;
    }

    @Bean(name="primaryEntityManagerFactory")
    @Primary
    LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(primaryDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());

        return factoryBean;
    }

}
</code>```

Secondary Data Source Config

```<code> @Configuration
@EnableJpaRepositories(basePackages="com.example",
entityManagerFactoryRef = "secondaryEntityManagerFactory")
public class DS2Configuration {

    @Bean(name="secondaryDataSource")
    @ConfigurationProperties(prefix = "datasource.secondary")

    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(secondaryEntityManagerFactory().getObject());
        return tm;
    }

    @Bean(name="secondaryEntityManagerFactory")
    LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(secondaryDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());

        return factoryBean;
    }

}
</code>```

application.properties

```<code>spring.jpa.show-sql = true
spring.jpa.properties.hibernate.show_sql=true
spring.jooq.sql-dialect=MYSQL
logging.level.org.springframework.data=DEBUG

# Primary DataSource configuration
datasource.primary.url=jdbc:mysql://127.0.0.1:3306/jpa
datasource.primary.username=root
datasource.primary.password=root

# Secondary DataSource configuration
datasource.secondary.url=jdbc:mysql://127.0.0.1:3306/jpa2
datasource.secondary.username=root
datasource.secondary.password=root

# Disable Spring DataSource auto-initialization
spring.datasource.initialize=false

server.port=8081
</code>```

When I am actually running function findAll() from EmpService, it is always using primary datasource even when i am specifying  secondary entitymanagefactory as

```<code>@Autowired
    @Qualifier("secondaryEntityManagerFactory")
    EntityManager em;
</code>```

How to resolve this?
P.S. - Please do not share blog links for this.

答:
This happens because there are more than one beans of type javax.persistence.EntityManagerFactory to help spring boot decide which bean to prefer

annotate the bean with @primary annotation

@primary official documentation

Title: SpringBoot Multiple Data Source JPA

Body:
I have following code

Entity

 @Entity
    public class Employee {

        @Id
        @GeneratedValue
        long id;

        @Column(name="first_name")
        String firstName;

        @Column(name="last_name")
        String lastName;

        @Column(name="salary")
        int salary;

        @ManyToOne
        @JoinColumn(name="address")
        Address address;

    ..... setter & getter

    }

Repo

public interface EmpRepository extends JpaRepository<Employee, Long>{}

Service

@Service
public class EmpService {

    @Autowired
    private EmpRepository empRepo;

    @Autowired @Qualifier("primaryEntityManagerFactory") EntityManager em;

    public List<Employee> findAll(){
        return empRepo.findAll();
    }

}

Controller

@RestController
@RequestMapping(value = "/demo")
public class DemoController {

    @Autowired
    private EmpService empService;

    @RequestMapping("/abcd")
    public List<Employee> findAll(){
        return empService.findAll();
    }

}

Data Source Configuraion (Primary)

@Configuration
@EnableJpaRepositories(basePackages="com.example",
entityManagerFactoryRef = "primaryEntityManagerFactory")
public class DataSourceConfiguration {

    @Bean(name="primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(primaryEntityManagerFactory().getObject());
        return tm;
    }

    @Bean(name="primaryEntityManagerFactory")
    @Primary
    LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(primaryDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());

        return factoryBean;
    }

}

Secondary Data Source Config

 @Configuration
@EnableJpaRepositories(basePackages="com.example",
entityManagerFactoryRef = "secondaryEntityManagerFactory")
public class DS2Configuration {

    @Bean(name="secondaryDataSource")
    @ConfigurationProperties(prefix = "datasource.secondary")

    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(secondaryEntityManagerFactory().getObject());
        return tm;
    }

    @Bean(name="secondaryEntityManagerFactory")
    LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(secondaryDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());

        return factoryBean;
    }

}

application.properties

spring.jpa.show-sql = true
spring.jpa.properties.hibernate.show_sql=true
spring.jooq.sql-dialect=MYSQL
logging.level.org.springframework.data=DEBUG

# Primary DataSource configuration
datasource.primary.url=jdbc:mysql://127.0.0.1:3306/jpa
datasource.primary.username=root
datasource.primary.password=root

# Secondary DataSource configuration
datasource.secondary.url=jdbc:mysql://127.0.0.1:3306/jpa2
datasource.secondary.username=root
datasource.secondary.password=root

# Disable Spring DataSource auto-initialization
spring.datasource.initialize=false

server.port=8081

When I am actually running function findAll() from EmpService, it is always using primary datasource even when i am specifying  secondary entitymanagefactory as

@Autowired
    @Qualifier("secondaryEntityManagerFactory")
    EntityManager em;

How to resolve this?
P.S. - Please do not share blog links for this.


问:
Sonata FormMapper adding link from integer field
Been trying to add a element to a table row, this element is an ID from a table and its defined as integer. When I add it to FormMapper it shows is as a integer field. I would like to show it as a button to edit that location on another page.

Here is a snippet of MB/SiteBundle/Admin/LocationAdmin.php

```<code>protected function configureFormFields(FormMapper $formMapper)
{
 $id = $this->getSubject()->getId();

 $options = array('required' => false);
 $options['help'] = '<a href="/admin/mb/site/location/' . $id. '/edit">';

$formMapper
  ->add('year')
  ->add('duns_number')
  ->add('address_1')
  ->add('address_2')
  ->add('city')
  ->add('state')
  ->add('zip')
  ->add('type')
  ->add('isPrimary', null, array('required' => false))
  ->add('numEmployees')
  ->add('numCoveredEmployees')
  ->add('benefitOption')
  ->add('freeformBenefit1', null, array('label' => "benefit_4c_description"))
  ->add('freeformBenefit2', null, array('label' => "benefit_4c_whyappropriate"))

  ->add('id', null, $options)
  ->end()

  ->with('Contact Info')
    ->add('cbc', 'sonata_type_admin', array('delete' => false, 'label' => false, 'required' => false, 'btn_add' => false))
  ->end()
  ;
}
</code>```

Now below is a snippet of MB/SiteBundle/Entity/Location.php

```<code>/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
</code>```

On the last td of the row table would like to see a link to location page as on the help property i stated. thx

答:
Rendering a button is easy, but it will trigger your form instead of redirecting to the new page (the latter breaks UX, since buttons are a call-to-action, not a link).

using custom buttons

You'll need to create a custom FormType and render your custom button (as , instead of <button/>). Then you can easily set the desired URL and render it.

using built-in behaviour

An alternative way (if the Entities know each other and there is an Admin registered for it): use sonata_type_model_list

```<code>$formMapper
    ->add('location', 'sonata_type_model_list', array('btn_add' => false, 'btn_delete' => false);
</code>```

This won't render a button, but renders Sonata's list-element for references which is clickable too.

Body:
Been trying to add a element to a table row, this element is an ID from a table and its defined as integer. When I add it to FormMapper it shows is as a integer field. I would like to show it as a button to edit that location on another page.

Here is a snippet of MB/SiteBundle/Admin/LocationAdmin.php

protected function configureFormFields(FormMapper $formMapper)
{
 $id = $this->getSubject()->getId();

 $options = array('required' => false);
 $options['help'] = '';

$formMapper
  ->add('year')
  ->add('duns_number')
  ->add('address_1')
  ->add('address_2')
  ->add('city')
  ->add('state')
  ->add('zip')
  ->add('type')
  ->add('isPrimary', null, array('required' => false))
  ->add('numEmployees')
  ->add('numCoveredEmployees')
  ->add('benefitOption')
  ->add('freeformBenefit1', null, array('label' => "benefit_4c_description"))
  ->add('freeformBenefit2', null, array('label' => "benefit_4c_whyappropriate"))

  ->add('id', null, $options)
  ->end()

  ->with('Contact Info')
    ->add('cbc', 'sonata_type_admin', array('delete' => false, 'label' => false, 'required' => false, 'btn_add' => false))
  ->end()
  ;
}

Now below is a snippet of MB/SiteBundle/Entity/Location.php

/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

On the last td of the row table would like to see a link to location page as on the help property i stated. thx

Body:
Rendering a button is easy, but it will trigger your form instead of redirecting to the new page (the latter breaks UX, since buttons are a call-to-action, not a link).

using custom buttons

You'll need to create a custom FormType and render your custom button (as <a/>, instead of <button/>). Then you can easily set the desired URL and render it.

using built-in behaviour

An alternative way (if the Entities know each other and there is an Admin registered for it): use sonata_type_model_list

$formMapper
    ->add('location', 'sonata_type_model_list', array('btn_add' => false, 'btn_delete' => false);

This won't render a button, but renders Sonata's list-element for references which is clickable too.


问:
safe way to create sqlite3 table in python
For inserting into a table, the safe way is

```<code>c.execute("insert into table (?,?,?,...)",my_tuple)
</code>```

But how does one create a table safely? I've tried something like this:

```<code>conn = sqlite3.connect(database)
c = conn.cursor()
cmd = "create table ? (? text,? text)"
my_tuple = ("my_table","first","second")
c.execute(cmd,my_tuple)
</code>```

but I get errors like this:

```<code>Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: near "?": syntax error
</code>```

Should I just assemble a string in python and throw it at sqlite to create the table?

答:
If you're just trying to import csv files, and assuming that they're not being sent to you by some user who might try to mess with your database, just put it together in Python:

```<code>"create table %s (%s text,%s text)" % ("my_table","first","second")
</code>```

If there's any chance the spreadsheets could come from a malicious user, then it's up to you to worry about sanitising the column / file names.

Body:
For inserting into a table, the safe way is

c.execute("insert into table (?,?,?,...)",my_tuple)

But how does one create a table safely? I've tried something like this:

conn = sqlite3.connect(database)
c = conn.cursor()
cmd = "create table ? (? text,? text)"
my_tuple = ("my_table","first","second")
c.execute(cmd,my_tuple)

but I get errors like this:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: near "?": syntax error

Should I just assemble a string in python and throw it at sqlite to create the table?

Body:
If you're just trying to import csv files, and assuming that they're not being sent to you by some user who might try to mess with your database, just put it together in Python:

"create table %s (%s text,%s text)" % ("my_table","first","second")

If there's any chance the spreadsheets could come from a malicious user, then it's up to you to worry about sanitising the column / file names.


问:
How to change session data by sessionid in codeigniter using redis library?
We have a admin panel built in codeigniter, where two types of user get logged in (admin and super admin). Admin permissions are control by super admin. Admin permissions are stored in session at time of login. We are using codeigniter redis library for storing session data.

Now, the challenge is to update admin user session data without effecting admin login when permissions are changed by super admin.

答:
if you want to do this on runtime i think with redis it shouldnt be really a problem

Create a pre Controller Hook where you check on every request if users session has been changed

since you use redis - you really don't need to use a DB Query in order to check it - just simply create an object which holds all changed users whose session have been changed and save it to redis

the hook could look like

```<code>class AppRefreshSession
{
    private $ci;

    public function __construct()
    {
        $this->ci = get_instance();
    }

    public function initialize()
    {
        if (!$this->isSessionValid())
        {
            //refresh users Session
        }
    }

    private function isSessionValid()
    {
        $obj = $this->ci->cache->redis->get("ModifiedSessions_Object");

        if ($obj->hasSessionModified())
        {
            return false;
        }

        return true;

    }
}
</code>```

And your modified sessions object should get filled with user ids or something like that whenever a superadmin changes the permission.
Save this object to redis and that should pretty much do what you want.

Body:
if you want to do this on runtime i think with redis it shouldnt be really a problem

Create a pre Controller Hook where you check on every request if users session has been changed

since you use redis - you really don't need to use a DB Query in order to check it - just simply create an object which holds all changed users whose session have been changed and save it to redis

the hook could look like

class AppRefreshSession
{
    private $ci;

    public function __construct()
    {
        $this->ci = get_instance();
    }

    public function initialize()
    {
        if (!$this->isSessionValid())
        {
            //refresh users Session
        }
    }

    private function isSessionValid()
    {
        $obj = $this->ci->cache->redis->get("ModifiedSessions_Object");

        if ($obj->hasSessionModified())
        {
            return false;
        }

        return true;

    }
}

And your modified sessions object should get filled with user ids or something like that whenever a superadmin changes the permission.
Save this object to redis and that should pretty much do what you want.


问:
Creating fixture with block format instead of inline format in django
I am using pyyaml.
I'm using following command to create fixtures in django project:

```<code>python manage.py dumpdata app.ModelName --format=yaml  > fixtures/dev/fixture_name.yaml
</code>```

What I get as output is:

```<code>- fields: {active: true, created_at: !!timestamp '2016-11-14 10:43:40.221602', age: 54,
    updated_at: !!timestamp '2016-11-14 10:43:40.221603', user_type: 1}
  model: app.ModelName
  pk: 1
</code>```

What I want is:

```<code>- fields:
    created_at: 2016-11-14 10:43:40.220895
    age: 54
    user_type: 1
    updated_at: 2016-11-14 10:43:40.220900
  model: app.ModelName
  pk: 1
</code>```

How can I achieve this?

答:
In manage.py, you are calling dump() (or safe_dump() incorrectly. You should call it with arguments

```<code> dump(your_data, default_flow_style=False)
</code>```

you also have to provide a representer for timestamp as that is not a type that PyYAML knows about. Or use (a subclass of) datetime.datetime for which PyYAML knows how to represent it.

Body:
I am using pyyaml.
I'm using following command to create fixtures in django project:

python manage.py dumpdata app.ModelName --format=yaml  > fixtures/dev/fixture_name.yaml

What I get as output is:

- fields: {active: true, created_at: !!timestamp '2016-11-14 10:43:40.221602', age: 54,
    updated_at: !!timestamp '2016-11-14 10:43:40.221603', user_type: 1}
  model: app.ModelName
  pk: 1

What I want is:

- fields:
    created_at: 2016-11-14 10:43:40.220895
    age: 54
    user_type: 1
    updated_at: 2016-11-14 10:43:40.220900
  model: app.ModelName
  pk: 1

How can I achieve this?

Body:
In manage.py, you are calling dump() (or safe_dump() incorrectly. You should call it with arguments

 dump(your_data, default_flow_style=False)

you also have to provide a representer for timestamp as that is not a type that PyYAML knows about. Or use (a subclass of) datetime.datetime for which PyYAML knows how to represent it.


问:
Error when building - Could not find property 'MyOpenWeatherMapApiKey'
i got this error from gradle when i try to build the project after i put the api key in gradle file

```<code>android {
.....
    buildTypes.each {
        it.buildConfigField 'String', 'cedf6......80c62', MyOpenWeatherMapApiKey
    }
}
</code>```

this error i got when i build the project :-

```<code>    Error:(22, 0) Could not find property 'MyOpenWeatherMapApiKey' on com.android.build.gradle.AppExtension_Decorated@48bee3b8.
<a href="openFile:F:\Projects\Android\advanced sunshine\Advanced_Android_Development\app\build.gradle">Open File</a>
</code>```

i think i have to make a file in some folder , but i don't know in which folder ? ,
and what i ishould to type inside the file after i create it  ?

答:
Since you are using a String you have to use this syntax:

buildConfigField "String" , "OPEN_WEATHER_MAP_API_KEY" ,  "\"XXXXX-XXXXX-XXX\""
The last parameter has to be a String

Otherwise you can use something like this:

resValue "string", "OPEN_WEATHER_MAP_API_KEY", "\"XXXXX-XXXXX-XXX\""
The first case generates a constants iin your BuildConfig file.
The second case generates a string resource value that can be accessed using the @string/OPEN_WEATHER_MAP_API_KEY annotation.

Credits: Could not find property 'xxxx' on com.android.build.gradle.AppExtension_Decorated

Body:
i got this error from gradle when i try to build the project after i put the api key in gradle file

android {
.....
    buildTypes.each {
        it.buildConfigField 'String', 'cedf6......80c62', MyOpenWeatherMapApiKey
    }
}

this error i got when i build the project :-

    Error:(22, 0) Could not find property 'MyOpenWeatherMapApiKey' on com.android.build.gradle.AppExtension_Decorated@48bee3b8.
Open File

i think i have to make a file in some folder , but i don't know in which folder ? ,
and what i ishould to type inside the file after i create it  ?


问:
Get Image size from 4 pixel position using JavaScript or PHP

Can anybody here who help me to find width and height from the four corners, like in this picture i have 4 places

```<code>W - Width
H - Height

1 - 156W/116H
2 - 337W/54H
3 - 136W/312H
4 - 244/279H
</code>```

Is there any one who can provide a formula for finding the width and height from four positions using JavaScript or PHP?

答:
Assuming you are talking about the area in the image, which is a distorted rectangle due to perspective angle, you can approximate its width and height by taking the higher difference between coordinates. According to Alisher Gafurov's response :</p>

```<code>point_01 = {'x':156, 'y': 116};
point_02 = {'x':337, 'y': 54};
point_03 = {'x':136, 'y': 312};
point_04 = {'x':244, 'y': 279};

rectangle = {
  'height': Math.max(point_03.y - point_01.y, point_04.y - point_02.y),
  'width' : Math.max(point_02.x - point_01.x, point_04.x - point_02.x)
};
</code>```

Body:
Can anybody here who help me to find width and height from the four corners, like in this picture i have 4 places

W - Width
H - Height

1 - 156W/116H
2 - 337W/54H
3 - 136W/312H
4 - 244/279H

Is there any one who can provide a formula for finding the width and height from four positions using JavaScript or PHP?

Body:
Assuming you are talking about the area in the image, which is a distorted rectangle due to perspective angle, you can approximate its width and height by taking the higher difference between coordinates. According to Alisher Gafurov's response :

point_01 = {'x':156, 'y': 116};
point_02 = {'x':337, 'y': 54};
point_03 = {'x':136, 'y': 312};
point_04 = {'x':244, 'y': 279};

rectangle = {
  'height': Math.max(point_03.y - point_01.y, point_04.y - point_02.y),
  'width' : Math.max(point_02.x - point_01.x, point_04.x - point_02.x)
};


问:
Delphi: why breakpoints from time to time are not usable (green highlighted line on IDE)?
From time to time I lose breakpoint functionality in Delphi.

I thought this to be a Delphi 2009 issue but now I have also it in Delphi XE.

In Delphi 2009 by deleting .dproj file I made the breakpoints work again.

In Delphi XE I am not able to make breakopints appear. I have update 1 with all hotfixes applied.

Does anyone have a solution?

答: If the project group uses packages (BPLs) ensure that none of them have any compiler warnings regarding implicitly imported units. If these exist you will only be able to step through the code via the CPU debug window.</p>


问:
Authentication in single-user API
In my API, there is no data assigned to any users, it's just about protection to prevent unauthorized people from using it. What are some possibilities of securing such kind of API?

I know there are JWTs, oAuth etc., but are they suitable for such simple API structure? I thought about just storing the single API key and make clients send it, but I heard it's not very safe. I would like to skip using database for this API entirely. What are the possibilities?

I'm using PHP and Laravel 5.4.

答:
Depends on how many users you have.

If you want to give multiple users access it would be recommended to give them separate API keys.

If it is just one user, keep it simple and use a single API key.

In general, API keys can be compromised but it's always a consideration of functionality and what protection you need. Look at the Eventbrite API or Google Maps API. The public interfaces work by sending your API key only, Google adding some layers of security by doing checks what website the request came from.

Eventbrite is doing no checks here since all the API does is return structured data for the events which are public anyways and don't count against any limits.

Title: Authentication in single-user API


问:
Java Redis (jedis) transaction and Sorted Set
I am new to Redis and I am experimenting with Redis transactions and I want to use Redis transactions in the following scenario. Need to know if it is feasible to do this:

Start Transaction.

Read top 10 elements from sorted set.

A 'for loop' for each of the elements to do something.

Execute.

I tried the following code but it isn't working as I am doing a <Response>.get() before executing the transaction.

```<code>final Transaction tx = jedis.multi();
final Response<Set<Tuple>> tuples = tx.zrangeByScoreWithScores("randomKey", 0d, 100, 0, 10);
for (final Tuple tuple : tuples.get()) {
    jedis.incr(tuple);
}
tx.exec(); //In a hope that get and sets happen in a single transaction.
</code>```

Is there a way to go around this?

答:
You could use Redisson instead. Use Lock object instead of transaction. Example for your case:</p>

```<code>RLock lock = redisson.getLock("myLock");
lock.lock();
try {
    Collection<ScoredEntry<V>> entries = redisson.getScoredSortedSet("randomKey").entryRange(true, 0, true, 100, 0, 10);
    for (final ScoredEntry<V> entry : entries) {
       redisson.getAtomicLong(entry.getValue()).incrementAndGet();
    }
} finally {
    lock.unlock();
}
</code>```

Body:
I am new to Redis and I am experimenting with Redis transactions and I want to use Redis transactions in the following scenario. Need to know if it is feasible to do this:

Start Transaction.

Read top 10 elements from sorted set.

A 'for loop' for each of the elements to do something.

Execute.

I tried the following code but it isn't working as I am doing a <Response>.get() before executing the transaction.

final Transaction tx = jedis.multi();
final Response<Set<Tuple>> tuples = tx.zrangeByScoreWithScores("randomKey", 0d, 100, 0, 10);
for (final Tuple tuple : tuples.get()) {
    jedis.incr(tuple);
}
tx.exec(); //In a hope that get and sets happen in a single transaction.

Is there a way to go around this?

Body:
You could use Redisson instead. Use Lock object instead of transaction. Example for your case:

RLock lock = redisson.getLock("myLock");
lock.lock();
try {
    Collection<ScoredEntry<V>> entries = redisson.getScoredSortedSet("randomKey").entryRange(true, 0, true, 100, 0, 10);
    for (final ScoredEntry<V> entry : entries) {
       redisson.getAtomicLong(entry.getValue()).incrementAndGet();
    }
} finally {
    lock.unlock();
}


问:
JavaScript expression parser in Silverlight
Hey everybody! I have a Silverlight project that needs to help users create JavaScript logical expressions (e.g. "var1 != var2 && var3 >= var4"). Very simple. The problem is that I do not have much time to create one myself because tweaking the transition table would be a little time consuming.

So I was searching online for one, but all I found was a couple classes that help you validate the JavaScript, but I need a way to load it, parse it and then write it back. So I was wondering if anyone has any ideas about how I can do it. I am assuming it will not require much code, and it does not have to be a C# example either. If only you could give me some ideas in C++ or even pseudo code, that would help a lot.

Thank you,

Vladimir

答:
Create a recursive descent parser by hand.  It's fun!

First define a grammar:

```<code>Expression -> SimpleExpression ExpressionTail
              (Expression)
SimpleExpression -> Atom Inequality Atom
ExpressionTail -> && Expression |
                  || Expression |
                  e
Atom -> Variable | Literal
Inequality -> == | != | > | >= | < | <=
</code>```

(This grammar doesn't handle operator precedence, but it is easy to write a grammar that will.)

Next, create a lexical analyzer that will read the input string and create tokens so the string "var1 != 4.0" would be translated to a list of {Variable, !=, Literal}.  This can be hacked together, or if you want to get fancy you can use a finite state machine to analyze the string.

Now create a recursive descent parser to parse the list of tokens into an expression tree.

```<code>public class Parser {

    public Parser() {
    }

    public Expression parse( LexicalAnalyzer lex) {
        lex.advance();
        return expression( lex);
    }

    private Expression expression( LexicalAnalyzer lex) {

        switch( lex.current().type() ) {
            case Token.OpenParen:
                lex.advance();
                Expression expression = expression( lex);
                lex.eat( Token.CloseParen);
                return expression;
            case Token.Literal:
            case Token.Variable:
                return expressionTail( lex, simpleExpression(lex));
            default:
                throw new Exception( "ParseError: Expecting (, variable, or literal at character " +
                                      lex.character());
        }
    }

    private SimpleExpression simpleExpression( LexicalAnalyzer lex) {

        Atom atom = atom( lex);
        switch( lex.current().type() ) {
            case Token.Equal:
                lex.advance();
                return new Equal( atom, atom(lex));
            case Token.NotEqual:
                lex.advance();
                return new NotEqual( atom, atom(lex));
            ...
            default:
                throw new Exception( "ParseError: Expecting ==, !=, <, <=, >, >= at" +
                                     lex.character());
        }
     }

     private Expression expressionTail( LexicalAnalyzer lex, SimpleExpression expression) {

        switch( lex.current().type() ) {
            case Token.LogicalOr:
                lex.advance();
                return new OrExpression( expression, expression(lex) );
            case Token.LogicalAnd:
                lex.advance();
                return new AndExpression( expression, exptression(lex) );
            default:
                return expression;
        }
     }

     private Atom atom( LexicalAnalyzer lex) {
         switch( lex.current().type() ) {
             case Token.Literal:
                 Literal literal = new Literal( lex.current() );
                 lex.advance();
                 return literal;
             case Token.Variable:
                 Variable var = new Variable( lex.current() );
                 lex.advance();
                 return var;
             default:
                 throw new Exception("ParseError: ...");
          }
      }
}

public interface Expression {
    boolean evaluate( VariableValues values);
}

public interface SimpleExpression implements Expression {
}

public class Equal implements SimpleExpression {
    private final Atom left, right;
    public Equal( Atom left, Atom right) {
        this.left = left;
        this.right = right;
    }
    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) == right.evaluate(values);
    }
}
public class NotEqual implements SimpleExpression {
    private final Atom left, right;
    public NotEqual( Atom left, Atom right) {
        this.left = left;
        this.right = right;
    }
    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) != right.evaluate(values);
    }
}

public class OrExpression implements Expression {
    private final Expression left, right;

    public OrExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) || right.evaluate(values);
    }
}
public class AndExpression implements Expression {
    private final Expression left, right;

    public AndExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) && right.evaluate(values);
    }
}
public interface Atom {
    double evaluate( VariableValues values);
}
public class Literal implements Atom {
    private final double value;
    public Literal( double value) {
        this.value = value;
    }
    public double evaluate( VariableValues values) {
        return value;
    }
}
public class Variable implements Atom {
    private final String name;
    public Variable( String name) {
        this.name = name;
    }
    public double evaluate( VariableValues values) {
        return values.getValue( name);
    }
}
</code>```

Body:
Create a recursive descent parser by hand.  It's fun!

First define a grammar:

Expression -> SimpleExpression ExpressionTail
              (Expression)
SimpleExpression -> Atom Inequality Atom
ExpressionTail -> && Expression |
                  || Expression |
                  e
Atom -> Variable | Literal
Inequality -> == | != | > | >= | < | <=

(This grammar doesn't handle operator precedence, but it is easy to write a grammar that will.)

Next, create a lexical analyzer that will read the input string and create tokens so the string "var1 != 4.0" would be translated to a list of {Variable, !=, Literal}.  This can be hacked together, or if you want to get fancy you can use a finite state machine to analyze the string.

Now create a recursive descent parser to parse the list of tokens into an expression tree.

public class Parser {

    public Parser() {
    }

    public Expression parse( LexicalAnalyzer lex) {
        lex.advance();
        return expression( lex);
    }

    private Expression expression( LexicalAnalyzer lex) {

        switch( lex.current().type() ) {
            case Token.OpenParen:
                lex.advance();
                Expression expression = expression( lex);
                lex.eat( Token.CloseParen);
                return expression;
            case Token.Literal:
            case Token.Variable:
                return expressionTail( lex, simpleExpression(lex));
            default:
                throw new Exception( "ParseError: Expecting (, variable, or literal at character " +
                                      lex.character());
        }
    }

    private SimpleExpression simpleExpression( LexicalAnalyzer lex) {

        Atom atom = atom( lex);
        switch( lex.current().type() ) {
            case Token.Equal:
                lex.advance();
                return new Equal( atom, atom(lex));
            case Token.NotEqual:
                lex.advance();
                return new NotEqual( atom, atom(lex));
            ...
            default:
                throw new Exception( "ParseError: Expecting ==, !=, <, <=, >, >= at" +
                                     lex.character());
        }
     }

     private Expression expressionTail( LexicalAnalyzer lex, SimpleExpression expression) {

        switch( lex.current().type() ) {
            case Token.LogicalOr:
                lex.advance();
                return new OrExpression( expression, expression(lex) );
            case Token.LogicalAnd:
                lex.advance();
                return new AndExpression( expression, exptression(lex) );
            default:
                return expression;
        }
     }

     private Atom atom( LexicalAnalyzer lex) {
         switch( lex.current().type() ) {
             case Token.Literal:
                 Literal literal = new Literal( lex.current() );
                 lex.advance();
                 return literal;
             case Token.Variable:
                 Variable var = new Variable( lex.current() );
                 lex.advance();
                 return var;
             default:
                 throw new Exception("ParseError: ...");
          }
      }
}

public interface Expression {
    boolean evaluate( VariableValues values);
}

public interface SimpleExpression implements Expression {
}

public class Equal implements SimpleExpression {
    private final Atom left, right;
    public Equal( Atom left, Atom right) {
        this.left = left;
        this.right = right;
    }
    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) == right.evaluate(values);
    }
}
public class NotEqual implements SimpleExpression {
    private final Atom left, right;
    public NotEqual( Atom left, Atom right) {
        this.left = left;
        this.right = right;
    }
    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) != right.evaluate(values);
    }
}

public class OrExpression implements Expression {
    private final Expression left, right;

    public OrExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) || right.evaluate(values);
    }
}
public class AndExpression implements Expression {
    private final Expression left, right;

    public AndExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) && right.evaluate(values);
    }
}
public interface Atom {
    double evaluate( VariableValues values);
}
public class Literal implements Atom {
    private final double value;
    public Literal( double value) {
        this.value = value;
    }
    public double evaluate( VariableValues values) {
        return value;
    }
}
public class Variable implements Atom {
    private final String name;
    public Variable( String name) {
        this.name = name;
    }
    public double evaluate( VariableValues values) {
        return values.getValue( name);
    }
}


问:
Compute metrics on different window in Apache FLink
I am using Apache Flink 1.2 and here's my question:
I have a stream of data and I would like to compute a metric over a window of 1 day. Therefore I will write something like:

```<code>DataStream<Tuple6<Timestamp, String, Double, Double, Double, Integer>> myStream0 =
            env.readTextFile("Myfile.csv")
            .map(new MyMapper())                // Parse the input
            .assignTimestampsAndWatermarks(new MyExtractor())   //Assign the timestamp of the event
            .timeWindowAll(Time.days(1))
            .apply(new average());  // compute average, max, sum
</code>```

Now I would like to compute the same metrics over a window of 1 hour.

I can write same as before and specify Time.hours(1), but my concerns is that in this way apache flink reads two times the input file and does twice the work. I wonder if there is a way of doing all togheter (i.e. using the same stream).

答:
You can compute hourly aggregates and from those the daily aggregates. This would look for a simple DataStream<Double> as follows:

```<code>DataStream<Double> vals = ... // source + timestamp extractor

DataStream<Tuple2<Double, Long>> valCnt = vals // (sum, cnt)
  .map(new CntAppender())     // Double -> Tuple2<Double, Long(1)>

DataStream<Tuple3<Double, Long, Long>> hourlySumCnt = valCnt // (sum, cnt, endTime)
  .timeWindowAll(Time.hours(1))
  // SumCounter ReduceFunction sums the Double and Long field (Long is Count)
  // WindowEndAppender WindowFunction adds the window end timestamp (3rd field)
  .reduce(new SumCounter(), new WindowEndAppender())

DataStream<Tuple2<Double, Long>> hourlyAvg = hourlySumCnt // (avg, endTime)
  .map(new SumDivCnt()) // MapFunction divides Sum by Cnt for average

DataStream<Tuple3<Double, Long, Long>> dailySumCnt = hourlySumCnt // (sum, cnt, endTime)
  .map(new StripeOffTime()) // removes unnecessary time field -> Tuple2<Double, Long>
  .timeWindowAll(Time.days(1))
  .reduce(new SumCounter(), new WindowEndAppender()) // same as above

DataStream<Tuple2<Double, Long>> dailyAvg = dailySumCnt // (avg, endTime)
  .map(new SumDivCnt()) // same as above
</code>```

So, you basically compute sum and count for each hour, and based on that result you

compute the hourly average

compute daily sum and count and the daily average

Note, that I am using a ReduceFunction instead of a WindowFunction for the sum and count computation, because a ReduceFunction is eagerly applied, i.e., all records of the window are not collected but immediately aggregated. Hence the state that needs to be maintained is a single record.

Body:
I am using Apache Flink 1.2 and here's my question:
I have a stream of data and I would like to compute a metric over a window of 1 day. Therefore I will write something like:

DataStream<Tuple6<Timestamp, String, Double, Double, Double, Integer>> myStream0 =
            env.readTextFile("Myfile.csv")
            .map(new MyMapper())                // Parse the input
            .assignTimestampsAndWatermarks(new MyExtractor())   //Assign the timestamp of the event
            .timeWindowAll(Time.days(1))
            .apply(new average());  // compute average, max, sum

Now I would like to compute the same metrics over a window of 1 hour.

I can write same as before and specify Time.hours(1), but my concerns is that in this way apache flink reads two times the input file and does twice the work. I wonder if there is a way of doing all togheter (i.e. using the same stream).

Body:
You can compute hourly aggregates and from those the daily aggregates. This would look for a simple DataStream<Double> as follows:

DataStream<Double> vals = ... // source + timestamp extractor

DataStream<Tuple2<Double, Long>> valCnt = vals // (sum, cnt)
  .map(new CntAppender())     // Double -> Tuple2<Double, Long(1)>

DataStream<Tuple3<Double, Long, Long>> hourlySumCnt = valCnt // (sum, cnt, endTime)
  .timeWindowAll(Time.hours(1))
  // SumCounter ReduceFunction sums the Double and Long field (Long is Count)
  // WindowEndAppender WindowFunction adds the window end timestamp (3rd field)
  .reduce(new SumCounter(), new WindowEndAppender())

DataStream<Tuple2<Double, Long>> hourlyAvg = hourlySumCnt // (avg, endTime)
  .map(new SumDivCnt()) // MapFunction divides Sum by Cnt for average

DataStream<Tuple3<Double, Long, Long>> dailySumCnt = hourlySumCnt // (sum, cnt, endTime)
  .map(new StripeOffTime()) // removes unnecessary time field -> Tuple2<Double, Long>
  .timeWindowAll(Time.days(1))
  .reduce(new SumCounter(), new WindowEndAppender()) // same as above

DataStream<Tuple2<Double, Long>> dailyAvg = dailySumCnt // (avg, endTime)
  .map(new SumDivCnt()) // same as above

So, you basically compute sum and count for each hour, and based on that result you

compute the hourly average

compute daily sum and count and the daily average

Note, that I am using a ReduceFunction instead of a WindowFunction for the sum and count computation, because a ReduceFunction is eagerly applied, i.e., all records of the window are not collected but immediately aggregated. Hence the state that needs to be maintained is a single record.


问:
How to store the output come from cases just store into an object
Whenever i will call getJsonKeyValue it should print the output like below,How can i store the value of getJsonKeyValue and using accordingly.

```<code>      getJsonKeyValue(WithMap: Map[String, Any])

      def getJsonKeyValue(mapIs: Map[String, Any]) {

         mapIs.foreach {
            case (k: String, v: List[Map[String, Any]]) =>  v.foreach(x => getJsonKeyValue(x))
            case (k: String, v: Any) => (k + "=" + v)

      }

    }
</code>```

mapIs

```<code>Map(RedDef -> List(Map(RedTypP -> ^.{14}XY.*$, RedTypC -> XY, ExpNoOfAt -> 19, attributes -> List(Map(AttId -> 1, AttNa -> Pro Ty, AttMaxLen -> 1, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 2, AttNa -> Pro Cod, AttMaxLen -> 6, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 3, AttNa -> REQ CODE, AttMaxLen -> 7, DataTy -> Map(DataTyName -> AN))), RedLen -> 117, RedDeIn -> 2, MinNoOfAt -> 19), Map(RedTypP -> ^.{14}JK.*$, RedTypC -> JK, ExpNoOfAt -> 10, attributes -> List(Map(AttId -> 1, AttNa -> Log Si Ty, AttMaxLen -> 1, DataTy -> Map(DataTyName -> A)), Map(AttId -> 2, AttNa -> Log Si Cod, AttMaxLen -> 6, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 3, AttNa -> Ex Qu Cod, AttMaxLen -> 7, DataTy -> Map(DataTyName -> AN))), RedDeIn -> 3, MinNoOfAt -> 10), Map(RedTypP -> ^.{14}FK.*$, RedTypC -> FK, ExpNoOfAt -> 33, attributes -> List(Map(AttId -> 1, AttNa -> Pro Ty, AttMaxLen -> 1, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 2, AttNa -> Pro Cod, AttMaxLen -> 6, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 3, AttNa -> REQ CDE, AttMaxLen -> 7, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 4, AttNa -> RED Ty, AttMaxLen -> 2, DataTy -> Map(DataTyName -> AN))), RedLen -> 117, RedDeIn -> 4, MinNoOfAt -> 33)))
</code>```

The output come from getJsonKeyValue

```<code>RedTypP = ^.{14}XY.*$
RedTypC = XY
ExpNoOfAt = 19
AttId = 1
AttNa = Pro Ty
AttMaxLen =1
DataTyName = AN
AttId = 2
AttNa = Pro Cod
AttMaxLen = 6
DataName = AN
AttId = 3
AttNa = REQ CODE
AttMaxLen = 7
DataTyName = AN
RedLen = 117
RedDeIn = 2
MinNoOfAt =19
</code>```

答:
You can use mapValues to apply a function to each value in the map:

```<code>def getJsonKeyValue(mapIs: Map[String, Any]) :Map[String, Any] = {
  mapIs.mapValues {
    case (v: List[Map[String, Any]]) => v.map(x => getJsonKeyValue(x))
    case (v: Any) => v
  }
}
</code>```

Body:
Whenever i will call getJsonKeyValue it should print the output like below,How can i store the value of getJsonKeyValue and using accordingly.

      getJsonKeyValue(WithMap: Map[String, Any])

      def getJsonKeyValue(mapIs: Map[String, Any]) {

         mapIs.foreach {
            case (k: String, v: List[Map[String, Any]]) =>  v.foreach(x => getJsonKeyValue(x))
            case (k: String, v: Any) => (k + "=" + v)

      }

    }

mapIs

Map(RedDef -> List(Map(RedTypP -> ^.{14}XY.*$, RedTypC -> XY, ExpNoOfAt -> 19, attributes -> List(Map(AttId -> 1, AttNa -> Pro Ty, AttMaxLen -> 1, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 2, AttNa -> Pro Cod, AttMaxLen -> 6, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 3, AttNa -> REQ CODE, AttMaxLen -> 7, DataTy -> Map(DataTyName -> AN))), RedLen -> 117, RedDeIn -> 2, MinNoOfAt -> 19), Map(RedTypP -> ^.{14}JK.*$, RedTypC -> JK, ExpNoOfAt -> 10, attributes -> List(Map(AttId -> 1, AttNa -> Log Si Ty, AttMaxLen -> 1, DataTy -> Map(DataTyName -> A)), Map(AttId -> 2, AttNa -> Log Si Cod, AttMaxLen -> 6, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 3, AttNa -> Ex Qu Cod, AttMaxLen -> 7, DataTy -> Map(DataTyName -> AN))), RedDeIn -> 3, MinNoOfAt -> 10), Map(RedTypP -> ^.{14}FK.*$, RedTypC -> FK, ExpNoOfAt -> 33, attributes -> List(Map(AttId -> 1, AttNa -> Pro Ty, AttMaxLen -> 1, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 2, AttNa -> Pro Cod, AttMaxLen -> 6, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 3, AttNa -> REQ CDE, AttMaxLen -> 7, DataTy -> Map(DataTyName -> AN)), Map(AttId -> 4, AttNa -> RED Ty, AttMaxLen -> 2, DataTy -> Map(DataTyName -> AN))), RedLen -> 117, RedDeIn -> 4, MinNoOfAt -> 33)))

The output come from getJsonKeyValue

RedTypP = ^.{14}XY.*$
RedTypC = XY
ExpNoOfAt = 19
AttId = 1
AttNa = Pro Ty
AttMaxLen =1
DataTyName = AN
AttId = 2
AttNa = Pro Cod
AttMaxLen = 6
DataName = AN
AttId = 3
AttNa = REQ CODE
AttMaxLen = 7
DataTyName = AN
RedLen = 117
RedDeIn = 2
MinNoOfAt =19

Body:
You can use mapValues to apply a function to each value in the map:

def getJsonKeyValue(mapIs: Map[String, Any]) :Map[String, Any] = {
  mapIs.mapValues {
    case (v: List[Map[String, Any]]) => v.map(x => getJsonKeyValue(x))
    case (v: Any) => v
  }
}


问:
SQL. I need connect two row based on dates
At the start i'm realy sorry for my bad english.

I need compare rows with the same id and if they are correct connect them:

```<code>  id  Date1       Date2         Date3     Date4
1210 2013-01-09    NULL     2018-04-10  2023-04-11
1210 2013-09-01 2018-10-04  2023-11-04     NULL
  83 2009-11-17    NULL     2014-11-30  2016-11-30
  83 2009-11-17    NULL        NULL     2016-11-30
 198 2008-04-22    NULL     2013-04-30  2015-04-30
 198 2008-04-22 2013-04-30  2014-04-30  2015-04-30
 198 2008-04-22    NULL        NULL        NULL
2070 1997-06-18    NULL     2002-09-30     N/A
2070 1997-06-18 2001-09-30  2002-09-30     NULL
2070 1997-06-18    NULL        NULL     2002-09-30
</code>```

Rows from which I have already take data shoul be deleted.

Effect should be:

```<code> id  Date1       Date2         Date3     Date4
1210 2013-01-09    NULL     2018-04-10  2023-04-11
1210 2013-09-01 2018-10-04  2023-11-04     NULL
  83 2009-11-17    NULL     2014-11-30  2016-11-30
 198 2008-04-22    NULL     2013-04-30  2015-04-30
 198 2008-04-22 2013-04-30  2014-04-30  2015-04-30
2070 1997-06-18 2001-09-30  2002-09-30  2002-09-30
</code>```

1210 - Is unchanged because part of the date is different.

83 - are comparet then row with less data should be removed.

198 - Matched line data is assigned to the first matching line and the line is deleted. second line Is unchanged because part of the date is different.

2070 - All lines are merged into one. The attached lines are deleted.

I was tried make code:

```<code> update tb
 set tb.Date1 = case
                  when tj.Date1 is not null and (tb.Date1 is null or tb.Date1 = 'n/a')  then tj.Date1 end,
 tb.Date2 = case
                  when tj.Date2 is not null and (tb.Date2 is null or tb.Date2 = 'n/a') then tj.Date2 end,
 tb.Date3 = case
                  when tj.Date3 is not null and (tb.Date3 is null or tb.Date3 = 'n/a') then tj.Date3 end,
 tb.Date4 = case
                  when tj.Date4 is not null and (tb.Date4 is null or tb.Date4 = 'n/a') then tj.Date4    end
from
testcheck as tb inner join testcheck as tj on tb.Product_ID= tj.Product_ID
where (tb.Date1 = tj.Date1 or tb.Date1 is null or tj.Date1 is null or tb.Date1 = 'n/a' or tj.Date1 = 'n/a')
and (tb.Date2 = tj.Date2 or tb.Date2 is null or tj.Date2 is null or tb.Date2 = 'n/a' or tj.Date2 = 'n/a')
and (tb.Date3 = tj.Date3 or tb.Date3 is null or tj.Date3 is null or tb.Date3 = 'n/a' or tj.Date3 = 'n/a')
and (tb.Date4 = tj.Date4 or tb.Date4 is null or tj.Date4 is null or tb.Date4 = 'n/a' or tj.Date4 = 'n/a')
</code>```

答:
If I were in your situation, rather than trying to update the testcheck table, I would use a query to extract the data in the format I wanted, and then just insert that into a new table with the same structure:

```<code>CREATE TABLE newtestcheck (id int, Date1 datetime, Date2 datetime, Date3 datetime,
                           Date4 datetime);

INSERT INTO newtestcheck
SELECT id,
       Date1,
       MAX(Date2),
       MAX(Date3),
       MAX(Date4)
FROM testcheck
GROUP BY id, Date1;
</code>```

After this, you can drop the original table and then possibly rename newtestcheck back to testcheck if you want.

Note: You have a very suspicious looking N/A data point in one of the date columns.  If literal, then it would mean you are storing your dates as text, and then my query would have to be modified.

Body:
At the start i'm realy sorry for my bad english.

I need compare rows with the same id and if they are correct connect them:

  id  Date1       Date2         Date3     Date4
1210 2013-01-09    NULL     2018-04-10  2023-04-11
1210 2013-09-01 2018-10-04  2023-11-04     NULL
  83 2009-11-17    NULL     2014-11-30  2016-11-30
  83 2009-11-17    NULL        NULL     2016-11-30
 198 2008-04-22    NULL     2013-04-30  2015-04-30
 198 2008-04-22 2013-04-30  2014-04-30  2015-04-30
 198 2008-04-22    NULL        NULL        NULL
2070 1997-06-18    NULL     2002-09-30     N/A
2070 1997-06-18 2001-09-30  2002-09-30     NULL
2070 1997-06-18    NULL        NULL     2002-09-30

Rows from which I have already take data shoul be deleted.

Effect should be:

 id  Date1       Date2         Date3     Date4
1210 2013-01-09    NULL     2018-04-10  2023-04-11
1210 2013-09-01 2018-10-04  2023-11-04     NULL
  83 2009-11-17    NULL     2014-11-30  2016-11-30
 198 2008-04-22    NULL     2013-04-30  2015-04-30
 198 2008-04-22 2013-04-30  2014-04-30  2015-04-30
2070 1997-06-18 2001-09-30  2002-09-30  2002-09-30

1210 - Is unchanged because part of the date is different.

83 - are comparet then row with less data should be removed.

198 - Matched line data is assigned to the first matching line and the line is deleted. second line Is unchanged because part of the date is different.

2070 - All lines are merged into one. The attached lines are deleted.

I was tried make code:

 update tb
 set tb.Date1 = case
                  when tj.Date1 is not null and (tb.Date1 is null or tb.Date1 = 'n/a')  then tj.Date1 end,
 tb.Date2 = case
                  when tj.Date2 is not null and (tb.Date2 is null or tb.Date2 = 'n/a') then tj.Date2 end,
 tb.Date3 = case
                  when tj.Date3 is not null and (tb.Date3 is null or tb.Date3 = 'n/a') then tj.Date3 end,
 tb.Date4 = case
                  when tj.Date4 is not null and (tb.Date4 is null or tb.Date4 = 'n/a') then tj.Date4    end
from
testcheck as tb inner join testcheck as tj on tb.Product_ID= tj.Product_ID
where (tb.Date1 = tj.Date1 or tb.Date1 is null or tj.Date1 is null or tb.Date1 = 'n/a' or tj.Date1 = 'n/a')
and (tb.Date2 = tj.Date2 or tb.Date2 is null or tj.Date2 is null or tb.Date2 = 'n/a' or tj.Date2 = 'n/a')
and (tb.Date3 = tj.Date3 or tb.Date3 is null or tj.Date3 is null or tb.Date3 = 'n/a' or tj.Date3 = 'n/a')
and (tb.Date4 = tj.Date4 or tb.Date4 is null or tj.Date4 is null or tb.Date4 = 'n/a' or tj.Date4 = 'n/a')

Body:
If I were in your situation, rather than trying to update the testcheck table, I would use a query to extract the data in the format I wanted, and then just insert that into a new table with the same structure:

CREATE TABLE newtestcheck (id int, Date1 datetime, Date2 datetime, Date3 datetime,
                           Date4 datetime);

INSERT INTO newtestcheck
SELECT id,
       Date1,
       MAX(Date2),
       MAX(Date3),
       MAX(Date4)
FROM testcheck
GROUP BY id, Date1;

After this, you can drop the original table and then possibly rename newtestcheck back to testcheck if you want.

Note: You have a very suspicious looking N/A data point in one of the date columns.  If literal, then it would mean you are storing your dates as text, and then my query would have to be modified.


问:
How can I set a fixed location for text so when it grows it still be in a center?
When integer is changed the text contained it changes its location. I want that it be at the same position as when int equals to 100. Even when it equals to 5. Here is my code :

```<code>Stage priceStage = new Stage();
priceStage.setResizable(false);
priceStage.setWidth(450);
priceStage.setHeight(450);
priceStage.setTitle(windowTitle);

IntegerProperty price, maxIncome, adLevel;

price = new SimpleIntegerProperty(priceDifference);
maxIncome = new SimpleIntegerProperty();
adLevel = new SimpleIntegerProperty(1);
Button goButton = new Button("Организовать!");

Text assignPriceText = new Text("   Цена на одного студента: ");
assignPriceText.setFont(Font.font("Arial", FontWeight.BOLD, 30));

Text plus = new Text("+");
Text minus = new Text("-");
Text priceInfo = new Text();

Text priceText = new Text();
Text studentsAmmountText = new Text();
Text maxIncomeText = new Text();
Text adLevelText = new Text();

priceText.textProperty().bind(price.asString("%d $"));
studentsAmmountText.textProperty().bind(studentsAmmount.asString("\nКоличество студентов: %d"));
maxIncomeText.textProperty().bind(maxIncome.asString("\nДоход: %d $"));
adLevelText.textProperty().bind(adLevel.asString("\nРеклама: %d %% \n"));

TextFlow priceTextFlow = new TextFlow(minus, priceText, plus, studentsAmmountText, maxIncomeText, adLevelText);
priceTextFlow.setPadding(new Insets(0,0,0,50));

plus.setFill(Color.RED);
minus.setFill(Color.RED);

plus.setFont(Font.font(80));
minus.setFont(Font.font(80));
priceText.setFont(Font.font(100));
studentsAmmountText.setFont(Font.font(30));
maxIncomeText.setFont(Font.font(30));
adLevelText.setFont(Font.font(30));
goButton.setFont(Font.font(30));
</code>```

As you can see from pictures, when number is 75 there is a useless space which I indicated by red line. But when number is 100 it is perfectly located at the center. So how can I make text automatically changes its position when number changes?

答:
Finally, I have found the solution :

```<code>price.addListener((c, o, n)->{
    space.setPrefWidth(120-30*String.valueOf(n).length());
});
</code>```

I have added listener to the price (not text, but IntegerProperty) and everytime when there is a new digit added to number, space (Region) is reduced as much as the size of space of new digit. It equals to 30. So I convert new number to string for defining its length, then I multiple it to 30 and reduce space.

Body:
When integer is changed the text contained it changes its location. I want that it be at the same position as when int equals to 100. Even when it equals to 5. Here is my code :

Stage priceStage = new Stage();
priceStage.setResizable(false);
priceStage.setWidth(450);
priceStage.setHeight(450);
priceStage.setTitle(windowTitle);

IntegerProperty price, maxIncome, adLevel;

price = new SimpleIntegerProperty(priceDifference);
maxIncome = new SimpleIntegerProperty();
adLevel = new SimpleIntegerProperty(1);
Button goButton = new Button("Организовать!");

Text assignPriceText = new Text("   Цена на одного студента: ");
assignPriceText.setFont(Font.font("Arial", FontWeight.BOLD, 30));

Text plus = new Text("+");
Text minus = new Text("-");
Text priceInfo = new Text();

Text priceText = new Text();
Text studentsAmmountText = new Text();
Text maxIncomeText = new Text();
Text adLevelText = new Text();

priceText.textProperty().bind(price.asString("%d $"));
studentsAmmountText.textProperty().bind(studentsAmmount.asString("\nКоличество студентов: %d"));
maxIncomeText.textProperty().bind(maxIncome.asString("\nДоход: %d $"));
adLevelText.textProperty().bind(adLevel.asString("\nРеклама: %d %% \n"));

TextFlow priceTextFlow = new TextFlow(minus, priceText, plus, studentsAmmountText, maxIncomeText, adLevelText);
priceTextFlow.setPadding(new Insets(0,0,0,50));

plus.setFill(Color.RED);
minus.setFill(Color.RED);

plus.setFont(Font.font(80));
minus.setFont(Font.font(80));
priceText.setFont(Font.font(100));
studentsAmmountText.setFont(Font.font(30));
maxIncomeText.setFont(Font.font(30));
adLevelText.setFont(Font.font(30));
goButton.setFont(Font.font(30));

As you can see from pictures, when number is 75 there is a useless space which I indicated by red line. But when number is 100 it is perfectly located at the center. So how can I make text automatically changes its position when number changes?

Body:
Finally, I have found the solution :

price.addListener((c, o, n)->{
    space.setPrefWidth(120-30*String.valueOf(n).length());
});

I have added listener to the price (not text, but IntegerProperty) and everytime when there is a new digit added to number, space (Region) is reduced as much as the size of space of new digit. It equals to 30. So I convert new number to string for defining its length, then I multiple it to 30 and reduce space.