问:
How to realize an algorithm to filter IPv4 adress without regex?
I need to realize an algorithm to filter IPv4 address. It should be work with decimal, hexadecimal, octal notation with dots and without. Also, I can't use regex.

Examples:

192.0.2.235           return True

0xC0.0x00.0x02.0xEB   return True

256.256.256.256       return False

0300.0000.0002.0353   return True

0xC00002EB            return True

3221226219            return True

030000001353          return True

I'm trying to do code like below but it's doesn't work for all examples

```<code>    def convertor(s):
        s = s.split('.')
        if len(s) != 4:
            return False
        for i in s:
            if not i.isdigit():
                i = int(i,16)
                list.append(i)
            else:
                if int(i) < 0 and int(i) > 255:
                    print('This is not correct IPv4')
                    return False
                else:
                    i = int(i)
                    list.append(i)
        print('This is correct IPv4')
        return list

    def convert(ip):
        n = 4
        ip = str(int(ip,32))
        ip = [ip[i:i+n] for i in range(0, len(ip),n)]
        return convertor(ip)

    print(convert('3221226219'))
</code>```

Any advice?

答:
First thing that comes to mind:

```<code>MAX_DEC = 4294967295
MAX_QUAD_DEC = 255

def is_quad_ip(ip):
  """
  Validates IPs in quad decimal, octal and hexadecimal
  Ex.
  127.0.0.1
  0x7f.0x0.0x0.0x1
  :param ip: ip to validate
  :type ip: string
  :return: true if it is a valid ip in quad decimal, octal or hexadecimal; false otherwise
  :type return: boolean
  """
  ll = ip.split(".")
  if len(ll) != 4:
    return False
  try:
    is_dec = all([
      0 <= int(x) <= MAX_QUAD_DEC
      and (len(x) == 1 or (len(x) >= 2 and not x.startswith("0")))
      for x in ll
    ])
  except ValueError:
    is_dec = False
  try:
    is_oct = all([
      len(x) == 4
      and 0 <= int(x, 8) <= MAX_QUAD_DEC
      for x in ll
    ])
  except ValueError:
    is_oct = False
  try:
    is_hex = all([0 <= int(x, 16) <= MAX_QUAD_DEC for x in ll])
  except ValueError:
    is_hex = False
  return is_dec or is_oct or is_hex

def is_ip(ip):
  """
  Validates IPs either in quad notation or not
  Ex.
  127.0.0.1 (QUAD DECIMAL)
  2130706433 (DECIMAL)
  :param ip: ip to validate
  :type ip: string
  :return: true if it is a valid ip; false otherwise
  :type return: boolean
  """
  if is_quad_ip(ip):
    return True
  try:
    is_dec = 0 <= int(ip) <= MAX_DEC
  except ValueError:
    is_dec = False
  try:
    is_oct = 0 <= int(ip, 8) <= MAX_DEC
  except ValueError:
    is_oct = False
  try:
    is_hex = 0 <= int(ip, 16) <= MAX_DEC
  except ValueError:
    is_hex = False
  return is_dec or is_oct or is_hex

print(is_ip("192.0.2.235"))
print(is_ip("0xC0.0x00.0x02.0xEB"))
print(is_ip("256.256.256.256"))
print(is_ip("0300.0000.0002.0353"))
print(is_ip("0xC00002EB"))
print(is_ip("3221226219"))
print(is_ip("030000001353"))
</code>```

Returns:

```<code>True
True
False
True
True
True
True
</code>```

Body:
I need to realize an algorithm to filter IPv4 address. It should be work with decimal, hexadecimal, octal notation with dots and without. Also, I can't use regex.

Examples:

192.0.2.235           return True

0xC0.0x00.0x02.0xEB   return True

256.256.256.256       return False

0300.0000.0002.0353   return True

0xC00002EB            return True

3221226219            return True

030000001353          return True

I'm trying to do code like below but it's doesn't work for all examples

    def convertor(s):
        s = s.split('.')
        if len(s) != 4:
            return False
        for i in s:
            if not i.isdigit():
                i = int(i,16)
                list.append(i)
            else:
                if int(i) < 0 and int(i) > 255:
                    print('This is not correct IPv4')
                    return False
                else:
                    i = int(i)
                    list.append(i)
        print('This is correct IPv4')
        return list

    def convert(ip):
        n = 4
        ip = str(int(ip,32))
        ip = [ip[i:i+n] for i in range(0, len(ip),n)]
        return convertor(ip)

    print(convert('3221226219'))

Any advice?

Body:
First thing that comes to mind:

MAX_DEC = 4294967295
MAX_QUAD_DEC = 255

def is_quad_ip(ip):
  """
  Validates IPs in quad decimal, octal and hexadecimal
  Ex.
  127.0.0.1
  0x7f.0x0.0x0.0x1
  :param ip: ip to validate
  :type ip: string
  :return: true if it is a valid ip in quad decimal, octal or hexadecimal; false otherwise
  :type return: boolean
  """
  ll = ip.split(".")
  if len(ll) != 4:
    return False
  try:
    is_dec = all([
      0 <= int(x) <= MAX_QUAD_DEC
      and (len(x) == 1 or (len(x) >= 2 and not x.startswith("0")))
      for x in ll
    ])
  except ValueError:
    is_dec = False
  try:
    is_oct = all([
      len(x) == 4
      and 0 <= int(x, 8) <= MAX_QUAD_DEC
      for x in ll
    ])
  except ValueError:
    is_oct = False
  try:
    is_hex = all([0 <= int(x, 16) <= MAX_QUAD_DEC for x in ll])
  except ValueError:
    is_hex = False
  return is_dec or is_oct or is_hex

def is_ip(ip):
  """
  Validates IPs either in quad notation or not
  Ex.
  127.0.0.1 (QUAD DECIMAL)
  2130706433 (DECIMAL)
  :param ip: ip to validate
  :type ip: string
  :return: true if it is a valid ip; false otherwise
  :type return: boolean
  """
  if is_quad_ip(ip):
    return True
  try:
    is_dec = 0 <= int(ip) <= MAX_DEC
  except ValueError:
    is_dec = False
  try:
    is_oct = 0 <= int(ip, 8) <= MAX_DEC
  except ValueError:
    is_oct = False
  try:
    is_hex = 0 <= int(ip, 16) <= MAX_DEC
  except ValueError:
    is_hex = False
  return is_dec or is_oct or is_hex

print(is_ip("192.0.2.235"))
print(is_ip("0xC0.0x00.0x02.0xEB"))
print(is_ip("256.256.256.256"))
print(is_ip("0300.0000.0002.0353"))
print(is_ip("0xC00002EB"))
print(is_ip("3221226219"))
print(is_ip("030000001353"))

Returns:

True
True
False
True
True
True
True


来源: stackexchange

问:
How do I configure net-ssh so I can fetch data using rest-client through an ssh tunnel?
We have an elasticsearch setup that is only available from a jump box.  I want to set up an ssh tunnel so I can query from my laptop or a Docker container.
When I run ssh, either directly or via 'system' the tunnel works and my post fetches data.  When I try to set up the tunnel using net-ssh I get a RestClient::Exceptions::ReadTimeout.  I'm not sure what I'm missing in the net-ssh configuration.  I've provided a simplified code example.

Tried running this on Windows with Cygwin, and in a Docker container running Centos7.

```<code>require 'json'
require 'net/ssh'
require 'rest-client'

def fetchData
  indexName = "REDACTED"
  url = "http://localhost:9999/#{indexName}/_search?pretty"
  body = '{"size":1, "query":{"match_all":{}}}'
  resp = RestClient.post url, body, :content_type => :json, :accept => :json
  return JSON.parse(resp)
end

begin
  userName   = 'REDACTED'
  privateKey = 'id_rsa'
  jumpBoxUrl = 'REDACTED.com'
  elasticUrl = 'REDACTED.com'

  # this works
  system("ssh -fN -o StrictHostKeyChecking=no -i ~/.ssh/#{privateKey} #{userName}@#{jumpBoxUrl} -p 22 -L 9999:#{elasticUrl}:9200 sleep 10 >> logfile")
  puts fetchData

  # wait for the ssh to time out
  sleep 5

  # Timed out reading data from server (RestClient::Exceptions::ReadTimeout) - WHY?!
  #
  Net::SSH.start(jumpBoxUrl, userName, :port=>22, :forward_agent=>true, :verbose=>:info, :keys=>["~/.ssh/#{privateKey}"]) do |session|
    session.forward.local(9999, elasticUrl, 9200)

    # this works - able to authenticate to the shell box
    puts session.exec!("ls -la")

    # this times out - data is not returned
    puts fetchData
  end
end
</code>```

I expect the post to return the same data when using net-ssh as it does when using ssh.

Appreciate any help with what I'm missing in my net-ssh setup.

答:
I suspect it's related to the port forwarding. Inside that block you should be able to access elasticUrl:9200 since you're essentially on the jumphost at that point.

My suggestion would be to ssh into the jumphost and curl the API endpoint as test. If that works, you should be able to copy that command verbatim and pass it to session.exec!. And finally if that works, then you should be able to update fetchData to make the request to elasticUrl:9200 and you're off to the races.

ContentLicense: CC BY-SA 4.0

Body:
We have an elasticsearch setup that is only available from a jump box.  I want to set up an ssh tunnel so I can query from my laptop or a Docker container.
When I run ssh, either directly or via 'system' the tunnel works and my post fetches data.  When I try to set up the tunnel using net-ssh I get a RestClient::Exceptions::ReadTimeout.  I'm not sure what I'm missing in the net-ssh configuration.  I've provided a simplified code example.

Tried running this on Windows with Cygwin, and in a Docker container running Centos7.

require 'json'
require 'net/ssh'
require 'rest-client'

def fetchData
  indexName = "REDACTED"
  url = "http://localhost:9999/#{indexName}/_search?pretty"
  body = '{"size":1, "query":{"match_all":{}}}'
  resp = RestClient.post url, body, :content_type => :json, :accept => :json
  return JSON.parse(resp)
end

begin
  userName   = 'REDACTED'
  privateKey = 'id_rsa'
  jumpBoxUrl = 'REDACTED.com'
  elasticUrl = 'REDACTED.com'

  # this works
  system("ssh -fN -o StrictHostKeyChecking=no -i ~/.ssh/#{privateKey} #{userName}@#{jumpBoxUrl} -p 22 -L 9999:#{elasticUrl}:9200 sleep 10 >> logfile")
  puts fetchData

  # wait for the ssh to time out
  sleep 5

  # Timed out reading data from server (RestClient::Exceptions::ReadTimeout) - WHY?!
  #
  Net::SSH.start(jumpBoxUrl, userName, :port=>22, :forward_agent=>true, :verbose=>:info, :keys=>["~/.ssh/#{privateKey}"]) do |session|
    session.forward.local(9999, elasticUrl, 9200)

    # this works - able to authenticate to the shell box
    puts session.exec!("ls -la")

    # this times out - data is not returned
    puts fetchData
  end
end

I expect the post to return the same data when using net-ssh as it does when using ssh.

Appreciate any help with what I'm missing in my net-ssh setup.


问:
mysql: need records only if the date is there at least once each day, the date should be repeated for 4 days from the current datetime
I have a table with 6 columns: failure date, ipaddress, assettag, sid(primary key), rdl and error type.
I need a table with columns as First failure, Recent(Last) failure, ipaddress, assettag, rdl
But the records are to be there only if the date is repeated for 4 days from the current datetime. Not even one single day to be missed.
Ex: If today is 30th May, I need all the records whose failure date is there every single day--30th, 29th, 28th, 27th. If a record date is there only for two/three/one day(s)--it has to be ignored.

I can get First and Last failures using "min(date) and max(date)-group by ipaddress" but not able to get the records as per the condition--"failure (date) to be repeated for 4 days from current datetime"

```<code>    select min(date), max(date), ipaddress, assettag, rdl
 from flashinglist.response
  where ((DATE_FORMAT((date_sub(NOW(), interval 24 hour)), '%y-%m-%d')) in
  (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress)
       and (DATE_FORMAT((date_sub(NOW(), interval 48 hour)), '%y-%m-%d')) in
        (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress)
        and (DATE_FORMAT((date_sub(NOW(), interval 72 hour)), '%y-%m-%d')) in
        (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress)
        and (DATE_FORMAT((date_sub(NOW(), interval 96 hour)), '%y-%m-%d')) in
        (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress) )
order by max(date) desc
</code>```

The above query should work as I am concatenating all dates group by IP and checking through 'IN' condition, but it doesn't work, not able to figure out why. (used 'date_format' to find only date instead of timestamp)

Below is the schema and sample data:

```<code>CREATE TABLE `response` (
  `date` varchar(50) NOT NULL,
  `ipaddress` varchar(16) NOT NULL,
  `assettag` varchar(200) NOT NULL,
  `sid` int(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `rdl` varchar(30) NOT NULL,
  `errortype` int(2) NOT NULL)
ENGINE=InnoDB DEFAULT CHARSET=latin1;
</code>```

Sample data:

```<code>INSERT INTO `response` (`date`, `ipaddress`, `assettag`, `sid`, `rdl`, `errortype`) VALUES
('2019-05-31 09:46:10.878', '123.34.45.67', 'fresh', 483, '13234', 1),
('2019-05-30 19:46:11.578', '123.34.45.67', 'fresh', 490, '13234', 1),
('2019-05-29 14:30:11.577', '123.34.45.67', 'fresh', 496, '13234', 1),
('2019-05-28 17:23:11.573', '123.34.45.67', 'fresh', 499, '13234', 1),
('2019-05-27 22:32:11.550', '123.34.45.67', 'fresh', 503, '13234', 1),
('2019-05-29 12:54:11.571', '457.673.768.24', 'store', 560, '9297', 1),
('2019-05-31 08:46:11.569', '457.673.768.24', 'store', 565, '9297', 1),
('2019-05-28 10:45:11.566', '457.673.768.24', 'store', 567, '9297', 1),
('2019-05-30 20:16:11.566', '457.673.768.24', 'store', 569, '9297', 1),
('2019-05-29 23:46:11.234', '140.232.546.74', 'sample', 580, '6076', 1),
('2019-05-31 09:26:11.562', '140.232.546.74', 'sample', 581, '6076', 1),
('2019-05-30 19:34:16.533', '140.232.546.74', 'sample', 583, '6076', 1);
COMMIT;
</code>```

Please change values according to today's date and the last 4 days.
My output should return First failure, Recent(Last) failure, ipaddress, assettag, rdl-- with the above sample data, it has to show IP records: 123.34.45.67 and 457.673.768.24 with corresponding max and min dates with in the range of 1 to 96 hours (4 days) only.
IP- 140.232.546.74 should not appear as it is the failure is not repeated for 4 days (28th date is missing). Hope this clears my question.

答:
Count the number of different dates in the result, and test if this is the required number.

```<code>SELECT  min(date) AS mindate, max(date) AS maxdate, date, ipaddress, assettag, rdl
FROM flashinglist.response
  WHERE  date < DATE_SUB(NOW(), interval 1 hour)
  AND date > date_sub(NOW(), interval 96 hour)
GROUP BY ipaddress
ORDER BY mindate DESC
HAVING COUNT(DISTINCT DATE(date)) = DATE_SUB(maxdate, mindate) + 1
</code>```

You also shouldn't have these lines:

```<code>  AND (date > date_sub(NOW(), interval 24 hour) )
  AND (date > date_sub(NOW(), interval 48 hour))
  AND (date > date_sub(NOW(), interval 72 hour))
</code>```

since they will exclude rows that are more than 1 day old.

Body:
I have a table with 6 columns: failure date, ipaddress, assettag, sid(primary key), rdl and error type.
I need a table with columns as First failure, Recent(Last) failure, ipaddress, assettag, rdl
But the records are to be there only if the date is repeated for 4 days from the current datetime. Not even one single day to be missed.
Ex: If today is 30th May, I need all the records whose failure date is there every single day--30th, 29th, 28th, 27th. If a record date is there only for two/three/one day(s)--it has to be ignored.

I can get First and Last failures using "min(date) and max(date)-group by ipaddress" but not able to get the records as per the condition--"failure (date) to be repeated for 4 days from current datetime"

    select min(date), max(date), ipaddress, assettag, rdl
 from flashinglist.response
  where ((DATE_FORMAT((date_sub(NOW(), interval 24 hour)), '%y-%m-%d')) in
  (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress)
       and (DATE_FORMAT((date_sub(NOW(), interval 48 hour)), '%y-%m-%d')) in
        (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress)
        and (DATE_FORMAT((date_sub(NOW(), interval 72 hour)), '%y-%m-%d')) in
        (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress)
        and (DATE_FORMAT((date_sub(NOW(), interval 96 hour)), '%y-%m-%d')) in
        (select group_concat((DATE_FORMAT(date,'%y-%m-%d')) separator ', ')
from flashinglist.response group by ipaddress) )
order by max(date) desc

The above query should work as I am concatenating all dates group by IP and checking through 'IN' condition, but it doesn't work, not able to figure out why. (used 'date_format' to find only date instead of timestamp)

Below is the schema and sample data:

CREATE TABLE `response` (
  `date` varchar(50) NOT NULL,
  `ipaddress` varchar(16) NOT NULL,
  `assettag` varchar(200) NOT NULL,
  `sid` int(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `rdl` varchar(30) NOT NULL,
  `errortype` int(2) NOT NULL)
ENGINE=InnoDB DEFAULT CHARSET=latin1;

Sample data:

INSERT INTO `response` (`date`, `ipaddress`, `assettag`, `sid`, `rdl`, `errortype`) VALUES
('2019-05-31 09:46:10.878', '123.34.45.67', 'fresh', 483, '13234', 1),
('2019-05-30 19:46:11.578', '123.34.45.67', 'fresh', 490, '13234', 1),
('2019-05-29 14:30:11.577', '123.34.45.67', 'fresh', 496, '13234', 1),
('2019-05-28 17:23:11.573', '123.34.45.67', 'fresh', 499, '13234', 1),
('2019-05-27 22:32:11.550', '123.34.45.67', 'fresh', 503, '13234', 1),
('2019-05-29 12:54:11.571', '457.673.768.24', 'store', 560, '9297', 1),
('2019-05-31 08:46:11.569', '457.673.768.24', 'store', 565, '9297', 1),
('2019-05-28 10:45:11.566', '457.673.768.24', 'store', 567, '9297', 1),
('2019-05-30 20:16:11.566', '457.673.768.24', 'store', 569, '9297', 1),
('2019-05-29 23:46:11.234', '140.232.546.74', 'sample', 580, '6076', 1),
('2019-05-31 09:26:11.562', '140.232.546.74', 'sample', 581, '6076', 1),
('2019-05-30 19:34:16.533', '140.232.546.74', 'sample', 583, '6076', 1);
COMMIT;

Please change values according to today's date and the last 4 days.
My output should return First failure, Recent(Last) failure, ipaddress, assettag, rdl-- with the above sample data, it has to show IP records: 123.34.45.67 and 457.673.768.24 with corresponding max and min dates with in the range of 1 to 96 hours (4 days) only.
IP- 140.232.546.74 should not appear as it is the failure is not repeated for 4 days (28th date is missing). Hope this clears my question.

Body:
Count the number of different dates in the result, and test if this is the required number.

SELECT  min(date) AS mindate, max(date) AS maxdate, date, ipaddress, assettag, rdl
FROM flashinglist.response
  WHERE  date < DATE_SUB(NOW(), interval 1 hour)
  AND date > date_sub(NOW(), interval 96 hour)
GROUP BY ipaddress
ORDER BY mindate DESC
HAVING COUNT(DISTINCT DATE(date)) = DATE_SUB(maxdate, mindate) + 1

You also shouldn't have these lines:

  AND (date > date_sub(NOW(), interval 24 hour) )
  AND (date > date_sub(NOW(), interval 48 hour))
  AND (date > date_sub(NOW(), interval 72 hour))

since they will exclude rows that are more than 1 day old.


问:
SVG textpath rendering appears reversed in Firefox
I'm trying to render text along a curved path in an SVG. It renders as expected in Chrome, Safari, and Edge, but it renders differently in Firefox.

jsfiddle: http://jsfiddle.net/hLyq1ug6/

```<code><svg width="320" height="320" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background: blue"><path d="m57.8,160 a102.2,102.2 0 1 1 204.4,0" fill="red" id="curvedTextPath5cf008a181659"></path><text x="160" y="185.5" style="fill: #ffffff; font-size: 35pt"><textPath xlink:href="#curvedTextPath5cf008a181659" startOffset="0" text-anchor="middle">Hello</textPath></text></svg>
</code>```

Expected:

Firefox:

答:
Per the SVG specification

When the inline-base direction is horizontal, then any ‘x’ attributes on ‘text’ or ‘tspan’ elements represent new absolute offsets along the path, thus providing explicit new values for startpoint-on-the-path.

It seems only Firefox does this correctly.

Body:
I'm trying to render text along a curved path in an SVG. It renders as expected in Chrome, Safari, and Edge, but it renders differently in Firefox.

jsfiddle: http://jsfiddle.net/hLyq1ug6/

<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background: blue"><path d="m57.8,160 a102.2,102.2 0 1 1 204.4,0" fill="red" id="curvedTextPath5cf008a181659"></path><text x="160" y="185.5" style="fill: #ffffff; font-size: 35pt"><textPath xlink:href="#curvedTextPath5cf008a181659" startOffset="0" text-anchor="middle">Hello</textPath></text></svg>

Expected:

Firefox:


问:
How do i draw a shape on a canvas after the second click
Ive figured out to draw the shape if i drag the mouse while holding down, but i need to be able to click in the canvas to set the first point, then click in the canvas a second time to set the second coordinates after which it will draw the shape.

class Canvas extends java.awt.Canvas implements MouseListener, MouseMotionListener {
    // Constants for shapes
    public static final int CIRCLE = 1;
    public static final int RECTANGLE = 2;

```<code>// Coordinates of points to draw
private int x1, y1, x2, y2;

// shape to draw
private int shape = CIRCLE;
private final int PAINT = 0; // do we need to draw current component
private final int NOPAINT = 1; // we dont need to draw current componet
private int paintOrRepaint = NOPAINT;// at the beginning we dont need to draw

public void setShape(int shape) {
    this.shape = shape;
}

// filled color
private Color filledColor = null;

public void setFilledColor(Color color) {
    filledColor = color;
}

public Canvas() {
    addMouseListener(this);
    addMouseMotionListener(this);
} // end of constructor

@Override
public void paint(Graphics g) {
    // the drawing area
    int x, y, width, height;

    // determine the upper-left corner of bounding rectangle
    x = Math.min(x1, x2);
    y = Math.min(y1, y2);

    // determine the width and height of bounding rectangle
    width = Math.abs(x1 - x2);
    height = Math.abs(y1 - y2);

    // current shape(cur_shape) : by default it is a line after using a switch we update this to
    // circle of rectangle
    Shape cur_shape = new Line2D.Double(x1, y1, x2, y2);
    switch (shape) {
        case RECTANGLE :
            cur_shape = new Rectangle2D.Double(x, y, width, height);
            break;
        case CIRCLE :
            int diameter = Math.max(width, height);
            cur_shape = new Ellipse2D.Double(x,y, diameter, diameter);
            break;
    }

    if(paintOrRepaint == PAINT){
        Figure sh;
        if(shape == RECTANGLE) {
            sh = new Rectangle(cur_shape,filledColor, shape);
            GUI.shapes.add(sh);
        }
        else if(shape == CIRCLE) {
            sh = new Circle(cur_shape,filledColor, shape);
            GUI.shapes.add(sh);
        }
    }

    Graphics2D graphics = (Graphics2D) g;
    for (Figure s : GUI.shapes) {

        if(s.fill != null)
            g.setColor(s.fill);
        else
            g.setColor(Color.BLACK);
        if(s.fill != null)
            graphics.fill(s.shape);
        else
            graphics.draw(s.shape);
    }
    GUI.updateShapes();
    setPaintOrRepaint(NOPAINT);

    GUI.selectColor = false;
    GUI.selectShape = false;
}

@Override
public void mousePressed(MouseEvent event) {
    x1 = event.getX();
    y1 = event.getY();

}

@Override
public void mouseReleased(MouseEvent event) {
    x2 = event.getX();
    y2 = event.getY();

    setPaintOrRepaint(PAINT);
    repaint();

}

@Override
public void mouseClicked(MouseEvent evt) { }
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}

@Override
public void mouseDragged(MouseEvent event) {
    x2 = event.getX();
    y2 = event.getY();
}

@Override
public void mouseMoved(MouseEvent e) {}

private void setPaintOrRepaint(int option) {
    paintOrRepaint = option;
}
</code>```

}

答:
Your points need to be stored in an array or list.  So what you do is you use a MouseListener and MouseMotionListener (use MouseAdapter for this).

For the first point and others, set it in mouseClicked().  As you click the mouse store the point in the data structure of your chosing.

If you drag the mouse, you will get a stream of points so I don't know how useful that would be (unless you want to draw lines and save the coordinates).

Not that if you use an inner class and extend MouseAdapter you can get rid of the clutter of implementing the listeners independently.  Since MouseAdapter implements both listeners with empty methods, you just override the ones you need and then use an instance of your own MouseListener.

class MyMouseListener extends MouseAdapter {
   // your overriden methods go here.
   // you only need to override the ones you need.
}
```

<p>Then</p>

<pre class="lang-java prettyprint-override"><code>MyMouseListener ml = new MyMouseListener();
addMouseListener(ml);
addMouseMotionListener(ml);
</code>```

I'm not certain how you are painting but typically it is done on a JPanel which is contained by a JFrame.  In JPanel you would override paintComponent(g) as follows.

public void paintComponent(Graphics g) {
    super.paintComponent(g);
   // your stuff here
}
```

Body:
Ive figured out to draw the shape if i drag the mouse while holding down, but i need to be able to click in the canvas to set the first point, then click in the canvas a second time to set the second coordinates after which it will draw the shape.

class Canvas extends java.awt.Canvas implements MouseListener, MouseMotionListener {
    // Constants for shapes
    public static final int CIRCLE = 1;
    public static final int RECTANGLE = 2;

// Coordinates of points to draw
private int x1, y1, x2, y2;

// shape to draw
private int shape = CIRCLE;
private final int PAINT = 0; // do we need to draw current component
private final int NOPAINT = 1; // we dont need to draw current componet
private int paintOrRepaint = NOPAINT;// at the beginning we dont need to draw

public void setShape(int shape) {
    this.shape = shape;
}

// filled color
private Color filledColor = null;

public void setFilledColor(Color color) {
    filledColor = color;
}

public Canvas() {
    addMouseListener(this);
    addMouseMotionListener(this);
} // end of constructor

@Override
public void paint(Graphics g) {
    // the drawing area
    int x, y, width, height;

    // determine the upper-left corner of bounding rectangle
    x = Math.min(x1, x2);
    y = Math.min(y1, y2);

    // determine the width and height of bounding rectangle
    width = Math.abs(x1 - x2);
    height = Math.abs(y1 - y2);

    // current shape(cur_shape) : by default it is a line after using a switch we update this to
    // circle of rectangle
    Shape cur_shape = new Line2D.Double(x1, y1, x2, y2);
    switch (shape) {
        case RECTANGLE :
            cur_shape = new Rectangle2D.Double(x, y, width, height);
            break;
        case CIRCLE :
            int diameter = Math.max(width, height);
            cur_shape = new Ellipse2D.Double(x,y, diameter, diameter);
            break;
    }

    if(paintOrRepaint == PAINT){
        Figure sh;
        if(shape == RECTANGLE) {
            sh = new Rectangle(cur_shape,filledColor, shape);
            GUI.shapes.add(sh);
        }
        else if(shape == CIRCLE) {
            sh = new Circle(cur_shape,filledColor, shape);
            GUI.shapes.add(sh);
        }
    }

    Graphics2D graphics = (Graphics2D) g;
    for (Figure s : GUI.shapes) {

        if(s.fill != null)
            g.setColor(s.fill);
        else
            g.setColor(Color.BLACK);
        if(s.fill != null)
            graphics.fill(s.shape);
        else
            graphics.draw(s.shape);
    }
    GUI.updateShapes();
    setPaintOrRepaint(NOPAINT);

    GUI.selectColor = false;
    GUI.selectShape = false;
}

@Override
public void mousePressed(MouseEvent event) {
    x1 = event.getX();
    y1 = event.getY();

}

@Override
public void mouseReleased(MouseEvent event) {
    x2 = event.getX();
    y2 = event.getY();

    setPaintOrRepaint(PAINT);
    repaint();

}

@Override
public void mouseClicked(MouseEvent evt) { }
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}

@Override
public void mouseDragged(MouseEvent event) {
    x2 = event.getX();
    y2 = event.getY();
}

@Override
public void mouseMoved(MouseEvent e) {}

private void setPaintOrRepaint(int option) {
    paintOrRepaint = option;
}

}

Body:
Your points need to be stored in an array or list.  So what you do is you use a MouseListener and MouseMotionListener (use MouseAdapter for this).

For the first point and others, set it in mouseClicked().  As you click the mouse store the point in the data structure of your chosing.

If you drag the mouse, you will get a stream of points so I don't know how useful that would be (unless you want to draw lines and save the coordinates).

Not that if you use an inner class and extend MouseAdapter you can get rid of the clutter of implementing the listeners independently.  Since MouseAdapter implements both listeners with empty methods, you just override the ones you need and then use an instance of your own MouseListener.

class MyMouseListener extends MouseAdapter {
   // your overriden methods go here.
   // you only need to override the ones you need.
}

Then

MyMouseListener ml = new MyMouseListener();
addMouseListener(ml);
addMouseMotionListener(ml);

I'm not certain how you are painting but typically it is done on a JPanel which is contained by a JFrame.  In JPanel you would override paintComponent(g) as follows.

public void paintComponent(Graphics g) {
    super.paintComponent(g);
   // your stuff here
}


问:
efficient way to get words before and after substring in text (python)
I'm using regex to find occurrences of string patterns in a body of text. Once I find that the string pattern occurs, I want to get x words before and after the string as well (x could be as small as 4, but preferably ~10 if still as efficient).

I am currently using regex to find all instances, but occasionally it will hang. Is there a more efficient way to solve this problem?

This is the solution I currently have:

```<code>sub = r'(\w*)\W*(\w*)\W*(\w*)\W*(\w*)\W*(%s)\W*(\w*)\W*(\w*)\W*(\w*)\W*(\w*)' % result_string #refind string and get surrounding += 4 words
surrounding_text = re.findall(sub, text)
for found_text in surrounding_text:
  result_found.append(" ".join(map(str,found_text)))
</code>```

答: I personally think that using text.partition() is the best option, as it eliminates the messy regular expressions, and automatically leaves output in an easy-to-access tuple.</p>

ContentLicense: CC BY-SA 3.0

Body:
I'm using regex to find occurrences of string patterns in a body of text. Once I find that the string pattern occurs, I want to get x words before and after the string as well (x could be as small as 4, but preferably ~10 if still as efficient).

I am currently using regex to find all instances, but occasionally it will hang. Is there a more efficient way to solve this problem?

This is the solution I currently have:

sub = r'(\w*)\W*(\w*)\W*(\w*)\W*(\w*)\W*(%s)\W*(\w*)\W*(\w*)\W*(\w*)\W*(\w*)' % result_string #refind string and get surrounding += 4 words
surrounding_text = re.findall(sub, text)
for found_text in surrounding_text:
  result_found.append(" ".join(map(str,found_text)))


问:
slf4j logger doesn't print full package name
I have a project with some classes using org.slf4j.Logger to log some information. The loggers in all other classes are working OK and print full class name, e.g. INFO com.myapp.gca.servlet.LoginServlet - Entering login. But for one class, it doesn't print full class name, e.g. INFO c.m.gca.servlet.HealthCheckServlet - GCA health check OK, where com.myapp. is replaced by c.m..

I couldn't find any difference in this particular class from others. The logger is defined like

```<code> private static Logger log = LoggerFactory.getLogger(HealthCheckServlet.class);
</code>```

What may be the reason?

答:
Use %logger{26} in pattern in logback.xml.

For more details, refer this link.

https://logback.qos.ch/manual/layouts.html

Body:
I have a project with some classes using org.slf4j.Logger to log some information. The loggers in all other classes are working OK and print full class name, e.g. INFO com.myapp.gca.servlet.LoginServlet - Entering login. But for one class, it doesn't print full class name, e.g. INFO c.m.gca.servlet.HealthCheckServlet - GCA health check OK, where com.myapp. is replaced by c.m..

I couldn't find any difference in this particular class from others. The logger is defined like

 private static Logger log = LoggerFactory.getLogger(HealthCheckServlet.class);

What may be the reason?


问:
Sorting lines and removing all but one line based on the last string?
searching for a solution to my problem I found this thread: Sorting on the last field of a line

I used some solutions for sorting using sed and awk and they work, one more thing I need is to delete all but one line based on last string in a line.

Example, I have:

```<code>www.site.com/324242_1234
www.site.com/233_1234
www.site.com/45357_1234
www.site.com/6545_2345
www.site.com/5433_2345
www.site.com/87745_456
www.site.com/453209_456
www.site.com/1345_456
</code>```

Need this result:

```<code>www.site.com/324242_1234
www.site.com/6545_2345
www.site.com/87745_456
</code>```

So I need to keep only one line that contains that last string, in this example they are separated by underline. I appreciate help.

答:
```<code>$ sort -t_ -u -k2 file

www.site.com/324242_1234
www.site.com/6545_2345
www.site.com/87745_456
</code>```

assumes there are no preceding underscores.

awk solution can be

```<code>$ awk -F_ '!a[$NF]++' file

www.site.com/324242_1234
www.site.com/6545_2345
www.site.com/87745_456
</code>```

Explanation After setting the field delimiter, $NF refers to the last field, a[$NF]++ counts the occurrences of each value starting with zero.  !a[$NF]++ negates the value, so it will only be true when the count is zero, which is the first instance of the key value looked.  This site has many examples of this awk idiom.

Body:
searching for a solution to my problem I found this thread: Sorting on the last field of a line

I used some solutions for sorting using sed and awk and they work, one more thing I need is to delete all but one line based on last string in a line.

Example, I have:

www.site.com/324242_1234
www.site.com/233_1234
www.site.com/45357_1234
www.site.com/6545_2345
www.site.com/5433_2345
www.site.com/87745_456
www.site.com/453209_456
www.site.com/1345_456

Need this result:

www.site.com/324242_1234
www.site.com/6545_2345
www.site.com/87745_456

So I need to keep only one line that contains that last string, in this example they are separated by underline. I appreciate help.

Body:
$ sort -t_ -u -k2 file

www.site.com/324242_1234
www.site.com/6545_2345
www.site.com/87745_456

assumes there are no preceding underscores.

awk solution can be

$ awk -F_ '!a[$NF]++' file

www.site.com/324242_1234
www.site.com/6545_2345
www.site.com/87745_456

Explanation After setting the field delimiter, $NF refers to the last field, a[$NF]++ counts the occurrences of each value starting with zero.  !a[$NF]++ negates the value, so it will only be true when the count is zero, which is the first instance of the key value looked.  This site has many examples of this awk idiom.


问:
Bottom Navigation View setup with fragment navigation component not working
I tried implementing the bottom navigation view to set up with fragment transition using navigation components by referring Navigation Codelab.

The fragments are not changing when clicking on the bottom navigation view.

Note:

I am trying to implement the bottom navigation view inside another fragment. (Not an activity like in the codelab example)

MainActivity.kt:

```<code>class MainActivity : AppCompatActivity() {

    // Data binding
    private lateinit var mainActivityBinding: MainActivityBinding

    // On activity creation starting
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Set activity layout
        mainActivityBinding = DataBindingUtil.setContentView(this, R.layout.main_activity)
    }
}
</code>```

main_activity.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".activity.MainActivity">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_activity_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/main_activity_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/activity_navigation" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>
</code>```

activity_navigation.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_navigation"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.appz.abhi.moneytracker.view.main.MainFragment"
        android:label="main_fragment"
        tools:layout="@layout/main_fragment" />

</navigation>
</code>```

MainFragment.kt:

```<code>class MainFragment : Fragment() {

    // Data binding
    private var mainFragmentBinding: MainFragmentBinding? = null

    // On fragment view creation starting
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {

        // Inflate the fragment layout
        mainFragmentBinding = DataBindingUtil
                .inflate(inflater, R.layout.main_fragment, container, false)

        // Return root view
        return mainFragmentBinding!!.root
    }

    // On fragment view creation completion
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Initialize UI
        initUI()
    }

    // Initialize UI
    private fun initUI() {

        // Setup action bar
        (activity as AppCompatActivity).setSupportActionBar(mainFragmentBinding?.mainFragmentToolbar)

        // Setup bottom navigation view
        setUpBottomNavigationView()
    }

    // Setup bottom navigation view
    private fun setUpBottomNavigationView() {

        // Nav host fragment
        val host: NavHostFragment = activity?.supportFragmentManager
                ?.findFragmentById(R.id.main_fragment_nav_host_fragment) as NavHostFragment?
                ?: return

        // Set up Action Bar
        val navController = host.navController

        // Setup bottom navigation view
        mainFragmentBinding?.mainFragmentBottomNavigationView?.setupWithNavController(navController)
    }
}
</code>```

main_fragment.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".view.main.MainFragment">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_fragment_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/main_fragment_app_bar_layout"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/main_fragment_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@drawable/toolbar_background"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                tools:title="Money Tracker" />

        </com.google.android.material.appbar.AppBarLayout>

        <fragment
            android:id="@+id/main_fragment_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/main_fragment_app_bar_layout"
            app:navGraph="@navigation/bottom_navigation_view_navigation" />

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/main_fragment_bottom_navigation_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@color/white"
            app:itemIconTint="@color/bottom_navigation"
            app:itemTextColor="@color/bottom_navigation"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/bottom_navigation_view_menu"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>
</code>```

bottom_navigation_view_navigation.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bottom_navigation_view_navigation"
    app:startDestination="@id/settingsFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.appz.abhi.moneytracker.view.home.HomeFragment"
        android:label="Home"
        tools:layout="@layout/home_fragment" />

    <fragment
        android:id="@+id/settingsFragment"
        android:name="com.appz.abhi.moneytracker.view.settings.SettingsFragment"
        android:label="Settings"
        tools:layout="@layout/settings_fragment" />

</navigation>
</code>```

bottom_navigation_view_menu:

```<code><?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@id/homeFragment"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/home"
        app:showAsAction="ifRoom" />

    <item
        android:id="@id/settingsFragment"
        android:icon="@drawable/ic_settings_black_24dp"
        android:title="@string/settings"
        app:showAsAction="ifRoom" />

</menu>
</code>```

HomeFragment.kt:

```<code>class HomeFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.home_fragment, container, false)
    }
}
</code>```

SettingsFragment.kt:

```<code>class SettingsFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.settings_fragment, container, false)
    }
}
</code>```

答:
NOTE: I don't have experience with Kotlin but I'm assuming the implementation is similar enough in Java.

It seems odd that you are doing the bottom navigation inside a fragment where in my experience the bottom nav bar goes in the activity and you programmatically set the first fragment. The fragments that come into view using the navigation bar populate a FrameLayout that sits above the nav bar in the activity.

Here is an example in Java.

MainActivity.java

public class HomeActivity extends AppCompatActivity {

    private String currentFragmentTag;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            /* I just put some filler code but each fragment type will probably
 be different */
            switch (item.getItemId()) {
                case R.id.fragment_one:
                    CustomFragment fragment = new CustomFragment();
                    if (!currentFragmentTag.equals(fragment.fragmentTag)) {
                        switchFragment(customFragment, null);
                    }
                    return true;
                case R.id.fragment_two:
                    CustomFragment fragment = new CustomFragment();
                    if (!currentFragmentTag.equals(fragment.fragmentTag)) {
                        switchFragment(customFragment, null);
                    }
                    return true;
                 case ....
            }
            return false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        currentFragmentTag = "FIRST_FRAGMENT";
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    }

    /**
     * Select fragment.
     */
    public void switchFragment(Fragment fragment, String tag) {
        getSupportFragmentManager().beginTransaction().replace(R.id.home_frame, fragment, tag)
                .addToBackStack(tag).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit();

    }

```

<p>MaiActivity layout file</p>

<pre class="lang-xml prettyprint-override"><code>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activities.MainActivity">

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/background_grey"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/navigation" />

    <FrameLayout
        android:id="@+id/home_frame"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </FrameLayout>

</android.support.constraint.ConstraintLayout>
</code>```

Body:
I tried implementing the bottom navigation view to set up with fragment transition using navigation components by referring Navigation Codelab.

The fragments are not changing when clicking on the bottom navigation view.

Note:

I am trying to implement the bottom navigation view inside another fragment. (Not an activity like in the codelab example)

MainActivity.kt:

class MainActivity : AppCompatActivity() {

    // Data binding
    private lateinit var mainActivityBinding: MainActivityBinding

    // On activity creation starting
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Set activity layout
        mainActivityBinding = DataBindingUtil.setContentView(this, R.layout.main_activity)
    }
}

main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".activity.MainActivity">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_activity_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/main_activity_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/activity_navigation" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

activity_navigation.xml:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_navigation"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.appz.abhi.moneytracker.view.main.MainFragment"
        android:label="main_fragment"
        tools:layout="@layout/main_fragment" />

</navigation>

MainFragment.kt:

class MainFragment : Fragment() {

    // Data binding
    private var mainFragmentBinding: MainFragmentBinding? = null

    // On fragment view creation starting
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {

        // Inflate the fragment layout
        mainFragmentBinding = DataBindingUtil
                .inflate(inflater, R.layout.main_fragment, container, false)

        // Return root view
        return mainFragmentBinding!!.root
    }

    // On fragment view creation completion
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Initialize UI
        initUI()
    }

    // Initialize UI
    private fun initUI() {

        // Setup action bar
        (activity as AppCompatActivity).setSupportActionBar(mainFragmentBinding?.mainFragmentToolbar)

        // Setup bottom navigation view
        setUpBottomNavigationView()
    }

    // Setup bottom navigation view
    private fun setUpBottomNavigationView() {

        // Nav host fragment
        val host: NavHostFragment = activity?.supportFragmentManager
                ?.findFragmentById(R.id.main_fragment_nav_host_fragment) as NavHostFragment?
                ?: return

        // Set up Action Bar
        val navController = host.navController

        // Setup bottom navigation view
        mainFragmentBinding?.mainFragmentBottomNavigationView?.setupWithNavController(navController)
    }
}

main_fragment.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".view.main.MainFragment">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_fragment_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/main_fragment_app_bar_layout"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/main_fragment_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@drawable/toolbar_background"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                tools:title="Money Tracker" />

        </com.google.android.material.appbar.AppBarLayout>

        <fragment
            android:id="@+id/main_fragment_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/main_fragment_app_bar_layout"
            app:navGraph="@navigation/bottom_navigation_view_navigation" />

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/main_fragment_bottom_navigation_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@color/white"
            app:itemIconTint="@color/bottom_navigation"
            app:itemTextColor="@color/bottom_navigation"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/bottom_navigation_view_menu"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

bottom_navigation_view_navigation.xml:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bottom_navigation_view_navigation"
    app:startDestination="@id/settingsFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.appz.abhi.moneytracker.view.home.HomeFragment"
        android:label="Home"
        tools:layout="@layout/home_fragment" />

    <fragment
        android:id="@+id/settingsFragment"
        android:name="com.appz.abhi.moneytracker.view.settings.SettingsFragment"
        android:label="Settings"
        tools:layout="@layout/settings_fragment" />

</navigation>

bottom_navigation_view_menu:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@id/homeFragment"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/home"
        app:showAsAction="ifRoom" />

    <item
        android:id="@id/settingsFragment"
        android:icon="@drawable/ic_settings_black_24dp"
        android:title="@string/settings"
        app:showAsAction="ifRoom" />

</menu>

HomeFragment.kt:

class HomeFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.home_fragment, container, false)
    }
}

SettingsFragment.kt:

class SettingsFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.settings_fragment, container, false)
    }
}

Body:
NOTE: I don't have experience with Kotlin but I'm assuming the implementation is similar enough in Java.

It seems odd that you are doing the bottom navigation inside a fragment where in my experience the bottom nav bar goes in the activity and you programmatically set the first fragment. The fragments that come into view using the navigation bar populate a FrameLayout that sits above the nav bar in the activity.

Here is an example in Java.

MainActivity.java

public class HomeActivity extends AppCompatActivity {

    private String currentFragmentTag;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            /* I just put some filler code but each fragment type will probably
 be different */
            switch (item.getItemId()) {
                case R.id.fragment_one:
                    CustomFragment fragment = new CustomFragment();
                    if (!currentFragmentTag.equals(fragment.fragmentTag)) {
                        switchFragment(customFragment, null);
                    }
                    return true;
                case R.id.fragment_two:
                    CustomFragment fragment = new CustomFragment();
                    if (!currentFragmentTag.equals(fragment.fragmentTag)) {
                        switchFragment(customFragment, null);
                    }
                    return true;
                 case ....
            }
            return false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        currentFragmentTag = "FIRST_FRAGMENT";
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    }

    /**
     * Select fragment.
     */
    public void switchFragment(Fragment fragment, String tag) {
        getSupportFragmentManager().beginTransaction().replace(R.id.home_frame, fragment, tag)
                .addToBackStack(tag).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit();

    }

MaiActivity layout file

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activities.MainActivity">

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/background_grey"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/navigation" />

    <FrameLayout
        android:id="@+id/home_frame"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </FrameLayout>

</android.support.constraint.ConstraintLayout>


问:
YouTube API v3 Search List - Querying Multiple Channel IDs Not Working
When including multiple YouTube channel ids the response does not return a result.

Expected

Returning video results from multiple channel ids with the API request.

Request

GET https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCiAW4HQiYjpPmyi4v905u1A%2C+UCrFCDzgIucPi7x_OzsYefWQ&key={YOUR_API_KEY}

Observed

Response

The response is empty.

```<code>{
 "kind": "youtube#searchListResponse",
 "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/-f6JA5_OcXz2RWuH1mpAA2_9mM8\"",
 "regionCode": "US",
 "pageInfo": {
  "totalResults": 0,
  "resultsPerPage": 5
 },
 "items": [
 ]
}
</code>```

答:
Channel's request accepts multiple channel IDs like below:
https://www.googleapis.com/youtube/v3/channels?part=snippet&id=UCiAW4HQiYjpPmyi4v905u1A%2CUCrFCDzgIucPi7x_OzsYefWQ&key={YOUR_API_KEY}

But nowadays there no way to get video IDs directly from channels API response, you have to set "part=snippet%2CcontentDetails" in channel request part, and then fetch ID of list uploaded videos in response ("relatedPlaylists" -> "uploads"). Then you can get whole channel's videos ID's by playListItems request: https://developers.google.com/youtube/v3/docs/playlistItems

Body:
When including multiple YouTube channel ids the response does not return a result.

Expected

Returning video results from multiple channel ids with the API request.

Request

GET https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCiAW4HQiYjpPmyi4v905u1A%2C+UCrFCDzgIucPi7x_OzsYefWQ&key={YOUR_API_KEY}

Observed

Response

The response is empty.

{
 "kind": "youtube#searchListResponse",
 "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/-f6JA5_OcXz2RWuH1mpAA2_9mM8\"",
 "regionCode": "US",
 "pageInfo": {
  "totalResults": 0,
  "resultsPerPage": 5
 },
 "items": [
 ]
}


问:
Debug stored procedure with user defined data type
Is it possible to debug a stored procedure with a user defined data type as a parameter?

Edit: which is the syntax to call it? (exec ....)

My type:

```<code>CREATE TYPE [dbo].[FacturaInspeccion] AS TABLE(
    [sIdServicio] [nvarchar](3) NOT NULL,
    [nIdTipoInspeccion] [int] NOT NULL,
    [sIdTipoMotivoInspeccion] [nvarchar](2) NOT NULL,
    [nIdTipoVehiculo] [int] NOT NULL,
    [nBase] [real] NOT NULL,
    [nNoPeriodica] [real] NULL,
    [nTarifaConProyecto] [real] NULL,
    [nTarifaSinyecto] [real] NULL,
    [nTasaTrafico] [real] NULL,
    [nDescuento] [real] NULL,
    [nTotal] [float] NULL
</code>```

)

  GO

答:
Yes you can debug it normally, but you unfortunately don't get a good view on the data in the TVP.

See the following Microsoft Connect items for more info (and vote if you want to get better support for debugging TVPs ;) ).

Body:
Is it possible to debug a stored procedure with a user defined data type as a parameter?

Edit: which is the syntax to call it? (exec ....)

My type:

CREATE TYPE [dbo].[FacturaInspeccion] AS TABLE(
    [sIdServicio] [nvarchar](3) NOT NULL,
    [nIdTipoInspeccion] [int] NOT NULL,
    [sIdTipoMotivoInspeccion] [nvarchar](2) NOT NULL,
    [nIdTipoVehiculo] [int] NOT NULL,
    [nBase] [real] NOT NULL,
    [nNoPeriodica] [real] NULL,
    [nTarifaConProyecto] [real] NULL,
    [nTarifaSinyecto] [real] NULL,
    [nTasaTrafico] [real] NULL,
    [nDescuento] [real] NULL,
    [nTotal] [float] NULL

)

  GO


问:
C++ Palindrome checking solution is tripped by one test case
Given a string s, check if it is possible to make it a palindrome by deleting AT MOST one character (meaning zero deletions is acceptable). String s will contain <50,000 lowercase alphabetical characters.

The code I wrote below passed 458/460 test cases, and it got stuck on one in particular with no obvious reason, returning false instead of true. The logic of the algorithm is simple, and I've tried moving conditionals around but nothing seems to change.

class Solution {
  public:
    bool ispalindrome; //holds result
    bool validPalindrome(string s) {
        bool candelete = true; //allows one delete
        ispalindrome = true; //initial condition
        int lcursor = 0;
        int rcursor = s.length() - 1;
        while(lcursor < rcursor && ispalindrome){
            //if cursor points at different letters
            if(s[lcursor] != s[rcursor]){
                // if delete is still allowed and delete works
                if(s[lcursor + 1] == s[rcursor] && candelete){
                    lcursor++;
                    candelete = false;
                } else if (s[lcursor] == s[rcursor - 1] && candelete){
                    rcursor--;
                    candelete = false;
                } else {
                    ispalindrome = false;
                }
            }
            lcursor++;
            rcursor--;
        }
        return ispalindrome;
    }
};
```

<p>The test case that trips this solution is as follows:</p>

```aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga
```

<p>Code testing with this testcase:</p>

<pre class="lang-cpp prettyprint-override"><code>#include <iostream>
using std::string;

// class Solution { ... etc., from above

int main() {
  string s = "aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga";
  std::cout << Solution().validPalindrome(s) << std::endl;
};
</code>```

答:
If there is a case where the cursor points at different letters, and a character can be deleted from either the left or right cursors, your algorithm will only check with a delete from the left.  If a palindrome is formed by deleting from the right, instead, your code will miss it.

So if you delete from the left, you need to also check if a delete from the right is possible and (potentially) check that if there is no palindrome when deleting from the left.

Body:
Given a string s, check if it is possible to make it a palindrome by deleting AT MOST one character (meaning zero deletions is acceptable). String s will contain <50,000 lowercase alphabetical characters.

The code I wrote below passed 458/460 test cases, and it got stuck on one in particular with no obvious reason, returning false instead of true. The logic of the algorithm is simple, and I've tried moving conditionals around but nothing seems to change.

class Solution {
  public:
    bool ispalindrome; //holds result
    bool validPalindrome(string s) {
        bool candelete = true; //allows one delete
        ispalindrome = true; //initial condition
        int lcursor = 0;
        int rcursor = s.length() - 1;
        while(lcursor < rcursor && ispalindrome){
            //if cursor points at different letters
            if(s[lcursor] != s[rcursor]){
                // if delete is still allowed and delete works
                if(s[lcursor + 1] == s[rcursor] && candelete){
                    lcursor++;
                    candelete = false;
                } else if (s[lcursor] == s[rcursor - 1] && candelete){
                    rcursor--;
                    candelete = false;
                } else {
                    ispalindrome = false;
                }
            }
            lcursor++;
            rcursor--;
        }
        return ispalindrome;
    }
};

The test case that trips this solution is as follows:

aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga

Code testing with this testcase:

#include <iostream>
using std::string;

// class Solution { ... etc., from above

int main() {
  string s = "aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga";
  std::cout << Solution().validPalindrome(s) << std::endl;
};


问:
How to pass Token while calling a RESTful Webservice in Informatica
Need to call a RESTfull webservice from Informatica powercenter. it has a never expiring token for authorization.

Tried calling the webservie using HTTP transformation and passing the access token in the header. it works fine and webservice returns the result. But everyone can see the token once mapping is checked out.

How can we manage the token, store in encoded format or is there a away to create application connection to store the token ?

答:
Here is what we do in Informatica world to protect the sensitive data like password and so on.

You store the value in a file and put it inside a folder.
Make the folder invisible / restrict access to read only for that informatica unix user and rest users have 0 permission.
Once it is done, create a parameter in the file and use that file as a parameter for the informatica mapping, so when ever the mapping runs, it will go and pick up the parameter from the file, which the informatica user can only read, and run the mapping .

This prevents
1. Hard coding sensitive elements in the mapping
2. Hiding the sensitive data from all other Unix users other than Informatica unix user, thereby protecting the data


问:
Generate code for core data attributes in xcode 4
In xcode 3 there was a helpful feature in the data model builder where you could highlight some attributes/relationships in an entity, right-click, and choose to copy method and property declarations to the clipboard. (You could choose if you wanted objective-c 2.0 property declarations also). Then you could paste them into your NSManagedObject subclass.

I see how you can still generate the entire class file; but this isn't helpful if you are adding attributes to an existing entity. Have they removed this feature from xcode 4? I used it all the time!

答: Watch out for the fact that the special paste menu item only appears in the Edit menu not the contextual menu in the source editor.</p>

ContentLicense: CC BY-SA 2.5


问:
Calculate height of div based off width & maintain proportion
I am looking for a pure CSS solution to what I have here done using jQuery to help.

Basically I have 3 divs that spread evenly in width in a container. They maintain a 3/4 ration with the height being calculated off of the width. Furthermore, each div has a background image that stays proportional and some text that is centered horizontally and vertically.

$(document).ready(function() {
  function setw() {
    var footdivwidth = $('footer div').width();
    var footdivheight = footdivwidth * .75;
    $('footer div').css({
      'height': footdivheight + 'px'
    });
    $('footer div span').html('w: ' + footdivwidth + '
h: ' + footdivheight);
  }
  setw();
  $(window).resize(function() {
    setw();
  })
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>FOOTER {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}

FOOTER DIV SPAN {
  display: inline-block;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}</code>```

left photo

center photo

right photo and more text

```
</div>
</div>
</p>

<p>Here is a pen showing what I have.
https://codepen.io/nom3d/pen/arGpBV</p>

<p>Here is a gif showing the effect when resized. Note the background image staying proportional and text staying centered.
<img src="https://i.stack.imgur.com/OyB78.gif" alt="3 box resize with proportions kept"></p>

<p>Also wondering if it's not possible with just CSS, how to do this with <strong>plain javascript</strong>, would I need to add id's to my divs?</p>

<p>Update: here is a plain javaScript function to handle this task</p>

```function setHeight(el,val){
    var box = document.querySelectorAll(el);
    var i;
    for(i = 0;i < box.length;i++){
        var width = box[i].offsetWidth;
        var height = width * val;
        box[i].style.height = height + 'px';
    }
}
// set your element to target and the ratio value
setHeight('footer div',.75);
window.onresize = function(event) {
    setHeight('footer div',.75);
};
```

答:
You can simply consider the basic trick for maitaining the aspect ratio using padding.

Here is an example where I kept both examples so you can compare, the one using jQuery and the other using pure CSS.

$(document).ready(function() {
  function setw() {
    var footdivwidth = $('footer div').width();
    var footdivheight = footdivwidth * .75;
    $('footer.no-padd div').css({
      'height': footdivheight + 'px'
    });
    $('footer div span').html('w: ' + footdivwidth + '
h: ' + footdivheight);
  }
  setw();
  $(window).resize(function() {
    setw();
  })
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>FOOTER {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex
}
FOOTER:not(.no-padd) DIV:before {
  content:"";
  padding-top: 75%;
}

FOOTER DIV SPAN {
  margin:auto;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}</code>```

left photo

center photo

right photo and more text

left photo

center photo

right photo and more text

```

Body:
I am looking for a pure CSS solution to what I have here done using jQuery to help.

Basically I have 3 divs that spread evenly in width in a container. They maintain a 3/4 ration with the height being calculated off of the width. Furthermore, each div has a background image that stays proportional and some text that is centered horizontally and vertically.

$(document).ready(function() {
  function setw() {
    var footdivwidth = $('footer div').width();
    var footdivheight = footdivwidth * .75;
    $('footer div').css({
      'height': footdivheight + 'px'
    });
    $('footer div span').html('w: ' + footdivwidth + '
h: ' + footdivheight);
  }
  setw();
  $(window).resize(function() {
    setw();
  })
});

FOOTER {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}

FOOTER DIV SPAN {
  display: inline-block;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}

left photo

center photo

right photo and more text

Here is a pen showing what I have.
https://codepen.io/nom3d/pen/arGpBV

Here is a gif showing the effect when resized. Note the background image staying proportional and text staying centered.

Also wondering if it's not possible with just CSS, how to do this with plain javascript, would I need to add id's to my divs?

Update: here is a plain javaScript function to handle this task

function setHeight(el,val){
    var box = document.querySelectorAll(el);
    var i;
    for(i = 0;i < box.length;i++){
        var width = box[i].offsetWidth;
        var height = width * val;
        box[i].style.height = height + 'px';
    }
}
// set your element to target and the ratio value
setHeight('footer div',.75);
window.onresize = function(event) {
    setHeight('footer div',.75);
};

Body:
You can simply consider the basic trick for maitaining the aspect ratio using padding.

Here is an example where I kept both examples so you can compare, the one using jQuery and the other using pure CSS.

$(document).ready(function() {
  function setw() {
    var footdivwidth = $('footer div').width();
    var footdivheight = footdivwidth * .75;
    $('footer.no-padd div').css({
      'height': footdivheight + 'px'
    });
    $('footer div span').html('w: ' + footdivwidth + '<br>h: ' + footdivheight);
  }
  setw();
  $(window).resize(function() {
    setw();
  })
});

FOOTER {
  max-width: 1000px;
  margin: 0 auto;
  background-color: rgba(0, 0, 0, 0.171);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

FOOTER DIV {
  background-image: url('https://learnwebdesign.online/img/bg.jpg');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  flex: 1;
  text-align: center;
  display: flex
}
FOOTER:not(.no-padd) DIV:before {
  content:"";
  padding-top: 75%;
}

FOOTER DIV SPAN {
  margin:auto;
  text-align: center;
  background-color: rgba(165, 165, 165, 0.282);
  padding: 7px 15px;
  border-radius: 3px;
  color: #FFFFFF;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: 2px;
  font-size: 21px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<footer class="no-padd">
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>

<footer >
  <div><span>left photo</span></div>
  <div><span>center photo</span></div>
  <div><span>right photo and more text</span></div>
</footer>


问:
How do I stop an animation when tapped
I'm making a tap game, and this is the button with the animation. It is very slow, and I want to speed it up so when the user taps, it will reset the animation and count the tap.

Currently, it is slow to the point that it will miss taps if tapped again while the animation is still going on.

```<code>@IBAction func slimeTap(_ sender: UIButton) {
    tapCount += tapIncrease
    checkLevel(tapCount)
    UIView.animate(withDuration: 0.03, animations: {
        //shrink
        self.playSound()
        sender.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
    }, completion: {_ in
        //change it back to how it was
        //grow
        UIView.animate(withDuration: 0.05, animations: {
           sender.transform = CGAffineTransform(scaleX: 1, y: 1)
        })
    })
}
</code>```

答:
Try adding .layer.removeAllAnimations() to remove any existing animations on the layer, and .allowUserInteraction as an animation option to enable and register user tap events:

@IBAction func slimeTap(_ sender: UIButton) {
    tapCount += tapIncrease
    checkLevel(tapCount)

    resizingView.layer.removeAllAnimations()

    UIView.animate(withDuration: 0.3, delay: 0, options: [.allowUserInteraction], animations: {
        self.playSound()
        sender.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
    }) { _ in
        UIView.animate(withDuration: 0.5, delay: 0, options: [.allowUserInteraction], animations: {
            sender.transform = CGAffineTransform(scaleX: 1, y: 1)
        })
    }
}
```

Title: How do I stop an animation when tapped

Body:
I'm making a tap game, and this is the button with the animation. It is very slow, and I want to speed it up so when the user taps, it will reset the animation and count the tap.

Currently, it is slow to the point that it will miss taps if tapped again while the animation is still going on.

@IBAction func slimeTap(_ sender: UIButton) {
    tapCount += tapIncrease
    checkLevel(tapCount)
    UIView.animate(withDuration: 0.03, animations: {
        //shrink
        self.playSound()
        sender.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
    }, completion: {_ in
        //change it back to how it was
        //grow
        UIView.animate(withDuration: 0.05, animations: {
           sender.transform = CGAffineTransform(scaleX: 1, y: 1)
        })
    })
}


问:
Need to add a column to a CSV that adds a number for each line of data (1,2,3,etc)
Need to append a CSV file to add a Column (Pkey) with an increment numeric starting from 1 for every line of data.  I prefer to have a VB script do this, but if theres an easier method I can run on a windows task scheduler I am open to anything.

I just need a script that creates a column in the CSV named "Pkey" and adds a increasing numeric +1 to every line of data, starting with 1.  This has to be unique counts all the way down to the final line of data.

Expected to have a column added with header Pkey, then number down the lines of data 1,2,3,4,5,etc till all lines of data have been numbered with a unique integer

Code that I currently use to pull the query into the CSV and save it, everytime I try to do the increment it breaks the script:

```<code>    Option Explicit

Dim TextExportPath
Dim TextExportFile
Dim db
Dim cn
Dim strCon
Dim objFileSys

db = "X:\VPP DATABASE\Pham.mdb"
TextExportPath = "X:\Scripts\FTP\QuickBase Sync\CustomerData\"
TextExportFile = NewFileName(TextExportPath)

Set objFileSys = CreateObject("Scripting.FileSystemObject")
If objFileSys.FileExists("X:\Scripts\FTP\QuickBase Sync\CustomerData\MMD_Abacus.csv") Then
objFileSys.DeleteFile "X:\Scripts\FTP\QuickBase Sync\CustomerData\MMD_Abacus.csv"

End If

Set cn = CreateObject("ADODB.Connection")

cn.Open _
    "Provider = Microsoft.Jet.OLEDB.4.0; " & _
    "Data Source =" & db

cn.Execute "SELECT * INTO [text;HDR=Yes;Database=" & TextExportPath & _
   "]." & TextExportFile & " FROM 83AFFNIGHT"

Function NewFileName(TextExportPath)
Dim fs
Dim NewFileTemp
Dim a, i

Set fs = CreateObject("Scripting.FileSystemObject")

NewFileTemp = "MMD_Abacus" & ".csv"

a = fs.FileExists(TextExportPath & NewFileTemp)

NewFileName = NewFileTemp
End Function
</code>```

So would I add something like this, or even create a separate vb script to run after this one?

```<code>Dim lines As New List(Of String)
Dim lineNumber = 1

Using parser As New TextFieldParser("TextFile1.txt") With {.Delimiters = {","}}
    Do Until parser.EndOfData
        Dim fields = parser.ReadFields()

        'Add quotes around the column that may be multiline.
        fields(1) = $"""{fields(1)}"""

        lines.Add(String.Join(",", fields) & "," & lineNumber)
        lineNumber += 1
    Loop
End Using

File.WriteAllLines("TextFile1.txt", lines)
</code>```

答:
Using StdIn and StdOut means we don't have to write file handling code.

This starts at 1

```<code>    Count = 1
    Set Inp = WScript.Stdin
    Set Outp = Wscript.Stdout
    Do Until Inp.AtEndOfStream
        Line=Inp.readline
        outp.writeline Count & vbtab & Line
        Count = Count + 1
    Loop
</code>```

To use

```<code>cscript //nologo MyScript.vbs < InputFile > Outputfile
</code>```

Body:
Need to append a CSV file to add a Column (Pkey) with an increment numeric starting from 1 for every line of data.  I prefer to have a VB script do this, but if theres an easier method I can run on a windows task scheduler I am open to anything.

I just need a script that creates a column in the CSV named "Pkey" and adds a increasing numeric +1 to every line of data, starting with 1.  This has to be unique counts all the way down to the final line of data.

Expected to have a column added with header Pkey, then number down the lines of data 1,2,3,4,5,etc till all lines of data have been numbered with a unique integer

Code that I currently use to pull the query into the CSV and save it, everytime I try to do the increment it breaks the script:

    Option Explicit

Dim TextExportPath
Dim TextExportFile
Dim db
Dim cn
Dim strCon
Dim objFileSys

db = "X:\VPP DATABASE\Pham.mdb"
TextExportPath = "X:\Scripts\FTP\QuickBase Sync\CustomerData\"
TextExportFile = NewFileName(TextExportPath)

Set objFileSys = CreateObject("Scripting.FileSystemObject")
If objFileSys.FileExists("X:\Scripts\FTP\QuickBase Sync\CustomerData\MMD_Abacus.csv") Then
objFileSys.DeleteFile "X:\Scripts\FTP\QuickBase Sync\CustomerData\MMD_Abacus.csv"

End If

Set cn = CreateObject("ADODB.Connection")

cn.Open _
    "Provider = Microsoft.Jet.OLEDB.4.0; " & _
    "Data Source =" & db

cn.Execute "SELECT * INTO [text;HDR=Yes;Database=" & TextExportPath & _
   "]." & TextExportFile & " FROM 83AFFNIGHT"

Function NewFileName(TextExportPath)
Dim fs
Dim NewFileTemp
Dim a, i

Set fs = CreateObject("Scripting.FileSystemObject")

NewFileTemp = "MMD_Abacus" & ".csv"

a = fs.FileExists(TextExportPath & NewFileTemp)

NewFileName = NewFileTemp
End Function

So would I add something like this, or even create a separate vb script to run after this one?

Dim lines As New List(Of String)
Dim lineNumber = 1

Using parser As New TextFieldParser("TextFile1.txt") With {.Delimiters = {","}}
    Do Until parser.EndOfData
        Dim fields = parser.ReadFields()

        'Add quotes around the column that may be multiline.
        fields(1) = $"""{fields(1)}"""

        lines.Add(String.Join(",", fields) & "," & lineNumber)
        lineNumber += 1
    Loop
End Using

File.WriteAllLines("TextFile1.txt", lines)

Body:
Using StdIn and StdOut means we don't have to write file handling code.

This starts at 1

    Count = 1
    Set Inp = WScript.Stdin
    Set Outp = Wscript.Stdout
    Do Until Inp.AtEndOfStream
        Line=Inp.readline
        outp.writeline Count & vbtab & Line
        Count = Count + 1
    Loop

To use

cscript //nologo MyScript.vbs < InputFile > Outputfile


问:
How to use shared element transitions in Navigation Controller
I would like to add a shared elements transition using the navigation architecture components, when navigating to an other fragment. But I have no idea how. Also in the documentations there is nothing about it. Can someone help me?</p>

答:
To make this work from a recyclerView's ImageView the setup everything like the following:

```<code>val adapter = PostAdapter() { transitionView, post ->
    findNavController().navigate(
        R.id.action_postsFragment_to_postsDetailFragment,
        null,
        null,
        FragmentNavigatorExtras(transitionView to getString(R.string.transition_image)))
}
</code>```

within the adapter this does the trick:

```<code>itemView.setOnClickListener {
    ViewCompat.setTransitionName(imageView, itemView.context.getString(R.string.transition_image))
    onClickedAction?.invoke(imageView, post)
}
</code>```

You don't have to specify the transition name within the adapter's item's xml but simply set it from code as soon as the item gets clicked.

The onClickedAction looks like:

```<code>private val onClickedAction: ((transitionView: View, post: Post) -> Unit)?
</code>```

and you pass it to your ViewHolder.

In the second Fragment you set the transition name to the ImageView in xml:

```<code>android:transitionName="@string/transition_image"
</code>```

and assign the transition like

```<code>override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val transition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
    sharedElementEnterTransition = transition
    sharedElementReturnTransition = transition
}
</code>```

Body:
To make this work from a recyclerView's ImageView the setup everything like the following:

val adapter = PostAdapter() { transitionView, post ->
    findNavController().navigate(
        R.id.action_postsFragment_to_postsDetailFragment,
        null,
        null,
        FragmentNavigatorExtras(transitionView to getString(R.string.transition_image)))
}

within the adapter this does the trick:

itemView.setOnClickListener {
    ViewCompat.setTransitionName(imageView, itemView.context.getString(R.string.transition_image))
    onClickedAction?.invoke(imageView, post)
}

You don't have to specify the transition name within the adapter's item's xml but simply set it from code as soon as the item gets clicked.

The onClickedAction looks like:

private val onClickedAction: ((transitionView: View, post: Post) -> Unit)?

and you pass it to your ViewHolder.

In the second Fragment you set the transition name to the ImageView in xml:

android:transitionName="@string/transition_image"

and assign the transition like

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val transition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
    sharedElementEnterTransition = transition
    sharedElementReturnTransition = transition
}


问:
How to filter Power BI table using list of keywords (in a column in other table)
I have a big data table with a column called Account Name. In another table (Accounts) I have a column of Account Keywords that contains parts of full account names. I want to filter the big data by column 'Account Name' using the list of keywords in the 'Acount Keywords' list.

I've created a new measure in the big data table called 'Filter Accounts' with the following DAX:

```<code>FILTER ACCOUNTS = contains(Accounts,Accounts[Account Keyword],Big_Data[Account Name])
</code>```

But the "contains" function works on exact matches. I want it to return true if the 'Account Keyword' is found within any part of the 'Account Name' field. I also want it to ignore case.

The DAX statement results in TRUE only for exact matches. How do I modify my DAX to achieve the desired non-exact matches?

答:
DAX has two functions for text contains matching, CONTAINSSTRING and CONTAINSSTRINGEXACT, where the latter is case-sensitive but the former is not.

You can find how many keywords match an Account Name by writing a calculated column like this on the Big_Data table:

```<code>Keyword Matches =
COUNTROWS (
    FILTER (
        Accounts,
        CONTAINSSTRING ( Big_Data[Account Name], Accounts[Account Keyword] )
    )
)
</code>```

To get a TRUE or FALSE output instead of a count, simply append > 0 to see if the count is a positive value.

```<code>Match Exists =
COUNTROWS (
    FILTER (
        Accounts,
        CONTAINSSTRING ( Big_Data[Account Name], Accounts[Account Keyword] )
    )
) > 0
</code>```

Body:
I have a big data table with a column called Account Name. In another table (Accounts) I have a column of Account Keywords that contains parts of full account names. I want to filter the big data by column 'Account Name' using the list of keywords in the 'Acount Keywords' list.

I've created a new measure in the big data table called 'Filter Accounts' with the following DAX:

FILTER ACCOUNTS = contains(Accounts,Accounts[Account Keyword],Big_Data[Account Name])

But the "contains" function works on exact matches. I want it to return true if the 'Account Keyword' is found within any part of the 'Account Name' field. I also want it to ignore case.

The DAX statement results in TRUE only for exact matches. How do I modify my DAX to achieve the desired non-exact matches?

Body:
DAX has two functions for text contains matching, CONTAINSSTRING and CONTAINSSTRINGEXACT, where the latter is case-sensitive but the former is not.

You can find how many keywords match an Account Name by writing a calculated column like this on the Big_Data table:

Keyword Matches =
COUNTROWS (
    FILTER (
        Accounts,
        CONTAINSSTRING ( Big_Data[Account Name], Accounts[Account Keyword] )
    )
)

To get a TRUE or FALSE output instead of a count, simply append > 0 to see if the count is a positive value.

Match Exists =
COUNTROWS (
    FILTER (
        Accounts,
        CONTAINSSTRING ( Big_Data[Account Name], Accounts[Account Keyword] )
    )
) > 0


问:
Power BI Embedded Row Level security not working
I have setup roles in powerbi desktop. Can view as roles in desktop. But while embedding i'm getting this error

```<code>{
    code: 'InvalidRequest',
    message: 'Creating embed token with effective identity requires dataset to be provided'
}
</code>```

My payload to token fetch API is

```<code>{
 accessLevel: 'View',
 "identities": [
    {
      "username": "username",
      "roles": [ "role" ],
      "datasets": ["datasetid"]
    }
     ]
}
</code>```

答:
If you are using an Analysis Services data source the Roles are not defined in the PowerBI report/pbix file like they are with a static/imported data. This is the method I am referring to: https://learn.microsoft.com/en-us/power-bi/report-server/row-level-security-report-server

To use Roles with Analysis Services you need to set up Roles on the tabular model itself. Microsoft has some good documentation how to do so here: https://learn.microsoft.com/en-us/power-bi/developer/embedded-row-level-security#working-with-analysis-services-live-connections

On this page look at "2. Create a Role in the Analysis Services server." and "3. Set your General settings. Here you give the Role Name and set the database permissions to Read only." This is how you create the role so you can pass "RoleA" or whatever you have called the role.

On the next steps "4. Set the Membership settings. Here you add the users that are affected by this role." and "5. Set your Row filters DAX query using the CUSTOMDATA() function." you can apply certain DAX filters to your role similar to how you can if you created a role in a PowerBI Pbix file for a static data set.

Body:
I have setup roles in powerbi desktop. Can view as roles in desktop. But while embedding i'm getting this error

{
    code: 'InvalidRequest',
    message: 'Creating embed token with effective identity requires dataset to be provided'
}

My payload to token fetch API is

{
 accessLevel: 'View',
 "identities": [
    {
      "username": "username",
      "roles": [ "role" ],
      "datasets": ["datasetid"]
    }
     ]
}


问:
Match two consecutive words in a sentence
I have a bunch of sentences and want to figure out if the sentence contains a specific set of consecutive words. As an example, I have a list like below

```<code>  list = ["Data Scientist",  "Data Analyst", "Data Engineer"]
</code>```

and have sentences like below

```<code>  Sentence1 = "I am first going to be a Data Analyst and then a Data Scientist"
  Sentence2 = "I only like to be a Data Engineer"
</code>```

with the desired output picking out "Data Analyst" and "Data Scientist" for Sentence1 and "Data Engineer" for Sentence2.

答:
You can use a list comprehension and the in operator to check membership:

```<code>l = ["Data Scientist",  "Data Analyst", "Data Engineer"]
Sentence1 = "I am first going to be a Data Analyst and then a Data Scientist"

[i for i in l if i in Sentence1]
# ['Data Scientist', 'Data Analyst']
</code>```

Body:
I have a bunch of sentences and want to figure out if the sentence contains a specific set of consecutive words. As an example, I have a list like below

  list = ["Data Scientist",  "Data Analyst", "Data Engineer"]

and have sentences like below

  Sentence1 = "I am first going to be a Data Analyst and then a Data Scientist"
  Sentence2 = "I only like to be a Data Engineer"

with the desired output picking out "Data Analyst" and "Data Scientist" for Sentence1 and "Data Engineer" for Sentence2.

Body:
You can use a list comprehension and the in operator to check membership:

l = ["Data Scientist",  "Data Analyst", "Data Engineer"]
Sentence1 = "I am first going to be a Data Analyst and then a Data Scientist"

[i for i in l if i in Sentence1]
# ['Data Scientist', 'Data Analyst']