问:
Unable to crawl multiple pages
I am trying to crawl quotes, author names and tags from goodreads. I am able to crawl single page with following code

```<code>import scrapy

class goodReadsSpider(scrapy.Spider):
#identity
name='goodreads'

#requests
def start_requests(self):
    url = 'https://www.goodreads.com/quotes?page=1'
    yield scrapy.Request(url=url,callback=self.parse)

#reponse
def parse(self,response):
   for quote in response.selector.xpath('//div[@class="quote"]'):
    yield{
        'text':quote.xpath('.//div[@class = "quoteText"]/text()[1]').extract(),
        'author':quote.xpath('.//span[@class = "authorOrTitle"]').extract_first(),
        'tags':quote.xpath('.//div[@class="greyText smallText left"]/a/text()').extract()
    }
</code>```

but when I try to crawl same spider with addition of following code

```<code> next_page = response.selector.xpath('//a[@class = "next_page"/@href').extract()

 if next_page is not None:
           next_page_link = response.urljoin(next_page)
           yield scrapy.request(url=next_page_link, callback=self.parse)
</code>```

I get the following error.

2019-05-29 10:47:14 [scrapy.core.engine] INFO: Spider opened

  2019-05-29 10:47:14 [scrapy.extensions.logstats] INFO: Crawled 0 pages
  (at 0 pages/min), scraped 0 items (at 0 items/min)   2019-05-29
  10:47:14 [scrapy.extensions.telnet] INFO: Telnet console listening on
  127.0.0.1:6023   2019-05-29 10:47:15 [scrapy.core.engine] DEBUG: Crawled (200) https://www.goodreads.com/robots.txt> (referer:
  None)   2019-05-29 10:47:16 [scrapy.core.engine] DEBUG: Crawled (200)
  https://www.goodreads.com/quotes?page=1> (referer: None)

  2019-05-29 10:47:16 [scrapy.core.scraper] DEBUG: Scraped from <200
  https://www.goodreads.com/quotes?page=1>   {'text': ["\n      “Don't
  cry because it's over, smile because it happened.”\n  "], 'author':
  '\n    Dr. Seuss\n  ', 'tags':
  ['attributed-no-source', 'cry', 'crying', 'experience', 'happiness',
  'joy', 'life', 'misattributed-dr-seuss', 'optimism', 'sadness',
  'smile', 'smiling']}   2019-05-29 10:47:16 [scrapy.core.scraper]
  ERROR: Spider error processing https://www.goodreads.com/quotes?page=1> (referer: None)   Traceback
  (most recent call last):     File
  "c:\programdata\anaconda3\lib\site-packages\parsel\selector.py", line
  238, in xpath

      **kwargs)     File "src/lxml/etree.pyx", line 1586, in lxml.etree._Element.xpath     File "src/lxml/xpath.pxi", line 307, in
  lxml.etree.XPathElementEvaluator.call     File
  "src/lxml/xpath.pxi", line 227, in
  lxml.etree._XPathEvaluatorBase._handle_result

  lxml.etree.XPathEvalError: Invalid predicate

During handling of the above exception, another exception occurred:

Traceback (most recent call last):     File
  "c:\programdata\anaconda3\lib\site-packages\scrapy\utils\defer.py",
  line 102, in iter_errback

      yield next(it)     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\offsite.py",
  line 29, in process_spider_output

      for x in result:     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\referer.py",
  line 339, in

      return (_set_referer(r) for r in result or ())     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\urllength.py",
  line 37, in

      return (r for r in result or () if _filter(r))     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\depth.py",
  line 58, in

      return (r for r in result or () if _filter(r))     File "C:\Users\Zona\Documents\Visual\demo_project\demo_project\spiders\goodreads.py",
  line 23, in parse

      next_page = response.selector.xpath('//a[@class = "next_page"/@href').extract()     File
  "c:\programdata\anaconda3\lib\site-packages\parsel\selector.py", line
  242, in xpath

      six.reraise(ValueError, ValueError(msg), sys.exc_info()[2])     File "c:\programdata\anaconda3\lib\site-packages\six.py", line 692, in
  reraise

      raise value.with_traceback(tb)     File "c:\programdata\anaconda3\lib\site-packages\parsel\selector.py", line
  238, in xpath

      **kwargs)     File "src/lxml/etree.pyx", line 1586, in lxml.etree._Element.xpath     File "src/lxml/xpath.pxi", line 307, in
  lxml.etree.XPathElementEvaluator.call     File
  "src/lxml/xpath.pxi", line 227, in
  lxml.etree._XPathEvaluatorBase._handle_result   ValueError: XPath
  error: Invalid predicate in //a[@class = "next_page"/@href

  2019-05-29 10:47:16 [scrapy.core.engine] INFO: Closing spider
  (finished)   2019-05-29 10:47:16 [scrapy.statscollectors] INFO:
  Dumping Scrapy stats:   {'downloader/request_bytes': 621,

  'downloader/request_count': 2,

  'downloader/request_method_count/GET': 2,

  'downloader/response_bytes': 29812,    'downloader/response_count': 2,
  'downloader/response_status_count/200': 2,    'finish_reason':
  'finished',    'finish_time': datetime.datetime(2019, 5, 29, 5, 47,
  16, 767370),    'item_scraped_count': 1,    'log_count/DEBUG': 3,

  'log_count/ERROR': 1,    'log_count/INFO': 9,

  'response_received_count': 2,    'robotstxt/request_count': 1,

  'robotstxt/response_count': 1,

  'robotstxt/response_status_count/200': 1,    'scheduler/dequeued': 1,
  'scheduler/dequeued/memory': 1,    'scheduler/enqueued': 1,

  'scheduler/enqueued/memory': 1,    'spider_exceptions/ValueError': 1,
  'start_time': datetime.datetime(2019, 5, 29, 5, 47, 14, 108786)}

  2019-05-29 10:47:16 [scrapy.core.engine] INFO: Spider closed
  (finished)

I am not sure that the problem is with xpath because in first attempt I get

'item_scraped_count': 30

but in here it is 1, which means spider isn't crawling even first page.

答:
You have to fix two issues to get your next page link working. Other than what @pako pointed out, you could have used .extract_first() or .get() to get the first item of an array. Rectified one should be more like .xpath('//a[@class="next_page"]/@href').get(). I've rewritten some of your xpaths to kick out whitespaces from the output.

```<code>class goodReadsSpider(scrapy.Spider):
    name='goodreads'

    start_urls = ['https://www.goodreads.com/quotes?page=1']

    def parse(self,response):
        for quote in response.xpath('//div[@class="quote"]'):
            yield {
                'text':quote.xpath('normalize-space(.//div[@class="quoteText"]/text())').getall(),
                'author':quote.xpath('normalize-space(.//span[@class="authorOrTitle"]/text())').get(),
                'tags':quote.xpath('.//div[contains(@class,"greyText")]/a/text()').getall()
            }

        next_page = response.xpath('//a[@class="next_page"]/@href').get()
        if next_page:
            nlink = response.urljoin(next_page)
            yield scrapy.Request(url=nlink,callback=self.parse)
</code>```

Title: Unable to crawl multiple pages

Body:
I am trying to crawl quotes, author names and tags from goodreads. I am able to crawl single page with following code

import scrapy

class goodReadsSpider(scrapy.Spider):
#identity
name='goodreads'

#requests
def start_requests(self):
    url = 'https://www.goodreads.com/quotes?page=1'
    yield scrapy.Request(url=url,callback=self.parse)

#reponse
def parse(self,response):
   for quote in response.selector.xpath('//div[@class="quote"]'):
    yield{
        'text':quote.xpath('.//div[@class = "quoteText"]/text()[1]').extract(),
        'author':quote.xpath('.//span[@class = "authorOrTitle"]').extract_first(),
        'tags':quote.xpath('.//div[@class="greyText smallText left"]/a/text()').extract()
    }

but when I try to crawl same spider with addition of following code

 next_page = response.selector.xpath('//a[@class = "next_page"/@href').extract()

 if next_page is not None:
           next_page_link = response.urljoin(next_page)
           yield scrapy.request(url=next_page_link, callback=self.parse)

I get the following error.

2019-05-29 10:47:14 [scrapy.core.engine] INFO: Spider opened

  2019-05-29 10:47:14 [scrapy.extensions.logstats] INFO: Crawled 0 pages
  (at 0 pages/min), scraped 0 items (at 0 items/min)   2019-05-29
  10:47:14 [scrapy.extensions.telnet] INFO: Telnet console listening on
  127.0.0.1:6023   2019-05-29 10:47:15 [scrapy.core.engine] DEBUG: Crawled (200) https://www.goodreads.com/robots.txt> (referer:
  None)   2019-05-29 10:47:16 [scrapy.core.engine] DEBUG: Crawled (200)
  https://www.goodreads.com/quotes?page=1> (referer: None)

  2019-05-29 10:47:16 [scrapy.core.scraper] DEBUG: Scraped from <200
  https://www.goodreads.com/quotes?page=1>   {'text': ["\n      “Don't
  cry because it's over, smile because it happened.”\n  "], 'author':
  '\n    Dr. Seuss\n  ', 'tags':
  ['attributed-no-source', 'cry', 'crying', 'experience', 'happiness',
  'joy', 'life', 'misattributed-dr-seuss', 'optimism', 'sadness',
  'smile', 'smiling']}   2019-05-29 10:47:16 [scrapy.core.scraper]
  ERROR: Spider error processing https://www.goodreads.com/quotes?page=1> (referer: None)   Traceback
  (most recent call last):     File
  "c:\programdata\anaconda3\lib\site-packages\parsel\selector.py", line
  238, in xpath

      **kwargs)     File "src/lxml/etree.pyx", line 1586, in lxml.etree._Element.xpath     File "src/lxml/xpath.pxi", line 307, in
  lxml.etree.XPathElementEvaluator.call     File
  "src/lxml/xpath.pxi", line 227, in
  lxml.etree._XPathEvaluatorBase._handle_result

  lxml.etree.XPathEvalError: Invalid predicate

During handling of the above exception, another exception occurred:

Traceback (most recent call last):     File
  "c:\programdata\anaconda3\lib\site-packages\scrapy\utils\defer.py",
  line 102, in iter_errback

      yield next(it)     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\offsite.py",
  line 29, in process_spider_output

      for x in result:     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\referer.py",
  line 339, in

      return (_set_referer(r) for r in result or ())     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\urllength.py",
  line 37, in

      return (r for r in result or () if _filter(r))     File "c:\programdata\anaconda3\lib\site-packages\scrapy\spidermiddlewares\depth.py",
  line 58, in

      return (r for r in result or () if _filter(r))     File "C:\Users\Zona\Documents\Visual\demo_project\demo_project\spiders\goodreads.py",
  line 23, in parse

      next_page = response.selector.xpath('//a[@class = "next_page"/@href').extract()     File
  "c:\programdata\anaconda3\lib\site-packages\parsel\selector.py", line
  242, in xpath

      six.reraise(ValueError, ValueError(msg), sys.exc_info()[2])     File "c:\programdata\anaconda3\lib\site-packages\six.py", line 692, in
  reraise

      raise value.with_traceback(tb)     File "c:\programdata\anaconda3\lib\site-packages\parsel\selector.py", line
  238, in xpath

      **kwargs)     File "src/lxml/etree.pyx", line 1586, in lxml.etree._Element.xpath     File "src/lxml/xpath.pxi", line 307, in
  lxml.etree.XPathElementEvaluator.call     File
  "src/lxml/xpath.pxi", line 227, in
  lxml.etree._XPathEvaluatorBase._handle_result   ValueError: XPath
  error: Invalid predicate in //a[@class = "next_page"/@href

  2019-05-29 10:47:16 [scrapy.core.engine] INFO: Closing spider
  (finished)   2019-05-29 10:47:16 [scrapy.statscollectors] INFO:
  Dumping Scrapy stats:   {'downloader/request_bytes': 621,

  'downloader/request_count': 2,

  'downloader/request_method_count/GET': 2,

  'downloader/response_bytes': 29812,    'downloader/response_count': 2,
  'downloader/response_status_count/200': 2,    'finish_reason':
  'finished',    'finish_time': datetime.datetime(2019, 5, 29, 5, 47,
  16, 767370),    'item_scraped_count': 1,    'log_count/DEBUG': 3,

  'log_count/ERROR': 1,    'log_count/INFO': 9,

  'response_received_count': 2,    'robotstxt/request_count': 1,

  'robotstxt/response_count': 1,

  'robotstxt/response_status_count/200': 1,    'scheduler/dequeued': 1,
  'scheduler/dequeued/memory': 1,    'scheduler/enqueued': 1,

  'scheduler/enqueued/memory': 1,    'spider_exceptions/ValueError': 1,
  'start_time': datetime.datetime(2019, 5, 29, 5, 47, 14, 108786)}

  2019-05-29 10:47:16 [scrapy.core.engine] INFO: Spider closed
  (finished)

I am not sure that the problem is with xpath because in first attempt I get

'item_scraped_count': 30

but in here it is 1, which means spider isn't crawling even first page.

Body:
You have to fix two issues to get your next page link working. Other than what @pako pointed out, you could have used .extract_first() or .get() to get the first item of an array. Rectified one should be more like .xpath('//a[@class="next_page"]/@href').get(). I've rewritten some of your xpaths to kick out whitespaces from the output.

class goodReadsSpider(scrapy.Spider):
    name='goodreads'

    start_urls = ['https://www.goodreads.com/quotes?page=1']

    def parse(self,response):
        for quote in response.xpath('//div[@class="quote"]'):
            yield {
                'text':quote.xpath('normalize-space(.//div[@class="quoteText"]/text())').getall(),
                'author':quote.xpath('normalize-space(.//span[@class="authorOrTitle"]/text())').get(),
                'tags':quote.xpath('.//div[contains(@class,"greyText")]/a/text()').getall()
            }

        next_page = response.xpath('//a[@class="next_page"]/@href').get()
        if next_page:
            nlink = response.urljoin(next_page)
            yield scrapy.Request(url=nlink,callback=self.parse)


来源: stackexchange

问:
Problem with custom link cursor in Chrome
I want to use a custom cursor on hover for links. It works fine on Safari and Firefox, but on Chrome it jumps back to the default cursor for a millisecond, and then goes to my custom cursor.

Codepen: https://codepen.io/ford1234/pen/vwzRgJ

I've recreated the problem in Codepen but it also happens on the site I'm applying it to.

```<code><div>
  <a href="#"><p>Hello</p></a>
</div>

<style>
html {
    cursor: url('http://telephoneavenue.art/wp-content/uploads/2019/02/black-01.png'), auto;
}

a:hover {
    cursor: url('http://telephoneavenue.art/wp-content/uploads/2019/05/blacktriangle-small17px.png'), auto;
</code>```

}

Expected result: A transition from the circle to the triangle.
Actual result: A transition from the circle, to the default hand pointer, to the triangle.

答:
remove ":hover" on your selector.
your selector must be;

a{
      cursor: url('http://telephoneavenue.art/wp-content/uploads/2019/05/blacktriangle-small17px.png'),
  auto; }

ContentLicense: CC BY-SA 4.0

Body:
I want to use a custom cursor on hover for links. It works fine on Safari and Firefox, but on Chrome it jumps back to the default cursor for a millisecond, and then goes to my custom cursor.

Codepen: https://codepen.io/ford1234/pen/vwzRgJ

I've recreated the problem in Codepen but it also happens on the site I'm applying it to.

Hello


问:
map function returns item even if condition is not true
Here's my code:

```<code>//input = aaaaaaa,                ddd,            ,
 asdsad,

newUser =
users
  .split(',')
  .map(item => {
    item = item.trim();
    if(item.length > 0) {
      return item;
    }
}).join();

//output = aaaaaaa,ddd,,asdsad,
</code>```

So my question is why if item has 0 length is returned from map function? Am I missing something obvious?

//EDIT:

Yeah, now its removoing empty strings but what about white spaces? My result still looks like this:

asdasdasd      ,       aa

I want to have:

asdasdasd,aa

答:
You can use String replace and regex to remove all white space

let input = 'aaaaaaa,                ddd,            ,    asdsad,';
let newData = input.replace(/ /g, '');;
console.log(newData)```
</div>
</div>
</p>

<p>Alternatively you can use reduce function. Inside reduce callback check the the length of the string and if condition satisfies then push it with the accumulator. Finally use <code>join</code> to cancat using <code>,</code> delimiter</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>let users = " aaaaaaa,                ddd,            ,   asdsad"
let newUser = users.split(',')
  .reduce(function(acc, curr) {
    if (curr.trim().length > 0) {
      acc .push(curr.trim());
    }
    return acc;
  },[]).join(',')
console.log(newUser)</code>```

Body:
Here's my code:

//input = aaaaaaa,                ddd,            ,
 asdsad,

newUser =
users
  .split(',')
  .map(item => {
    item = item.trim();
    if(item.length > 0) {
      return item;
    }
}).join();

//output = aaaaaaa,ddd,,asdsad,

So my question is why if item has 0 length is returned from map function? Am I missing something obvious?

//EDIT:

Yeah, now its removoing empty strings but what about white spaces? My result still looks like this:

asdasdasd      ,       aa

I want to have:

asdasdasd,aa

Body:
You can use String replace and regex to remove all white space

let input = 'aaaaaaa,                ddd,            ,    asdsad,';
let newData = input.replace(/ /g, '');;
console.log(newData)

Alternatively you can use reduce function. Inside reduce callback check the the length of the string and if condition satisfies then push it with the accumulator. Finally use join to cancat using , delimiter

let users = " aaaaaaa,                ddd,            ,   asdsad"
let newUser = users.split(',')
  .reduce(function(acc, curr) {
    if (curr.trim().length > 0) {
      acc .push(curr.trim());
    }
    return acc;
  },[]).join(',')
console.log(newUser)


问:
Admob GDPR consent dialog is popup every time came back to EU?
i am facing weird behaviour with Admob consent dialog ,everytime i travel back to UK after few days outside the country the GPDR admob dialog is popup again i have to give my consent again .

below is the code i am using :

```<code>   // PACConsentInformation.sharedInstance.debugGeography   = .EEA;
    PACConsentInformation.sharedInstance.requestConsentInfoUpdate( forPublisherIdentifiers: ["pub-XXXXX"])
    {(_ error: Error?) -> Void in

        if let error = error
        {
            print("[GDPR][CHECK] Error updateing \(error)")
        } else
        {
            print("[GDPR][CHECK] Updated")

            let status =  PACConsentInformation.sharedInstance.consentStatus

            if status == PACConsentStatus.personalized
            {
                print("[GDPR][CHECK] User selected personalized")
                user_info().set(key: user.gdpr_nonPersonalized, value: false)
            }else
            if status == PACConsentStatus.nonPersonalized
            {
                print("[GDPR][CHECK] User selected none-personalized")
                user_info().set(key: user.gdpr_nonPersonalized, value: true)
            }else
            //unknown !!
            if status == PACConsentStatus.unknown && PACConsentInformation.sharedInstance.isRequestLocationInEEAOrUnknown == true
            {
                print("[GDPR][CHECK] unkown !")
                APP_DELEGATE.showGDPRDialog(from: self)
            }else
            {
               print("[GDPR][CHECK] unkown ! user outside EU" )
               user_info().set(key: user.gdpr_nonPersonalized, value: false)
            }
        }
    }

//[GDPR] Dialog
    func showGDPRDialog( from:UIViewController)
    {

        guard let privacyUrl = URL(string: "http://xx/privacy-policy"),
            let form = PACConsentForm(applicationPrivacyPolicyURL: privacyUrl) else {
                print("[GDPR] incorrect privacy URL.")
                return
        }

        form.shouldOfferPersonalizedAds    = true
        form.shouldOfferNonPersonalizedAds = true
        form.shouldOfferAdFree             = false

        form.load {(_ error: Error?) -> Void in

            print("[GDPR] FORM Load complete.")

            if let error = error {
                // Handle error.
                print("[GDPR] FORM Error loading form: \(error.localizedDescription)")
            } else
            {
                print("[GDPR] success will present.")

                // Load successful.
                user_info().set(key: user.gdpr_dialog_showed, value: true)

                form.present(from: from) { (error, userPrefersAdFree) in

                    APP_DELEGATE.logEvent("opened_gdpr", [ : ]);

                    if let error = error
                    {
                        // Handle error.
                        print("[GDPR] ERROR while present \(error)")
                    } else if userPrefersAdFree
                    {
                        // User prefers to use a paid version of the app.
                    } else
                    {

                        ALPrivacySettings.setHasUserConsent(true)

                        // Check the user's consent choice.
                        let status =  PACConsentInformation.sharedInstance.consentStatus

                        if status == PACConsentStatus.personalized
                        {

                            print("[GDPR] User selected personalized")
                            user_info().set(key: user.gdpr_nonPersonalized, value: false)
                            PACConsentInformation.sharedInstance.consentStatus = .personalized
                        }else
                        if status == PACConsentStatus.nonPersonalized
                        {

                            print("[GDPR] User selected none-personalized")
                            user_info().set(key: user.gdpr_nonPersonalized, value: true)
                            PACConsentInformation.sharedInstance.consentStatus = .nonPersonalized
                        }else
                        {

                        }

                    }
                }
            }
        }
    }
</code>```

is this normal ? what is the showcases of GDPR consent dialog !

答:
Only display consent form if the following equals true</p>

```<code>requestLocationInEEAOrUnknown
</code>```

Body:
i am facing weird behaviour with Admob consent dialog ,everytime i travel back to UK after few days outside the country the GPDR admob dialog is popup again i have to give my consent again .

below is the code i am using :

   // PACConsentInformation.sharedInstance.debugGeography   = .EEA;
    PACConsentInformation.sharedInstance.requestConsentInfoUpdate( forPublisherIdentifiers: ["pub-XXXXX"])
    {(_ error: Error?) -> Void in

        if let error = error
        {
            print("[GDPR][CHECK] Error updateing \(error)")
        } else
        {
            print("[GDPR][CHECK] Updated")

            let status =  PACConsentInformation.sharedInstance.consentStatus

            if status == PACConsentStatus.personalized
            {
                print("[GDPR][CHECK] User selected personalized")
                user_info().set(key: user.gdpr_nonPersonalized, value: false)
            }else
            if status == PACConsentStatus.nonPersonalized
            {
                print("[GDPR][CHECK] User selected none-personalized")
                user_info().set(key: user.gdpr_nonPersonalized, value: true)
            }else
            //unknown !!
            if status == PACConsentStatus.unknown && PACConsentInformation.sharedInstance.isRequestLocationInEEAOrUnknown == true
            {
                print("[GDPR][CHECK] unkown !")
                APP_DELEGATE.showGDPRDialog(from: self)
            }else
            {
               print("[GDPR][CHECK] unkown ! user outside EU" )
               user_info().set(key: user.gdpr_nonPersonalized, value: false)
            }
        }
    }

//[GDPR] Dialog
    func showGDPRDialog( from:UIViewController)
    {

        guard let privacyUrl = URL(string: "http://xx/privacy-policy"),
            let form = PACConsentForm(applicationPrivacyPolicyURL: privacyUrl) else {
                print("[GDPR] incorrect privacy URL.")
                return
        }

        form.shouldOfferPersonalizedAds    = true
        form.shouldOfferNonPersonalizedAds = true
        form.shouldOfferAdFree             = false

        form.load {(_ error: Error?) -> Void in

            print("[GDPR] FORM Load complete.")

            if let error = error {
                // Handle error.
                print("[GDPR] FORM Error loading form: \(error.localizedDescription)")
            } else
            {
                print("[GDPR] success will present.")

                // Load successful.
                user_info().set(key: user.gdpr_dialog_showed, value: true)

                form.present(from: from) { (error, userPrefersAdFree) in

                    APP_DELEGATE.logEvent("opened_gdpr", [ : ]);

                    if let error = error
                    {
                        // Handle error.
                        print("[GDPR] ERROR while present \(error)")
                    } else if userPrefersAdFree
                    {
                        // User prefers to use a paid version of the app.
                    } else
                    {

                        ALPrivacySettings.setHasUserConsent(true)

                        // Check the user's consent choice.
                        let status =  PACConsentInformation.sharedInstance.consentStatus

                        if status == PACConsentStatus.personalized
                        {

                            print("[GDPR] User selected personalized")
                            user_info().set(key: user.gdpr_nonPersonalized, value: false)
                            PACConsentInformation.sharedInstance.consentStatus = .personalized
                        }else
                        if status == PACConsentStatus.nonPersonalized
                        {

                            print("[GDPR] User selected none-personalized")
                            user_info().set(key: user.gdpr_nonPersonalized, value: true)
                            PACConsentInformation.sharedInstance.consentStatus = .nonPersonalized
                        }else
                        {

                        }

                    }
                }
            }
        }
    }

is this normal ? what is the showcases of GDPR consent dialog !

Body:
Only display consent form if the following equals true

requestLocationInEEAOrUnknown


问:
Jackson enum Serializing and DeSerializer
I'm using JAVA 1.6 and Jackson 1.9.9 I've got an enum

```<code>public enum Event {
    FORGOT_PASSWORD("forgot password");

    private final String value;

    private Event(final String description) {
        this.value = description;
    }

    @JsonValue
    final String value() {
        return this.value;
    }
}
</code>```

I've added a @JsonValue, this seems to do the job it serializes the object into:

```<code>{"event":"forgot password"}
</code>```

but when I try to deserialize I get a

```<code>Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.globalrelay.gas.appsjson.authportal.Event from String value 'forgot password': value not one of declared Enum instance names
</code>```

What am I missing here?

答:
The simplest way I found is using @JsonFormat.Shape.OBJECT annotation for the enum.</p>

```<code>@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum MyEnum{
    ....
}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I'm using JAVA 1.6 and Jackson 1.9.9 I've got an enum

public enum Event {
    FORGOT_PASSWORD("forgot password");

    private final String value;

    private Event(final String description) {
        this.value = description;
    }

    @JsonValue
    final String value() {
        return this.value;
    }
}

I've added a @JsonValue, this seems to do the job it serializes the object into:

{"event":"forgot password"}

but when I try to deserialize I get a

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.globalrelay.gas.appsjson.authportal.Event from String value 'forgot password': value not one of declared Enum instance names

What am I missing here?

Body:
The simplest way I found is using @JsonFormat.Shape.OBJECT annotation for the enum.

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum MyEnum{
    ....
}


问:
Object: null prototype does not allow to retrieve a value
I'm getting this error when trying to compare passwords

UnhandledPromiseRejectionWarning: Error: data and hash arguments
  required

the thing is user.password returns undefined, but when i do console.log(user) it returns the model

Like this

```<code>ModelBase {
  attributes:
   [Object: null prototype] {
     username: 'billy',
     id: 4,
     password:
      '$2b$12$oIIn*******AnNkr/Pt89S****W3Vi2o8DYBgnEy9t9gcje',
     email: 'exampleman@example.com',
     created_at: 2019-05-28T20:00:37.164Z,
     updated_at: 2019-05-28T20:00:37.164Z },
</code>```

So im not understanding why im gettng undefined when doing user.password

passport.js

```<code> .......
    passport.use('login',
        new Local(
        {
            usernameField:'username',
            passwordField:'password',
            session:false
        },
        (username, password, done, req) => {
            try{
                User.forge({username: username}).fetch()
                .then(user => {
                    if(user === null){
                        return done(null, false, {message: 'Username doesn\'t exist'})
                    }
                    else{

                        console.log(user);  // logs out user model along with password info

                       // not getting user.password from user model.
                      bcrypt.compare(password, user.password)
                        .then(response => {
                            if(response !== true){
                                console.log('passwords do not match');
                                return done(null, false, {message:'passwords do not match'} )
                            }
                            console.log('user found & authenticated');
                            return done(null, user);
                        })
                    }
                })
            }catch(err){
                done(err);
            }
        }
    ))
</code>```

答: Try to compare with user.attributes.password.

Body:
I'm getting this error when trying to compare passwords

UnhandledPromiseRejectionWarning: Error: data and hash arguments
  required

the thing is user.password returns undefined, but when i do console.log(user) it returns the model

Like this

ModelBase {
  attributes:
   [Object: null prototype] {
     username: 'billy',
     id: 4,
     password:
      '$2b$12$oIIn*******AnNkr/Pt89S****W3Vi2o8DYBgnEy9t9gcje',
     email: 'exampleman@example.com',
     created_at: 2019-05-28T20:00:37.164Z,
     updated_at: 2019-05-28T20:00:37.164Z },

So im not understanding why im gettng undefined when doing user.password

passport.js

 .......
    passport.use('login',
        new Local(
        {
            usernameField:'username',
            passwordField:'password',
            session:false
        },
        (username, password, done, req) => {
            try{
                User.forge({username: username}).fetch()
                .then(user => {
                    if(user === null){
                        return done(null, false, {message: 'Username doesn\'t exist'})
                    }
                    else{

                        console.log(user);  // logs out user model along with password info

                       // not getting user.password from user model.
                      bcrypt.compare(password, user.password)
                        .then(response => {
                            if(response !== true){
                                console.log('passwords do not match');
                                return done(null, false, {message:'passwords do not match'} )
                            }
                            console.log('user found & authenticated');
                            return done(null, user);
                        })
                    }
                })
            }catch(err){
                done(err);
            }
        }
    ))


问:
Angular Material form field appearance padding size
On

```<code><mat-form-field appearance="outline">
</code>```

Is it possible to reduce the default padding size of the border?

In the developer tool I can find the class and able to reduce size.

Putting this class in my css would not change the size.

Not sure how to put class name in my css to change the padding.

答:
To reduce the field padding I had to override the appearance-outline and the infix classes like this :</p>

```<code>::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
  padding: 0.7em 0 0.7em 0 !important;
  top: -0.25em;
}
</code>```

Body:
On

<mat-form-field appearance="outline">

Is it possible to reduce the default padding size of the border?

In the developer tool I can find the class and able to reduce size.

Putting this class in my css would not change the size.

Not sure how to put class name in my css to change the padding.

Body:
To reduce the field padding I had to override the appearance-outline and the infix classes like this :

::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
  padding: 0.7em 0 0.7em 0 !important;
  top: -0.25em;
}


问:
How to create a circular Alphabet in Python so that the letter after z is a and the letter before a is z
Is there a Function in Python to easily create a circular Alphabet, so that the letter after z is a and the letter before a is z?

I tried something with chr() and .join(Alphabet), but that didn't worked because i got the error message an integer is required (got type str).

for character in word:
    if chr(Alphabet[Alphabet.find(character)) >= "z":
        new_Alphabet = Alphabet.join(Alphabet)
    elif chr(Alphabet[Alphabet.find(character)) <= "a":
        new_Alphabet = Alphabet.join(Alphabet[:-1])
```

答: I think you have to use circular queue. for more information please check this link.


问:
iphone - performSelectorInBackground image loading
i'm loading images into a UIView inside a  UIscrollview using performSelectorInBackground to fetch the images from the URL. Images are getting downloaded correctly into an array but when I assign to the UIImageView these images all the images are assigned to the last page of Scroll view.</p>

```<code>@implementation DetailViewController

- (id)initWithDataSource:(id<TabBarElementProtocol,UITableViewDataSource>)theDataSource {
    if ([self init]) {

        // Scroll View
        scrollView = [[UIScrollView alloc]init];

        //a page is the width of the scroll view

        scrollView.delegate = self;
        scrollView.pagingEnabled = YES;
        scrollView.frame = CGRectMake(0, 0, 320, 300);
        scrollView.contentSize = CGSizeMake(320*10, 300);
        scrollView.backgroundColor = [UIColor clearColor];
        scrollView.showsHorizontalScrollIndicator = NO;
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.scrollsToTop = NO;
        scrollView.bounces = NO;
        scrollView.showsHorizontalScrollIndicator = NO;

        scrollView.pagingEnabled = YES;

        [self.view addSubview:scrollView];

        scrollView.contentOffset = CGPointMake(10*320, 0);

        [self displayView];

    }
    return self;
}

-(void) displayView{
    DouglasAppDelegate *delegate = (DouglasAppDelegate *)[[UIApplication sharedApplication] delegate];

    for (int i=0; i < 10; i++)
    {

        myview = [[UIView alloc] init];
        myview.frame = CGRectMake(320*i , 0, 320, 300);
        [myview setBackgroundColor: [UIColor whiteColor]];

        pictureImageView = [[UIImageView alloc] initWithFrame:CGRectMake(179, 11, 100, 100)];
        pictureImageView.tag = i;
        [myview addSubview: pictureImageView];
        [pictureImageView release];
// Picture URL is accessed dynamically and loading correctly.
        [dataArray insertObject:[NSMutableArray arrayWithObjects:picUrl,[NSString stringWithFormat:@"%d", i],nil]       atIndex:i];

        [scrollView addSubview:myview];

    }

    [self performSelectorInBackground:@selector(loadImageInBackground:) withObject:dataArray];

    //Pager control

    tpageControl                    = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 300 , 320, 17)];
    tpageControl.backgroundColor    = [UIColor clearColor];
    tpageControl.numberOfPages      = [delegate.NeuEntries count];
    tpageControl.currentPage        = delegate.neuDetailIndex;
    zumPage                         = delegate.neuDetailIndex ;
    [tpageControl addTarget:self action:@selector(pageTurn:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview: tpageControl];

}

- (void) loadImageInBackground:(NSMutableArray *)urlAndTagReference  {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSData *imgData;
    UIImage *img;
    NSMutableArray *arr1 = [[NSMutableArray alloc] initWithCapacity: [urlAndTagReference count]];

    for(int i=0; i<[urlAndTagReference count] ;i++)
      {
            NSString *url = [[urlAndTagReference objectAtIndex:i] objectAtIndex:0];
            NSURL *imgURL = [NSURL URLWithString:url];
            imgData = [NSData dataWithContentsOfURL:imgURL];
            img = [[UIImage alloc] initWithData:imgData];
            [arr1 insertObject:[NSMutableArray arrayWithObjects:img,[[urlAndTagReference objectAtIndex:i]objectAtIndex:1],nil] atIndex:i];

    }

    [self performSelectorOnMainThread:@selector(assignImageToImageView:) withObject:arr1 waitUntilDone:YES];
}

- (void) assignImageToImageView:(NSArray *)imgAndTagReference
{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

     for(int i=0; i<[imgAndTagReference count] ;i++){

            UIImage *img = [[UIImage alloc] init];
            img = [[imgAndTagReference objectAtIndex:i] objectAtIndex:0];
            NSLog(@"img %@",img);
            // SAME IMAGES OVERLAPPING ON LAST PAGE OF SCROLL VIEW????????????????
            [pictureImageView setImage:img];
         }

}

- (void) pageTurn:(UIPageControl*) aPageController{

    int whichPage                   = aPageController.currentPage;
    scrollView.contentOffset        = CGPointMake(320.0f * whichPage, 0.0f);

}

- (void)scrollViewDidScroll:(UIScrollView *)sender
{

    CGPoint offset              = sender.contentOffset;
    tpageControl.currentPage    = offset.x / 320.0f;

}
</code>```

答:
On the following line you are creating a memory leak

```<code>UIImage *img = [[UIImage alloc] init];
img = [[imgAndTagReference objectAtIndex:i] objectAtIndex:0];
</code>```

You do not need to alloc and init a new UIImage but just set it to the value on the second line.

While you are looping images your are setting all of the images on the same object pictureImageView. You need to store an array of pictureImageView and loop over them the same way you are doing the images and assign each image to the appropriate image view.

```<code>for (int i=0; i < 10; i++)
{
    //It looks like myview is an ivar as well and should only be local
    myview = [[UIView alloc] init];
    myview.frame = CGRectMake(320*i , 0, 320, 300);
    [myview setBackgroundColor: [UIColor whiteColor]];

    UIImageView *tmp = [[UIImageView alloc] initWithFrame:CGRectMake(179, 11, 100, 100)];
    //NSMutableArray declared in header and already allocated
    [pictureImageViewArray addObject:tmp];
    tmp.tag = i;
    [myview addSubview: tmp];
    [tmp release];
    // Picture URL is accessed dynamically and loading correctly.
    [dataArray insertObject:[NSMutableArray arrayWithObjects:picUrl,[NSString stringWithFormat:@"%d", i],nil]       atIndex:i];

    [scrollView addSubview:myview];
    [myview release]; //<-- Fix memory leak
}

...

//inside of - (void) assignImageToImageView:
for(int i=0; i<[imgAndTagReference count] ;i++){
     UIImage *img = [[imgAndTagReference objectAtIndex:i] objectAtIndex:0];
    [(UIImageView*)[pictureImageViewArray objectAtIndex:i] setImage:img];
}
</code>```

Body:
i'm loading images into a UIView inside a  UIscrollview using performSelectorInBackground to fetch the images from the URL. Images are getting downloaded correctly into an array but when I assign to the UIImageView these images all the images are assigned to the last page of Scroll view.

@implementation DetailViewController

- (id)initWithDataSource:(id<TabBarElementProtocol,UITableViewDataSource>)theDataSource {
    if ([self init]) {

        // Scroll View
        scrollView = [[UIScrollView alloc]init];

        //a page is the width of the scroll view

        scrollView.delegate = self;
        scrollView.pagingEnabled = YES;
        scrollView.frame = CGRectMake(0, 0, 320, 300);
        scrollView.contentSize = CGSizeMake(320*10, 300);
        scrollView.backgroundColor = [UIColor clearColor];
        scrollView.showsHorizontalScrollIndicator = NO;
        scrollView.showsVerticalScrollIndicator = NO;
        scrollView.scrollsToTop = NO;
        scrollView.bounces = NO;
        scrollView.showsHorizontalScrollIndicator = NO;

        scrollView.pagingEnabled = YES;

        [self.view addSubview:scrollView];

        scrollView.contentOffset = CGPointMake(10*320, 0);

        [self displayView];

    }
    return self;
}

-(void) displayView{
    DouglasAppDelegate *delegate = (DouglasAppDelegate *)[[UIApplication sharedApplication] delegate];

    for (int i=0; i < 10; i++)
    {

        myview = [[UIView alloc] init];
        myview.frame = CGRectMake(320*i , 0, 320, 300);
        [myview setBackgroundColor: [UIColor whiteColor]];

        pictureImageView = [[UIImageView alloc] initWithFrame:CGRectMake(179, 11, 100, 100)];
        pictureImageView.tag = i;
        [myview addSubview: pictureImageView];
        [pictureImageView release];
// Picture URL is accessed dynamically and loading correctly.
        [dataArray insertObject:[NSMutableArray arrayWithObjects:picUrl,[NSString stringWithFormat:@"%d", i],nil]       atIndex:i];

        [scrollView addSubview:myview];

    }

    [self performSelectorInBackground:@selector(loadImageInBackground:) withObject:dataArray];

    //Pager control

    tpageControl                    = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 300 , 320, 17)];
    tpageControl.backgroundColor    = [UIColor clearColor];
    tpageControl.numberOfPages      = [delegate.NeuEntries count];
    tpageControl.currentPage        = delegate.neuDetailIndex;
    zumPage                         = delegate.neuDetailIndex ;
    [tpageControl addTarget:self action:@selector(pageTurn:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview: tpageControl];

}

- (void) loadImageInBackground:(NSMutableArray *)urlAndTagReference  {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSData *imgData;
    UIImage *img;
    NSMutableArray *arr1 = [[NSMutableArray alloc] initWithCapacity: [urlAndTagReference count]];

    for(int i=0; i<[urlAndTagReference count] ;i++)
      {
            NSString *url = [[urlAndTagReference objectAtIndex:i] objectAtIndex:0];
            NSURL *imgURL = [NSURL URLWithString:url];
            imgData = [NSData dataWithContentsOfURL:imgURL];
            img = [[UIImage alloc] initWithData:imgData];
            [arr1 insertObject:[NSMutableArray arrayWithObjects:img,[[urlAndTagReference objectAtIndex:i]objectAtIndex:1],nil] atIndex:i];

    }

    [self performSelectorOnMainThread:@selector(assignImageToImageView:) withObject:arr1 waitUntilDone:YES];
}

- (void) assignImageToImageView:(NSArray *)imgAndTagReference
{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

     for(int i=0; i<[imgAndTagReference count] ;i++){

            UIImage *img = [[UIImage alloc] init];
            img = [[imgAndTagReference objectAtIndex:i] objectAtIndex:0];
            NSLog(@"img %@",img);
            // SAME IMAGES OVERLAPPING ON LAST PAGE OF SCROLL VIEW????????????????
            [pictureImageView setImage:img];
         }

}

- (void) pageTurn:(UIPageControl*) aPageController{

    int whichPage                   = aPageController.currentPage;
    scrollView.contentOffset        = CGPointMake(320.0f * whichPage, 0.0f);

}

- (void)scrollViewDidScroll:(UIScrollView *)sender
{

    CGPoint offset              = sender.contentOffset;
    tpageControl.currentPage    = offset.x / 320.0f;

}

Body:
On the following line you are creating a memory leak

UIImage *img = [[UIImage alloc] init];
img = [[imgAndTagReference objectAtIndex:i] objectAtIndex:0];

You do not need to alloc and init a new UIImage but just set it to the value on the second line.

While you are looping images your are setting all of the images on the same object pictureImageView. You need to store an array of pictureImageView and loop over them the same way you are doing the images and assign each image to the appropriate image view.

for (int i=0; i < 10; i++)
{
    //It looks like myview is an ivar as well and should only be local
    myview = [[UIView alloc] init];
    myview.frame = CGRectMake(320*i , 0, 320, 300);
    [myview setBackgroundColor: [UIColor whiteColor]];

    UIImageView *tmp = [[UIImageView alloc] initWithFrame:CGRectMake(179, 11, 100, 100)];
    //NSMutableArray declared in header and already allocated
    [pictureImageViewArray addObject:tmp];
    tmp.tag = i;
    [myview addSubview: tmp];
    [tmp release];
    // Picture URL is accessed dynamically and loading correctly.
    [dataArray insertObject:[NSMutableArray arrayWithObjects:picUrl,[NSString stringWithFormat:@"%d", i],nil]       atIndex:i];

    [scrollView addSubview:myview];
    [myview release]; //<-- Fix memory leak
}

...

//inside of - (void) assignImageToImageView:
for(int i=0; i<[imgAndTagReference count] ;i++){
     UIImage *img = [[imgAndTagReference objectAtIndex:i] objectAtIndex:0];
    [(UIImageView*)[pictureImageViewArray objectAtIndex:i] setImage:img];
}


问:
Does HelpNDoc Pascal Script support structures?
I am trying to create a structure:

```<code>MyTopic
    TopicID : String;
    HelpID : Integer;
</code>```

I wanted to create an array of these structures so I could sort them.

I have tried using this type / record syntax but it is failing.

Update

I defined this type and procedure:

type
    TMyTopicRecord = record
        idTopic : String;
        idContextHelp : integer;
    End;

procedure GetSortedTopicIDs(aTopics : array of String; size : Integer);
var
    aMyTopicRecords : array of TMyTopicRecord;
    temp : TMyTopicRecord;
    iTopic, i, j : Integer;
begin
    // Init the array
    SetLength(aMyTopicRecords, size);

    // Fill the array with the existing topid ids.
    // Get the context ids at the same time.
    for iTopic := 0 to size - 1 do
        aMyTopicRecords[iTopic].idTopic := aTopics[iTopic];
        aMyTopicRecords[iTopic].idContextHelp := HndTopics.GetTopicHelpContext(aTopics[iTopic]);

    // Sort the array on context id
    for i := size-1 DownTo 1 do
    for j := 2 to i do
        if (aMyTopicRecords[j-1].idContextHelp > aMyTopicRecords[j].idContextHelp) Then
        begin
            temp := aMyTopicRecords[j-1];
            aMyTopicRecords[j-1] := aMyTopicRecords[j];
            aMyTopicRecords[j] := temp;
        end;

    // Rebuild the original array of topic ids
    for iTopic := 0 to size - 1 do
        aTopics[iTopic] := aMyTopicRecords[iTopic].idTopic;
end;
```

<p>The procedure gets called in a loop of the <strong>parent</strong> function (code snipped):</p>

<pre class="lang-pascal prettyprint-override"><code>function GetKeywordsAsHtml(): string;
var
    aKeywordList: THndKeywordsInfoArray;
    aAssociatedTopics: array of string;
    nBlocLevel, nDif, nClose, nCurKeywordLevel, nCurKeywordChildrenCnt: Integer;
    nCurKeyword, nCurKeywordTopic: Integer;
    nCountAssociatedTopics: Integer;
    sCurrentKeyword, sKeywordLink, sKeywordRelated: string;
    sKeywordJsCaption: string;
begin
    Result := '<ul>';
    nBlocLevel := 0;
    try
        aKeywordList := HndKeywords.GetKeywordList(False);
        for nCurKeyword := 0 to length(aKeywordList) - 1 do
        begin
            sCurrentKeyword := aKeywordList[nCurKeyword].id;
            nCurKeywordLevel := HndKeywords.GetKeywordLevel(sCurrentKeyword);
            nCurKeywordChildrenCnt := HndKeywords.GetKeywordDirectChildrenCount(sCurrentKeyword);

            sKeywordLink := '#';
            sKeywordRelated := '[]';

            aAssociatedTopics := HndTopicsKeywords.GetTopicsAssociatedWithKeyword(sCurrentKeyword);
            nCountAssociatedTopics := Length(aAssociatedTopics);
            if nCountAssociatedTopics > 0 then
            begin
                GetSortedTopicIDs(aAssociatedTopics, nCountAssociatedTopics);
                // Code snipped
            end;
        end;
    finally
        Result := Result + '</ul>';
    end;
end;
</code>```

The script compiled in the HelpNDoc internal editor with no issues. But when I go to actually build my HTML documentation I encounter a problem:

The HelpNDoc API is explained here.

Is there something wrong with my code?

答:
I decided to go about it a different way and used a simpler technique:

procedure GetSortedTopicIDs(var aTopics : array of String; iNumTopics : Integer);
var
    iTopic : Integer;
    // List of output
    aList: TStringList;
begin
    // Init list
    aList := TStringList.Create;

    // Build a new array of "nnn x"
    //  - nnn is the help context id
    //  - x is the topid id

    // Note: I know that the context ID values are within the range 0 - 200
    for iTopic := 0 to iNumTopics - 1 do
        // We pad the context id with 0. We could increase the padding width to
        // make the script mre useful
        aList.Add(Format('%0.3d %s', [
            HndTopics.GetTopicHelpContext(aTopics[iTopic]),
            aTopics[iTopic]
        ]));

    // Now we sort the new array (which basically sorts it by context id)
    aList.Sort;

    // Update original array
    for iTopic := 0 to iNumTopics - 1 do
        // We ignore the "nnn " part of the string to get just the topic id
        aTopics[iTopic] := copy(aList[iTopic],5, length(aList[iTopic])-4);

    // Tidy up
    aList.Free;
end;
```

This compiles and I get the sorted array of topic IDs at the end of it. So the pop-up help is now listed as I want.

Body:
I am trying to create a structure:

MyTopic
    TopicID : String;
    HelpID : Integer;

I wanted to create an array of these structures so I could sort them.

I have tried using this type / record syntax but it is failing.

Update

I defined this type and procedure:

type
    TMyTopicRecord = record
        idTopic : String;
        idContextHelp : integer;
    End;

procedure GetSortedTopicIDs(aTopics : array of String; size : Integer);
var
    aMyTopicRecords : array of TMyTopicRecord;
    temp : TMyTopicRecord;
    iTopic, i, j : Integer;
begin
    // Init the array
    SetLength(aMyTopicRecords, size);

    // Fill the array with the existing topid ids.
    // Get the context ids at the same time.
    for iTopic := 0 to size - 1 do
        aMyTopicRecords[iTopic].idTopic := aTopics[iTopic];
        aMyTopicRecords[iTopic].idContextHelp := HndTopics.GetTopicHelpContext(aTopics[iTopic]);

    // Sort the array on context id
    for i := size-1 DownTo 1 do
    for j := 2 to i do
        if (aMyTopicRecords[j-1].idContextHelp > aMyTopicRecords[j].idContextHelp) Then
        begin
            temp := aMyTopicRecords[j-1];
            aMyTopicRecords[j-1] := aMyTopicRecords[j];
            aMyTopicRecords[j] := temp;
        end;

    // Rebuild the original array of topic ids
    for iTopic := 0 to size - 1 do
        aTopics[iTopic] := aMyTopicRecords[iTopic].idTopic;
end;

The procedure gets called in a loop of the parent function (code snipped):

function GetKeywordsAsHtml(): string;
var
    aKeywordList: THndKeywordsInfoArray;
    aAssociatedTopics: array of string;
    nBlocLevel, nDif, nClose, nCurKeywordLevel, nCurKeywordChildrenCnt: Integer;
    nCurKeyword, nCurKeywordTopic: Integer;
    nCountAssociatedTopics: Integer;
    sCurrentKeyword, sKeywordLink, sKeywordRelated: string;
    sKeywordJsCaption: string;
begin
    Result := '
';
    nBlocLevel := 0;
    try
        aKeywordList := HndKeywords.GetKeywordList(False);
        for nCurKeyword := 0 to length(aKeywordList) - 1 do
        begin
            sCurrentKeyword := aKeywordList[nCurKeyword].id;
            nCurKeywordLevel := HndKeywords.GetKeywordLevel(sCurrentKeyword);
            nCurKeywordChildrenCnt := HndKeywords.GetKeywordDirectChildrenCount(sCurrentKeyword);

            sKeywordLink := '#';
            sKeywordRelated := '[]';

            aAssociatedTopics := HndTopicsKeywords.GetTopicsAssociatedWithKeyword(sCurrentKeyword);
            nCountAssociatedTopics := Length(aAssociatedTopics);
            if nCountAssociatedTopics > 0 then
            begin
                GetSortedTopicIDs(aAssociatedTopics, nCountAssociatedTopics);
                // Code snipped
            end;
        end;
    finally
        Result := Result + '
';
    end;
end;

The script compiled in the HelpNDoc internal editor with no issues. But when I go to actually build my HTML documentation I encounter a problem:

The HelpNDoc API is explained here.

Is there something wrong with my code?

Body:
I decided to go about it a different way and used a simpler technique:

procedure GetSortedTopicIDs(var aTopics : array of String; iNumTopics : Integer);
var
    iTopic : Integer;
    // List of output
    aList: TStringList;
begin
    // Init list
    aList := TStringList.Create;

    // Build a new array of "nnn x"
    //  - nnn is the help context id
    //  - x is the topid id

    // Note: I know that the context ID values are within the range 0 - 200
    for iTopic := 0 to iNumTopics - 1 do
        // We pad the context id with 0. We could increase the padding width to
        // make the script mre useful
        aList.Add(Format('%0.3d %s', [
            HndTopics.GetTopicHelpContext(aTopics[iTopic]),
            aTopics[iTopic]
        ]));

    // Now we sort the new array (which basically sorts it by context id)
    aList.Sort;

    // Update original array
    for iTopic := 0 to iNumTopics - 1 do
        // We ignore the "nnn " part of the string to get just the topic id
        aTopics[iTopic] := copy(aList[iTopic],5, length(aList[iTopic])-4);

    // Tidy up
    aList.Free;
end;

This compiles and I get the sorted array of topic IDs at the end of it. So the pop-up help is now listed as I want.


问:
How to make two ''where' conditions on SQL select query
I have a table like this

column 1| column2 | column 3|

01                      45                     heavy

02                        50                       easy

04                      100                      middle

I want a result that will show all records that if  in 'column 3' is 'heavy' then 'column 2' must have value greater then 50, and if in 'column 3' is not 'heavy'  then 'column 2' must have value greater then 90

答:
You can translate your logic directly into a where clause:

```<code>where (column3 = 'heavy' and column2 > 50) or
      (column3 <> 'heavy' and column2 > 90)
</code>```

Body:
You can translate your logic directly into a where clause:

where (column3 = 'heavy' and column2 > 50) or
      (column3 <> 'heavy' and column2 > 90)


答:
As per doc of .map()

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

So using map you can perform some opration on each element, you can not omit any element.

If you want to omit some element based on some condtion then use .filter().

For your case you can first use map() for triming all element then use filter() to removed element whose length is not >0.

var input = "aaaaaaa,                ddd,            ,asdsad   ";

var output = input.split(',').map(item => {
    item = item.trim();
    return item;
}).filter(item => {
    return item.length > 0;
}).join();

console.log(output);```

Title: map function returns item even if condition is not true


问:
How do I use MsiGetProductInfo to get installed version number c# winforms 4.0?
I'm trying to get the installed version number of my win fomrs application using the MsiGetProductInfo function. I am try to alter code i found on this post, but all I get is wing ding looking text when I alter my call to the function like so

```<code>MsiGetProductInfo("{9806C9BE-59D4-4DEE-802F-0E492023DE8A}", "INSTALLPROPERTY_VERSIONSTRING", builder, ref len);
</code>```

Its a 4.0 c# Winforms project that is installed with a standard vs2010 setup project. The client machines are win 7 and win XP

答:
Have you checked the return value of the function? If it returns an error, it's possible that the buffer is filled with garbage.

This is a list of the possible returns, from the MSDN page here

Return Value

ERROR_BAD_CONFIGURATION
The configuration data is corrupt.

ERROR_INVALID_PARAMETER
An invalid parameter was passed to the function.

ERROR_MORE_DATA
A buffer is too small to hold the requested data.

ERROR_SUCCESS
The function completed successfully.

ERROR_UNKNOWN_PRODUCT
The product is unadvertised or uninstalled.

ERROR_UNKNOWN_PROPERTY
The property is unrecognized.

Note  The MsiGetProductInfo function returns ERROR_UNKNOWN_PROPERTY if the application being queried is advertised and not installed.

Body:
I'm trying to get the installed version number of my win fomrs application using the MsiGetProductInfo function. I am try to alter code i found on this post, but all I get is wing ding looking text when I alter my call to the function like so

MsiGetProductInfo("{9806C9BE-59D4-4DEE-802F-0E492023DE8A}", "INSTALLPROPERTY_VERSIONSTRING", builder, ref len);

Its a 4.0 c# Winforms project that is installed with a standard vs2010 setup project. The client machines are win 7 and win XP


问:
Table row onclick String value shows error in jquery
I have populated table from database in Ajax using json. But on click edit button only number field are passed to java script function. But when i want to pass  string like name, base64Encoding String not passed
Here is the java script code

```<code>'<a href="javascript:void(0)" onclick="doGet('+item.pohto+','+item.name+')" > <i class="fas fa-pencil-alt"></i> </a>';
</code>```

When I click on edit icon it shows bellow error

```<code>SyntaxError: missing ) after argument list
</code>```

But when I use only number value it is working.

Please help me to pass string value like image , name

答:
That is because when item.pohto and item.name are strings that contain spaces, you end up with something like this:

```<code>onclick="doGet(value one, value two)"
</code>```

which is invalid syntax. You'll have to add quotes to make those values string literals.

```<code>'<a href="javascript:void(0)" onclick="doGet(\''+item.pohto+'\', \''+item.name+'\')" > <i class="fas fa-pencil-alt"></i> </a>'
</code>```

You can also use a string template which will make this easier to read:

```<code>`<a href="javascript:void(0)" onclick="doGet('${item.pohto}', '${item.name}')" > <i class="fas fa-pencil-alt"></i> </a>`
</code>```

Body:
I have populated table from database in Ajax using json. But on click edit button only number field are passed to java script function. But when i want to pass  string like name, base64Encoding String not passed
Here is the java script code

'  ';

When I click on edit icon it shows bellow error

SyntaxError: missing ) after argument list

But when I use only number value it is working.

Please help me to pass string value like image , name

Body:
That is because when item.pohto and item.name are strings that contain spaces, you end up with something like this:

onclick="doGet(value one, value two)"

which is invalid syntax. You'll have to add quotes to make those values string literals.

'<a href="javascript:void(0)" onclick="doGet(\''+item.pohto+'\', \''+item.name+'\')" > <i class="fas fa-pencil-alt"></i> </a>'

You can also use a string template which will make this easier to read:

`<a href="javascript:void(0)" onclick="doGet('${item.pohto}', '${item.name}')" > <i class="fas fa-pencil-alt"></i> </a>`


问:
Can I use SNS subscription with internal ALB endpoint within the VPC?
I have an SNS uses an HTTP subscription, the endpoint is an application load balancer which is created as an internal ALB within the VPC.

For SNS to call the endpoint I have to make the endpoint publicly available, I can't make the endpoint public just for SNS as my other use cases are getting addressed within the VPC.

Is there a better way to create a subscription without having to make the endpoint public.

I have for now made the endpoint public, but cant keep it the same forever

Is there a better way to create a subscription without having to make the endpoint public.

答:
One possible solution would be to subscribe a Lambda function (deployed in your VPC) to proxy the request to your internal ALB.

See Using AWS Lambda with Amazon SNS for an exemple of event that your function will receive.

Note that it won't be possible to configure a custom Delivery Retry Policies like you can when using HTTP/HTTPS endpoints. Instead you will have the basic AWS Lambda Retry Behavior.


答:
```<code>item.name
</code>```

Might be empty, try checking if item.name has a value

```<code>onclick="doGet('+item.pohto+''+item.name ? ','+item.name : ''+')"
</code>```

Title: Table row onclick String value shows error in jquery

Body:
item.name

Might be empty, try checking if item.name has a value

onclick="doGet('+item.pohto+''+item.name ? ','+item.name : ''+')"


问:
raphael.js crop image
I am newbie to raphael.js and svg. I have an image element, i can select rectangles on it using drag and drop in any area. The problem is that image must be transparent, but selected rectangles not.

If i used css i would set background-image for rectangles and background position, but i have not found such possibility for svg (and probably vml for ie).

How can i crop the image and put it over transparent image or set background position to rectangle?

UPD: Actually i found the solution: for each newly created rectangle I can copy image and use clip-rect attribute. But this solution does not match my needs. I can not rotate clip-rect area, image only.

答:
The rectangular clip-rect that raphaël provides is a subset of what you can do in svg.

Here's an example of rotated clipping: masking-path-02-b

Here's something a bit more advanced: masking-path-07-b

Title: raphael.js crop image


答:
Use itertools.cycle ans string.ascii_lowercase:

```<code>from itertools import cycle
import string
circular_alphabet = cycle(string.ascii_lowercase)
</code>```

That is an infinite iterator with the lowercase letters:

```<code>>>> "".join(next(circular_alphabet ) for _ in range(50))
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx'
</code>```

Title: How to create a circular Alphabet in Python so that the letter after z is a and the letter before a is z

Body:
Is there a Function in Python to easily create a circular Alphabet, so that the letter after z is a and the letter before a is z?

I tried something with chr() and .join(Alphabet), but that didn't worked because i got the error message an integer is required (got type str).

for character in word:
    if chr(Alphabet[Alphabet.find(character)) >= "z":
        new_Alphabet = Alphabet.join(Alphabet)
    elif chr(Alphabet[Alphabet.find(character)) <= "a":
        new_Alphabet = Alphabet.join(Alphabet[:-1])

Body:
Use itertools.cycle ans string.ascii_lowercase:

from itertools import cycle
import string
circular_alphabet = cycle(string.ascii_lowercase)

That is an infinite iterator with the lowercase letters:

>>> "".join(next(circular_alphabet ) for _ in range(50))
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx'


问:
C++ Heap Corruption
I haven't done any C++ in a while, but decided to finish a big project I was working on for someone. I am getting the following error message now though...

HEAP CORRUPTION DETECTED: after Normal Block (#1761) at 0x17DEB940.
CRT Detected that the application wrote to memory after end of heap buffer.

I have been stepping through all of the functions I thought might have caused it but I am at a loss. Is there any way using the more advanced debugging features to hunt this down?

答:
Try to catch it with Intruments.

Sounds a bit like a classical C error. You are sure you don't write beyond an c array ( like int[xyz]) in a while or for loop? It don't cause any errors, but you get strange effects in a lot spaces that have nothing to do with the part where the bug lives. :p

Title: C++ Heap Corruption


问:
Alexa responding before data is returned
I'm new to promises, async/await, and Alexa/lambda so bear with me.

My function is returning prior to the data being returned. I had a similar issue where I was getting an error, but have since edited my function quite a bit and therefore asking a new question. I'm now no longer getting an error, but instead my data is being returned first, then the promise is executing.

I've tried re-writing the promise/function after reading many, many SO, google, and amazon developer forums. Nothing seems to be working for me.

```<code>const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let responseData, promise;

         checkAuthenticationStatus(handlerInput,function(json){
            console.log('waited!')
            if(json.error) {
                return handlerInput.responseBuilder.speak(messages.NO_ACCESS).withSimpleCard('Unauthorized Request', messages.NO_ACCESS).getResponse();
            } else if(json.noerror && json.noerror.okay == 'true'){
                console.log('starting to get intent data')
                const url = new URL(json.noerror.okay.path);
                promise = new Promise((resolve, reject) => {
                    console.log('start promise')
                   return httpsGetIntent(handlerInput, url).then((resultData) => {
                        console.log(resultData)
                        responseData = resultData;
                        resolve(responseData)
                        console.log('inside promise, no error, prior to return data')
                    })

            }).then((result) => { console.log('result', result)})
                return handlerInput.responseBuilder.speak('Test').getResponse();
            }

        });
        console.log('response data', responseData)

        let result = await promise;
        return result;

    },
};
</code>```

Out of my many console.logs() added for debugging, they print as follows:
- 'response data'
- 'waited!'
- 'starting to get intent data'
- 'start promise'
- resultData
- 'inside promise, no error, prior to return data'

答:
While it's not fully fleshed out (I need to address the error handling portion) I wanted to share my solution here in case anyone stumbled upon this post and needed some help.

I moved the promise outside the checkAuthentication function and returned the data when it was processed. I then chained the promise with .then() and passed it the data returned, and prompted Alexa to speak.

```<code>const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let responseData, promise;
        return new Promise((resolve, reject) => {
            checkAuthenticationStatus(handlerInput, async function(json) {
                if (json.error) {
                    return handlerInput.responseBuilder.speak(messages.NO_ACCESS).withSimpleCard('Unauthorized Request', messages.NO_ACCESS).getResponse();
                } else if (json.noerror && json.noerror.okay == 'true') {
                    const url = new URL(json.noerror.okay.path);
                    let resultD = await httpsGetIntent(handlerInput, url, function(resultData) {
                        if (resultData) {
                            return resolve(resultData);
                        } else {
                            return resolve(handlerInput.responseBuilder.speak('False Test').getResponse());
                        }
                    })

                }
            })

        }).then((data) => {
            return handlerInput.responseBuilder.speak(data.response.outputSpeech.text).getResponse();
        });
    },
};
</code>```

Body:
I'm new to promises, async/await, and Alexa/lambda so bear with me.

My function is returning prior to the data being returned. I had a similar issue where I was getting an error, but have since edited my function quite a bit and therefore asking a new question. I'm now no longer getting an error, but instead my data is being returned first, then the promise is executing.

I've tried re-writing the promise/function after reading many, many SO, google, and amazon developer forums. Nothing seems to be working for me.

const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let responseData, promise;

         checkAuthenticationStatus(handlerInput,function(json){
            console.log('waited!')
            if(json.error) {
                return handlerInput.responseBuilder.speak(messages.NO_ACCESS).withSimpleCard('Unauthorized Request', messages.NO_ACCESS).getResponse();
            } else if(json.noerror && json.noerror.okay == 'true'){
                console.log('starting to get intent data')
                const url = new URL(json.noerror.okay.path);
                promise = new Promise((resolve, reject) => {
                    console.log('start promise')
                   return httpsGetIntent(handlerInput, url).then((resultData) => {
                        console.log(resultData)
                        responseData = resultData;
                        resolve(responseData)
                        console.log('inside promise, no error, prior to return data')
                    })

            }).then((result) => { console.log('result', result)})
                return handlerInput.responseBuilder.speak('Test').getResponse();
            }

        });
        console.log('response data', responseData)

        let result = await promise;
        return result;

    },
};

Out of my many console.logs() added for debugging, they print as follows:
- 'response data'
- 'waited!'
- 'starting to get intent data'
- 'start promise'
- resultData
- 'inside promise, no error, prior to return data'

Body:
While it's not fully fleshed out (I need to address the error handling portion) I wanted to share my solution here in case anyone stumbled upon this post and needed some help.

I moved the promise outside the checkAuthentication function and returned the data when it was processed. I then chained the promise with .then() and passed it the data returned, and prompted Alexa to speak.

const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let responseData, promise;
        return new Promise((resolve, reject) => {
            checkAuthenticationStatus(handlerInput, async function(json) {
                if (json.error) {
                    return handlerInput.responseBuilder.speak(messages.NO_ACCESS).withSimpleCard('Unauthorized Request', messages.NO_ACCESS).getResponse();
                } else if (json.noerror && json.noerror.okay == 'true') {
                    const url = new URL(json.noerror.okay.path);
                    let resultD = await httpsGetIntent(handlerInput, url, function(resultData) {
                        if (resultData) {
                            return resolve(resultData);
                        } else {
                            return resolve(handlerInput.responseBuilder.speak('False Test').getResponse());
                        }
                    })

                }
            })

        }).then((data) => {
            return handlerInput.responseBuilder.speak(data.response.outputSpeech.text).getResponse();
        });
    },
};


问:
Cannot copy sheet to another workbook
I have what it seems a small issue but cannot figure out how to solve.
So, every week I have to make a bunch of pivot tables to summarize raw data that I am getting. I figured, it would be much easier if I create all the tables into a Layout file and then just copy them to the new file and then change the source. And I wrote the following code:

```<code>Sub something()

Workbooks.Open Filename:="C:\\\\Layout.xlsx"
With Workbooks("Layout.xlsx")
    .Sheets("Pivot").Copy Before:=ActiveWorkbook.Sheets("Main List")
    .Close savechanges:=False
End With

End Sub
</code>```

This code works just fine. The issue comes when I try to paste the code into my personal workbook and then run through VBA directly, rather than copying and pasting it every time.

What I could do is, to change the code from 'Activeworkbook' to the name of my new workbook but its name change every week, because it is based on a date.
I already tried to declare the name of the new workbook as a string and call it through that but that didn't work either.

Any ideas?

答:
I would use workbook objects to keep the two files clear:</p>

```<code>Sub something()

    Dim wb_from As Workbook, wb_to As Workbook
    Set wb_to = ActiveWorkbook
    Workbooks.Open Filename:="C:\\\\Layout.xlsx"
    Set wb_from = Workbooks("Layout.xlsx")
    wb_from.Sheets("Pivot").Copy Before:=wb_to.Sheets("Main List")
    wb_from.Close SaveChanges:=False
end sub
</code>```

Title: Cannot copy sheet to another workbook

Body:
I have what it seems a small issue but cannot figure out how to solve.
So, every week I have to make a bunch of pivot tables to summarize raw data that I am getting. I figured, it would be much easier if I create all the tables into a Layout file and then just copy them to the new file and then change the source. And I wrote the following code:

Sub something()

Workbooks.Open Filename:="C:\\\\Layout.xlsx"
With Workbooks("Layout.xlsx")
    .Sheets("Pivot").Copy Before:=ActiveWorkbook.Sheets("Main List")
    .Close savechanges:=False
End With

End Sub

This code works just fine. The issue comes when I try to paste the code into my personal workbook and then run through VBA directly, rather than copying and pasting it every time.

What I could do is, to change the code from 'Activeworkbook' to the name of my new workbook but its name change every week, because it is based on a date.
I already tried to declare the name of the new workbook as a string and call it through that but that didn't work either.

Any ideas?

Body:
I would use workbook objects to keep the two files clear:

Sub something()

    Dim wb_from As Workbook, wb_to As Workbook
    Set wb_to = ActiveWorkbook
    Workbooks.Open Filename:="C:\\\\Layout.xlsx"
    Set wb_from = Workbooks("Layout.xlsx")
    wb_from.Sheets("Pivot").Copy Before:=wb_to.Sheets("Main List")
    wb_from.Close SaveChanges:=False
end sub


答:
You can use case / when:

```<code>select ...
where column2 > (
    case column3
        when 'heavy' then 50
        else 90
    end
)
</code>```

Title: How to make two ''where' conditions on SQL select query

Body:
I have a table like this

column 1| column2 | column 3|

01                      45                     heavy

02                        50                       easy

04                      100                      middle

I want a result that will show all records that if  in 'column 3' is 'heavy' then 'column 2' must have value greater then 50, and if in 'column 3' is not 'heavy'  then 'column 2' must have value greater then 90

Body:
You can use case / when:

select ...
where column2 > (
    case column3
        when 'heavy' then 50
        else 90
    end
)


问:
Get text between specific strings as different strings in regex
I have been trying to get text between two strings-('Item' and 'Item') but since 'Item' is present multiple times throughout the large document(which is itself a string) i get almost all whole of the document.
I can't figure out the regex code to get text between one 'item' and the next 'Item' till the last 'Item' as different strings.

I have tried regex codes but i can't figure it out.

First try :

```<code>(?<=Item)(.*)(?=Item)

</code>```

Second try:

```<code>value = search('Item(.+)Item', text)
if value is not None:
    value = value.group(1)

</code>```

The First try selects almost all of document

The Second try only gives the first occurrence of text between 'Item' and 'Item'.

Any help would be greatly appreciated.

答:
```<code>import re

string = 'Item Hello this is a sample Item String on StackOverflow Item Posted on a Item Wednesday'

print re.findall(r"(?<=Item ).+?(?= Item|$)",  string)
</code>```

Output:

```<code>['Hello this is a sample', 'String on StackOverflow', 'Posted on a', 'Wednesday']
</code>```

Explanation:

```<code>(?<=Item )      # positive lookbehind, make sure we have "Item " before
.+?             # 1 or more any character, not greedy
(?= Item|$)     # positive lookahead, make sure we have "Item " or end of line after
</code>```

Body:
I have been trying to get text between two strings-('Item' and 'Item') but since 'Item' is present multiple times throughout the large document(which is itself a string) i get almost all whole of the document.
I can't figure out the regex code to get text between one 'item' and the next 'Item' till the last 'Item' as different strings.

I have tried regex codes but i can't figure it out.

First try :

(?<=Item)(.*)(?=Item)

Second try:

value = search('Item(.+)Item', text)
if value is not None:
    value = value.group(1)

The First try selects almost all of document

The Second try only gives the first occurrence of text between 'Item' and 'Item'.

Any help would be greatly appreciated.

Body:
import re

string = 'Item Hello this is a sample Item String on StackOverflow Item Posted on a Item Wednesday'

print re.findall(r"(?<=Item ).+?(?= Item|$)",  string)

Output:

['Hello this is a sample', 'String on StackOverflow', 'Posted on a', 'Wednesday']

Explanation:

(?<=Item )      # positive lookbehind, make sure we have "Item " before
.+?             # 1 or more any character, not greedy
(?= Item|$)     # positive lookahead, make sure we have "Item " or end of line after


问:
'ER_PARSE_ERROR' because of a ? in the url parameter using MySQL
Using Loopback/NodeJs and trying to create a method to insert a multipart form I get this error when adding a youtube link that contains "?" in the form Any recommendations to avoid this error because I can so far insert a link without "?" and also it is very bad in terms of security.

This is the code I built so far:

```<code>cm_comediens_extraits_video.postVideo = function (titre, description, typeExtrait, langue, intention1, intention2, intention3, lienYoutube, options, req, res, file, cb) {
const token = options && options.accessToken;
const userId = token && token.userId;
var ds = app.datasources.mydb;

let newpath = '';
let fileName = '';
const form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
  var oldpath = files.file.path;
  fileName = files.file.name;
  titre = fields.titre;
  description = fields.description;
  typeExtrait = fields.typeExtrait;
  langue = fields.langue;
  intention1 = fields.intention1;
  intention2 = fields.intention2;
  intention3 = fields.intention3;
  lienYoutube = fields.lienYoutube;
  console.log(lienYoutube)
  newpath = 'public/videos/' + fileName;
  //  console.log(files.file)
  fs.copyFile(oldpath, newpath, function (err) {
    fs.unlinkSync(oldpath)
    if (err) throw err;
  });

var sql = "INSERT INTO cm_medias (id_comedien,type_media,intitule,filename,original_filename) VALUES ((SELECT id_comedien FROM cm_comediens WHERE id_utilisateur= '" + userId + "'),'video','"+titre+"','"+'http://localhost:3000/'+fileName+"','"+fileName+"')";
var sql2 = "INSERT INTO cm_comediens_extraits_video (id_media,description,qf_type,qf_langue,qf_interpretation1,qf_interpretation2,qf_interpretation3,lien_youtube) VALUES ((select max(cm_medias.id_media) as id_media from cm_medias inner join cm_comediens on cm_medias.id_comedien=cm_comediens.id_comedien inner join user on cm_comediens.id_utilisateur= user.id where user.id= '" + userId + "'),'" + description + "','" + typeExtrait + "','" + langue + "','" + intention1 + "','" + intention2 + "','" + intention3 + "','"+ lienYoutube +"')";
ds.connector.execute(sql, [titre], function (err, cm_comediens_extraits_videos) {
    ds.connector.execute(sql2, [description, typeExtrait, langue, intention1, intention2, intention3, lienYoutube], function (err, cm_comediens_extraits_videos) {
  if (err) console.error(err);
  cb(err, cm_comediens_extraits_videos);
    });
    });
    });
  };

  cm_comediens_extraits_video.remoteMethod(
    'postVideo', {
      http: {verb: 'POST'},
      description: 'Add a Video',
      accepts: [
                 { arg: 'titre', type: 'string' },
                { arg: 'description', type: 'string' },
                { arg: 'typeExtrait', type: 'integer' },
                { arg: 'langue', type: 'integer' },
                { arg: 'intention1', type: 'integer' },
                { arg: 'intention2', type: 'integer' },
                { arg: 'intention3', type: 'integer' },
                { arg: 'lienYoutube', type: 'string' },
                { arg: "options", "type": "object", "http": "optionsFromRequest"},
                { arg: 'req', type: 'object', 'http': {source: 'req'}},
                { arg: 'res', type: 'object', 'http': {source: 'res'}},
                { arg: 'file', type: 'file' }
      ],
      returns: {arg: 'data',type: ['cm_comediens_extraits_video'],root: true}
    }
  );
</code>```

This is an example of the error. The "?" in lienYoutube is considered as next parameter I think :

```<code>  code: 'ER_PARSE_ERROR',
  errno: 1064,
  sqlMessage:
   'Erreur de syntaxe près de \'://www.youtube.com/watchv=V`vcvcvcvcvcvc`MiSnR9frEg)\' à la ligne 1',
  sqlState: '42000',
  index: 0,
</code>```

Any help would be appreciated. Thank you.

答:
You have an error here: '"+titre+"','"+'http://localhost:3000/'
simpy remove quotes or escape them: '"+titre+"','"http://localhost:3000/"'

Body:
Using Loopback/NodeJs and trying to create a method to insert a multipart form I get this error when adding a youtube link that contains "?" in the form Any recommendations to avoid this error because I can so far insert a link without "?" and also it is very bad in terms of security.

This is the code I built so far:

cm_comediens_extraits_video.postVideo = function (titre, description, typeExtrait, langue, intention1, intention2, intention3, lienYoutube, options, req, res, file, cb) {
const token = options && options.accessToken;
const userId = token && token.userId;
var ds = app.datasources.mydb;

let newpath = '';
let fileName = '';
const form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
  var oldpath = files.file.path;
  fileName = files.file.name;
  titre = fields.titre;
  description = fields.description;
  typeExtrait = fields.typeExtrait;
  langue = fields.langue;
  intention1 = fields.intention1;
  intention2 = fields.intention2;
  intention3 = fields.intention3;
  lienYoutube = fields.lienYoutube;
  console.log(lienYoutube)
  newpath = 'public/videos/' + fileName;
  //  console.log(files.file)
  fs.copyFile(oldpath, newpath, function (err) {
    fs.unlinkSync(oldpath)
    if (err) throw err;
  });

var sql = "INSERT INTO cm_medias (id_comedien,type_media,intitule,filename,original_filename) VALUES ((SELECT id_comedien FROM cm_comediens WHERE id_utilisateur= '" + userId + "'),'video','"+titre+"','"+'http://localhost:3000/'+fileName+"','"+fileName+"')";
var sql2 = "INSERT INTO cm_comediens_extraits_video (id_media,description,qf_type,qf_langue,qf_interpretation1,qf_interpretation2,qf_interpretation3,lien_youtube) VALUES ((select max(cm_medias.id_media) as id_media from cm_medias inner join cm_comediens on cm_medias.id_comedien=cm_comediens.id_comedien inner join user on cm_comediens.id_utilisateur= user.id where user.id= '" + userId + "'),'" + description + "','" + typeExtrait + "','" + langue + "','" + intention1 + "','" + intention2 + "','" + intention3 + "','"+ lienYoutube +"')";
ds.connector.execute(sql, [titre], function (err, cm_comediens_extraits_videos) {
    ds.connector.execute(sql2, [description, typeExtrait, langue, intention1, intention2, intention3, lienYoutube], function (err, cm_comediens_extraits_videos) {
  if (err) console.error(err);
  cb(err, cm_comediens_extraits_videos);
    });
    });
    });
  };

  cm_comediens_extraits_video.remoteMethod(
    'postVideo', {
      http: {verb: 'POST'},
      description: 'Add a Video',
      accepts: [
                 { arg: 'titre', type: 'string' },
                { arg: 'description', type: 'string' },
                { arg: 'typeExtrait', type: 'integer' },
                { arg: 'langue', type: 'integer' },
                { arg: 'intention1', type: 'integer' },
                { arg: 'intention2', type: 'integer' },
                { arg: 'intention3', type: 'integer' },
                { arg: 'lienYoutube', type: 'string' },
                { arg: "options", "type": "object", "http": "optionsFromRequest"},
                { arg: 'req', type: 'object', 'http': {source: 'req'}},
                { arg: 'res', type: 'object', 'http': {source: 'res'}},
                { arg: 'file', type: 'file' }
      ],
      returns: {arg: 'data',type: ['cm_comediens_extraits_video'],root: true}
    }
  );

This is an example of the error. The "?" in lienYoutube is considered as next parameter I think :

  code: 'ER_PARSE_ERROR',
  errno: 1064,
  sqlMessage:
   'Erreur de syntaxe près de \'://www.youtube.com/watchv=V`vcvcvcvcvcvc`MiSnR9frEg)\' à la ligne 1',
  sqlState: '42000',
  index: 0,

Any help would be appreciated. Thank you.


问:
Count duplicate values that share same FK id
I am trying to Count how many duplicates there are in one column that share the same FK id. There should only be one type per Shared_FK_id.

```<code>table:
Shared_FK_ID : bigint
type: varchar(50)
</code>```

Sample data:

```<code>831 Ford
831 Fiat
831 Honda
831 Honda
831 Dodge
831 Volvo
831 Volvo
831 Opel
</code>```

答:
Should work for most sql DBMSes</p>

```<code>  select Shared_FK_ID, count(*) nmbr_of_dbls
    from (
       select Shared_FK_ID, type , count(*)
       group by Shared_FK_ID, type
       having count(*) > 1
    ) t
  group by Shared_FK_ID
</code>```

Body:
I am trying to Count how many duplicates there are in one column that share the same FK id. There should only be one type per Shared_FK_id.

table:
Shared_FK_ID : bigint
type: varchar(50)

Sample data:

831 Ford
831 Fiat
831 Honda
831 Honda
831 Dodge
831 Volvo
831 Volvo
831 Opel

Body:
Should work for most sql DBMSes

  select Shared_FK_ID, count(*) nmbr_of_dbls
    from (
       select Shared_FK_ID, type , count(*)
       group by Shared_FK_ID, type
       having count(*) > 1
    ) t
  group by Shared_FK_ID


问:
JSON key value coming as blank when using JQ
I am using JQ to parse JSON returned by Salesforce CLI.
My bash script is:

```<code>orgCreateResult=$(sfdx force:org:display -u mockScreenOrg --json)
orgCreateStatus=$(echo $orgCreateResult | ./bash-scripts/jq-win64.exe .status -r)
echo "orgCreateResult: "
echo "$orgCreateResult"
echo "orgCreateStatus: $orgCreateStatus"
instanceUrl=$(echo $checkDevHubResult | ./bash-scripts/jq-win64.exe .result -r)
echo "instanceUrl: $instanceUrl"
</code>```

I am using bash terminal in VS Code on windows. Output I am getting from this script is :

```<code>orgCreateResult:
{
  "status": 0,
  "result": {
    "username": "test-******@example.com",
    "devHubId": "****@**.com",
    "id": "************",
    "createdBy": "*****@**.com",
    "createdDate": "2019-05-13T14:15:32.000+0000",
    "expirationDate": "2019-06-12",
    "status": "Active",
    "edition": "Developer",
    "orgName": "HPESC",
    "accessToken": "************************************",
    "instanceUrl": "https://nosoftware-ruby-2532-dev-ed.cs6.my.salesforce.com",
    "clientId": "PlatformCLI",
    "alias": "mockScreenOrg"
  }
}
orgCreateStatus: 0
instanceUrl:
</code>```

I am able to read status field from JSON but it kinda fails with result object. I want to read instanceUrl field from JSON to use later in my script. Not sure if I am doing something wrong. I am very new to bash and JQ

答:
Try this:

instanceUrl=$(echo $orgCreateResult | ./bash-scripts/jq-win64.exe .result.instanceUrl -r)

Body:
I am using JQ to parse JSON returned by Salesforce CLI.
My bash script is:

orgCreateResult=$(sfdx force:org:display -u mockScreenOrg --json)
orgCreateStatus=$(echo $orgCreateResult | ./bash-scripts/jq-win64.exe .status -r)
echo "orgCreateResult: "
echo "$orgCreateResult"
echo "orgCreateStatus: $orgCreateStatus"
instanceUrl=$(echo $checkDevHubResult | ./bash-scripts/jq-win64.exe .result -r)
echo "instanceUrl: $instanceUrl"

I am using bash terminal in VS Code on windows. Output I am getting from this script is :

orgCreateResult:
{
  "status": 0,
  "result": {
    "username": "test-******@example.com",
    "devHubId": "****@**.com",
    "id": "************",
    "createdBy": "*****@**.com",
    "createdDate": "2019-05-13T14:15:32.000+0000",
    "expirationDate": "2019-06-12",
    "status": "Active",
    "edition": "Developer",
    "orgName": "HPESC",
    "accessToken": "************************************",
    "instanceUrl": "https://nosoftware-ruby-2532-dev-ed.cs6.my.salesforce.com",
    "clientId": "PlatformCLI",
    "alias": "mockScreenOrg"
  }
}
orgCreateStatus: 0
instanceUrl:

I am able to read status field from JSON but it kinda fails with result object. I want to read instanceUrl field from JSON to use later in my script. Not sure if I am doing something wrong. I am very new to bash and JQ


问:
How to reference abstract class
When posting this question my hope was to find a way how to reference/point to
an abstract class that that could be used by a worker/holder.

As the comments by @progman suggested and @laryx-decidua there is no way to hold a reference to an abstract class, but one can only hold a reference to a instantiated object.

Below you can find what I think is their proposed solution. To me this is an ugly solution, and I would have liked to have one that derives multiple static classes from an abstract base class and the holder gets references to those static classes to do its work. Deriving a static class form an abstract class Why you can't drive a static class is it seems prohibited by design and indicates bad architecture; although I don't see why the solution above is any better.

Suggested Solution

```<code>using System;
using System.Collections.Generic;

public abstract class BaseClass
{
    // Some declarative knowledge
    public int value;

    protected BaseClass(int value){
        this.value = value;
    }

    // Some procedural
    public abstract void execute();
}

public class ConcreteClass1 : BaseClass
{
    public ConcreteClass1() : base(42) {}

    public override void execute()
    {
        Console.WriteLine("In Concrete1! Value " + value);
    }
}

public class ConcreteClass2 : BaseClass
{
    public ConcreteClass2() : base(8888) { }

    public override void execute()
    {
        Console.WriteLine("In Concrete2! Value " + value);
    }
}

public class Holder
{
    BaseClass activeClass;
    public void setClass(BaseClass newClass){
        activeClass = newClass;
    }

    public void doWork()
    {
        int x;
        activeClass.execute();
        x = activeClass.value * activeClass.value;
        Console.WriteLine("Holder has done its work: " + x);
    }
}

class MainClass
{
    static void Main(string[] args)
    {
        List<BaseClass> classes = new List<BaseClass>();
        classes.Add(new ConcreteClass1());
        classes.Add(new ConcreteClass2());

        Holder holder = new Holder();

        holder.setClass(classes[0]);
        holder.doWork();

        holder.setClass(classes[1]);
        holder.doWork();

        holder.setClass(classes[0]);
        holder.doWork();
    }
}
</code>```

producing

```<code>In Concrete1! Value 42
Holder has done its work: 1764
In Concrete2! Value 8888
Holder has done its work: 78996544
In Concrete1! Value 42
Holder has done its work: 1764
</code>```

答:
Disclaimer: I don't speak C#, but I suspect the situation is similar to C++. The rest of the answer is based on my C++ and general OOP experience.

If I understood you correctly, you'd like to hold derived class object(s) through a base class reference and invoke a polymorphic ("virtual") method on those objects. Because you expect those derived classes to be "stateless" (i.e. no data members), you thought maybe you could "get away with" static (and/or abstract) classes.

The problem is that you need to instantiate something to put into your Holder objects, because a reference (or a pointer) can refer to (point to) only to a concrete object. So you need to instantiate objects that will be referred to via a reference in Holder, as some of the commenters have already pointed out. That's why abstract classes won't do -- they cannot be instantiated.

If there were an OOP language that supports references to types , plus some mechanism that can do the following: "Hmm, here is a reference AnimalTypeRef to the (possibly abstract) base class type Animal. AnimalTypeRef actually refers to the derived class type Elephant. Now, the user wants to invoke a virtual method Animal::make_noise() that does not use any class state, so let's invoke the corresponding method Elephant::make_noise() that overrides it and returns this :-)." -- well, then you could do what you have asked for.

I suspect this has not been implemented in C++ or C# because there are not too many use cases for it, and actually the same thing can be done with the general mechanism that requires that references refer to concrete objects.

Just go ahead and derive concrete (non-abstract) classes from your abstract base class, and don't worry about their statelessness. It's perfectly OK to define and use concrete objects that have no data members. Instantiate them, then initialise a Holder object with them, using a reference to the (abstract) base class and that's it. Polymorphic method invocation through base class references will do the rest.

Title: How to reference abstract class

Body:
When posting this question my hope was to find a way how to reference/point to
an abstract class that that could be used by a worker/holder.

As the comments by @progman suggested and @laryx-decidua there is no way to hold a reference to an abstract class, but one can only hold a reference to a instantiated object.

Below you can find what I think is their proposed solution. To me this is an ugly solution, and I would have liked to have one that derives multiple static classes from an abstract base class and the holder gets references to those static classes to do its work. Deriving a static class form an abstract class Why you can't drive a static class is it seems prohibited by design and indicates bad architecture; although I don't see why the solution above is any better.

Suggested Solution

using System;
using System.Collections.Generic;

public abstract class BaseClass
{
    // Some declarative knowledge
    public int value;

    protected BaseClass(int value){
        this.value = value;
    }

    // Some procedural
    public abstract void execute();
}

public class ConcreteClass1 : BaseClass
{
    public ConcreteClass1() : base(42) {}

    public override void execute()
    {
        Console.WriteLine("In Concrete1! Value " + value);
    }
}

public class ConcreteClass2 : BaseClass
{
    public ConcreteClass2() : base(8888) { }

    public override void execute()
    {
        Console.WriteLine("In Concrete2! Value " + value);
    }
}

public class Holder
{
    BaseClass activeClass;
    public void setClass(BaseClass newClass){
        activeClass = newClass;
    }

    public void doWork()
    {
        int x;
        activeClass.execute();
        x = activeClass.value * activeClass.value;
        Console.WriteLine("Holder has done its work: " + x);
    }
}

class MainClass
{
    static void Main(string[] args)
    {
        List<BaseClass> classes = new List<BaseClass>();
        classes.Add(new ConcreteClass1());
        classes.Add(new ConcreteClass2());

        Holder holder = new Holder();

        holder.setClass(classes[0]);
        holder.doWork();

        holder.setClass(classes[1]);
        holder.doWork();

        holder.setClass(classes[0]);
        holder.doWork();
    }
}

producing

In Concrete1! Value 42
Holder has done its work: 1764
In Concrete2! Value 8888
Holder has done its work: 78996544
In Concrete1! Value 42
Holder has done its work: 1764