问:
JBPM Task Event Lister Registration
I am using JBPM 6.2 core engine in our application.

I wanted to use my own Custom Task Event Listener to execute my own java code.

I didn't find any documentation so that I can use with JBPM core runtime engine. I found multiple places to use with console and define in deployment descriptor.

Please help!

答:
We can register Task event Listener at RuntimeManager level or at TaskService level.

```<code>TaskService taskService = runtime.getTaskService();
        ((EventService<TaskLifeCycleEventListener>)taskService).registerTaskEventListener(new DefaultTaskEventListener() {
            @Override
            public void afterTaskAddedEvent(TaskEvent event) {
                System.out.println("taskId = " + event.getTask().getId());
            }
        });
</code>```

At RuntimeManager level:

RuntimeEnvironment environment =
  RuntimeEnvironmentBuilder.getDefault()
                  .persistence(true)
                  .entityManagerFactory(emf)
                  .userGroupCallback(userGroupCallback)
                  .addAsset(ResourceFactory.newClassPathResource(process),
  ResourceType.BPMN2)
                  .registerableItemsFactory(new DefaultRegisterableItemsFactory() {
                      @Override
                      public List getTaskListeners() {
                          List listeners = super.getTaskListeners();
                          listeners.add(new DefaultTaskEventListener() {
                              @Override
                              public void afterTaskAddedEvent(TaskEvent event) {
                                  System.out.println("taskId = " + event.getTask().getId());
                              }
                          });
                          return listeners;
                      }
                  })
                  .get();
          return RuntimeManagerFactory.Factory.get().newPerProcessInstanceRuntimeManager(environment);

Title: JBPM Task Event Lister Registration

Body:
We can register Task event Listener at RuntimeManager level or at TaskService level.

TaskService taskService = runtime.getTaskService();
        ((EventService<TaskLifeCycleEventListener>)taskService).registerTaskEventListener(new DefaultTaskEventListener() {
            @Override
            public void afterTaskAddedEvent(TaskEvent event) {
                System.out.println("taskId = " + event.getTask().getId());
            }
        });

At RuntimeManager level:

RuntimeEnvironment environment =
  RuntimeEnvironmentBuilder.getDefault()
                  .persistence(true)
                  .entityManagerFactory(emf)
                  .userGroupCallback(userGroupCallback)
                  .addAsset(ResourceFactory.newClassPathResource(process),
  ResourceType.BPMN2)
                  .registerableItemsFactory(new DefaultRegisterableItemsFactory() {
                      @Override
                      public List getTaskListeners() {
                          List listeners = super.getTaskListeners();
                          listeners.add(new DefaultTaskEventListener() {
                              @Override
                              public void afterTaskAddedEvent(TaskEvent event) {
                                  System.out.println("taskId = " + event.getTask().getId());
                              }
                          });
                          return listeners;
                      }
                  })
                  .get();
          return RuntimeManagerFactory.Factory.get().newPerProcessInstanceRuntimeManager(environment);


来源: stackexchange

问:
Output being printed twice
I'm attempting to use sockets to program client and server interactions. The user can read their messages, compose a message to someone, and exit. Everything works properly except "NO MESSAGES" is printing out twice instead of once and I can't figure out why. I'll put the relevant code below, any help would be great. Thanks!

Client.java

```<code>     import java.io.*;
import java.net.*;

public class Client {

    public static void main(String[] args) {

    String messages = "";

    // Makes sure there are only two arguments entered

        if(args.length != 2) {
            System.err.println("Usage: java Client <host name> <port number>");
            System.exit(1);
        }

        // Stores the command line arguments for readability further in the program
        String host = args[0];
        int port = Integer.parseInt(args[1]);

        try (

            // Creates the socket to be used
            Socket s = new Socket(host, port);

            // Reader and Writer to talk with Server
            PrintWriter pw =
                        new PrintWriter(s.getOutputStream(), true);
            BufferedReader bf = new BufferedReader(
                        new InputStreamReader(s.getInputStream()));
        ) {

            // Reader to read from standard input (keyboard)
            BufferedReader keyboard =
                        new BufferedReader(new InputStreamReader(System.in));

        // User interface
        while (true) {

        System.out.println("Please enter your username: ");
        String username = keyboard.readLine();

            // Check that the login is valid
            if (username == null) {
            System.out.println("No username entered");
            }
            else if (username.contains(" ")) {
            System.out.println("Username cannot contain spaces");
            }
                // Send username to server and return number of messages
            else {
                pw.println(username);
            messages = bf.readLine();
            System.out.println("You have " + Integer.parseInt(messages) + " messages");
            break;
            }
        }

        // Enable the user to continue reading and composing messages until
        // they choose to exit
        while (true) {
            System.out.println("Would you like to READ, COMPOSE or EXIT?");
            String choice = keyboard.readLine();

        // Shows the messages left for the user
                if (choice.equals("READ")) {
            pw.println("READ");
            messages = bf.readLine();
                    if (Integer.parseInt(messages) == 0) {
                        System.out.println("NO MESSAGES");
            }
            else {
            String incoming = bf.readLine();
            System.out.println(incoming);
                        incoming = bf.readLine();
            System.out.println(incoming);
            }
            }
        // Allows user to write a message to another user
            else if (choice.equals("COMPOSE")) {
            pw.println("COMPOSE");
            // I've separated this into two lines for readability
            System.out.println("Enter message recipient");
            String recipient = keyboard.readLine();
            if (recipient == null) {
                System.out.println("No recipient username entered");
                }
                else if (recipient.contains(" ")) {
                System.out.println("Recipient username cannot contain spaces");
                }
            else {
            pw.println(recipient);
                        System.out.println("Enter message to be sent");
                String im = keyboard.readLine();
                pw.println(im);
            System.out.println(bf.readLine());
            }
            }
            else if (choice.equals("EXIT")) {
            pw.println("EXIT");
            System.exit(1);
            }
            else {
                    System.out.println("Error: you must either READ, COMPOSE or EXIT");
            }
        }

        }

        // Catches the exception in which the server cannot be found
        catch(IOException e) {

            System.out.println("Error, could not connect to Server");
            System.exit(1);
        }
    }
}
</code>```

Sever.java

```<code>    import java.io.*;
import java.net.*;

public class Server {

        public static void main(String[] args) {

        String request;

            // Makes sure that the user has specified the correct number of command line arguments
            if(args.length != 1) {
                System.err.println("Usage: java Server <port number>");
                System.exit(1);
            }
            int port = Integer.parseInt(args[0]);

            try (
            // Creates a server socket and waits for a connection
                ServerSocket ss = new ServerSocket(port);

                // A socket to communicate with the client
                Socket cs = ss.accept();

                // Reader and Writer to talk with Client
                PrintWriter pw =
                            new PrintWriter(cs.getOutputStream(), true);
                BufferedReader bf = new BufferedReader(
                            new InputStreamReader(cs.getInputStream()));
            )

                // Links the server to the protocol
            {
            Protocol protocol = new Protocol();
            protocol.storeUsername(bf.readLine());
            pw.println(protocol.messagesNumber());

            // Loop through user input until EXIT is entered
                while (true) {
                request = bf.readLine();
                // Controls output if user inputs READ
                if (request.equals("READ")) {
                    pw.println(protocol.messagesNumber());
                    if (protocol.messagesNumber() != 0) {
                        pw.println(protocol.readSender());
                        pw.println(protocol.readMessage());
                    }
                }
                // Controls input if user inputs COMPOSE
                else if (request.equals("COMPOSE")) {
                    String sender = bf.readLine();
                    String message = bf.readLine();
                    if (protocol.append(sender, message)) {
                    pw.println("MESSAGE SENT");
                }
                    else {
                    pw.println("MESSAGE FAILED");
                }
                }
                // Exits the server
                else {
                    System.exit(1);
                }
            }
            }

              // Catches the exception in which the server cannot find a client
              catch(IOException e) {
                  System.out.println("Failed to find a client");
                  System.exit(1);
              }

       }
    }
</code>```

Protocol.java

```<code>import java.net.*;
import java.io.*;
import java.util.*;

public class Protocol {
    private String username;
    private String recipient;
    private String sender;
    private HashMap<String, ArrayList<String>> senderMap = new HashMap<String, ArrayList<String>>();
    private HashMap<String, ArrayList<String>> messageMap = new HashMap<String, ArrayList<String>>();

    // Stores the username for the logged in user
    public void storeUsername(String user) {
    username = user;
    }

    // Stores the recipient name
    public void storeRecipient(String name) {
        recipient = name;
    }

    // Returns how many messages the logged in user has
    public int messagesNumber() {
    if(messageMap.containsKey(username))
        return messageMap.get(username).size();
    else
        return 0;
    }

    public boolean append(String recipient, String message) {
    boolean success = false;
    // If there is an entry for that name, just add the message to the end
        if(messageMap.containsKey(recipient)) {
        senderMap.get(recipient).add(username);
        messageMap.get(recipient).add(message);
        success = true;
        }
    // If there is no entry for that name, create a new entry with a list of messages and add the first message
    else {
        senderMap.put(recipient, new ArrayList<String>());
        senderMap.get(recipient).add(username);
        messageMap.put(recipient, new ArrayList<String>());
        messageMap.get(recipient).add(message);
        success = true;
    }
    return success;
    }

     public String readSender() {

    // If the user has an entry and has at least 1 sender, return the least recent sender and then remove it  (the sender first in the list)
        if(senderMap.containsKey(username)) {

            if(senderMap.get(username).size() > 0) {
            String temp = senderMap.get(username).get(0);
            senderMap.get(username).remove(0);
            return temp;
        }
            else
            // If there are no messages left to read
            return "NO MESSAGES";
        }
        else
        // If the login hasn't been created yet
            return "NO MESSAGES";
    }

    public String readMessage() {

    // If the user has an entry and has at least 1 unread message, return the least recent unread message and then remove it (the first  message in the list)
        if(messageMap.containsKey(username)) {

            if(messageMap.get(username).size() > 0) {
            String temp = messageMap.get(username).get(0);
            messageMap.get(username).remove(0);
            return temp;
        }
            else
            // If there are no messages left to read
            return "NO MESSAGES";
        }
        else
        // If the login hasn't been created yet
            return "NO MESSAGES";
    }

}
</code>```

答:
The reason for this is that you are fetching the "NO MESSAGES" twice.

Have a look at the code from server.java

```<code> if (request.equals("READ")) {
   pw.println(protocol.messagesNumber());
   pw.println(protocol.readSender());
   pw.println(protocol.readMessage());
 }
</code>```

This will call readSender() and readMessage() methods.

Now have a look at the return statements from both of these methods - return "NO MESSAGES";

Just set debug breakpoints in these two methods and debug and check!

ContentLicense: CC BY-SA 3.0

Title: Output being printed twice

Body:
I'm attempting to use sockets to program client and server interactions. The user can read their messages, compose a message to someone, and exit. Everything works properly except "NO MESSAGES" is printing out twice instead of once and I can't figure out why. I'll put the relevant code below, any help would be great. Thanks!

Client.java

     import java.io.*;
import java.net.*;

public class Client {

    public static void main(String[] args) {

    String messages = "";

    // Makes sure there are only two arguments entered

        if(args.length != 2) {
            System.err.println("Usage: java Client <host name> <port number>");
            System.exit(1);
        }

        // Stores the command line arguments for readability further in the program
        String host = args[0];
        int port = Integer.parseInt(args[1]);

        try (

            // Creates the socket to be used
            Socket s = new Socket(host, port);

            // Reader and Writer to talk with Server
            PrintWriter pw =
                        new PrintWriter(s.getOutputStream(), true);
            BufferedReader bf = new BufferedReader(
                        new InputStreamReader(s.getInputStream()));
        ) {

            // Reader to read from standard input (keyboard)
            BufferedReader keyboard =
                        new BufferedReader(new InputStreamReader(System.in));

        // User interface
        while (true) {

        System.out.println("Please enter your username: ");
        String username = keyboard.readLine();

            // Check that the login is valid
            if (username == null) {
            System.out.println("No username entered");
            }
            else if (username.contains(" ")) {
            System.out.println("Username cannot contain spaces");
            }
                // Send username to server and return number of messages
            else {
                pw.println(username);
            messages = bf.readLine();
            System.out.println("You have " + Integer.parseInt(messages) + " messages");
            break;
            }
        }

        // Enable the user to continue reading and composing messages until
        // they choose to exit
        while (true) {
            System.out.println("Would you like to READ, COMPOSE or EXIT?");
            String choice = keyboard.readLine();

        // Shows the messages left for the user
                if (choice.equals("READ")) {
            pw.println("READ");
            messages = bf.readLine();
                    if (Integer.parseInt(messages) == 0) {
                        System.out.println("NO MESSAGES");
            }
            else {
            String incoming = bf.readLine();
            System.out.println(incoming);
                        incoming = bf.readLine();
            System.out.println(incoming);
            }
            }
        // Allows user to write a message to another user
            else if (choice.equals("COMPOSE")) {
            pw.println("COMPOSE");
            // I've separated this into two lines for readability
            System.out.println("Enter message recipient");
            String recipient = keyboard.readLine();
            if (recipient == null) {
                System.out.println("No recipient username entered");
                }
                else if (recipient.contains(" ")) {
                System.out.println("Recipient username cannot contain spaces");
                }
            else {
            pw.println(recipient);
                        System.out.println("Enter message to be sent");
                String im = keyboard.readLine();
                pw.println(im);
            System.out.println(bf.readLine());
            }
            }
            else if (choice.equals("EXIT")) {
            pw.println("EXIT");
            System.exit(1);
            }
            else {
                    System.out.println("Error: you must either READ, COMPOSE or EXIT");
            }
        }

        }

        // Catches the exception in which the server cannot be found
        catch(IOException e) {

            System.out.println("Error, could not connect to Server");
            System.exit(1);
        }
    }
}

Sever.java

    import java.io.*;
import java.net.*;

public class Server {

        public static void main(String[] args) {

        String request;

            // Makes sure that the user has specified the correct number of command line arguments
            if(args.length != 1) {
                System.err.println("Usage: java Server <port number>");
                System.exit(1);
            }
            int port = Integer.parseInt(args[0]);

            try (
            // Creates a server socket and waits for a connection
                ServerSocket ss = new ServerSocket(port);

                // A socket to communicate with the client
                Socket cs = ss.accept();

                // Reader and Writer to talk with Client
                PrintWriter pw =
                            new PrintWriter(cs.getOutputStream(), true);
                BufferedReader bf = new BufferedReader(
                            new InputStreamReader(cs.getInputStream()));
            )

                // Links the server to the protocol
            {
            Protocol protocol = new Protocol();
            protocol.storeUsername(bf.readLine());
            pw.println(protocol.messagesNumber());

            // Loop through user input until EXIT is entered
                while (true) {
                request = bf.readLine();
                // Controls output if user inputs READ
                if (request.equals("READ")) {
                    pw.println(protocol.messagesNumber());
                    if (protocol.messagesNumber() != 0) {
                        pw.println(protocol.readSender());
                        pw.println(protocol.readMessage());
                    }
                }
                // Controls input if user inputs COMPOSE
                else if (request.equals("COMPOSE")) {
                    String sender = bf.readLine();
                    String message = bf.readLine();
                    if (protocol.append(sender, message)) {
                    pw.println("MESSAGE SENT");
                }
                    else {
                    pw.println("MESSAGE FAILED");
                }
                }
                // Exits the server
                else {
                    System.exit(1);
                }
            }
            }

              // Catches the exception in which the server cannot find a client
              catch(IOException e) {
                  System.out.println("Failed to find a client");
                  System.exit(1);
              }

       }
    }

Protocol.java

import java.net.*;
import java.io.*;
import java.util.*;

public class Protocol {
    private String username;
    private String recipient;
    private String sender;
    private HashMap<String, ArrayList<String>> senderMap = new HashMap<String, ArrayList<String>>();
    private HashMap<String, ArrayList<String>> messageMap = new HashMap<String, ArrayList<String>>();

    // Stores the username for the logged in user
    public void storeUsername(String user) {
    username = user;
    }

    // Stores the recipient name
    public void storeRecipient(String name) {
        recipient = name;
    }

    // Returns how many messages the logged in user has
    public int messagesNumber() {
    if(messageMap.containsKey(username))
        return messageMap.get(username).size();
    else
        return 0;
    }

    public boolean append(String recipient, String message) {
    boolean success = false;
    // If there is an entry for that name, just add the message to the end
        if(messageMap.containsKey(recipient)) {
        senderMap.get(recipient).add(username);
        messageMap.get(recipient).add(message);
        success = true;
        }
    // If there is no entry for that name, create a new entry with a list of messages and add the first message
    else {
        senderMap.put(recipient, new ArrayList<String>());
        senderMap.get(recipient).add(username);
        messageMap.put(recipient, new ArrayList<String>());
        messageMap.get(recipient).add(message);
        success = true;
    }
    return success;
    }

     public String readSender() {

    // If the user has an entry and has at least 1 sender, return the least recent sender and then remove it  (the sender first in the list)
        if(senderMap.containsKey(username)) {

            if(senderMap.get(username).size() > 0) {
            String temp = senderMap.get(username).get(0);
            senderMap.get(username).remove(0);
            return temp;
        }
            else
            // If there are no messages left to read
            return "NO MESSAGES";
        }
        else
        // If the login hasn't been created yet
            return "NO MESSAGES";
    }

    public String readMessage() {

    // If the user has an entry and has at least 1 unread message, return the least recent unread message and then remove it (the first  message in the list)
        if(messageMap.containsKey(username)) {

            if(messageMap.get(username).size() > 0) {
            String temp = messageMap.get(username).get(0);
            messageMap.get(username).remove(0);
            return temp;
        }
            else
            // If there are no messages left to read
            return "NO MESSAGES";
        }
        else
        // If the login hasn't been created yet
            return "NO MESSAGES";
    }

}

Body:
The reason for this is that you are fetching the "NO MESSAGES" twice.

Have a look at the code from server.java

 if (request.equals("READ")) {
   pw.println(protocol.messagesNumber());
   pw.println(protocol.readSender());
   pw.println(protocol.readMessage());
 }

This will call readSender() and readMessage() methods.

Now have a look at the return statements from both of these methods - return "NO MESSAGES";

Just set debug breakpoints in these two methods and debug and check!


问:
Python: draw tangent graph using math & turtle libraries
I was stuck on this task for several days. Although, the solution should be simple. I apply math and turtle libraries for drawing 3 graphs: sine, cosine and tangent with amplitude 200. The problem is I cant build the tangent graph as It should be drawn.
This is what I should do:

This is what I got:

As you see, my turtle goes up and doesn't come back anymore.
Pls, don't suggest me to use numpy. It's out of my task.
Thank you for advance!

```<code>import math
import turtle

ws = turtle.Screen()
ws.bgcolor("white")
t = turtle.Turtle()
for i in [(0,250), (0,0), (0,-250), (0,0), (400,0), (0,0)]:
    t.goto(i, None)
    t.write(i, font=("Arial", 12))

t.color("red")

for angle in range(360):
    y = math.sin(math.radians(angle))
    t.goto(angle, y * 200)

t.penup()
t.setpos(0,200)
t.goto(0,200)
t.pendown()
t.color("blue")

for angle in range(360):
    y = math.cos(math.radians(angle))
    t.goto(angle, y * 200)

t.penup()
t.setpos(0,0)
t.goto(0,0)
t.pendown()
t.color("green")

for angle in range(360):
    y = math.tan(math.radians(angle))
    t.goto(angle, y * 200)

ws.exitonclick()
</code>```

答:
To show that it should work, below is my minimalist implementation of plotting sine, cosine and tangent using turtle graphics:

```<code>import math
from turtle import Turtle, Screen

RESOLUTION = 0.1

def plot(x_points, y_points):
    for i, y in enumerate(y_points):
        if abs(y) <= 2.0:
            yertle.goto(x_points[i], y)
            yertle.pendown()
        else:
            yertle.penup()

    yertle.penup()

screen = Screen()
screen.setworldcoordinates(0, -1.5, 2 * math.pi / RESOLUTION, 1.5)

yertle = Turtle()
yertle.penup()

x = range(int(2 * math.pi / RESOLUTION))

yertle.color("blue")
plot(x, (math.cos(n * RESOLUTION) for n in x))

yertle.color("red")
plot(x, (math.sin(n * RESOLUTION) for n in x))

yertle.color("dark green")
plot(x, (math.tan(n * RESOLUTION) for n in x))

screen.exitonclick()
</code>```

OUTPUT

My guess is you're not waiting long enough for tangent to plot, i.e. it's slowly plotting lots of points off the window and will eventually reappear on-screen.  My code works around that issue.

Body:
I was stuck on this task for several days. Although, the solution should be simple. I apply math and turtle libraries for drawing 3 graphs: sine, cosine and tangent with amplitude 200. The problem is I cant build the tangent graph as It should be drawn.
This is what I should do:

This is what I got:

As you see, my turtle goes up and doesn't come back anymore.
Pls, don't suggest me to use numpy. It's out of my task.
Thank you for advance!

import math
import turtle

ws = turtle.Screen()
ws.bgcolor("white")
t = turtle.Turtle()
for i in [(0,250), (0,0), (0,-250), (0,0), (400,0), (0,0)]:
    t.goto(i, None)
    t.write(i, font=("Arial", 12))

t.color("red")

for angle in range(360):
    y = math.sin(math.radians(angle))
    t.goto(angle, y * 200)

t.penup()
t.setpos(0,200)
t.goto(0,200)
t.pendown()
t.color("blue")

for angle in range(360):
    y = math.cos(math.radians(angle))
    t.goto(angle, y * 200)

t.penup()
t.setpos(0,0)
t.goto(0,0)
t.pendown()
t.color("green")

for angle in range(360):
    y = math.tan(math.radians(angle))
    t.goto(angle, y * 200)

ws.exitonclick()

Body:
To show that it should work, below is my minimalist implementation of plotting sine, cosine and tangent using turtle graphics:

import math
from turtle import Turtle, Screen

RESOLUTION = 0.1

def plot(x_points, y_points):
    for i, y in enumerate(y_points):
        if abs(y) <= 2.0:
            yertle.goto(x_points[i], y)
            yertle.pendown()
        else:
            yertle.penup()

    yertle.penup()

screen = Screen()
screen.setworldcoordinates(0, -1.5, 2 * math.pi / RESOLUTION, 1.5)

yertle = Turtle()
yertle.penup()

x = range(int(2 * math.pi / RESOLUTION))

yertle.color("blue")
plot(x, (math.cos(n * RESOLUTION) for n in x))

yertle.color("red")
plot(x, (math.sin(n * RESOLUTION) for n in x))

yertle.color("dark green")
plot(x, (math.tan(n * RESOLUTION) for n in x))

screen.exitonclick()

OUTPUT

My guess is you're not waiting long enough for tangent to plot, i.e. it's slowly plotting lots of points off the window and will eventually reappear on-screen.  My code works around that issue.


问:
How to increase amplify AudioTrack?
I have the following code:

```<code>public class MainActivity extends Activity {
    private int freq = 8000;
    private AudioRecord audioRecord = null;
    private Thread Rthread = null;

    int PERMISSION_ALL = 1;
    String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO};

    private AudioTrack audioTrack = null;
    byte[] buffer = new byte[freq];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }

        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        final int bufferSize = AudioRecord.getMinBufferSize(freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize);

        audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
                AudioTrack.MODE_STREAM);

        LoudnessEnhancer enhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());

        enhancer.setTargetGain(100);
        enhancer.setEnabled(true);

        audioTrack.setPlaybackRate(freq);
        buffer = new byte[bufferSize];
        audioRecord.startRecording();
        Log.i("info", "Audio Recording started");
        audioTrack.play();
        Log.i("info", "Audio Playing started");
        Rthread = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        audioRecord.read(buffer, 0, bufferSize);
                        audioTrack.write(buffer, 0, buffer.length);

                    } catch (Throwable t) {
                        Log.e("Error", "Read write failed");
                        t.printStackTrace();
                    }
                }
            }
        });
        Rthread.start();
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }
}
</code>```

This code is able to read input from the mic and play it back on a speaker/connected headphones. So far, so good. Now, I need to amplify the volume of the input. I've tried the solution proposed here, but I just end up getting really distorted audio. I also tried the LoudnessEnhancer, but it doesn't seem to have any effect.

答:
Okay, I managed to get the LoudnessEnhancer working. I know it's a huge gain value in there, but I need a lot of gain on this one. Here's the updated code for anyone else who might have a similar problem.</p>

```<code>public class MainActivity extends Activity {
    private int freq = 8000;
    private AudioRecord audioRecord = null;
    private Thread Rthread = null;

    int PERMISSION_ALL = 1;
    String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO};

    private AudioTrack audioTrack = null;
    byte[] buffer = new byte[freq];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }

        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        final int bufferSize = AudioRecord.getMinBufferSize(freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize);

        audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
                AudioTrack.MODE_STREAM);

        LoudnessEnhancer enhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());
        NoiseSuppressor.create(audioTrack.getAudioSessionId());
        AcousticEchoCanceler.create(audioTrack.getAudioSessionId());

        enhancer.setTargetGain(10000);
        enhancer.setEnabled(true);

        audioTrack.setPlaybackRate(freq);
        buffer = new byte[bufferSize];
        audioRecord.startRecording();
        Log.i("info", "Audio Recording started");
        audioTrack.play();
        Log.i("info", "Audio Playing started");
        Rthread = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        audioRecord.read(buffer, 0, bufferSize);
                        audioTrack.write(buffer, 0, buffer.length);

                    } catch (Throwable t) {
                        Log.e("Error", "Read write failed");
                        t.printStackTrace();
                    }
                }
            }
        });
        Rthread.start();
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }
}
</code>```

Title: How to increase amplify AudioTrack?

Body:
I have the following code:

public class MainActivity extends Activity {
    private int freq = 8000;
    private AudioRecord audioRecord = null;
    private Thread Rthread = null;

    int PERMISSION_ALL = 1;
    String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO};

    private AudioTrack audioTrack = null;
    byte[] buffer = new byte[freq];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }

        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        final int bufferSize = AudioRecord.getMinBufferSize(freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize);

        audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
                AudioTrack.MODE_STREAM);

        LoudnessEnhancer enhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());

        enhancer.setTargetGain(100);
        enhancer.setEnabled(true);

        audioTrack.setPlaybackRate(freq);
        buffer = new byte[bufferSize];
        audioRecord.startRecording();
        Log.i("info", "Audio Recording started");
        audioTrack.play();
        Log.i("info", "Audio Playing started");
        Rthread = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        audioRecord.read(buffer, 0, bufferSize);
                        audioTrack.write(buffer, 0, buffer.length);

                    } catch (Throwable t) {
                        Log.e("Error", "Read write failed");
                        t.printStackTrace();
                    }
                }
            }
        });
        Rthread.start();
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }
}

This code is able to read input from the mic and play it back on a speaker/connected headphones. So far, so good. Now, I need to amplify the volume of the input. I've tried the solution proposed here, but I just end up getting really distorted audio. I also tried the LoudnessEnhancer, but it doesn't seem to have any effect.

Body:
Okay, I managed to get the LoudnessEnhancer working. I know it's a huge gain value in there, but I need a lot of gain on this one. Here's the updated code for anyone else who might have a similar problem.

public class MainActivity extends Activity {
    private int freq = 8000;
    private AudioRecord audioRecord = null;
    private Thread Rthread = null;

    int PERMISSION_ALL = 1;
    String[] PERMISSIONS = {Manifest.permission.RECORD_AUDIO};

    private AudioTrack audioTrack = null;
    byte[] buffer = new byte[freq];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!hasPermissions(this, PERMISSIONS)){
            ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
        }

        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        final int bufferSize = AudioRecord.getMinBufferSize(freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize);

        audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
                AudioTrack.MODE_STREAM);

        LoudnessEnhancer enhancer = new LoudnessEnhancer(audioTrack.getAudioSessionId());
        NoiseSuppressor.create(audioTrack.getAudioSessionId());
        AcousticEchoCanceler.create(audioTrack.getAudioSessionId());

        enhancer.setTargetGain(10000);
        enhancer.setEnabled(true);

        audioTrack.setPlaybackRate(freq);
        buffer = new byte[bufferSize];
        audioRecord.startRecording();
        Log.i("info", "Audio Recording started");
        audioTrack.play();
        Log.i("info", "Audio Playing started");
        Rthread = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        audioRecord.read(buffer, 0, bufferSize);
                        audioTrack.write(buffer, 0, buffer.length);

                    } catch (Throwable t) {
                        Log.e("Error", "Read write failed");
                        t.printStackTrace();
                    }
                }
            }
        });
        Rthread.start();
    }

    public static boolean hasPermissions(Context context, String... permissions) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }
}


问:
PHP: extract version number for string
I get each time different string.

From the string i need to extract the version number. when the version number can come in different types like:

```<code>v1.3
V1.3
v 2.4.1
V 2.4.1

version1.3
version 1.3
Version2.4.1
Version 2.4.1
</code>```

The output need to be: 1.3 or 2.4.1

one more problem is that string can contain numbers beside the version number.

what will be the fast way to do this task?

答:
You can use preg_match to do this. This will match any versions that are at the end of the string. Regex is /(\d+\.?)+$/.

```<code>$versions = array(
    'v1.3',
    'V1.3',
    'v 2.4.1',
    'V 2.4.1',
    'version1.3',
    'version 1.3',
    'Version2.4.1',
    'Version 2.4.1',
);

foreach($versions as $version) {
    if (0 !== preg_match('/(\d+\.?)+$/', $version, $matches)) {
        echo 'original: ' . $version . '; extracted: ' . $matches[0] . PHP_EOL;
    }
}
</code>```

output

```<code>original: v1.3; extracted: 1.3
original: V1.3; extracted: 1.3
original: v 2.4.1; extracted: 2.4.1
original: V 2.4.1; extracted: 2.4.1
original: version1.3; extracted: 1.3
original: version 1.3; extracted: 1.3
original: Version2.4.1; extracted: 2.4.1
original: Version 2.4.1; extracted: 2.4.1
</code>```

Title: PHP: extract version number for string

Body:
I get each time different string.

From the string i need to extract the version number. when the version number can come in different types like:

v1.3
V1.3
v 2.4.1
V 2.4.1

version1.3
version 1.3
Version2.4.1
Version 2.4.1

The output need to be: 1.3 or 2.4.1

one more problem is that string can contain numbers beside the version number.

what will be the fast way to do this task?

Body:
You can use preg_match to do this. This will match any versions that are at the end of the string. Regex is /(\d+\.?)+$/.

$versions = array(
    'v1.3',
    'V1.3',
    'v 2.4.1',
    'V 2.4.1',
    'version1.3',
    'version 1.3',
    'Version2.4.1',
    'Version 2.4.1',
);

foreach($versions as $version) {
    if (0 !== preg_match('/(\d+\.?)+$/', $version, $matches)) {
        echo 'original: ' . $version . '; extracted: ' . $matches[0] . PHP_EOL;
    }
}

output

original: v1.3; extracted: 1.3
original: V1.3; extracted: 1.3
original: v 2.4.1; extracted: 2.4.1
original: V 2.4.1; extracted: 2.4.1
original: version1.3; extracted: 1.3
original: version 1.3; extracted: 1.3
original: Version2.4.1; extracted: 2.4.1
original: Version 2.4.1; extracted: 2.4.1


问:
Splitting an array using .split method javascript
I apologize if this has been seen before but I am here:

```<code>var fullName = ["Linus Trovalds "];
var birthYear = [1969];
var myArray = [fullName + birthYear];
console.log(myArray);
</code>```

And I am trying to declare a variable named splitName, and set it equal to fullName split into two separate objects in an array using the split method. In other words, splitName should equal ["Linus", "Torvalds"] when printed to the console. How should this be written so that split name is printed to the console as mentioned above?

This split method is not working for me.

Any help will be greatly appreciated.

答:
I don't know how you have tried it but on top of my head I think you might have forgotten that fullName variable is an array.

Try console.log(fullName[0].split(" "));

Body:
I apologize if this has been seen before but I am here:

var fullName = ["Linus Trovalds "];
var birthYear = [1969];
var myArray = [fullName + birthYear];
console.log(myArray);

And I am trying to declare a variable named splitName, and set it equal to fullName split into two separate objects in an array using the split method. In other words, splitName should equal ["Linus", "Torvalds"] when printed to the console. How should this be written so that split name is printed to the console as mentioned above?

This split method is not working for me.

Any help will be greatly appreciated.


问:
Error in using 'import' in webpack.config.babel.js
```<code>(function (exports, require, module, __filename, __dirname) { import path from 'path'
                                                              ^^^^^^
SyntaxError: Unexpected token import
</code>```

This error occurs when I use webpack-dev-server --hot.

It seems like this occurs because it can't read import or webpack doesn't support import. I tried to use babel-register but it doesn't work. Is there any way to solve this problem? Refer to the code below.

webpack.config.babel.js

```<code>import path from 'path'
import webpack from 'webpack'
import HtmlPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'

const vueLoaders = {
  html: 'pug-loader',
  css: ExtractTextPlugin.extract({
    use: 'css-loader',
    fallback: 'vue-style-loader'
  }),
  scss: 'vue-style-loader!css-loader!sass-loader',
  sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
}

export default {
  entry: './client/main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },

  plugins: [
    new ExtractTextPlugin('bundle.css'),
    new HtmlPlugin({
      title: 'sex',
      template: 'client/assets/index.pug'
    })
  ],

  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: 'css-loader', fallback: 'style-loader'
        })
      }, {
        test: /\.s[a|c]ss$/,
        use: ExtractTextPlugin.extract({
          use: ['css-loader', 'sass-loader'], fallback: 'style-loader'
        })
      }, {
        test: /\.pug$/,
        loader: 'pug-loader'
      }, {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }, {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: { loaders: vueLoaders }
      }, {
        test: /\.(png|jpe?g|gif|svg|ttf|woff2?|eot)$/,
        loader: 'file-loader',
        options: { name: '[name].[ext]?[hash]' }
      }
    ]
  },

  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.common.js'
    }
  },

  devServer: {
    host: '0.0.0.0',
    historyApiFallback: true
  },
  performance: {
    hints: false
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: '"production"' }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: { warnings: false }
    }),
    new webpack.LoaderOptionsPlugin({ minimize: true })
  ])
}
</code>```

答:
babel-register only transforms the modules you require with babel where you call require("babel-register");, not the module itself.

You can use an intermediate step to make this work with the Webpack configuration.

webpack.config.js

```<code>require('babel-register');
module.exports = require('./webpack.config.babel.js');
</code>```

webpack.config.babel.js

```<code>import path from 'path'
import webpack from 'webpack'
import HtmlPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'

const vueLoaders = {
  html: 'pug-loader',
  css: ExtractTextPlugin.extract({
  ...
</code>```

Body:
(function (exports, require, module, __filename, __dirname) { import path from 'path'
                                                              ^^^^^^
SyntaxError: Unexpected token import

This error occurs when I use webpack-dev-server --hot.

It seems like this occurs because it can't read import or webpack doesn't support import. I tried to use babel-register but it doesn't work. Is there any way to solve this problem? Refer to the code below.

webpack.config.babel.js

import path from 'path'
import webpack from 'webpack'
import HtmlPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'

const vueLoaders = {
  html: 'pug-loader',
  css: ExtractTextPlugin.extract({
    use: 'css-loader',
    fallback: 'vue-style-loader'
  }),
  scss: 'vue-style-loader!css-loader!sass-loader',
  sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
}

export default {
  entry: './client/main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },

  plugins: [
    new ExtractTextPlugin('bundle.css'),
    new HtmlPlugin({
      title: 'sex',
      template: 'client/assets/index.pug'
    })
  ],

  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: 'css-loader', fallback: 'style-loader'
        })
      }, {
        test: /\.s[a|c]ss$/,
        use: ExtractTextPlugin.extract({
          use: ['css-loader', 'sass-loader'], fallback: 'style-loader'
        })
      }, {
        test: /\.pug$/,
        loader: 'pug-loader'
      }, {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }, {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: { loaders: vueLoaders }
      }, {
        test: /\.(png|jpe?g|gif|svg|ttf|woff2?|eot)$/,
        loader: 'file-loader',
        options: { name: '[name].[ext]?[hash]' }
      }
    ]
  },

  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.common.js'
    }
  },

  devServer: {
    host: '0.0.0.0',
    historyApiFallback: true
  },
  performance: {
    hints: false
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: '"production"' }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: { warnings: false }
    }),
    new webpack.LoaderOptionsPlugin({ minimize: true })
  ])
}

Body:
babel-register only transforms the modules you require with babel where you call require("babel-register");, not the module itself.

You can use an intermediate step to make this work with the Webpack configuration.

webpack.config.js

require('babel-register');
module.exports = require('./webpack.config.babel.js');

webpack.config.babel.js

import path from 'path'
import webpack from 'webpack'
import HtmlPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'

const vueLoaders = {
  html: 'pug-loader',
  css: ExtractTextPlugin.extract({
  ...


问:
How to remove specific set of list from a list?
```<code>a = [0, 0, 0, 0, 1, 0, 0]
b = [0, 0, 0, 0]
</code>```

I want to remove the [0, 0, 0, 0] from list a.

How do I do this?

答:
Convert each list to a string:

```<code>a1 = ''.join('1' if x else '0' for x in a)
b1 = ''.join('1' if x else '0' for x in b)
</code>```

Find the start index of b1 in a1:

```<code>start = a1.index(b1)
</code>```

The end index is start index plus the length of b1:

```<code>end = start + len(b1)
</code>```

Now, extract the original list fragments before start and after end and combine them:

```<code>newlist = a[:start] + a[end:]
</code>```

Body:
a = [0, 0, 0, 0, 1, 0, 0]
b = [0, 0, 0, 0]

I want to remove the [0, 0, 0, 0] from list a.

How do I do this?

Body:
Convert each list to a string:

a1 = ''.join('1' if x else '0' for x in a)
b1 = ''.join('1' if x else '0' for x in b)

Find the start index of b1 in a1:

start = a1.index(b1)

The end index is start index plus the length of b1:

end = start + len(b1)

Now, extract the original list fragments before start and after end and combine them:

newlist = a[:start] + a[end:]


Title: PHP: extract version number for string

Body:
PHP code demo

<?php
ini_set("display_errors", 1);
$versions=array(
"v1.3",
"V1.3",
"v 2.4.1",
"V 2.4.1",
"version1.3",
"version 1.3",
"Version2.4.1",
"Version 2.4.1");

foreach($versions as $version)
{
    preg_match("/[vV](?:ersion)?\s*\K[\d\.]+/", $version,$matches);
    print_r($matches);
}

Output:

Array
(
    [0] => 1.3
)
Array
(
    [0] => 1.3
)
Array
(
    [0] => 2.4.1
)
Array
(
    [0] => 2.4.1
)
Array
(
    [0] => 1.3
)
Array
(
    [0] => 1.3
)
Array
(
    [0] => 2.4.1
)
Array
(
    [0] => 2.4.1
)


问:
Getting the charging state of laptop with python on window
In my laptop, Window 7 is installed. I want to know whether my laptop is connected to charger or not using python.

答:
For the charging state, you can use the built-in psutil library or a 3rd party power library.

I am on AC power right now.

power

Installation -

```<code>pip install power
</code>```

Usage -

```<code>import power
source = power.PowerManagement().get_providing_power_source_type()
source == power.POWER_TYPE_AC
# True
source == power.POWER_TYPE_BATTERY
# False
source == power.POWER_TYPE_UPS
# False
</code>```

psutil

Does not seem to be very reliable, v5.2.1 -

```<code>import psutil
psutil.sensors_battery()
# sbattery(percent=0.0, secsleft=-1, power_plugged=None)
psutil.sensors_battery().power_plugged
# None
</code>```

Body:
For the charging state, you can use the built-in psutil library or a 3rd party power library.

I am on AC power right now.

power

Installation -

pip install power

Usage -

import power
source = power.PowerManagement().get_providing_power_source_type()
source == power.POWER_TYPE_AC
# True
source == power.POWER_TYPE_BATTERY
# False
source == power.POWER_TYPE_UPS
# False

psutil

Does not seem to be very reliable, v5.2.1 -

import psutil
psutil.sensors_battery()
# sbattery(percent=0.0, secsleft=-1, power_plugged=None)
psutil.sensors_battery().power_plugged
# None


问:
How can I upsert a document in rethinkdb (reql) by an arbitrary property?
I have an .itemId which comes from a 3rd party, not generated by me.

I need to look for it in the db and update or insert it if one doesn't exist.

I've tried using this example from the cookbook: https://www.rethinkdb.com/docs/cookbook/javascript/#manipulating-documents

```<code>  const res = await this.r.table('products').filter({itemId: item.itemId})
    .limit(1)
    .replace(doc => {
      return this.r.branch(
        doc.eq(null),
        this.r.expr(item).merge({created_at: this.r.now()}),
        doc.merge(item).merge({updated_at: this.r.now()})
      )
    }, {
      returnChanges: true
    }).run(this.conn);

  if (res.replaced) {
    return res.changes[0].new_val;
  } else {
    return item; // doc was never inserted as everything in `res` is `0`.
  }
</code>```

res.changes is undefined if the doc doesn't exist and if I search for the id after it is not in the database. It never got inserted.

Is there a way to simplify upsert() command given an arbitrary property of an object?

答:
In the "else" clause you should do the insert query and the branch clause in your code is useless (the query will never return "null" so the item will not be "created")

There are several ways to approach this:
The best approach is to use itemId (or r.uuid(itemId)) as the primary key and do an insert with a conflict clause.

If you can't
One approach is to try and replace and if it didn't replace anything insert:

```<code>this.r.table('products').filter({itemId: item.itemId})
.limit(1)
.replace(
    doc => doc.merge(item).merge({updated_at: this.r.now()}),
    { returnChanges: true }
)
.do(res => res('replaced').eq(1).branch(
    res,
    r.table('products').insert(
        { ...item, created_at: this.r.now()},
        { returnChanges: true }
    )
))
.run()
</code>```

Another approach is to try and see if exists and use the index to upsert:

```<code>this.r.table('products').filter({itemId: item.itemId})
.nth(0)
.default(null)
.do(res =>
    r.table('products').insert(
        {
          ...item,
          id: res('id').default(r.uuid()),
          created_at: this.r.now()
        },
        {
            returnChanges: true,
            conflict: (id, old, new) =>
                old.merge(item).merge({updated_at: this.r.now()})
        }
    )
))
.run()
</code>```

Also if you need it to perform I recommend creating a secondary index on itemId and use "getAll" instead of "filter".

These approaches won't help if you have a high probability of getting multiple items with the same itemId at the same time, to fix this you'll need to create a different unique table:

```<code>r.table('products_itemId')
 .insert(
    {itemId: item.itemId, id: r.uuid()},
    { returnChanges: true, conflict: (id, old, new) => old }
 )
 .do(res =>
     r.table('products').insert(
        {
          ...item,
          id: res('new_val')('id'),
          created_at: this.r.now()
        },
        {
            returnChanges: true,
            conflict: (id, old, new) =>
                old.merge(item).merge({updated_at: this.r.now()})
        }
    )
))
.run()
</code>```

Notice that you'll have to maintain deletions and updates to the itemId field manually

Body:
I have an .itemId which comes from a 3rd party, not generated by me.

I need to look for it in the db and update or insert it if one doesn't exist.

I've tried using this example from the cookbook: https://www.rethinkdb.com/docs/cookbook/javascript/#manipulating-documents

  const res = await this.r.table('products').filter({itemId: item.itemId})
    .limit(1)
    .replace(doc => {
      return this.r.branch(
        doc.eq(null),
        this.r.expr(item).merge({created_at: this.r.now()}),
        doc.merge(item).merge({updated_at: this.r.now()})
      )
    }, {
      returnChanges: true
    }).run(this.conn);

  if (res.replaced) {
    return res.changes[0].new_val;
  } else {
    return item; // doc was never inserted as everything in `res` is `0`.
  }

res.changes is undefined if the doc doesn't exist and if I search for the id after it is not in the database. It never got inserted.

Is there a way to simplify upsert() command given an arbitrary property of an object?

Body:
In the "else" clause you should do the insert query and the branch clause in your code is useless (the query will never return "null" so the item will not be "created")

There are several ways to approach this:
The best approach is to use itemId (or r.uuid(itemId)) as the primary key and do an insert with a conflict clause.

If you can't
One approach is to try and replace and if it didn't replace anything insert:

this.r.table('products').filter({itemId: item.itemId})
.limit(1)
.replace(
    doc => doc.merge(item).merge({updated_at: this.r.now()}),
    { returnChanges: true }
)
.do(res => res('replaced').eq(1).branch(
    res,
    r.table('products').insert(
        { ...item, created_at: this.r.now()},
        { returnChanges: true }
    )
))
.run()

Another approach is to try and see if exists and use the index to upsert:

this.r.table('products').filter({itemId: item.itemId})
.nth(0)
.default(null)
.do(res =>
    r.table('products').insert(
        {
          ...item,
          id: res('id').default(r.uuid()),
          created_at: this.r.now()
        },
        {
            returnChanges: true,
            conflict: (id, old, new) =>
                old.merge(item).merge({updated_at: this.r.now()})
        }
    )
))
.run()

Also if you need it to perform I recommend creating a secondary index on itemId and use "getAll" instead of "filter".

These approaches won't help if you have a high probability of getting multiple items with the same itemId at the same time, to fix this you'll need to create a different unique table:

r.table('products_itemId')
 .insert(
    {itemId: item.itemId, id: r.uuid()},
    { returnChanges: true, conflict: (id, old, new) => old }
 )
 .do(res =>
     r.table('products').insert(
        {
          ...item,
          id: res('new_val')('id'),
          created_at: this.r.now()
        },
        {
            returnChanges: true,
            conflict: (id, old, new) =>
                old.merge(item).merge({updated_at: this.r.now()})
        }
    )
))
.run()

Notice that you'll have to maintain deletions and updates to the itemId field manually


问:
How do I specify the initial zoom level in D3?
I have written a script to graphically display some row-oriented data, with bars, labels and connections between rows. As the dataset has grown, the resulting SVG element has exceeded the size of the screen. To keep the result on one screen (partly to make the d3 zoom behavior easier for the user to manage), I have scaled the SVG element before drawing so that it will fit the screen. I did this by appending a transform/scale attribute to the SVG element.

The problem is, d3's behavior.zoom does not know about this change in scale, so when I start to zoom, it first resets the scale to 1. Is there a way to change the initial scale in d3's behavior.zoom?

EDIT: added a work-around

Kludged this by multiplying d3.event.scale by the initial scale in the redraw() function. So, initial declaration of SVG element is

```<code>var SVG = d3.select('#timeline')
    .append('svg:svg')
        .attr('class','chart')
        .attr('transform','scale('+bscale+')')
        .attr('width', wwidth)
        .attr('height', wheight)
        .call(d3.behavior.zoom()
            .extent([[0,Infinity],[0,Infinity],[0,Infinity]])
            .on('zoom', redraw));
</code>```

and

```<code>function redraw() {
    SVG.attr("transform",
        "translate(" + d3.event.translate + ")"
        + "scale(" + d3.event.scale * bscale + ")");
};
</code>```

答:
In d3 v4, you can use:

svg.call(zoom.transform,
  d3.zoomIdentity.scale(X_SCALE,Y_SCALE));

Simple example:

```<code>var zoom = d3.zoom()
        .on("zoom", zoomed);

var zoomer = svg.append("rect")
        .call(zoom)
        .call(zoom.transform, d3.zoomIdentity.scale(2,2));

function zoomed() {
        svg.attr("transform", d3.event.transform);
    }
</code>```

Hope that helps.

Body:
I have written a script to graphically display some row-oriented data, with bars, labels and connections between rows. As the dataset has grown, the resulting SVG element has exceeded the size of the screen. To keep the result on one screen (partly to make the d3 zoom behavior easier for the user to manage), I have scaled the SVG element before drawing so that it will fit the screen. I did this by appending a transform/scale attribute to the SVG element.

The problem is, d3's behavior.zoom does not know about this change in scale, so when I start to zoom, it first resets the scale to 1. Is there a way to change the initial scale in d3's behavior.zoom?

EDIT: added a work-around

Kludged this by multiplying d3.event.scale by the initial scale in the redraw() function. So, initial declaration of SVG element is

var SVG = d3.select('#timeline')
    .append('svg:svg')
        .attr('class','chart')
        .attr('transform','scale('+bscale+')')
        .attr('width', wwidth)
        .attr('height', wheight)
        .call(d3.behavior.zoom()
            .extent([[0,Infinity],[0,Infinity],[0,Infinity]])
            .on('zoom', redraw));

and

function redraw() {
    SVG.attr("transform",
        "translate(" + d3.event.translate + ")"
        + "scale(" + d3.event.scale * bscale + ")");
};

Body:
In d3 v4, you can use:

svg.call(zoom.transform,
  d3.zoomIdentity.scale(X_SCALE,Y_SCALE));

Simple example:

var zoom = d3.zoom()
        .on("zoom", zoomed);

var zoomer = svg.append("rect")
        .call(zoom)
        .call(zoom.transform, d3.zoomIdentity.scale(2,2));

function zoomed() {
        svg.attr("transform", d3.event.transform);
    }

Hope that helps.


问:
How to use yaml template variable as a part of value in Concourse CI
When I try to use template variable, e.g. {{hostname}} as a part of value, it gets wrapped with double quotes.

How to add a variable w/o quotes?

Example:

```<code>---
resource_types:
  - name: maven
    type: docker-image
    source:
      repository: patrickcrocker/maven-resource
      tag: latest

resources:
  - name: maven-snapshot
    type: maven
    source:
      url: http://{{hostname}}:8081/repository/maven-snapshots/

  - name: repo
    type: git
    source:
      uri: "git@bitbucket.org:foo/bar.git"
      branch: master{{hostname}}
</code>```

And the result for the command fly -t ci set-pipeline --pipeline test --config test.yml --var="hostname=localhost" is as follows (look at "localhost"):

```<code>resources:
  resource maven-snapshot has been added:
    name: maven-snapshot
    type: maven
    source:
      url: http://"localhost":8081/repository/maven-snapshots/

  resource repo has been added:
    name: repo
    type: git
    source:
      branch: master"localhost"
      uri: git@bitbucket.org:foo/bar.git

resource types:
  resource type maven has been added:
    name: maven
    type: docker-image
    source:
      repository: patrickcrocker/maven-resource
      tag: latest
</code>```

The reason I've included a 3rd-party maven resource is that git resource does not allow {{}} in the uri, leading to the error:

```<code>failed to unmarshal configStructure: yaml: line 17: did not find expected key
</code>```

答:
UPDATE

As of concourse v3.2.0 {{someValue}} syntax is deprecated in favor of ((someValue)). New syntax will understand you are trying to interpolate the string and place the value accordingly.

Replacing {{hostname}} with ((hostname)) will solve your issue:

```<code>resources:
  - name: maven-snapshot
    type: maven
    source:
      url: http://((hostname)):8081/repository/maven-snapshots/
</code>```

Concourse does not support this.
The Concourse yaml templating is very primitive and you can not insert variables in the middle of strings.
You will need to set your url parameter as http://localhost:8081/repository/maven-snapshots/ and your branch parameter as localmaster or whatever it should be.

We know this is a problem and we are working on it, but for now you can not set variables in the way you want.

Body:
When I try to use template variable, e.g. {{hostname}} as a part of value, it gets wrapped with double quotes.

How to add a variable w/o quotes?

Example:

---
resource_types:
  - name: maven
    type: docker-image
    source:
      repository: patrickcrocker/maven-resource
      tag: latest

resources:
  - name: maven-snapshot
    type: maven
    source:
      url: http://{{hostname}}:8081/repository/maven-snapshots/

  - name: repo
    type: git
    source:
      uri: "git@bitbucket.org:foo/bar.git"
      branch: master{{hostname}}

And the result for the command fly -t ci set-pipeline --pipeline test --config test.yml --var="hostname=localhost" is as follows (look at "localhost"):

resources:
  resource maven-snapshot has been added:
    name: maven-snapshot
    type: maven
    source:
      url: http://"localhost":8081/repository/maven-snapshots/

  resource repo has been added:
    name: repo
    type: git
    source:
      branch: master"localhost"
      uri: git@bitbucket.org:foo/bar.git

resource types:
  resource type maven has been added:
    name: maven
    type: docker-image
    source:
      repository: patrickcrocker/maven-resource
      tag: latest

The reason I've included a 3rd-party maven resource is that git resource does not allow {{}} in the uri, leading to the error:

failed to unmarshal configStructure: yaml: line 17: did not find expected key

Body:
UPDATE

As of concourse v3.2.0 {{someValue}} syntax is deprecated in favor of ((someValue)). New syntax will understand you are trying to interpolate the string and place the value accordingly.

Replacing {{hostname}} with ((hostname)) will solve your issue:

resources:
  - name: maven-snapshot
    type: maven
    source:
      url: http://((hostname)):8081/repository/maven-snapshots/

Concourse does not support this.
The Concourse yaml templating is very primitive and you can not insert variables in the middle of strings.
You will need to set your url parameter as http://localhost:8081/repository/maven-snapshots/ and your branch parameter as localmaster or whatever it should be.

We know this is a problem and we are working on it, but for now you can not set variables in the way you want.


问:
Index2word in Gensim's Doc2vec raises an Attribute error
I trained a doc2vec (gensim.models.Doc2Vec) model and now I'm using this line:

```<code>print(dict([(model.index2word[i], similarity) for i, similarity in enumerate(model.similar_by_word('igdumd32.dll@0x', topn=False))])['igdumd64.dll@0x'])
</code>```

but it yields this error:
AttributeError: 'Doc2Vec' object has no attribute 'index2word'

I am using gensim 1.0.1

Can you help?

答:
The index2word list of word-vectors has moved to the wv property of the model in recent gensim versions, so where you would say model.index2word you must now use model.wv.index2word.

(Note that this is still just word-vectors, which are only trained by the "DM" dm=1 Doc2Vec modes. Doc-vectors are in the model.docvecs object, and you can see a list of the string tags to which doc-vectors may be associated in model.docvecs.offset2doctag.)

Body:
I trained a doc2vec (gensim.models.Doc2Vec) model and now I'm using this line:

print(dict([(model.index2word[i], similarity) for i, similarity in enumerate(model.similar_by_word('igdumd32.dll@0x', topn=False))])['igdumd64.dll@0x'])

but it yields this error:
AttributeError: 'Doc2Vec' object has no attribute 'index2word'

I am using gensim 1.0.1

Can you help?


问:
PHP: game loop (threads or the sort)
I am writing PHP code to be a game client. It uses socket; socket_create followed by socket_connect and then socket_read. It works fine, but the issue is that the server can send a packet at any time which means socket_read needs to be happening constantly in a "game loop". So something like this:

```<code><?php
$reply = "";
do {
     $recv = "";
     $recv = socket_read($socket, '1400');
     if($recv != "") {
         $reply .= $recv;
     }
} while($recv != "");

echo($reply);
?>
</code>```

Doesn't work because it's stuck in the loop (server doesn't terminate connection until game is quit by client) and the PHP code needs to handle the packet stuff as it comes in.

So PHP doesn't really have threading. What's the best way of handling this?

答:
All you have to do is to use socket_select() function:

http://php.net/manual/en/function.socket-select.php

It will put your script to sleep and wake it up when there is data on the socket to be read. It's waaay more efficient that periodical sleep/read, cron scripts and all other proposed solutions.

@aib made a valid point. The server might sent a complete "game message" divided into several packets. Dont expect to get all your data in a singe exceution of code block after socket_select() returns.

ContentLicense: CC BY-SA 2.5

Title: PHP: game loop (threads or the sort)

Body:
I am writing PHP code to be a game client. It uses socket; socket_create followed by socket_connect and then socket_read. It works fine, but the issue is that the server can send a packet at any time which means socket_read needs to be happening constantly in a "game loop". So something like this:

<?php
$reply = "";
do {
     $recv = "";
     $recv = socket_read($socket, '1400');
     if($recv != "") {
         $reply .= $recv;
     }
} while($recv != "");

echo($reply);
?>

Doesn't work because it's stuck in the loop (server doesn't terminate connection until game is quit by client) and the PHP code needs to handle the packet stuff as it comes in.

So PHP doesn't really have threading. What's the best way of handling this?


问:
Input validation in do-while
I'm having a problem with the input error.My input is validated but my error message "Invalid Range. Please Enter Range 0-100:" is not showing if there's invalid input.

Here's an example:

```<code>Please Enter Grade 1: 101 (It does not accept input)
Please Enter Grade 1: 321 (It does not accept input)
</code>```

Instead of showing:

```<code>Please Enter Grade 1: 101 (It does not accept input)

Invalid Rage. Please Enter Range 0-100.
Please Enter Grade 1:
</code>```

Here's My Code:

```<code>for(vector<double>::size_type i = 0; i < 15; i++)
  {
    do
    {
         cout << "Please Enter Grade "<< i + 1 <<": " << flush;
            cin >> gradesVector[i];
        }
        while(gradesVector[i] < 0.0 || gradesVector[i] > 100.0);
        {
            cout << "Invalid Rage. Please Enter Range 0-100:\n";
                cout << "Please Enter Grade "<< i + 1 <<": " << flush;
                    cin >> gradesVector[i];
         }
}
</code>```

答:
You are mixing a do construct with a while. Use either not both. Also your test in your while does not make sense. It can't be less and more at the same time. Edit to the following and it should work

```<code>for(vector<double>::size_type i = 0; i < 15; i++)
    {
        cout << "Please Enter Grade "<< i + 1 <<": " << flush;
        cin >> gradesVector[i];
        while(gradesVector[i] < 0.0 || gradesVector[i] > 100.0); // or not and
        {
            cout << "Invalid Rage. Please Enter Range 0-100:\n";
                cout << "Please Enter Grade "<< i + 1 <<": " << flush;
                    cin >> gradesVector[i];
        }
    }
</code>```

Title: Input validation in do-while

Body:
I'm having a problem with the input error.My input is validated but my error message "Invalid Range. Please Enter Range 0-100:" is not showing if there's invalid input.

Here's an example:

Please Enter Grade 1: 101 (It does not accept input)
Please Enter Grade 1: 321 (It does not accept input)

Instead of showing:

Please Enter Grade 1: 101 (It does not accept input)

Invalid Rage. Please Enter Range 0-100.
Please Enter Grade 1:

Here's My Code:

for(vector<double>::size_type i = 0; i < 15; i++)
  {
    do
    {
         cout << "Please Enter Grade "<< i + 1 <<": " << flush;
            cin >> gradesVector[i];
        }
        while(gradesVector[i] < 0.0 || gradesVector[i] > 100.0);
        {
            cout << "Invalid Rage. Please Enter Range 0-100:\n";
                cout << "Please Enter Grade "<< i + 1 <<": " << flush;
                    cin >> gradesVector[i];
         }
}

Body:
You are mixing a do construct with a while. Use either not both. Also your test in your while does not make sense. It can't be less and more at the same time. Edit to the following and it should work

for(vector<double>::size_type i = 0; i < 15; i++)
    {
        cout << "Please Enter Grade "<< i + 1 <<": " << flush;
        cin >> gradesVector[i];
        while(gradesVector[i] < 0.0 || gradesVector[i] > 100.0); // or not and
        {
            cout << "Invalid Rage. Please Enter Range 0-100:\n";
                cout << "Please Enter Grade "<< i + 1 <<": " << flush;
                    cin >> gradesVector[i];
        }
    }


答:
Your while condition is not right.

```<code>std::vector<double> gradesVector;
gradesVector.reserve(15);
for (std::vector<double>::size_type i = 0; i < 15; i++)
{
    double grade;
    std::cout << "Please Enter Grade " << i + 1 << ": " << std::flush;
    std::cin >> grade;
    while (grade < 0.0 || grade > 100.0)
    {
        std::cout << "Invalid Range. Please Enter Range 0-100:\n";
        std::cin >> grade;
    }
    gradesVector.push_back(grade);
}
</code>```

Also I would only add the grade to the vector once it is valid.

Title: Input validation in do-while

Body:
Your while condition is not right.

std::vector<double> gradesVector;
gradesVector.reserve(15);
for (std::vector<double>::size_type i = 0; i < 15; i++)
{
    double grade;
    std::cout << "Please Enter Grade " << i + 1 << ": " << std::flush;
    std::cin >> grade;
    while (grade < 0.0 || grade > 100.0)
    {
        std::cout << "Invalid Range. Please Enter Range 0-100:\n";
        std::cin >> grade;
    }
    gradesVector.push_back(grade);
}

Also I would only add the grade to the vector once it is valid.


问:
urlManager for module Yii2
I've got a basic Yii2 project, in which i created a separate module "rest". I have set up urlManager in config/web.php file. It works fine for common url, but it seems to me it is not working with url starting with my module name: rest/.. I have actionAuth() in AuthController in my rest module, and it is accessible  with this url: test.ru/auth/auth. But i want it to be accessible with this url:test.ru/auth. I tried to write like this in web.php :

```<code>  'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [

           [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\auth',
              'extraPatterns' => [
                  'POST /' => 'auth',
              ],
              'pluralize' => false,
            ],

      ],
    ],
</code>```

But it does not work(not found error in browser).
I also tried like this:

```<code>'rules' => [

           [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\auth',
              'extraPatterns' => [
                  'POST rest/auth' => 'auth',
              ],
              'pluralize' => false,
            ],

      ],
    ],
</code>```

It seems to me that urlManager does not want to work for module. Next i tried to write the same code in my Module.php in rest/ directory. But it produced many errors. I think because of the same error things like that dont work too:`

```<code>    'class' => 'yii\rest\UrlRule',
                      'controller' => 'rest\city',
                      'extraPatterns' => [
                        'DELETE {id}' => 'delete',
                      ],
    `
</code>```

So my question is: how to set up urlManager for module in Yii2? I need to configure HTTP DELETE method, post methods work without any settings in urlManager.

The whole web.php file:

```<code><?php

 $params = require(__DIR__ . '/params.php');

  $config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'language' => 'ru',
'components' => [
'authManager' => [
        'class' => 'yii\rbac\DbManager',
    ],
    'request' => [
        // !!! insert a secret key in the following (if it is empty) - this              is required by cookie validation
        'cookieValidationKey' => 'xxxxxxx',
        'parsers' => [
            'application/json' => 'yii\web\JsonParser',
            ]
    ],
    'cache' => [
        'class' => 'yii\caching\FileCache',
    ],
     'user' => [
        'identityClass' => 'app\models\User',
    //    'loginUrl' => ['site/login'],

    ],
    'errorHandler' => [
        'errorAction' => 'site/error',
    ],
    'mailer' => [
        'class' => 'yii\swiftmailer\Mailer',
        // send all mails to a file by default. You have to set
        // 'useFileTransport' to false and configure a transport
        // for the mailer to send real emails.
        'useFileTransport' => true,
    ],
    'log' => [
        'traceLevel' => YII_DEBUG ? 3 : 0,
        'targets' => [
            [
                'class' => 'yii\log\FileTarget',
                'levels' => ['error', 'warning'],
            ],
        ],
    ],
    'db' => require(__DIR__ . '/db.php'),

    'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\user',
              'except' => ['delete', 'create', 'update', 'index'],
              'extraPatterns' => [
                  'GET all' => 'all',
              ]
           ],
           [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\auth',
              'extraPatterns' => [
                  'POST reg' => 'reg',
                  'POST auth' => 'auth',
                  'POST rest/auth' => 'auth',
              ],
              'pluralize' => false,
            ],
            [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\city',
              'extraPatterns' => [
                'DELETE {id}' => 'delete',
              ],

            ],

      ],
    ],

        'i18n' => [
    'translations' => [
        '*' => [
            'class' => 'yii\i18n\PhpMessageSource',
           // 'basePath' => '@app/messages', // if advanced application, set @frontend/messages
            'sourceLanguage' => 'en',
            'fileMap' => [
                //'main' => 'main.php',
            ],
        ],
    ],
],

],
'modules' => [
    'admin' => [
        'class' => 'app\modules\admin\Module',
    ],
    'manager' => [
        'class' => 'app\modules\manager\Module',
    ],
    'rest' => [
        'class' => 'app\modules\rest\Module',
    ],

    'rbac' => [
       'class' => 'mdm\admin\Module',
       'controllerMap' => [
             'assignment' => [
                'class' => 'mdm\admin\controllers\AssignmentController',
                /* 'userClassName' => 'app\models\User', */
                'idField' => 'id',
                'usernameField' => 'username',
            ],
        ],
    'layout' => 'left-menu',
    'mainLayout' => '@app/views/layouts/admin.php',
    ]

],

'aliases' => [
    //'@mdm/admin' => 'app/mdm/admin',
],

'params' => $params,
 ];

if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
    'class' => 'yii\debug\Module',
    // uncomment the following to add your IP if you are not connecting from    localhost.
    //'allowedIPs' => ['127.0.0.1', '::1'],
 ];

$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
    'class' => 'yii\gii\Module',
    // uncomment the following to add your IP if you are not connecting from localhost.
    //'allowedIPs' => ['127.0.0.1', '::1'],
 ];
}

   return $config;
</code>```

My Module.php code(commented code shows my attempt to write urlManager):

```<code>    <?php

     namespace app\modules\rest;

     /**
     * rest module definition class
     */
     class Module extends \yii\base\Module
     {
    /**
     * @inheritdoc
     */
    public $controllerNamespace = 'app\modules\rest\controllers';

    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
    // custom initialization code goes here
     \Yii::$app->user->enableSession = false;
      $config = [

      'components' => [
        'basePath' => dirname(__DIR__),
        // 'user' => [
        //           'identityClass' => 'app\models\User',
        //           'class' => 'app\models\User',
        //           'enableSession' => false
        //       ],

        //   'urlManager' => [
        //               'enablePrettyUrl' => true,
        //               'enableStrictParsing' => true,
        //               'showScriptName' => false,
        //               'rules' => [
        //                    [
        //                     'class' => 'yii\rest\UrlRule',
        //                     'controller' => 'rest\city',
        //                     'extraPatterns' => [
        //                     'DELETE {id}' => 'delete',
        //                 ],
        //               ],
        // ],
        //   ],

        'response' => [
                  'format' => \yii\web\Response::FORMAT_JSON,
                  'charset' => 'UTF-8',
                  'class' => 'yii\web\Response',

                  'on beforeSend' => function ($event) {

                      $response = $event->sender;

                      if(( $response->statusCode >= 200) && ( $response->statusCode < 300)) {

                          if(isset($response->data['_appErr'])) {
                              unset($response->data['_appErr']);
                              $response->data = [
                                  'success' => false,
                                  'error' => $response->data,
                                  'data' => null,
                              ];
                          } else {

                              $response->data = [
                                  'success' => $response->isSuccessful,
                                  'error' => null,
                                  'data' => $response->data,
                              ];
                          }

                      } else {

                          if($response->statusCode == 401) {
                              $response->data = [
                                  'success' => false,
                                  'error' => [
                                      'code' => 9,
                                      'message' => 'Unauthorized',
                                      'user_msg' => 'You need to be authorized',
                                  ],
                                  'data' => null,
                              ];
                          }
                        //   else {
                        //       $response->data = [
                        //           'success' => false,
                        //           'error' => [
                        //               'code' => 1,
                        //               'message' => 'server has returned   '.$response->statusCode.' error',
                        //           ],
                        //           'data' => null,
                        //       ];
                        //   }
                      }
                  },
              ],

      ],
      ];

        \Yii::configure(\Yii::$app, $config);
      }
     }
</code>```

答:
Try this:</p>

```<code>namespace yii\rest;

class UrlRule extends Object implements UrlRuleInterface {

    public function parseRequest($manager, $request) {
        list($e1, $e2) = sscanf($request->getPathInfo(), '%[a-zA-Z]/%[a-zA-Z]');
        if ($e1 === 'auth' && $e2 === '') {
            return ['/auth/auth', $request->queryParams];
        }
        return false;
    }
}
</code>```

Title: urlManager for module Yii2

Body:
I've got a basic Yii2 project, in which i created a separate module "rest". I have set up urlManager in config/web.php file. It works fine for common url, but it seems to me it is not working with url starting with my module name: rest/.. I have actionAuth() in AuthController in my rest module, and it is accessible  with this url: test.ru/auth/auth. But i want it to be accessible with this url:test.ru/auth. I tried to write like this in web.php :

  'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [

           [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\auth',
              'extraPatterns' => [
                  'POST /' => 'auth',
              ],
              'pluralize' => false,
            ],

      ],
    ],

But it does not work(not found error in browser).
I also tried like this:

'rules' => [

           [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\auth',
              'extraPatterns' => [
                  'POST rest/auth' => 'auth',
              ],
              'pluralize' => false,
            ],

      ],
    ],

It seems to me that urlManager does not want to work for module. Next i tried to write the same code in my Module.php in rest/ directory. But it produced many errors. I think because of the same error things like that dont work too:`

    'class' => 'yii\rest\UrlRule',
                      'controller' => 'rest\city',
                      'extraPatterns' => [
                        'DELETE {id}' => 'delete',
                      ],
    `

So my question is: how to set up urlManager for module in Yii2? I need to configure HTTP DELETE method, post methods work without any settings in urlManager.

The whole web.php file:

<?php

 $params = require(__DIR__ . '/params.php');

  $config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'language' => 'ru',
'components' => [
'authManager' => [
        'class' => 'yii\rbac\DbManager',
    ],
    'request' => [
        // !!! insert a secret key in the following (if it is empty) - this              is required by cookie validation
        'cookieValidationKey' => 'xxxxxxx',
        'parsers' => [
            'application/json' => 'yii\web\JsonParser',
            ]
    ],
    'cache' => [
        'class' => 'yii\caching\FileCache',
    ],
     'user' => [
        'identityClass' => 'app\models\User',
    //    'loginUrl' => ['site/login'],

    ],
    'errorHandler' => [
        'errorAction' => 'site/error',
    ],
    'mailer' => [
        'class' => 'yii\swiftmailer\Mailer',
        // send all mails to a file by default. You have to set
        // 'useFileTransport' to false and configure a transport
        // for the mailer to send real emails.
        'useFileTransport' => true,
    ],
    'log' => [
        'traceLevel' => YII_DEBUG ? 3 : 0,
        'targets' => [
            [
                'class' => 'yii\log\FileTarget',
                'levels' => ['error', 'warning'],
            ],
        ],
    ],
    'db' => require(__DIR__ . '/db.php'),

    'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\user',
              'except' => ['delete', 'create', 'update', 'index'],
              'extraPatterns' => [
                  'GET all' => 'all',
              ]
           ],
           [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\auth',
              'extraPatterns' => [
                  'POST reg' => 'reg',
                  'POST auth' => 'auth',
                  'POST rest/auth' => 'auth',
              ],
              'pluralize' => false,
            ],
            [
              'class' => 'yii\rest\UrlRule',
              'controller' => 'rest\city',
              'extraPatterns' => [
                'DELETE {id}' => 'delete',
              ],

            ],

      ],
    ],

        'i18n' => [
    'translations' => [
        '*' => [
            'class' => 'yii\i18n\PhpMessageSource',
           // 'basePath' => '@app/messages', // if advanced application, set @frontend/messages
            'sourceLanguage' => 'en',
            'fileMap' => [
                //'main' => 'main.php',
            ],
        ],
    ],
],

],
'modules' => [
    'admin' => [
        'class' => 'app\modules\admin\Module',
    ],
    'manager' => [
        'class' => 'app\modules\manager\Module',
    ],
    'rest' => [
        'class' => 'app\modules\rest\Module',
    ],

    'rbac' => [
       'class' => 'mdm\admin\Module',
       'controllerMap' => [
             'assignment' => [
                'class' => 'mdm\admin\controllers\AssignmentController',
                /* 'userClassName' => 'app\models\User', */
                'idField' => 'id',
                'usernameField' => 'username',
            ],
        ],
    'layout' => 'left-menu',
    'mainLayout' => '@app/views/layouts/admin.php',
    ]

],

'aliases' => [
    //'@mdm/admin' => 'app/mdm/admin',
],

'params' => $params,
 ];

if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
    'class' => 'yii\debug\Module',
    // uncomment the following to add your IP if you are not connecting from    localhost.
    //'allowedIPs' => ['127.0.0.1', '::1'],
 ];

$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
    'class' => 'yii\gii\Module',
    // uncomment the following to add your IP if you are not connecting from localhost.
    //'allowedIPs' => ['127.0.0.1', '::1'],
 ];
}

   return $config;

My Module.php code(commented code shows my attempt to write urlManager):

    <?php

     namespace app\modules\rest;

     /**
     * rest module definition class
     */
     class Module extends \yii\base\Module
     {
    /**
     * @inheritdoc
     */
    public $controllerNamespace = 'app\modules\rest\controllers';

    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
    // custom initialization code goes here
     \Yii::$app->user->enableSession = false;
      $config = [

      'components' => [
        'basePath' => dirname(__DIR__),
        // 'user' => [
        //           'identityClass' => 'app\models\User',
        //           'class' => 'app\models\User',
        //           'enableSession' => false
        //       ],

        //   'urlManager' => [
        //               'enablePrettyUrl' => true,
        //               'enableStrictParsing' => true,
        //               'showScriptName' => false,
        //               'rules' => [
        //                    [
        //                     'class' => 'yii\rest\UrlRule',
        //                     'controller' => 'rest\city',
        //                     'extraPatterns' => [
        //                     'DELETE {id}' => 'delete',
        //                 ],
        //               ],
        // ],
        //   ],

        'response' => [
                  'format' => \yii\web\Response::FORMAT_JSON,
                  'charset' => 'UTF-8',
                  'class' => 'yii\web\Response',

                  'on beforeSend' => function ($event) {

                      $response = $event->sender;

                      if(( $response->statusCode >= 200) && ( $response->statusCode < 300)) {

                          if(isset($response->data['_appErr'])) {
                              unset($response->data['_appErr']);
                              $response->data = [
                                  'success' => false,
                                  'error' => $response->data,
                                  'data' => null,
                              ];
                          } else {

                              $response->data = [
                                  'success' => $response->isSuccessful,
                                  'error' => null,
                                  'data' => $response->data,
                              ];
                          }

                      } else {

                          if($response->statusCode == 401) {
                              $response->data = [
                                  'success' => false,
                                  'error' => [
                                      'code' => 9,
                                      'message' => 'Unauthorized',
                                      'user_msg' => 'You need to be authorized',
                                  ],
                                  'data' => null,
                              ];
                          }
                        //   else {
                        //       $response->data = [
                        //           'success' => false,
                        //           'error' => [
                        //               'code' => 1,
                        //               'message' => 'server has returned   '.$response->statusCode.' error',
                        //           ],
                        //           'data' => null,
                        //       ];
                        //   }
                      }
                  },
              ],

      ],
      ];

        \Yii::configure(\Yii::$app, $config);
      }
     }

Body:
Try this:

namespace yii\rest;

class UrlRule extends Object implements UrlRuleInterface {

    public function parseRequest($manager, $request) {
        list($e1, $e2) = sscanf($request->getPathInfo(), '%[a-zA-Z]/%[a-zA-Z]');
        if ($e1 === 'auth' && $e2 === '') {
            return ['/auth/auth', $request->queryParams];
        }
        return false;
    }
}


问:
Mutiple shortest match in HTMLwith regular expression using Python
I am trying to get the content of 4 table of this HTML code http://catedral.prefeitura.unicamp.br/cardapio.php using the regular expressions in Python.
The tables starts with
"[\t\n\s]"
and finish with
"
[\t\n\s]	"
I am using the code follow:

```<code>menuSearchString = '<td align="left" valign="top">[\t\n\s]*<table width="[\d%]+" class="fundo_cardapio">([\s\S\d\t\n]+)<\/table>[\t\n\s]*<\/td>'
menus = re.findall(menuSearchString,page)
print menus
</code>```

But I couldn't get the four matches of the tables. I think I am mistaking the greedy configuration and the "?" operator, I tried at the end but didn't work.

答:
You are right. Part of your regex is being greedy which cause your regex to catch all the four tables in one match. All you have to do is to make this part lazy in order to get four matches.

Change this part of your regex:

```<code>[\s\S\d\t\n]+
</code>```

To:

```<code>[\s\S\d\t\n]+?
</code>```

Complete Code:

```<code>menuSearchString = '<td align="left" valign="top">[\t\n\s]*<table width="[\d%]+" class="fundo_cardapio">([\s\S\d\t\n]+?)<\/table>[\t\n\s]*<\/td>'
menus = re.findall(menuSearchString,page)
print menus
</code>```

Body:
I am trying to get the content of 4 table of this HTML code http://catedral.prefeitura.unicamp.br/cardapio.php using the regular expressions in Python.
The tables starts with
"[\t\n\s]"
and finish with
"
[\t\n\s]	"
I am using the code follow:

menuSearchString = '[\t\n\s]*
([\s\S\d\t\n]+)<\/table>[\t\n\s]*<\/td>'
menus = re.findall(menuSearchString,page)
print menus

But I couldn't get the four matches of the tables. I think I am mistaking the greedy configuration and the "?" operator, I tried at the end but didn't work.

Body:
You are right. Part of your regex is being greedy which cause your regex to catch all the four tables in one match. All you have to do is to make this part lazy in order to get four matches.

Change this part of your regex:

[\s\S\d\t\n]+

To:

[\s\S\d\t\n]+?

Complete Code:

menuSearchString = '<td align="left" valign="top">[\t\n\s]*<table width="[\d%]+" class="fundo_cardapio">([\s\S\d\t\n]+?)<\/table>[\t\n\s]*<\/td>'
menus = re.findall(menuSearchString,page)
print menus