问:
PHP - Is it possible to add a string to a variable?
I would like to make a small change in a code for a table of contents.

I want to add a sign in front of each heading. The character should be recognized as text.

I've tried a few things, but unfortunately I have not found the right variable.

The code comes from a plugin for Wordpress

I have already tried the following variables:

```<code>$items
$tic
$find
$replace
$post
</code>```

Here is the code that prints the list:

```<code>if ( $tic->is_eligible($custom_toc_position) ) {

                extract( $args );

                $items = $tic->extract_headings( $find, $replace,wptexturize($post->post_content) );
                $title = ( array_key_exists('title', $instance) ) ? apply_filters('widget_title', $instance['title']) : '';
                if ( strpos($title, '%PAGE_TITLE%') !== false ) $title = str_replace( '%PAGE_TITLE%', get_the_title(), $title );
                if ( strpos($title, '%PAGE_NAME%') !== false ) $title = str_replace( '%PAGE_NAME%', get_the_title(), $title );
                $hide_inline = $toc_options['show_toc_in_widget_only'];

                $css_classes = '';
                // bullets?
                if ( $toc_options['bullet_spacing'] )
                    $css_classes .= ' have_bullets';
                else
                    $css_classes .= ' no_bullets';

                if ( $items ) {
                    // before widget (defined by themes)
                    echo $before_widget;

                    // display the widget title if one was input (before and after titles defined by themes)
                    if ( $title ) echo $before_title . $title . $after_title;

                    // display the list
                    echo '<ul class="toc_widget_list' . $css_classes . '">' . $items . '</ul>';

                    // after widget (defined by themes)
                    echo $after_widget;
                }
</code>```

This are the full code of function extract_headings:

```<code>public function extract_headings( &$find, &$replace, $content = '' )
        {
            $matches = array();
            $anchor = '';
            $items = false;

            // reset the internal collision collection as the_content may have been triggered elsewhere
            // eg by themes or other plugins that need to read in content such as metadata fields in
            // the head html tag, or to provide descriptions to twitter/facebook
            $this->collision_collector = array();

            if ( is_array($find) && is_array($replace) && $content ) {
                // get all headings
                // the html spec allows for a maximum of 6 heading depths
                if ( preg_match_all('/(<h([1-6]{1})[^>]*>).*<\/h\2>/msuU', $content, $matches, PREG_SET_ORDER) ) {

                    // remove undesired headings (if any) as defined by heading_levels
                    if ( count($this->options['heading_levels']) != 6 ) {
                        $new_matches = array();
                        for ($i = 0; $i < count($matches); $i++) {
                            if ( in_array($matches[$i][2], $this->options['heading_levels']) )
                                $new_matches[] = $matches[$i];
                        }
                        $matches = $new_matches;
                    }

                    // remove specific headings if provided via the 'exclude' property
                    if ( $this->options['exclude'] ) {
                        $excluded_headings = explode('|', $this->options['exclude']);
                        if ( count($excluded_headings) > 0 ) {
                            for ($j = 0; $j < count($excluded_headings); $j++) {
                                // escape some regular expression characters
                                // others: http://www.php.net/manual/en/regexp.reference.meta.php
                                $excluded_headings[$j] = str_replace(
                                    array('*'),
                                    array('.*'),
                                    trim($excluded_headings[$j])
                                );
                            }

                            $new_matches = array();
                            for ($i = 0; $i < count($matches); $i++) {
                                $found = false;
                                for ($j = 0; $j < count($excluded_headings); $j++) {
                                    if ( @preg_match('/^' . $excluded_headings[$j] . '$/imU', strip_tags($matches[$i][0])) ) {
                                        $found = true;
                                        break;
                                    }
                                }
                                if (!$found) $new_matches[] = $matches[$i];
                            }
                            if ( count($matches) != count($new_matches) )
                                $matches = $new_matches;
                        }
                    }

                    // remove empty headings
                    $new_matches = array();
                    for ($i = 0; $i < count($matches); $i++) {
                        if ( trim( strip_tags($matches[$i][0]) ) != false )
                            $new_matches[] = $matches[$i];
                    }
                    if ( count($matches) != count($new_matches) )
                        $matches = $new_matches;

                    // check minimum number of headings
                    if ( count($matches) >= $this->options['start'] ) {

                        for ($i = 0; $i < count($matches); $i++) {
                            // get anchor and add to find and replace arrays
                            $anchor = $this->url_anchor_target( $matches[$i][0] );
                            $find[] = $matches[$i][0];
                            $replace[] = str_replace(
                                array(
                                    $matches[$i][1],    // start of heading
                                    '</h' . $matches[$i][2] . '>'   // end of heading
                                ),
                                array(
                                    $matches[$i][1] . '<span id="' . $anchor . '">',
                                    '</span></h' . $matches[$i][2] . '>'
                                ),
                                $matches[$i][0]
                            );

                            // assemble flat list
                            if ( !$this->options['show_heirarchy'] ) {
                                $items .= '<li><a href="#' . $anchor . '">';
                                if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
                                $items .= strip_tags($matches[$i][0]) . '</a></li>';
                            }
                        }

                        // build a hierarchical toc?
                        // we could have tested for $items but that var can be quite large in some cases
                        if ( $this->options['show_heirarchy'] ) $items = $this->build_hierarchy( $matches );

                    }
                }
            }

            return $items;
        }
</code>```

I tried it like this:

```<code>$items = '>'.$items
$tic = '>'.$tic
$find = '>'.$find
.
.
.
</code>```

Unfortunately, nothing has hit the right place
$ items addressed only the entire list
The other Variables had no effect or led to errors

答:
The extract_headings is creating the list items. This section of the function...

```<code>// assemble flat list
if ( !$this->options['show_heirarchy'] ) {
    $items .= '<li><a href="#' . $anchor . '">';
    if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
    $items .= strip_tags($matches[$i][0]) . '</a></li>';
}
</code>```

Should look like this:

```<code>// assemble flat list
if ( !$this->options['show_heirarchy'] ) {
    $items .= '<li><a href="#' . $anchor . '">>';
    if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
    $items .= strip_tags($matches[$i][0]) . '</a></li>';
}
</code>```

You can see I've added an extra > inside the hyperlink on the third line. If adding an extra > causes any issues, you can also use >.

Body:
I would like to make a small change in a code for a table of contents.

I want to add a sign in front of each heading. The character should be recognized as text.

I've tried a few things, but unfortunately I have not found the right variable.

The code comes from a plugin for Wordpress

I have already tried the following variables:

$items
$tic
$find
$replace
$post

Here is the code that prints the list:

if ( $tic->is_eligible($custom_toc_position) ) {

                extract( $args );

                $items = $tic->extract_headings( $find, $replace,wptexturize($post->post_content) );
                $title = ( array_key_exists('title', $instance) ) ? apply_filters('widget_title', $instance['title']) : '';
                if ( strpos($title, '%PAGE_TITLE%') !== false ) $title = str_replace( '%PAGE_TITLE%', get_the_title(), $title );
                if ( strpos($title, '%PAGE_NAME%') !== false ) $title = str_replace( '%PAGE_NAME%', get_the_title(), $title );
                $hide_inline = $toc_options['show_toc_in_widget_only'];

                $css_classes = '';
                // bullets?
                if ( $toc_options['bullet_spacing'] )
                    $css_classes .= ' have_bullets';
                else
                    $css_classes .= ' no_bullets';

                if ( $items ) {
                    // before widget (defined by themes)
                    echo $before_widget;

                    // display the widget title if one was input (before and after titles defined by themes)
                    if ( $title ) echo $before_title . $title . $after_title;

                    // display the list
                    echo '
' . $items . '
';

                    // after widget (defined by themes)
                    echo $after_widget;
                }

This are the full code of function extract_headings:

public function extract_headings( &$find, &$replace, $content = '' )
        {
            $matches = array();
            $anchor = '';
            $items = false;

            // reset the internal collision collection as the_content may have been triggered elsewhere
            // eg by themes or other plugins that need to read in content such as metadata fields in
            // the head html tag, or to provide descriptions to twitter/facebook
            $this->collision_collector = array();

            if ( is_array($find) && is_array($replace) && $content ) {
                // get all headings
                // the html spec allows for a maximum of 6 heading depths
                if ( preg_match_all('/(<h([1-6]{1})[^>]*>).*<\/h\2>/msuU', $content, $matches, PREG_SET_ORDER) ) {

                    // remove undesired headings (if any) as defined by heading_levels
                    if ( count($this->options['heading_levels']) != 6 ) {
                        $new_matches = array();
                        for ($i = 0; $i < count($matches); $i++) {
                            if ( in_array($matches[$i][2], $this->options['heading_levels']) )
                                $new_matches[] = $matches[$i];
                        }
                        $matches = $new_matches;
                    }

                    // remove specific headings if provided via the 'exclude' property
                    if ( $this->options['exclude'] ) {
                        $excluded_headings = explode('|', $this->options['exclude']);
                        if ( count($excluded_headings) > 0 ) {
                            for ($j = 0; $j < count($excluded_headings); $j++) {
                                // escape some regular expression characters
                                // others: http://www.php.net/manual/en/regexp.reference.meta.php
                                $excluded_headings[$j] = str_replace(
                                    array('*'),
                                    array('.*'),
                                    trim($excluded_headings[$j])
                                );
                            }

                            $new_matches = array();
                            for ($i = 0; $i < count($matches); $i++) {
                                $found = false;
                                for ($j = 0; $j < count($excluded_headings); $j++) {
                                    if ( @preg_match('/^' . $excluded_headings[$j] . '$/imU', strip_tags($matches[$i][0])) ) {
                                        $found = true;
                                        break;
                                    }
                                }
                                if (!$found) $new_matches[] = $matches[$i];
                            }
                            if ( count($matches) != count($new_matches) )
                                $matches = $new_matches;
                        }
                    }

                    // remove empty headings
                    $new_matches = array();
                    for ($i = 0; $i < count($matches); $i++) {
                        if ( trim( strip_tags($matches[$i][0]) ) != false )
                            $new_matches[] = $matches[$i];
                    }
                    if ( count($matches) != count($new_matches) )
                        $matches = $new_matches;

                    // check minimum number of headings
                    if ( count($matches) >= $this->options['start'] ) {

                        for ($i = 0; $i < count($matches); $i++) {
                            // get anchor and add to find and replace arrays
                            $anchor = $this->url_anchor_target( $matches[$i][0] );
                            $find[] = $matches[$i][0];
                            $replace[] = str_replace(
                                array(
                                    $matches[$i][1],    // start of heading
                                    '</h' . $matches[$i][2] . '>'   // end of heading
                                ),
                                array(
                                    $matches[$i][1] . '',
                                    '</h' . $matches[$i][2] . '>'
                                ),
                                $matches[$i][0]
                            );

                            // assemble flat list
                            if ( !$this->options['show_heirarchy'] ) {
                                $items .= '
';
                                if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
                                $items .= strip_tags($matches[$i][0]) . '
';
                            }
                        }

                        // build a hierarchical toc?
                        // we could have tested for $items but that var can be quite large in some cases
                        if ( $this->options['show_heirarchy'] ) $items = $this->build_hierarchy( $matches );

                    }
                }
            }

            return $items;
        }

I tried it like this:

$items = '>'.$items
$tic = '>'.$tic
$find = '>'.$find
.
.
.

Unfortunately, nothing has hit the right place
$ items addressed only the entire list
The other Variables had no effect or led to errors

Body:
The extract_headings is creating the list items. This section of the function...

// assemble flat list
if ( !$this->options['show_heirarchy'] ) {
    $items .= '<li><a href="#' . $anchor . '">';
    if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
    $items .= strip_tags($matches[$i][0]) . '</a></li>';
}

Should look like this:

// assemble flat list
if ( !$this->options['show_heirarchy'] ) {
    $items .= '<li><a href="#' . $anchor . '">>';
    if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
    $items .= strip_tags($matches[$i][0]) . '</a></li>';
}

You can see I've added an extra > inside the hyperlink on the third line. If adding an extra > causes any issues, you can also use &gt;.


来源: stackexchange

问:
Elegant and maintainable way of populating Tree structures in c#
I have a Tree.

```<code>class TreeNode {
    public TreeNode(string name, string description) {
        Name = name;
        Description = description;
    }
    string Name { get; set; }
    string Description { get; set; }
    public List<TreeNode> Children = new List<TreeNode>();
}
</code>```

I would like to populate a large one for unit testing purposes. I would really like to keep stuff DRY.

Say for illustration purposes my tree has the following structure

```
Parent,desc
  Child 1, desc1
    Grandchild 1, desc1
  Child 2, desc2
```

How would you go about populating the tree in an elegant an maintainable way?

I find this code quite repetitious and error prone:

```<code>var parent = new TreeNode("Parent", "desc");
var child1 = new TreeNode("Child 1", "desc1");
var child2 = new TreeNode("Child 2", "desc2");
var grandchild1 = new TreeNode("Grandchild 1", "desc1");

parent.Children.Add(child1);
parent.Children.Add(child2);

child1.Children.Add(grandchild1);
</code>```

EDIT

I ended up doing the DSL approach:

A demo test lives here.

The implementation is here.

It uses a builder and a simple DSL.

答:
I would split the implementation into a TreeClass and a TreeNodeClass

The Tree Class would have member variables

```<code>TreeNodeClass root
</code>```

with methods

```<code>TreeNodeClass addAtRoot(data)
</code>```

Which return the node they just created

The TreeNodeClass Also needs an AddChild() Method, which would also return the node it just added.

Then you can do something like

```<code>addAtRoot(rootData).AddChild(childData).AddChild(grandchildData);
</code>```

or

Use something like this to randomly generate a tree

```<code>AddRecursively(TreeNodeClass root)
{
    numChildren = SomeRandomNumber;
    While(numChildren > 0)
    {
       CTreeNodeClass newnode = root.AddChild(SomeRandomData);
       AddRecursively(newnode);
    }
}
</code>```

The main idea is that you want to return the Node that you just added to the tree.

You might also want to make the child know its parent as that can be quite handy sometimes.

ContentLicense: CC BY-SA 3.0

Body:
I have a Tree.

class TreeNode {
    public TreeNode(string name, string description) {
        Name = name;
        Description = description;
    }
    string Name { get; set; }
    string Description { get; set; }
    public List<TreeNode> Children = new List<TreeNode>();
}

I would like to populate a large one for unit testing purposes. I would really like to keep stuff DRY.

Say for illustration purposes my tree has the following structure

Parent,desc
  Child 1, desc1
    Grandchild 1, desc1
  Child 2, desc2

How would you go about populating the tree in an elegant an maintainable way?

I find this code quite repetitious and error prone:

var parent = new TreeNode("Parent", "desc");
var child1 = new TreeNode("Child 1", "desc1");
var child2 = new TreeNode("Child 2", "desc2");
var grandchild1 = new TreeNode("Grandchild 1", "desc1");

parent.Children.Add(child1);
parent.Children.Add(child2);

child1.Children.Add(grandchild1);

EDIT

I ended up doing the DSL approach:

A demo test lives here.

The implementation is here.

It uses a builder and a simple DSL.

Body:
I would split the implementation into a TreeClass and a TreeNodeClass

The Tree Class would have member variables

TreeNodeClass root

with methods

TreeNodeClass addAtRoot(data)

Which return the node they just created

The TreeNodeClass Also needs an AddChild() Method, which would also return the node it just added.

Then you can do something like

addAtRoot(rootData).AddChild(childData).AddChild(grandchildData);

or

Use something like this to randomly generate a tree

AddRecursively(TreeNodeClass root)
{
    numChildren = SomeRandomNumber;
    While(numChildren > 0)
    {
       CTreeNodeClass newnode = root.AddChild(SomeRandomData);
       AddRecursively(newnode);
    }
}

The main idea is that you want to return the Node that you just added to the tree.

You might also want to make the child know its parent as that can be quite handy sometimes.

OwnerDisplayName: JSmyth

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: JSmyth


问:
how to avoid memory wastage when storing UTF-8 characters (8 bit) in Java character (16 bit). two in one?
I'm afraid I have a question on a detail of a rather oversaturated topic, I searched aroudn a lot, but couldn't find a clear answer to that specific obvious -imho- important, problem:

When converting byte[] to String using UTF-8, each byte (8bit) becomes a 8 bit character encoded by UTF-8, but each UTF-8 character is saved as a 16 bit character in java. Is that correct?
If yes, this means, that each stupid java character only uses the first 8 bits, and consumes double the memory? Is that correct too? I wonder how this wasteful behaviour is acceptable..

Isn't there some trick to have a pseudo String that is 8 bit?  Would that actually result in less memory consumption?
Or maybe, is there a way to store >two< 8bit characters in one java 16bit character to avoid this memory waste?

thanks for any deconfusing answers...

EDIT:
hi, thanks everybody for answering. I was aware of the variable-length property of UTF-8. However, since my source is byte which is 8 bit, I understood (apparently wrongly) that it needs only 8-bit UTF-8 words. Is UTF-8 conversion actually saving the strange symbols that you see when on the CLI you do "cat somebinary" ? I thought UTF-8 was just somehow used to map each of the possible 8bit words of byte to one particular 8 bit word of UTF-8. Wrong? I thought about using Base64 but it's bad because it uses only 7 bit..

questions reformulated: is there a smarter way to convert byte to something String?
May favorite was to just cast byte[] to char[], but then I still have 16bit words.

additional use case info:

I'm adapting Jedis (java client for the NoSQL Redis) as the  "primitive storage layer" for hypergraphDB. So, jedis is a database for another "database".
My problem is that I have to feed jedis with byte[] data all the time, but internally, >Redis< (the actual server)  is dealing only with "binary safe" Strings. Since Redis is written in C, a char is 8 bit long, AFAIK not ASCIII which is 7 bit. In Jedis however, java world, every character is 16 bit long internally. I don't understand this code (yet), but I suppose jedis then converts this java 16 bit strings to a Redis conforming 8 bit string (([here][3]). It says it extends FilterOutputStream. My hope is to bypass the byte[] <-> string conversion altogether and use that Filteroutputstream...?  )

now I wonder: if I had to interconvert byte[] and String all the time, with datasizes ranging from very small to potentially very big, isn't there a huge waste of memory to have each 8 bit character passed around as 16bit within java?

答:
Actually, you have the UTF-8 part wrong: UTF-8 is a variable-length multibyte encoding, so there are valid characters 1-4 bytes in length (in other words, some UTF-8 characters are 8-bit, some are 16-bit, some are 24-bit, and some are 32-bit). Although the 1-byte characters take up 8 bits, there are many more multibyte characters. If you only had 1-byte characters, it would only allow you to have 256 different characters in total (a.k.a. "Extended ASCII"); that may be sufficient for 90% of use in English (my naïve guesstimate), but would bite you in the ass as soon as you even think of anything beyond that subset (see the word naïve - English, yet can't be written just with ASCII).

So, although UTF-16 (which Java uses) looks wasteful, it's actually not. Anyway, unless you're on a very limited embedded system (in which case, what you're doing there with Java?), trying to trim down the strings is pointless microoptimization.

For a slightly longer introduction to character encodings, see e.g. this: http://www.joelonsoftware.com/articles/Unicode.html


问:
How to update a scatter plot in PyQt via a callback?
I have this program, that upon user's click on a button, I want to update the previously drawn plot with the new data given by the user. What I'm trying to do is to show a user is a plot of the decision boundary of a classifier system, and when the user adds new data, I want to update my scatter plot accordingly. Here's my code:

```<code>from matplotlib.backends.backend_qt5agg import (
    FigureCanvasQTAgg,
    FigureManagerQT,
)
from PyQt5 import QtWidgets
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import numpy as np
class CustomFigureCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, cmap_name="coolwarm"):
        fig = Figure()
        self.color_map = plt.get_cmap(cmap_name)
        self.axes = fig.add_subplot(111)
        super().__init__(fig)
        self.setParent(parent)
        self.setBaseSize(300, 300)
        self.setMaximumSize(400, 400)
        self.setMinimumSize(250, 250)
        self.setSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.MinimumExpanding,
        )

    def set_clf_2d(self, clf_2d):
        self.clf = clf_2d

    def plot_new_datapoints(self, x2D):
        self.add_datapoint(x2D)

    @staticmethod
    def _make_meshgrid(x, y, h=0.02):
        x_min, x_max = x.min() - 1, x.max() + 1
        y_min, y_max = y.min() - 1, y.max() + 1
        XX, YY = np.meshgrid(
            np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)
        )
        return XX, YY

    def _plot_contours(self, xx, yy, **params):
        """Plot the decision boundaries for a classifier.

        Parameters
        ----------
        ax: matplotlib axes object
        clf: a classifier
        xx: meshgrid ndarray
        yy: meshgrid ndarray
        params: dictionary of params to pass to contourf, optional
        """
        Z = self.clf.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        self.axes.contourf(xx, yy, Z, **params)

    def plot_data(self, x2D, y):
        """plots the given array and the decision function bounday.

        Arguments:
            x2D {np.array} -- [2d array]
            y {np.array} -- [1d array]
        """

        x0, x1 = x2D[:, 0], x2D[:, 1]
        xx, yy = CustomFigureCanvas._make_meshgrid(x0, x1)
        labels = ["Cognitive", "Not Cognitive"]
        colors = ["r", "b"]
        self.axes.clear()
        self._plot_contours(xx, yy, cmap=self.color_map, alpha=0.8)
        target_ids = [0, 1]

        for i, c, label in zip(target_ids, colors, labels):
            print(i, label)
            self.axes.scatter(
                x0[y == i],
                x1[y == i],
                color=c,
                label=label,
                marker="o",
                s=(15, 15),
            )

        self.axes.set_xlim(xx.min(), xx.max())
        self.axes.set_ylim(yy.min(), yy.max())
        self.axes.set_title("2D Representation using PCA")
        self.axes.legend(fontsize=8)
        self.axes.plot()

    def add_datapoint(self, x2d):
        """Adds a new datapoint to the plot

        Arguments:
            x2d {a 2d single point, [x,y]} -- [np.array with shape (1,2)]
            axes {plt.axes} -- [description]

        """
        print(x2d, type(x2d))
        self.axes.scatter(
            x2d[:, 0],
            x2d[:, 1],
            color="k",
            label="Current Text",
            marker="o",
            s=(15, 15),
        )
        self.axes.legend(fontsize=8)
        self.axes.plot()
</code>```

The problem I'm currently having is that, after the call of _plot_contours, the plot won't be updated. After reading about "update able" figures in matplotlib, I saw a few suggesting using plt.ion() for generating update-able figures. There also been some suggestion about using FuncAnimation class, but this is not exactly the solution that I need, since it doesn't rely on user's button clicked callback, and instead refreshes the plot in a given interval.

EDIT: This a minimal code that reproduces the problem I'm having:

```<code>import sys
from PyQt5 import QtWidgets

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import (
    NavigationToolbar2QT as NavigationToolbar,
)
from matplotlib.figure import Figure
from custom_figure_canvas import CustomFigureCanvas

import random
import numpy as np
from sklearn.svm import SVC

class Window(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        # a figure instance to plot on
        self.figure = Figure()

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.canvas = CustomFigureCanvas(parent=self)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        # Just some button connected to `plot` method
        self.button = QtWidgets.QPushButton("Plot")
        self.button.clicked.connect(self.plot)

        # set the layout
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        layout.addWidget(self.button)
        self.setLayout(layout)

    def plot(self):

        x2D = np.random.rand(50, 2)
        y = np.random.randint(0, 2, size=(50,))

        x2D_train = np.random.rand(50, 2)
        y_train = np.random.randint(0, 2, size=(50,))

        clf = SVC()
        clf.fit(x2D_train, y_train)

        print(x2D)
        self.canvas.set_clf_2d(clf)
        self.canvas.plot_data(x2D, y)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    main = Window()
    main.show()

    sys.exit(app.exec_())
</code>```

答:
I cannot exactly figure where the adding of new data points must be taking place since your code is far from minimal, but here is a simple example of adding new points to a scatter plot in a qt application (although that doesn't really matter actually).

```<code>import sys
import numpy as np
from matplotlib.backends.backend_qt5agg import \
    (FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
from PyQt5 import QtCore, QtWidgets

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)

        self.canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(self.canvas)
        self.addToolBar(QtCore.Qt.BottomToolBarArea,
                        NavigationToolbar(self.canvas, self))

        self.ax = self.canvas.figure.subplots()
        self.scat = self.ax.scatter([], [], marker='o', color='red', s=100)
        self.ax.set_xlim([0, 1])
        self.ax.set_ylim([0, 1])

        self.button = QtWidgets.QPushButton("Add point")
        self.button.clicked.connect(self.addPoint)
        layout.addWidget(self.button)

    def addPoint(self):
        x, y = np.random.random(size=(2,))
        old_data = self.scat.get_offsets()
        data = np.append(old_data, [[x, y]], axis=0)
        self.scat.set_offsets(data)
        self.canvas.draw_idle()

if __name__ == "__main__":
    qapp = QtWidgets.QApplication(sys.argv)
    app = ApplicationWindow()
    app.show()
    qapp.exec_()
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have this program, that upon user's click on a button, I want to update the previously drawn plot with the new data given by the user. What I'm trying to do is to show a user is a plot of the decision boundary of a classifier system, and when the user adds new data, I want to update my scatter plot accordingly. Here's my code:

from matplotlib.backends.backend_qt5agg import (
    FigureCanvasQTAgg,
    FigureManagerQT,
)
from PyQt5 import QtWidgets
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import numpy as np
class CustomFigureCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, cmap_name="coolwarm"):
        fig = Figure()
        self.color_map = plt.get_cmap(cmap_name)
        self.axes = fig.add_subplot(111)
        super().__init__(fig)
        self.setParent(parent)
        self.setBaseSize(300, 300)
        self.setMaximumSize(400, 400)
        self.setMinimumSize(250, 250)
        self.setSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.MinimumExpanding,
        )

    def set_clf_2d(self, clf_2d):
        self.clf = clf_2d

    def plot_new_datapoints(self, x2D):
        self.add_datapoint(x2D)

    @staticmethod
    def _make_meshgrid(x, y, h=0.02):
        x_min, x_max = x.min() - 1, x.max() + 1
        y_min, y_max = y.min() - 1, y.max() + 1
        XX, YY = np.meshgrid(
            np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)
        )
        return XX, YY

    def _plot_contours(self, xx, yy, **params):
        """Plot the decision boundaries for a classifier.

        Parameters
        ----------
        ax: matplotlib axes object
        clf: a classifier
        xx: meshgrid ndarray
        yy: meshgrid ndarray
        params: dictionary of params to pass to contourf, optional
        """
        Z = self.clf.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        self.axes.contourf(xx, yy, Z, **params)

    def plot_data(self, x2D, y):
        """plots the given array and the decision function bounday.

        Arguments:
            x2D {np.array} -- [2d array]
            y {np.array} -- [1d array]
        """

        x0, x1 = x2D[:, 0], x2D[:, 1]
        xx, yy = CustomFigureCanvas._make_meshgrid(x0, x1)
        labels = ["Cognitive", "Not Cognitive"]
        colors = ["r", "b"]
        self.axes.clear()
        self._plot_contours(xx, yy, cmap=self.color_map, alpha=0.8)
        target_ids = [0, 1]

        for i, c, label in zip(target_ids, colors, labels):
            print(i, label)
            self.axes.scatter(
                x0[y == i],
                x1[y == i],
                color=c,
                label=label,
                marker="o",
                s=(15, 15),
            )

        self.axes.set_xlim(xx.min(), xx.max())
        self.axes.set_ylim(yy.min(), yy.max())
        self.axes.set_title("2D Representation using PCA")
        self.axes.legend(fontsize=8)
        self.axes.plot()

    def add_datapoint(self, x2d):
        """Adds a new datapoint to the plot

        Arguments:
            x2d {a 2d single point, [x,y]} -- [np.array with shape (1,2)]
            axes {plt.axes} -- [description]

        """
        print(x2d, type(x2d))
        self.axes.scatter(
            x2d[:, 0],
            x2d[:, 1],
            color="k",
            label="Current Text",
            marker="o",
            s=(15, 15),
        )
        self.axes.legend(fontsize=8)
        self.axes.plot()

The problem I'm currently having is that, after the call of _plot_contours, the plot won't be updated. After reading about "update able" figures in matplotlib, I saw a few suggesting using plt.ion() for generating update-able figures. There also been some suggestion about using FuncAnimation class, but this is not exactly the solution that I need, since it doesn't rely on user's button clicked callback, and instead refreshes the plot in a given interval.

EDIT: This a minimal code that reproduces the problem I'm having:

import sys
from PyQt5 import QtWidgets

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import (
    NavigationToolbar2QT as NavigationToolbar,
)
from matplotlib.figure import Figure
from custom_figure_canvas import CustomFigureCanvas

import random
import numpy as np
from sklearn.svm import SVC

class Window(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        # a figure instance to plot on
        self.figure = Figure()

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.canvas = CustomFigureCanvas(parent=self)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        # Just some button connected to `plot` method
        self.button = QtWidgets.QPushButton("Plot")
        self.button.clicked.connect(self.plot)

        # set the layout
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        layout.addWidget(self.button)
        self.setLayout(layout)

    def plot(self):

        x2D = np.random.rand(50, 2)
        y = np.random.randint(0, 2, size=(50,))

        x2D_train = np.random.rand(50, 2)
        y_train = np.random.randint(0, 2, size=(50,))

        clf = SVC()
        clf.fit(x2D_train, y_train)

        print(x2D)
        self.canvas.set_clf_2d(clf)
        self.canvas.plot_data(x2D, y)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    main = Window()
    main.show()

    sys.exit(app.exec_())

Body:
I cannot exactly figure where the adding of new data points must be taking place since your code is far from minimal, but here is a simple example of adding new points to a scatter plot in a qt application (although that doesn't really matter actually).

import sys
import numpy as np
from matplotlib.backends.backend_qt5agg import \
    (FigureCanvasQTAgg as FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
from PyQt5 import QtCore, QtWidgets

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)

        self.canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(self.canvas)
        self.addToolBar(QtCore.Qt.BottomToolBarArea,
                        NavigationToolbar(self.canvas, self))

        self.ax = self.canvas.figure.subplots()
        self.scat = self.ax.scatter([], [], marker='o', color='red', s=100)
        self.ax.set_xlim([0, 1])
        self.ax.set_ylim([0, 1])

        self.button = QtWidgets.QPushButton("Add point")
        self.button.clicked.connect(self.addPoint)
        layout.addWidget(self.button)

    def addPoint(self):
        x, y = np.random.random(size=(2,))
        old_data = self.scat.get_offsets()
        data = np.append(old_data, [[x, y]], axis=0)
        self.scat.set_offsets(data)
        self.canvas.draw_idle()

if __name__ == "__main__":
    qapp = QtWidgets.QApplication(sys.argv)
    app = ApplicationWindow()
    app.show()
    qapp.exec_()


问:
Specify type that is a subtype
We are specifying an abstract class as well as implementation like this:

```<code>from abc import ABC
class Base(ABC):
    ...

class Type1(Base):
    def __init__(self, var1: str):
        ...
</code>```

then we are trying to use it in this way

```<code>from typing import Dict
constructors: Dict[str, Base]= {'type1': Type1}

constructors['type1']("")  # Error here
</code>```

But we are getting an error in our IDE that says Base is not callable -- which is true.  How do we specify that the our dictionary values are descendants of the Base class which are callable?

答:
The annotation Dict[str,Base] indicates a dict that maps str keys to values that are instances of Base (or its subclasses). You intend the values to be the class Base (or one of its subclasses) itself, so you need to use Type[Base] instead. (Just like Base et al. are instances of the (meta)class type.)

```<code>constructors: Dict[str, Type[Base]] = {'type1': Type1}
constructors['type1']("")
</code>```

Whether your IDE is smart enough tell if constructors['type1'] is abstract or not is another matter, though.

Title: Specify type that is a subtype

Body:
We are specifying an abstract class as well as implementation like this:

from abc import ABC
class Base(ABC):
    ...

class Type1(Base):
    def __init__(self, var1: str):
        ...

then we are trying to use it in this way

from typing import Dict
constructors: Dict[str, Base]= {'type1': Type1}

constructors['type1']("")  # Error here

But we are getting an error in our IDE that says Base is not callable -- which is true.  How do we specify that the our dictionary values are descendants of the Base class which are callable?

Body:
The annotation Dict[str,Base] indicates a dict that maps str keys to values that are instances of Base (or its subclasses). You intend the values to be the class Base (or one of its subclasses) itself, so you need to use Type[Base] instead. (Just like Base et al. are instances of the (meta)class type.)

constructors: Dict[str, Type[Base]] = {'type1': Type1}
constructors['type1']("")

Whether your IDE is smart enough tell if constructors['type1'] is abstract or not is another matter, though.


问:
Convert DTS.Variables of type System.Object into a list
I have an SSIS package that executes a SQL task in order to get the names of servers I need to connect to. Then, the results of that query are stored in an variable object called "servers". I then want to run another package on each server at once, so I wanted to split out the "servers" variable. However, when I do this in a C# Script Task, I keep getting the error:

Error: 0x1 at Script Task: Exception has been thrown by the target of an invocation.

Here's the code to split out the servers variable:

Error: 0x1 at Script Task: Exception has been thrown by the target of an invocation.

```<code>public void Main()
{
    var serverlist = (string[])Dts.Variables["User::servers"].Value;

    Dts.Variables["server1"].Value = serverlist[0];
    Dts.TaskResult = (int)ScriptResults.Success;
}

</code>```

It should be a pretty simple code, but for some reason, it just does not work.

答:
Since you have mentioned that:

I have an SSIS package that executes a SQL task in order to get the names of servers

The main problem is in the following line:

```<code>var serverlist = (string[])Dts.Variables["User::servers"].Value;
</code>```

Execute SQL Task doesn't return a list of string, it return a record-set object. In order to read it within a script task you have to follow the following post (You have to use OledbAdapter):

SSIS - How to access a RecordSet variable inside a Script Task

Body:
I have an SSIS package that executes a SQL task in order to get the names of servers I need to connect to. Then, the results of that query are stored in an variable object called "servers". I then want to run another package on each server at once, so I wanted to split out the "servers" variable. However, when I do this in a C# Script Task, I keep getting the error:

Error: 0x1 at Script Task: Exception has been thrown by the target of an invocation.

Here's the code to split out the servers variable:

Error: 0x1 at Script Task: Exception has been thrown by the target of an invocation.

public void Main()
{
    var serverlist = (string[])Dts.Variables["User::servers"].Value;

    Dts.Variables["server1"].Value = serverlist[0];
    Dts.TaskResult = (int)ScriptResults.Success;
}

It should be a pretty simple code, but for some reason, it just does not work.

Body:
Since you have mentioned that:

I have an SSIS package that executes a SQL task in order to get the names of servers

The main problem is in the following line:

var serverlist = (string[])Dts.Variables["User::servers"].Value;

Execute SQL Task doesn't return a list of string, it return a record-set object. In order to read it within a script task you have to follow the following post (You have to use OledbAdapter):

SSIS - How to access a RecordSet variable inside a Script Task


问:
How to execute 2 consecutive commands in a thread without a context switch occurring?
I have a C# program, which has an "Agent" class. The program creates several Agents, and each Agent has a "run()" method, which executes a Task (i.e.: Task.Factory.StartNew()...).

Each Agent performs some calculations, and then needs to wait for all the other Agents to finish their calculations, before proceeding to the next stage (his actions will be based according to the calculations of the others).

In order to make an Agent wait, I have created a CancellationTokenSource (named "tokenSource"), and in order to alert the program that this Agent is going to sleep, I threw an event. Thus, the 2 consecutive commands are:

```<code>(1) OnWaitingForAgents(new EventArgs());
(2) tokenSource.Token.WaitHandle.WaitOne();
</code>```

(The event is caught by an "AgentManager" class, which is a thread in itself, and the 2nd command makes the Agent Task thread sleep until a signal will be received for the Cancellation Token).

Each time the above event is fired, the AgentManager class catches it, and adds +1 to a counter. If the number of the counter equals the number of Agents used in the program, the AgentManager (which holds a reference to all Agents) wakes each one up as follows:

```<code>agent.TokenSource.Cancel();
</code>```

Now we reach my problem: The 1st command is executed asynchronously by an Agent, then due to a context switch between threads, the AgentManager seems to catch the event, and goes on to wake up all the Agents. BUT - the current Agent has not even reached the 2nd command yet !
Thus, the Agent is receiving a "wake up" signal, and only then does he go to sleep, which means he gets stuck sleeping with no one to wake him up!
Is there a way to "atomize" the 2 consecutive methods together, so no context switch will happen, thus forcing the Agent to go to sleep before the AgentManager has the chance to wake him up?

答: The low-level technique that you are asking about is thread synchronisation. What you have there is a critical section (or part of one), and you need to protect access to it. I'm surprised that you've learned about multithreaded programming without having learned about thread synchronisation and critical sections yet! It's essential to know about these things for any kind of "low-level" multithreaded programming.</p>

Body:
I have a C# program, which has an "Agent" class. The program creates several Agents, and each Agent has a "run()" method, which executes a Task (i.e.: Task.Factory.StartNew()...).

Each Agent performs some calculations, and then needs to wait for all the other Agents to finish their calculations, before proceeding to the next stage (his actions will be based according to the calculations of the others).

In order to make an Agent wait, I have created a CancellationTokenSource (named "tokenSource"), and in order to alert the program that this Agent is going to sleep, I threw an event. Thus, the 2 consecutive commands are:

(1) OnWaitingForAgents(new EventArgs());
(2) tokenSource.Token.WaitHandle.WaitOne();

(The event is caught by an "AgentManager" class, which is a thread in itself, and the 2nd command makes the Agent Task thread sleep until a signal will be received for the Cancellation Token).

Each time the above event is fired, the AgentManager class catches it, and adds +1 to a counter. If the number of the counter equals the number of Agents used in the program, the AgentManager (which holds a reference to all Agents) wakes each one up as follows:

agent.TokenSource.Cancel();

Now we reach my problem: The 1st command is executed asynchronously by an Agent, then due to a context switch between threads, the AgentManager seems to catch the event, and goes on to wake up all the Agents. BUT - the current Agent has not even reached the 2nd command yet !
Thus, the Agent is receiving a "wake up" signal, and only then does he go to sleep, which means he gets stuck sleeping with no one to wake him up!
Is there a way to "atomize" the 2 consecutive methods together, so no context switch will happen, thus forcing the Agent to go to sleep before the AgentManager has the chance to wake him up?


问:
How to use html special special characters as normal string
How to convert HTML special characters as normal string...

For example:

```<code><h1>Copy Right Symbol 𝕔</h1>
</code>```

I want to print &copf as normal string...

答:
Encode the & as

```<code>&
</code>```

So it would be

```<code><h1>Copy Right Symbol &copf;</h1>
</code>```

Body:
How to convert HTML special characters as normal string...

For example:

Copy Right Symbol 𝕔

I want to print &copf as normal string...

Body:
Encode the & as

&amp;

So it would be

<h1>Copy Right Symbol &amp;copf;</h1>


问:
Search Filter needed to find a user with networkID in Active Directory
Updated 5/28/2019

I'm using ActiveDirectoryLdapAuthenticationProvider from org.springframework.security.ldap.authentication.ad and searchForUser method is able to find the user by email.

I'm using the default searchFilter: (&(objectClass=user)(userPrincipalName={0})).

But it doesn't work if networkID is provided as username. So:

employee@PublicCompanyEmail.com  works fine

employee_AD_username@internaldomain.com doesn't work

Appreciate any ideas on it!

答:
A little bit of terminology first

Security Account Manager (SAM) Name

```<code>  The networkID you use to login to the network.
</code>```

User Principal Name (UPN)

```<code> It may be Implicit UPN (iUPN) or Explicit UPN (eUPN).

 An example for iUPN would be: networkID@internalDomain.com

 An example for eUPN would be: employee_name@companyName.com

 eUPN may be defined by network administrator.

 In my case, the UPN we're using in our AD is actually an eUPN.
</code>```

Search Filter Syntax

```<code> This is query language for AD.

 We used it to define the filter while searching for objects in AD.

 {0}-occurrence means full username with domain in it. If the domain is defined in LDAP configuration then Spring Security checks if it's present in the entered username to login. If not, then it'll be added.

 {1}-occurrence means whatever entered as username. So, Spring won't do any modification on the provided username.
</code>```

If you want to be able to login without providing domain name, you need to define the domain in LDAP configuration

```<code>ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
            "domain",...);
</code>```

Then if it's the domain used in email address, this filter:

```<code>(&(objectClass=user)(userPrincipalName={0}))
</code>```

will find the user with and without the domain name.

Then if the configured domain is internal-domain, this filter:

```<code>(&(objectClass=user)(sAMAccountName={1}))
</code>```

will find the user if the username provided is networkID with no doamin.

If you don't define the domain for LDAP configuration and leave it null while instantiating the object, then you should be able to search for both UPN and sam -account with {1} occurrence but you have to provide the domain for both networkID and email-username while on login.

Body:
A little bit of terminology first

Security Account Manager (SAM) Name

  The networkID you use to login to the network.

User Principal Name (UPN)

 It may be Implicit UPN (iUPN) or Explicit UPN (eUPN).

 An example for iUPN would be: networkID@internalDomain.com

 An example for eUPN would be: employee_name@companyName.com

 eUPN may be defined by network administrator.

 In my case, the UPN we're using in our AD is actually an eUPN.

Search Filter Syntax

 This is query language for AD.

 We used it to define the filter while searching for objects in AD.

 {0}-occurrence means full username with domain in it. If the domain is defined in LDAP configuration then Spring Security checks if it's present in the entered username to login. If not, then it'll be added.

 {1}-occurrence means whatever entered as username. So, Spring won't do any modification on the provided username.

If you want to be able to login without providing domain name, you need to define the domain in LDAP configuration

ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
            "domain",...);

Then if it's the domain used in email address, this filter:

(&(objectClass=user)(userPrincipalName={0}))

will find the user with and without the domain name.

Then if the configured domain is internal-domain, this filter:

(&(objectClass=user)(sAMAccountName={1}))

will find the user if the username provided is networkID with no doamin.

If you don't define the domain for LDAP configuration and leave it null while instantiating the object, then you should be able to search for both UPN and sam -account with {1} occurrence but you have to provide the domain for both networkID and email-username while on login.


问:
How to find a particular object in DevTools memory snapshot if the type of the object is just "Object"?
queryObjects function returns instances of a given prototype.
I want to inspect retainers of those instances. To do that I need to find them in devtools memory snapshot. One of those instances type is "Object", so searching by class type isn't helpful. They are just too many of them.

How can I find that particular instance in a snapshot?

答:
If it's ok to modify these objects you can try the following trick.

Store the array you got from the queryObjects into a temp variable. You can do it via the context menu. Then run the following code to give each object a unique id:

temp1.forEach((t, i) => t.__id = String(i))
```

Then take a heap snapshot. Now each object should be identifiable by that __id string.

Body:
If it's ok to modify these objects you can try the following trick.

Store the array you got from the queryObjects into a temp variable. You can do it via the context menu. Then run the following code to give each object a unique id:

temp1.forEach((t, i) => t.__id = String(i))

Then take a heap snapshot. Now each object should be identifiable by that __id string.


问:
how to select from database using an array in condition in laravel
I have an array called $slugs and I need to receive  data form database table called posts in single array how to archive that ?</p>

答:
If I'm not wrong you have array of slugs like this ['slug', 'slug1', 'slug2'] and you want to get values from table where slugs matches your slugs array in a single query.

```<code>//Solution via eloquent
$slugs = ['slug', 'slug1', 'slug2'];

Post::whereIn('slug', $slugs)->get();

// Solution via Query builder
use Illuminate\Support\Facades\DB;

$slugs = ['slug', 'slug1', 'slug2'];
DB::table('posts')->whereIn('slug', $slugs)->get();
</code>```

If you want to convert all your posts response to an array and then assign it to $slugs array you should use below solution

```<code>$posts = Post::all()->toArray();
$slugs[] = $posts;
</code>```

To know more about whereIn visit

Body:
If I'm not wrong you have array of slugs like this ['slug', 'slug1', 'slug2'] and you want to get values from table where slugs matches your slugs array in a single query.

//Solution via eloquent
$slugs = ['slug', 'slug1', 'slug2'];

Post::whereIn('slug', $slugs)->get();

// Solution via Query builder
use Illuminate\Support\Facades\DB;

$slugs = ['slug', 'slug1', 'slug2'];
DB::table('posts')->whereIn('slug', $slugs)->get();

If you want to convert all your posts response to an array and then assign it to $slugs array you should use below solution

$posts = Post::all()->toArray();
$slugs[] = $posts;

To know more about whereIn visit


问:
Starting Electron with JS file as argument
When I install the electron quick start and run

```<code>node_modules/.bin/electron --help
</code>```

it tells me:

```<code>A path to an Electron app may be specified. It must be one of the following:
  - index.js file.
  - Folder containing a package.json file.
  - Folder containing an index.js file.
  - .html/.htm file.
  - http://, https://, or file:// URL.
</code>```

Running

```<code>node_modules/.bin/electron .
</code>```

(i.e. the option "Folder containing a package.json file") works alright. package.json points to main.js and looks as follows:

```<code>{
  "name": "electron-quick-start",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "repository": "https://github.com/electron/electron-quick-start",
  "keywords": [
    "Electron",
    "quick",
    "start",
    "tutorial",
    "demo"
  ],
  "author": "GitHub",
  "license": "CC0-1.0",
  "devDependencies": {
    "electron": "^4.1.4"
  }
}
</code>```

I'd assume that running this:

```<code>node_modules/.bin/electron main.js
</code>```

should work as well, but it does not – it just shows the Electron "dummy" screen.

How can I specify on the command line which JavaScript to run?

答:
Turns out the JavaScript is executed alright – the problem is how the path to the main HTML file is resolved.  Solution: Replace:

mainWindow.loadFile('index.html')
```

<p>with:</p>

<pre class="lang-js prettyprint-override"><code>const arg = process.argv[1]  // better command line parsing might be needed
const dir = fs.lstatSync(arg).isDirectory() ? arg : path.resolve(arg, '..')
mainWindow.loadFile(path.resolve(dir, 'index.html'))
</code>```

Body:
When I install the electron quick start and run

node_modules/.bin/electron --help

it tells me:

A path to an Electron app may be specified. It must be one of the following:
  - index.js file.
  - Folder containing a package.json file.
  - Folder containing an index.js file.
  - .html/.htm file.
  - http://, https://, or file:// URL.

Running

node_modules/.bin/electron .

(i.e. the option "Folder containing a package.json file") works alright. package.json points to main.js and looks as follows:

{
  "name": "electron-quick-start",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "repository": "https://github.com/electron/electron-quick-start",
  "keywords": [
    "Electron",
    "quick",
    "start",
    "tutorial",
    "demo"
  ],
  "author": "GitHub",
  "license": "CC0-1.0",
  "devDependencies": {
    "electron": "^4.1.4"
  }
}

I'd assume that running this:

node_modules/.bin/electron main.js

should work as well, but it does not – it just shows the Electron "dummy" screen.

How can I specify on the command line which JavaScript to run?

Body:
Turns out the JavaScript is executed alright – the problem is how the path to the main HTML file is resolved.  Solution: Replace:

mainWindow.loadFile('index.html')

with:

const arg = process.argv[1]  // better command line parsing might be needed
const dir = fs.lstatSync(arg).isDirectory() ? arg : path.resolve(arg, '..')
mainWindow.loadFile(path.resolve(dir, 'index.html'))


问:
Is there any way to get EmployeeID in .NET Core without third party libraries?
I used to use the UserPrincipal class to retrieve active directory information on a user, specifically the EmployeeId (not the username, we don't usually use that to tie employees to specific data points in sql). However, in .net core that class doesn't exist and I'm still fairly new to .net core so I'm not sure how a lot of it's features work in an Intranet setting. I know many probably won't work with asp.net core being cross platform and other server types not having any idea of active directory.

Below is code I use in regular asp.net environments to grab an employee id.

```<code>var userContext = System.Web.HttpContext.Current;
PrincipalContext pcxt = new PrincipalContext(ContextType.Domain, "mydomain.com");
UserPrincipal uPrincipal = UserPrincipal.FindByIdentity(pcxt, IdentityType.SamAccountName, userContext.User.Identity.Name);
return uPrincipal.EmployeeId;
</code>```

What kind of code if any can I use to grab the same information? Is it possible without third party libraries? It seems the IIS server may transport some kind of information I need through claims? I've attempted to do research but every thing just leads me down more research avenues and I'm not sure where to start.

答: What you are looking for now has moved in Net Core. The User Principal lives on the HttpContext, but you access via the IHttpContextAccessor which is injected using dependency injection.. This is an example from Microsoft of the starting point for it: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-2.2</p>

Body:
I used to use the UserPrincipal class to retrieve active directory information on a user, specifically the EmployeeId (not the username, we don't usually use that to tie employees to specific data points in sql). However, in .net core that class doesn't exist and I'm still fairly new to .net core so I'm not sure how a lot of it's features work in an Intranet setting. I know many probably won't work with asp.net core being cross platform and other server types not having any idea of active directory.

Below is code I use in regular asp.net environments to grab an employee id.

var userContext = System.Web.HttpContext.Current;
PrincipalContext pcxt = new PrincipalContext(ContextType.Domain, "mydomain.com");
UserPrincipal uPrincipal = UserPrincipal.FindByIdentity(pcxt, IdentityType.SamAccountName, userContext.User.Identity.Name);
return uPrincipal.EmployeeId;

What kind of code if any can I use to grab the same information? Is it possible without third party libraries? It seems the IIS server may transport some kind of information I need through claims? I've attempted to do research but every thing just leads me down more research avenues and I'm not sure where to start.


问:
How to fix error of field creation in Laravel 5.3?
I have a migration that correctly created table at local vagrant server, but when I tried migrate at VPS with nginx it encounters strange error.

Local env is Vagrant/homestead (I don't know OS, sorry), VPS env is Debian 8, nginx. Laravel version 5.3
Migrations have to create 12 tables, but problem encountered before the end process, so 10 tables only created. By the way it shows that env and other settings is OK (I think) and just in 1 table 1 field is error

this is creation code:

```<code>public function up()
    {
        Schema::create('vicards', function (Blueprint $table) {
            $table->increments('id');
            $table->string('visi_slug', 100);
            $table->unique('visi_slug', 'visi_slug_unique');
            $table->integer('user_id');
            $table->index('user_id', 'cards_user_id_index');
            $table->string('user_slug', 100);
            $table->index('user_slug', 'cards_user_slug_index');
            $table->string('avatar', 44)->default(0);
            $table->string('header', 80);
            $table->string('price', 12);
            $table->text('description');
            $table->text('pictures'); // 5 pics * 20 symbols + 4 commas
            $table->text('videos'); // 3 videos * 41 symbols + 2 commas
            $table->text('contacts'); //
            $table->text('links'); // links separated by commas
            $table->text('styles'); // object serialized
            $table->tinyInteger('actual', 1)->default(0);
            $table->timestamps();
        });
    }
</code>```

problem invokes this field

```<code>$table->tinyInteger('actual', 1)->default(0);
</code>```

artisan interprets it in:

```<code> `actual` tinyint not null default '0' auto_increment primary key
</code>```

and off-course it is error because 'auto_increment primary key' already exist - 1st field

Expected result - regular table creation.

I got error:

" [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'actual' (SQL: create table vicards (id int unsigned not
  null auto_increment primary key, visi_slug varchar(100) not null, user_id int not null, user_slug varchar(100) not null, avatar varchar
  (44) not null default '0', header varchar(80) not null, price varchar(12) not null, description text not null, pictures text not null,
  videos text not null, contacts text not null, links text not null, styles text not null, actual tinyint not null default '0' auto_inc
  rement primary key, created_at timestamp null, updated_at timestamp null) default character set utf8 collate utf8_unicode_ci)"

What is cause of this error? Help me please.

答:
Do not use lenght value, just create tinyint with default value:</p>

```<code>$table->tinyInteger('actual')->default(0);
</code>```

Body:
I have a migration that correctly created table at local vagrant server, but when I tried migrate at VPS with nginx it encounters strange error.

Local env is Vagrant/homestead (I don't know OS, sorry), VPS env is Debian 8, nginx. Laravel version 5.3
Migrations have to create 12 tables, but problem encountered before the end process, so 10 tables only created. By the way it shows that env and other settings is OK (I think) and just in 1 table 1 field is error

this is creation code:

public function up()
    {
        Schema::create('vicards', function (Blueprint $table) {
            $table->increments('id');
            $table->string('visi_slug', 100);
            $table->unique('visi_slug', 'visi_slug_unique');
            $table->integer('user_id');
            $table->index('user_id', 'cards_user_id_index');
            $table->string('user_slug', 100);
            $table->index('user_slug', 'cards_user_slug_index');
            $table->string('avatar', 44)->default(0);
            $table->string('header', 80);
            $table->string('price', 12);
            $table->text('description');
            $table->text('pictures'); // 5 pics * 20 symbols + 4 commas
            $table->text('videos'); // 3 videos * 41 symbols + 2 commas
            $table->text('contacts'); //
            $table->text('links'); // links separated by commas
            $table->text('styles'); // object serialized
            $table->tinyInteger('actual', 1)->default(0);
            $table->timestamps();
        });
    }

problem invokes this field

$table->tinyInteger('actual', 1)->default(0);

artisan interprets it in:

 `actual` tinyint not null default '0' auto_increment primary key

and off-course it is error because 'auto_increment primary key' already exist - 1st field

Expected result - regular table creation.

I got error:

" [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'actual' (SQL: create table vicards (id int unsigned not
  null auto_increment primary key, visi_slug varchar(100) not null, user_id int not null, user_slug varchar(100) not null, avatar varchar
  (44) not null default '0', header varchar(80) not null, price varchar(12) not null, description text not null, pictures text not null,
  videos text not null, contacts text not null, links text not null, styles text not null, actual tinyint not null default '0' auto_inc
  rement primary key, created_at timestamp null, updated_at timestamp null) default character set utf8 collate utf8_unicode_ci)"

What is cause of this error? Help me please.

Body:
Do not use lenght value, just create tinyint with default value:

$table->tinyInteger('actual')->default(0);


问:
Using regular expression extractor to extract a value?
I am trying to extract the value from the following code. Even though my regex expression is fine it is still not extracting the value.

```<code>token" value="(.+?)"
</code>```

this does give me the exact match which I checked using regex101.com

```<code><input type="hidden" name="token" value="GSYGEP2UUWOTMZ2SFV1G5D2M8L247KIG">
</code>```

what the regex expression should be

Body:
I am trying to extract the value from the following code. Even though my regex expression is fine it is still not extracting the value.

token" value="(.+?)"

this does give me the exact match which I checked using regex101.com

<input type="hidden" name="token" value="GSYGEP2UUWOTMZ2SFV1G5D2M8L247KIG">

what the regex expression should be

Body:
Try this

<input(?=(?:[^>"']|"[^"]*"|'[^']*')*?\sname\s*=\s*(['"])\s*token\s*\1)(?=(?:[^>"']|"[^"]*"|'[^']*')*?\svalue\s*=\s*(['"])((?:(?!\2)[\S\s])*)\2)\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]*?)+>

The Value content you're after is in Capture Group 3

https://regex101.com/r/HJhStT/1

https://regex101.com/r/8BWONb/1

Explained

 < input                # Input tag

 (?=                    # Name attribute: Assert (a pseudo atomic group)
      (?: [^>"'] | " [^"]* " | ' [^']* ' )*?
      \s name  \s* = \s*     # name =
      ( ['"] )               # (1), Quote
      \s* token \s*          # token
      \1
 )
 (?=                    # Value attribute
      (?: [^>"'] | " [^"]* " | ' [^']* ' )*?
      \s value  \s* = \s*    # value =
      ( ['"] )               # (2), Quote
      (                      # (3 start), value content
           (?:
                (?! \2 )
                [\S\s]
           )*
      )                      # (3 end)
      \2
 )
 # Just get rest of tag
 \s+
 (?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]*? )+
 >


问:
PHPunit: How to change Mock object propriety from an external function
I am using Symfony and I'm trying to test the addStudentCard function in "Student" class, which adds a "StudentCard" object to $studentCards array collection propriety AND a "Student" object to $student propriety in "StudentCard" class. This is how I did it:

class StudentCard {
  private $student;
  public function getStudent();
  public function setStudent();
  //...
}

class Student {
  private $studentCards;
  public function getStudentCards();
  public function addStudentCard(StudentCard $studentCard){
    $studentCard->setStudent($this);
    $this->studentCards[] = $studentCard;
    return $this;
  //...
}
```

<p>What I want to achieve is to test this addStudentCard function using a MockBuilder, I have already done this without using mocks by doing:</p>

<pre class="lang-php prettyprint-override"><code>class StudentTest extends AbstractTestCase {
  public function testAddStudentCard(){
    $studentCard = new StudentCard();
    $student = new Student();
    $student->addStudentCard($studentCard);
    $student->assertSame($studentCard, $student->getStudentCards()[0]);
    $student->assertSame($student, $studentCard->getStudent());
}
</code>```

This works as expected with no problem.

What I would like is to replace the line:

$studentCard = new StudentCard();
```

<p>with something like this:</p>

<pre class="lang-php prettyprint-override"><code>$studentCard = $this->getMockBuilder(StudentCard::class)->getMock();
</code>```

But what I get is the error:
Failed asserting that null is identical to an object of class Student.

答:
The problem with your scenario is, that you are asserting that the mock returns the original student:

$student->assertSame($student, $studentCard->getStudent());
```

<p>If the <code>$studentCard</code> is a Mock object, it doesn't return the original object unless you tell it to do so. But since you are already using a mock, there is no need to test that. </p>

<p>What you actually want to test in this case is, that the <code>$student</code> was assigned back to the <code>$studentCard</code>. That is what expectations are for.</p>

<p>So in your particular case you would go with:</p>

<pre class="lang-php prettyprint-override"><code>$studentCard->expects($this->once())->method('setStudent')->with($student);
// ...
$student->addStudentCard($studentCard);
</code>```

Make sure that you have the line there (as I shown in the code) before you call addStudentCard, otherwise the test will fail that the expectation has not been met.

After you set the expectations, there is no need to run any assertions (and you should not) on the mock objects.

Body:
I am using Symfony and I'm trying to test the addStudentCard function in "Student" class, which adds a "StudentCard" object to $studentCards array collection propriety AND a "Student" object to $student propriety in "StudentCard" class. This is how I did it:

class StudentCard {
  private $student;
  public function getStudent();
  public function setStudent();
  //...
}

class Student {
  private $studentCards;
  public function getStudentCards();
  public function addStudentCard(StudentCard $studentCard){
    $studentCard->setStudent($this);
    $this->studentCards[] = $studentCard;
    return $this;
  //...
}

What I want to achieve is to test this addStudentCard function using a MockBuilder, I have already done this without using mocks by doing:

class StudentTest extends AbstractTestCase {
  public function testAddStudentCard(){
    $studentCard = new StudentCard();
    $student = new Student();
    $student->addStudentCard($studentCard);
    $student->assertSame($studentCard, $student->getStudentCards()[0]);
    $student->assertSame($student, $studentCard->getStudent());
}

This works as expected with no problem.

What I would like is to replace the line:

$studentCard = new StudentCard();

with something like this:

$studentCard = $this->getMockBuilder(StudentCard::class)->getMock();

But what I get is the error:
Failed asserting that null is identical to an object of class Student.

Body:
The problem with your scenario is, that you are asserting that the mock returns the original student:

$student->assertSame($student, $studentCard->getStudent());

If the $studentCard is a Mock object, it doesn't return the original object unless you tell it to do so. But since you are already using a mock, there is no need to test that.

What you actually want to test in this case is, that the $student was assigned back to the $studentCard. That is what expectations are for.

So in your particular case you would go with:

$studentCard->expects($this->once())->method('setStudent')->with($student);
// ...
$student->addStudentCard($studentCard);

Make sure that you have the line there (as I shown in the code) before you call addStudentCard, otherwise the test will fail that the expectation has not been met.

After you set the expectations, there is no need to run any assertions (and you should not) on the mock objects.


问:
C# Server side DateTime
Please tell me, is it good to store DateTime, for example createtime of posts, on server in ticks?</p>

```<code>DateTime.Ticks
</code>```

答:
Why would you want to do that? There is no penalty in storing it as regular DateTime. The better question you should ask yourself is how you would handle different timezones.

We store all dates in database as UTC, and do the appropriate conversion based on either user selected timezone or server timezone. Usually user selected, because it makes more sense for a user to handle times in his own timezone, but data will then be used by people in different timezones.

Title: C# Server side DateTime

Body:
Please tell me, is it good to store DateTime, for example createtime of posts, on server in ticks?

DateTime.Ticks


问:
How can I get the model created by super().create() in a ModelViewSet?
I'm trying to get a copy of the model created by super().create() in my ModelViewSet's create() method. What's the simplest way to do that?

I have a ModelViewSet that takes a generic POST request, which I know is good because I end up with a new record in my DB. What I want to do is get the object that was just created so I can return its pk to the client. However, the following will not work:

class ItemViewSet(viewsets.ModelViewSet):
    model = Item
    # ...
    def create(self, request, *args, **kwargs):
        super().create(request, *args, **kwargs)  # Successfully creates instance
        instance = self.get_object()  # Throws error
        return Response({'status': 'success', 'pk': instance.pk})
```

Like with other DRF ModelViewSet methods, I'd expect self.get_object() to get me the instance created, though this is usually only usable in a "detail route". What I get instead is the following error:
AssertionError: Expected view CultivarStockViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.

Any insight is appreciated!

答:
With a little further debugging, I figured it out. For posterity's sake, here's my working create() method:

def create(self, request, *args, **kwargs):
    response = super().create(request, *args, **kwargs)
    instance = response.data
    return Response({'status': 'success', 'pk': instance['pk']})
```

Body:
I'm trying to get a copy of the model created by super().create() in my ModelViewSet's create() method. What's the simplest way to do that?

I have a ModelViewSet that takes a generic POST request, which I know is good because I end up with a new record in my DB. What I want to do is get the object that was just created so I can return its pk to the client. However, the following will not work:

class ItemViewSet(viewsets.ModelViewSet):
    model = Item
    # ...
    def create(self, request, *args, **kwargs):
        super().create(request, *args, **kwargs)  # Successfully creates instance
        instance = self.get_object()  # Throws error
        return Response({'status': 'success', 'pk': instance.pk})

Like with other DRF ModelViewSet methods, I'd expect self.get_object() to get me the instance created, though this is usually only usable in a "detail route". What I get instead is the following error:
AssertionError: Expected view CultivarStockViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.

Any insight is appreciated!


问:
Loop through entire array while excluding an item
I have an array of items that I'd like to loop through and apply some code to, excluding one item (the clicked-on item).  I've tried using splice but I don't want to remove the array item, just skip over it.  In this case, I'm trying to remove a CSS class for each item, except the excluded one.

I've tried a few methods, using splice for one which isn't what I need.  I've also tried something like if (array[i] == 3 || (i - 1) = 2) { continue; else { .... } but can't seem to get that to work.

```<code>   var array = ["item1", "item2", "item3"];
   var i;
   for (i = 0; i < items.length; i++) {
       if(array[i] is the excluded one){
               skip over}
    else { $(items[i]).removeClass('class');
    }
</code>```

No error messages, just not working as expected.

答:
Use continue

In the following example we want to exclude "item2" and fixed variable naming/reference:

var items = ["item1", "item2", "item3"];
var i;
for (i = 0; i < items.length; i++) {
  if(items[i] === "item2"){
    continue;
  }

   //$(items[i]).removeClass('class');
   document.write(items[i] + "
");
}```

Body:
I have an array of items that I'd like to loop through and apply some code to, excluding one item (the clicked-on item).  I've tried using splice but I don't want to remove the array item, just skip over it.  In this case, I'm trying to remove a CSS class for each item, except the excluded one.

I've tried a few methods, using splice for one which isn't what I need.  I've also tried something like if (array[i] == 3 || (i - 1) = 2) { continue; else { .... } but can't seem to get that to work.

   var array = ["item1", "item2", "item3"];
   var i;
   for (i = 0; i < items.length; i++) {
       if(array[i] is the excluded one){
               skip over}
    else { $(items[i]).removeClass('class');
    }

No error messages, just not working as expected.

Body:
Use continue

In the following example we want to exclude "item2" and fixed variable naming/reference:

var items = ["item1", "item2", "item3"];
var i;
for (i = 0; i < items.length; i++) {
  if(items[i] === "item2"){
    continue;
  }

   //$(items[i]).removeClass('class');
   document.write(items[i] + "<br>");
}


问:
Trouble clicking on different links using puppeteer
I've written tiny scripts in node using puppeteer to perform clicks cyclically on the link of different posts from it's landing page of a website.

The site link used within my scripts is a placeholder. Moreover, they are not dynamic. So, puppeteer might be overkill. However, My intention is to learn the logic of clicking.

When I execute my first script, It clicks once and throws the following error as it goes out of the source.

```<code>const puppeteer = require("puppeteer");

(async () => {
    const browser = await puppeteer.launch({headless:false});
    const [page] = await browser.pages();
    await page.goto("https://stackoverflow.com/questions/tagged/web-scraping",{waitUntil:'networkidle2'});
    await page.waitFor(".summary");
    const sections = await page.$$(".summary");

    for (const section of sections) {
        await section.$eval(".question-hyperlink", el => el.click())
    }

    await browser.close();
})();
</code>```

The error the above script encounters:

```<code>(node:9944) UnhandledPromiseRejectionWarning: Error: Execution context was destroyed, most likely because of a navigation.
</code>```

When I execute the following, the script pretends to click once (in reality it is not) and encounters the same error as earlier.

```<code>const puppeteer = require("puppeteer");

(async () => {
    const browser = await puppeteer.launch({headless:false});
    const [page] = await browser.pages();
    await page.goto("https://stackoverflow.com/questions/tagged/web-scraping");

    await page.waitFor(".summary .question-hyperlink");
    const sections = await page.$$(".summary .question-hyperlink");

    for (let i=0, lngth = sections.length; i < lngth; i++) {
        await sections[i].click();
    }

    await browser.close();
})();
</code>```

The error the above one throws:

```<code>(node:10128) UnhandledPromiseRejectionWarning: Error: Execution context was destroyed, most likely because of a navigation.
</code>```

How can I let my script perform clicks cyclically?

答:
Problem:

Execution context was destroyed, most likely because of a navigation.

The error says you wanted to click some link, or do something on some page which does not exist anymore, most likely because of you navigated away.

Logic:

Think of the puppeteer script as a real human browsing the real page.

First, we load the url (https://stackoverflow.com/questions/tagged/web-scraping).

Next, we want to go through all questions asked on that page. To do that what would we normally do? We would do either of the following,

Open one link in a new tab. Focus on that new tab, finish our work and come back to the original tab. Continue next link.

We click on a link, do our stuff, go back to previous page, continue next one.

So both of them involves moving away from and coming back to current page.

If you don't follow this flow, you will get the error message as above.

Solution

There are at least 4 or more ways to resolve this. I will go with the simplest and complex ones.

Way: Link Extraction

First we extract all links on current page.

```<code>const links = await page.$$eval(".hyperlink", element => element.href);
</code>```

This gives us a list of url. We can create a new tab for each link.

```<code>for(let link of links){
  const newTab = await browser.newPage();
  await newTab.goto(link);
  // do the stuff
  await newTab.close();
}
</code>```

This will go through each link one by one. We could improve this by using promise.map and various queue libraries, but you get the idea.

Way: Coming back to main page

We will need to store the state somehow so we can know which link we visited last time. If we visited third question and came back to tag page, we need to visit the  4th question next time and vice versa.

Check the following code.

```<code>const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(
    `https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&pagesize=15`
  );

  const visitLink = async (index = 0) => {
    await page.waitFor("div.summary > h3 > a");

    // extract the links to click, we need this every time
    // because the context will be destryoed once we navigate
    const links = await page.$$("div.summary > h3 > a");
    // assuming there are 15 questions on one page,
    // we will stop on 16th question, since that does not exist
    if (links[index]) {
      console.log("Clicking ", index);

      await Promise.all([

        // so, start with the first link
        await page.evaluate(element => {
          element.click();
        }, links[index]),

        // either make sure we are on the correct page due to navigation
        await page.waitForNavigation(),
        // or wait for the post data as well
        await page.waitFor(".post-text")
      ]);

      const currentPage = await page.title();
      console.log(index, currentPage);

      // go back and visit next link
      await page.goBack({ waitUntil: "networkidle0" });
      return visitLink(index + 1);
    }
    console.log("No links left to click");
  };

  await visitLink();

  await browser.close();
})();
</code>```

Result:

EDIT: There are multiple questions similar to this one. I will be referencing them in case you want to learn more.

Answer by Thomas Dondorf

My answer about a logic for infinite scrolling

Body:
I've written tiny scripts in node using puppeteer to perform clicks cyclically on the link of different posts from it's landing page of a website.

The site link used within my scripts is a placeholder. Moreover, they are not dynamic. So, puppeteer might be overkill. However, My intention is to learn the logic of clicking.

When I execute my first script, It clicks once and throws the following error as it goes out of the source.

const puppeteer = require("puppeteer");

(async () => {
    const browser = await puppeteer.launch({headless:false});
    const [page] = await browser.pages();
    await page.goto("https://stackoverflow.com/questions/tagged/web-scraping",{waitUntil:'networkidle2'});
    await page.waitFor(".summary");
    const sections = await page.$$(".summary");

    for (const section of sections) {
        await section.$eval(".question-hyperlink", el => el.click())
    }

    await browser.close();
})();

The error the above script encounters:

(node:9944) UnhandledPromiseRejectionWarning: Error: Execution context was destroyed, most likely because of a navigation.

When I execute the following, the script pretends to click once (in reality it is not) and encounters the same error as earlier.

const puppeteer = require("puppeteer");

(async () => {
    const browser = await puppeteer.launch({headless:false});
    const [page] = await browser.pages();
    await page.goto("https://stackoverflow.com/questions/tagged/web-scraping");

    await page.waitFor(".summary .question-hyperlink");
    const sections = await page.$$(".summary .question-hyperlink");

    for (let i=0, lngth = sections.length; i < lngth; i++) {
        await sections[i].click();
    }

    await browser.close();
})();

The error the above one throws:

(node:10128) UnhandledPromiseRejectionWarning: Error: Execution context was destroyed, most likely because of a navigation.

How can I let my script perform clicks cyclically?

Body:
Problem:

Execution context was destroyed, most likely because of a navigation.

The error says you wanted to click some link, or do something on some page which does not exist anymore, most likely because of you navigated away.

Logic:

Think of the puppeteer script as a real human browsing the real page.

First, we load the url (https://stackoverflow.com/questions/tagged/web-scraping).

Next, we want to go through all questions asked on that page. To do that what would we normally do? We would do either of the following,

Open one link in a new tab. Focus on that new tab, finish our work and come back to the original tab. Continue next link.

We click on a link, do our stuff, go back to previous page, continue next one.

So both of them involves moving away from and coming back to current page.

If you don't follow this flow, you will get the error message as above.

Solution

There are at least 4 or more ways to resolve this. I will go with the simplest and complex ones.

Way: Link Extraction

First we extract all links on current page.

const links = await page.$$eval(".hyperlink", element => element.href);

This gives us a list of url. We can create a new tab for each link.

for(let link of links){
  const newTab = await browser.newPage();
  await newTab.goto(link);
  // do the stuff
  await newTab.close();
}

This will go through each link one by one. We could improve this by using promise.map and various queue libraries, but you get the idea.

Way: Coming back to main page

We will need to store the state somehow so we can know which link we visited last time. If we visited third question and came back to tag page, we need to visit the  4th question next time and vice versa.

Check the following code.

const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  await page.goto(
    `https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&pagesize=15`
  );

  const visitLink = async (index = 0) => {
    await page.waitFor("div.summary > h3 > a");

    // extract the links to click, we need this every time
    // because the context will be destryoed once we navigate
    const links = await page.$$("div.summary > h3 > a");
    // assuming there are 15 questions on one page,
    // we will stop on 16th question, since that does not exist
    if (links[index]) {
      console.log("Clicking ", index);

      await Promise.all([

        // so, start with the first link
        await page.evaluate(element => {
          element.click();
        }, links[index]),

        // either make sure we are on the correct page due to navigation
        await page.waitForNavigation(),
        // or wait for the post data as well
        await page.waitFor(".post-text")
      ]);

      const currentPage = await page.title();
      console.log(index, currentPage);

      // go back and visit next link
      await page.goBack({ waitUntil: "networkidle0" });
      return visitLink(index + 1);
    }
    console.log("No links left to click");
  };

  await visitLink();

  await browser.close();
})();

Result:

EDIT: There are multiple questions similar to this one. I will be referencing them in case you want to learn more.

Answer by Thomas Dondorf

My answer about a logic for infinite scrolling


问:
After pushing on lambda FCM does not work
I want to send push notifications in my lambda function. It working as expected on localhost but when I push it to lambda code does not working.
Here is my code: </p>

```<code>const FCM = require('fcm-node');

let sendNotification = function(regToken) {

let serverKey = 'MY_SERVER_KEY';
let fcm = new FCM(serverKey);

let message = {
    to: regToken,
    notification: {
        title: 'Title of push notification',
        body: 'Body of push notification'
    }
};

fcm.send(message, function(err, response){
    if (err) {
        console.log("Something has gone wrong!", err);
    } else {
        console.log("Successfully sent with response: ", response);
    }
});
}
</code>```

答: You need to encapsulate functions in the exports.handler </p>

Body:
I want to send push notifications in my lambda function. It working as expected on localhost but when I push it to lambda code does not working.
Here is my code:

const FCM = require('fcm-node');

let sendNotification = function(regToken) {

let serverKey = 'MY_SERVER_KEY';
let fcm = new FCM(serverKey);

let message = {
    to: regToken,
    notification: {
        title: 'Title of push notification',
        body: 'Body of push notification'
    }
};

fcm.send(message, function(err, response){
    if (err) {
        console.log("Something has gone wrong!", err);
    } else {
        console.log("Successfully sent with response: ", response);
    }
});
}