问:
DIV is generating 2 times on checkout page (WOO COMMERCE)?
The problem starts when user clicks on shipping details checkbox. The div with class order-detail-summary-outer automatically generates when user checks the box.On the checkout page when user checkbox for the shipping details the order summary doubles. I have done many modifications in the in past. So i think i made mistake.On clicking shipping information checkbox. the order summary becomes double. only subtotal, shipping and total.

I am providing review-order.php file code below

```<code><?php
/**
 * Review order table
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/checkout/review-order.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see https://docs.woocommerce.com/document/template-structure/
 * @package WooCommerce/Templates
 * @version 3.8.0
 */

defined( 'ABSPATH' ) || exit;
?>
<table class="shop_table woocommerce-checkout-review-order-table">
    <thead>
        <tr>
            <th class="product-name"><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
            <th class="product-total"><?php esc_html_e( 'Subtotal', 'woocommerce' ); ?></th>
        </tr>
    </thead>
    <tbody>
        <?php
        do_action( 'woocommerce_review_order_before_cart_contents' );

        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
            $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );

            if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_checkout_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
                ?>
                <tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
                    <td class="product-name">
                        <?php echo apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                        <?php echo apply_filters( 'woocommerce_checkout_cart_item_quantity', ' <strong class="product-quantity">' . sprintf( '× %s', $cart_item['quantity'] ) . '</strong>', $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                        <?php echo wc_get_formatted_cart_item_data( $cart_item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                    </td>
                    <td class="product-total">
                        <?php echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                    </td>
                </tr>
                <?php
            }
        }

        do_action( 'woocommerce_review_order_after_cart_contents' );
        ?>
    </tbody>
</table>

<div class="order-detail-summary-outer">

        <div class="cart-subtotal">
            <h2><?php esc_html_e( 'Subtotal', 'woocommerce' ); ?></h2>
            <div class="order-detail-summary-item"><?php wc_cart_totals_subtotal_html(); ?></div>
        </div>

        <?php foreach ( WC()->cart->get_coupons() as $code => $coupon ) : ?>
            <div class="cart-discount coupon-<?php echo esc_attr( sanitize_title( $code ) ); ?>">
                <h2><?php wc_cart_totals_coupon_label( $coupon ); ?></h2>
                <div class="order-detail-summary-item"><?php wc_cart_totals_coupon_html( $coupon ); ?></div>
            </div>
        <?php endforeach; ?>
<h2>Shipping</h2>
        <?php if ( WC()->cart->needs_shipping() && WC()->cart->show_shipping() ) : ?>

            <?php do_action( 'woocommerce_review_order_before_shipping' ); ?>

            <?php wc_cart_totals_shipping_html(); ?>

            <?php do_action( 'woocommerce_review_order_after_shipping' ); ?>

        <?php endif; ?>

        <?php foreach ( WC()->cart->get_fees() as $fee ) : ?>
            <div class="fee">
                <h2><?php echo esc_html( $fee->name ); ?></h2>
                <div class="order-detail-summary-item"><?php wc_cart_totals_fee_html( $fee ); ?></div>
            </div>
        <?php endforeach; ?>

        <?php if ( wc_tax_enabled() && ! WC()->cart->display_prices_including_tax() ) : ?>
            <?php if ( 'itemized' === get_option( 'woocommerce_tax_total_display' ) ) : ?>
                <?php foreach ( WC()->cart->get_tax_totals() as $code => $tax ) : // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited ?>
                    <div class="tax-rate tax-rate-<?php echo esc_attr( sanitize_title( $code ) ); ?>">
                        <h2><?php echo esc_html( $tax->label ); ?></h2>
                        <div class="order-detail-summary-item"><?php echo wp_kses_post( $tax->formatted_amount ); ?></div>
                    </div>
                <?php endforeach; ?>
            <?php else : ?>
                <div class="tax-total">
                    <h2><?php echo esc_html( WC()->countries->tax_or_vat() ); ?></h2>
                    <div class="order-detail-summary-item"><?php wc_cart_totals_taxes_total_html(); ?></div>
                </div>
            <?php endif; ?>
        <?php endif; ?>

        <?php do_action( 'woocommerce_review_order_before_order_total' ); ?>

        <div class="order-total">
            <h2><?php esc_html_e( 'Total', 'woocommerce' ); ?></h2>
            <div class="order-detail-summary-item"><?php wc_cart_totals_order_total_html(); ?></div>
        </div>

        <?php do_action( 'woocommerce_review_order_after_order_total' ); ?>

</div>
</code>```

答:
This matter could come from many things, a mistake in sql query, an javascript that duplicate div, ...

If it's from php side, i don't know WOOCommerce but can you apply \array_unique() method on your loop to remove duplicates (e.g code below as a workaround).

```<code><?php foreach ( \array_unique(WC()->cart->get_coupons()) as $code => $coupon ) : ?>
</code>```

https://www.php.net/manual/en/function.array-unique.php

PS : But i'm sure it's an mistake on javascript side.

Body:
The problem starts when user clicks on shipping details checkbox. The div with class order-detail-summary-outer automatically generates when user checks the box.On the checkout page when user checkbox for the shipping details the order summary doubles. I have done many modifications in the in past. So i think i made mistake.On clicking shipping information checkbox. the order summary becomes double. only subtotal, shipping and total.

I am providing review-order.php file code below

<?php
/**
 * Review order table
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/checkout/review-order.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see https://docs.woocommerce.com/document/template-structure/
 * @package WooCommerce/Templates
 * @version 3.8.0
 */

defined( 'ABSPATH' ) || exit;
?>

            <?php esc_html_e( 'Product', 'woocommerce' ); ?>
            <?php esc_html_e( 'Subtotal', 'woocommerce' ); ?>

        <?php
        do_action( 'woocommerce_review_order_before_cart_contents' );

        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
            $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );

            if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_checkout_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
                ?>
                <tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">

                        <?php echo apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' '; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                        <?php echo apply_filters( 'woocommerce_checkout_cart_item_quantity', ' ' . sprintf( '× %s', $cart_item['quantity'] ) . '', $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                        <?php echo wc_get_formatted_cart_item_data( $cart_item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

                        <?php echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>

                <?php
            }
        }

        do_action( 'woocommerce_review_order_after_cart_contents' );
        ?>

<?php esc_html_e( 'Subtotal', 'woocommerce' ); ?>

<?php wc_cart_totals_subtotal_html(); ?>

        <?php foreach ( WC()->cart->get_coupons() as $code => $coupon ) : ?>
            <div class="cart-discount coupon-<?php echo esc_attr( sanitize_title( $code ) ); ?>">

<?php wc_cart_totals_coupon_label( $coupon ); ?>

<?php wc_cart_totals_coupon_html( $coupon ); ?>

        <?php endforeach; ?>

Shipping

        <?php if ( WC()->cart->needs_shipping() && WC()->cart->show_shipping() ) : ?>

            <?php do_action( 'woocommerce_review_order_before_shipping' ); ?>

            <?php wc_cart_totals_shipping_html(); ?>

            <?php do_action( 'woocommerce_review_order_after_shipping' ); ?>

        <?php endif; ?>

        <?php foreach ( WC()->cart->get_fees() as $fee ) : ?>

<?php echo esc_html( $fee->name ); ?>

<?php wc_cart_totals_fee_html( $fee ); ?>

        <?php endforeach; ?>

        <?php if ( wc_tax_enabled() && ! WC()->cart->display_prices_including_tax() ) : ?>
            <?php if ( 'itemized' === get_option( 'woocommerce_tax_total_display' ) ) : ?>
                <?php foreach ( WC()->cart->get_tax_totals() as $code => $tax ) : // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited ?>
                    <div class="tax-rate tax-rate-<?php echo esc_attr( sanitize_title( $code ) ); ?>">

<?php echo esc_html( $tax->label ); ?>

<?php echo wp_kses_post( $tax->formatted_amount ); ?>

                <?php endforeach; ?>
            <?php else : ?>

<?php echo esc_html( WC()->countries->tax_or_vat() ); ?>

<?php wc_cart_totals_taxes_total_html(); ?>

            <?php endif; ?>
        <?php endif; ?>

        <?php do_action( 'woocommerce_review_order_before_order_total' ); ?>

<?php esc_html_e( 'Total', 'woocommerce' ); ?>

<?php wc_cart_totals_order_total_html(); ?>

        <?php do_action( 'woocommerce_review_order_after_order_total' ); ?>

Body:
This matter could come from many things, a mistake in sql query, an javascript that duplicate div, ...

If it's from php side, i don't know WOOCommerce but can you apply \array_unique() method on your loop to remove duplicates (e.g code below as a workaround).

<?php foreach ( \array_unique(WC()->cart->get_coupons()) as $code => $coupon ) : ?>

https://www.php.net/manual/en/function.array-unique.php

PS : But i'm sure it's an mistake on javascript side.


来源: stackexchange

问:
Rawvideo to mp4 container
How can I stream rawvideo codec to mp4 container? The error is Could not find tag for codec rawvideo in stream #0, codec not currently supported in container. Url is for example video=Logitech HD Webcam C270 and Format is dshow. Filename is lets say out.mp4

```<code>AVFormatContext* pInputFmtCtx = avformat_alloc_context();
AVInputFormat* inputFormat = av_find_input_format(Format);

avformat_open_input(&pInputFmtCtx, url, inputFormat, null);
if (avformat_find_stream_info(pInputFmtCtx, null) != -1)
   ... find stream index

AVCodec* videoDecoder = avcodec_find_decoder(pInputFmtCtx->streams[_vidStreamIndex]->codecpar->codec_id);

AVCodecContext* videcCodecCtx = avcodec_alloc_context3(videoDecoder);
avcodec_parameters_to_context(videcCodecCtx, videoCodecParams);

avcodec_open2(videcCodecCtx, videoDecoder, null);

// and the output context
AVFormatContext* pOutputFmtCtx = null;
avformat_alloc_output_context2(&pOutputFmtCtx, null, null, fileName);

// iterate over streams of input context and when we find it
AVStream* in_stream = pInputFmtCtx->streams[i];
AVCodecParameters* in_codecpar = in_stream->codecpar;

AVStream* out_stream = avformat_new_stream(pOutputFmtCtx, null);

// init h264 encoder
AVCodec* videoEncoder = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_H264);
pVideoEncoderCodecContext = ffmpeg.avcodec_alloc_context3(videoEncoder);

pVideoEncoderCodecContext->time_base = videcCodecCtx->time_base;
pVideoEncoderCodecContext->framerate = videcCodecCtx->framerate;
pVideoEncoderCodecContext->width = videcCodecCtx->width;
pVideoEncoderCodecContext->height = videcCodecCtx->height;
pVideoEncoderCodecContext->bit_rate = videcCodecCtx->bit_rate;
pVideoEncoderCodecContext->gop_size = videcCodecCtx->gop_size;
pVideoEncoderCodecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
pVideoEncoderCodecContext->flags |= ffmpeg.AV_CODEC_FLAG_GLOBAL_HEADER;

// copy parameters to outstream codec
avcodec_parameters_copy(out_stream->codecpar, in_codecpar);

....

// after that
avio_open(&pOutputFmtCtx->pb, fileName, AVIO_FLAG_WRITE);
avformat_write_header(pOutputFmtCtx, &opts);

// and reading
while (av_read_frame(pInputFormatContext, pkt) >= 0)

// decode
avcodec_send_packet(videcCodecCtx, pkt);
//receive the raw frame from the decoder
avcodec_receive_frame(videcCodecCtx, frame);

// now encode if its video packet
int ret = avcodec_send_frame(pVideoEncoderCodecContext, frame);
if (ret < 0)
{
    continue;
}

while (ret >= 0)
{
    ret = avcodec_receive_packet(pVideoEncoderCodecContext, packet);

    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
    {
           return;
    }

    av_packet_rescale_ts(packet, pVideoEncoderCodecContext->time_base, pOutputFmtCtx->streams[packet->stream_index]->time_base);
    av_interleaved_write_frame(pOutputFmtCtx, pkt);

    av_packet_unref(packet);
}
</code>```

This works fine if the camera streams H264, but if the camera streams rawvideo, it doesn't stream to the file and throws error.

EDIT As suggested I'm trying to encode it now, but avcodec_send_frame() returns -22 and nothing is saved to the file. Where do I miss? Code edited.

答: Mp4 does not support rawvideo. You must either encode it to another format, or use a container that supports it. </p>

ContentLicense: CC BY-SA 4.0

Title: Rawvideo to mp4 container

Body:
How can I stream rawvideo codec to mp4 container? The error is Could not find tag for codec rawvideo in stream #0, codec not currently supported in container. Url is for example video=Logitech HD Webcam C270 and Format is dshow. Filename is lets say out.mp4

AVFormatContext* pInputFmtCtx = avformat_alloc_context();
AVInputFormat* inputFormat = av_find_input_format(Format);

avformat_open_input(&pInputFmtCtx, url, inputFormat, null);
if (avformat_find_stream_info(pInputFmtCtx, null) != -1)
   ... find stream index

AVCodec* videoDecoder = avcodec_find_decoder(pInputFmtCtx->streams[_vidStreamIndex]->codecpar->codec_id);

AVCodecContext* videcCodecCtx = avcodec_alloc_context3(videoDecoder);
avcodec_parameters_to_context(videcCodecCtx, videoCodecParams);

avcodec_open2(videcCodecCtx, videoDecoder, null);

// and the output context
AVFormatContext* pOutputFmtCtx = null;
avformat_alloc_output_context2(&pOutputFmtCtx, null, null, fileName);

// iterate over streams of input context and when we find it
AVStream* in_stream = pInputFmtCtx->streams[i];
AVCodecParameters* in_codecpar = in_stream->codecpar;

AVStream* out_stream = avformat_new_stream(pOutputFmtCtx, null);

// init h264 encoder
AVCodec* videoEncoder = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_H264);
pVideoEncoderCodecContext = ffmpeg.avcodec_alloc_context3(videoEncoder);

pVideoEncoderCodecContext->time_base = videcCodecCtx->time_base;
pVideoEncoderCodecContext->framerate = videcCodecCtx->framerate;
pVideoEncoderCodecContext->width = videcCodecCtx->width;
pVideoEncoderCodecContext->height = videcCodecCtx->height;
pVideoEncoderCodecContext->bit_rate = videcCodecCtx->bit_rate;
pVideoEncoderCodecContext->gop_size = videcCodecCtx->gop_size;
pVideoEncoderCodecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
pVideoEncoderCodecContext->flags |= ffmpeg.AV_CODEC_FLAG_GLOBAL_HEADER;

// copy parameters to outstream codec
avcodec_parameters_copy(out_stream->codecpar, in_codecpar);

....

// after that
avio_open(&pOutputFmtCtx->pb, fileName, AVIO_FLAG_WRITE);
avformat_write_header(pOutputFmtCtx, &opts);

// and reading
while (av_read_frame(pInputFormatContext, pkt) >= 0)

// decode
avcodec_send_packet(videcCodecCtx, pkt);
//receive the raw frame from the decoder
avcodec_receive_frame(videcCodecCtx, frame);

// now encode if its video packet
int ret = avcodec_send_frame(pVideoEncoderCodecContext, frame);
if (ret < 0)
{
    continue;
}

while (ret >= 0)
{
    ret = avcodec_receive_packet(pVideoEncoderCodecContext, packet);

    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
    {
           return;
    }

    av_packet_rescale_ts(packet, pVideoEncoderCodecContext->time_base, pOutputFmtCtx->streams[packet->stream_index]->time_base);
    av_interleaved_write_frame(pOutputFmtCtx, pkt);

    av_packet_unref(packet);
}

This works fine if the camera streams H264, but if the camera streams rawvideo, it doesn't stream to the file and throws error.

EDIT As suggested I'm trying to encode it now, but avcodec_send_frame() returns -22 and nothing is saved to the file. Where do I miss? Code edited.


问:
OMS--Leaflet markers have different stack order after spiderfy

our setup

We have an L.map with various layers of L.markers loading from a dynamic array of events spanning a monthly period. Many of the listed venues hold numerous events during any given period and hence we end up with numerous markers sharing locations that are very nicely spiderfied using the OMS-Leaflet plugin (0.2.6) we run from CDN

Each marker is put into one of several marker Layers depending on day of week or whether the event has been confirmed / expires e.g. here is one that falls on a weekend:

```<code>markerWeekEnd = L.marker([lat, lon], { %options% });
markerWeekEnd.addTo(map);
weekend.addLayer(markerWeekEnd);
oms.addMarker(markerWeekEnd);
</code>```

It took me a while to figure out how to stack the markers correctly so that they shows up in a certain order (1. upcoming markers, 2. other future date markers and 3. any expired markers if applicable) using zIndexOffset as the bringToFront() method does not support L.markers.

the issue

We have everything loading and stacking as required and it all works fine until we unspiderfy/spiderfy. When the markers get re-spiderfied the one that ends up on top is not the one initially displayed.

I took a look at all the OMS issues, not just OMS-Leaflet  (i.e. also the OMS version for Google Maps API v3), and found a couple of closed ones that seemed to suggest a similar issue:

OMS should remember original zIndex of marker #76
z-Indices reset #117 (previous fix closes this)

Now as far as I can tell the related fix for these appears to have been applied to OverlappingMarkerSpiderfier/1.0.2/oms.js (also 1.0.3 now I imagine) but perhaps not the OverlappingMarkerSpiderfier-Leaflet/0.2.6/oms.js version.

In any case our subsequent efforts to get around the issues described above did seem to address the zIndex somewhat but not overcome our stacking issue relating to OMS spiderfy.

what we tried

Decided to tweak my marker options to retain the original zIndexOffset settings L.marker([lat, lon], {... zIndexOffset: mIndex, mDay: mDay})  and to see if resetting the zIndex using the retained values could fix my stacking issue

```<code>// for both spiderfy & unspiderfy
oms.addListener('spiderfy', function(markers) {
   markers.forEach(function(marker) { zIndexCheck(marker); });
}
function zIndexCheck(marker){
   L.setOptions( marker, { zIndex: mIndex, zIndexOffset: mIndex });
}
</code>```

Sadly even though it seem to retain the zIndex values for markers before and after the unspiderfy/spiderfy, the eventual marker that remains on top is not the one that was there before, nor the one with the highest supplied zIndex count (addListener for spiderfy).

I have re-created a stripped down version of our sites functionality on the following jsfiddle and console logged the zIndexes of the initial markers before and after the spiderfy:

```<code>Marker Title: 'London Socials #1 (1/2)' startTime:ENDED: 1st Feb zIndex:-10
Marker Title: 'London Socials #2 (14/2)' startTime:Fri 14th Feb zIndex:5054 (Active)
Marker Title: 'London Socials #3 (28/2)' startTime:Fri 28th Feb zIndex:2026
</code>```

#2 is the active item initially

Spiderfy

```<code>[London Socials #1 (1/2)]  index:990
[London Socials #2 (14/2)]  index:5027
[London Socials #3 (28/2)]  index:5013
</code>```

UnSpiderfy

```<code>[London Socials #1 (1/2)]  index:990
[London Socials #2 (14/2)]  index:5027
[London Socials #3 (28/2)]  index:5013 (Active)
</code>```

#3 is now the active item after spiderfy/unspiderfy (see final elements below)

Final marker element

```<code><div class="awesome-marker-icon-blue awesome-marker leaflet-zoom-animated leaflet-interactive"
title="London Socials #2 (14/2)" tabindex="0" style="margin-left: -17px; margin-top: -42px; width: 35px; height: 45px; transform: translate3d(83px, 218px, 0px);
z-index: 5218;"><i class=" fa fa-moon  icon-white"></i></div>

<div class="awesome-marker-icon-blue awesome-marker leaflet-zoom-animated leaflet-interactive"
title="London Socials #3 (28/2)" tabindex="0" style="margin-left: -17px; margin-top: -42px; width: 35px; height: 45px; transform: translate3d(83px, 218px, 0px);
z-index: 5218;"><i class=" fa fa-moon  icon-white"></i></div>
</code>```

And this is as far as I got to, unable to figure out how item 3 with a previously lower zIndex (compared to item 2) managed to end up on top with a new z-index: 5218 which just so happens to be the same new z-index value as for item 2!

I posted this as a bug on gitHub, but now I'm not so sure it is a bug with OMS-Leaflet. So am posting on here as well. Here's the fiddle showing the issues:

https://jsfiddle.net/magicmb/17j2z4gy/

Environment specific versions:
leaflet.js (1.6.0), Leaflet.awesome-markers (2.0.2), OverlappingMarkerSpiderfier-Leaflet (0.2.6)

答:
Turns out it's not exactly a bug with OMS-Leaflet but more an issue
  with Leaflet and how it handles z-Indexes

Here's an extract from a thread I discovered on gis.stackexchange that was answered by YaFred way back in Oct 2 '14 and still very much relevant today:

Until somebody finds a better solution, here what I would do ...

As you noticed, leaflet is using pixel position to set zIndex (in Marker.js)

```<code>pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
this._zIndex = pos.y + this.options.zIndexOffset;
</code>```

What I suggest is to undo leaflet zIndex using setZIndexOffset()

Say you want to set zIndex = 100, you would do

```<code>var pos = map.latLngToLayerPoint(marker.getLatLng()).round();
marker.setZIndexOffset(100 - pos.y);
</code>```

There is a bit of a glitch: you have to do it every time the map is zoomed :( [EDIT: Spiderfied in our case!]

Here is a JSFiddle example (comment the code in adjustZindex() to see the difference)

For my OMS Spiderfy case this was resolved by adding:

```<code>function adjustZindex() {
    var markers = oms.getMarkers();
    for (var i = 0, len = markers.length; i < len; i ++) {
      var marker = markers[i];
      var latlng = marker._latlng, mIndexOffset = marker.options.mIndexOffset ;
      var pos = map.latLngToLayerPoint(latlng).round();
      marker.setZIndexOffset(mIndexOffset - pos.y);
    }
  }
  adjustZindex();
</code>```

and then calling adjustZindex() from my spiderfy listeners

```<code>oms.addListener('spiderfy', function(markers) {
    layersBring2Front();
    adjustZindex();
  });
</code>```

So I guess whether OMS should remember original zIndex of marker #76 was resolved in the version of OMS-Leaflet is kinda irrelevant as in all probability it would not have solved our issue.

Body:
our setup

We have an L.map with various layers of L.markers loading from a dynamic array of events spanning a monthly period. Many of the listed venues hold numerous events during any given period and hence we end up with numerous markers sharing locations that are very nicely spiderfied using the OMS-Leaflet plugin (0.2.6) we run from CDN

Each marker is put into one of several marker Layers depending on day of week or whether the event has been confirmed / expires e.g. here is one that falls on a weekend:

markerWeekEnd = L.marker([lat, lon], { %options% });
markerWeekEnd.addTo(map);
weekend.addLayer(markerWeekEnd);
oms.addMarker(markerWeekEnd);

It took me a while to figure out how to stack the markers correctly so that they shows up in a certain order (1. upcoming markers, 2. other future date markers and 3. any expired markers if applicable) using zIndexOffset as the bringToFront() method does not support L.markers.

the issue

We have everything loading and stacking as required and it all works fine until we unspiderfy/spiderfy. When the markers get re-spiderfied the one that ends up on top is not the one initially displayed.

I took a look at all the OMS issues, not just OMS-Leaflet  (i.e. also the OMS version for Google Maps API v3), and found a couple of closed ones that seemed to suggest a similar issue:

OMS should remember original zIndex of marker #76
z-Indices reset #117 (previous fix closes this)

Now as far as I can tell the related fix for these appears to have been applied to OverlappingMarkerSpiderfier/1.0.2/oms.js (also 1.0.3 now I imagine) but perhaps not the OverlappingMarkerSpiderfier-Leaflet/0.2.6/oms.js version.

In any case our subsequent efforts to get around the issues described above did seem to address the zIndex somewhat but not overcome our stacking issue relating to OMS spiderfy.

what we tried

Decided to tweak my marker options to retain the original zIndexOffset settings L.marker([lat, lon], {... zIndexOffset: mIndex, mDay: mDay})  and to see if resetting the zIndex using the retained values could fix my stacking issue

// for both spiderfy & unspiderfy
oms.addListener('spiderfy', function(markers) {
   markers.forEach(function(marker) { zIndexCheck(marker); });
}
function zIndexCheck(marker){
   L.setOptions( marker, { zIndex: mIndex, zIndexOffset: mIndex });
}

Sadly even though it seem to retain the zIndex values for markers before and after the unspiderfy/spiderfy, the eventual marker that remains on top is not the one that was there before, nor the one with the highest supplied zIndex count (addListener for spiderfy).

I have re-created a stripped down version of our sites functionality on the following jsfiddle and console logged the zIndexes of the initial markers before and after the spiderfy:

Marker Title: 'London Socials #1 (1/2)' startTime:ENDED: 1st Feb zIndex:-10
Marker Title: 'London Socials #2 (14/2)' startTime:Fri 14th Feb zIndex:5054 (Active)
Marker Title: 'London Socials #3 (28/2)' startTime:Fri 28th Feb zIndex:2026

#2 is the active item initially

Spiderfy

[London Socials #1 (1/2)]  index:990
[London Socials #2 (14/2)]  index:5027
[London Socials #3 (28/2)]  index:5013

UnSpiderfy

[London Socials #1 (1/2)]  index:990
[London Socials #2 (14/2)]  index:5027
[London Socials #3 (28/2)]  index:5013 (Active)

#3 is now the active item after spiderfy/unspiderfy (see final elements below)

Final marker element

And this is as far as I got to, unable to figure out how item 3 with a previously lower zIndex (compared to item 2) managed to end up on top with a new z-index: 5218 which just so happens to be the same new z-index value as for item 2!

I posted this as a bug on gitHub, but now I'm not so sure it is a bug with OMS-Leaflet. So am posting on here as well. Here's the fiddle showing the issues:

https://jsfiddle.net/magicmb/17j2z4gy/

Environment specific versions:
leaflet.js (1.6.0), Leaflet.awesome-markers (2.0.2), OverlappingMarkerSpiderfier-Leaflet (0.2.6)

Body:
Turns out it's not exactly a bug with OMS-Leaflet but more an issue
  with Leaflet and how it handles z-Indexes

Here's an extract from a thread I discovered on gis.stackexchange that was answered by YaFred way back in Oct 2 '14 and still very much relevant today:

Until somebody finds a better solution, here what I would do ...

As you noticed, leaflet is using pixel position to set zIndex (in Marker.js)

pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
this._zIndex = pos.y + this.options.zIndexOffset;

What I suggest is to undo leaflet zIndex using setZIndexOffset()

Say you want to set zIndex = 100, you would do

var pos = map.latLngToLayerPoint(marker.getLatLng()).round();
marker.setZIndexOffset(100 - pos.y);

There is a bit of a glitch: you have to do it every time the map is zoomed :( [EDIT: Spiderfied in our case!]

Here is a JSFiddle example (comment the code in adjustZindex() to see the difference)

For my OMS Spiderfy case this was resolved by adding:

function adjustZindex() {
    var markers = oms.getMarkers();
    for (var i = 0, len = markers.length; i < len; i ++) {
      var marker = markers[i];
      var latlng = marker._latlng, mIndexOffset = marker.options.mIndexOffset ;
      var pos = map.latLngToLayerPoint(latlng).round();
      marker.setZIndexOffset(mIndexOffset - pos.y);
    }
  }
  adjustZindex();

and then calling adjustZindex() from my spiderfy listeners

oms.addListener('spiderfy', function(markers) {
    layersBring2Front();
    adjustZindex();
  });

So I guess whether OMS should remember original zIndex of marker #76 was resolved in the version of OMS-Leaflet is kinda irrelevant as in all probability it would not have solved our issue.


问:
Save image from internal storage to gallery through ACTION_VIEW intent
I have a chat application. If a user sends an image i save that image to internal storage of the app under

```<code>data/data/package_name/....
</code>```

So if the user clicks on that image i send an intent to the system to open it

```<code>val uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(it.localUri))
       val intent = Intent(Intent.ACTION_VIEW).apply {
       flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
       setDataAndType(uri, "image/*")
    }
    startActivity(intent)
</code>```

The problem is that in the image viewer there is no choice to save the file in the public storage of the phone, in that case in the gallery.
Is there any way to do that without changing the internal storage default save location of the images in my app?

答:
If this is something you are interested in, you can use MediaStore to programmatically save in the gallery a picture from your internal storage.

Code

You could use the following code, which I successfully use in my app.

```<code>ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "MyPicture.jpg");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
   contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
}

ContentResolver resolver = myContext.getContentResolver();
Bitmap bitmap;
Uri uri;
try {
   // Requires permission WRITE_EXTERNAL_STORAGE
   bitmap = BitmapFactory.decodeFile(currentPhotoPath);
   uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
} catch (Exception e) {
   Log.e(LOG_TAG, "Error inserting picture in MediaStore: " + e.getMessage());
   return;
}

try (OutputStream stream = resolver.openOutputStream(uri)) {
   if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream) {
      throw new IOException("Error compressing the picture.");
   }
} catch (Exception e) {
   if (uri != null) {
      resolver.delete(uri, null, null);
   }
   Log.e(LOG_TAG, "Error adding picture to gallery: " + e.getMessage());
}

</code>```

Credits to this answer for the conversion of File to Bitmap and to this answer for the usage of  MediaStore.

Notes

BitmapFactory.decodeFile() requires the runtime permission WRITE_EXTERNAL_STORAGE

With the introduction of scoped memory in Android 10 (which will become mandatory in Android 11, see this article) MediaStore is probably the only reliable way to save pictures to the gallery

A consequence of scoped storage is that, yes, you should keep using the internal storage for the cache copy of your picture.

Tests

I have tested this code with with targetSdkVersion 29 on the following devices / OS combinations

Samsung Galaxy S10 / API 29

Samsung Galaxy S9 / API 29

Huawei Nexus 6P / API 27

Body:
I have a chat application. If a user sends an image i save that image to internal storage of the app under

data/data/package_name/....

So if the user clicks on that image i send an intent to the system to open it

val uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(it.localUri))
       val intent = Intent(Intent.ACTION_VIEW).apply {
       flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
       setDataAndType(uri, "image/*")
    }
    startActivity(intent)

The problem is that in the image viewer there is no choice to save the file in the public storage of the phone, in that case in the gallery.
Is there any way to do that without changing the internal storage default save location of the images in my app?

Body:
If this is something you are interested in, you can use MediaStore to programmatically save in the gallery a picture from your internal storage.

Code

You could use the following code, which I successfully use in my app.

ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "MyPicture.jpg");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
   contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
}

ContentResolver resolver = myContext.getContentResolver();
Bitmap bitmap;
Uri uri;
try {
   // Requires permission WRITE_EXTERNAL_STORAGE
   bitmap = BitmapFactory.decodeFile(currentPhotoPath);
   uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
} catch (Exception e) {
   Log.e(LOG_TAG, "Error inserting picture in MediaStore: " + e.getMessage());
   return;
}

try (OutputStream stream = resolver.openOutputStream(uri)) {
   if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream) {
      throw new IOException("Error compressing the picture.");
   }
} catch (Exception e) {
   if (uri != null) {
      resolver.delete(uri, null, null);
   }
   Log.e(LOG_TAG, "Error adding picture to gallery: " + e.getMessage());
}

Credits to this answer for the conversion of File to Bitmap and to this answer for the usage of  MediaStore.

Notes

BitmapFactory.decodeFile() requires the runtime permission WRITE_EXTERNAL_STORAGE

With the introduction of scoped memory in Android 10 (which will become mandatory in Android 11, see this article) MediaStore is probably the only reliable way to save pictures to the gallery

A consequence of scoped storage is that, yes, you should keep using the internal storage for the cache copy of your picture.

Tests

I have tested this code with with targetSdkVersion 29 on the following devices / OS combinations

Samsung Galaxy S10 / API 29

Samsung Galaxy S9 / API 29

Huawei Nexus 6P / API 27


问:
Can't get display resolution for all devices using EnumDisplaySettings
I need to get the current display resolution of all monitors attached to the computer.

I can succesfully enum the display devices using the EnumDisplayDevicesA API but for an unknown reason I can't get the current display resolution for the device \\.\DISPLAY2 using the EnumDisplayDevicesA API.
Here is the code:

```<code>displays = 0;
result = 1;

for (index = 0; result != 0; index++)
{
    devices[index].cb = sizeof(DISPLAY_DEVICEA);
    result = EnumDisplayDevicesA(NULL, index, &(devices[displays] ), 0);

    if (result == 0)
    {
            break;
    }

    settings[index].dmSize = sizeof(DEVMODEA);
    mode = 0;

    // Collect the settings
    while(EnumDisplaySettingsA(devices[index].DeviceName, mode, (DEVMODEA *)&(settings[displays] ) ) )
    {
        mode++;
    };

    // Read the current settings
    result = EnumDisplaySettingsA(devices[index].DeviceName, ENUM_CURRENT_SETTINGS, (DEVMODEA *)&(settings[displays] ) );

    if (result != 0)
    {
        displays++;
    }
    else
    {
        result = GetLastError();
        printf("Error while readind display settings %d\n", result);

        //Skip this device
        result = 1;
    }
}
</code>```

Note that this code works flawlessly on some computers while on computers with multiple video cards it fails. For examle it fails on a laptop with an Intel HD Graphicw 630 + Nvidia Quadro M1200 where the active displays are the main laptop display and an exteral display attached through either the HDMI or DP port). More precisely on these computers I can get the correct resolution for the first display device (\\.\DISPLAY1) but on the second display device (\\.\DISPLAY2) the returned width and height is 0.

The EnumDisplaySettingsA API just return 0 as well as the GetLastError API.

What does  devices represent ? Are they a monitor attached to a single video card or are they just monitors attached to whatever video card ?

NOTE: Using EnumDisplayMonitors I can get the resolution of all monitors while EnumDisplaySettingsA fails.

答:
```<code>(DEVMODEA*)&(settings[displays])
</code>```

The fact that you are using a cast suggests settings is defined incorrectly, and cast is used to hide the problem. If you have declared, for example, DEVMODEA *settings = malloc(count * sizeof(DEVMODEA)) then casting should not be necessary.

You should simply use Unicode functions as recommended by Microsoft. If you need to print ANSI, then use WideCharToMultiByte to convert Unicode to ANSI.

Moreover, you are overwriting settings[index] in the code below:

```<code>while(EnumDisplaySettingsA(devices[index].DeviceName, mode, (DEVMODEA *)&(settings[displays] ) ) )
    mode++;
result = EnumDisplaySettingsA(devices[index].DeviceName, ENUM_CURRENT_SETTINGS, (DEVMODEA *)&(settings[displays] ) );
</code>```

Note that the second call to EnumDisplaySettingsA uses ENUM_CURRENT_SETTINGS, this call will never fail and may cause problems in your loop. It will also overwrite the previous value for settings[displays]

Try the code below to see if there is a difference.

```<code>int main()
{
    DISPLAY_DEVICE device = { 0 };
    device.cb = sizeof(DISPLAY_DEVICE);
    for(int index = 0;; index++)
    {
        if(!EnumDisplayDevices(NULL, index, &device, EDD_GET_DEVICE_INTERFACE_NAME))
            break;

#ifdef UNICODE
        wprintf(L"%s\n", device.DeviceName);
#else
        printf("%s\n", device.DeviceName);
#endif

        DEVMODE devmode = { 0 };
        devmode.dmSize = sizeof(DEVMODE);
        for(int modes = 0;; modes++)
        {
            if(!EnumDisplaySettings(device.DeviceName, modes, &devmode))
                break;
            printf("%d %d %d\n",
                devmode.dmPelsWidth,
                devmode.dmPelsHeight,
                devmode.dmDisplayFrequency);
        }
    }

    return 0;
}
</code>```

Or read current resolution for each monitor

```<code>int main()
{
    int count = 0;
    DISPLAY_DEVICE temp = { 0 };
    temp.cb = sizeof(DISPLAY_DEVICE);
    while(EnumDisplayDevices(NULL, count, &temp, EDD_GET_DEVICE_INTERFACE_NAME))
        count++;
    DEVMODE *settings = malloc(count * sizeof(DEVMODE));
    DISPLAY_DEVICE *devices = malloc(count * sizeof(DISPLAY_DEVICE));

    for (int index = 0; index < count; index++)
    {
        memset(&devices[index], 0, sizeof(DISPLAY_DEVICE));
        memset(&settings[index], 0, sizeof(DEVMODE));
        devices[index].cb = sizeof(DISPLAY_DEVICE);
        settings[index].dmSize = sizeof(DEVMODE);
        if(!EnumDisplayDevices(NULL, index, &devices[index], EDD_GET_DEVICE_INTERFACE_NAME))
            break;
        if(!EnumDisplaySettings(devices[index].DeviceName, ENUM_CURRENT_SETTINGS, &settings[index]))
            break;
    }

    for(int index = 0; index < count; index++)
    {
#ifdef UNICODE
        wprintf(L"%s ", devices[index].DeviceName);
#else
        printf("%s ",  devices[index].DeviceName);
#endif
        printf("%d %d %d\n",
            settings[index].dmPelsWidth,
            settings[index].dmPelsHeight,
            settings[index].dmDisplayFrequency);
    }
    return 0;
}
</code>```

Body:
I need to get the current display resolution of all monitors attached to the computer.

I can succesfully enum the display devices using the EnumDisplayDevicesA API but for an unknown reason I can't get the current display resolution for the device \\.\DISPLAY2 using the EnumDisplayDevicesA API.
Here is the code:

displays = 0;
result = 1;

for (index = 0; result != 0; index++)
{
    devices[index].cb = sizeof(DISPLAY_DEVICEA);
    result = EnumDisplayDevicesA(NULL, index, &(devices[displays] ), 0);

    if (result == 0)
    {
            break;
    }

    settings[index].dmSize = sizeof(DEVMODEA);
    mode = 0;

    // Collect the settings
    while(EnumDisplaySettingsA(devices[index].DeviceName, mode, (DEVMODEA *)&(settings[displays] ) ) )
    {
        mode++;
    };

    // Read the current settings
    result = EnumDisplaySettingsA(devices[index].DeviceName, ENUM_CURRENT_SETTINGS, (DEVMODEA *)&(settings[displays] ) );

    if (result != 0)
    {
        displays++;
    }
    else
    {
        result = GetLastError();
        printf("Error while readind display settings %d\n", result);

        //Skip this device
        result = 1;
    }
}

Note that this code works flawlessly on some computers while on computers with multiple video cards it fails. For examle it fails on a laptop with an Intel HD Graphicw 630 + Nvidia Quadro M1200 where the active displays are the main laptop display and an exteral display attached through either the HDMI or DP port). More precisely on these computers I can get the correct resolution for the first display device (\\.\DISPLAY1) but on the second display device (\\.\DISPLAY2) the returned width and height is 0.

The EnumDisplaySettingsA API just return 0 as well as the GetLastError API.

What does  devices represent ? Are they a monitor attached to a single video card or are they just monitors attached to whatever video card ?

NOTE: Using EnumDisplayMonitors I can get the resolution of all monitors while EnumDisplaySettingsA fails.

Body:
(DEVMODEA*)&(settings[displays])

The fact that you are using a cast suggests settings is defined incorrectly, and cast is used to hide the problem. If you have declared, for example, DEVMODEA *settings = malloc(count * sizeof(DEVMODEA)) then casting should not be necessary.

You should simply use Unicode functions as recommended by Microsoft. If you need to print ANSI, then use WideCharToMultiByte to convert Unicode to ANSI.

Moreover, you are overwriting settings[index] in the code below:

while(EnumDisplaySettingsA(devices[index].DeviceName, mode, (DEVMODEA *)&(settings[displays] ) ) )
    mode++;
result = EnumDisplaySettingsA(devices[index].DeviceName, ENUM_CURRENT_SETTINGS, (DEVMODEA *)&(settings[displays] ) );

Note that the second call to EnumDisplaySettingsA uses ENUM_CURRENT_SETTINGS, this call will never fail and may cause problems in your loop. It will also overwrite the previous value for settings[displays]

Try the code below to see if there is a difference.

int main()
{
    DISPLAY_DEVICE device = { 0 };
    device.cb = sizeof(DISPLAY_DEVICE);
    for(int index = 0;; index++)
    {
        if(!EnumDisplayDevices(NULL, index, &device, EDD_GET_DEVICE_INTERFACE_NAME))
            break;

#ifdef UNICODE
        wprintf(L"%s\n", device.DeviceName);
#else
        printf("%s\n", device.DeviceName);
#endif

        DEVMODE devmode = { 0 };
        devmode.dmSize = sizeof(DEVMODE);
        for(int modes = 0;; modes++)
        {
            if(!EnumDisplaySettings(device.DeviceName, modes, &devmode))
                break;
            printf("%d %d %d\n",
                devmode.dmPelsWidth,
                devmode.dmPelsHeight,
                devmode.dmDisplayFrequency);
        }
    }

    return 0;
}

Or read current resolution for each monitor

int main()
{
    int count = 0;
    DISPLAY_DEVICE temp = { 0 };
    temp.cb = sizeof(DISPLAY_DEVICE);
    while(EnumDisplayDevices(NULL, count, &temp, EDD_GET_DEVICE_INTERFACE_NAME))
        count++;
    DEVMODE *settings = malloc(count * sizeof(DEVMODE));
    DISPLAY_DEVICE *devices = malloc(count * sizeof(DISPLAY_DEVICE));

    for (int index = 0; index < count; index++)
    {
        memset(&devices[index], 0, sizeof(DISPLAY_DEVICE));
        memset(&settings[index], 0, sizeof(DEVMODE));
        devices[index].cb = sizeof(DISPLAY_DEVICE);
        settings[index].dmSize = sizeof(DEVMODE);
        if(!EnumDisplayDevices(NULL, index, &devices[index], EDD_GET_DEVICE_INTERFACE_NAME))
            break;
        if(!EnumDisplaySettings(devices[index].DeviceName, ENUM_CURRENT_SETTINGS, &settings[index]))
            break;
    }

    for(int index = 0; index < count; index++)
    {
#ifdef UNICODE
        wprintf(L"%s ", devices[index].DeviceName);
#else
        printf("%s ",  devices[index].DeviceName);
#endif
        printf("%d %d %d\n",
            settings[index].dmPelsWidth,
            settings[index].dmPelsHeight,
            settings[index].dmDisplayFrequency);
    }
    return 0;
}


问:
Created observable doesn't emit anything
I'm trying to create a function which returns Observable<(HTTPURLResponse, Any)> using RxAlamofire:

```<code>class APIManager {
    let disposeBag = DisposeBag()
    func getResponse(credentialData: Credentials, ulr: String)->Observable<(HTTPURLResponse, Any)>{
    let credentialData = "\(credentialData.username):\(credentialData.password)".data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
    let base64Credentials = credentialData.base64EncodedString()
    let headers = ("Authorization", "Basic \(base64Credentials)")
    let header = HTTPHeaders.init(dictionaryLiteral: headers)
    return Observable.create{ observer in
        requestJSON(.get, ulr, parameters: nil, encoding: JSONEncoding.default, headers: header)
        .subscribe(onNext: { response in
            observer.onNext(response)
            } ,

    onError: { error in
        observer.onError(error)
        },
    onCompleted: {},
    onDisposed: {}).disposed(by: self.disposeBag)
    return Disposables.create()
    }
}
</code>```

}

The code into onNext is not executed; it's going through onDisposed only.

How can I fix it?

答:
Why are you wrapping requestJSON function with another Observable which is just forwarding the same element and error, when that function is already returning the Observable you need?.

Isn't this enough for you?

class APIManager {
    func getResponse(credentialData: Credentials, ulr: String) -> Observable<(HTTPURLResponse, Any)> {
        let credentialData = "\(credentialData.username):\(credentialData.password)"
            .data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
        let base64Credentials = credentialData.base64EncodedString()
        let headers = ("Authorization", "Basic \(base64Credentials)")
        let header = HTTPHeaders.init(dictionaryLiteral: headers)
        return requestJSON(.get, ulr, parameters: nil, encoding: JSONEncoding.default, headers: header)
    }
}
```

Body:
I'm trying to create a function which returns Observable<(HTTPURLResponse, Any)> using RxAlamofire:

class APIManager {
    let disposeBag = DisposeBag()
    func getResponse(credentialData: Credentials, ulr: String)->Observable<(HTTPURLResponse, Any)>{
    let credentialData = "\(credentialData.username):\(credentialData.password)".data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
    let base64Credentials = credentialData.base64EncodedString()
    let headers = ("Authorization", "Basic \(base64Credentials)")
    let header = HTTPHeaders.init(dictionaryLiteral: headers)
    return Observable.create{ observer in
        requestJSON(.get, ulr, parameters: nil, encoding: JSONEncoding.default, headers: header)
        .subscribe(onNext: { response in
            observer.onNext(response)
            } ,

    onError: { error in
        observer.onError(error)
        },
    onCompleted: {},
    onDisposed: {}).disposed(by: self.disposeBag)
    return Disposables.create()
    }
}

}

The code into onNext is not executed; it's going through onDisposed only.

How can I fix it?


问:
Save two specific worksheets in a new workbook without formulas but keeping the design
I've got a workbook where I am creating a button that allows to save two specific sheets without formula's (the purpose being that the sheets are going to be send to partners and costumers). I would like the sheets to be saved in a single document somewhere on my computer, and still have the current "design" with colors, setup etc.

I've currently written this code, which does everything that I've described, except deleting the formulas...

```<code>Sub SaveAsValues()
Dim ws As Worksheet

Worksheets(Array("frontpage", "mobile")).Copy After:= ws.Worksheets

With ActiveWorkbook
.SaveAs Filename:= "C:XXXX" & "NAME", FileFormat:= xlOpenXMLWorkbook
.Close savechanges = False
End With
End Sub
</code>```

Hope you can help :-)

答:
I have a sheet I use something similar for, I'll adjust the code a bit to work with your scenario. If you don't want the settings to change, delete the TurnOnFunctions & TurnOffFunctions subs.

This code will only break the links, not necessarily all the formulas. So if a formula references another spreadsheet it will be a static value; however, if it is a simple formula that stays within the spreadsheet it will stay that way.

Also add your workbook name to the respective area.

```<code>Sub NewWorkbooks()
'This will make seperate workbooks for each of the tabs listed
Dim wb As Workbook
Dim NewBook As Workbook
Dim ws As Worksheet

Call TurnOffFunctions
Set wb = ActiveWorkbook

For Each ws In Workbooks("YOUR WORKBOOK NAMR"). _
Worksheets(Array("frontpage", "mobile"))
        ws.Copy
        Set NewBook = ActiveWorkbook
        With NewBook
            Call break_links(NewBook)
            .SaveAs Filename:="C:XXXX" & "NAME", FileFormat:=xlOpenXMLWorkbook
            .Close SaveChanges:=False
        End With
Next

Call TurnOnFunctions

End Sub
Sub break_links(ByRef wb As Workbook)
Dim Links As Variant
On Error Resume Next
Links = wb.LinkSources(Type:=xlLinkTypeExcelLinks)
On Error GoTo 0

If Not IsEmpty(Links) Then
    For i = 1 To UBound(Links)
        wb.BreakLink _
        Name:=Links(i), _
        Type:=xlLinkTypeExcelLinks
    Next i
End If

End Sub
Private Sub TurnOffFunctions()

    Application.ScreenUpdating = False
    Application.DisplayStatusBar = False
    Application.DisplayAlerts = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

End Sub
Private Sub TurnOnFunctions()

    Application.ScreenUpdating = True
    Application.DisplayStatusBar = True
    Application.DisplayAlerts = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True

End Sub
</code>```

You can use yours too with this mod (untested):

```<code>Sub SaveAsValues()
Dim ws As Worksheet

Worksheets(Array("frontpage", "mobile")).Copy After:= ws.Worksheets

Call break_links ActiveWorkbook

With ActiveWorkbook
.SaveAs Filename:= "C:XXXX" & "NAME", FileFormat:= xlOpenXMLWorkbook
.Close savechanges = False
End With
End Sub

Sub break_links(ByRef wb As Workbook)
Dim Links As Variant
On Error Resume Next
Links = wb.LinkSources(Type:=xlLinkTypeExcelLinks)
On Error GoTo 0

If Not IsEmpty(Links) Then
    For i = 1 To UBound(Links)
        wb.BreakLink _
        Name:=Links(i), _
        Type:=xlLinkTypeExcelLinks
    Next i
End If

End Sub
</code>```

Body:
I've got a workbook where I am creating a button that allows to save two specific sheets without formula's (the purpose being that the sheets are going to be send to partners and costumers). I would like the sheets to be saved in a single document somewhere on my computer, and still have the current "design" with colors, setup etc.

I've currently written this code, which does everything that I've described, except deleting the formulas...

Sub SaveAsValues()
Dim ws As Worksheet

Worksheets(Array("frontpage", "mobile")).Copy After:= ws.Worksheets

With ActiveWorkbook
.SaveAs Filename:= "C:XXXX" & "NAME", FileFormat:= xlOpenXMLWorkbook
.Close savechanges = False
End With
End Sub

Hope you can help :-)

Body:
I have a sheet I use something similar for, I'll adjust the code a bit to work with your scenario. If you don't want the settings to change, delete the TurnOnFunctions & TurnOffFunctions subs.

This code will only break the links, not necessarily all the formulas. So if a formula references another spreadsheet it will be a static value; however, if it is a simple formula that stays within the spreadsheet it will stay that way.

Also add your workbook name to the respective area.

Sub NewWorkbooks()
'This will make seperate workbooks for each of the tabs listed
Dim wb As Workbook
Dim NewBook As Workbook
Dim ws As Worksheet

Call TurnOffFunctions
Set wb = ActiveWorkbook

For Each ws In Workbooks("YOUR WORKBOOK NAMR"). _
Worksheets(Array("frontpage", "mobile"))
        ws.Copy
        Set NewBook = ActiveWorkbook
        With NewBook
            Call break_links(NewBook)
            .SaveAs Filename:="C:XXXX" & "NAME", FileFormat:=xlOpenXMLWorkbook
            .Close SaveChanges:=False
        End With
Next

Call TurnOnFunctions

End Sub
Sub break_links(ByRef wb As Workbook)
Dim Links As Variant
On Error Resume Next
Links = wb.LinkSources(Type:=xlLinkTypeExcelLinks)
On Error GoTo 0

If Not IsEmpty(Links) Then
    For i = 1 To UBound(Links)
        wb.BreakLink _
        Name:=Links(i), _
        Type:=xlLinkTypeExcelLinks
    Next i
End If

End Sub
Private Sub TurnOffFunctions()

    Application.ScreenUpdating = False
    Application.DisplayStatusBar = False
    Application.DisplayAlerts = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

End Sub
Private Sub TurnOnFunctions()

    Application.ScreenUpdating = True
    Application.DisplayStatusBar = True
    Application.DisplayAlerts = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True

End Sub

You can use yours too with this mod (untested):

Sub SaveAsValues()
Dim ws As Worksheet

Worksheets(Array("frontpage", "mobile")).Copy After:= ws.Worksheets

Call break_links ActiveWorkbook

With ActiveWorkbook
.SaveAs Filename:= "C:XXXX" & "NAME", FileFormat:= xlOpenXMLWorkbook
.Close savechanges = False
End With
End Sub

Sub break_links(ByRef wb As Workbook)
Dim Links As Variant
On Error Resume Next
Links = wb.LinkSources(Type:=xlLinkTypeExcelLinks)
On Error GoTo 0

If Not IsEmpty(Links) Then
    For i = 1 To UBound(Links)
        wb.BreakLink _
        Name:=Links(i), _
        Type:=xlLinkTypeExcelLinks
    Next i
End If

End Sub


问:
How do I take an item from an javascript array and transfer it to html in a paragraph tag?
I have an JS array panier=["Crayon Crayola"] and I want to put the item inside it into a paragraph tag
Crayon Crayola
. So how can I do this?

答:
if you have only one element in the array then you can use this(you need to give the p tag an id):

```<code>document.getElementById("p1").innerHTML = panier[0];
</code>```

if you want the whole array then use:

```<code>document.getElementById("p1").innerHTML = panier.toString();
</code>```

Body:
if you have only one element in the array then you can use this(you need to give the p tag an id):

document.getElementById("p1").innerHTML = panier[0];

if you want the whole array then use:

document.getElementById("p1").innerHTML = panier.toString();


问:
Remove last char in a string for each row in pandas df
I have a pandas dataframe with column keys, I need to remove the last character from each string.

```<code>id       keys
123      "https://www.cosmopolitan.com/entertainment/tv/a46533/"
124      "https://www.bazaar.com/entertainment/tv/a46533/"
</code>```

Currently, I am trying to create a function that would return a clean string and I would apply the function to df later. I tried the following:

```<code>url_test = "https://www.cosmopolitan.com/entertainment/tv/"

def clean_string(url):
    for string in url:
        new_string = string[:-1]
        return new_string
clean_string(url_test)
</code>```

It returns an empty string. And I want it to return "url_test = "https://www.cosmopolitan.com/entertainment/tv"

答:
Just remove the for loop, you're passing in a string, then iterating over the characters, and returning the first character without the first character, hence an empty string.

```<code>def clean_string(url):
    return url[:-1]
</code>```

Although I'm not sure you'd still need a function to do this.

If you're just trying to remove the trailing slash, you may prefer to use rstrip

```<code>return url.rstrip("/")
</code>```

Body:
I have a pandas dataframe with column keys, I need to remove the last character from each string.

id       keys
123      "https://www.cosmopolitan.com/entertainment/tv/a46533/"
124      "https://www.bazaar.com/entertainment/tv/a46533/"

Currently, I am trying to create a function that would return a clean string and I would apply the function to df later. I tried the following:

url_test = "https://www.cosmopolitan.com/entertainment/tv/"

def clean_string(url):
    for string in url:
        new_string = string[:-1]
        return new_string
clean_string(url_test)

It returns an empty string. And I want it to return "url_test = "https://www.cosmopolitan.com/entertainment/tv"

Body:
Just remove the for loop, you're passing in a string, then iterating over the characters, and returning the first character without the first character, hence an empty string.

def clean_string(url):
    return url[:-1]

Although I'm not sure you'd still need a function to do this.

If you're just trying to remove the trailing slash, you may prefer to use rstrip

return url.rstrip("/")


问:
Angular 8 - Lazy Loading of Module not working
As shown in https://stackblitz.com/edit/angular-qbbhgp, I am trying to achieve a very simple routing which involve lazy loading of module. When I click on the "link", it seems not working. I expected to see the word "Student Page" appear, but it did not happen.

Note that I would like the solution to involve the use of import api (the newer syntax to lazy load module)

答: You have to define the routes of the lazy loaded module and specify the root component of the lazy loaded module.</p>


问:
Database design for email-style application
I'm looking for some advice on how to design a database for an email-style application, specifically how to handle sending a message to multiple users, and displaying what messages were sent to what users.

This is what I have so far:

Messages (Primary Key is Id)

Id (Identity)

SenderId (Foreign Key to Users.Id)

<message data>

ReceivedMessages (Primary key is MessageId + RecipientId)

MessageId (Foreign Key to Messages.Id)

RecipientId (Foreign Key to Users.Id)

IsRead

So for every message sent, there would be one row in Messages, with the data, and then one row for each recipient in ReceivedMessages.

But what if I want to view all the messages sent by a user, and who they were sent to? For each message, I'd need to find all the ReceivedMessages rows for that message, and join all of those with the user table, and then somehow concat all the names (something like this: Concatenate many rows into a single text string?). Might this cause scaling issues, or is it not really anything to worry about?

Any thoughts/suggestions? Thanks.

答:
I see no problem with your design, and would not anticipate and scalability issues with proper indexing on your tables (unless you are talking about massive scale, e.g. gmail, Yahoo mail, etc.).

As far as concatenating the recipient names, I would recommend you do this on the application side and not in SQL, or determine whether you need to do it at all (you might want to show a list and not a concatenated string).

ContentLicense: CC BY-SA 3.0


问:
`sizeof` struct in union definition
To access a struct byte-wise, I'm using a union.

```<code>typedef struct {
    char hi;
    char lo;
} range;

union {
    range by_name;
    char as_bytes[sizeof(range)];
} U1;

char use_U1(void){
    char c = U1.as_bytes[0];
    return U1.by_name.hi;
}
</code>```

Question 1: Is it possible to skip the typedef? Like this:

```<code>union {
    struct {
        char hi;
        char lo;
    } by_name;
    char as_bytes[2]; //want sizeof()
} U2;
</code>```

A naive char as_bytes[sizeof(by_name)] doesn't compile:

error: 'by_name' undeclared here (not in a function)

Question 2: Same but with anonymous structure, to avoid typing .by_name when using.

```<code>union {
    struct {
        char hi;
        char lo;
    };
    char as_bytes[2]; //want sizeof()
} U3;

int use_U3(void){
    char c = U3.as_bytes[0];
    return U3.hi; // anonymous structure
}
</code>```

Read so far: union, struct

答:
You cannot take the size of an an anonymous type, so simply make it not anonymous:

```<code>union
{
    struct range// <<< give it a tag here
    {
        char hi;
        char lo;
    } by_name;

    char as_bytes[sizeof(struct range)]; // <<< Take sizeof here

} U2;
</code>```

You can also create a nested typedef, though it serves little purpose perhaps:

```<code>union
{
    typedef struct
    {
        char hi;
        char lo;
    } range ;

    range by_name;

    char as_bytes[sizeof(range)];
} U2;
</code>```

Title: `sizeof` struct in union definition

Body:
To access a struct byte-wise, I'm using a union.

typedef struct {
    char hi;
    char lo;
} range;

union {
    range by_name;
    char as_bytes[sizeof(range)];
} U1;

char use_U1(void){
    char c = U1.as_bytes[0];
    return U1.by_name.hi;
}

Question 1: Is it possible to skip the typedef? Like this:

union {
    struct {
        char hi;
        char lo;
    } by_name;
    char as_bytes[2]; //want sizeof()
} U2;

A naive char as_bytes[sizeof(by_name)] doesn't compile:

error: 'by_name' undeclared here (not in a function)

Question 2: Same but with anonymous structure, to avoid typing .by_name when using.

union {
    struct {
        char hi;
        char lo;
    };
    char as_bytes[2]; //want sizeof()
} U3;

int use_U3(void){
    char c = U3.as_bytes[0];
    return U3.hi; // anonymous structure
}

Read so far: union, struct

Body:
You cannot take the size of an an anonymous type, so simply make it not anonymous:

union
{
    struct range// <<< give it a tag here
    {
        char hi;
        char lo;
    } by_name;

    char as_bytes[sizeof(struct range)]; // <<< Take sizeof here

} U2;

You can also create a nested typedef, though it serves little purpose perhaps:

union
{
    typedef struct
    {
        char hi;
        char lo;
    } range ;

    range by_name;

    char as_bytes[sizeof(range)];
} U2;


问:
Python keyboard listener
I have used this code and it runs fine. However, there is something weird about it, it's like it's not Python!

The e variable in print_event is used in a way I haven't seen before. It's a regular function that prints whatever is passed to it, but the problem is how it's used, even the event variable that's supposed to be passed as an argument to the parameter e

If you don't pay attention, it seems like the append function returns added values to print_event, instead of appending them, like what the append does in Python.The whole function gets appended to the list of handlers once and then it keeps running until the program terminates,like it's a while True loop.

The code basically starts a keyboard listener and keeps recording key pressed keys, but what happens to the keys is the quesion. The for loop in low level listener doesn't make sense, why iterate through the handlers if it's supposed to record the keys, not read them. Besides, why pass the event? Handlers is a list, not a function, i'm only aware of the assignement operator for initializing variables

Also, if handlers is initialize empty, how does it assign values to items and through them if their memory space isn't allocated and doesn't exist?

I don't seeing any buffer function being called, so how's it working? Python shouldn't look like that

What i'm trying to do is to access the handlers list in real time and process the events

An explanation would be appreciated. Thanks in advance

答:
Are you asking about Function Variables?

If yes, you can pass around functions like any other variable, and call them later by a different name.

EG:

```<code>def hi(string):
    print(string)

fns = [hi, hi]

for fn in fns:
    fn('hello')
</code>```

If that remains puzzling, perhaps you could step through it with a debugger to make the idea seem more concrete.

Title: Python keyboard listener

Body:
Are you asking about Function Variables?

If yes, you can pass around functions like any other variable, and call them later by a different name.

EG:

def hi(string):
    print(string)

fns = [hi, hi]

for fn in fns:
    fn('hello')

If that remains puzzling, perhaps you could step through it with a debugger to make the idea seem more concrete.


问:
C++ initialization in template function - new Initializer expression list treated as compound expression
I am trying to initialize widgets of different types in a template function. But I am getting an error "new Initializer expression list treated as compound expression".

```<code>template <class T>
void setProperties(T &widget, QString input)
{
    widget = new T(input, view());
}
</code>```

Unfortunately couldn't find what is the error.

答:
Your signature is wrong, it should be:</p>

```<code>template <class T>
void setProperties(T*& widget, QString input)
{
    widget = new T(input, view());
}
</code>```

Body:
I am trying to initialize widgets of different types in a template function. But I am getting an error "new Initializer expression list treated as compound expression".

template <class T>
void setProperties(T &widget, QString input)
{
    widget = new T(input, view());
}

Unfortunately couldn't find what is the error.

Body:
Your signature is wrong, it should be:

template <class T>
void setProperties(T*& widget, QString input)
{
    widget = new T(input, view());
}


问:
faillock marks correct password as wrong on RHEL6
I've been having a mysterious problem of being unable to login to my root account via SSH or Console. This is a real physical machine, not a VM. Luckily I still have a sudo user to experiment with.

RHEL6

$ su root from another user works fine, so the password is correct

Login via Putty SSH does not work. Returns Access denied

Login directly via keyboard also does not work. Returns Incorrect login

My pam.d settings are set to lock accounts and I can see the locked accounts with

$ sudo failock --root.

If enter the wrong password wrong 3 times, my root will be blocked due to pam settings, and at that point, $ su root will also stop working. So I reset my blocked accounts with:

$ sudo faillock --user root reset

Looking at $ sudo failock --root, I can see the denied access being logged as I am doing them.
Trying to connect via SSH or keyboard directly with correct password also  makes a log entry

Anyway - my root account is locked somewhere and I don't know how to unlock it

Some other settings:

```<code>    $ sudo chage -l root
    Last password change                                    : Feb 14, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
</code>```

```<code>    # /etc/passwd
    root:x:0:0:root:/root:/bin/bash
</code>```

```<code>    # /etc/shadow
    root:$6$SALTSALT$HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_H:18306:0:99999:7:::
</code>```

```<code>    # /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faillock.so preauth silent even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        sufficient    pam_unix.so  try_first_pass
auth        [default=die] pam_faillock.so authfail even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_faillock.so
account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so

password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow try_first_pass use_authtok remember=5
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

</code>```

```<code>    # /etc/pam.d/password-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faillock.so preauth silent even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        sufficient    pam_unix.so nullok try_first_pass
auth        [default=die] pam_faillock.so authfail even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_faillock.so
account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so

password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
</code>```

答:
This was caused by 2 separate problems:

1

File /etc/securetty file was empty, so I added: tty1 to it.

unitstackexchange answer

2

File /etc/ssh/sshd_config had PermitRootLogin uncommented, so I commented it and restartred sshd service.

I still do have a problem, since there is a service that is creating an empty /etc/securetty file if it does not exist, but I will try to track this down eventually.

Body:
I've been having a mysterious problem of being unable to login to my root account via SSH or Console. This is a real physical machine, not a VM. Luckily I still have a sudo user to experiment with.

RHEL6

$ su root from another user works fine, so the password is correct

Login via Putty SSH does not work. Returns Access denied

Login directly via keyboard also does not work. Returns Incorrect login

My pam.d settings are set to lock accounts and I can see the locked accounts with

$ sudo failock --root.

If enter the wrong password wrong 3 times, my root will be blocked due to pam settings, and at that point, $ su root will also stop working. So I reset my blocked accounts with:

$ sudo faillock --user root reset

Looking at $ sudo failock --root, I can see the denied access being logged as I am doing them.
Trying to connect via SSH or keyboard directly with correct password also  makes a log entry

Anyway - my root account is locked somewhere and I don't know how to unlock it

Some other settings:

    $ sudo chage -l root
    Last password change                                    : Feb 14, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7

    # /etc/passwd
    root:x:0:0:root:/root:/bin/bash

    # /etc/shadow
    root:$6$SALTSALT$HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_HASH_H:18306:0:99999:7:::

    # /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faillock.so preauth silent even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        sufficient    pam_unix.so  try_first_pass
auth        [default=die] pam_faillock.so authfail even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_faillock.so
account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so

password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow try_first_pass use_authtok remember=5
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

    # /etc/pam.d/password-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faillock.so preauth silent even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        sufficient    pam_unix.so nullok try_first_pass
auth        [default=die] pam_faillock.so authfail even_deny_root deny=3 unlock_time=604800 fail_interval=900
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_faillock.so
account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so

password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so


问:
Executing gcloud command in Jenkins pipeline
I'm trying to run the gcloud command in a Jenkins declarative pipeline just like in the following example:

```<code>pipeline {
    agent any

   stages {
      stage('Run gcloud version') {

         steps {
            sh 'gcloud --version'
         }
      }
   }
}
</code>```

I downloaded the "GCloud SDK Plugin" and configured it like this (in "Global Tool Configuration" for Jenkins):

but when I try to build the pipeline using the above Jenkinsfile, I'm getting a 'gcloud: not found' error in the pipeline.

答:
I am running Jenkins 2.176.2 in containers and the GCloud plugin was not able to install the SDK in the slave (agents) containers.
I used the docker file to install it when deploying the agents: </p>

```<code>RUN echo "deb http://packages.cloud.google.com/apt cloud-sdk-stretch main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
    && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \
    && apt-get update -y && apt-get install google-cloud-sdk -y \
    && PATH=$PATH:/root/google-cloud-sdk/bin
</code>```

Body:
I'm trying to run the gcloud command in a Jenkins declarative pipeline just like in the following example:

pipeline {
    agent any

   stages {
      stage('Run gcloud version') {

         steps {
            sh 'gcloud --version'
         }
      }
   }
}

I downloaded the "GCloud SDK Plugin" and configured it like this (in "Global Tool Configuration" for Jenkins):

but when I try to build the pipeline using the above Jenkinsfile, I'm getting a 'gcloud: not found' error in the pipeline.

Body:
I am running Jenkins 2.176.2 in containers and the GCloud plugin was not able to install the SDK in the slave (agents) containers.
I used the docker file to install it when deploying the agents:

RUN echo "deb http://packages.cloud.google.com/apt cloud-sdk-stretch main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
    && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \
    && apt-get update -y && apt-get install google-cloud-sdk -y \
    && PATH=$PATH:/root/google-cloud-sdk/bin


问:
Why can an instance only be seen by main methods
```<code>public static void main(String[] args)
    {
        GUI TestGUI = new GUI();

        TestGUI.setVisible(true);
    }

    public void blahh()
    {
        TestGUI.setVisible(true);
    }
</code>```

Can not find symbol for TestGUI in blahh, but can be seen in the main method.
How can I access TestGUI from other methods?

答:
This is a scope issue. You could solve this by passing your GUI object to the blahh() method. Currently your blahh method has no way of reaching that variable.

```<code>public void blahh(GUI testGui) {
    ...
}
</code>```

You can then call this method like this:

```<code>blahh(testGui);
</code>```

Here is some reading you can do on scope, hopefully it will be helpful

Alternatively, you could declare your testGui variable as a field, and it will be accessible from anywhere in the class (make sure to make it static if you must access it in a static method). However, this will offer you less privacy with that variable even though it might seem more convenient.

Body:
public static void main(String[] args)
    {
        GUI TestGUI = new GUI();

        TestGUI.setVisible(true);
    }

    public void blahh()
    {
        TestGUI.setVisible(true);
    }

Can not find symbol for TestGUI in blahh, but can be seen in the main method.
How can I access TestGUI from other methods?

Body:
This is a scope issue. You could solve this by passing your GUI object to the blahh() method. Currently your blahh method has no way of reaching that variable.

public void blahh(GUI testGui) {
    ...
}

You can then call this method like this:

blahh(testGui);

Here is some reading you can do on scope, hopefully it will be helpful

Alternatively, you could declare your testGui variable as a field, and it will be accessible from anywhere in the class (make sure to make it static if you must access it in a static method). However, this will offer you less privacy with that variable even though it might seem more convenient.


问:
information criteria for confusion matrices
One can measure goodness of fit of a statistical model using Akaike Information Criterion (AIC), which accounts for goodness of fit and for the number of parameters that were used for model creation. AIC involves calculation of maximized value of likelihood function for that model (L).
How can one compute L, given prediction results of a classification model, represented as a confusion matrix?

答:
Information-Based Evaluation Criterion for Classifier's Performance by Kononenko and Bratko is exactly what I was looking for:

Classification accuracy is usually used as a measure of classification performance. This measure is, however, known to have several defects. A fair evaluation criterion should exclude the influence of the class probabilities which may enable a completely uninformed classifier to trivially achieve high classification accuracy. In this paper a method for evaluating the information score of a classifier''s answers is proposed. It excludes the influence of prior probabilities, deals with various types of imperfect or probabilistic answers and can be used also for comparing the performance in different domains.

OwnerDisplayName: bgbg

ContentLicense: CC BY-SA 2.5


问:
Can I modify one spreadsheet document (google sheets) based on information from a separate spreadsheet
Not sure if this is the best place to ask about spreadsheets, but here goes:

I'm trying to help someone modify information on one spreadsheet document when information on a separate spreadsheet document is modified (without coding a solution from scratch using the sheetsAPI).

For example, my client has a product database stored in a spreadsheet document, products, when a customer places an order on the clients website, a separate spreadsheet document, openOrders, is updated using the sheetsAPI and some server code. When this document is updated, I'd like to subtract the quantity of items being ordered, from the quantity of the item (or items) available being listed in products. I'm wondering if letting these spreadsheet documents "speak" to each other is possible without coding a solution server-side using the API.

products looks kind of like this:

```<code>Product Name | Units | Unit Price
---------------------------------
Product 1    |     6 |       1600
Product 2    |     3 |       1200
Product 3    |    17 |        400
Product 4    |     2 |        600
</code>```

openOrders looks kind of like this:

```<code>Product Ordered | Units | Unit Price | Total
--------------------------------------------
Product 3       |     1 |        400 |   400
Product 2       |     2 |       1200 |  2400
Product 3       |     5 |        400 |  2000
Product 1       |     1 |       1600 |  1600
</code>```

When the openOrders sheet is updated with a new order, I'd like to subtract the number of Units ordered, from the number of Units available in products. Keep in mind these are two separate spreadsheet documents. I am new to spreadsheets so this is all very foreign to me, it could be possible that I'm using the spreadsheets in a fundamentally incorrect way, and I'm open to that possibility.

答:
you can do:

```<code>=ARRAYFORMULA(QUERY({A2:A, B2:B*-1;
 IMPORTRANGE("ID_of_spreadsheet", "Sheet1!A2:B")},
 "select sum(Col2) where Col1 <> '' group by Col1 label sum(Col2)''", 0)*-1)
</code>```

Body:
Not sure if this is the best place to ask about spreadsheets, but here goes:

I'm trying to help someone modify information on one spreadsheet document when information on a separate spreadsheet document is modified (without coding a solution from scratch using the sheetsAPI).

For example, my client has a product database stored in a spreadsheet document, products, when a customer places an order on the clients website, a separate spreadsheet document, openOrders, is updated using the sheetsAPI and some server code. When this document is updated, I'd like to subtract the quantity of items being ordered, from the quantity of the item (or items) available being listed in products. I'm wondering if letting these spreadsheet documents "speak" to each other is possible without coding a solution server-side using the API.

products looks kind of like this:

Product Name | Units | Unit Price
---------------------------------
Product 1    |     6 |       1600
Product 2    |     3 |       1200
Product 3    |    17 |        400
Product 4    |     2 |        600

openOrders looks kind of like this:

Product Ordered | Units | Unit Price | Total
--------------------------------------------
Product 3       |     1 |        400 |   400
Product 2       |     2 |       1200 |  2400
Product 3       |     5 |        400 |  2000
Product 1       |     1 |       1600 |  1600

When the openOrders sheet is updated with a new order, I'd like to subtract the number of Units ordered, from the number of Units available in products. Keep in mind these are two separate spreadsheet documents. I am new to spreadsheets so this is all very foreign to me, it could be possible that I'm using the spreadsheets in a fundamentally incorrect way, and I'm open to that possibility.

Body:
you can do:

=ARRAYFORMULA(QUERY({A2:A, B2:B*-1;
 IMPORTRANGE("ID_of_spreadsheet", "Sheet1!A2:B")},
 "select sum(Col2) where Col1 <> '' group by Col1 label sum(Col2)''", 0)*-1)


问:
Vue transitions do not work for router-view with reusable component
So I created component which in which I placed router-view only and based on the routes the component changes. Worth noting is that this is second router-view and the first one is placed in the App.vue component and transition work with that work (they work for all routes except those that are containted with the component below)

MainComponent.vue

```<code><template>
<transition name="fade" mode="out-in">
     <router-view></router-view>
</transition>
</template>

<style>
.fade-enter-active, .fade-leave-active {
  transition-property: opacity;
  transition-duration: .25s;
}

.fade-enter-active {
  transition-delay: .25s;
}

.fade-enter, .fade-leave-active {
  opacity: 0
}
</style>
</code>```

Here is the route setup.

```<code>{
    path: '/main',
    name: 'main',
    component: () => import('../views/MainComponent.vue'),
    children: [
      {

        path: 'first',
        name: 'first',
        props: { titleName: "First",},
        component: () => import('../components/Component.vue')
      },
      {

        path: 'second',
        name: 'second',
        props: { titleName: "Second"},
        component: () => import('../components/Component.vue')
      },
      {

        path: 'third',
        name: 'third',
        props: { titleName: "Third"},
        component: () => import('../components/Component.vue')
      }
   ]
  }
</code>```

Is there a special setup needed for the transitions to work with reusable component in <router-view>?

答:
When you enter a route whose component you are already viewing, by default the component is reused, so there is no DOM transition triggered.  Change your router-view to:

<router-view :key="$route.fullPath" />
```

The key attribute tells Vue to use a different instance of the component (instead of reusing the existing one) any time the key value changes.  With $route.fullPath, that will be every time the route changes.

Body:
So I created component which in which I placed router-view only and based on the routes the component changes. Worth noting is that this is second router-view and the first one is placed in the App.vue component and transition work with that work (they work for all routes except those that are containted with the component below)

MainComponent.vue

<template>
<transition name="fade" mode="out-in">
     <router-view></router-view>
</transition>
</template>

Here is the route setup.

{
    path: '/main',
    name: 'main',
    component: () => import('../views/MainComponent.vue'),
    children: [
      {

        path: 'first',
        name: 'first',
        props: { titleName: "First",},
        component: () => import('../components/Component.vue')
      },
      {

        path: 'second',
        name: 'second',
        props: { titleName: "Second"},
        component: () => import('../components/Component.vue')
      },
      {

        path: 'third',
        name: 'third',
        props: { titleName: "Third"},
        component: () => import('../components/Component.vue')
      }
   ]
  }

Is there a special setup needed for the transitions to work with reusable component in <router-view>?

Body:
When you enter a route whose component you are already viewing, by default the component is reused, so there is no DOM transition triggered.  Change your router-view to:

<router-view :key="$route.fullPath" />

The key attribute tells Vue to use a different instance of the component (instead of reusing the existing one) any time the key value changes.  With $route.fullPath, that will be every time the route changes.


问:
Mysql accepts Zero month in date column!? Please explain
MySQL 5.6 - we had a talk with one of the developers and found something very curious - couldn't find anything about it in google:

```<code>create temporary table md (dates date);
insert into md select '2000-01-01'; -- result: 2000-01-01
insert into md select '2000-00-01'; -- result: 1999-12-01 ????
insert into md select '2000-00-00'; -- result: 1999-11-30 ????
insert into md select '2000-01-00'; -- result: 1999-12-31 ????
insert into md select '2000-13-01'; -- result: EXPECTED: SQL Error [1292] [22001]: Data truncation: Incorrect date value: '2000-13-01' for column 'dates' at row 1
insert into md select '2000-12-49'; -- result: EXPECTED: SQL Error [1292] [22001]: Data truncation: Incorrect date value: '2000-12-49' for column 'dates' at row 1
</code>```

Could someone please explain?

Why does it let this happen? It should throw the same Data issue error imho.

Documentation?

What is the exact logic behind this?

a) Month 00 previous month same day?

b) Day 00 previous month last day?

c) both 00-00 previous month's previous' last day?

Thanks!

答:
https://dev.mysql.com/doc/refman/8.0/en/using-date.html

MySQL permits you to store dates where the day or month and day are zero. This is convenient if you want to store a birthdate in a DATE column and you know only part of the date. To disallow zero month or day parts in dates, enable the NO_ZERO_IN_DATE mode.

Body:
MySQL 5.6 - we had a talk with one of the developers and found something very curious - couldn't find anything about it in google:

create temporary table md (dates date);
insert into md select '2000-01-01'; -- result: 2000-01-01
insert into md select '2000-00-01'; -- result: 1999-12-01 ????
insert into md select '2000-00-00'; -- result: 1999-11-30 ????
insert into md select '2000-01-00'; -- result: 1999-12-31 ????
insert into md select '2000-13-01'; -- result: EXPECTED: SQL Error [1292] [22001]: Data truncation: Incorrect date value: '2000-13-01' for column 'dates' at row 1
insert into md select '2000-12-49'; -- result: EXPECTED: SQL Error [1292] [22001]: Data truncation: Incorrect date value: '2000-12-49' for column 'dates' at row 1

Could someone please explain?

Why does it let this happen? It should throw the same Data issue error imho.

Documentation?

What is the exact logic behind this?

a) Month 00 previous month same day?

b) Day 00 previous month last day?

c) both 00-00 previous month's previous' last day?

Thanks!


问:
Use local docker image without registry setup in k8s
I've set up single node kubernetes  according to official tutorial.

In addition to official documentation I've set-up single node cluster:

```<code>kubectl taint nodes --all node-role.kubernetes.io/master-
</code>```

Disabled eviction limit:

```<code>cat << EOF >> /var/lib/kubelet/config.yaml
evictionHard:
  imagefs.available: 1%
  memory.available: 100Mi
  nodefs.available: 1%
  nodefs.inodesFree: 1%
EOF

systemctl daemon-reload
systemctl restart kubelet
</code>```

And set systemd driver for Docker:

```<code>cat << EOF > /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

systemctl daemon-reload
systemctl restart docker
</code>```

I've tried following:

```<code>docker build -t localhost:5000/my-image .
kubectl run -it --rm --restart=Always --image=localhost:5000/my-image my-image
</code>```

But in pod logs I see ImagePullBackOff. If I setup local repository and I do docker push localhost:5000/my-image after I build image, then everything is working.

Is it is possible to use local images (which are already available after issuing docker images) without needing to setting up local repository, pushing to this repository and then pulling from it?

答:
You simply need to set the imagePullPolicy in your Pod template in the container specification to Never. Otherwise the kubelet will try to pull the image. The example Pod definition may look like this:

```<code>apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
    - name: uses-local-image
      image: local-image-name
      imagePullPolicy: Never
</code>```

More on that you can find here.

By default, the kubelet will try to pull each image from the specified
  registry. However, if the  imagePullPolicy  property of the
  container is set to  IfNotPresent  or  Never, then a local image
  is used (preferentially or exclusively, respectively).

If you want to rely on pre-pulled images as a substitute for registry
  authentication, you must ensure all nodes in the cluster have the same
  pre-pulled images.

This can be used to preload certain images for speed or as an
  alternative to authenticating to a private registry.

All pods will have read access to any pre-pulled images.

Body:
I've set up single node kubernetes  according to official tutorial.

In addition to official documentation I've set-up single node cluster:

kubectl taint nodes --all node-role.kubernetes.io/master-

Disabled eviction limit:

cat << EOF >> /var/lib/kubelet/config.yaml
evictionHard:
  imagefs.available: 1%
  memory.available: 100Mi
  nodefs.available: 1%
  nodefs.inodesFree: 1%
EOF

systemctl daemon-reload
systemctl restart kubelet

And set systemd driver for Docker:

cat << EOF > /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

systemctl daemon-reload
systemctl restart docker

I've tried following:

docker build -t localhost:5000/my-image .
kubectl run -it --rm --restart=Always --image=localhost:5000/my-image my-image

But in pod logs I see ImagePullBackOff. If I setup local repository and I do docker push localhost:5000/my-image after I build image, then everything is working.

Is it is possible to use local images (which are already available after issuing docker images) without needing to setting up local repository, pushing to this repository and then pulling from it?

Body:
You simply need to set the imagePullPolicy in your Pod template in the container specification to Never. Otherwise the kubelet will try to pull the image. The example Pod definition may look like this:

apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
    - name: uses-local-image
      image: local-image-name
      imagePullPolicy: Never

More on that you can find here.

By default, the kubelet will try to pull each image from the specified
  registry. However, if the  imagePullPolicy  property of the
  container is set to  IfNotPresent  or  Never, then a local image
  is used (preferentially or exclusively, respectively).

If you want to rely on pre-pulled images as a substitute for registry
  authentication, you must ensure all nodes in the cluster have the same
  pre-pulled images.

This can be used to preload certain images for speed or as an
  alternative to authenticating to a private registry.

All pods will have read access to any pre-pulled images.